aboutsummaryrefslogtreecommitdiff
path: root/xsde/cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2009-10-27 10:10:46 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2009-10-27 10:10:46 +0200
commit3dcdc88b14aec626c87f8f480a1d07781a27c069 (patch)
tree3d64d4701e07441545ffaf3afe0050c4c9e35b41 /xsde/cxx
parent8161144e7f3182d9dc66a811b4618a81232d4af3 (diff)
Implement schema enumeration to C++ enum mapping in C++/Hybrid
Diffstat (limited to 'xsde/cxx')
-rw-r--r--xsde/cxx/hybrid/cli.hxx2
-rw-r--r--xsde/cxx/hybrid/default-value.cxx47
-rw-r--r--xsde/cxx/hybrid/default-value.hxx8
-rw-r--r--xsde/cxx/hybrid/elements.cxx29
-rw-r--r--xsde/cxx/hybrid/elements.hxx128
-rw-r--r--xsde/cxx/hybrid/extraction-header.cxx43
-rw-r--r--xsde/cxx/hybrid/extraction-source.cxx56
-rw-r--r--xsde/cxx/hybrid/generator.cxx6
-rw-r--r--xsde/cxx/hybrid/insertion-header.cxx43
-rw-r--r--xsde/cxx/hybrid/insertion-source.cxx47
-rw-r--r--xsde/cxx/hybrid/parser-header.cxx219
-rw-r--r--xsde/cxx/hybrid/parser-name-processor.cxx58
-rw-r--r--xsde/cxx/hybrid/parser-source.cxx466
-rw-r--r--xsde/cxx/hybrid/serializer-header.cxx168
-rw-r--r--xsde/cxx/hybrid/serializer-name-processor.cxx55
-rw-r--r--xsde/cxx/hybrid/serializer-source.cxx199
-rw-r--r--xsde/cxx/hybrid/tree-forward.cxx48
-rw-r--r--xsde/cxx/hybrid/tree-header.cxx249
-rw-r--r--xsde/cxx/hybrid/tree-inline.cxx113
-rw-r--r--xsde/cxx/hybrid/tree-name-processor.cxx128
-rw-r--r--xsde/cxx/hybrid/tree-size-processor.cxx51
-rw-r--r--xsde/cxx/hybrid/tree-source.cxx131
22 files changed, 2118 insertions, 176 deletions
diff --git a/xsde/cxx/hybrid/cli.hxx b/xsde/cxx/hybrid/cli.hxx
index 509005a..4e86e41 100644
--- a/xsde/cxx/hybrid/cli.hxx
+++ b/xsde/cxx/hybrid/cli.hxx
@@ -34,6 +34,7 @@ namespace CXX
extern Key suppress_parser_val;
extern Key suppress_serializer_val;
extern Key omit_default_attributes;
+ extern Key suppress_enum;
extern Key generate_detach;
extern Key generate_insertion;
extern Key generate_extraction;
@@ -122,6 +123,7 @@ namespace CXX
suppress_parser_val, Boolean,
suppress_serializer_val, Boolean,
omit_default_attributes, Boolean,
+ suppress_enum, Boolean,
generate_detach, Boolean,
generate_insertion, Cult::Containers::Vector<NarrowString>,
generate_extraction, Cult::Containers::Vector<NarrowString>,
diff --git a/xsde/cxx/hybrid/default-value.cxx b/xsde/cxx/hybrid/default-value.cxx
index e232eae..6abfb05 100644
--- a/xsde/cxx/hybrid/default-value.cxx
+++ b/xsde/cxx/hybrid/default-value.cxx
@@ -578,6 +578,38 @@ namespace CXX
}
Void InitValue::
+ traverse (SemanticGraph::Enumeration& e)
+ {
+ using SemanticGraph::Enumerator;
+ using SemanticGraph::Enumeration;
+
+ // First see if we should delegate this one to the Complex
+ // generator.
+ //
+ Enumeration* base_enum (0);
+
+ if (!enum_ || !enum_mapping (e, &base_enum))
+ {
+ traverse (static_cast<SemanticGraph::Complex&> (e));
+ return;
+ }
+
+ Enumeration& x (base_enum ? *base_enum : e);
+
+ os << member_ << x.context ().get<String> ("value") << "(";
+
+ Enumeration::NamesIteratorPair ip (x.find (value_));
+
+ if (ip.first != ip.second)
+ {
+ Enumerator& er (dynamic_cast<Enumerator&> (ip.first->named ()));
+ os << fq_name (e) << "::" << ename (er);
+ }
+
+ os << ");";
+ }
+
+ Void InitValue::
traverse (SemanticGraph::Type& t)
{
// This is a fall-back case where we handle all other (literal)
@@ -1213,6 +1245,21 @@ namespace CXX
}
Void CompareValue::
+ traverse (SemanticGraph::Enumeration& e)
+ {
+ // First see if we should delegate this one to the Complex
+ // generator.
+ //
+ if (!enum_ || !enum_mapping (e))
+ {
+ traverse (static_cast<SemanticGraph::Complex&> (e));
+ return;
+ }
+
+ os << *lhs_ << " == " << *rhs_;
+ }
+
+ Void CompareValue::
traverse (SemanticGraph::Type&)
{
// This is a fall-back case where we handle all other types.
diff --git a/xsde/cxx/hybrid/default-value.hxx b/xsde/cxx/hybrid/default-value.hxx
index b9f902c..46a6bf0 100644
--- a/xsde/cxx/hybrid/default-value.hxx
+++ b/xsde/cxx/hybrid/default-value.hxx
@@ -163,6 +163,7 @@ namespace CXX
struct InitValue: Traversal::List,
Traversal::Union,
Traversal::Complex,
+ Traversal::Enumeration,
Traversal::Type,
Traversal::AnySimpleType,
@@ -217,6 +218,9 @@ namespace CXX
traverse (SemanticGraph::Complex&);
virtual Void
+ traverse (SemanticGraph::Enumeration&);
+
+ virtual Void
traverse (SemanticGraph::Type& t);
// anySimpleType.
@@ -337,6 +341,7 @@ namespace CXX
struct CompareValue: Traversal::Union,
Traversal::Complex,
+ Traversal::Enumeration,
Traversal::Type,
Context
{
@@ -354,6 +359,9 @@ namespace CXX
traverse (SemanticGraph::Complex&);
virtual Void
+ traverse (SemanticGraph::Enumeration&);
+
+ virtual Void
traverse (SemanticGraph::Type& t);
private:
diff --git a/xsde/cxx/hybrid/elements.cxx b/xsde/cxx/hybrid/elements.cxx
index 6db57ff..eba0880 100644
--- a/xsde/cxx/hybrid/elements.cxx
+++ b/xsde/cxx/hybrid/elements.cxx
@@ -39,6 +39,7 @@ namespace CXX
detach (ops.value<CLI::generate_detach> ()),
mixin (ops.value<CLI::reuse_style_mixin> ()),
tiein (!mixin),
+ enum_ (!ops.value<CLI::suppress_enum> ()),
fwd_expr (fe),
hxx_expr (he),
ixx_expr (ie),
@@ -495,6 +496,34 @@ namespace CXX
return os;
}
+ Boolean Context::
+ enum_mapping (SemanticGraph::Enumeration& e,
+ SemanticGraph::Enumeration** base)
+ {
+ Boolean gen (false);
+ StringBasedType t (gen);
+ t.dispatch (e);
+
+ if (gen)
+ {
+ // The first enumeration in the inheritance hierarchy breaks
+ // inheritance. If its base is polymorphic then generating
+ // the enum mapping will most likely break things.
+ //
+ SemanticGraph::Enumeration* b (0);
+ EnumBasedType t (b);
+ t.dispatch (e);
+
+ SemanticGraph::Enumeration& first (b ? *b : e);
+ gen = !polymorphic (first.inherits ().base ());
+
+ if (gen && base)
+ *base = b;
+ }
+
+ return gen;
+ }
+
// Namespace
//
Namespace::
diff --git a/xsde/cxx/hybrid/elements.hxx b/xsde/cxx/hybrid/elements.hxx
index 5a94dda..77b91a2 100644
--- a/xsde/cxx/hybrid/elements.hxx
+++ b/xsde/cxx/hybrid/elements.hxx
@@ -48,6 +48,7 @@ namespace CXX
typeinfo (c.typeinfo),
mixin (c.mixin),
tiein (c.tiein),
+ enum_ (c.enum_),
fwd_expr (c.fwd_expr),
hxx_expr (c.hxx_expr),
ixx_expr (c.ixx_expr),
@@ -78,6 +79,7 @@ namespace CXX
typeinfo (c.typeinfo),
mixin (c.mixin),
tiein (c.tiein),
+ enum_ (c.enum_),
fwd_expr (c.fwd_expr),
hxx_expr (c.hxx_expr),
ixx_expr (c.ixx_expr),
@@ -572,6 +574,13 @@ namespace CXX
open_ns ();
public:
+ // Determine whether we are generating the enum mapping for this
+ // enumeration. Also optionally return the base enum.
+ //
+ static Boolean
+ enum_mapping (SemanticGraph::Enumeration& e,
+ SemanticGraph::Enumeration** base = 0);
+ public:
typedef
Cult::Containers::Deque<String>
NamespaceStack;
@@ -588,6 +597,7 @@ namespace CXX
Boolean typeinfo;
Boolean mixin;
Boolean tiein;
+ Boolean enum_;
Regex const* fwd_expr;
Regex const* hxx_expr;
@@ -871,6 +881,124 @@ namespace CXX
Boolean& r_;
};
+ // Check whether this is a string-based type (excluding ID, IDFER,
+ // anyURI, and ENTITY).
+ //
+ struct StringBasedType: Traversal::Complex,
+ Traversal::Fundamental::String,
+ Traversal::Fundamental::NormalizedString,
+ Traversal::Fundamental::Token,
+ Traversal::Fundamental::Name,
+ Traversal::Fundamental::NameToken,
+ Traversal::Fundamental::NCName,
+ Traversal::Fundamental::Language
+ {
+ StringBasedType (Boolean& r)
+ : r_ (r)
+ {
+ *this >> inherits_ >> *this;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ inherits (c, inherits_);
+ }
+
+ // Strings.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::String&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NormalizedString&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Token&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameToken&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Name&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NCName&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Language&)
+ {
+ r_ = true;
+ }
+
+ private:
+ Boolean& r_;
+ Traversal::Inherits inherits_;
+ };
+
+
+ // Check whether this is a enumeration-based type.
+ //
+ struct EnumBasedType: Traversal::Complex
+ {
+ EnumBasedType (SemanticGraph::Enumeration*& e)
+ : enum_ (e)
+ {
+ *this >> inherits_;
+
+ inherits_ >> *this;
+ inherits_ >> enum_;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ inherits (c, inherits_);
+ }
+
+ private:
+ struct Enumeration: Traversal::Enumeration
+ {
+ Enumeration (SemanticGraph::Enumeration*& e)
+ : e_ (e)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (e_ == 0)
+ e_ = &e;
+ }
+
+ private:
+ SemanticGraph::Enumeration*& e_;
+ };
+
+
+ private:
+ Enumeration enum_;
+ Traversal::Inherits inherits_;
+ };
+
//
//
diff --git a/xsde/cxx/hybrid/extraction-header.cxx b/xsde/cxx/hybrid/extraction-header.cxx
index dc729f6..e2ed714 100644
--- a/xsde/cxx/hybrid/extraction-header.cxx
+++ b/xsde/cxx/hybrid/extraction-header.cxx
@@ -14,6 +14,47 @@ namespace CXX
{
namespace
{
+ struct Enumeration : Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c, Traversal::Complex& complex)
+ : Context (c), complex_ (complex)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ // First see if we should delegate this one to the Complex
+ // generator.
+ //
+ if (!enum_ || !enum_mapping (e))
+ {
+ complex_.traverse (e);
+ return;
+ }
+
+ String const& name (ename_custom (e));
+
+ // We may not need to generate the class if this type is
+ // being customized.
+ //
+ if (!name)
+ return;
+
+ for (Streams::ConstIterator i (istreams.begin ());
+ i != istreams.end (); ++i)
+ {
+ os << (exceptions ? "void" : "bool") << endl
+ << "operator>> (" << istream (*i) << "&," << endl
+ << name << "&);"
+ << endl;
+ }
+ }
+
+ private:
+ Traversal::Complex& complex_;
+ };
+
struct List : Traversal::List, Context
{
List (Context& c)
@@ -256,6 +297,7 @@ namespace CXX
List list (ctx);
Union union_ (ctx);
Complex complex (ctx);
+ Enumeration enumeration (ctx, complex);
schema >> sources >> schema;
schema >> names_ns >> ns >> names;
@@ -263,6 +305,7 @@ namespace CXX
names >> list;
names >> union_;
names >> complex;
+ names >> enumeration;
schema.dispatch (ctx.schema_root);
}
diff --git a/xsde/cxx/hybrid/extraction-source.cxx b/xsde/cxx/hybrid/extraction-source.cxx
index 5460740..e829760 100644
--- a/xsde/cxx/hybrid/extraction-source.cxx
+++ b/xsde/cxx/hybrid/extraction-source.cxx
@@ -14,6 +14,60 @@ namespace CXX
{
namespace
{
+ struct Enumeration : Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c, Traversal::Complex& complex)
+ : Context (c), complex_ (complex)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ // First see if we should delegate this one to the Complex
+ // generator.
+ //
+ if (!enum_ || !enum_mapping (e))
+ {
+ complex_.traverse (e);
+ return;
+ }
+
+ String const& name (ename_custom (e));
+
+ // We may not need to generate the class if this type is
+ // being customized.
+ //
+ if (!name)
+ return;
+
+ for (Streams::ConstIterator i (istreams.begin ());
+ i != istreams.end (); ++i)
+ {
+ os << (exceptions ? "void" : "bool") << endl
+ << "operator>> (" << istream (*i) << "& s," << endl
+ << name << "& x)"
+ << "{"
+ << "unsigned int i;";
+
+ if (exceptions)
+ os << "s >> i;";
+ else
+ os << "if (!(s >> i))" << endl
+ << "return false;";
+
+ os << "x = static_cast< " << name << "::" <<
+ e.context ().get<String> ("value-type") << " > (i);"
+ << (exceptions ? "" : "return true;")
+ << "}"
+ << endl;
+ }
+ }
+
+ private:
+ Traversal::Complex& complex_;
+ };
+
struct List : Traversal::List, Context
{
List (Context& c)
@@ -1102,6 +1156,7 @@ namespace CXX
List list (ctx);
Union union_ (ctx);
Complex complex (ctx);
+ Enumeration enumeration (ctx, complex);
schema >> sources >> schema;
schema >> names_ns >> ns >> names;
@@ -1109,6 +1164,7 @@ namespace CXX
names >> list;
names >> union_;
names >> complex;
+ names >> enumeration;
schema.dispatch (ctx.schema_root);
}
diff --git a/xsde/cxx/hybrid/generator.cxx b/xsde/cxx/hybrid/generator.cxx
index 78b9142..c7dcb1d 100644
--- a/xsde/cxx/hybrid/generator.cxx
+++ b/xsde/cxx/hybrid/generator.cxx
@@ -122,6 +122,7 @@ namespace CXX
extern Key suppress_parser_val = "suppress-parser-val";
extern Key suppress_serializer_val = "suppress-serializer-val";
extern Key omit_default_attributes = "omit-default-attributes";
+ extern Key suppress_enum = "suppress-enum";
extern Key generate_detach = "generate-detach";
extern Key generate_insertion = "generate-insertion";
extern Key generate_extraction = "generate-extraction";
@@ -257,6 +258,11 @@ namespace CXX
<< " from serialized XML documents."
<< endl;
+ e << "--suppress-enum" << endl
+ << " Suppress the generation of the XML Schema\n"
+ << " enumeration to C++ enum mapping."
+ << endl;
+
e << "--generate-detach" << endl
<< " Generate detach functions for elements and\n"
<< " attributes of variable-length types."
diff --git a/xsde/cxx/hybrid/insertion-header.cxx b/xsde/cxx/hybrid/insertion-header.cxx
index 4898c02..b1a4dbe 100644
--- a/xsde/cxx/hybrid/insertion-header.cxx
+++ b/xsde/cxx/hybrid/insertion-header.cxx
@@ -14,6 +14,47 @@ namespace CXX
{
namespace
{
+ struct Enumeration : Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c, Traversal::Complex& complex)
+ : Context (c), complex_ (complex)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ // First see if we should delegate this one to the Complex
+ // generator.
+ //
+ if (!enum_ || !enum_mapping (e))
+ {
+ complex_.traverse (e);
+ return;
+ }
+
+ String const& name (ename_custom (e));
+
+ // We may not need to generate the class if this type is
+ // being customized.
+ //
+ if (!name)
+ return;
+
+ for (Streams::ConstIterator i (ostreams.begin ());
+ i != ostreams.end (); ++i)
+ {
+ os << (exceptions ? "void" : "bool") << endl
+ << "operator<< (" << ostream (*i) << "&," << endl
+ << "const " << name << "&);"
+ << endl;
+ }
+ }
+
+ private:
+ Traversal::Complex& complex_;
+ };
+
struct List : Traversal::List, Context
{
List (Context& c)
@@ -256,6 +297,7 @@ namespace CXX
List list (ctx);
Union union_ (ctx);
Complex complex (ctx);
+ Enumeration enumeration (ctx, complex);
schema >> sources >> schema;
schema >> names_ns >> ns >> names;
@@ -263,6 +305,7 @@ namespace CXX
names >> list;
names >> union_;
names >> complex;
+ names >> enumeration;
schema.dispatch (ctx.schema_root);
}
diff --git a/xsde/cxx/hybrid/insertion-source.cxx b/xsde/cxx/hybrid/insertion-source.cxx
index 7dc6fcb..7fce9ee 100644
--- a/xsde/cxx/hybrid/insertion-source.cxx
+++ b/xsde/cxx/hybrid/insertion-source.cxx
@@ -14,6 +14,51 @@ namespace CXX
{
namespace
{
+ struct Enumeration : Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c, Traversal::Complex& complex)
+ : Context (c), complex_ (complex)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ // First see if we should delegate this one to the Complex
+ // generator.
+ //
+ if (!enum_ || !enum_mapping (e))
+ {
+ complex_.traverse (e);
+ return;
+ }
+
+ String const& name (ename_custom (e));
+
+ // We may not need to generate the class if this type is
+ // being customized.
+ //
+ if (!name)
+ return;
+
+ for (Streams::ConstIterator i (ostreams.begin ());
+ i != ostreams.end (); ++i)
+ {
+ os << (exceptions ? "void" : "bool") << endl
+ << "operator<< (" << ostream (*i) << "& s," << endl
+ << "const " << name << "& x)"
+ << "{"
+ << "unsigned int i = x;"
+ << (exceptions ? "" : "return ") << "s << i;"
+ << "}"
+ << endl;
+ }
+ }
+
+ private:
+ Traversal::Complex& complex_;
+ };
+
struct List : Traversal::List, Context
{
List (Context& c)
@@ -721,6 +766,7 @@ namespace CXX
List list (ctx);
Union union_ (ctx);
Complex complex (ctx);
+ Enumeration enumeration (ctx, complex);
schema >> sources >> schema;
schema >> names_ns >> ns >> names;
@@ -728,6 +774,7 @@ namespace CXX
names >> list;
names >> union_;
names >> complex;
+ names >> enumeration;
schema.dispatch (ctx.schema_root);
}
diff --git a/xsde/cxx/hybrid/parser-header.cxx b/xsde/cxx/hybrid/parser-header.cxx
index c174df4..d8948d7 100644
--- a/xsde/cxx/hybrid/parser-header.cxx
+++ b/xsde/cxx/hybrid/parser-header.cxx
@@ -14,6 +14,194 @@ namespace CXX
{
namespace
{
+ //
+ //
+ 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;
+ }
+ }
+ }
+ };
+
+ //
+ //
+ struct Enumeration: Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c, Traversal::Complex& complex)
+ : Context (c), complex_ (complex), post_override_ (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ // First see if we should delegate this one to the Complex
+ // generator.
+ //
+ Type* base_enum (0);
+
+ if (!enum_ || !enum_mapping (e, &base_enum))
+ {
+ complex_.traverse (e);
+ return;
+ }
+
+ String const& name (epimpl_custom (e));
+
+ // We may not need to generate the class if this parser is
+ // being customized.
+ //
+ if (name)
+ {
+ Boolean fl (fixed_length (e));
+ SemanticGraph::Type& b (e.inherits ().base ());
+
+ os << "class " << name << ": public " <<
+ (mixin ? "virtual " : "") << epskel (e);
+
+ // Derive from base pimpl even if base_enum == 0. This is done
+ // so that we have implementations for all the (otherwise pure
+ // virtual) post_*() functions.
+ //
+ if (mixin)
+ os << "," << endl
+ << " public " << fq_name (b, "p:impl");
+
+ os << "{"
+ << "public:" << endl;
+
+ // c-tor
+ //
+ if (!fl || tiein)
+ os << name << " (" << (fl ? "" : "bool = false") << ");"
+ << endl;
+
+ if (!fl)
+ {
+ // d-tor
+ //
+ os << "~" << name << " ();"
+ << endl;
+
+ // reset
+ //
+ if (reset)
+ os << "virtual void" << endl
+ << "_reset ();"
+ << endl;
+ }
+
+ // pre
+ //
+ os << "virtual void" << endl
+ << "pre ();"
+ << endl;
+
+ // _characters
+ //
+ if (!base_enum)
+ os << "virtual void" << endl
+ << "_characters (const " << string_type << "&);"
+ << endl;
+
+ // post
+ //
+ String const& ret (pret_type (e));
+
+ if (polymorphic (e))
+ post_override_.dispatch (e);
+
+ os << "virtual " << ret << endl
+ << post_name (e) << " ();"
+ << endl;
+
+ String const& type (fq_name (e));
+
+ // pre_impl
+ //
+ if (!fl)
+ os << (tiein ? "public:" : "protected:") << endl
+ << "void" << endl
+ << pre_impl_name (e) << " (" << type << "*);"
+ << endl;
+
+ // Base implementation.
+ //
+ if (tiein && base_enum)
+ os << (tiein ? "public:" : "protected:") << endl
+ << fq_name (b, "p:impl") << " base_impl_;"
+ << endl;
+
+ // State.
+ //
+ if (!fl || !base_enum)
+ {
+ String const& state_type (epstate_type (e));
+
+ os << (tiein ? "public:" : "protected:") << endl
+ << "struct " << state_type
+ << "{";
+
+ if (!fl)
+ os << type << "* " << "x_;";
+
+ if (!base_enum)
+ {
+ if (stl)
+ os << "::std::string str_;";
+ else
+ os << "::xsde::cxx::string str_;";
+ }
+
+ os << "};"
+ << state_type << " " << epstate (e) << ";";
+ }
+
+ if (!fl)
+ os << "bool " << epstate_base (e) << ";";
+
+ os << "};";
+ }
+
+ // Generate include for custom parser.
+ //
+ if (e.context ().count ("p:impl-include"))
+ {
+ close_ns ();
+
+ os << "#include " << process_include_path (
+ e.context ().get<String> ("p:impl-include")) << endl
+ << endl;
+
+ open_ns ();
+ }
+ }
+
+ private:
+ Traversal::Complex& complex_;
+ PostOverride post_override_;
+ };
+
struct List: Traversal::List, Context
{
List (Context& c)
@@ -352,35 +540,6 @@ 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;
- }
- }
- }
- };
-
- //
- //
struct Complex : Traversal::Complex, Context
{
Complex (Context& c)
@@ -624,10 +783,12 @@ namespace CXX
List list (ctx);
Union union_ (ctx);
Complex complex (ctx);
+ Enumeration enumeration (ctx, complex);
names >> list;
names >> union_;
names >> complex;
+ names >> enumeration;
schema.dispatch (ctx.schema_root);
}
diff --git a/xsde/cxx/hybrid/parser-name-processor.cxx b/xsde/cxx/hybrid/parser-name-processor.cxx
index c635aec..819280f 100644
--- a/xsde/cxx/hybrid/parser-name-processor.cxx
+++ b/xsde/cxx/hybrid/parser-name-processor.cxx
@@ -4,6 +4,7 @@
// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
#include <cxx/elements.hxx>
+#include <cxx/hybrid/elements.hxx>
#include <cxx/hybrid/parser-name-processor.hxx>
#include <xsd-frontend/semantic-graph.hxx>
@@ -251,6 +252,61 @@ namespace CXX
//
//
+ struct Enumeration: Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c, Traversal::Complex& complex)
+ : Context (c), complex_ (complex)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ // First see if we should delegate this one to the Complex
+ // generator.
+ //
+ Type* base_enum (0);
+
+ if (options.value<CLI::suppress_enum> () ||
+ !Hybrid::Context::enum_mapping (e, &base_enum))
+ {
+ complex_.traverse (e);
+ return;
+ }
+
+ SemanticGraph::Context& ec (e.context ());
+
+ // In case of customization use p:impl-base instead of p:impl.
+ // If the name is empty then we are not generating anything.
+ //
+ String const& name (ec.count ("p:impl-base")
+ ? ec.get<String> ("p:impl-base")
+ : ec.get<String> ("p:impl"));
+ if (!name)
+ return;
+
+ Boolean fl (fixed_length (e));
+
+ NameSet set;
+ set.insert (name);
+
+ if (!fl || !base_enum)
+ {
+ String state_type (find_name (name + L"_state", set));
+ ec.set ("pstate-type", state_type);
+ ec.set ("pstate", find_name (state_type, "_", set));
+ }
+
+ if (!fl)
+ ec.set ("pstate-base", find_name (name + L"_base", "_", set));
+ }
+
+ private:
+ Traversal::Complex& complex_;
+ };
+
+ //
+ //
struct List: Traversal::List, Context
{
List (Context& c)
@@ -708,10 +764,12 @@ namespace CXX
List list (ctx);
Union union_ (ctx);
Complex complex (ctx);
+ Enumeration enumeration (ctx, complex);
ns_names >> list;
ns_names >> union_;
ns_names >> complex;
+ ns_names >> enumeration;
schema.dispatch (tu);
}
diff --git a/xsde/cxx/hybrid/parser-source.cxx b/xsde/cxx/hybrid/parser-source.cxx
index c877e1d..e5bbb90 100644
--- a/xsde/cxx/hybrid/parser-source.cxx
+++ b/xsde/cxx/hybrid/parser-source.cxx
@@ -14,6 +14,423 @@ namespace CXX
{
namespace
{
+ //
+ //
+ 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 Enumerator: Traversal::Enumerator, Context
+ {
+ Enumerator (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ using SemanticGraph::Enumeration;
+
+ Enumeration& s (dynamic_cast<Enumeration&> (e.scope ()));
+
+ os << "if (strcmp (s, " <<
+ strlit (e.name ()) << ") == 0)" << endl
+ << "v = " << fq_name (s) << "::" << ename (e) << ";";
+ }
+ };
+
+ //
+ //
+ struct Enumeration: Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c, Traversal::Complex& complex)
+ : Context (c),
+ complex_ (complex),
+ post_override_ (c),
+ enumerator_ (c)
+ {
+ names_ >> enumerator_;
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ // First see if we should delegate this one to the Complex
+ // generator.
+ //
+ Type* base_enum (0);
+
+ if (!enum_ || !enum_mapping (e, &base_enum))
+ {
+ complex_.traverse (e);
+ return;
+ }
+
+ String const& name (epimpl_custom (e));
+
+ if (!name)
+ return;
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ Boolean fl (fixed_length (e));
+
+ SemanticGraph::Context& ec (e.context ());
+ SemanticGraph::Type& b (e.inherits ().base ());
+
+ String const& type (fq_name (e));
+ String state;
+
+ if (!fl || !base_enum)
+ state = epstate (e);
+
+ // c-tor
+ //
+ if (!fl || tiein)
+ {
+ os << name << "::" << endl
+ << name << " (" << (fl ? "" : "bool b") << ")";
+
+ if (tiein)
+ os << endl
+ << ": " << epskel (e) << " (" <<
+ (base_enum ? "&base_impl_" : "0") << ")";
+
+ if (base_enum && !fixed_length (b))
+ {
+ if (tiein)
+ os << "," << endl
+ << " base_impl_" << " (true)";
+ else
+ os << endl
+ << ": " << fq_name (b, "p:impl") << " (true)";
+ }
+
+ os << "{";
+
+ if (!fl)
+ {
+ os << "this->" << epstate_base (e) << " = b;"
+ << "this->" << state << ".x_ = 0;";
+ }
+
+ os << "}";
+ }
+
+ if (!fl)
+ {
+ // d-tor
+ //
+ os << name << "::" << endl
+ << "~" << name << " ()"
+ << "{"
+ << "if (!this->" << epstate_base (e) << ")" << endl
+ << "delete this->" << state << ".x_;"
+ << "}";
+
+ // reset
+ //
+ if (reset)
+ {
+ os << "void " << name << "::" << endl
+ << "_reset ()"
+ << "{";
+
+ if (mixin && base_enum)
+ os << epimpl (b) << "::_reset ();";
+
+ os << epskel (e) << "::_reset ();"
+ << endl;
+
+ os << "if (!this->" << epstate_base (e) << ")"
+ << "{"
+ << "delete this->" << state << ".x_;"
+ << "this->" << state << ".x_ = 0;"
+ << "}"
+ << "}";
+ }
+ }
+
+ // pre_impl
+ //
+ if (!fl)
+ {
+ os << "void " << name << "::" << endl
+ << pre_impl_name (e) << " (" << type << "* x)"
+ << "{"
+ << "this->" << state << ".x_ = x;";
+
+ // Call base pre_impl (var-length) or pre (fix-length).
+ //
+ if (base_enum)
+ {
+ if (tiein)
+ os << "this->base_impl_.";
+ else
+ os << epimpl (b) << "::"; //@@ fq-name.
+
+ if (fixed_length (b))
+ os << "pre ();";
+ else
+ os << pre_impl_name (b) << " (x);";
+ }
+
+ // Clear the string buffer.
+ //
+ if (!base_enum)
+ {
+ if (stl)
+ os << "this->" << state << ".str_.clear ();";
+ else
+ {
+ if (exceptions)
+ os << "this->" << state << ".str_.assign (\"\", 0);";
+ else
+ {
+ os << endl
+ << "if (this->" << state << ".str_.assign (\"\", 0))" << endl
+ << "this->_sys_error (::xsde::cxx::sys_error::no_memory);";
+ }
+ }
+ }
+
+ os << "}";
+ }
+
+ // pre
+ //
+ os << "void " << name << "::" << endl
+ << "pre ()"
+ << "{";
+
+ if (fl)
+ {
+ if (base_enum)
+ {
+ // Our base is also fixed-length so call its pre()
+ //
+ if (tiein)
+ os << "this->base_impl_.";
+ else
+ os << epimpl (b) << "::"; //@@ fq-name.
+
+ os << "pre ();";
+ }
+
+ // Clear the string buffer.
+ //
+ if (!base_enum)
+ {
+ if (stl)
+ os << "this->" << state << ".str_.clear ();";
+ else
+ {
+ if (exceptions)
+ os << "this->" << state << ".str_.assign (\"\", 0);";
+ else
+ {
+ os << endl
+ << "if (this->" << state << ".str_.assign (\"\", 0))" << endl
+ << "this->_sys_error (::xsde::cxx::sys_error::no_memory);";
+ }
+ }
+ }
+ }
+ else
+ {
+ if (exceptions)
+ os << "this->" << pre_impl_name (e) << " (new " << type << ");";
+ else
+ os << type << "* x = new " << type << ";"
+ << "if (x)" << endl
+ << "this->" << pre_impl_name (e) << " (x);"
+ << "else" << endl
+ << "this->_sys_error (::xsde::cxx::sys_error::no_memory);";
+ }
+
+ os << "}";
+
+ // _characters
+ //
+ if (!base_enum)
+ {
+ os << "void " << name << "::" << endl
+ << "_characters (const " << string_type << "& s)"
+ << "{";
+
+ if (stl)
+ os << "this->" << state << ".str_.append (s.data (), s.size ());";
+ else
+ {
+ if (exceptions)
+ os << "this->" << state << ".str_.append (s.data (), s.size ());";
+ else
+ {
+ os << "if (this->" << state << ".str_.append (" <<
+ "s.data (), s.size ()))" << endl
+ << "this->_sys_error (::xsde::cxx::sys_error::no_memory);";
+ }
+ }
+
+ os << "}";
+ }
+
+ // post
+ //
+ String const& ret (pret_type (e));
+
+ if (polymorphic (e))
+ post_override_.dispatch (e);
+
+ os << ret << " " << name << "::" << endl
+ << post_name (e) << " ()"
+ << "{";
+
+ if (base_enum)
+ {
+ if (fl)
+ {
+ os << type << " r;"
+ << "static_cast< " << fq_name (b) << "& > (r) = ";
+
+ if (tiein)
+ os << "this->base_impl_.";
+ else
+ os << epimpl (b) << "::"; //@@ fq-name.
+
+ os << post_name (b) << " ();";
+ }
+ else
+ {
+ os << type << "* r = this->" << state << ".x_;"
+ << "this->" << state << ".x_ = 0;";
+
+ Boolean flb (fixed_length (b));
+
+ // Copy the value if our base is fixed-length.
+ //
+ if (flb)
+ os << "r->" << base_enum->context ().get<String> ("value") <<
+ " (";
+
+ if (tiein)
+ os << "this->base_impl_.";
+ else
+ os << epimpl (b) << "::"; //@@ fq-name.
+
+ os << post_name (b) << " ()";
+
+ if (flb)
+ os << ")";
+
+ os << ";";
+ }
+
+ //
+ // @@ TODO: check enumerators (switch)
+ //
+ }
+ else
+ {
+ String const& vt (ec.get<String> ("value-type"));
+
+ os << type << "::" << vt << " v = static_cast< " << type <<
+ "::" << vt << " > (0);"
+ << "const char* s = this->" << state << ".str_." <<
+ (stl ? "c_str" : "data") << " ();"
+ << endl;
+
+ names<Enumeration> (e, names_, 0, 0, 0, &Enumeration::comma);
+
+
+ /*
+ // @@ Cannot do error checking in post.
+
+ if (!options.value<CLI::suppress_validation> () &&
+ !options.value<CLI::suppress_parser_val> ())
+ {
+ os << "else" << endl
+ << "this->_schema_error (" <<
+ "::xsde::cxx::schema_error::invalid_enumeration_value);";
+ }
+ */
+
+ os << endl;
+
+ if (fl)
+ os << type << " r (v);";
+ else
+ os << type << "* r = this->" << state << ".x_;"
+ << "this->" << state << ".x_ = 0;"
+ << "r->" << ec.get<String> ("value") << " (v);";
+ }
+
+ os << "return r;"
+ << "}";
+ }
+
+ virtual Void
+ comma (Type&)
+ {
+ os << "else ";
+ }
+
+ private:
+ Traversal::Complex& complex_;
+ PostOverride post_override_;
+
+ Traversal::Names names_;
+ Enumerator enumerator_;
+ };
+
+ //
+ //
struct List: Traversal::List, Context
{
List (Context& c)
@@ -907,53 +1324,6 @@ 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)
@@ -1444,10 +1814,12 @@ namespace CXX
List list (ctx);
Union union_ (ctx);
Complex complex (ctx);
+ Enumeration enumeration (ctx, complex);
names >> list;
names >> union_;
names >> complex;
+ names >> enumeration;
schema.dispatch (ctx.schema_root);
}
diff --git a/xsde/cxx/hybrid/serializer-header.cxx b/xsde/cxx/hybrid/serializer-header.cxx
index 153da8d..b36b910 100644
--- a/xsde/cxx/hybrid/serializer-header.cxx
+++ b/xsde/cxx/hybrid/serializer-header.cxx
@@ -14,6 +14,141 @@ namespace CXX
{
namespace
{
+ //
+ //
+ 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 Enumeration: Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c, Traversal::Complex& complex)
+ : Context (c), complex_ (complex), pre_override_ (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ // First see if we should delegate this one to the Complex
+ // generator.
+ //
+ Type* base_enum (0);
+
+ if (!enum_ || !enum_mapping (e, &base_enum))
+ {
+ complex_.traverse (e);
+ return;
+ }
+
+ String const& name (esimpl_custom (e));
+
+ // We may not need to generate the class if this serializer is
+ // being customized.
+ //
+ if (name)
+ {
+ String const& arg (sarg_type (e));
+ SemanticGraph::Type& b (e.inherits ().base ());
+
+ os << "class " << name << ": public " <<
+ (mixin ? "virtual " : "") << esskel (e);
+
+ // Derive from base simpl even if base_enum == 0. This is done
+ // so that we have implementations for all the (otherwise pure
+ // virtual) pre() functions.
+ //
+ if (mixin)
+ os << "," << endl
+ << " public " << fq_name (b, "s:impl");
+
+ os << "{"
+ << "public:" << endl;
+
+ // c-tor
+ //
+ if (tiein)
+ os << name << " ();"
+ << endl;
+
+ // pre
+ //
+ if (polymorphic (e))
+ pre_override_.dispatch (e);
+
+ os << "virtual void" << endl
+ << "pre (" << arg << ");"
+ << endl;
+
+ // _serialize_content
+ //
+ if (!base_enum)
+ os << "virtual void" << endl
+ << "_serialize_content ();"
+ << endl;
+
+ // State.
+ //
+ if (!base_enum)
+ {
+ os << (tiein ? "public:" : "protected:") << endl
+ << "const " << fq_name (e) << "* " << esstate (e) << ";";
+ }
+ else if (tiein)
+ {
+ os << "public:" << endl
+ << fq_name (b, "s:impl") << " base_impl_;";
+ }
+
+ os << "};";
+ }
+
+ // Generate include for custom serializer.
+ //
+ if (e.context ().count ("s:impl-include"))
+ {
+ close_ns ();
+
+ os << "#include " << process_include_path (
+ e.context ().get<String> ("s:impl-include")) << endl
+ << endl;
+
+ open_ns ();
+ }
+ }
+
+ private:
+ Traversal::Complex& complex_;
+ PreOverride pre_override_;
+ };
+
+ //
+ //
struct List: Traversal::List, Context
{
List (Context& c)
@@ -343,35 +478,6 @@ 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)
@@ -511,7 +617,7 @@ namespace CXX
if (tiein && hb)
- os << (tiein ? "public:" : "protected:") << endl
+ os << "public:" << endl
<< fq_name (c.inherits ().base (), "s:impl") << " base_impl_;"
<< endl;
@@ -605,10 +711,12 @@ namespace CXX
List list (ctx);
Union union_ (ctx);
Complex complex (ctx);
+ Enumeration enumeration (ctx, complex);
names >> list;
names >> union_;
names >> complex;
+ names >> enumeration;
schema.dispatch (ctx.schema_root);
}
diff --git a/xsde/cxx/hybrid/serializer-name-processor.cxx b/xsde/cxx/hybrid/serializer-name-processor.cxx
index 2f7d296..159e3b0 100644
--- a/xsde/cxx/hybrid/serializer-name-processor.cxx
+++ b/xsde/cxx/hybrid/serializer-name-processor.cxx
@@ -4,6 +4,7 @@
// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
#include <cxx/elements.hxx>
+#include <cxx/hybrid/elements.hxx>
#include <cxx/hybrid/serializer-name-processor.hxx>
#include <xsd-frontend/semantic-graph.hxx>
@@ -244,6 +245,54 @@ namespace CXX
//
//
+ struct Enumeration: Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c, Traversal::Complex& complex)
+ : Context (c), complex_ (complex)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ // First see if we should delegate this one to the Complex
+ // generator.
+ //
+ Type* base_enum (0);
+
+ if (options.value<CLI::suppress_enum> () ||
+ !Hybrid::Context::enum_mapping (e, &base_enum))
+ {
+ complex_.traverse (e);
+ return;
+ }
+
+ SemanticGraph::Context& ec (e.context ());
+
+ // In case of customization use s:impl-base instead of s:impl.
+ // If the name is empty then we are not generating anything.
+ //
+ String const& name (ec.count ("s:impl-base")
+ ? ec.get<String> ("s:impl-base")
+ : ec.get<String> ("s:impl"));
+ if (!name)
+ return;
+
+ if (!base_enum)
+ {
+ NameSet set;
+ set.insert (name);
+
+ ec.set ("sstate", find_name (name + L"_state", "_", set));
+ }
+ }
+
+ private:
+ Traversal::Complex& complex_;
+ };
+
+ //
+ //
struct List: Traversal::List, Context
{
List (Context& c)
@@ -288,9 +337,9 @@ namespace CXX
}
virtual Void
- traverse (Type& l)
+ traverse (Type& u)
{
- SemanticGraph::Context& uc (l.context ());
+ SemanticGraph::Context& uc (u.context ());
// In case of customization use s:impl-base instead of s:impl.
// If the name is empty then we are not generating anything.
@@ -723,10 +772,12 @@ namespace CXX
List list (ctx);
Union union_ (ctx);
Complex complex (ctx);
+ Enumeration enumeration (ctx, complex);
ns_names >> list;
ns_names >> union_;
ns_names >> complex;
+ ns_names >> enumeration;
schema.dispatch (tu);
}
diff --git a/xsde/cxx/hybrid/serializer-source.cxx b/xsde/cxx/hybrid/serializer-source.cxx
index 0aeaf89..1268631 100644
--- a/xsde/cxx/hybrid/serializer-source.cxx
+++ b/xsde/cxx/hybrid/serializer-source.cxx
@@ -70,6 +70,155 @@ 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 Enumeration: Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c, Traversal::Complex& complex)
+ : Context (c),
+ complex_ (complex),
+ pre_override_ (c),
+ type_pass_(c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ // First see if we should delegate this one to the Complex
+ // generator.
+ //
+ Type* base_enum (0);
+
+ if (!enum_ || !enum_mapping (e, &base_enum))
+ {
+ complex_.traverse (e);
+ return;
+ }
+
+ String const& name (esimpl_custom (e));
+
+ if (!name)
+ return;
+
+ String state;
+
+ if (!base_enum)
+ state = esstate (e);
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ // c-tor
+ //
+ if (tiein)
+ {
+ os << name << "::" << endl
+ << name << " ()" << endl
+ << ": " << esskel (e) << " (" <<
+ (base_enum ? "&base_impl_" : "0") << ")"
+ << "{"
+ << "}";
+ }
+
+ // pre
+ //
+ String const& arg (sarg_type (e));
+
+ if (polymorphic (e))
+ pre_override_.dispatch (e);
+
+ os << "void " << name << "::" << endl
+ << "pre (" << arg << " x)"
+ << "{";
+
+ if (base_enum)
+ {
+ SemanticGraph::Type& b (e.inherits ().base ());
+
+ if (tiein)
+ os << "this->base_impl_.pre (";
+ else
+ os << esimpl (b) << "::pre (";
+
+ type_pass_.dispatch (b);
+
+ os << "x);";
+ }
+ else
+ os << "this->" << state << " = &x;";
+
+ os << "}";
+
+ // _serialize_content
+ //
+ if (!base_enum)
+ {
+ String const& string (e.context ().get<String> ("string"));
+
+ os << "void " << name << "::" << endl
+ << "_serialize_content ()"
+ << "{"
+ << "this->_characters (this->" << state << "->" <<
+ string << " ());"
+ << "}";
+ }
+ }
+
+ private:
+ Traversal::Complex& complex_;
+ PreOverride pre_override_;
+ TypePass type_pass_;
+ };
+
+ //
+ //
struct List: Traversal::List, Context
{
List (Context& c)
@@ -931,53 +1080,6 @@ 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)
@@ -1125,7 +1227,6 @@ namespace CXX
if (!b.is_a<SemanticGraph::AnyType> () &&
!b.is_a<SemanticGraph::AnySimpleType> ())
{
-
if (tiein)
os << "this->base_impl_.pre (";
else
@@ -1290,10 +1391,12 @@ namespace CXX
List list (ctx);
Union union_ (ctx);
Complex complex (ctx);
+ Enumeration enumeration (ctx, complex);
names >> list;
names >> union_;
names >> complex;
+ names >> enumeration;
schema.dispatch (ctx.schema_root);
}
diff --git a/xsde/cxx/hybrid/tree-forward.cxx b/xsde/cxx/hybrid/tree-forward.cxx
index 17a4916..bd53f9d 100644
--- a/xsde/cxx/hybrid/tree-forward.cxx
+++ b/xsde/cxx/hybrid/tree-forward.cxx
@@ -14,6 +14,50 @@ namespace CXX
{
namespace
{
+ struct Enumeration : Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c, Traversal::Complex& complex)
+ : Context (c), complex_ (complex)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ // First see if we should delegate this one to the Complex
+ // generator.
+ //
+ if (!enum_ || !enum_mapping (e))
+ {
+ complex_.traverse (e);
+ return;
+ }
+
+ SemanticGraph::Context& ctx (e.context ());
+
+ // Forward-declare the base.
+ //
+ if (ctx.count ("name-base"))
+ {
+ if (String base = ctx.get<String> ("name-base"))
+ os << "class " << base << ";";
+ }
+
+ // Typedef or forward-declare the type.
+ //
+ if (ctx.count ("name-typedef"))
+ {
+ os << "typedef " << ctx.get<String> ("name-typedef") << " " <<
+ ename (e) << ";";
+ }
+ else
+ os << "class " << ename (e) << ";";
+ }
+
+ private:
+ Traversal::Complex& complex_;
+ };
+
struct List : Traversal::List, Context
{
List (Context& c)
@@ -752,7 +796,7 @@ namespace CXX
List list (ctx);
Union union_ (ctx);
Complex complex (ctx);
- //Enumeration enumeration (ctx);
+ Enumeration enumeration (ctx, complex);
schema >> sources >> schema;
schema >> names_ns >> ns >> names;
@@ -760,7 +804,7 @@ namespace CXX
names >> list;
names >> union_;
names >> complex;
- //names >> enumeration;
+ names >> enumeration;
schema.dispatch (ctx.schema_root);
diff --git a/xsde/cxx/hybrid/tree-header.cxx b/xsde/cxx/hybrid/tree-header.cxx
index 929ea6e..aba65c7 100644
--- a/xsde/cxx/hybrid/tree-header.cxx
+++ b/xsde/cxx/hybrid/tree-header.cxx
@@ -14,6 +14,229 @@ namespace CXX
{
namespace
{
+ struct Enumerator: Traversal::Enumerator, Context
+ {
+ Enumerator (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ os << ename (e);
+ }
+ };
+
+ struct Enumeration : Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c, Traversal::Complex& complex)
+ : Context (c),
+ complex_ (complex),
+ base_name_ (c, TypeName::base),
+ enumerator_ (c)
+ {
+ names_ >> enumerator_;
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ // First see if we should delegate this one to the Complex
+ // generator.
+ //
+ Type* base_enum (0);
+
+ if (!enum_ || !enum_mapping (e, &base_enum))
+ {
+ complex_.traverse (e);
+ return;
+ }
+
+ SemanticGraph::Context& ec (e.context ());
+ String const& name (ename_custom (e));
+
+ // We may not need to generate the class if this type is
+ // being customized.
+ //
+ if (name)
+ {
+ Boolean fl (fixed_length (e));
+ Boolean cd (ec.count ("cd-name"));
+ Boolean poly (polymorphic (e));
+ String const& vt (ec.get<String> ("value-type"));
+
+ os << "// " << comment (e.name ()) << " (" <<
+ (fl ? "fixed-length" : "variable-length") << ")" << endl
+ << "//" << endl;
+
+ os << "class " << name;
+
+ if (base_enum)
+ {
+ os << ": public ";
+ base_name_.dispatch (e.inherits ().base ());
+ }
+
+ os << "{";
+
+ if (!fl)
+ os << "private:" << endl
+ << name << " (const " << name << "&);"
+ << name << "& operator= (const " << name << "&);"
+ << endl;
+
+ os << "public:" << endl;
+
+ // value_type
+ //
+ if (base_enum)
+ {
+ os << "typedef ";
+ base_name_.dispatch (*base_enum);
+ os << "::" << base_enum->context ().get<String> ("value-type") <<
+ " " << vt << ";"
+ << endl;
+ }
+ else
+ {
+ os << "enum " << vt
+ << "{";
+ names<Enumeration> (e, names_, 0, 0, 0, &Enumeration::comma);
+ os << "};";
+ }
+
+ // c-tors
+ //
+ os << name << " ();"
+ << name << " (" << vt << ");"
+ << endl;
+
+ // value (value_type)
+ //
+ if (!base_enum)
+ os << "void" << endl
+ << ec.get<String> ("value") << " (" << vt << ");"
+ << endl;
+
+ // d-tor
+ //
+ if (poly)
+ os << "virtual" << endl
+ << "~" << name << " ();"
+ << endl;
+
+ if (!base_enum)
+ {
+ // operator value()
+ //
+ // Name lookup differences in various compilers make generation
+ // of this operator outside of the class a really hard task. So
+ // we are going to make it always inline.
+ //
+ os << "operator " << vt << " () const"
+ << "{"
+ << "return " << ec.get<String> ("value-member") << ";"
+ << "}";
+
+ // string()
+ //
+ os << "const char*" << endl
+ << ec.get<String> ("string") << " () const;"
+ << endl;
+ }
+
+ // Custom data.
+ //
+ if (cd)
+ {
+ String const& name (ecd_name (e));
+ String const& sequence (ecd_sequence (e));
+ String const& iterator (ecd_iterator (e));
+ String const& const_iterator (ecd_const_iterator (e));
+
+ os << "// Custom data." << endl
+ << "//" << endl;
+
+ // sequence & iterators
+ //
+ os << "typedef " << data_seq << " " << sequence << ";"
+ << "typedef " << sequence << "::iterator " << iterator << ";"
+ << "typedef " << sequence << "::const_iterator " <<
+ const_iterator << ";"
+ << endl;
+
+ // const seq&
+ // name () const
+ //
+ os << "const " << sequence << "&" << endl
+ << name << " () const;"
+ << endl;
+
+ // seq&
+ // name ()
+ //
+ 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 (!base_enum || cd)
+ os << "private:" << endl;
+
+ if (!base_enum)
+ os << vt << " " << ec.get<String> ("value-member") << ";";
+
+ if (cd)
+ os << ecd_sequence (e) << " " << ecd_member (e) << ";";
+
+ os << "};";
+ }
+
+ // Generate include for custom type.
+ //
+ if (ec.count ("name-include"))
+ {
+ close_ns ();
+
+ os << "#include " << process_include_path (
+ ec.get<String> ("name-include")) << endl
+ << endl;
+
+ open_ns ();
+ }
+ }
+
+ virtual Void
+ comma (Type&)
+ {
+ os << "," << endl;
+ }
+
+ private:
+ Traversal::Complex& complex_;
+ TypeName base_name_;
+
+ Traversal::Names names_;
+ Enumerator enumerator_;
+ };
+
struct List : Traversal::List, Context
{
List (Context& c)
@@ -2412,6 +2635,14 @@ namespace CXX
os << "{";
+ // copy c-tor & operator= (private)
+ //
+ if (!fl)
+ os << "private:" << endl
+ << name << " (const " << name << "&);"
+ << name << "& operator= (const " << name << "&);"
+ << endl;
+
// c-tor
//
os << "public:" << endl
@@ -2422,19 +2653,13 @@ namespace CXX
if (!restriction || poly)
os << (poly ? "virtual\n" : "") << "~" << name << " ();";
- // copy c-tor & operator=
+ // copy c-tor & operator= (public)
//
- if (!fl)
- os << endl
- << "private:" << endl;
-
- if (!fl || !restriction)
+ if (fl && !restriction)
os << name << " (const " << name << "&);"
- << name << "& operator= (const " << name << "&);"
- << endl;
+ << name << "& operator= (const " << name << "&);";
- if ((!restriction && !fl) || cd)
- os << "public:" << endl;
+ os << endl;
if (!restriction)
{
@@ -2614,7 +2839,7 @@ namespace CXX
List list (ctx);
Union union_ (ctx);
Complex complex (ctx);
- //Enumeration enumeration (ctx);
+ Enumeration enumeration (ctx, complex);
schema >> sources >> schema;
schema >> names_ns >> ns >> names;
@@ -2622,7 +2847,7 @@ namespace CXX
names >> list;
names >> union_;
names >> complex;
- //names >> enumeration;
+ names >> enumeration;
schema.dispatch (ctx.schema_root);
}
diff --git a/xsde/cxx/hybrid/tree-inline.cxx b/xsde/cxx/hybrid/tree-inline.cxx
index 26b1a48..28a0582 100644
--- a/xsde/cxx/hybrid/tree-inline.cxx
+++ b/xsde/cxx/hybrid/tree-inline.cxx
@@ -15,6 +15,115 @@ namespace CXX
{
namespace
{
+ struct Enumeration : Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c, Traversal::Complex& complex)
+ : Context (c),
+ complex_ (complex),
+ base_name_ (c, TypeName::base)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ // First see if we should delegate this one to the Complex
+ // generator.
+ //
+ Type* base_enum (0);
+
+ if (!enum_ || !enum_mapping (e, &base_enum))
+ {
+ complex_.traverse (e);
+ return;
+ }
+
+ String const& name (ename_custom (e));
+
+ // We may not need to generate the class if this type is
+ // being customized.
+ //
+ if (!name)
+ return;
+
+ SemanticGraph::Context& ec (e.context ());
+ String const& vt (ec.get<String> ("value-type"));
+
+ os << "// " << comment (e.name ()) << endl
+ << "//" << endl
+ << endl;
+
+ // c-tors
+ //
+ os << inl
+ << name << "::" << endl
+ << name << " ()"
+ << "{"
+ << "}";
+
+ os << inl
+ << name << "::" << endl
+ << name << " (" << vt << " v)"
+ << "{";
+
+ if (base_enum)
+ {
+ os << "this->" << base_enum->context ().get<String> ("value") <<
+ " (v);";
+ }
+ else
+ os << ec.get<String> ("value-member") << " = v;";
+
+ os << "}";
+
+ // value (value_type)
+ //
+ if (!base_enum)
+ {
+ os << inl
+ << "void " << name << "::" << endl
+ << ec.get<String> ("value") << " (" << vt << " v)"
+ << "{"
+ << ec.get<String> ("value-member") << " = v;"
+ << "}";
+ }
+
+ // Custom data.
+ //
+ if (ec.count ("cd-name"))
+ {
+ String const& cd_name (ecd_name (e));
+ String const& member (ecd_member (e));
+ String const& sequence (ecd_sequence (e));
+
+ // const seq&
+ // name () const
+ //
+ os << inl
+ << "const " << name << "::" << sequence << "& " <<
+ name << "::" << endl
+ << cd_name << " () const"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+
+ // seq&
+ // name ()
+ //
+ os << inl
+ << name << "::" << sequence << "& " << name << "::" << endl
+ << cd_name << " ()"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+ }
+ }
+
+ private:
+ Traversal::Complex& complex_;
+ TypeName base_name_;
+ };
+
struct List : Traversal::List, Context
{
List (Context& c)
@@ -2029,7 +2138,7 @@ namespace CXX
List list (ctx);
Union union_ (ctx);
Complex complex (ctx);
- //Enumeration enumeration (ctx);
+ Enumeration enumeration (ctx, complex);
schema >> sources >> schema;
schema >> names_ns >> ns >> names;
@@ -2037,7 +2146,7 @@ namespace CXX
names >> list;
names >> union_;
names >> complex;
- //names >> enumeration;
+ names >> enumeration;
schema.dispatch (ctx.schema_root);
}
diff --git a/xsde/cxx/hybrid/tree-name-processor.cxx b/xsde/cxx/hybrid/tree-name-processor.cxx
index 240da59..e5c55db 100644
--- a/xsde/cxx/hybrid/tree-name-processor.cxx
+++ b/xsde/cxx/hybrid/tree-name-processor.cxx
@@ -4,6 +4,8 @@
// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
#include <cxx/elements.hxx>
+
+#include <cxx/hybrid/elements.hxx>
#include <cxx/hybrid/tree-name-processor.hxx>
#include <xsd-frontend/semantic-graph.hxx>
@@ -51,6 +53,7 @@ namespace CXX
schema_path (schema_path_),
stl (!ops.value<CLI::no_stl> ()),
detach (ops.value<CLI::generate_detach> ()),
+ enum_ (!ops.value<CLI::suppress_enum> ()),
custom_data_map (custom_data_map_),
custom_type_map (custom_type_map_),
global_type_names (global_type_names_)
@@ -179,6 +182,7 @@ namespace CXX
schema_path (c.schema_path),
stl (c.stl),
detach (c.detach),
+ enum_ (c.enum_),
custom_data_map (c.custom_data_map),
custom_type_map (c.custom_type_map),
global_type_names (c.global_type_names)
@@ -279,6 +283,7 @@ namespace CXX
Boolean stl;
Boolean detach;
+ Boolean enum_;
CustomDataMap& custom_data_map;
CustomTypeMap& custom_type_map;
@@ -1140,9 +1145,29 @@ namespace CXX
//
//
+ struct Enumerator: Traversal::Enumerator, Context
+ {
+ Enumerator (Context& c, NameSet& set)
+ : Context (c), set_ (set)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ e.context ().set ("name", find_name (e.name (), set_));
+ }
+
+ private:
+ NameSet& set_;
+ };
+
+ //
+ //
struct GlobalTypeMembers: Traversal::List,
Traversal::Union,
Traversal::Complex,
+ Traversal::Enumeration,
Context
{
GlobalTypeMembers (Context& c, Boolean data_members)
@@ -1151,6 +1176,82 @@ namespace CXX
}
virtual Void
+ traverse (SemanticGraph::Enumeration& e)
+ {
+ // First see if we should delegate this one to Complex.
+ //
+ SemanticGraph::Enumeration* base_enum (0);
+
+ if (!enum_ || !Hybrid::Context::enum_mapping (e, &base_enum))
+ {
+ traverse (static_cast<SemanticGraph::Complex&> (e));
+ return;
+ }
+
+ SemanticGraph::Context& ec (e.context ());
+
+ // In case of customization use name-base instead of name.
+ // If name is empty then we are not generating anything.
+ //
+ String const& name (ec.count ("name-base")
+ ? ec.get<String> ("name-base")
+ : ec.get<String> ("name"));
+ if (!name)
+ return;
+
+ if (!data_members_)
+ {
+ ec.set (member_set_key, NameSet ());
+ NameSet& set (ec.get<NameSet> (member_set_key));
+ set.insert (name);
+
+ String v (ec.get<String> ("value-type")); // Set by GlobalTypeName.
+ set.insert (v);
+
+ Enumerator enumerator (*this, set);
+ Traversal::Names names (enumerator);
+ Enumeration::names (e, names);
+
+ if (!base_enum)
+ {
+ ec.set ("value", find_name ("value", set));
+ ec.set ("string", find_name ("string", set));
+ }
+
+ // Check if this type has custom data.
+ //
+ CustomDataMap::Iterator i (custom_data_map.find (e.name ()));
+
+ if (i != custom_data_map.end () &&
+ i->second->find (L"") != i->second->end ())
+ {
+ String name (find_name ("custom_data", set));
+
+ ec.set ("cd-name", name);
+ ec.set ("cd-sequence", find_name (name + L"_sequence", set));
+ ec.set ("cd-iterator", find_name (name + L"_iterator", set));
+ ec.set ("cd-const-iterator",
+ find_name (name + L"_const_iterator", set));
+ }
+ }
+ else
+ {
+ NameSet& set (ec.get<NameSet> (member_set_key));
+
+ if (!base_enum)
+ ec.set ("value-member", find_name ("value_", set));
+
+ // Custom data.
+ //
+ if (ec.count ("cd-name"))
+ {
+ String const& base (ec.get<String> ("cd-name"));
+ ec.set ("cd-member", find_name (base + L"_", set));
+ }
+ }
+ }
+
+ virtual Void
traverse (SemanticGraph::List& l)
{
SemanticGraph::Context& lc (l.context ());
@@ -1531,6 +1632,7 @@ namespace CXX
//
struct GlobalTypeName: Traversal::Type,
Traversal::Union,
+ Traversal::Enumeration,
Context
{
GlobalTypeName (Context& c, NameSet& set)
@@ -1591,6 +1693,32 @@ namespace CXX
uc.set ("value", find_name ("value", set));
}
+ virtual Void
+ traverse (SemanticGraph::Enumeration& e)
+ {
+ traverse (static_cast<SemanticGraph::Type&> (e));
+
+ if (enum_ && Hybrid::Context::enum_mapping (e))
+ {
+ // We need to assign the value type name for enumerations
+ // even in included/imported schemas since we may need this
+ // information when generating derived enums. We need to do
+ // this even if the type is completely customized.
+ //
+ SemanticGraph::Context& ec (e.context ());
+ String name (ec.count ("name-base")
+ ? ec.get<String> ("name-base")
+ : ec.get<String> ("name"));
+
+ if (!name)
+ name = ec.get<String> ("name");
+
+ NameSet set;
+ set.insert (name);
+ ec.set ("value-type", find_name ("value_type", set));
+ }
+ }
+
private:
NameSet& set_;
};
diff --git a/xsde/cxx/hybrid/tree-size-processor.cxx b/xsde/cxx/hybrid/tree-size-processor.cxx
index 33d829a..c6b347e 100644
--- a/xsde/cxx/hybrid/tree-size-processor.cxx
+++ b/xsde/cxx/hybrid/tree-size-processor.cxx
@@ -237,20 +237,23 @@ namespace CXX
//
struct Type: Traversal::List,
Traversal::Union,
- Traversal::Complex
+ Traversal::Complex,
+ Traversal::Enumeration
{
Type (Boolean& valid,
TypeSet& custom_data,
CustomTypeMap& custom_type_map,
TypeSet& poly_types,
Boolean stl_,
- Boolean poly_)
+ Boolean poly_,
+ Boolean enum_mapping)
: valid_ (valid),
custom_data_ (custom_data),
custom_type_map_ (custom_type_map),
poly_types_ (poly_types),
stl (stl_),
- poly (poly_)
+ poly (poly_),
+ enum_ (enum_mapping)
{
}
@@ -281,6 +284,44 @@ namespace CXX
}
virtual Void
+ traverse (SemanticGraph::Enumeration& e)
+ {
+ if (!test (e))
+ {
+ // First process our base since enum_mapping() needs the
+ // polymorphic property determined.
+ //
+ SemanticGraph::Type& b (e.inherits ().base ());
+
+ if (!test (b))
+ dispatch (b);
+
+ SemanticGraph::Enumeration* base_enum (0);
+
+ if (!enum_ || !Context::enum_mapping (e, &base_enum))
+ {
+ traverse (static_cast<SemanticGraph::Complex&> (e));
+ return;
+ }
+
+ Boolean fixed (true);
+
+ if (base_enum && !get (b))
+ fixed = false;
+
+ // Check for custom data.
+ //
+ if (fixed)
+ {
+ if (custom_data_.find (e.name ()) != custom_data_.end ())
+ fixed = false;
+ }
+
+ set (e, fixed);
+ }
+ }
+
+ virtual Void
traverse (SemanticGraph::Complex& c)
{
SemanticGraph::Context& ctx (c.context ());
@@ -428,6 +469,7 @@ namespace CXX
TypeSet& poly_types_;
Boolean stl;
Boolean poly;
+ Boolean enum_;
typedef Containers::Vector<SemanticGraph::Complex*> Path;
Path path_;
@@ -1184,7 +1226,8 @@ namespace CXX
custom_type_map,
poly_types,
stl,
- poly);
+ poly,
+ !ops.value<CLI::suppress_enum> ());
schema >> schema_names >> ns >> ns_names >> type;
diff --git a/xsde/cxx/hybrid/tree-source.cxx b/xsde/cxx/hybrid/tree-source.cxx
index eb83658..61186b5 100644
--- a/xsde/cxx/hybrid/tree-source.cxx
+++ b/xsde/cxx/hybrid/tree-source.cxx
@@ -15,6 +15,135 @@ namespace CXX
{
namespace
{
+ struct Enumerator: Traversal::Enumerator, Context
+ {
+ Enumerator (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ os << strlit (e.name ());
+ }
+ };
+
+ struct Enumeration: Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c, Traversal::Complex& complex)
+ : Context (c), complex_ (complex), enumerator_ (c)
+ {
+ names_ >> enumerator_;
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ // First see if we should delegate this one to the Complex
+ // generator.
+ //
+ Type* base_enum (0);
+
+ if (!enum_ || !enum_mapping (e, &base_enum))
+ {
+ complex_.traverse (e);
+ return;
+ }
+
+ String const& name (ename_custom (e));
+
+ // We may not need to generate the class if this type is
+ // being customized.
+ //
+ if (!name)
+ return;
+
+ SemanticGraph::Context& ec (e.context ());
+
+ os << "// " << comment (e.name ()) << endl
+ << "//" << endl
+ << endl;
+
+ if (!base_enum)
+ {
+ os << "static const char* _xsde_" << name << "_enumerators_[] = {";
+ names<Enumeration> (e, names_, 0, 0, 0, &Enumeration::comma);
+ os << "};";
+
+ // string()
+ //
+ os << "const char* " << name << "::" << endl
+ << ec.get<String> ("string") << " () const"
+ << "{"
+ << "return _xsde_" << name << "_enumerators_[" <<
+ ec.get<String> ("value-member") << "];"
+ << "}";
+ }
+
+ if (polymorphic (e))
+ {
+ // d-tor
+ //
+ os << name << "::" << endl
+ << "~" << name << " ()"
+ << "{"
+ << "}";
+
+ if (typeinfo)
+ {
+ String id (e.name ());
+
+ if (String ns = xml_ns_name (e))
+ {
+ 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 ();"
+ << "}";
+ }
+ }
+ }
+
+ virtual Void
+ comma (Type&)
+ {
+ os << "," << endl;
+ }
+
+ private:
+ Traversal::Complex& complex_;
+
+ Traversal::Names names_;
+ Enumerator enumerator_;
+ };
+
struct List : Traversal::List, Context
{
List (Context& c)
@@ -1968,6 +2097,7 @@ namespace CXX
List list (ctx);
Union union_ (ctx);
Complex complex (ctx);
+ Enumeration enumeration (ctx, complex);
schema >> sources >> schema;
schema >> names_ns >> ns >> names;
@@ -1975,6 +2105,7 @@ namespace CXX
names >> list;
names >> union_;
names >> complex;
+ names >> enumeration;
schema.dispatch (ctx.schema_root);
}