aboutsummaryrefslogtreecommitdiff
path: root/xsde/cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2009-03-26 17:09:53 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2009-03-26 17:09:53 +0200
commite4c22d3686da0e973e21eae0561c1169c0eeff36 (patch)
tree0a49e9167edc88938b0287949080931314e8afea /xsde/cxx
parent0d62005a3ff3b62d02c2eb3fd8644e0e19b202e8 (diff)
Implement support for XML Schema polymorphism in C++/Hybrid
examples/cxx/hybrid/polyroot/ examples/cxx/hybrid/polymorphism/: new examples tests/cxx/hybrid/polymorphism/: new tests
Diffstat (limited to 'xsde/cxx')
-rw-r--r--xsde/cxx/elements.cxx9
-rw-r--r--xsde/cxx/hybrid/aggregate-elements.hxx31
-rw-r--r--xsde/cxx/hybrid/aggregate-include.hxx223
-rw-r--r--xsde/cxx/hybrid/cli.hxx10
-rw-r--r--xsde/cxx/hybrid/elements.cxx7
-rw-r--r--xsde/cxx/hybrid/elements.hxx12
-rw-r--r--xsde/cxx/hybrid/generator.cxx130
-rw-r--r--xsde/cxx/hybrid/generator.hxx63
-rw-r--r--xsde/cxx/hybrid/parser-aggregate-header.cxx315
-rw-r--r--xsde/cxx/hybrid/parser-aggregate-source.cxx162
-rw-r--r--xsde/cxx/hybrid/parser-header.cxx35
-rw-r--r--xsde/cxx/hybrid/parser-name-processor.cxx11
-rw-r--r--xsde/cxx/hybrid/parser-name-processor.hxx3
-rw-r--r--xsde/cxx/hybrid/parser-source.cxx52
-rw-r--r--xsde/cxx/hybrid/serializer-aggregate-header.cxx330
-rw-r--r--xsde/cxx/hybrid/serializer-aggregate-source.cxx169
-rw-r--r--xsde/cxx/hybrid/serializer-header.cxx35
-rw-r--r--xsde/cxx/hybrid/serializer-name-processor.cxx13
-rw-r--r--xsde/cxx/hybrid/serializer-name-processor.hxx3
-rw-r--r--xsde/cxx/hybrid/serializer-source.cxx100
-rw-r--r--xsde/cxx/hybrid/tree-header.cxx94
-rw-r--r--xsde/cxx/hybrid/tree-inline.cxx9
-rw-r--r--xsde/cxx/hybrid/tree-name-processor.cxx13
-rw-r--r--xsde/cxx/hybrid/tree-name-processor.hxx3
-rw-r--r--xsde/cxx/hybrid/tree-size-processor.cxx274
-rw-r--r--xsde/cxx/hybrid/tree-size-processor.hxx5
-rw-r--r--xsde/cxx/hybrid/tree-source.cxx225
-rw-r--r--xsde/cxx/hybrid/validator.cxx9
-rw-r--r--xsde/cxx/parser/generator.cxx10
-rw-r--r--xsde/cxx/parser/generator.hxx17
-rw-r--r--xsde/cxx/parser/name-processor.cxx11
-rw-r--r--xsde/cxx/parser/name-processor.hxx5
-rw-r--r--xsde/cxx/parser/validator.cxx2
-rw-r--r--xsde/cxx/serializer/generator.cxx10
-rw-r--r--xsde/cxx/serializer/generator.hxx17
-rw-r--r--xsde/cxx/serializer/name-processor.cxx11
-rw-r--r--xsde/cxx/serializer/name-processor.hxx5
-rw-r--r--xsde/cxx/serializer/validator.cxx2
38 files changed, 2144 insertions, 291 deletions
diff --git a/xsde/cxx/elements.cxx b/xsde/cxx/elements.cxx
index 6116856..79fd6c5 100644
--- a/xsde/cxx/elements.cxx
+++ b/xsde/cxx/elements.cxx
@@ -194,8 +194,15 @@ namespace CXX
if (schema.used ())
{
+ // Here we need to detect a special multi-schema compilation
+ // case where the root schemas are imported into a special
+ // schema that doesn't have a namespace.
+ //
SemanticGraph::Uses& u (*schema.used_begin ());
- path = u.path ();
+ SemanticGraph::Schema& s (u.user ());
+
+ if (s.names_begin () != s.names_end ())
+ path = u.path ();
}
String pair;
diff --git a/xsde/cxx/hybrid/aggregate-elements.hxx b/xsde/cxx/hybrid/aggregate-elements.hxx
new file mode 100644
index 0000000..aa4c504
--- /dev/null
+++ b/xsde/cxx/hybrid/aggregate-elements.hxx
@@ -0,0 +1,31 @@
+// file : xsde/cxx/hybrid/aggregate-elements.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CXX_HYBRID_AGGREGATE_ELEMENTS_HXX
+#define CXX_HYBRID_AGGREGATE_ELEMENTS_HXX
+
+#include <cult/containers/map.hxx>
+
+#include <cxx/hybrid/elements.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ typedef
+ Cult::Containers::Map<SemanticGraph::Type*, String>
+ TypeInstanceMap;
+
+ struct InstanceInfo
+ {
+ SemanticGraph::Type* type;
+ String name;
+ };
+
+ typedef Cult::Containers::Map<String, InstanceInfo> TypeIdInstanceMap;
+ }
+}
+
+#endif // CXX_HYBRID_AGGREGATE_ELEMENTS_HXX
diff --git a/xsde/cxx/hybrid/aggregate-include.hxx b/xsde/cxx/hybrid/aggregate-include.hxx
new file mode 100644
index 0000000..9bd50bb
--- /dev/null
+++ b/xsde/cxx/hybrid/aggregate-include.hxx
@@ -0,0 +1,223 @@
+// file : xsde/cxx/hybrid/aggregate-include.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CXX_HYBRID_AGGREGATE_INCLUDE_HXX
+#define CXX_HYBRID_AGGREGATE_INCLUDE_HXX
+
+#include <cult/containers/set.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cxx/hybrid/elements.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ // Parser/serializer implementation includes for additional
+ // schemas (polymorphic code).
+ //
+
+ // For base types we only want member's types, but not the
+ // base itself.
+ //
+ struct BaseInclude: Traversal::Complex, Context
+ {
+ BaseInclude (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ inherits (c);
+
+ if (!restriction_p (c))
+ {
+ names (c);
+ contains_compositor (c);
+ }
+ }
+ };
+
+ struct TypeInclude: Traversal::Type,
+ Traversal::Complex,
+ Context
+ {
+ TypeInclude (Context& c)
+ : Context (c), base_ (c)
+ {
+ *this >> inherits_ >> base_ >> inherits_;
+
+ *this >> contains_compositor_;
+ base_ >> contains_compositor_;
+
+ *this >> names_;
+ base_ >> names_;
+
+ contains_compositor_ >> compositor_;
+ compositor_ >> contains_particle_;
+ contains_particle_ >> compositor_;
+ contains_particle_ >> particle_;
+
+ names_ >> attribute_;
+
+ particle_ >> belongs_;
+ attribute_ >> belongs_;
+ belongs_ >> *this;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& t)
+ {
+ if (types_.find (&t) != types_.end ())
+ return;
+
+ types_.insert (&t);
+
+ if (polymorphic (t))
+ collect (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ if (types_.find (&c) != types_.end ())
+ return;
+
+ types_.insert (&c);
+
+ if (polymorphic (c))
+ collect (c);
+
+ inherits (c);
+
+ if (!restriction_p (c))
+ {
+ names (c);
+ contains_compositor (c);
+ }
+ }
+
+ private:
+ virtual Void
+ collect (SemanticGraph::Type& t)
+ {
+ using SemanticGraph::Type;
+
+ for (Type::BegetsIterator i (t.begets_begin ());
+ i != t.begets_end ();
+ ++i)
+ {
+ Type& d (i->derived ());
+ emit (d);
+ dispatch (d);
+ collect (d);
+ }
+ }
+
+ virtual Void
+ emit (SemanticGraph::Type& t)
+ {
+ using SemanticGraph::Schema;
+
+ Schema* s (&dynamic_cast<Schema&> (t.scope ().scope ()));
+
+ // If this is not a top-level schema, get one that
+ // includes/import/sources this schema. Top-level schema
+ // is either not used by any other schema or is imported
+ // into a special schema that doesn't have a namespace.
+ //
+ for (;;)
+ {
+ if (!s->used ())
+ break;
+
+ SemanticGraph::Uses& u (*s->used_begin ());
+ Schema& us (u.user ());
+
+ if (us.names_begin () == us.names_end ())
+ break;
+
+ s = &us;
+ }
+
+
+ if (s != &schema_root && schemas_.find (s) == schemas_.end ())
+ {
+ schemas_.insert (s);
+
+ SemanticGraph::Path path (s->used_begin ()->path ());
+
+ // Try to use the portable representation of the path. If that
+ // fails, fall back to the native representation.
+ //
+ NarrowString path_str;
+ try
+ {
+ path_str = path.string ();
+ }
+ catch (SemanticGraph::InvalidPath const&)
+ {
+ path_str = path.native_file_string ();
+ }
+
+ String inc_path (hxx_expr->merge (path_str));
+ os << "#include " << process_include_path (inc_path) << endl
+ << endl;
+ }
+ }
+
+ private:
+ Cult::Containers::Set<SemanticGraph::Type*> types_;
+ Cult::Containers::Set<SemanticGraph::Schema*> schemas_;
+
+ BaseInclude base_;
+ Traversal::Inherits inherits_;
+
+ Traversal::Compositor compositor_;
+ Traversal::Element particle_;
+ Traversal::ContainsCompositor contains_compositor_;
+ Traversal::ContainsParticle contains_particle_;
+
+ Traversal::Names names_;
+ Traversal::Attribute attribute_;
+
+ Traversal::Belongs belongs_;
+ };
+
+ struct AggregateInclude: Traversal::Type,
+ Traversal::Element,
+ Context
+ {
+ AggregateInclude (Context& c, Char const* key)
+ : Context (c), key_ (key), type_include_ (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& t)
+ {
+ if (t.context ().count (key_))
+ type_include_.dispatch (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (e.context ().count (key_))
+ type_include_.dispatch (e.type ());
+ }
+
+ private:
+ Char const* key_;
+ TypeInclude type_include_;
+ };
+ }
+}
+
+#endif // CXX_HYBRID_AGGREGATE_INCLUDE_HXX
diff --git a/xsde/cxx/hybrid/cli.hxx b/xsde/cxx/hybrid/cli.hxx
index 0d1ec70..80b91bc 100644
--- a/xsde/cxx/hybrid/cli.hxx
+++ b/xsde/cxx/hybrid/cli.hxx
@@ -41,6 +41,11 @@ namespace CXX
extern Key generate_xml_schema;
extern Key extern_xml_schema;
extern Key suppress_reset;
+ extern Key generate_polymorphic;
+ extern Key runtime_polymorphic;
+ extern Key polymorphic_type;
+ extern Key generate_typeinfo;
+ extern Key polymorphic_schema;
extern Key reuse_style_mixin;
extern Key custom_data;
extern Key custom_type;
@@ -123,6 +128,11 @@ namespace CXX
generate_xml_schema, Boolean,
extern_xml_schema, NarrowString,
suppress_reset, Boolean,
+ generate_polymorphic, Boolean,
+ runtime_polymorphic, Boolean,
+ polymorphic_type, Cult::Containers::Vector<NarrowString>,
+ generate_typeinfo, Boolean,
+ polymorphic_schema, Cult::Containers::Vector<NarrowString>,
reuse_style_mixin, Boolean,
custom_data, Cult::Containers::Vector<NarrowString>,
custom_type, Cult::Containers::Vector<NarrowString>,
diff --git a/xsde/cxx/hybrid/elements.cxx b/xsde/cxx/hybrid/elements.cxx
index 80dc5c4..4edbc06 100644
--- a/xsde/cxx/hybrid/elements.cxx
+++ b/xsde/cxx/hybrid/elements.cxx
@@ -33,8 +33,7 @@ namespace CXX
options (ops),
exceptions (!ops.value<CLI::no_exceptions> ()),
stl (!ops.value<CLI::no_stl> ()),
- poly_code (false),
- poly_runtime (false),
+ poly_code (ops.value<CLI::generate_polymorphic> ()),
reset (!ops.value<CLI::suppress_reset> ()),
detach (ops.value<CLI::generate_detach> ()),
mixin (ops.value<CLI::reuse_style_mixin> ()),
@@ -55,6 +54,10 @@ namespace CXX
ixdrstream (ixdrstream_),
oxdrstream (oxdrstream_)
{
+ typeinfo = poly_code &&
+ (ops.value<CLI::generate_typeinfo> () ||
+ ops.value<CLI::generate_serializer> ());
+
String xs_ns (xs_ns_name ());
string_type = L"::xsde::cxx::ro_string";
diff --git a/xsde/cxx/hybrid/elements.hxx b/xsde/cxx/hybrid/elements.hxx
index 7f3ba3a..8452976 100644
--- a/xsde/cxx/hybrid/elements.hxx
+++ b/xsde/cxx/hybrid/elements.hxx
@@ -42,9 +42,9 @@ namespace CXX
exceptions (c.exceptions),
stl (c.stl),
poly_code (c.poly_code),
- poly_runtime (c.poly_runtime),
reset (c.reset),
detach (c.detach),
+ typeinfo (c.typeinfo),
mixin (c.mixin),
tiein (c.tiein),
fwd_expr (c.fwd_expr),
@@ -71,9 +71,9 @@ namespace CXX
exceptions (c.exceptions),
stl (c.stl),
poly_code (c.poly_code),
- poly_runtime (c.poly_runtime),
reset (c.reset),
detach (c.detach),
+ typeinfo (c.typeinfo),
mixin (c.mixin),
tiein (c.tiein),
fwd_expr (c.fwd_expr),
@@ -534,6 +534,12 @@ namespace CXX
return t.context ().count ("recursive");
}
+ Boolean
+ polymorphic (SemanticGraph::Type& t)
+ {
+ return t.context ().count ("polymorphic");
+ }
+
public:
String
istream (NarrowString const& is) const;
@@ -559,9 +565,9 @@ namespace CXX
Boolean exceptions;
Boolean stl;
Boolean poly_code;
- Boolean poly_runtime;
Boolean reset;
Boolean detach;
+ Boolean typeinfo;
Boolean mixin;
Boolean tiein;
diff --git a/xsde/cxx/hybrid/generator.cxx b/xsde/cxx/hybrid/generator.cxx
index 14afad6..3eba4ba 100644
--- a/xsde/cxx/hybrid/generator.cxx
+++ b/xsde/cxx/hybrid/generator.cxx
@@ -129,6 +129,11 @@ namespace CXX
extern Key generate_xml_schema = "generate-xml-schema";
extern Key extern_xml_schema = "extern-xml-schema";
extern Key suppress_reset = "suppress-reset";
+ extern Key generate_polymorphic = "generate-polymorphic";
+ extern Key runtime_polymorphic = "runtime-polymorphic";
+ extern Key polymorphic_type = "polymorphic-type";
+ extern Key generate_typeinfo = "generate-typeinfo";
+ extern Key polymorphic_schema = "polymorphic-schema";
extern Key reuse_style_mixin = "reuse-style-mixin";
extern Key custom_data = "custom-data";
extern Key custom_type = "custom-type";
@@ -285,6 +290,32 @@ namespace CXX
<< " reset code."
<< endl;
+ e << "--generate-polymorphic" << endl
+ << " Generate polymorphism-aware code. Specify this\n"
+ << " option if you use substitution groups or xsi:type."
+ << endl;
+
+ e << "--runtime-polymorphic" << endl
+ << " Generate non-polymorphic code that uses the\n"
+ << " runtime library configured with polymorphism\n"
+ << " support."
+ << endl;
+
+ e << "--polymorphic-type <type>" << endl
+ << " Indicate that <type> is a root of a polymorphic\n"
+ << " type hierarchy."
+ << endl;
+
+ e << "--generate-typeinfo" << endl
+ << " Generate type information functions for\n"
+ << " polymorphic object model types."
+ << endl;
+
+ e << "--polymorphic-schema <file>" << endl
+ << " Indicate that <file> contains derivations of\n"
+ << " polymorphic types."
+ << endl;
+
e << "--reuse-style-mixin" << endl
<< " Generate code that supports the mixin base\n"
<< " parser/serializer implementation reuse style."
@@ -783,6 +814,8 @@ namespace CXX
r->value<P::generate_xml_schema> () = h.value<H::generate_xml_schema> ();
r->value<P::extern_xml_schema> () = h.value<H::extern_xml_schema> ();
r->value<P::suppress_reset> () = h.value<H::suppress_reset> ();
+ r->value<P::generate_polymorphic> () = h.value<H::generate_polymorphic> ();
+ r->value<P::runtime_polymorphic> () = h.value<H::runtime_polymorphic> ();
r->value<P::output_dir> () = h.value<H::output_dir> ();
r->value<P::skel_file_suffix> () = h.value<H::pskel_file_suffix> ();
r->value<P::skel_type_suffix> () = h.value<H::pskel_type_suffix> ();
@@ -862,6 +895,8 @@ namespace CXX
r->value<S::generate_xml_schema> () = h.value<H::generate_xml_schema> ();
r->value<S::extern_xml_schema> () = h.value<H::extern_xml_schema> ();
r->value<S::suppress_reset> () = h.value<H::suppress_reset> ();
+ r->value<S::generate_polymorphic> () = h.value<H::generate_polymorphic> ();
+ r->value<S::runtime_polymorphic> () = h.value<H::runtime_polymorphic> ();
r->value<S::output_dir> () = h.value<H::output_dir> ();
r->value<S::skel_file_suffix> () = h.value<H::sskel_file_suffix> ();
r->value<S::skel_type_suffix> () = h.value<H::sskel_type_suffix> ();
@@ -924,16 +959,44 @@ namespace CXX
Void Hybrid::Generator::
calculate_size (CLI::Options const& ops,
XSDFrontend::SemanticGraph::Schema& schema,
- XSDFrontend::SemanticGraph::Path const& file)
+ XSDFrontend::SemanticGraph::Path const& file,
+ const WarningSet& disabled_warnings)
{
// Determine which types are fixed/variable-sized.
//
TreeSizeProcessor proc;
- if (!proc.process (ops, schema, file))
+ if (!proc.process (ops, schema, file, disabled_warnings))
throw Failed ();
}
+ Void Hybrid::Generator::
+ process_tree_names (CLI::Options const& ops,
+ XSDFrontend::SemanticGraph::Schema& schema,
+ XSDFrontend::SemanticGraph::Path const& file)
+ {
+ TreeNameProcessor proc;
+ proc.process (ops, schema, file, false);
+ }
+
+ Void Hybrid::Generator::
+ process_parser_names (CLI::Options const& ops,
+ XSDFrontend::SemanticGraph::Schema& schema,
+ XSDFrontend::SemanticGraph::Path const& file)
+ {
+ ParserNameProcessor proc;
+ proc.process (ops, schema, file, false);
+ }
+
+ Void Hybrid::Generator::
+ process_serializer_names (CLI::Options const& ops,
+ XSDFrontend::SemanticGraph::Schema& schema,
+ XSDFrontend::SemanticGraph::Path const& file)
+ {
+ SerializerNameProcessor proc;
+ proc.process (ops, schema, file, false);
+ }
+
namespace
{
template <typename S>
@@ -1095,7 +1158,7 @@ namespace CXX
//
{
TreeNameProcessor proc;
- proc.process (ops, schema, file_path);
+ proc.process (ops, schema, file_path, true);
}
// Generate code.
@@ -1819,7 +1882,7 @@ namespace CXX
//
{
ParserNameProcessor proc;
- proc.process (ops, schema, file_path);
+ proc.process (ops, schema, file_path, true);
}
NarrowString name (file_path.leaf ());
@@ -1976,6 +2039,8 @@ namespace CXX
guard_prefix += '_';
+ Boolean aggr (ops.value<CLI::generate_aggregate> ());
+
// HXX
//
{
@@ -2012,6 +2077,14 @@ namespace CXX
hxx << "#include <xsde/cxx/pre.hxx>" << endl
<< endl;
+ // Define omit aggregate macro.
+ //
+ hxx << "#ifndef XSDE_OMIT_PAGGR" << endl
+ << "# define XSDE_OMIT_PAGGR" << endl
+ << "# define " << guard << "_CLEAR_OMIT_PAGGR" << endl
+ << "#endif" << endl
+ << endl;
+
// Set auto-indentation.
//
Indentation::Clip<Indentation::CXX, WideChar> hxx_clip (hxx);
@@ -2021,9 +2094,24 @@ namespace CXX
generate_parser_header (ctx);
- if (ops.value<CLI::generate_aggregate> ())
+ // Clear omit aggregate macro.
+ //
+ hxx << "#ifdef " << guard << "_CLEAR_OMIT_PAGGR" << endl
+ << "# undef XSDE_OMIT_PAGGR" << endl
+ << "#endif" << endl
+ << endl;
+
+ if (aggr)
+ {
+ hxx << "#ifndef XSDE_OMIT_PAGGR" << endl
+ << endl;
+
generate_parser_aggregate_header (ctx);
+ hxx << "#endif // XSDE_OMIT_PAGGR" << endl
+ << endl;
+ }
+
hxx << "#include <xsde/cxx/post.hxx>" << endl
<< endl;
}
@@ -2090,7 +2178,7 @@ namespace CXX
generate_parser_source (ctx);
- if (ops.value<CLI::generate_aggregate> ())
+ if (aggr)
generate_parser_aggregate_source (ctx);
}
@@ -2198,7 +2286,7 @@ namespace CXX
//
{
SerializerNameProcessor proc;
- proc.process (ops, schema, file_path);
+ proc.process (ops, schema, file_path, true);
}
NarrowString name (file_path.leaf ());
@@ -2342,6 +2430,7 @@ namespace CXX
if (guard_prefix)
guard_prefix += '_';
+ Boolean aggr (ops.value<CLI::generate_aggregate> ());
// HXX
//
@@ -2379,6 +2468,14 @@ namespace CXX
hxx << "#include <xsde/cxx/pre.hxx>" << endl
<< endl;
+ // Define omit aggregate macro.
+ //
+ hxx << "#ifndef XSDE_OMIT_SAGGR" << endl
+ << "# define XSDE_OMIT_SAGGR" << endl
+ << "# define " << guard << "_CLEAR_OMIT_SAGGR" << endl
+ << "#endif" << endl
+ << endl;
+
// Set auto-indentation.
//
Indentation::Clip<Indentation::CXX, WideChar> hxx_clip (hxx);
@@ -2388,9 +2485,24 @@ namespace CXX
generate_serializer_header (ctx);
- if (ops.value<CLI::generate_aggregate> ())
+ // Clear omit aggregate macro.
+ //
+ hxx << "#ifdef " << guard << "_CLEAR_OMIT_SAGGR" << endl
+ << "# undef XSDE_OMIT_SAGGR" << endl
+ << "#endif" << endl
+ << endl;
+
+ if (aggr)
+ {
+ hxx << "#ifndef XSDE_OMIT_SAGGR" << endl
+ << endl;
+
generate_serializer_aggregate_header (ctx);
+ hxx << "#endif // XSDE_OMIT_SAGGR" << endl
+ << endl;
+ }
+
hxx << "#include <xsde/cxx/post.hxx>" << endl
<< endl;
}
@@ -2457,7 +2569,7 @@ namespace CXX
generate_serializer_source (ctx);
- if (ops.value<CLI::generate_aggregate> ())
+ if (aggr)
generate_serializer_aggregate_source (ctx);
}
diff --git a/xsde/cxx/hybrid/generator.hxx b/xsde/cxx/hybrid/generator.hxx
index ff29750..6f506b2 100644
--- a/xsde/cxx/hybrid/generator.hxx
+++ b/xsde/cxx/hybrid/generator.hxx
@@ -44,42 +44,67 @@ namespace CXX
static Serializer::CLI::Options*
serializer_options (CLI::Options const&);
- struct Failed {};
-
+ // Calculate type sizes.
+ //
static Void
calculate_size (
- CLI::Options const& options,
+ CLI::Options const&,
XSDFrontend::SemanticGraph::Schema&,
- XSDFrontend::SemanticGraph::Path const& file);
+ XSDFrontend::SemanticGraph::Path const&,
+ WarningSet const& disabled_warnings);
+
+ // Assign names to global declarations.
+ //
+ static Void
+ process_tree_names (
+ CLI::Options const&,
+ XSDFrontend::SemanticGraph::Schema&,
+ XSDFrontend::SemanticGraph::Path const&);
+
+ static Void
+ process_parser_names (
+ CLI::Options const&,
+ XSDFrontend::SemanticGraph::Schema&,
+ XSDFrontend::SemanticGraph::Path const&);
+
+ static Void
+ process_serializer_names (
+ CLI::Options const&,
+ XSDFrontend::SemanticGraph::Schema&,
+ XSDFrontend::SemanticGraph::Path const&);
+
+ // Generate code.
+ //
+ struct Failed {};
static UnsignedLong
generate_tree (
- CLI::Options const& options,
+ CLI::Options const&,
XSDFrontend::SemanticGraph::Schema&,
- XSDFrontend::SemanticGraph::Path const& file,
- const WarningSet& disabled_warnings,
+ XSDFrontend::SemanticGraph::Path const&,
+ WarningSet const& disabled_warnings,
TypeMap::Namespaces& parser_type_map,
TypeMap::Namespaces& serializer_type_map,
- FileList& file_list,
- AutoUnlinks& unlinks);
+ FileList&,
+ AutoUnlinks&);
static UnsignedLong
generate_parser (
- CLI::Options const& options,
+ CLI::Options const&,
XSDFrontend::SemanticGraph::Schema&,
- XSDFrontend::SemanticGraph::Path const& file,
- const WarningSet& disabled_warnings,
- FileList& file_list,
- AutoUnlinks& unlinks);
+ XSDFrontend::SemanticGraph::Path const&,
+ WarningSet const& disabled_warnings,
+ FileList&,
+ AutoUnlinks&);
static UnsignedLong
generate_serializer (
- CLI::Options const& options,
+ CLI::Options const&,
XSDFrontend::SemanticGraph::Schema&,
- XSDFrontend::SemanticGraph::Path const& file,
- const WarningSet& disabled_warnings,
- FileList& file_list,
- AutoUnlinks& unlinks);
+ XSDFrontend::SemanticGraph::Path const&,
+ WarningSet const& disabled_warnings,
+ FileList&,
+ AutoUnlinks&);
private:
Generator ();
diff --git a/xsde/cxx/hybrid/parser-aggregate-header.cxx b/xsde/cxx/hybrid/parser-aggregate-header.cxx
index a717c68..c75eb54 100644
--- a/xsde/cxx/hybrid/parser-aggregate-header.cxx
+++ b/xsde/cxx/hybrid/parser-aggregate-header.cxx
@@ -4,11 +4,12 @@
// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
#include <cxx/hybrid/parser-aggregate-header.hxx>
+#include <cxx/hybrid/aggregate-elements.hxx>
+#include <cxx/hybrid/aggregate-include.hxx>
#include <xsd-frontend/semantic-graph.hxx>
#include <xsd-frontend/traversal.hxx>
-#include <cult/containers/map.hxx>
#include <cult/containers/set.hxx>
namespace CXX
@@ -17,10 +18,6 @@ namespace CXX
{
namespace
{
- typedef
- Cult::Containers::Map<SemanticGraph::Type*, String>
- TypeInstanceMap;
-
typedef Cult::Containers::Set<String> InstanceSet;
// For base types we only want member's types, but not the
@@ -108,8 +105,15 @@ namespace CXX
Context
{
- ParserDef (Context& c, TypeInstanceMap& map, InstanceSet& set)
- : Context (c), map_ (map), set_ (set), base_ (c)
+ ParserDef (Context& c,
+ TypeInstanceMap& map,
+ TypeIdInstanceMap& tid_map,
+ InstanceSet& set)
+ : Context (c),
+ map_ (map),
+ tid_map_ (tid_map),
+ set_ (set),
+ base_ (c)
{
*this >> inherits_ >> base_ >> inherits_;
@@ -136,8 +140,10 @@ namespace CXX
{
if (map_.find (&t) == map_.end ())
{
- String inst (find_instance_name (t));
- map_[&t] = inst;
+ map_[&t] = find_instance_name (t);
+
+ if (polymorphic (t))
+ collect (t);
}
}
@@ -146,10 +152,12 @@ namespace CXX
{
if (map_.find (&l) == map_.end ())
{
- String inst (find_instance_name (l));
- map_[&l] = inst;
+ map_[&l] = find_instance_name (l);
dispatch (l.argumented ().type ());
+
+ if (polymorphic (l))
+ collect (l);
}
}
@@ -158,8 +166,7 @@ namespace CXX
{
if (map_.find (&c) == map_.end ())
{
- String inst (find_instance_name (c));
- map_[&c] = inst;
+ map_[&c] = find_instance_name (c);
// Use base type's parsers in case of a restriction
// since we are not capable of using a derived type
@@ -172,6 +179,38 @@ namespace CXX
names (c);
contains_compositor (c);
}
+
+ if (polymorphic (c))
+ collect (c);
+ }
+ }
+
+ virtual Void
+ collect (SemanticGraph::Type& t)
+ {
+ using SemanticGraph::Type;
+
+ for (Type::BegetsIterator i (t.begets_begin ());
+ i != t.begets_end ();
+ ++i)
+ {
+ Type& d (i->derived ());
+
+ String id (d.name ());
+ if (String ns = xml_ns_name (d))
+ {
+ id += L' ';
+ id += ns;
+ }
+
+ dispatch (d);
+
+ if (tid_map_.find (id) == tid_map_.end ())
+ {
+ tid_map_[id].type = &d;
+ tid_map_[id].name = map_.find (&d)->second;
+ collect (d);
+ }
}
}
@@ -475,10 +514,7 @@ namespace CXX
fund_type (SemanticGraph::Type& t, String const& name)
{
if (map_.find (&t) == map_.end ())
- {
- String inst (find_instance_name (name));
- map_[&t] = inst;
- }
+ map_[&t] = find_instance_name (name);
}
String
@@ -504,6 +540,7 @@ namespace CXX
}
TypeInstanceMap& map_;
+ TypeIdInstanceMap& tid_map_;
InstanceSet& set_;
BaseType base_;
@@ -535,37 +572,65 @@ namespace CXX
if (!tc.count ("paggr"))
return;
+ Boolean poly (polymorphic (t));
String const& name (tc.get<String> ("paggr"));
- String pre (unclash (name, "pre"));
- String post (unclash (name, "post"));
+ String pre;
+ String post;
String root_parser (unclash (name, "root_parser"));
+ String root_map;
String error, reset;
+ String parser_map, parser_map_entries;
InstanceSet set;
- set.insert (pre);
- set.insert (post);
set.insert (name);
set.insert (root_parser);
- if (!exceptions)
+ if (poly)
+ {
+ root_map = unclash (name, "root_map");
+ set.insert (root_map);
+ }
+ else
+ {
+ pre = unclash (name, "pre");
+ post = unclash (name, "post");
+
+ set.insert (pre);
+ set.insert (post);
+ }
+
+ if (!poly && !exceptions)
{
error = unclash (name, "_error");
set.insert (error);
}
- if (Context::reset)
+ if (!poly && Context::reset)
{
reset = unclash (name, "reset");
set.insert (reset);
}
+ if (poly_code)
+ {
+ parser_map = unclash (name, "parser_map_");
+ parser_map_entries = unclash (name, "parser_map_entries_");
+
+ tc.set ("paggr-parser-map", parser_map);
+ tc.set ("paggr-parser-map-entries", parser_map_entries);
+ }
+
tc.set ("paggr-map", TypeInstanceMap ());
TypeInstanceMap& map (tc.get<TypeInstanceMap> ("paggr-map"));
+ TypeIdInstanceMap tid_map;
- ParserDef def (*this, map, set);
+ ParserDef def (*this, map, tid_map, set);
def.dispatch (t);
+ if (poly_code && !tid_map.empty ())
+ tc.set ("paggr-tid-map", tid_map);
+
String const& root_member (map.find (&t)->second);
os << "// Parser aggregate for the " << comment (t.name ()) <<
@@ -581,24 +646,27 @@ namespace CXX
os << name << " ();"
<< endl;
- // pre ()
- //
- os << "void" << endl
- << pre << " ()"
- << "{"
- << "this->" << root_member << ".pre ();"
- << "}";
+ if (!poly)
+ {
+ // pre ()
+ //
+ os << "void" << endl
+ << pre << " ()"
+ << "{"
+ << "this->" << root_member << ".pre ();"
+ << "}";
- // post ()
- //
- String const& ret (pret_type (t));
+ // post ()
+ //
+ String const& ret (pret_type (t));
- os << ret << endl
- << post << " ()"
- << "{"
- << (ret == L"void" ? "" : "return ") << "this->" <<
- root_member << "." << post_name (t) << " ();"
- << "}";
+ os << ret << endl
+ << post << " ()"
+ << "{"
+ << (ret == L"void" ? "" : "return ") << "this->" <<
+ root_member << "." << post_name (t) << " ();"
+ << "}";
+ }
// root_parser ()
//
@@ -608,9 +676,23 @@ namespace CXX
<< "return this->" << root_member << ";"
<< "}";
+ if (poly)
+ {
+ // root_map ()
+ //
+ if (poly)
+ {
+ os << "const " << xs_ns_name () + L"::parser_map&" << endl
+ << root_map << " ()"
+ << "{"
+ << "return this->" << parser_map << ";"
+ << "}";
+ }
+ }
+
// _error ()
//
- if (error)
+ if (!poly && error)
{
os << xs_ns_name () << "::parser_error" << endl
<< error << " ()"
@@ -626,8 +708,12 @@ namespace CXX
os << "void" << endl
<< reset << " ()"
<< "{"
- << "this->" << root_member << "._reset ();"
- << "}";
+ << "this->" << root_member << "._reset ();";
+
+ if (poly && tid_map.size () > 0)
+ os << "this->" << parser_map << ".reset ();";
+
+ os << "}";
}
os << "public:" << endl;
@@ -636,6 +722,13 @@ namespace CXX
i != end; ++i)
os << fq_name (*i->first, "p:impl") << " " << i->second << ";";
+ if (tid_map.size () > 0)
+ {
+ os << endl
+ << "::xsde::cxx::hybrid::parser_map_impl " << parser_map << ";"
+ << "::xsde::cxx::hybrid::parser_map_impl::entry " <<
+ parser_map_entries << "[" << tid_map.size () << "UL];";
+ }
os << "};";
}
};
@@ -656,41 +749,70 @@ namespace CXX
return;
SemanticGraph::Type& t (e.type ());
+ Boolean poly (polymorphic (t));
String const& name (ec.get<String> ("paggr"));
- String pre (unclash (name, "pre"));
- String post (unclash (name, "post"));
+ String pre;
+ String post;
String root_parser (unclash (name, "root_parser"));
+ String root_map;
String root_name (unclash (name, "root_name"));
String root_namespace (unclash (name, "root_namespace"));
String error, reset;
+ String parser_map, parser_map_entries;
InstanceSet set;
- set.insert (pre);
- set.insert (post);
set.insert (name);
set.insert (root_parser);
+
+ if (poly)
+ {
+ root_map = unclash (name, "root_map");
+ set.insert (root_map);
+ }
+ else
+ {
+ pre = unclash (name, "pre");
+ post = unclash (name, "post");
+
+ set.insert (pre);
+ set.insert (post);
+ }
+
set.insert (root_name);
set.insert (root_namespace);
- if (!exceptions)
+ if (!poly && !exceptions)
{
error = unclash (name, "_error");
set.insert (error);
}
- if (Context::reset)
+ if (!poly && Context::reset)
{
reset = unclash (name, "reset");
set.insert (reset);
}
+ if (poly_code)
+ {
+ parser_map = unclash (name, "parser_map_");
+ parser_map_entries = unclash (name, "parser_map_entries_");
+
+ ec.set ("paggr-parser-map", parser_map);
+ ec.set ("paggr-parser-map-entries", parser_map_entries);
+ }
+
ec.set ("paggr-map", TypeInstanceMap ());
TypeInstanceMap& map (ec.get<TypeInstanceMap> ("paggr-map"));
+ TypeIdInstanceMap tid_map;
- ParserDef def (*this, map, set);
+ ParserDef def (*this, map, tid_map, set);
def.dispatch (t);
+ if (poly_code && !tid_map.empty ())
+ ec.set ("paggr-tid-map", tid_map);
+
String const& root_member (map.find (&t)->second);
os << "// Parser aggregate for the " << comment (e.name ()) <<
@@ -706,24 +828,27 @@ namespace CXX
os << name << " ();"
<< endl;
- // pre ()
- //
- os << "void" << endl
- << pre << " ()"
- << "{"
- << "this->" << root_member << ".pre ();"
- << "}";
+ if (!poly)
+ {
+ // pre ()
+ //
+ os << "void" << endl
+ << pre << " ()"
+ << "{"
+ << "this->" << root_member << ".pre ();"
+ << "}";
- // post ()
- //
- String const& ret (pret_type (t));
+ // post ()
+ //
+ String const& ret (pret_type (t));
- os << ret << endl
- << post << " ()"
- << "{"
- << (ret == L"void" ? "" : "return ") << "this->" <<
- root_member << "." << post_name (t) << " ();"
- << "}";
+ os << ret << endl
+ << post << " ()"
+ << "{"
+ << (ret == L"void" ? "" : "return ") << "this->" <<
+ root_member << "." << post_name (t) << " ();"
+ << "}";
+ }
// root_parser ()
//
@@ -733,6 +858,20 @@ namespace CXX
<< "return this->" << root_member << ";"
<< "}";
+ if (poly)
+ {
+ // root_map ()
+ //
+ if (poly)
+ {
+ os << "const " << xs_ns_name () + L"::parser_map&" << endl
+ << root_map << " ()"
+ << "{"
+ << "return this->" << parser_map << ";"
+ << "}";
+ }
+ }
+
// root_name ()
//
os << "static const char*" << endl
@@ -747,7 +886,7 @@ namespace CXX
// _error ()
//
- if (error)
+ if (!poly && error)
{
os << xs_ns_name () << "::parser_error" << endl
<< error << " ()"
@@ -763,8 +902,12 @@ namespace CXX
os << "void" << endl
<< reset << " ()"
<< "{"
- << "this->" << root_member << "._reset ();"
- << "}";
+ << "this->" << root_member << "._reset ();";
+
+ if (poly && tid_map.size () > 0)
+ os << "this->" << parser_map << ".reset ();";
+
+ os << "}";
}
os << "public:" << endl;
@@ -773,6 +916,14 @@ namespace CXX
i != end; ++i)
os << fq_name (*i->first, "p:impl") << " " << i->second << ";";
+ if (tid_map.size () > 0)
+ {
+ os << endl
+ << "::xsde::cxx::hybrid::parser_map_impl " << parser_map << ";"
+ << "::xsde::cxx::hybrid::parser_map_impl::entry " <<
+ parser_map_entries << "[" << tid_map.size () << "UL];";
+ }
+
os << "};";
}
};
@@ -801,6 +952,10 @@ namespace CXX
if (gen)
{
+ if (ctx.poly_code)
+ ctx.os << "#include <xsde/cxx/hybrid/parser-map.hxx>" << endl
+ << endl;
+
// Emit "weak" header includes that are used in the file-per-type
// compilation model.
//
@@ -813,6 +968,28 @@ namespace CXX
schema.dispatch (ctx.schema_root);
}
+ // Emit includes for additional schemas that define derived
+ // polymorphic types.
+ //
+ if (ctx.poly_code)
+ {
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+
+ schema >> sources >> schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names names;
+ AggregateInclude include (ctx, "paggr");
+
+ schema >> schema_names >> ns >> names >> include;
+
+ schema.dispatch (ctx.schema_root);
+ }
+
+ // Generate code.
+ //
Traversal::Schema schema;
Traversal::Sources sources;
diff --git a/xsde/cxx/hybrid/parser-aggregate-source.cxx b/xsde/cxx/hybrid/parser-aggregate-source.cxx
index 6e80318..055cffb 100644
--- a/xsde/cxx/hybrid/parser-aggregate-source.cxx
+++ b/xsde/cxx/hybrid/parser-aggregate-source.cxx
@@ -4,6 +4,7 @@
// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
#include <cxx/hybrid/parser-aggregate-source.hxx>
+#include <cxx/hybrid/aggregate-elements.hxx>
#include <xsd-frontend/semantic-graph.hxx>
#include <xsd-frontend/traversal.hxx>
@@ -16,10 +17,6 @@ namespace CXX
{
namespace
{
- typedef
- Cult::Containers::Map<SemanticGraph::Type*, String>
- TypeInstanceMap;
-
//
//
struct ParticleArg: Traversal::Element, Context
@@ -186,6 +183,57 @@ namespace CXX
TypeInstanceMap& map_;
};
+ //
+ //
+ struct ParserMapConnect: Traversal::Complex,
+ Traversal::Element,
+ Context
+ {
+ ParserMapConnect (Context& c, String const& inst, String const& map)
+ : Context (c), inst_ (inst), map_ (map)
+ {
+ *this >> inherits_ >> *this;
+
+ *this >> contains_compositor_;
+ contains_compositor_ >> compositor_;
+ compositor_ >> contains_particle_;
+ contains_particle_ >> compositor_;
+ contains_particle_ >> *this;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ inherits (c);
+
+ if (!restriction_p (c))
+ contains_compositor (c);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ SemanticGraph::Type& t (e.type ());
+
+ if (polymorphic (t))
+ {
+ os << "this->" << inst_ << "." <<
+ e.context ().get<String> ("p:parser") << " (" << map_ << ");";
+ }
+ }
+
+ private:
+ String const& inst_;
+ String const& map_;
+
+ Traversal::Inherits inherits_;
+
+ Traversal::Compositor compositor_;
+ Traversal::Element particle_;
+ Traversal::ContainsCompositor contains_compositor_;
+ Traversal::ContainsParticle contains_particle_;
+ };
+
struct GlobalType: Traversal::Type, Context
{
GlobalType (Context& c)
@@ -208,18 +256,67 @@ namespace CXX
<< "//" << endl
<< endl;
+ TypeIdInstanceMap* tid_map (0);
+
+ if (poly_code && tc.count ("paggr-tid-map"))
+ tid_map = &tc.get<TypeIdInstanceMap> ("paggr-tid-map");
+
// c-tor ()
//
os << name << "::" << endl
- << name << " ()"
- << "{";
+ << name << " ()";
+
+ if (tid_map)
+ {
+ os << endl
+ << ": " << tc.get<String> ("paggr-parser-map") << " (" <<
+ tc.get<String> ("paggr-parser-map-entries") << ", " <<
+ tid_map->size () << "UL)";
+ }
+
+ os << "{";
+ // Populate the polymorphic parser map.
+ //
+ if (tid_map)
+ {
+ String const& entry (tc.get<String> ("paggr-parser-map-entries"));
+
+ Size n (0);
+
+ for (TypeIdInstanceMap::Iterator i (tid_map->begin ());
+ i != tid_map->end ();
+ ++i, ++n)
+ {
+ os << entry << "[" << n << "UL].type_id = " <<
+ fq_name (*i->second.type, "p:name") << "::_static_type ();"
+ << entry << "[" << n << "UL].parser = &this->" <<
+ i->second.name << ";"
+ << endl;
+ }
+ }
+
+ // Connect parsers.
+ //
ParserConnect connect (*this, map);
for (TypeInstanceMap::Iterator i (map.begin ()), end (map.end ());
i != end; ++i)
connect.dispatch (*i->first);
+ // Connect the parser map.
+ //
+ if (tid_map)
+ {
+ for (TypeInstanceMap::Iterator i (map.begin ()), end (map.end ());
+ i != end; ++i)
+ {
+ ParserMapConnect t (
+ *this, i->second, tc.get<String> ("paggr-parser-map"));
+ t.dispatch (*i->first);
+ }
+ }
+
os << "}";
}
};
@@ -246,18 +343,67 @@ namespace CXX
<< "//" << endl
<< endl;
+ TypeIdInstanceMap* tid_map (0);
+
+ if (poly_code && ec.count ("paggr-tid-map"))
+ tid_map = &ec.get<TypeIdInstanceMap> ("paggr-tid-map");
+
// c-tor ()
//
os << name << "::" << endl
- << name << " ()"
- << "{";
+ << name << " ()";
+
+ if (tid_map)
+ {
+ os << endl
+ << ": " << ec.get<String> ("paggr-parser-map") << " (" <<
+ ec.get<String> ("paggr-parser-map-entries") << ", " <<
+ tid_map->size () << "UL)";
+ }
+
+ os << "{";
+
+ // Populate the polymorphic parser map.
+ //
+ if (tid_map)
+ {
+ String const& entry (ec.get<String> ("paggr-parser-map-entries"));
+
+ Size n (0);
+
+ for (TypeIdInstanceMap::Iterator i (tid_map->begin ());
+ i != tid_map->end ();
+ ++i, ++n)
+ {
+ os << entry << "[" << n << "UL].type_id = " <<
+ fq_name (*i->second.type, "p:name") << "::_static_type ();"
+ << entry << "[" << n << "UL].parser = &this->" <<
+ i->second.name << ";"
+ << endl;
+ }
+ }
+ // Connect parsers.
+ //
ParserConnect connect (*this, map);
for (TypeInstanceMap::Iterator i (map.begin ()), end (map.end ());
i != end; ++i)
connect.dispatch (*i->first);
+ // Connect the parser map.
+ //
+ if (tid_map)
+ {
+ for (TypeInstanceMap::Iterator i (map.begin ()), end (map.end ());
+ i != end; ++i)
+ {
+ ParserMapConnect t (
+ *this, i->second, ec.get<String> ("paggr-parser-map"));
+ t.dispatch (*i->first);
+ }
+ }
+
os << "}";
// root_name ()
diff --git a/xsde/cxx/hybrid/parser-header.cxx b/xsde/cxx/hybrid/parser-header.cxx
index 72cc2e3..6a893c5 100644
--- a/xsde/cxx/hybrid/parser-header.cxx
+++ b/xsde/cxx/hybrid/parser-header.cxx
@@ -347,6 +347,34 @@ namespace CXX
}
};
+ //
+ //
+ struct PostOverride: Traversal::Complex, Context
+ {
+ PostOverride (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ if (c.inherits_p ())
+ {
+ SemanticGraph::Type& b (c.inherits ().base ());
+
+ if (polymorphic (b))
+ {
+ if (tiein)
+ dispatch (b);
+
+ os << "virtual " << pret_type (b) << endl
+ << post_name (b) << " ();"
+ << endl;
+ }
+ }
+ }
+ };
//
//
@@ -354,6 +382,8 @@ namespace CXX
{
Complex (Context& c)
: Context (c),
+ post_override_ (c),
+
// State.
//
compositor_state_ (c),
@@ -472,6 +502,9 @@ namespace CXX
// post
//
+ if (polymorphic (c))
+ post_override_.dispatch (c);
+
os << "virtual " << ret << endl
<< post_name (c) << " ();"
<< endl;
@@ -546,6 +579,8 @@ namespace CXX
}
private:
+ PostOverride post_override_;
+
// State.
//
CompositorState compositor_state_;
diff --git a/xsde/cxx/hybrid/parser-name-processor.cxx b/xsde/cxx/hybrid/parser-name-processor.cxx
index 740cf36..c635aec 100644
--- a/xsde/cxx/hybrid/parser-name-processor.cxx
+++ b/xsde/cxx/hybrid/parser-name-processor.cxx
@@ -657,7 +657,8 @@ namespace CXX
Void
process_impl (CLI::Options const& ops,
SemanticGraph::Schema& tu,
- SemanticGraph::Path const& file)
+ SemanticGraph::Path const& file,
+ Boolean deep)
{
Context ctx (ops, tu, file);
@@ -686,6 +687,9 @@ namespace CXX
schema.dispatch (tu);
}
+ if (!deep)
+ return;
+
// Pass two - assign names inside complex types. Here we don't
// need to go into included/imported schemas.
//
@@ -717,9 +721,10 @@ namespace CXX
Void ParserNameProcessor::
process (CLI::Options const& ops,
SemanticGraph::Schema& tu,
- SemanticGraph::Path const& file)
+ SemanticGraph::Path const& file,
+ Boolean deep)
{
- process_impl (ops, tu, file);
+ process_impl (ops, tu, file, deep);
}
}
}
diff --git a/xsde/cxx/hybrid/parser-name-processor.hxx b/xsde/cxx/hybrid/parser-name-processor.hxx
index ea3e985..d0e1970 100644
--- a/xsde/cxx/hybrid/parser-name-processor.hxx
+++ b/xsde/cxx/hybrid/parser-name-processor.hxx
@@ -24,7 +24,8 @@ namespace CXX
Void
process (CLI::Options const& options,
XSDFrontend::SemanticGraph::Schema&,
- XSDFrontend::SemanticGraph::Path const& file);
+ XSDFrontend::SemanticGraph::Path const& file,
+ Boolean deep);
};
}
}
diff --git a/xsde/cxx/hybrid/parser-source.cxx b/xsde/cxx/hybrid/parser-source.cxx
index 4c4237c..505d661 100644
--- a/xsde/cxx/hybrid/parser-source.cxx
+++ b/xsde/cxx/hybrid/parser-source.cxx
@@ -904,11 +904,59 @@ namespace CXX
//
//
+ struct PostOverride: Traversal::Complex, Context
+ {
+ PostOverride (Context& c)
+ : Context (c), scope_ (0)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ Boolean clear (false);
+
+ if (scope_ == 0)
+ {
+ scope_ = &c;
+ clear = true;
+ }
+
+ if (c.inherits_p ())
+ {
+ SemanticGraph::Type& b (c.inherits ().base ());
+
+ if (polymorphic (b))
+ {
+ if (tiein)
+ dispatch (b);
+
+ String const& scope (epimpl_custom (*scope_));
+
+ os << pret_type (b) << " " << scope << "::" << endl
+ << post_name (b) << " ()"
+ << "{"
+ << "return this->" << post_name (c) << " ();"
+ << "}";
+ }
+ }
+
+ if (clear)
+ scope_ = 0;
+ }
+
+ private:
+ SemanticGraph::Complex* scope_;
+ };
+
+ //
+ //
struct Complex: Traversal::Complex, Context
{
Complex (Context& c)
: Context (c),
base_name_ (c, TypeName::base),
+ post_override_ (c),
compositor_callback_ (c),
particle_callback_ (c),
attribute_callback_ (c)
@@ -1253,6 +1301,9 @@ namespace CXX
// post
//
+ if (polymorphic (c))
+ post_override_.dispatch (c);
+
os << ret << " " << name << "::" << endl
<< post_name (c) << " ()"
<< "{";
@@ -1350,6 +1401,7 @@ namespace CXX
private:
TypeName base_name_;
+ PostOverride post_override_;
CompositorCallback compositor_callback_;
ParticleCallback particle_callback_;
diff --git a/xsde/cxx/hybrid/serializer-aggregate-header.cxx b/xsde/cxx/hybrid/serializer-aggregate-header.cxx
index b697715..3e3260f 100644
--- a/xsde/cxx/hybrid/serializer-aggregate-header.cxx
+++ b/xsde/cxx/hybrid/serializer-aggregate-header.cxx
@@ -4,6 +4,8 @@
// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
#include <cxx/hybrid/serializer-aggregate-header.hxx>
+#include <cxx/hybrid/aggregate-elements.hxx>
+#include <cxx/hybrid/aggregate-include.hxx>
#include <xsd-frontend/semantic-graph.hxx>
#include <xsd-frontend/traversal.hxx>
@@ -17,10 +19,6 @@ namespace CXX
{
namespace
{
- typedef
- Cult::Containers::Map<SemanticGraph::Type*, String>
- TypeInstanceMap;
-
typedef Cult::Containers::Set<String> InstanceSet;
// For base types we only want member's types, but not the
@@ -108,8 +106,15 @@ namespace CXX
Context
{
- SerializerDef (Context& c, TypeInstanceMap& map, InstanceSet& set)
- : Context (c), map_ (map), set_ (set), base_ (c)
+ SerializerDef (Context& c,
+ TypeInstanceMap& map,
+ TypeIdInstanceMap& tid_map,
+ InstanceSet& set)
+ : Context (c),
+ map_ (map),
+ tid_map_ (tid_map),
+ set_ (set),
+ base_ (c)
{
*this >> inherits_ >> base_ >> inherits_;
@@ -136,8 +141,10 @@ namespace CXX
{
if (map_.find (&t) == map_.end ())
{
- String inst (find_instance_name (t));
- map_[&t] = inst;
+ map_[&t] = find_instance_name (t);
+
+ if (polymorphic (t))
+ collect (t);
}
}
@@ -146,10 +153,11 @@ namespace CXX
{
if (map_.find (&l) == map_.end ())
{
- String inst (find_instance_name (l));
- map_[&l] = inst;
-
+ map_[&l] = find_instance_name (l);
dispatch (l.argumented ().type ());
+
+ if (polymorphic (l))
+ collect (l);
}
}
@@ -158,8 +166,7 @@ namespace CXX
{
if (map_.find (&c) == map_.end ())
{
- String inst (find_instance_name (c));
- map_[&c] = inst;
+ map_[&c] = find_instance_name (c);
// Use base type's serializers in case of a restriction
// since we are not capable of using a derived type
@@ -172,6 +179,38 @@ namespace CXX
names (c);
contains_compositor (c);
}
+
+ if (polymorphic (c))
+ collect (c);
+ }
+ }
+
+ virtual Void
+ collect (SemanticGraph::Type& t)
+ {
+ using SemanticGraph::Type;
+
+ for (Type::BegetsIterator i (t.begets_begin ());
+ i != t.begets_end ();
+ ++i)
+ {
+ Type& d (i->derived ());
+
+ String id (d.name ());
+ if (String ns = xml_ns_name (d))
+ {
+ id += L' ';
+ id += ns;
+ }
+
+ dispatch (d);
+
+ if (tid_map_.find (id) == tid_map_.end ())
+ {
+ tid_map_[id].type = &d;
+ tid_map_[id].name = map_.find (&d)->second;
+ collect (d);
+ }
}
}
@@ -475,10 +514,7 @@ namespace CXX
fund_type (SemanticGraph::Type& t, String const& name)
{
if (map_.find (&t) == map_.end ())
- {
- String inst (find_instance_name (name));
- map_[&t] = inst;
- }
+ map_[&t] = find_instance_name (name);
}
String
@@ -504,6 +540,7 @@ namespace CXX
}
TypeInstanceMap& map_;
+ TypeIdInstanceMap& tid_map_;
InstanceSet& set_;
BaseType base_;
@@ -535,37 +572,65 @@ namespace CXX
if (!tc.count ("saggr"))
return;
+ Boolean poly (polymorphic (t));
String const& name (tc.get<String> ("saggr"));
- String pre (unclash (name, "pre"));
- String post (unclash (name, "post"));
+ String pre;
+ String post;
String root_serializer (unclash (name, "root_serializer"));
+ String root_map;
String error, reset;
+ String serializer_map, serializer_map_entries;
InstanceSet set;
- set.insert (pre);
- set.insert (post);
set.insert (name);
set.insert (root_serializer);
- if (!exceptions)
+ if (poly)
+ {
+ root_map = unclash (name, "root_map");
+ set.insert (root_map);
+ }
+ else
+ {
+ pre = unclash (name, "pre");
+ post = unclash (name, "post");
+
+ set.insert (pre);
+ set.insert (post);
+ }
+
+ if (!poly && !exceptions)
{
error = unclash (name, "_error");
set.insert (error);
}
- if (Context::reset)
+ if (!poly && Context::reset)
{
reset = unclash (name, "reset");
set.insert (reset);
}
+ if (poly_code)
+ {
+ serializer_map = unclash (name, "serializer_map_");
+ serializer_map_entries = unclash (name, "serializer_map_entries_");
+
+ tc.set ("saggr-serializer-map", serializer_map);
+ tc.set ("saggr-serializer-map-entries", serializer_map_entries);
+ }
+
tc.set ("saggr-map", TypeInstanceMap ());
TypeInstanceMap& map (tc.get<TypeInstanceMap> ("saggr-map"));
+ TypeIdInstanceMap tid_map;
- SerializerDef def (*this, map, set);
+ SerializerDef def (*this, map, tid_map, set);
def.dispatch (t);
+ if (poly_code && !tid_map.empty ())
+ tc.set ("saggr-tid-map", tid_map);
+
String const& root_member (map.find (&t)->second);
os << "// Serializer aggregate for the " << comment (t.name ()) <<
@@ -581,29 +646,32 @@ namespace CXX
os << name << " ();"
<< endl;
- // pre ()
- //
- String const& arg (sarg_type (t));
+ if (!poly)
+ {
+ // pre ()
+ //
+ String const& arg (sarg_type (t));
- os << "void" << endl
- << pre << " (";
+ os << "void" << endl
+ << pre << " (";
- if (arg != L"void")
- os << arg << " x";
+ if (arg != L"void")
+ os << arg << " x";
- os <<")"
- << "{"
- << "this->" << root_member << ".pre (" <<
- (arg != L"void" ? "x" : "") << ");"
- << "}";
+ os <<")"
+ << "{"
+ << "this->" << root_member << ".pre (" <<
+ (arg != L"void" ? "x" : "") << ");"
+ << "}";
- // post ()
- //
- os << "void" << endl
- << post << " ()"
- << "{"
- << "this->" << root_member << ".post ();"
- << "}";
+ // post ()
+ //
+ os << "void" << endl
+ << post << " ()"
+ << "{"
+ << "this->" << root_member << ".post ();"
+ << "}";
+ }
// root_serializer ()
//
@@ -613,9 +681,23 @@ namespace CXX
<< "return this->" << root_member << ";"
<< "}";
+ if (poly)
+ {
+ // root_map ()
+ //
+ if (poly)
+ {
+ os << "const " << xs_ns_name () + L"::serializer_map&" << endl
+ << root_map << " ()"
+ << "{"
+ << "return this->" << serializer_map << ";"
+ << "}";
+ }
+ }
+
// _error ()
//
- if (error)
+ if (!poly && error)
{
os << xs_ns_name () << "::serializer_error" << endl
<< error << " ()"
@@ -631,8 +713,12 @@ namespace CXX
os << "void" << endl
<< reset << " ()"
<< "{"
- << "this->" << root_member << "._reset ();"
- << "}";
+ << "this->" << root_member << "._reset ();";
+
+ if (poly && tid_map.size () > 0)
+ os << "this->" << serializer_map << ".reset ();";
+
+ os << "}";
}
os << "public:" << endl;
@@ -641,6 +727,15 @@ namespace CXX
i != end; ++i)
os << fq_name (*i->first, "s:impl") << " " << i->second << ";";
+ if (tid_map.size () > 0)
+ {
+ os << endl
+ << "::xsde::cxx::hybrid::serializer_map_impl " <<
+ serializer_map << ";"
+ << "::xsde::cxx::hybrid::serializer_map_impl::entry " <<
+ serializer_map_entries << "[" << tid_map.size () << "UL];";
+ }
+
os << "};";
}
};
@@ -661,41 +756,70 @@ namespace CXX
return;
SemanticGraph::Type& t (e.type ());
+ Boolean poly (polymorphic (t));
String const& name (ec.get<String> ("saggr"));
- String pre (unclash (name, "pre"));
- String post (unclash (name, "post"));
+ String pre;
+ String post;
String root_serializer (unclash (name, "root_serializer"));
+ String root_map;
String root_name (unclash (name, "root_name"));
String root_namespace (unclash (name, "root_namespace"));
String error, reset;
+ String serializer_map, serializer_map_entries;
InstanceSet set;
- set.insert (pre);
- set.insert (post);
set.insert (name);
set.insert (root_serializer);
+
+ if (poly)
+ {
+ root_map = unclash (name, "root_map");
+ set.insert (root_map);
+ }
+ else
+ {
+ pre = unclash (name, "pre");
+ post = unclash (name, "post");
+
+ set.insert (pre);
+ set.insert (post);
+ }
+
set.insert (root_name);
set.insert (root_namespace);
- if (!exceptions)
+ if (!poly && !exceptions)
{
error = unclash (name, "_error");
set.insert (error);
}
- if (Context::reset)
+ if (!poly && Context::reset)
{
reset = unclash (name, "reset");
set.insert (reset);
}
+ if (poly_code)
+ {
+ serializer_map = unclash (name, "serializer_map_");
+ serializer_map_entries = unclash (name, "serializer_map_entries_");
+
+ ec.set ("saggr-serializer-map", serializer_map);
+ ec.set ("saggr-serializer-map-entries", serializer_map_entries);
+ }
+
ec.set ("saggr-map", TypeInstanceMap ());
TypeInstanceMap& map (ec.get<TypeInstanceMap> ("saggr-map"));
+ TypeIdInstanceMap tid_map;
- SerializerDef def (*this, map, set);
+ SerializerDef def (*this, map, tid_map, set);
def.dispatch (t);
+ if (poly_code && !tid_map.empty ())
+ ec.set ("saggr-tid-map", tid_map);
+
String const& root_member (map.find (&t)->second);
os << "// Serializer aggregate for the " << comment (e.name ()) <<
@@ -711,29 +835,32 @@ namespace CXX
os << name << " ();"
<< endl;
- // pre ()
- //
- String const& arg (sarg_type (t));
+ if (!poly)
+ {
+ // pre ()
+ //
+ String const& arg (sarg_type (t));
- os << "void" << endl
- << pre << " (";
+ os << "void" << endl
+ << pre << " (";
- if (arg != L"void")
- os << arg << " x";
+ if (arg != L"void")
+ os << arg << " x";
- os <<")"
- << "{"
- << "this->" << root_member << ".pre (" <<
- (arg != L"void" ? "x" : "") << ");"
- << "}";
+ os <<")"
+ << "{"
+ << "this->" << root_member << ".pre (" <<
+ (arg != L"void" ? "x" : "") << ");"
+ << "}";
- // post ()
- //
- os << "void" << endl
- << post << " ()"
- << "{"
- << "this->" << root_member << ".post ();"
- << "}";
+ // post ()
+ //
+ os << "void" << endl
+ << post << " ()"
+ << "{"
+ << "this->" << root_member << ".post ();"
+ << "}";
+ }
// root_serializer ()
//
@@ -743,6 +870,20 @@ namespace CXX
<< "return this->" << root_member << ";"
<< "}";
+ if (poly)
+ {
+ // root_map ()
+ //
+ if (poly)
+ {
+ os << "const " << xs_ns_name () + L"::serializer_map&" << endl
+ << root_map << " ()"
+ << "{"
+ << "return this->" << serializer_map << ";"
+ << "}";
+ }
+ }
+
// root_name ()
//
os << "static const char*" << endl
@@ -757,7 +898,7 @@ namespace CXX
// _error ()
//
- if (error)
+ if (!poly && error)
{
os << xs_ns_name () << "::serializer_error" << endl
<< error << " ()"
@@ -773,8 +914,12 @@ namespace CXX
os << "void" << endl
<< reset << " ()"
<< "{"
- << "this->" << root_member << "._reset ();"
- << "}";
+ << "this->" << root_member << "._reset ();";
+
+ if (poly && tid_map.size () > 0)
+ os << "this->" << serializer_map << ".reset ();";
+
+ os << "}";
}
os << "public:" << endl;
@@ -783,6 +928,15 @@ namespace CXX
i != end; ++i)
os << fq_name (*i->first, "s:impl") << " " << i->second << ";";
+ if (tid_map.size () > 0)
+ {
+ os << endl
+ << "::xsde::cxx::hybrid::serializer_map_impl " <<
+ serializer_map << ";"
+ << "::xsde::cxx::hybrid::serializer_map_impl::entry " <<
+ serializer_map_entries << "[" << tid_map.size () << "UL];";
+ }
+
os << "};";
}
};
@@ -811,6 +965,10 @@ namespace CXX
if (gen)
{
+ if (ctx.poly_code)
+ ctx.os << "#include <xsde/cxx/hybrid/serializer-map.hxx>" << endl
+ << endl;
+
// Emit "weak" header includes that are used in the file-per-type
// compilation model.
//
@@ -823,6 +981,28 @@ namespace CXX
schema.dispatch (ctx.schema_root);
}
+ // Emit includes for additional schemas that define derived
+ // polymorphic types.
+ //
+ if (ctx.poly_code)
+ {
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+
+ schema >> sources >> schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names names;
+ AggregateInclude include (ctx, "saggr");
+
+ schema >> schema_names >> ns >> names >> include;
+
+ schema.dispatch (ctx.schema_root);
+ }
+
+ // Generate code.
+ //
Traversal::Schema schema;
Traversal::Sources sources;
diff --git a/xsde/cxx/hybrid/serializer-aggregate-source.cxx b/xsde/cxx/hybrid/serializer-aggregate-source.cxx
index 7e305b6..0422031 100644
--- a/xsde/cxx/hybrid/serializer-aggregate-source.cxx
+++ b/xsde/cxx/hybrid/serializer-aggregate-source.cxx
@@ -4,6 +4,7 @@
// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
#include <cxx/hybrid/serializer-aggregate-source.hxx>
+#include <cxx/hybrid/aggregate-elements.hxx>
#include <xsd-frontend/semantic-graph.hxx>
#include <xsd-frontend/traversal.hxx>
@@ -16,10 +17,6 @@ namespace CXX
{
namespace
{
- typedef
- Cult::Containers::Map<SemanticGraph::Type*, String>
- TypeInstanceMap;
-
//
//
struct ParticleArg: Traversal::Element, Context
@@ -186,6 +183,62 @@ namespace CXX
TypeInstanceMap& map_;
};
+ //
+ //
+ struct SerializerMapConnect: Traversal::Complex,
+ Traversal::Element,
+ Context
+ {
+ SerializerMapConnect (Context& c,
+ String const& inst,
+ String const& map)
+ : Context (c), inst_ (inst), map_ (map)
+ {
+ *this >> inherits_ >> *this;
+
+ *this >> contains_compositor_;
+ contains_compositor_ >> compositor_;
+ compositor_ >> contains_particle_;
+ contains_particle_ >> compositor_;
+ contains_particle_ >> *this;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ inherits (c);
+
+ if (!restriction_p (c))
+ contains_compositor (c);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ SemanticGraph::Type& t (e.type ());
+
+ if (polymorphic (t))
+ {
+ os << "this->" << inst_ << "." <<
+ e.context ().get<String> ("s:serializer") << " (" <<
+ map_ << ");";
+ }
+ }
+
+ private:
+ String const& inst_;
+ String const& map_;
+
+ Traversal::Inherits inherits_;
+
+ Traversal::Compositor compositor_;
+ Traversal::Element particle_;
+ Traversal::ContainsCompositor contains_compositor_;
+ Traversal::ContainsParticle contains_particle_;
+ };
+
+ //
+ //
struct GlobalType: Traversal::Type, Context
{
GlobalType (Context& c)
@@ -208,18 +261,68 @@ namespace CXX
<< "//" << endl
<< endl;
+ TypeIdInstanceMap* tid_map (0);
+
+ if (poly_code && tc.count ("saggr-tid-map"))
+ tid_map = &tc.get<TypeIdInstanceMap> ("saggr-tid-map");
+
// c-tor ()
//
os << name << "::" << endl
- << name << " ()"
- << "{";
+ << name << " ()";
+
+ if (tid_map)
+ {
+ os << endl
+ << ": " << tc.get<String> ("saggr-serializer-map") << " (" <<
+ tc.get<String> ("saggr-serializer-map-entries") << ", " <<
+ tid_map->size () << "UL)";
+ }
+
+ os << "{";
+ // Populate the polymorphic serializer map.
+ //
+ if (tid_map)
+ {
+ String const& entry (
+ tc.get<String> ("saggr-serializer-map-entries"));
+
+ Size n (0);
+
+ for (TypeIdInstanceMap::Iterator i (tid_map->begin ());
+ i != tid_map->end ();
+ ++i, ++n)
+ {
+ os << entry << "[" << n << "UL].type_id = " <<
+ fq_name (*i->second.type, "s:name") << "::_static_type ();"
+ << entry << "[" << n << "UL].serializer = &this->" <<
+ i->second.name << ";"
+ << endl;
+ }
+ }
+
+ // Connect parsers.
+ //
SerializerConnect connect (*this, map);
for (TypeInstanceMap::Iterator i (map.begin ()), end (map.end ());
i != end; ++i)
connect.dispatch (*i->first);
+ // Connect the serializer map.
+ //
+ if (tid_map)
+ {
+ for (TypeInstanceMap::Iterator i (map.begin ()), end (map.end ());
+ i != end; ++i)
+ {
+ SerializerMapConnect t (
+ *this, i->second, tc.get<String> ("saggr-serializer-map"));
+ t.dispatch (*i->first);
+ }
+ }
+
os << "}";
}
};
@@ -246,18 +349,68 @@ namespace CXX
<< "//" << endl
<< endl;
+ TypeIdInstanceMap* tid_map (0);
+
+ if (poly_code && ec.count ("saggr-tid-map"))
+ tid_map = &ec.get<TypeIdInstanceMap> ("saggr-tid-map");
+
// c-tor ()
//
os << name << "::" << endl
- << name << " ()"
- << "{";
+ << name << " ()";
+
+ if (tid_map)
+ {
+ os << endl
+ << ": " << ec.get<String> ("saggr-serializer-map") << " (" <<
+ ec.get<String> ("saggr-serializer-map-entries") << ", " <<
+ tid_map->size () << "UL)";
+ }
+
+ os << "{";
+
+ // Populate the polymorphic serializer map.
+ //
+ if (tid_map)
+ {
+ String const& entry (
+ ec.get<String> ("saggr-serializer-map-entries"));
+
+ Size n (0);
+
+ for (TypeIdInstanceMap::Iterator i (tid_map->begin ());
+ i != tid_map->end ();
+ ++i, ++n)
+ {
+ os << entry << "[" << n << "UL].type_id = " <<
+ fq_name (*i->second.type, "s:name") << "::_static_type ();"
+ << entry << "[" << n << "UL].serializer = &this->" <<
+ i->second.name << ";"
+ << endl;
+ }
+ }
+ // Connect parsers.
+ //
SerializerConnect connect (*this, map);
for (TypeInstanceMap::Iterator i (map.begin ()), end (map.end ());
i != end; ++i)
connect.dispatch (*i->first);
+ // Connect the serializer map.
+ //
+ if (tid_map)
+ {
+ for (TypeInstanceMap::Iterator i (map.begin ()), end (map.end ());
+ i != end; ++i)
+ {
+ SerializerMapConnect t (
+ *this, i->second, ec.get<String> ("saggr-serializer-map"));
+ t.dispatch (*i->first);
+ }
+ }
+
os << "}";
// root_name ()
diff --git a/xsde/cxx/hybrid/serializer-header.cxx b/xsde/cxx/hybrid/serializer-header.cxx
index 20f4e15..db0578f 100644
--- a/xsde/cxx/hybrid/serializer-header.cxx
+++ b/xsde/cxx/hybrid/serializer-header.cxx
@@ -343,10 +343,40 @@ namespace CXX
//
//
+ struct PreOverride: Traversal::Complex, Context
+ {
+ PreOverride (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ if (c.inherits_p ())
+ {
+ SemanticGraph::Type& b (c.inherits ().base ());
+
+ if (polymorphic (b))
+ {
+ if (tiein)
+ dispatch (b);
+
+ os << "virtual void" << endl
+ << "pre (" << sarg_type (b) << ");"
+ << endl;
+ }
+ }
+ }
+ };
+
+ //
+ //
struct Complex : Traversal::Complex, Context
{
Complex (Context& c)
: Context (c),
+ pre_override_ (c),
// State.
//
@@ -422,6 +452,9 @@ namespace CXX
// pre
//
+ if (polymorphic (c))
+ pre_override_.dispatch (c);
+
os << "virtual void" << endl
<< "pre (" << arg << ");"
<< endl;
@@ -522,6 +555,8 @@ namespace CXX
}
private:
+ PreOverride pre_override_;
+
// State.
//
CompositorState compositor_state_;
diff --git a/xsde/cxx/hybrid/serializer-name-processor.cxx b/xsde/cxx/hybrid/serializer-name-processor.cxx
index ba4a268..2f7d296 100644
--- a/xsde/cxx/hybrid/serializer-name-processor.cxx
+++ b/xsde/cxx/hybrid/serializer-name-processor.cxx
@@ -265,7 +265,7 @@ namespace CXX
if (!name)
return;
- String const& skel (lc.get<String> ("p:name"));
+ String const& skel (lc.get<String> ("s:name"));
NameSet set;
set.insert (name);
@@ -672,7 +672,8 @@ namespace CXX
Void
process_impl (CLI::Options const& ops,
SemanticGraph::Schema& tu,
- SemanticGraph::Path const& file)
+ SemanticGraph::Path const& file,
+ Boolean deep)
{
Context ctx (ops, tu, file);
@@ -701,6 +702,9 @@ namespace CXX
schema.dispatch (tu);
}
+ if (!deep)
+ return;
+
// Pass two - assign names inside complex types. Here we don't
// need to go into included/imported schemas.
//
@@ -732,9 +736,10 @@ namespace CXX
Void SerializerNameProcessor::
process (CLI::Options const& ops,
SemanticGraph::Schema& tu,
- SemanticGraph::Path const& file)
+ SemanticGraph::Path const& file,
+ Boolean deep)
{
- process_impl (ops, tu, file);
+ process_impl (ops, tu, file, deep);
}
}
}
diff --git a/xsde/cxx/hybrid/serializer-name-processor.hxx b/xsde/cxx/hybrid/serializer-name-processor.hxx
index f69dfe4..b607c24 100644
--- a/xsde/cxx/hybrid/serializer-name-processor.hxx
+++ b/xsde/cxx/hybrid/serializer-name-processor.hxx
@@ -24,7 +24,8 @@ namespace CXX
Void
process (CLI::Options const& options,
XSDFrontend::SemanticGraph::Schema&,
- XSDFrontend::SemanticGraph::Path const& file);
+ XSDFrontend::SemanticGraph::Path const& file,
+ Boolean deep);
};
}
}
diff --git a/xsde/cxx/hybrid/serializer-source.cxx b/xsde/cxx/hybrid/serializer-source.cxx
index 6e82bd0..540d742 100644
--- a/xsde/cxx/hybrid/serializer-source.cxx
+++ b/xsde/cxx/hybrid/serializer-source.cxx
@@ -783,12 +783,35 @@ namespace CXX
<< esname (e) << " ()"
<< "{";
+ if (polymorphic (t))
+ {
+ if (stl)
+ {
+ os << "const ::std::string& dt = " << access << iter <<
+ "->_dynamic_type ();"
+ << "if (dt != " << esskel (t) << "::_static_type ())" << endl
+ << "this->_context ().type_id (dt.c_str ());"
+ << endl;
+ }
+ else
+ {
+ os << "const char* dt = " << access << iter <<
+ "->_dynamic_type ();"
+ << "if (strcmp (dt, " << esskel (t) <<
+ "::_static_type ()) != 0)" << endl
+ << "this->_context ().type_id (dt);"
+ << endl;
+ }
+ }
+
if (ret != L"void")
{
os << "return ";
type_pass_.dispatch (t);
os << "*" << access << iter << "++;";
}
+ else
+ os << access << iter << "++;";
os << "}";
}
@@ -807,6 +830,27 @@ namespace CXX
<< esname (e) << " ()"
<< "{";
+ if (polymorphic (t))
+ {
+ if (stl)
+ {
+ os << "const ::std::string& dt = " << access << ename (e) <<
+ " ()._dynamic_type ();"
+ << "if (dt != " << esskel (t) << "::_static_type ())" << endl
+ << "this->_context ().type_id (dt.c_str ());"
+ << endl;
+ }
+ else
+ {
+ os << "const char* dt = " << access << ename (e) <<
+ " ()._dynamic_type ();"
+ << "if (strcmp (dt, " << esskel (t) <<
+ "::_static_type ()) != 0)" << endl
+ << "this->_context ().type_id (dt);"
+ << endl;
+ }
+ }
+
if (ret != L"void")
{
os << "return ";
@@ -870,11 +914,59 @@ namespace CXX
//
//
+ struct PreOverride: Traversal::Complex, Context
+ {
+ PreOverride (Context& c)
+ : Context (c), scope_ (0)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ Boolean clear (false);
+
+ if (scope_ == 0)
+ {
+ scope_ = &c;
+ clear = true;
+ }
+
+ if (c.inherits_p ())
+ {
+ SemanticGraph::Type& b (c.inherits ().base ());
+
+ if (polymorphic (b))
+ {
+ if (tiein)
+ dispatch (b);
+
+ String const& scope (esimpl_custom (*scope_));
+
+ os << "void " << scope << "::" << endl
+ << "pre (" << sarg_type (b) << " x)"
+ << "{"
+ << "this->pre (static_cast< " << sarg_type (c) << " > (x));"
+ << "}";
+ }
+ }
+
+ if (clear)
+ scope_ = 0;
+ }
+
+ private:
+ SemanticGraph::Complex* scope_;
+ };
+
+ //
+ //
struct Complex: Traversal::Complex, Context
{
Complex (Context& c)
: Context (c),
type_pass_ (c),
+ pre_override_ (c),
// Initializers.
//
@@ -961,6 +1053,9 @@ namespace CXX
// pre
//
+ if (polymorphic (c))
+ pre_override_.dispatch (c);
+
String const& arg (sarg_type (c));
os << "void " << name << "::" << endl
@@ -1136,6 +1231,7 @@ namespace CXX
private:
TypePass type_pass_;
+ PreOverride pre_override_;
// Initializers.
//
@@ -1159,6 +1255,10 @@ namespace CXX
Void
generate_serializer_source (Context& ctx)
{
+ if (ctx.poly_code && !ctx.stl)
+ ctx.os << "#include <string.h>" << endl
+ << endl;
+
Traversal::Schema schema;
Traversal::Sources sources;
diff --git a/xsde/cxx/hybrid/tree-header.cxx b/xsde/cxx/hybrid/tree-header.cxx
index c2e8bf4..3003e4c 100644
--- a/xsde/cxx/hybrid/tree-header.cxx
+++ b/xsde/cxx/hybrid/tree-header.cxx
@@ -32,6 +32,9 @@ namespace CXX
//
if (name)
{
+ Boolean cd (lc.count ("cd-name"));
+ Boolean poly (polymorphic (l));
+
os << "// " << comment (l.name ()) << " (variable-length)" << endl
<< "//" << endl;
@@ -50,17 +53,23 @@ namespace CXX
os << "public:" << endl
<< name << " ();";
+ // d-tor
+ //
+ if (poly)
+ os << "virtual ~" << name << " ();";
+
+ os << endl;
+
// Custom data.
//
- if (lc.count ("cd-name"))
+ if (cd)
{
String const& name (ecd_name (l));
String const& sequence (ecd_sequence (l));
String const& iterator (ecd_iterator (l));
String const& const_iterator (ecd_const_iterator (l));
- os << endl
- << "// Custom data." << endl
+ os << "// Custom data." << endl
<< "//" << endl;
// sequence & iterators
@@ -84,9 +93,28 @@ namespace CXX
os << sequence << "&" << endl
<< name << " ();"
<< endl;
+ }
+
+ if (poly && typeinfo)
+ {
+ os << "// Type information." << endl
+ << "//" << endl;
+ os << "static const " <<
+ (stl ? "::std::string&" : "char*") << endl
+ << "_static_type ();"
+ << endl;
+
+ os << "virtual const " <<
+ (stl ? "::std::string&" : "char*") << endl
+ << "_dynamic_type () const;"
+ << endl;
+ }
+
+ if (cd)
+ {
os << "private:" << endl
- << sequence << " " << ecd_member (l) << ";";
+ << ecd_sequence (l) << " " << ecd_member (l) << ";";
}
os << "};";
@@ -128,15 +156,18 @@ namespace CXX
//
if (name)
{
+ Boolean fl (fixed_length (u));
+ Boolean poly (polymorphic (u));
Boolean cd (uc.count ("cd-name"));
- os << "// " << comment (u.name ()) << " (variable-length)" << endl
+ os << "// " << comment (u.name ()) << " (" <<
+ (fl ? "fixed-length" : "variable-length") << ")" << endl
<< "//" << endl;
os << "class " << name
<< "{";
- if (!fixed_length (u))
+ if (!fl)
os << "private:" << endl
<< name << " (const " << name << "&);"
<< name << "& operator= (const " << name << "&);"
@@ -148,13 +179,18 @@ namespace CXX
//
os << name << " ();";
+ // d-tor
+ //
+ if (!stl || poly)
+ os << (poly ? "virtual " : "") << "~" << name << " ();";
+
+ os << endl;
+
String const& value (uc.get<String> ("value"));
String const& member (uc.get<String> ("value-member"));
if (stl)
{
- os << endl;
-
// const std::string&
// name () const
//
@@ -178,11 +214,6 @@ namespace CXX
}
else
{
- // d-tor
- //
- os << "~" << name << " ();"
- << endl;
-
// const char*
// name () const
//
@@ -250,6 +281,22 @@ namespace CXX
<< endl;
}
+ if (poly && typeinfo)
+ {
+ os << "// Type information." << endl
+ << "//" << endl;
+
+ os << "static const " <<
+ (stl ? "::std::string&" : "char*") << endl
+ << "_static_type ();"
+ << endl;
+
+ os << "virtual const " <<
+ (stl ? "::std::string&" : "char*") << endl
+ << "_dynamic_type () const;"
+ << endl;
+ }
+
if (stl)
{
os << "private:" << endl
@@ -2337,6 +2384,7 @@ namespace CXX
if (name)
{
Boolean fl (fixed_length (c));
+ Boolean poly (polymorphic (c));
Boolean restriction (restriction_p (c));
Boolean cd (cc.count ("cd-name"));
@@ -2361,8 +2409,8 @@ namespace CXX
// d-tor
//
- if (!restriction)
- os << "~" << name << " ();";
+ if (!restriction || poly)
+ os << (poly ? "virtual " : "") << "~" << name << " ();";
// copy c-tor & operator=
//
@@ -2421,6 +2469,22 @@ namespace CXX
<< endl;
}
+ if (poly && typeinfo)
+ {
+ os << "// Type information." << endl
+ << "//" << endl;
+
+ os << "static const " <<
+ (stl ? "::std::string&" : "char*") << endl
+ << "_static_type ();"
+ << endl;
+
+ os << "virtual const " <<
+ (stl ? "::std::string&" : "char*") << endl
+ << "_dynamic_type () const;"
+ << endl;
+ }
+
if (!restriction || cd)
os << "private:" << endl;
diff --git a/xsde/cxx/hybrid/tree-inline.cxx b/xsde/cxx/hybrid/tree-inline.cxx
index b1c60e6..7cb4b2c 100644
--- a/xsde/cxx/hybrid/tree-inline.cxx
+++ b/xsde/cxx/hybrid/tree-inline.cxx
@@ -150,15 +150,6 @@ namespace CXX
}
else
{
- // d-tor
- //
- os << inl
- << name << "::" << endl
- << "~" << name << " ()"
- << "{"
- << "delete[] this->" << member << ";"
- << "}";
-
// const char*
// name () const
//
diff --git a/xsde/cxx/hybrid/tree-name-processor.cxx b/xsde/cxx/hybrid/tree-name-processor.cxx
index a3a1dd3..9308598 100644
--- a/xsde/cxx/hybrid/tree-name-processor.cxx
+++ b/xsde/cxx/hybrid/tree-name-processor.cxx
@@ -2053,8 +2053,9 @@ namespace CXX
Void
process_impl (CLI::Options const& ops,
- SemanticGraph::Schema& tu,
- SemanticGraph::Path const& file)
+ SemanticGraph::Schema& tu,
+ SemanticGraph::Path const& file,
+ Boolean deep)
{
Context ctx (ops, tu, file);
@@ -2120,6 +2121,9 @@ namespace CXX
schema.dispatch (tu);
}
+ if (!deep)
+ return;
+
// Pass three - assign names inside complex types. Here we don't
// need to go into included/imported schemas.
//
@@ -2178,9 +2182,10 @@ namespace CXX
Void TreeNameProcessor::
process (CLI::Options const& ops,
SemanticGraph::Schema& tu,
- SemanticGraph::Path const& file)
+ SemanticGraph::Path const& file,
+ Boolean deep)
{
- process_impl (ops, tu, file);
+ process_impl (ops, tu, file, deep);
}
}
}
diff --git a/xsde/cxx/hybrid/tree-name-processor.hxx b/xsde/cxx/hybrid/tree-name-processor.hxx
index 4d884bc..17becee 100644
--- a/xsde/cxx/hybrid/tree-name-processor.hxx
+++ b/xsde/cxx/hybrid/tree-name-processor.hxx
@@ -24,7 +24,8 @@ namespace CXX
Void
process (CLI::Options const& options,
XSDFrontend::SemanticGraph::Schema&,
- XSDFrontend::SemanticGraph::Path const& file);
+ XSDFrontend::SemanticGraph::Path const& file,
+ Boolean deep);
};
}
}
diff --git a/xsde/cxx/hybrid/tree-size-processor.cxx b/xsde/cxx/hybrid/tree-size-processor.cxx
index a3b2231..33d829a 100644
--- a/xsde/cxx/hybrid/tree-size-processor.cxx
+++ b/xsde/cxx/hybrid/tree-size-processor.cxx
@@ -242,11 +242,15 @@ namespace CXX
Type (Boolean& valid,
TypeSet& custom_data,
CustomTypeMap& custom_type_map,
- Boolean stl_)
+ TypeSet& poly_types,
+ Boolean stl_,
+ Boolean poly_)
: valid_ (valid),
custom_data_ (custom_data),
custom_type_map_ (custom_type_map),
- stl (stl_)
+ poly_types_ (poly_types),
+ stl (stl_),
+ poly (poly_)
{
}
@@ -364,9 +368,40 @@ namespace CXX
Void
set (SemanticGraph::Type& t, Boolean v)
{
+ using SemanticGraph::Complex;
+
+ String const& name (t.name ());
+
+ // Check if this type is polymorphic.
+ //
+ if (poly)
+ {
+ SemanticGraph::Context& ctx (t.context ());
+
+ if (!ctx.count ("polymorphic"))
+ {
+ // If our base is polymorphic then we are as well.
+ //
+ Boolean pb (false);
+ if (Complex* c = dynamic_cast<Complex*> (&t))
+ {
+ pb = c->inherits_p () &&
+ c->inherits ().base ().context ().count ("polymorphic");
+ }
+
+ if (pb || poly_types_.find (name) != poly_types_.end ())
+ {
+ ctx.set ("polymorphic", true);
+ v = false;
+ }
+ }
+ else
+ v = false;
+ }
+
// Check if this is a custom type.
//
- CustomTypeMap::Iterator i = custom_type_map_.find (t.name ());
+ CustomTypeMap::Iterator i = custom_type_map_.find (name);
if (i != custom_type_map_.end ())
{
@@ -390,7 +425,9 @@ namespace CXX
Boolean& valid_;
TypeSet& custom_data_;
CustomTypeMap& custom_type_map_;
+ TypeSet& poly_types_;
Boolean stl;
+ Boolean poly;
typedef Containers::Vector<SemanticGraph::Complex*> Path;
Path path_;
@@ -453,8 +490,8 @@ namespace CXX
Traversal::Fundamental::Entities
{
- FundType (Boolean stl_)
- : stl (stl_)
+ FundType (Boolean stl_, TypeSet& poly_types)
+ : stl (stl_), poly_types_ (poly_types)
{
}
@@ -463,7 +500,18 @@ namespace CXX
virtual Void
traverse (SemanticGraph::AnyType& t)
{
- set (t, true);
+ /*
+ @@ disabled
+ // Check if this type is marked polymorphic.
+ //
+ if (poly_types_.find (t.name ()) != poly_types_.end ())
+ {
+ t.context ().set ("polymorphic", true);
+ set (t, false);
+ }
+ else
+ */
+ set (t, true);
}
virtual Void
@@ -755,6 +803,130 @@ namespace CXX
private:
Boolean stl;
+ TypeSet& poly_types_;
+ };
+
+ struct GlobalElement: Traversal::Element
+ {
+ GlobalElement (TypeSet& poly_types,
+ Boolean& valid,
+ const WarningSet& disabled_warnings)
+ : poly_types_ (poly_types), valid_ (valid), warning_ (true)
+ {
+ if (disabled_warnings.find ("all") != disabled_warnings.end () ||
+ disabled_warnings.find ("H004") != disabled_warnings.end ())
+ warning_ = false;
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ using SemanticGraph::Schema;
+
+ if (!e.substitutes_p ())
+ return;
+
+ // If we are a substitution for some element, then mark
+ // that element's type as polymorphic.
+ //
+ Type& r (e.substitutes ().root ());
+ SemanticGraph::Type& rt (r.type ());
+ SemanticGraph::Context& ctx (rt.context ());
+
+ if (ctx.count ("polymorphic"))
+ return;
+
+ // Only user-defined and anyType can be declared polymorphic.
+ //
+ /*
+ @@ disabled
+ if (rt.is_a<SemanticGraph::Fundamental::Type> () ||
+ rt.is_a<SemanticGraph::AnySimpleType> ())
+ */
+ if (rt.is_a<SemanticGraph::Fundamental::Type> () ||
+ rt.is_a<SemanticGraph::AnySimpleType> () ||
+ rt.is_a<SemanticGraph::AnyType> ())
+ {
+ wcerr << r.file () << ":" << r.line () << ":" << r.column ()
+ << ": error: built-in type '" << rt.name () << "' "
+ << "is expected to be polymorphic" << endl;
+
+ wcerr << e.file () << ":" << e.line () << ":" << e.column ()
+ << ": info: because type '" << rt.name () << "' is "
+ << "used in a substitution group declared here" << endl;
+
+ /*
+ @@ disabled
+ wcerr << r.file () << ":" << r.line () << ":" << r.column ()
+ << ": info: only user-defined types and anyType can "
+ << "be polymorphic in this mapping" << endl;
+ */
+
+ wcerr << r.file () << ":" << r.line () << ":" << r.column ()
+ << ": info: only user-defined types can "
+ << "be polymorphic in this mapping" << endl;
+
+ valid_ = false;
+ return;
+ }
+
+ ctx.set ("polymorphic", true);
+
+ if (!warning_)
+ return;
+
+ Schema& es (dynamic_cast<Schema&> (e.scope ().scope ()));
+ Schema& rts (dynamic_cast<Schema&> (rt.scope ().scope ()));
+
+ // If the root type and this element are in different schemas
+ // and the root type is not explicitly marked as polymorphic,
+ // then issue a warning.
+ //
+ if (&es != &rts &&
+ !sources_p (es, rts) &&
+ poly_types_.find (rt.name ()) == poly_types_.end ())
+ {
+ wcerr << rt.file () << ":" << rt.line () << ":" << rt.column ()
+ << ": warning H004: assuming type '" << rt.name () << "' "
+ << "is polymorphic" << endl;
+
+ wcerr << e.file () << ":" << e.line () << ":" << e.column ()
+ << ": info: because type '" << rt.name () << "' is "
+ << "used in a substitution group declared here" << endl;
+
+ wcerr << rt.file () << ":" << rt.line () << ":" << rt.column ()
+ << ": info: use --polymorphic-type to indicate this type "
+ << "is polymorphic when compiling schemas that "
+ << "reference it" << endl;
+ }
+ }
+
+ private:
+ // Return true if root sources s.
+ //
+ Boolean
+ sources_p (SemanticGraph::Schema& root, SemanticGraph::Schema& s)
+ {
+ using SemanticGraph::Schema;
+ using SemanticGraph::Sources;
+
+ for (Schema::UsesIterator i (root.uses_begin ());
+ i != root.uses_end (); ++i)
+ {
+ if (i->is_a<Sources> ())
+ {
+ if (&i->schema () == &s || sources_p (i->schema (), s))
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private:
+ TypeSet& poly_types_;
+ Boolean& valid_;
+ Boolean warning_;
};
// Go into sourced/included/imported schemas while making sure
@@ -764,14 +936,19 @@ namespace CXX
Traversal::Includes,
Traversal::Imports
{
+ Uses (Char const* seen_key)
+ : seen_key_ (seen_key)
+ {
+ }
+
virtual Void
traverse (SemanticGraph::Sources& sr)
{
SemanticGraph::Schema& s (sr.schema ());
- if (!s.context ().count ("cxx-hybrid-size-processor-seen"))
+ if (!s.context ().count (seen_key_))
{
- s.context ().set ("cxx-hybrid-size-processor-seen", true);
+ s.context ().set (seen_key_, true);
Traversal::Sources::traverse (sr);
}
}
@@ -781,9 +958,9 @@ namespace CXX
{
SemanticGraph::Schema& s (i.schema ());
- if (!s.context ().count ("cxx-hybrid-size-processor-seen"))
+ if (!s.context ().count (seen_key_))
{
- s.context ().set ("cxx-hybrid-size-processor-seen", true);
+ s.context ().set (seen_key_, true);
Traversal::Includes::traverse (i);
}
}
@@ -793,21 +970,40 @@ namespace CXX
{
SemanticGraph::Schema& s (i.schema ());
- if (!s.context ().count ("cxx-hybrid-size-processor-seen"))
+ if (!s.context ().count (seen_key_))
{
- s.context ().set ("cxx-hybrid-size-processor-seen", true);
+ s.context ().set (seen_key_, true);
Traversal::Imports::traverse (i);
}
}
+
+ private:
+ Char const* seen_key_;
};
+ Char const* pass_one_key = "cxx-hybrid-size-processor-seen-one";
+ Char const* pass_two_key = "cxx-hybrid-size-processor-seen-two";
+
Boolean
process_impl (CLI::Options const& ops,
SemanticGraph::Schema& tu,
- SemanticGraph::Path const&)
+ SemanticGraph::Path const&,
+ const WarningSet& disabled_warnings)
{
Boolean valid (true);
Boolean stl (!ops.value<CLI::no_stl> ());
+ Boolean poly (ops.value<CLI::generate_polymorphic> ());
+
+ // Prepare a set of polymorphic types.
+ //
+
+ TypeSet poly_types;
+ if (poly)
+ {
+ poly_types.insert (
+ ops.value<CLI::polymorphic_type> ().begin (),
+ ops.value<CLI::polymorphic_type> ().end ());
+ }
// Root schema in the file-per-type mode is just a bunch
// of includes without a namespace.
@@ -824,7 +1020,7 @@ namespace CXX
Traversal::Names schema_names;
Traversal::Namespace ns;
Traversal::Names ns_names;
- FundType fund_type (stl);
+ FundType fund_type (stl, poly_types);
schema >> schema_names >> ns >> ns_names >> fund_type;
@@ -832,7 +1028,7 @@ namespace CXX
}
else
{
- // Pass one - assign sizes to fundamental types.
+ // First assign sizes to fundamental types.
//
{
Traversal::Schema schema;
@@ -844,7 +1040,7 @@ namespace CXX
Traversal::Names xs_schema_names;
Traversal::Namespace ns;
Traversal::Names ns_names;
- FundType fund_type (stl);
+ FundType fund_type (stl, poly_types);
xs_schema >> xs_schema_names >> ns >> ns_names >> fund_type;
@@ -855,7 +1051,7 @@ namespace CXX
// processed which may happen in the file-per-type compilation
// mode.
//
- if (!tu.context ().count ("cxx-hybrid-size-processor-seen"))
+ if (!tu.context ().count (pass_two_key))
{
// Prepare a set of types with custom data. Here we are
// only interested in detecting global types. If a type
@@ -877,8 +1073,7 @@ namespace CXX
}
}
- // Prepare a map of types custom types that specify type
- // size.
+ // Prepare a map of custom types that specify type length.
//
CustomTypeMap custom_type_map;
@@ -949,23 +1144,53 @@ namespace CXX
}
}
+ // Pass one - check substitution groups.
+ //
+ if (valid && poly)
+ {
+ Traversal::Schema schema;
+ Uses uses (pass_one_key);
+
+ schema >> uses >> schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+ GlobalElement element (poly_types, valid, disabled_warnings);
+
+ schema >> schema_names >> ns >> ns_names >> element;
+
+ // Some twisted schemas do recusive self-inclusion.
+ //
+ tu.context ().set (pass_one_key, true);
+
+ schema.dispatch (tu);
+ }
+
+ // Pass two - process types.
+ //
if (valid)
{
Traversal::Schema schema;
- Uses uses;
+ Uses uses (pass_two_key);
schema >> uses >> schema;
Traversal::Names schema_names;
Traversal::Namespace ns;
Traversal::Names ns_names;
- Type type (valid, custom_data_types, custom_type_map, stl);
+ Type type (valid,
+ custom_data_types,
+ custom_type_map,
+ poly_types,
+ stl,
+ poly);
schema >> schema_names >> ns >> ns_names >> type;
// Some twisted schemas do recusive self-inclusion.
//
- tu.context ().set ("cxx-hybrid-size-processor-seen", true);
+ tu.context ().set (pass_two_key, true);
schema.dispatch (tu);
}
@@ -979,9 +1204,10 @@ namespace CXX
Boolean TreeSizeProcessor::
process (CLI::Options const& ops,
SemanticGraph::Schema& tu,
- SemanticGraph::Path const& file)
+ SemanticGraph::Path const& file,
+ const WarningSet& disabled_warnings)
{
- return process_impl (ops, tu, file);
+ return process_impl (ops, tu, file, disabled_warnings);
}
}
}
diff --git a/xsde/cxx/hybrid/tree-size-processor.hxx b/xsde/cxx/hybrid/tree-size-processor.hxx
index d9257a1..d82364f 100644
--- a/xsde/cxx/hybrid/tree-size-processor.hxx
+++ b/xsde/cxx/hybrid/tree-size-processor.hxx
@@ -12,6 +12,8 @@
#include <cxx/hybrid/cli.hxx>
+#include <xsde.hxx>
+
namespace CXX
{
namespace Hybrid
@@ -24,7 +26,8 @@ namespace CXX
Boolean
process (CLI::Options const& options,
XSDFrontend::SemanticGraph::Schema&,
- XSDFrontend::SemanticGraph::Path const& file);
+ XSDFrontend::SemanticGraph::Path const& file,
+ const WarningSet& disabled_warnings);
};
}
}
diff --git a/xsde/cxx/hybrid/tree-source.cxx b/xsde/cxx/hybrid/tree-source.cxx
index 6de3e35..2723046 100644
--- a/xsde/cxx/hybrid/tree-source.cxx
+++ b/xsde/cxx/hybrid/tree-source.cxx
@@ -14,6 +14,161 @@ namespace CXX
{
namespace
{
+ struct List : Traversal::List, Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String const& name (ename_custom (l));
+
+ // We may not need to generate the class if this type is
+ // being customized.
+ //
+ if (!name)
+ return;
+
+ if (polymorphic (l))
+ {
+ os << "// " << comment (l.name ()) << endl
+ << "//" << endl
+ << endl;
+
+ // d-tor
+ //
+ os << name << "::" << endl
+ << "~" << name << " ()"
+ << "{"
+ << "}";
+
+ if (typeinfo)
+ {
+ String id (l.name ());
+
+ if (String ns = xml_ns_name (l))
+ {
+ id += L' ';
+ id += ns;
+ }
+
+ if (stl)
+ {
+ os << "static const ::std::string _xsde_" << name <<
+ "_static_type_ = " << strlit (id) << ";"
+ << endl;
+
+ os << "const ::std::string& " << name << "::" << endl
+ << "_static_type ()"
+ << "{"
+ << "return _xsde_" << name << "_static_type_;"
+ << "}";
+ }
+ else
+ {
+ os << "const char* " << name << "::" << endl
+ << "_static_type ()"
+ << "{"
+ << "return " << strlit (id) << ";"
+ << "}";
+ }
+
+ os << "const " << (stl ? "::std::string& " : "char* ") <<
+ name << "::" << endl
+ << "_dynamic_type () const"
+ << "{"
+ << "return _static_type ();"
+ << "}";
+ }
+ }
+ }
+ };
+
+ //
+ //
+ struct Union : Traversal::Union, Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ String const& name (ename_custom (u));
+
+ // We may not need to generate the class if this type is
+ // being customized.
+ //
+ if (!name)
+ return;
+
+ Boolean poly (polymorphic (u));
+
+ if (!stl || poly)
+ {
+ os << "// " << comment (u.name ()) << endl
+ << "//" << endl
+ << endl;
+
+ // d-tor
+ //
+ os << name << "::" << endl
+ << "~" << name << " ()"
+ << "{";
+
+ if (!stl)
+ os << "delete[] this->" <<
+ u.context ().get<String> ("value-member") << ";";
+
+ os << "}";
+
+ if (poly && typeinfo)
+ {
+ String id (u.name ());
+
+ if (String ns = xml_ns_name (u))
+ {
+ id += L' ';
+ id += ns;
+ }
+
+ if (stl)
+ {
+ os << "static const ::std::string _xsde_" << name <<
+ "_static_type_ = " << strlit (id) << ";"
+ << endl;
+
+ os << "const ::std::string& " << name << "::" << endl
+ << "_static_type ()"
+ << "{"
+ << "return _xsde_" << name << "_static_type_;"
+ << "}";
+ }
+ else
+ {
+ os << "const char* " << name << "::" << endl
+ << "_static_type ()"
+ << "{"
+ << "return " << strlit (id) << ";"
+ << "}";
+ }
+
+ os << "const " << (stl ? "::std::string& " : "char* ") <<
+ name << "::" << endl
+ << "_dynamic_type () const"
+ << "{"
+ << "return _static_type ();"
+ << "}";
+ }
+ }
+ }
+ };
+
struct ChoiceParticle: Traversal::Element,
Traversal::Compositor,
Context
@@ -1464,6 +1619,7 @@ namespace CXX
if (!name)
return;
+ Boolean poly (polymorphic (c));
Boolean restriction (restriction_p (c));
os << "// " << comment (c.name ()) << endl
@@ -1486,22 +1642,27 @@ namespace CXX
os << "}";
-
- if (!restriction)
+ // d-tor ()
+ //
+ if (!restriction || poly)
{
- // d-tor ()
- //
os << name << "::" << endl
<< "~" << name << " ()"
<< "{";
- Complex::names (c, attribute_names_dtor_);
+ if (!restriction)
+ {
+ Complex::names (c, attribute_names_dtor_);
- if (c.contains_compositor_p ())
- Complex::contains_compositor (c, contains_compositor_dtor_);
+ if (c.contains_compositor_p ())
+ Complex::contains_compositor (c, contains_compositor_dtor_);
+ }
os << "}";
+ }
+ if (!restriction)
+ {
if (fixed_length (c))
{
// copy c-tor
@@ -1554,7 +1715,49 @@ namespace CXX
//
if (c.contains_compositor_p ())
Complex::contains_compositor (c, contains_compositor_func_);
+ }
+
+ if (poly && typeinfo)
+ {
+ String id (c.name ());
+
+ if (String ns = xml_ns_name (c))
+ {
+ id += L' ';
+ id += ns;
+ }
+
+ if (stl)
+ {
+ os << "static const ::std::string _xsde_" << name <<
+ "_static_type_ = " << strlit (id) << ";"
+ << endl;
+ os << "const ::std::string& " << name << "::" << endl
+ << "_static_type ()"
+ << "{"
+ << "return _xsde_" << name << "_static_type_;"
+ << "}";
+ }
+ else
+ {
+ os << "const char* " << name << "::" << endl
+ << "_static_type ()"
+ << "{"
+ << "return " << strlit (id) << ";"
+ << "}";
+ }
+
+ os << "const " << (stl ? "::std::string& " : "char* ") <<
+ name << "::" << endl
+ << "_dynamic_type () const"
+ << "{"
+ << "return _static_type ();"
+ << "}";
+ }
+
+ if (!restriction)
+ {
// Nested c-tors, etc.
//
if (c.contains_compositor_p ())
@@ -1661,16 +1864,16 @@ namespace CXX
Namespace ns (ctx);
- //Union union_ (ctx);
+ List list (ctx);
+ Union union_ (ctx);
Complex complex (ctx);
- //Enumeration enumeration (ctx);
schema >> sources >> schema;
schema >> names_ns >> ns >> names;
- //names >> union_;
+ names >> list;
+ names >> union_;
names >> complex;
- //names >> enumeration;
schema.dispatch (ctx.schema_root);
}
diff --git a/xsde/cxx/hybrid/validator.cxx b/xsde/cxx/hybrid/validator.cxx
index 65dd3e2..c799563 100644
--- a/xsde/cxx/hybrid/validator.cxx
+++ b/xsde/cxx/hybrid/validator.cxx
@@ -20,6 +20,9 @@ namespace CXX
{
namespace
{
+ // H004 is used by tree-size-processor.
+ //
+
class ValidationContext: public Context
{
public:
@@ -34,6 +37,8 @@ namespace CXX
subst_group_warning_issued (subst_group_warning_issued_),
subst_group_warning_issued_ (false)
{
+ if (disabled_warnings_.find ("all") != disabled_warnings_.end ())
+ disabled_warnings_all_ = true;
}
public:
@@ -147,7 +152,6 @@ namespace CXX
}
}
- /*
virtual Void
traverse (SemanticGraph::Element& e)
{
@@ -165,11 +169,10 @@ namespace CXX
<< "--generate-polymorphic was not specified" << endl;
os << e.file () << ":" << e.line () << ":" << e.column ()
- << ": info: generated code may not be able to serialize "
+ << ": info: generated code may not be able to handle "
<< "some conforming instances" << endl;
}
}
- */
// Return true if root sources s.
//
diff --git a/xsde/cxx/parser/generator.cxx b/xsde/cxx/parser/generator.cxx
index e552c92..aed6e53 100644
--- a/xsde/cxx/parser/generator.cxx
+++ b/xsde/cxx/parser/generator.cxx
@@ -526,6 +526,14 @@ namespace CXX
return spec;
}
+ Void Parser::Generator::
+ process_names (CLI::Options const& ops,
+ XSDFrontend::SemanticGraph::Schema& schema,
+ XSDFrontend::SemanticGraph::Path const& file)
+ {
+ NameProcessor proc;
+ proc.process (ops, schema, file, false);
+ }
namespace
{
@@ -646,7 +654,7 @@ namespace CXX
//
{
NameProcessor proc;
- proc.process (ops, schema, file_path);
+ proc.process (ops, schema, file_path, true);
}
Boolean validation (!ops.value<CLI::suppress_validation> ());
diff --git a/xsde/cxx/parser/generator.hxx b/xsde/cxx/parser/generator.hxx
index a261eca..305d8b1 100644
--- a/xsde/cxx/parser/generator.hxx
+++ b/xsde/cxx/parser/generator.hxx
@@ -35,17 +35,26 @@ namespace CXX
static CLI::OptionsSpec
options_spec ();
+ // Assign names to global declarations.
+ //
+ static Void
+ process_names (CLI::Options const&,
+ XSDFrontend::SemanticGraph::Schema&,
+ XSDFrontend::SemanticGraph::Path const&);
+
+ // Generate code.
+ //
struct Failed {};
static UnsignedLong
- generate (CLI::Options const& options,
+ generate (CLI::Options const&,
XSDFrontend::SemanticGraph::Schema&,
- XSDFrontend::SemanticGraph::Path const& file,
+ XSDFrontend::SemanticGraph::Path const&,
TypeMap::Namespaces& type_map,
Boolean gen_driver,
const WarningSet& disabled_warnings,
- FileList& file_list,
- AutoUnlinks& unlinks);
+ FileList&,
+ AutoUnlinks&);
private:
Generator ();
diff --git a/xsde/cxx/parser/name-processor.cxx b/xsde/cxx/parser/name-processor.cxx
index bc0e7a5..9c945b3 100644
--- a/xsde/cxx/parser/name-processor.cxx
+++ b/xsde/cxx/parser/name-processor.cxx
@@ -1224,7 +1224,8 @@ namespace CXX
Void
process_impl (CLI::Options const& ops,
SemanticGraph::Schema& tu,
- SemanticGraph::Path const& file)
+ SemanticGraph::Path const& file,
+ Boolean deep)
{
Context ctx (ops, tu, file);
@@ -1290,6 +1291,9 @@ namespace CXX
schema.dispatch (tu);
}
+ if (!deep)
+ return;
+
// Pass three - assign names inside complex types. Here we don't
// need to go into included/imported schemas.
//
@@ -1318,9 +1322,10 @@ namespace CXX
Void NameProcessor::
process (CLI::Options const& ops,
SemanticGraph::Schema& tu,
- SemanticGraph::Path const& file)
+ SemanticGraph::Path const& file,
+ Boolean deep)
{
- process_impl (ops, tu, file);
+ process_impl (ops, tu, file, deep);
}
}
}
diff --git a/xsde/cxx/parser/name-processor.hxx b/xsde/cxx/parser/name-processor.hxx
index 8d55f30..6a7af9f 100644
--- a/xsde/cxx/parser/name-processor.hxx
+++ b/xsde/cxx/parser/name-processor.hxx
@@ -22,9 +22,10 @@ namespace CXX
{
public:
Void
- process (CLI::Options const& options,
+ process (CLI::Options const&,
XSDFrontend::SemanticGraph::Schema&,
- XSDFrontend::SemanticGraph::Path const& file);
+ XSDFrontend::SemanticGraph::Path const&,
+ Boolean deep);
};
}
}
diff --git a/xsde/cxx/parser/validator.cxx b/xsde/cxx/parser/validator.cxx
index 570a0bf..842fc4e 100644
--- a/xsde/cxx/parser/validator.cxx
+++ b/xsde/cxx/parser/validator.cxx
@@ -34,6 +34,8 @@ namespace CXX
subst_group_warning_issued (subst_group_warning_issued_),
subst_group_warning_issued_ (false)
{
+ if (disabled_warnings_.find ("all") != disabled_warnings_.end ())
+ disabled_warnings_all_ = true;
}
public:
diff --git a/xsde/cxx/serializer/generator.cxx b/xsde/cxx/serializer/generator.cxx
index c27ef09..5e72d86 100644
--- a/xsde/cxx/serializer/generator.cxx
+++ b/xsde/cxx/serializer/generator.cxx
@@ -519,6 +519,14 @@ namespace CXX
return spec;
}
+ Void Serializer::Generator::
+ process_names (CLI::Options const& ops,
+ XSDFrontend::SemanticGraph::Schema& schema,
+ XSDFrontend::SemanticGraph::Path const& file)
+ {
+ NameProcessor proc;
+ proc.process (ops, schema, file, false);
+ }
namespace
{
@@ -637,7 +645,7 @@ namespace CXX
//
{
NameProcessor proc;
- proc.process (ops, schema, file_path);
+ proc.process (ops, schema, file_path, true);
}
//
diff --git a/xsde/cxx/serializer/generator.hxx b/xsde/cxx/serializer/generator.hxx
index a5b8558..eaa378d 100644
--- a/xsde/cxx/serializer/generator.hxx
+++ b/xsde/cxx/serializer/generator.hxx
@@ -35,17 +35,26 @@ namespace CXX
static CLI::OptionsSpec
options_spec ();
+ // Assign names to global declarations.
+ //
+ static Void
+ process_names (CLI::Options const&,
+ XSDFrontend::SemanticGraph::Schema&,
+ XSDFrontend::SemanticGraph::Path const&);
+
+ // Generate code.
+ //
struct Failed {};
static UnsignedLong
- generate (CLI::Options const& options,
+ generate (CLI::Options const&,
XSDFrontend::SemanticGraph::Schema&,
- XSDFrontend::SemanticGraph::Path const& file,
+ XSDFrontend::SemanticGraph::Path const&,
TypeMap::Namespaces& type_map,
Boolean gen_driver,
const WarningSet& disabled_warnings,
- FileList& file_list,
- AutoUnlinks& unlinks);
+ FileList&,
+ AutoUnlinks&);
private:
Generator ();
diff --git a/xsde/cxx/serializer/name-processor.cxx b/xsde/cxx/serializer/name-processor.cxx
index d68b823..140ad06 100644
--- a/xsde/cxx/serializer/name-processor.cxx
+++ b/xsde/cxx/serializer/name-processor.cxx
@@ -1307,7 +1307,8 @@ namespace CXX
Void
process_impl (CLI::Options const& ops,
SemanticGraph::Schema& tu,
- SemanticGraph::Path const& file)
+ SemanticGraph::Path const& file,
+ Boolean deep)
{
Context ctx (ops, tu, file);
@@ -1373,6 +1374,9 @@ namespace CXX
schema.dispatch (tu);
}
+ if (!deep)
+ return;
+
// Pass three - assign names inside complex types. Here we don't
// need to go into included/imported schemas.
//
@@ -1401,9 +1405,10 @@ namespace CXX
Void NameProcessor::
process (CLI::Options const& ops,
SemanticGraph::Schema& tu,
- SemanticGraph::Path const& file)
+ SemanticGraph::Path const& file,
+ Boolean deep)
{
- process_impl (ops, tu, file);
+ process_impl (ops, tu, file, deep);
}
}
}
diff --git a/xsde/cxx/serializer/name-processor.hxx b/xsde/cxx/serializer/name-processor.hxx
index bf69ba6..f7cd63b 100644
--- a/xsde/cxx/serializer/name-processor.hxx
+++ b/xsde/cxx/serializer/name-processor.hxx
@@ -22,9 +22,10 @@ namespace CXX
{
public:
Void
- process (CLI::Options const& options,
+ process (CLI::Options const&,
XSDFrontend::SemanticGraph::Schema&,
- XSDFrontend::SemanticGraph::Path const& file);
+ XSDFrontend::SemanticGraph::Path const&,
+ Boolean deep);
};
}
}
diff --git a/xsde/cxx/serializer/validator.cxx b/xsde/cxx/serializer/validator.cxx
index d9cc724..189ccac 100644
--- a/xsde/cxx/serializer/validator.cxx
+++ b/xsde/cxx/serializer/validator.cxx
@@ -34,6 +34,8 @@ namespace CXX
subst_group_warning_issued (subst_group_warning_issued_),
subst_group_warning_issued_ (false)
{
+ if (disabled_warnings_.find ("all") != disabled_warnings_.end ())
+ disabled_warnings_all_ = true;
}
public: