aboutsummaryrefslogtreecommitdiff
path: root/xsde/cxx/hybrid
diff options
context:
space:
mode:
Diffstat (limited to 'xsde/cxx/hybrid')
-rw-r--r--xsde/cxx/hybrid/cli.hxx188
-rw-r--r--xsde/cxx/hybrid/elements.cxx493
-rw-r--r--xsde/cxx/hybrid/elements.hxx1880
-rw-r--r--xsde/cxx/hybrid/generator.cxx2476
-rw-r--r--xsde/cxx/hybrid/generator.hxx90
-rw-r--r--xsde/cxx/hybrid/parser-aggregate-header.cxx837
-rw-r--r--xsde/cxx/hybrid/parser-aggregate-header.hxx22
-rw-r--r--xsde/cxx/hybrid/parser-aggregate-source.cxx330
-rw-r--r--xsde/cxx/hybrid/parser-aggregate-source.hxx22
-rw-r--r--xsde/cxx/hybrid/parser-header.cxx574
-rw-r--r--xsde/cxx/hybrid/parser-header.hxx22
-rw-r--r--xsde/cxx/hybrid/parser-name-processor.cxx709
-rw-r--r--xsde/cxx/hybrid/parser-name-processor.hxx32
-rw-r--r--xsde/cxx/hybrid/parser-source.cxx1185
-rw-r--r--xsde/cxx/hybrid/parser-source.hxx22
-rw-r--r--xsde/cxx/hybrid/serializer-aggregate-header.cxx847
-rw-r--r--xsde/cxx/hybrid/serializer-aggregate-header.hxx22
-rw-r--r--xsde/cxx/hybrid/serializer-aggregate-source.cxx330
-rw-r--r--xsde/cxx/hybrid/serializer-aggregate-source.hxx22
-rw-r--r--xsde/cxx/hybrid/serializer-header.cxx534
-rw-r--r--xsde/cxx/hybrid/serializer-header.hxx22
-rw-r--r--xsde/cxx/hybrid/serializer-name-processor.cxx723
-rw-r--r--xsde/cxx/hybrid/serializer-name-processor.hxx32
-rw-r--r--xsde/cxx/hybrid/serializer-source.cxx1001
-rw-r--r--xsde/cxx/hybrid/serializer-source.hxx22
-rw-r--r--xsde/cxx/hybrid/tree-forward.cxx626
-rw-r--r--xsde/cxx/hybrid/tree-forward.hxx22
-rw-r--r--xsde/cxx/hybrid/tree-header.cxx2459
-rw-r--r--xsde/cxx/hybrid/tree-header.hxx22
-rw-r--r--xsde/cxx/hybrid/tree-inline.cxx1817
-rw-r--r--xsde/cxx/hybrid/tree-inline.hxx22
-rw-r--r--xsde/cxx/hybrid/tree-name-processor.cxx1993
-rw-r--r--xsde/cxx/hybrid/tree-name-processor.hxx32
-rw-r--r--xsde/cxx/hybrid/tree-size-processor.cxx850
-rw-r--r--xsde/cxx/hybrid/tree-size-processor.hxx32
-rw-r--r--xsde/cxx/hybrid/tree-source.cxx1672
-rw-r--r--xsde/cxx/hybrid/tree-source.hxx22
-rw-r--r--xsde/cxx/hybrid/tree-type-map.cxx248
-rw-r--r--xsde/cxx/hybrid/tree-type-map.hxx32
-rw-r--r--xsde/cxx/hybrid/validator.cxx584
-rw-r--r--xsde/cxx/hybrid/validator.hxx35
41 files changed, 22905 insertions, 0 deletions
diff --git a/xsde/cxx/hybrid/cli.hxx b/xsde/cxx/hybrid/cli.hxx
new file mode 100644
index 0000000..57aa3d4
--- /dev/null
+++ b/xsde/cxx/hybrid/cli.hxx
@@ -0,0 +1,188 @@
+// file : xsde/cxx/hybrid/cli.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_CLI_HXX
+#define CXX_HYBRID_CLI_HXX
+
+#include <cult/types.hxx>
+
+#include <cult/containers/vector.hxx>
+
+#include <cult/cli/options.hxx>
+#include <cult/cli/options-spec.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ namespace CLI
+ {
+ using namespace Cult::Types;
+
+ typedef Char const Key[];
+
+ extern Key no_stl;
+ extern Key no_iostream;
+ extern Key no_exceptions;
+ extern Key no_long_long;
+ extern Key generate_parser;
+ extern Key generate_serializer;
+ extern Key generate_aggregate;
+ extern Key suppress_validation;
+ extern Key suppress_parser_val;
+ extern Key suppress_serializer_val;
+ extern Key generate_inline;
+ extern Key generate_forward;
+ extern Key generate_xml_schema;
+ extern Key extern_xml_schema;
+ extern Key suppress_reset;
+ extern Key reuse_style_mixin;
+ extern Key custom_data;
+ extern Key custom_parser;
+ extern Key custom_serializer;
+ extern Key root_element_first;
+ extern Key root_element_last;
+ extern Key root_element_all;
+ extern Key root_element_none;
+ extern Key root_element;
+ extern Key root_type;
+ extern Key output_dir;
+ extern Key pskel_type_suffix;
+ extern Key sskel_type_suffix;
+ extern Key pskel_file_suffix;
+ extern Key sskel_file_suffix;
+ extern Key pimpl_type_suffix;
+ extern Key simpl_type_suffix;
+ extern Key pimpl_file_suffix;
+ extern Key simpl_file_suffix;
+ extern Key paggr_type_suffix;
+ extern Key saggr_type_suffix;
+ extern Key namespace_map;
+ extern Key namespace_regex;
+ extern Key namespace_regex_trace;
+ extern Key reserved_name;
+ extern Key include_with_brackets;
+ extern Key include_prefix;
+ extern Key include_regex;
+ extern Key include_regex_trace;
+ extern Key guard_prefix;
+ extern Key hxx_suffix;
+ extern Key ixx_suffix;
+ extern Key cxx_suffix;
+ extern Key fwd_suffix;
+ extern Key hxx_regex;
+ extern Key ixx_regex;
+ extern Key cxx_regex;
+ extern Key fwd_regex;
+ extern Key hxx_prologue;
+ extern Key ixx_prologue;
+ extern Key cxx_prologue;
+ extern Key fwd_prologue;
+ extern Key prologue;
+ extern Key hxx_epilogue;
+ extern Key ixx_epilogue;
+ extern Key cxx_epilogue;
+ extern Key fwd_epilogue;
+ extern Key epilogue;
+ extern Key hxx_prologue_file;
+ extern Key ixx_prologue_file;
+ extern Key cxx_prologue_file;
+ extern Key fwd_prologue_file;
+ extern Key prologue_file;
+ extern Key hxx_epilogue_file;
+ extern Key ixx_epilogue_file;
+ extern Key cxx_epilogue_file;
+ extern Key fwd_epilogue_file;
+ extern Key epilogue_file;
+ extern Key show_anonymous;
+ extern Key show_sloc;
+ extern Key proprietary_license;
+
+ typedef Cult::CLI::Options<
+ no_stl, Boolean,
+ no_iostream, Boolean,
+ no_exceptions, Boolean,
+ no_long_long, Boolean,
+ generate_parser, Boolean,
+ generate_serializer, Boolean,
+ generate_aggregate, Boolean,
+ suppress_validation, Boolean,
+ suppress_parser_val, Boolean,
+ suppress_serializer_val, Boolean,
+ generate_inline, Boolean,
+ generate_forward, Boolean,
+ generate_xml_schema, Boolean,
+ extern_xml_schema, NarrowString,
+ suppress_reset, Boolean,
+ reuse_style_mixin, Boolean,
+ custom_data, Cult::Containers::Vector<NarrowString>,
+ custom_parser, Cult::Containers::Vector<NarrowString>,
+ custom_serializer, Cult::Containers::Vector<NarrowString>,
+ root_element_first, Boolean,
+ root_element_last, Boolean,
+ root_element_all, Boolean,
+ root_element_none, Boolean,
+ root_element, Cult::Containers::Vector<NarrowString>,
+ root_type, Cult::Containers::Vector<NarrowString>,
+ output_dir, NarrowString,
+ pskel_type_suffix, NarrowString,
+ sskel_type_suffix, NarrowString,
+ pskel_file_suffix, NarrowString,
+ sskel_file_suffix, NarrowString,
+ pimpl_type_suffix, NarrowString,
+ simpl_type_suffix, NarrowString,
+ pimpl_file_suffix, NarrowString,
+ simpl_file_suffix, NarrowString,
+ paggr_type_suffix, NarrowString,
+ saggr_type_suffix, NarrowString,
+ namespace_map, Cult::Containers::Vector<NarrowString>,
+ namespace_regex, Cult::Containers::Vector<NarrowString>,
+ namespace_regex_trace, Boolean,
+ reserved_name, Cult::Containers::Vector<NarrowString>,
+ include_with_brackets, Boolean,
+ include_prefix, NarrowString,
+ include_regex, Cult::Containers::Vector<NarrowString>,
+ include_regex_trace, Boolean,
+ guard_prefix, NarrowString,
+ hxx_suffix, NarrowString,
+ ixx_suffix, NarrowString,
+ cxx_suffix, NarrowString,
+ fwd_suffix, NarrowString,
+ hxx_regex, Cult::Containers::Vector<NarrowString>,
+ ixx_regex, Cult::Containers::Vector<NarrowString>,
+ cxx_regex, Cult::Containers::Vector<NarrowString>,
+ fwd_regex, NarrowString,
+ hxx_prologue, Cult::Containers::Vector<NarrowString>,
+ ixx_prologue, Cult::Containers::Vector<NarrowString>,
+ cxx_prologue, Cult::Containers::Vector<NarrowString>,
+ fwd_prologue, Cult::Containers::Vector<NarrowString>,
+ prologue, Cult::Containers::Vector<NarrowString>,
+ hxx_epilogue, Cult::Containers::Vector<NarrowString>,
+ ixx_epilogue, Cult::Containers::Vector<NarrowString>,
+ cxx_epilogue, Cult::Containers::Vector<NarrowString>,
+ fwd_epilogue, Cult::Containers::Vector<NarrowString>,
+ epilogue, Cult::Containers::Vector<NarrowString>,
+ hxx_prologue_file, Cult::Containers::Vector<NarrowString>,
+ ixx_prologue_file, Cult::Containers::Vector<NarrowString>,
+ cxx_prologue_file, Cult::Containers::Vector<NarrowString>,
+ fwd_prologue_file, NarrowString,
+ prologue_file, Cult::Containers::Vector<NarrowString>,
+ hxx_epilogue_file, Cult::Containers::Vector<NarrowString>,
+ ixx_epilogue_file, Cult::Containers::Vector<NarrowString>,
+ cxx_epilogue_file, Cult::Containers::Vector<NarrowString>,
+ fwd_epilogue_file, NarrowString,
+ epilogue_file, Cult::Containers::Vector<NarrowString>,
+ show_anonymous, Boolean,
+ show_sloc, Boolean,
+ proprietary_license, Boolean
+
+ > Options;
+
+ struct OptionsSpec: Cult::CLI::OptionsSpec<Options> {};
+ }
+ }
+}
+
+#endif // CXX_HYBRID_CLI_HXX
diff --git a/xsde/cxx/hybrid/elements.cxx b/xsde/cxx/hybrid/elements.cxx
new file mode 100644
index 0000000..454d0c3
--- /dev/null
+++ b/xsde/cxx/hybrid/elements.cxx
@@ -0,0 +1,493 @@
+// file : xsde/cxx/hybrid/elements.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/hybrid/elements.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ Context::
+ Context (std::wostream& o,
+ SemanticGraph::Schema& root,
+ CLI::Options const& ops,
+ Regex const* fe,
+ Regex const* he,
+ Regex const* ie)
+ : CXX::Context (o,
+ root,
+ "name",
+ "char",
+ ops.value<CLI::include_with_brackets> (),
+ ops.value<CLI::include_prefix> (),
+ "", // export symbol
+ ops.value<CLI::namespace_map> (),
+ ops.value<CLI::namespace_regex> (),
+ ops.value<CLI::namespace_regex_trace> (),
+ ops.value<CLI::include_regex> (),
+ ops.value<CLI::include_regex_trace> (),
+ ops.value<CLI::generate_inline> (),
+ ops.value<CLI::reserved_name> ()),
+ options (ops),
+ exceptions (!ops.value<CLI::no_exceptions> ()),
+ stl (!ops.value<CLI::no_stl> ()),
+ poly_code (false),
+ poly_runtime (false),
+ reset (!ops.value<CLI::suppress_reset> ()),
+ mixin (ops.value<CLI::reuse_style_mixin> ()),
+ tiein (!mixin),
+ fwd_expr (fe),
+ hxx_expr (he),
+ ixx_expr (ie),
+ ns_stack (ns_stack_)
+ {
+ String xs_ns (xs_ns_name ());
+
+ string_type = L"::xsde::cxx::ro_string";
+ }
+
+ // Parser
+ //
+ String const& Context::
+ pret_type (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("p:ret-type");
+ }
+
+ String const& Context::
+ parg_type (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("p:arg-type");
+ }
+
+ String const& Context::
+ post_name (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("p:post");
+ }
+
+ static String pre_impl ("pre_impl");
+
+ String const& Context::
+ pre_impl_name (SemanticGraph::Type&)
+ {
+ // @@ Currently not assigned because we don't assign names to
+ // types in included/imported schemas which makes assigning
+ // this name correctly impossible.
+ //
+ return pre_impl;
+ // return t.context ().get<String> ("ppre-impl");
+ }
+
+ String const& Context::
+ epname (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("p:name");
+ }
+
+ String const& Context::
+ epname (SemanticGraph::Attribute& a)
+ {
+ return a.context ().get<String> ("p:name");
+ }
+
+ String const& Context::
+ epimpl (SemanticGraph::Type& t)
+ {
+ // Use p:impl instead of pimpl because C++/Parser assigns impl
+ // names to the built-in types.
+ //
+ return t.context ().get<String> ("p:impl");
+ }
+
+ String const& Context::
+ epimpl_custom (SemanticGraph::Type& t)
+ {
+ SemanticGraph::Context& c (t.context ());
+
+ if (!c.count ("p:impl-base"))
+ return c.get<String> ("p:impl");
+ else
+ return c.get<String> ("p:impl-base");
+ }
+
+ String const& Context::
+ epstate (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("pstate");
+ }
+
+ String const& Context::
+ epstate_type (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("pstate-type");
+ }
+
+ String const& Context::
+ epstate_member (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("pstate-member");
+ }
+
+ String const& Context::
+ epstate_base (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("pstate-base");
+ }
+
+ String const& Context::
+ epstate_member (SemanticGraph::Compositor& c)
+ {
+ return c.context ().get<String> ("pstate-member");
+ }
+
+ String const& Context::
+ epskel (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("p:name");
+ }
+
+ String const& Context::
+ eppresent (SemanticGraph::Compositor& c)
+ {
+ return c.context ().get<String> ("p:present");
+ }
+
+ String const& Context::
+ epnext (SemanticGraph::Compositor& c)
+ {
+ return c.context ().get<String> ("p:next");
+ }
+
+ String const& Context::
+ eptag (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("p:tag");
+ }
+
+ String const& Context::
+ eparm (SemanticGraph::Choice& c)
+ {
+ return c.context ().get<String> ("p:arm");
+ }
+
+ String const& Context::
+ eparm_tag (SemanticGraph::Choice& c)
+ {
+ return c.context ().get<String> ("p:arm-tag");
+ }
+
+ // Serializer
+ //
+ String const& Context::
+ sret_type (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("s:ret-type");
+ }
+
+ String const& Context::
+ sarg_type (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("s:arg-type");
+ }
+
+ String const& Context::
+ esname (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("s:name");
+ }
+
+ String const& Context::
+ esname (SemanticGraph::Attribute& a)
+ {
+ return a.context ().get<String> ("s:name");
+ }
+
+ String const& Context::
+ esimpl (SemanticGraph::Type& t)
+ {
+ // Use s:impl instead of simpl because C++/Serializer assigns impl
+ // names to the built-in types.
+ //
+ return t.context ().get<String> ("s:impl");
+ }
+
+ String const& Context::
+ esimpl_custom (SemanticGraph::Type& t)
+ {
+ SemanticGraph::Context& c (t.context ());
+
+ if (!c.count ("s:impl-base"))
+ return c.get<String> ("s:impl");
+ else
+ return c.get<String> ("s:impl-base");
+ }
+
+ String const& Context::
+ esstate (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("sstate");
+ }
+
+ String const& Context::
+ esstate_type (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("sstate-type");
+ }
+
+ String const& Context::
+ esstate_member (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("sstate-member");
+ }
+
+ String const& Context::
+ esstate_member (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("sstate-member");
+ }
+
+ String const& Context::
+ esstate_member_end (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("sstate-member-end");
+ }
+
+ String const& Context::
+ esskel (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("s:name");
+ }
+
+ String const& Context::
+ espresent (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("s:present");
+ }
+
+ String const& Context::
+ espresent (SemanticGraph::Attribute& a)
+ {
+ return a.context ().get<String> ("s:present");
+ }
+
+ String const& Context::
+ esnext (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("s:next");
+ }
+
+ String const& Context::
+ estag (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("s:tag");
+ }
+
+ String const& Context::
+ esarm (SemanticGraph::Choice& c)
+ {
+ return c.context ().get<String> ("s:arm");
+ }
+
+ String const& Context::
+ esarm_tag (SemanticGraph::Choice& c)
+ {
+ return c.context ().get<String> ("s:arm-tag");
+ }
+
+ //
+ //
+ String Context::
+ scope (SemanticGraph::Compositor& c, Boolean fq) const
+ {
+ using namespace SemanticGraph;
+
+ String r;
+
+ Compositor* p (&c);
+
+ while (!p->contained_compositor_p ())
+ {
+ p = &p->contained_particle ().compositor ();
+
+ if (!p->context ().count ("type"))
+ continue; // See-through compositor.
+
+ if (!r)
+ r = etype (*p);
+ else
+ {
+ String tmp;
+ tmp.swap (r);
+ r = etype (*p);
+ r += L"::";
+ r += tmp;
+ }
+ }
+
+ Complex& t (
+ dynamic_cast<Complex&> (
+ p->contained_compositor ().container ()));
+
+ if (!r)
+ r = fq ? fq_name (t) : ename (t);
+ else
+ {
+ String tmp;
+ tmp.swap (r);
+ r = fq ? fq_name (t) : ename (t);
+ r += L"::";
+ r += tmp;
+ }
+
+ return r;
+ }
+
+ String Context::
+ scope (SemanticGraph::Element& e, Boolean fq) const
+ {
+ SemanticGraph::Compositor& c (e.contained_particle ().compositor ());
+
+ if (!c.context ().count ("type"))
+ return scope (c, fq);
+ else
+ return scope (c, fq) + L"::" + etype (c);
+ }
+
+ String Context::
+ scope (SemanticGraph::Attribute& a, Boolean fq) const
+ {
+ using SemanticGraph::Complex;
+
+ Complex& t (dynamic_cast<Complex&> (a.scope ()));
+ return fq ? fq_name (t) : ename (t);
+ }
+
+ Void Context::
+ close_ns ()
+ {
+ for (Size i (0), n (ns_stack.size () - 1); i < n; ++i)
+ os << "}";
+ }
+
+ Void Context::
+ open_ns ()
+ {
+ for (NamespaceStack::Iterator i (ns_stack.begin () + 1);
+ i != ns_stack.end ();
+ ++i)
+ {
+ os << "namespace " << *i
+ << "{";
+ }
+ }
+
+ // Namespace
+ //
+ Namespace::
+ Namespace (Context& c, Boolean track_scope)
+ : CXX::Namespace (c, track_scope ? this : 0), ctx_ (c)
+ {
+ }
+
+ Void Namespace::
+ enter (String const& name)
+ {
+ ctx_.ns_stack.push_back (name);
+ }
+
+ Void Namespace::
+ leave ()
+ {
+ ctx_.ns_stack.pop_back ();
+ }
+
+ // Includes
+ //
+ Void TypeForward::
+ traverse (SemanticGraph::Type& t)
+ {
+ os << "class " << ename (t) << ";";
+ }
+
+ Void Includes::
+ traverse_ (SemanticGraph::Uses& u)
+ {
+ // Support for weak (forward) inclusion used in the file-per-type
+ // compilation model.
+ //
+ Type t (type_);
+ Boolean weak (u.context ().count ("weak"));
+
+ if (weak && (t == header || t == impl_header))
+ {
+ // Generate forward declarations. We don't really need them
+ // in the impl files.
+ //
+ if (t == impl_header)
+ return;
+
+ if (forward_)
+ t = forward;
+ else
+ {
+ schema_.dispatch (u.schema ());
+ return;
+ }
+ }
+
+ if (t == source && !weak)
+ return;
+
+ SemanticGraph::Path path (u.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;
+
+ switch (t)
+ {
+ case forward:
+ {
+ inc_path = ctx_.fwd_expr->merge (path_str);
+ break;
+ }
+ case header:
+ case impl_header:
+ case source:
+ {
+ inc_path = ctx_.hxx_expr->merge (path_str);
+ break;
+ }
+ case inline_:
+ {
+ if (weak)
+ {
+ inc_path = ctx_.hxx_expr->merge (path_str);
+ ctx_.os << "#include " << ctx_.process_include_path (inc_path)
+ << endl;
+ }
+
+ inc_path = ctx_.ixx_expr->merge (path_str);
+ break;
+ }
+ }
+
+ ctx_.os << "#include " << ctx_.process_include_path (inc_path) << endl
+ << endl;
+ }
+ }
+}
diff --git a/xsde/cxx/hybrid/elements.hxx b/xsde/cxx/hybrid/elements.hxx
new file mode 100644
index 0000000..816c80f
--- /dev/null
+++ b/xsde/cxx/hybrid/elements.hxx
@@ -0,0 +1,1880 @@
+// file : xsde/cxx/hybrid/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_ELEMENTS_HXX
+#define CXX_HYBRID_ELEMENTS_HXX
+
+#include <sstream>
+
+#include <cult/containers/deque.hxx>
+
+#include <backend-elements/regex.hxx>
+
+#include <cxx/elements.hxx>
+
+#include <cxx/hybrid/cli.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ //
+ //
+ class Context: public CXX::Context
+ {
+ public:
+ typedef BackendElements::Regex::Expression<Char> Regex;
+
+ public:
+ Context (std::wostream&,
+ SemanticGraph::Schema&,
+ CLI::Options const&,
+ Regex const* fwd_expr,
+ Regex const* hxx_expr,
+ Regex const* ixx_expr);
+
+ protected:
+ Context (Context& c)
+ : CXX::Context (c),
+ options (c.options),
+ exceptions (c.exceptions),
+ stl (c.stl),
+ poly_code (c.poly_code),
+ poly_runtime (c.poly_runtime),
+ reset (c.reset),
+ mixin (c.mixin),
+ tiein (c.tiein),
+ fwd_expr (c.fwd_expr),
+ hxx_expr (c.hxx_expr),
+ ixx_expr (c.ixx_expr),
+ ns_stack (c.ns_stack)
+ {
+ }
+
+ Context (Context& c, std::wostream& o)
+ : CXX::Context (c, o),
+ options (c.options),
+ exceptions (c.exceptions),
+ stl (c.stl),
+ poly_code (c.poly_code),
+ poly_runtime (c.poly_runtime),
+ reset (c.reset),
+ mixin (c.mixin),
+ tiein (c.tiein),
+ fwd_expr (c.fwd_expr),
+ hxx_expr (c.hxx_expr),
+ ixx_expr (c.ixx_expr),
+ ns_stack (c.ns_stack)
+ {
+ }
+
+ public:
+ using CXX::Context::ename;
+
+ static String const&
+ ename (SemanticGraph::Compositor& c)
+ {
+ return c.context ().get<String> ("name");
+ }
+
+ static String const&
+ etype (SemanticGraph::Compositor& c)
+ {
+ return c.context ().get<String> ("type");
+ }
+
+ static String const&
+ emember (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("member");
+ }
+
+ static String const&
+ emember (SemanticGraph::Attribute& a)
+ {
+ return a.context ().get<String> ("member");
+ }
+
+ // Optional.
+ //
+ static String const&
+ epresent (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("present");
+ }
+
+ static String const&
+ epresent (SemanticGraph::Attribute& a)
+ {
+ return a.context ().get<String> ("present");
+ }
+
+ static String const&
+ epresent_member (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("present-member");
+ }
+
+ static String const&
+ epresent_member (SemanticGraph::Attribute& a)
+ {
+ return a.context ().get<String> ("present-member");
+ }
+
+ // Sequence.
+ //
+ static String const&
+ esequence (SemanticGraph::Element& e)
+ {
+ return e.context ().get<String> ("sequence");
+ }
+
+ static String const&
+ esequence (SemanticGraph::Compositor& c)
+ {
+ return c.context ().get<String> ("sequence");
+ }
+
+ static String const&
+ eiterator (SemanticGraph::Element& e)
+ {
+ return e.context ().get<String> ("iterator");
+ }
+
+ static String const&
+ eiterator (SemanticGraph::Compositor& c)
+ {
+ return c.context ().get<String> ("iterator");
+ }
+
+ static String const&
+ econst_iterator (SemanticGraph::Element& e)
+ {
+ return e.context ().get<String> ("const-iterator");
+ }
+
+ static String const&
+ econst_iterator (SemanticGraph::Compositor& c)
+ {
+ return c.context ().get<String> ("const-iterator");
+ }
+
+ // Choice.
+ //
+ static String const&
+ etag (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("tag");
+ }
+
+ static String const&
+ earm (SemanticGraph::Choice& c)
+ {
+ return c.context ().get<String> ("arm");
+ }
+
+ static String const&
+ earm_tag (SemanticGraph::Choice& c)
+ {
+ return c.context ().get<String> ("arm-tag");
+ }
+
+ static UnsignedLong const&
+ arm_tag_count (SemanticGraph::Choice& c)
+ {
+ return c.context ().get<UnsignedLong> ("arm-tag-count");
+ }
+
+ static String const&
+ earm_member (SemanticGraph::Choice& c)
+ {
+ return c.context ().get<String> ("arm-member");
+ }
+
+ // Custom data.
+ //
+ static String const&
+ ecd_name (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("cd-name");
+ }
+
+ static String const&
+ ecd_name (SemanticGraph::Compositor& c)
+ {
+ return c.context ().get<String> ("cd-name");
+ }
+
+ static String const&
+ ecd_member (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("cd-member");
+ }
+
+ static String const&
+ ecd_member (SemanticGraph::Compositor& c)
+ {
+ return c.context ().get<String> ("cd-member");
+ }
+
+ static String const&
+ ecd_sequence (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("cd-sequence");
+ }
+
+ static String const&
+ ecd_sequence (SemanticGraph::Compositor& c)
+ {
+ return c.context ().get<String> ("cd-sequence");
+ }
+
+ static String const&
+ ecd_iterator (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("cd-iterator");
+ }
+
+ static String const&
+ ecd_iterator (SemanticGraph::Compositor& c)
+ {
+ return c.context ().get<String> ("cd-iterator");
+ }
+
+ static String const&
+ ecd_const_iterator (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("cd-const-iterator");
+ }
+
+ static String const&
+ ecd_const_iterator (SemanticGraph::Compositor& c)
+ {
+ return c.context ().get<String> ("cd-const-iterator");
+ }
+
+ // Parser
+ //
+ public:
+ static String const&
+ pret_type (SemanticGraph::Type&);
+
+ static String const&
+ parg_type (SemanticGraph::Type&);
+
+ static String const&
+ post_name (SemanticGraph::Type&);
+
+ static String const&
+ pre_impl_name (SemanticGraph::Type&);
+
+ // Names
+ //
+ static String const&
+ epname (SemanticGraph::Particle&);
+
+ static String const&
+ epname (SemanticGraph::Attribute&);
+
+ static String const&
+ epimpl (SemanticGraph::Type&);
+
+ static String const&
+ epimpl_custom (SemanticGraph::Type&);
+
+ static String const&
+ epskel (SemanticGraph::Type&);
+
+ // Optional.
+ //
+ static String const&
+ eppresent (SemanticGraph::Compositor&);
+
+ // Sequence.
+ //
+ static String const&
+ epnext (SemanticGraph::Compositor&);
+
+ // Choice.
+ //
+ static String const&
+ eptag (SemanticGraph::Particle&);
+
+ static String const&
+ eparm (SemanticGraph::Choice&);
+
+ static String const&
+ eparm_tag (SemanticGraph::Choice&);
+
+ // State
+ //
+ static String const&
+ epstate (SemanticGraph::Type&);
+
+ static String const&
+ epstate_type (SemanticGraph::Type&);
+
+ static String const&
+ epstate_base (SemanticGraph::Type&);
+
+ static String const&
+ epstate_member (SemanticGraph::Type&);
+
+ static String const&
+ epstate_member (SemanticGraph::Compositor&);
+
+ // Serializer
+ //
+ public:
+ static String const&
+ sret_type (SemanticGraph::Type&);
+
+ static String const&
+ sarg_type (SemanticGraph::Type&);
+
+ // Names
+ //
+ static String const&
+ esname (SemanticGraph::Particle&);
+
+ static String const&
+ esname (SemanticGraph::Attribute&);
+
+ static String const&
+ esimpl (SemanticGraph::Type&);
+
+ static String const&
+ esimpl_custom (SemanticGraph::Type&);
+
+ static String const&
+ esskel (SemanticGraph::Type&);
+
+ // Optional.
+ //
+ static String const&
+ espresent (SemanticGraph::Particle&);
+
+ static String const&
+ espresent (SemanticGraph::Attribute&);
+
+ // Sequence.
+ //
+ static String const&
+ esnext (SemanticGraph::Particle&);
+
+ // Choice.
+ //
+ static String const&
+ estag (SemanticGraph::Particle&);
+
+ static String const&
+ esarm (SemanticGraph::Choice&);
+
+ static String const&
+ esarm_tag (SemanticGraph::Choice&);
+
+ // State
+ //
+ static String const&
+ esstate (SemanticGraph::Type&);
+
+ static String const&
+ esstate_type (SemanticGraph::Type&);
+
+ static String const&
+ esstate_member (SemanticGraph::Type&);
+
+ static String const&
+ esstate_member (SemanticGraph::Particle&);
+
+ static String const&
+ esstate_member_end (SemanticGraph::Particle&);
+
+ public:
+ String
+ scope (SemanticGraph::Compositor& c) const
+ {
+ return scope (c, false);
+ }
+
+ String
+ scope (SemanticGraph::Element& e) const
+ {
+ return scope (e, false);
+ }
+
+ String
+ scope (SemanticGraph::Attribute& a) const
+ {
+ return scope (a, false);
+ }
+
+ String
+ fq_scope (SemanticGraph::Compositor& c) const
+ {
+ return scope (c, true);
+ }
+
+ String
+ fq_scope (SemanticGraph::Element& e) const
+ {
+ return scope (e, true);
+ }
+
+ String
+ fq_scope (SemanticGraph::Attribute& a) const
+ {
+ return scope (a, true);
+ }
+
+ private:
+ String
+ scope (SemanticGraph::Compositor&, Boolean fq) const;
+
+ String
+ scope (SemanticGraph::Element&, Boolean fq) const;
+
+ String
+ scope (SemanticGraph::Attribute&, Boolean fq) const;
+
+ public:
+ Boolean
+ restriction_p (SemanticGraph::Complex& c) const
+ {
+ if (c.inherits_p () &&
+ c.inherits ().is_a<SemanticGraph::Restricts> ())
+ {
+ // Restriction of anyType is a special case.
+ //
+ return !c.inherits ().base ().is_a<SemanticGraph::AnyType> ();
+ }
+
+ return false;
+ }
+
+ public:
+ static Boolean
+ fixed_length (SemanticGraph::Type& t)
+ {
+ return t.context ().get<Boolean> ("fixed");
+ }
+
+ static Boolean
+ fixed_length (SemanticGraph::Compositor& c)
+ {
+ return c.context ().get<Boolean> ("fixed");
+ }
+
+ public:
+ Void
+ close_ns ();
+
+ Void
+ open_ns ();
+
+ public:
+ typedef
+ Cult::Containers::Deque<String>
+ NamespaceStack;
+
+ public:
+ CLI::Options const& options;
+
+ Boolean exceptions;
+ Boolean stl;
+ Boolean poly_code;
+ Boolean poly_runtime;
+ Boolean reset;
+ Boolean mixin;
+ Boolean tiein;
+
+ Regex const* fwd_expr;
+ Regex const* hxx_expr;
+ Regex const* ixx_expr;
+
+ NamespaceStack& ns_stack;
+
+ private:
+ NamespaceStack ns_stack_;
+ };
+
+ //
+ //
+ struct Namespace: CXX::Namespace, CXX::Namespace::ScopeTracker
+ {
+ Namespace (Context&, Boolean track_scope = false);
+
+ protected:
+ virtual Void
+ enter (String const& name);
+
+ virtual Void
+ leave ();
+
+ protected:
+ Context& ctx_;
+ };
+
+ //
+ //
+ struct FundamentalType: Traversal::Fundamental::Byte,
+ Traversal::Fundamental::UnsignedByte,
+ Traversal::Fundamental::Short,
+ Traversal::Fundamental::UnsignedShort,
+ Traversal::Fundamental::Int,
+ Traversal::Fundamental::UnsignedInt,
+ Traversal::Fundamental::Long,
+ Traversal::Fundamental::UnsignedLong,
+ Traversal::Fundamental::Integer,
+ Traversal::Fundamental::NonPositiveInteger,
+ Traversal::Fundamental::NonNegativeInteger,
+ Traversal::Fundamental::PositiveInteger,
+ Traversal::Fundamental::NegativeInteger,
+
+ Traversal::Fundamental::Boolean,
+
+ Traversal::Fundamental::Float,
+ Traversal::Fundamental::Double,
+ Traversal::Fundamental::Decimal
+
+ {
+ FundamentalType (Boolean& result)
+ : r_ (result)
+ {
+ }
+
+ // Integral types.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Byte&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedByte&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Short&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedShort&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Int&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedInt&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Long&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedLong&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Integer&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonPositiveInteger&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonNegativeInteger&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::PositiveInteger&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NegativeInteger&)
+ {
+ r_ = true;
+ }
+
+ // Boolean.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Boolean&)
+ {
+ r_ = true;
+ }
+
+ // Floats.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Float&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Double&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Decimal&)
+ {
+ r_ = true;
+ }
+
+ private:
+ Boolean& r_;
+ };
+
+ //
+ //
+ struct StringType: Traversal::Fundamental::String,
+ Traversal::Fundamental::NormalizedString,
+ Traversal::Fundamental::Token,
+ Traversal::Fundamental::Name,
+ Traversal::Fundamental::NameToken,
+ Traversal::Fundamental::NCName,
+ Traversal::Fundamental::Language,
+ Traversal::Fundamental::Id,
+ Traversal::Fundamental::IdRef,
+ Traversal::Fundamental::AnyURI,
+ Traversal::Fundamental::Entity
+ {
+ StringType (Boolean& result)
+ : r_ (result)
+ {
+ }
+
+ 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;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Id&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRef&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::AnyURI&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entity&)
+ {
+ r_ = true;
+ }
+
+ private:
+ Boolean& r_;
+ };
+
+
+ //
+ //
+ struct TypeName : Traversal::Type,
+ Traversal::AnyType,
+ Traversal::AnySimpleType,
+
+ Traversal::Fundamental::Byte,
+ Traversal::Fundamental::UnsignedByte,
+ Traversal::Fundamental::Short,
+ Traversal::Fundamental::UnsignedShort,
+ Traversal::Fundamental::Int,
+ Traversal::Fundamental::UnsignedInt,
+ Traversal::Fundamental::Long,
+ Traversal::Fundamental::UnsignedLong,
+ Traversal::Fundamental::Integer,
+ Traversal::Fundamental::NonPositiveInteger,
+ Traversal::Fundamental::NonNegativeInteger,
+ Traversal::Fundamental::PositiveInteger,
+ Traversal::Fundamental::NegativeInteger,
+
+ Traversal::Fundamental::Boolean,
+
+ Traversal::Fundamental::Float,
+ Traversal::Fundamental::Double,
+ Traversal::Fundamental::Decimal,
+
+ Traversal::Fundamental::String,
+ Traversal::Fundamental::NormalizedString,
+ Traversal::Fundamental::Token,
+ Traversal::Fundamental::Name,
+ Traversal::Fundamental::NameToken,
+ Traversal::Fundamental::NameTokens,
+ Traversal::Fundamental::NCName,
+ Traversal::Fundamental::Language,
+
+ Traversal::Fundamental::QName,
+
+ Traversal::Fundamental::Id,
+ Traversal::Fundamental::IdRef,
+ Traversal::Fundamental::IdRefs,
+
+ Traversal::Fundamental::AnyURI,
+
+ Traversal::Fundamental::Base64Binary,
+ Traversal::Fundamental::HexBinary,
+
+ Traversal::Fundamental::Date,
+ Traversal::Fundamental::DateTime,
+ Traversal::Fundamental::Duration,
+ Traversal::Fundamental::Day,
+ Traversal::Fundamental::Month,
+ Traversal::Fundamental::MonthDay,
+ Traversal::Fundamental::Year,
+ Traversal::Fundamental::YearMonth,
+ Traversal::Fundamental::Time,
+
+ Traversal::Fundamental::Entity,
+ Traversal::Fundamental::Entities,
+
+ Context
+ {
+ enum Use
+ {
+ base,
+ ro_ret,
+ ret,
+ arg,
+ var,
+ seq
+ };
+
+ TypeName (Context& c, Use use)
+ : Context (c), use_ (use)
+ {
+ if (use == base)
+ xs_ns_ = xs_ns_name ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& t)
+ {
+ type (t);
+ }
+
+ // anyType & anySimpleType.
+ //
+ virtual Void
+ traverse (SemanticGraph::AnyType& t)
+ {
+ type (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnySimpleType& t)
+ {
+ type (t);
+ }
+
+ // Boolean.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Boolean&)
+ {
+ if (use_ != base)
+ fund_type ("bool");
+ else
+ os << xs_ns_ << "::boolean_base";
+ }
+
+ // Integral types.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Byte&)
+ {
+ if (use_ != base)
+ fund_type ("signed char");
+ else
+ os << xs_ns_ << "::byte_base";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedByte&)
+ {
+ if (use_ != base)
+ fund_type ("unsigned char");
+ else
+ os << xs_ns_ << "::unsigned_byte_base";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Short&)
+ {
+ if (use_ != base)
+ fund_type ("short");
+ else
+ os << xs_ns_ << "::short_base";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedShort&)
+ {
+ if (use_ != base)
+ fund_type ("unsigned short");
+ else
+ os << xs_ns_ << "::unsigned_short_base";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Int&)
+ {
+ if (use_ != base)
+ fund_type ("int");
+ else
+ os << xs_ns_ << "::int_base";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedInt&)
+ {
+ if (use_ != base)
+ fund_type ("unsigned int");
+ else
+ os << xs_ns_ << "::unsigned_int_base";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Long&)
+ {
+ if (use_ != base)
+ {
+ if (options.value<CLI::no_long_long> ())
+ fund_type ("long");
+ else
+ fund_type ("long long");
+ }
+ else
+ os << xs_ns_ << "::long_base";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedLong&)
+ {
+ if (use_ != base)
+ {
+ if (options.value<CLI::no_long_long> ())
+ fund_type ("unsigned long");
+ else
+ fund_type ("unsigned long long");
+ }
+ else
+ os << xs_ns_ << "::unsigned_long_base";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Integer&)
+ {
+ if (use_ != base)
+ fund_type ("long");
+ else
+ os << xs_ns_ << "::integer_base";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonPositiveInteger&)
+ {
+ if (use_ != base)
+ fund_type ("long");
+ else
+ os << xs_ns_ << "::non_positive_integer_base";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonNegativeInteger&)
+ {
+ if (use_ != base)
+ fund_type ("unsigned long");
+ else
+ os << xs_ns_ << "::non_negative_integer_base";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::PositiveInteger&)
+ {
+ if (use_ != base)
+ fund_type ("unsigned long");
+ else
+ os << xs_ns_ << "::positive_integer_base";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NegativeInteger&)
+ {
+ if (use_ != base)
+ fund_type ("long");
+ else
+ os << xs_ns_ << "::negative_integer_base";
+ }
+
+ // Floats.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Float&)
+ {
+ if (use_ != base)
+ fund_type ("float");
+ else
+ os << xs_ns_ << "::float_base";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Double&)
+ {
+ if (use_ != base)
+ fund_type ("double");
+ else
+ os << xs_ns_ << "::double_base";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Decimal&)
+ {
+ if (use_ != base)
+ fund_type ("double");
+ else
+ os << xs_ns_ << "::decimal_base";
+ }
+
+ // Strings.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::String&)
+ {
+ if (stl || use_ != base)
+ string_type ();
+ else
+ os << xs_ns_ << "::string_base";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NormalizedString&)
+ {
+ if (stl || use_ != base)
+ string_type ();
+ else
+ os << xs_ns_ << "::normalized_string_base";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Token&)
+ {
+ if (stl || use_ != base)
+ string_type ();
+ else
+ os << xs_ns_ << "::token_base";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameToken&)
+ {
+ if (stl || use_ != base)
+ string_type ();
+ else
+ os << xs_ns_ << "::nmtoken_base";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameTokens& t)
+ {
+ type (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Name&)
+ {
+ if (stl || use_ != base)
+ string_type ();
+ else
+ os << xs_ns_ << "::name_base";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NCName&)
+ {
+ if (stl || use_ != base)
+ string_type ();
+ else
+ os << xs_ns_ << "::ncname_base";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Language&)
+ {
+ if (stl || use_ != base)
+ string_type ();
+ else
+ os << xs_ns_ << "::language_base";
+ }
+
+
+ // Qualified name.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::QName& t)
+ {
+ type (t);
+ }
+
+
+ // ID/IDREF.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Id&)
+ {
+ if (stl || use_ != base)
+ string_type ();
+ else
+ os << xs_ns_ << "::id_base";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRef&)
+ {
+ if (stl || use_ != base)
+ string_type ();
+ else
+ os << xs_ns_ << "::idref_base";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRefs& t)
+ {
+ type (t);
+ }
+
+ // URI.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::AnyURI&)
+ {
+ if (stl || use_ != base)
+ string_type ();
+ else
+ os << xs_ns_ << "::uri_base";
+ }
+
+ // Binary.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Base64Binary& t)
+ {
+ type (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::HexBinary& t)
+ {
+ type (t);
+ }
+
+
+ // Date/time.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Date& t)
+ {
+ type (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::DateTime& t)
+ {
+ type (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Duration& t)
+ {
+ type (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Day& t)
+ {
+ type (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Month& t)
+ {
+ type (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::MonthDay& t)
+ {
+ type (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Year& t)
+ {
+ type (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::YearMonth& t)
+ {
+ type (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Time& t)
+ {
+ type (t);
+ }
+
+ // Entity.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entity&)
+ {
+ if (stl || use_ != base)
+ string_type ();
+ else
+ os << xs_ns_ << "::entity_base";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entities& t)
+ {
+ type (t);
+ }
+
+ private:
+ Void
+ type (SemanticGraph::Type& t)
+ {
+ String fq (fq_name (t));
+
+ switch (use_)
+ {
+ case base:
+ {
+ os << fq;
+ break;
+ }
+ case ro_ret:
+ {
+ os << "const " << fq << "&";
+ break;
+ }
+ case ret:
+ {
+ os << fq << "&";
+ break;
+ }
+ case arg:
+ {
+ if (fixed_length (t))
+ os << "const " << fq << "&";
+ else
+ os << fq << "*";
+
+ break;
+ }
+ case var:
+ {
+ if (fixed_length (t))
+ os << fq;
+ else
+ os << fq << "*";
+
+ break;
+ }
+ case seq:
+ {
+ if (fixed_length (t))
+ os << "::xsde::cxx::hybrid::fix_seq";
+ else
+ os << "::xsde::cxx::hybrid::var_seq";
+
+ os << "< " << fq << " >";
+ break;
+ }
+ }
+ }
+
+ Void
+ fund_type (Char const* name)
+ {
+ switch (use_)
+ {
+ case ret:
+ {
+ os << name << "&";
+ break;
+ }
+ case seq:
+ {
+ os << "::xsde::cxx::hybrid::pod_seq< " << name << " >";
+ break;
+ }
+ default:
+ {
+ os << name;
+ break;
+ }
+ }
+ }
+
+ Void
+ string_type ()
+ {
+ switch (use_)
+ {
+ case base:
+ {
+ // Non-STL case is handled by the caller.
+ //
+ os << "::std::string";
+ break;
+ }
+ case ro_ret:
+ {
+ if (stl)
+ os << "const ::std::string&";
+ else
+ os << "const char*";
+ break;
+ }
+ case ret:
+ {
+ if (stl)
+ os << "::std::string&";
+ else
+ os << "char*";
+ break;
+ }
+ case arg:
+ {
+ if (stl)
+ os << "const ::std::string&";
+ else
+ os << "char*";
+ break;
+ }
+ case var:
+ {
+ if (stl)
+ os << "::std::string";
+ else
+ os << "char*";
+ break;
+ }
+ case seq:
+ {
+ os << "::xsde::cxx::hybrid::str_seq";
+ break;
+ }
+ }
+ }
+
+ private:
+ Use use_;
+ String xs_ns_;
+ };
+
+ struct TypeOps: Traversal::Type,
+ Traversal::AnyType,
+ Traversal::AnySimpleType,
+
+ Traversal::Fundamental::Byte,
+ Traversal::Fundamental::UnsignedByte,
+ Traversal::Fundamental::Short,
+ Traversal::Fundamental::UnsignedShort,
+ Traversal::Fundamental::Int,
+ Traversal::Fundamental::UnsignedInt,
+ Traversal::Fundamental::Long,
+ Traversal::Fundamental::UnsignedLong,
+ Traversal::Fundamental::Integer,
+ Traversal::Fundamental::NonPositiveInteger,
+ Traversal::Fundamental::NonNegativeInteger,
+ Traversal::Fundamental::PositiveInteger,
+ Traversal::Fundamental::NegativeInteger,
+
+ Traversal::Fundamental::Boolean,
+
+ Traversal::Fundamental::Float,
+ Traversal::Fundamental::Double,
+ Traversal::Fundamental::Decimal,
+
+ Traversal::Fundamental::String,
+ Traversal::Fundamental::NormalizedString,
+ Traversal::Fundamental::Token,
+ Traversal::Fundamental::Name,
+ Traversal::Fundamental::NameToken,
+ Traversal::Fundamental::NameTokens,
+ Traversal::Fundamental::NCName,
+ Traversal::Fundamental::Language,
+
+ Traversal::Fundamental::QName,
+
+ Traversal::Fundamental::Id,
+ Traversal::Fundamental::IdRef,
+ Traversal::Fundamental::IdRefs,
+
+ Traversal::Fundamental::AnyURI,
+
+ Traversal::Fundamental::Base64Binary,
+ Traversal::Fundamental::HexBinary,
+
+ Traversal::Fundamental::Date,
+ Traversal::Fundamental::DateTime,
+ Traversal::Fundamental::Duration,
+ Traversal::Fundamental::Day,
+ Traversal::Fundamental::Month,
+ Traversal::Fundamental::MonthDay,
+ Traversal::Fundamental::Year,
+ Traversal::Fundamental::YearMonth,
+ Traversal::Fundamental::Time,
+
+ Traversal::Fundamental::Entity,
+ Traversal::Fundamental::Entities,
+
+ Context
+ {
+ enum Use
+ {
+ deref,
+ delete_
+ };
+
+ TypeOps (Context& c, Use use)
+ : Context (c), use_ (use)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& t)
+ {
+ type (t);
+ }
+
+ // anyType & anySimpleType.
+ //
+ virtual Void
+ traverse (SemanticGraph::AnyType& t)
+ {
+ type (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnySimpleType& t)
+ {
+ type (t);
+ }
+
+ // Boolean.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Boolean&)
+ {
+ fund_type ();
+ }
+
+ // Integral types.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Byte&)
+ {
+ fund_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedByte&)
+ {
+ fund_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Short&)
+ {
+ fund_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedShort&)
+ {
+ fund_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Int&)
+ {
+ fund_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedInt&)
+ {
+ fund_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Long&)
+ {
+ fund_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedLong&)
+ {
+ fund_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Integer&)
+ {
+ fund_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonPositiveInteger&)
+ {
+ fund_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonNegativeInteger&)
+ {
+ fund_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::PositiveInteger&)
+ {
+ fund_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NegativeInteger&)
+ {
+ fund_type ();
+ }
+
+ // Floats.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Float&)
+ {
+ fund_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Double&)
+ {
+ fund_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Decimal&)
+ {
+ fund_type ();
+ }
+
+ // Strings.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::String&)
+ {
+ string_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NormalizedString&)
+ {
+ string_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Token&)
+ {
+ string_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameToken&)
+ {
+ string_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameTokens& t)
+ {
+ type (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Name&)
+ {
+ string_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NCName&)
+ {
+ string_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Language&)
+ {
+ string_type ();
+ }
+
+ // Qualified name.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::QName& t)
+ {
+ type (t);
+ }
+
+ // ID/IDREF.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Id&)
+ {
+ string_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRef&)
+ {
+ string_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRefs& t)
+ {
+ type (t);
+ }
+
+ // URI.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::AnyURI&)
+ {
+ string_type ();
+ }
+
+ // Binary.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Base64Binary& t)
+ {
+ type (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::HexBinary& t)
+ {
+ type (t);
+ }
+
+ // Date/time.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Date& t)
+ {
+ type (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::DateTime& t)
+ {
+ type (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Duration& t)
+ {
+ type (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Day& t)
+ {
+ type (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Month& t)
+ {
+ type (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::MonthDay& t)
+ {
+ type (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Year& t)
+ {
+ type (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::YearMonth& t)
+ {
+ type (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Time& t)
+ {
+ type (t);
+ }
+
+ // Entity.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entity&)
+ {
+ string_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entities& t)
+ {
+ type (t);
+ }
+
+ private:
+ Void
+ type (SemanticGraph::Type& t)
+ {
+ switch (use_)
+ {
+ case deref:
+ {
+ if (!fixed_length (t))
+ os << "*";
+
+ break;
+ }
+ case delete_:
+ {
+ os << "delete";
+ break;
+ }
+ }
+ }
+
+ Void
+ fund_type ()
+ {
+ switch (use_)
+ {
+ case deref:
+ {
+ break;
+ }
+ case delete_:
+ {
+ os << "delete";
+ break;
+ }
+ }
+ }
+
+ Void
+ string_type ()
+ {
+ switch (use_)
+ {
+ case deref:
+ {
+ break;
+ }
+ case delete_:
+ {
+ if (stl)
+ os << "delete";
+ else
+ os << "delete[]";
+ break;
+ }
+ }
+ }
+
+ private:
+ Use use_;
+ };
+
+ //
+ //
+ struct TypeForward: Traversal::Type, Context
+ {
+ TypeForward (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& t);
+ };
+
+ struct Includes : Traversal::Imports,
+ Traversal::Includes
+ {
+ enum Type
+ {
+ forward,
+ header,
+ impl_header,
+ inline_,
+ source
+ };
+
+ Includes (Context& c, Type type)
+ : ctx_ (c),
+ type_ (type),
+ forward_ (c.options.value<CLI::generate_forward> ()),
+ namespace_ (c),
+ type_forward_ (c)
+ {
+ schema_ >> schema_names_ >> namespace_ >> names_ >> type_forward_;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Imports& i)
+ {
+ traverse_ (i);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Includes& i)
+ {
+ traverse_ (i);
+ }
+
+ private:
+ Void
+ traverse_ (SemanticGraph::Uses&);
+
+ private:
+ Context& ctx_;
+ Type type_;
+ Boolean forward_;
+
+ Traversal::Schema schema_;
+ Traversal::Names schema_names_;
+ Namespace namespace_;
+ Traversal::Names names_;
+ TypeForward type_forward_;
+ };
+
+ // Test whether there are any aggregates to be generated.
+ //
+ struct AggregateTest: Traversal::Type, Traversal::Element
+ {
+ AggregateTest (Boolean& generate, Char const* key)
+ : gen_ (generate), key_ (key)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& t)
+ {
+ if (!gen_ && t.context ().count (key_))
+ gen_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (!gen_ && e.context ().count (key_))
+ gen_ = true;
+ }
+
+ private:
+ Boolean& gen_;
+ Char const* key_;
+ };
+ }
+}
+
+#endif // CXX_HYBRID_ELEMENTS_HXX
diff --git a/xsde/cxx/hybrid/generator.cxx b/xsde/cxx/hybrid/generator.cxx
new file mode 100644
index 0000000..b6215f9
--- /dev/null
+++ b/xsde/cxx/hybrid/generator.cxx
@@ -0,0 +1,2476 @@
+// file : xsde/cxx/hybrid/generator.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/hybrid/elements.hxx>
+#include <cxx/hybrid/generator.hxx>
+
+#include <cxx/hybrid/validator.hxx>
+
+#include <cxx/hybrid/tree-size-processor.hxx>
+#include <cxx/hybrid/tree-name-processor.hxx>
+
+
+#include <cxx/hybrid/tree-forward.hxx>
+#include <cxx/hybrid/tree-header.hxx>
+#include <cxx/hybrid/tree-inline.hxx>
+#include <cxx/hybrid/tree-source.hxx>
+#include <cxx/hybrid/tree-type-map.hxx>
+
+#include <cxx/hybrid/parser-name-processor.hxx>
+#include <cxx/hybrid/parser-header.hxx>
+#include <cxx/hybrid/parser-source.hxx>
+#include <cxx/hybrid/parser-aggregate-header.hxx>
+#include <cxx/hybrid/parser-aggregate-source.hxx>
+
+#include <cxx/hybrid/serializer-name-processor.hxx>
+#include <cxx/hybrid/serializer-header.hxx>
+#include <cxx/hybrid/serializer-source.hxx>
+#include <cxx/hybrid/serializer-aggregate-header.hxx>
+#include <cxx/hybrid/serializer-aggregate-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+
+#include <backend-elements/regex.hxx>
+#include <backend-elements/indentation/cxx.hxx>
+#include <backend-elements/indentation/sloc.hxx>
+#include <backend-elements/indentation/clip.hxx>
+
+#include <cult/containers/set.hxx>
+#include <cult/containers/vector.hxx>
+
+#include <boost/filesystem/fstream.hpp>
+
+#include <iostream>
+
+#include <usage.hxx>
+
+#include "../../../libxsde/xsde/cxx/version.hxx"
+
+using std::endl;
+using std::wcerr;
+
+using namespace XSDFrontend::SemanticGraph;
+
+//
+//
+typedef
+boost::filesystem::wifstream
+WideInputFileStream;
+
+typedef
+boost::filesystem::wofstream
+WideOutputFileStream;
+
+typedef
+boost::filesystem::ifstream
+NarrowInputFileStream;
+
+namespace CXX
+{
+ namespace
+ {
+ Char const copyright_gpl[] =
+ "// Copyright (C) 2005-2009 Code Synthesis Tools CC\n"
+ "//\n"
+ "// This program was generated by CodeSynthesis XSD/e, an XML Schema\n"
+ "// to C++ data binding compiler for embedded systems.\n"
+ "//\n"
+ "// This program is free software; you can redistribute it and/or modify\n"
+ "// it under the terms of the GNU General Public License version 2 as\n"
+ "// published by the Free Software Foundation.\n"
+ "//\n"
+ "// This program is distributed in the hope that it will be useful,\n"
+ "// but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+ "// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
+ "// GNU General Public License for more details.\n"
+ "//\n"
+ "// You should have received a copy of the GNU General Public License\n"
+ "// along with this program; if not, write to the Free Software\n"
+ "// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n"
+ "//\n"
+ "//\n\n";
+
+ Char const copyright_proprietary[] =
+ "// Copyright (C) 2005-2009 Code Synthesis Tools CC\n"
+ "//\n"
+ "// This program was generated by CodeSynthesis XSD/e, an XML Schema to\n"
+ "// C++ data binding compiler for embedded systems, in the Proprietary\n"
+ "// License mode. You should have received a proprietary license from\n"
+ "// Code Synthesis Tools CC prior to generating this code. See the\n"
+ "// license text for conditions.\n"
+ "//\n\n";
+ }
+
+ namespace Hybrid
+ {
+ namespace CLI
+ {
+ extern Key no_stl = "no-stl";
+ extern Key no_iostream = "no-iostream";
+ extern Key no_exceptions = "no-exceptions";
+ extern Key no_long_long = "no-long-long";
+ extern Key generate_parser = "generate-parser";
+ extern Key generate_serializer = "generate-serializer";
+ extern Key generate_aggregate = "generate-aggregate";
+ extern Key suppress_validation = "suppress-validation";
+ extern Key suppress_parser_val = "suppress-parser-val";
+ extern Key suppress_serializer_val = "suppress-serializer-val";
+ extern Key generate_inline = "generate-inline";
+ extern Key generate_forward = "generate-forward";
+ extern Key generate_xml_schema = "generate-xml-schema";
+ extern Key extern_xml_schema = "extern-xml-schema";
+ extern Key suppress_reset = "suppress-reset";
+ extern Key reuse_style_mixin = "reuse-style-mixin";
+ extern Key custom_data = "custom-data";
+ extern Key custom_parser = "custom-parser";
+ extern Key custom_serializer = "custom-serializer";
+ extern Key root_element_first = "root-element-first";
+ extern Key root_element_last = "root-element-last";
+ extern Key root_element_all = "root-element-all";
+ extern Key root_element_none = "root-element-none";
+ extern Key root_element = "root-element";
+ extern Key root_type = "root-type";
+ extern Key output_dir = "output-dir";
+ extern Key pskel_type_suffix = "pskel-type-suffix";
+ extern Key sskel_type_suffix = "sskel-type-suffix";
+ extern Key pskel_file_suffix = "pskel-file-suffix";
+ extern Key sskel_file_suffix = "sskel-file-suffix";
+ extern Key pimpl_type_suffix = "pimpl-type-suffix";
+ extern Key simpl_type_suffix = "simpl-type-suffix";
+ extern Key pimpl_file_suffix = "pimpl-file-suffix";
+ extern Key simpl_file_suffix = "simpl-file-suffix";
+ extern Key paggr_type_suffix = "paggr-type-suffix";
+ extern Key saggr_type_suffix = "saggr-type-suffix";
+ extern Key namespace_map = "namespace-map";
+ extern Key namespace_regex = "namespace-regex";
+ extern Key namespace_regex_trace = "namespace-regex-trace";
+ extern Key reserved_name = "reserved-name";
+ extern Key include_with_brackets = "include-with-brackets";
+ extern Key include_prefix = "include-prefix";
+ extern Key include_regex = "include-regex";
+ extern Key include_regex_trace = "include-regex-trace";
+ extern Key guard_prefix = "guard-prefix";
+ extern Key hxx_suffix = "hxx-suffix";
+ extern Key ixx_suffix = "ixx-suffix";
+ extern Key cxx_suffix = "cxx-suffix";
+ extern Key fwd_suffix = "fwd-suffix";
+ extern Key hxx_regex = "hxx-regex";
+ extern Key ixx_regex = "ixx-regex";
+ extern Key cxx_regex = "cxx-regex";
+ extern Key fwd_regex = "fwd-regex";
+ extern Key hxx_prologue = "hxx-prologue";
+ extern Key ixx_prologue = "ixx-prologue";
+ extern Key cxx_prologue = "cxx-prologue";
+ extern Key fwd_prologue = "fwd-prologue";
+ extern Key prologue = "prologue";
+ extern Key hxx_epilogue = "hxx-epilogue";
+ extern Key ixx_epilogue = "ixx-epilogue";
+ extern Key cxx_epilogue = "cxx-epilogue";
+ extern Key fwd_epilogue = "fwd-epilogue";
+ extern Key epilogue = "epilogue";
+ extern Key hxx_prologue_file = "hxx-prologue-file";
+ extern Key ixx_prologue_file = "ixx-prologue-file";
+ extern Key cxx_prologue_file = "cxx-prologue-file";
+ extern Key fwd_prologue_file = "fwd-prologue-file";
+ extern Key prologue_file = "prologue-file";
+ extern Key hxx_epilogue_file = "hxx-epilogue-file";
+ extern Key ixx_epilogue_file = "ixx-epilogue-file";
+ extern Key cxx_epilogue_file = "cxx-epilogue-file";
+ extern Key fwd_epilogue_file = "fwd-epilogue-file";
+ extern Key epilogue_file = "epilogue-file";
+ extern Key show_anonymous = "show-anonymous";
+ extern Key show_sloc = "show-sloc";
+ extern Key proprietary_license = "proprietary-license";
+ }
+ }
+
+ Void Hybrid::Generator::
+ usage ()
+ {
+ std::wostream& e (wcerr);
+ ::CLI::Indent::Clip< ::CLI::OptionsUsage, WideChar> clip (e);
+
+ e << "--no-stl" << endl
+ << " Generate code that does not use STL."
+ << endl;
+
+ e << "--no-iostream" << endl
+ << " Generate code that does not use the iostream\n"
+ << " library."
+ << endl;
+
+ e << "--no-exceptions" << endl
+ << " Generate code that does not use C++ exceptions."
+ << endl;
+
+ e << "--no-long-long" << endl
+ << " Generate code that does not use the long long\n"
+ << " and unsigned long long types."
+ << endl;
+
+ e << "--generate-parser" << endl
+ << " Generate XML parsing code."
+ << endl;
+
+ e << "--generate-serializer" << endl
+ << " Generate XML serialization code."
+ << endl;
+
+ e << "--generate-aggregate" << endl
+ << " Generate parser/serializer aggregates for root\n"
+ << " elements and/or types."
+ << endl;
+
+ e << "--suppress-validation" << endl
+ << " Suppress the generation of validation code in\n"
+ << " parser and serializer."
+ << endl;
+
+ e << "--suppress-parser-val" << endl
+ << " Suppress the generation of validation code in\n"
+ << " parser."
+ << endl;
+
+ e << "--suppress-serializer-val" << endl
+ << " Suppress the generation of validation code in\n"
+ << " serializer."
+ << endl;
+
+ e << "--generate-inline" << endl
+ << " Generate certain functions inline."
+ << endl;
+
+ e << "--generate-forward" << endl
+ << " Generate forward declaration file."
+ << endl;
+
+ e << "--generate-xml-schema" << endl
+ << " Generate C++ header files as if the schema being\n"
+ << " compiled defines the XML Schema namespace."
+ << endl;
+
+ e << "--extern-xml-schema <file>" << endl
+ << " Generate code as if the XML Schema namespace was\n"
+ << " defined in <file> and xsd:included in the schema\n"
+ << " being compiled."
+ << endl;
+
+ e << "--suppress-reset" << endl
+ << " Suppress the generation of parser and serializer\n"
+ << " reset code."
+ << endl;
+
+ e << "--reuse-style-mixin" << endl
+ << " Generate code that supports the mixin base\n"
+ << " parser/serializer implementation reuse style."
+ << endl;
+
+ e << "--custom-data <type>" << endl
+ << " Add custom data to the C++ class generated for\n"
+ << " XML Schema type <type>."
+ << endl;
+
+ e << "--custom-parser <map>" << endl
+ << " Use a custom parser implementation instead of the\n"
+ << " generated version. The <map> argument is in the\n"
+ << " form type[=base[/include]], where <type> is an XML\n"
+ << " Schema type name, optional <base> is a C++ name\n"
+ << " that should be given to the generated version,\n"
+ << " and optional <include> is the header file that\n"
+ << " defines the custom implementation."
+ << endl;
+
+ e << "--custom-serializer <map>" << endl
+ << " Use a custom serializer implementation instead of\n"
+ << " the generated version. The <map> argument is in\n"
+ << " the form type[=base[/include]], where <type> is\n"
+ << " an XML Schema type name, optional <base> is a C++\n"
+ << " name that should be given to the generated\n"
+ << " version, and optional <include> is the header\n"
+ << " file that defines the custom implementation."
+ << endl;
+
+ e << "--root-element-first" << endl
+ << " Treat only the first global element as a document\n"
+ << " root."
+ << endl;
+
+ e << "--root-element-last" << endl
+ << " Treat only the last global element as a document\n"
+ << " root."
+ << endl;
+
+ e << "--root-element-all" << endl
+ << " Treat all global elements as document roots."
+ << endl;
+
+ e << "--root-element-none" << endl
+ << " Don't treat any global elements as document roots."
+ << endl;
+
+ e << "--root-element <element>" << endl
+ << " Treat only <element> as a document root. Repeat\n"
+ << " this option to specify more than one root element."
+ << endl;
+
+ e << "--root-type <type>" << endl
+ << " Generate parser/serializer aggregate for <type>.\n"
+ << " Repeat this option to specify more than one type."
+ << endl;
+
+ e << "--output-dir <dir>" << endl
+ << " Write generated files to <dir> instead of the\n"
+ << " current directory."
+ << endl;
+
+ e << "--pskel-type-suffix <sfx>" << endl
+ << " Use <sfx> instead of the default '_pskel' suffix\n"
+ << " to construct the names of generated parser\n"
+ << " skeletons."
+ << endl;
+
+ e << "--sskel-type-suffix <sfx>" << endl
+ << " Use <sfx> instead of the default '_sskel' suffix\n"
+ << " to construct the names of generated serializer\n"
+ << " skeletons."
+ << endl;
+
+ e << "--pskel-file-suffix <sfx>" << endl
+ << " Use <sfx> instead of the default '-pskel' suffix\n"
+ << " to construct the names of generated parser\n"
+ << " skeleton files."
+ << endl;
+
+ e << "--sskel-file-suffix <sfx>" << endl
+ << " Use <sfx> instead of the default '-sskel' suffix\n"
+ << " to construct the names of generated serializer\n"
+ << " skeleton files."
+ << endl;
+
+ e << "--pimpl-type-suffix <sfx>" << endl
+ << " Use <sfx> instead of the default '_pimpl' suffix\n"
+ << " to construct the names of generated parser\n"
+ << " implementations."
+ << endl;
+
+ e << "--simpl-type-suffix <sfx>" << endl
+ << " Use <sfx> instead of the default '_simpl' suffix\n"
+ << " to construct the names of generated serializer\n"
+ << " implementations."
+ << endl;
+
+ e << "--pimpl-file-suffix <sfx>" << endl
+ << " Use <sfx> instead of the default '-pimpl' suffix\n"
+ << " to construct the names of generated parser\n"
+ << " implementation files."
+ << endl;
+
+ e << "--simpl-file-suffix <sfx>" << endl
+ << " Use <sfx> instead of the default '-simpl' suffix\n"
+ << " to construct the names of generated serializer\n"
+ << " implementation files."
+ << endl;
+
+ e << "--paggr-type-suffix <sfx>" << endl
+ << " Use <sfx> instead of the default '_paggs' suffix\n"
+ << " to construct the names of generated parser\n"
+ << " aggregates."
+ << endl;
+
+ e << "--saggr-type-suffix <sfx>" << endl
+ << " Use <sfx> instead of the default '_saggr' suffix\n"
+ << " to construct the names of generated serializer\n"
+ << " aggregates."
+ << endl;
+
+ e << "--namespace-map <xns>=<cns>" << endl
+ << " Map XML Schema namespace <xns> to C++ namespace\n"
+ << " <cns>. Repeat this option to specify mapping for\n"
+ << " more than one XML Schema namespace."
+ << endl;
+
+ e << "--namespace-regex <regex>" << endl
+ << " Add <regex> to the list of regular expressions\n"
+ << " used to translate XML Schema namespace names to\n"
+ << " C++ namespace names."
+ << endl;
+
+ e << "--namespace-regex-trace" << endl
+ << " Trace the process of applying regular expressions\n"
+ << " specified with the --namespace-regex option."
+ << endl;
+
+ e << "--reserved-name <name>" << endl
+ << " Add <name> to the list of names that should not\n"
+ << " be used as identifiers. The name can optionally\n"
+ << " be followed by '=' and the replacement name that\n"
+ << " should be used instead."
+ << endl;
+
+ e << "--include-with-brackets" << endl
+ << " Use angle brackets (<>) instead of quotes (\"\") in\n"
+ << " generated #include directives."
+ << endl;
+
+ e << "--include-prefix <prefix>" << endl
+ << " Add <prefix> to generated #include directive\n"
+ << " paths."
+ << endl;
+
+ e << "--include-regex <regex>" << endl
+ << " Add <regex> to the list of regular expressions\n"
+ << " used to transform #include directive paths."
+ << endl;
+
+ e << "--include-regex-trace" << endl
+ << " Trace the process of applying regular expressions\n"
+ << " specified with the --include-regex option."
+ << endl;
+
+ e << "--guard-prefix <prefix>" << endl
+ << " Add <prefix> to generated header inclusion guards."
+ << endl;
+
+ // File suffix.
+ //
+ e << "--hxx-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '.hxx' to\n"
+ << " construct the name of the header files."
+ << endl;
+
+ e << "--ixx-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '.ixx' to\n"
+ << " construct the name of the inline files."
+ << endl;
+
+ e << "--cxx-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '.cxx' to\n"
+ << " construct the name of the source files."
+ << endl;
+
+ e << "--fwd-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '-fwd.hxx'\n"
+ << " to construct the name of the forward declaration\n"
+ << " file."
+ << endl;
+
+ // File regex.
+ //
+ e << "--hxx-regex <regex>" << endl
+ << " Use <regex> to construct the names of the header\n"
+ << " files."
+ << endl;
+
+ e << "--ixx-regex <regex>" << endl
+ << " Use <regex> to construct the names of the inline\n"
+ << " files."
+ << endl;
+
+ e << "--cxx-regex <regex>" << endl
+ << " Use <regex> to construct the names of the source\n"
+ << " files."
+ << endl;
+
+ e << "--fwd-regex <regex>" << endl
+ << " Use <regex> to construct the name of the forward\n"
+ << " declaration file."
+ << endl;
+
+
+ // Prologues.
+ //
+ e << "--hxx-prologue <text>" << endl
+ << " Insert <text> at the beginning of the header\n"
+ << " files."
+ << endl;
+
+ e << "--ixx-prologue <text>" << endl
+ << " Insert <text> at the beginning of the inline\n"
+ << " files."
+ << endl;
+
+ e << "--cxx-prologue <text>" << endl
+ << " Insert <text> at the beginning of the source\n"
+ << " files."
+ << endl;
+
+ e << "--fwd-prologue <text>" << endl
+ << " Insert <text> at the beginning of the forward\n"
+ << " declaration file."
+ << endl;
+
+ e << "--prologue <text>" << endl
+ << " Insert <text> at the beginning of each generated\n"
+ << " file for which there is no file-specific prologue."
+ << endl;
+
+
+ // Epilogues.
+ //
+ e << "--hxx-epilogue <text>" << endl
+ << " Insert <text> at the end of the header files."
+ << endl;
+
+ e << "--ixx-epilogue <text>" << endl
+ << " Insert <text> at the end of the inline files."
+ << endl;
+
+ e << "--cxx-epilogue <text>" << endl
+ << " Insert <text> at the end of the source files."
+ << endl;
+
+ e << "--fwd-epilogue <text>" << endl
+ << " Insert <text> at the end of the forward\n"
+ << " declaration file."
+ << endl;
+
+ e << "--epilogue <text>" << endl
+ << " Insert <text> at the end of each generated file\n"
+ << " for which there is no file-specific epilogue."
+ << endl;
+
+
+ // Prologue files.
+ //
+ e << "--hxx-prologue-file <file>" << endl
+ << " Insert the content of the <file> at the beginning\n"
+ << " of the header files."
+ << endl;
+
+ e << "--ixx-prologue-file <file>" << endl
+ << " Insert the content of the <file> at the beginning\n"
+ << " of the inline files."
+ << endl;
+
+ e << "--cxx-prologue-file <file>" << endl
+ << " Insert the content of the <file> at the beginning\n"
+ << " of the source files."
+ << endl;
+
+ e << "--fwd-prologue-file <file>" << endl
+ << " Insert the content of the <file> at the beginning\n"
+ << " of the forward declaration file."
+ << endl;
+
+ e << "--prologue-file <file>" << endl
+ << " Insert the content of the <file> at the beginning\n"
+ << " of each generated file for which there is no file-\n"
+ << " specific prologue file."
+ << endl;
+
+
+ // Epilogue files.
+ //
+ e << "--hxx-epilogue-file <file>" << endl
+ << " Insert the content of the <file> at the end of\n"
+ << " the header files."
+ << endl;
+
+ e << "--ixx-epilogue-file <file>" << endl
+ << " Insert the content of the <file> at the end of\n"
+ << " the inline files."
+ << endl;
+
+ e << "--cxx-epilogue-file <file>" << endl
+ << " Insert the content of the <file> at the end of\n"
+ << " the source files."
+ << endl;
+
+ e << "--fwd-epilogue-file <file>" << endl
+ << " Insert the content of the <file> at the end of\n"
+ << " the forward declaration file."
+ << endl;
+
+ e << "--epilogue-file <file>" << endl
+ << " Insert the content of the <file> at the end of\n"
+ << " each generated file for which there is no file-\n"
+ << " specific epilogue file."
+ << endl;
+
+
+ // Misc.
+ //
+ e << "--show-anonymous" << endl
+ << " Show elements and attributes that are of anonymous\n"
+ << " types."
+ << endl;
+
+ e << "--show-sloc" << endl
+ << " Show the number of generated physical source lines\n"
+ << " of code (SLOC)."
+ << endl;
+
+ e << "--sloc-limit <num>" << endl
+ << " Check that the number of generated physical source\n"
+ << " lines of code (SLOC) does not exceed <num>."
+ << endl;
+
+ e << "--options-file <file>" << endl
+ << " Read additional options from <file>. Each option\n"
+ << " should appear on a separate line optionally\n"
+ << " followed by space and an argument."
+ << endl;
+
+ e << "--proprietary-license" << endl
+ << " Indicate that the generated code is licensed under\n"
+ << " a proprietary license instead of the GPL."
+ << endl;
+ }
+
+ Hybrid::CLI::OptionsSpec Hybrid::Generator::
+ options_spec ()
+ {
+ CLI::OptionsSpec spec;
+
+ spec.option<CLI::pskel_file_suffix> ().default_value ("-pskel");
+ spec.option<CLI::sskel_file_suffix> ().default_value ("-sskel");
+ spec.option<CLI::pskel_type_suffix> ().default_value ("_pskel");
+ spec.option<CLI::sskel_type_suffix> ().default_value ("_sskel");
+
+ spec.option<CLI::pimpl_file_suffix> ().default_value ("-pimpl");
+ spec.option<CLI::simpl_file_suffix> ().default_value ("-simpl");
+ spec.option<CLI::pimpl_type_suffix> ().default_value ("_pimpl");
+ spec.option<CLI::simpl_type_suffix> ().default_value ("_simpl");
+
+ spec.option<CLI::paggr_type_suffix> ().default_value ("_paggr");
+ spec.option<CLI::saggr_type_suffix> ().default_value ("_saggr");
+
+ spec.option<CLI::hxx_suffix> ().default_value (".hxx");
+ spec.option<CLI::ixx_suffix> ().default_value (".ixx");
+ spec.option<CLI::cxx_suffix> ().default_value (".cxx");
+ spec.option<CLI::fwd_suffix> ().default_value ("-fwd.hxx");
+
+ return spec;
+ }
+
+ namespace
+ {
+ NarrowString
+ find_value (Cult::Containers::Vector<NarrowString> const& v,
+ Char const* key)
+ {
+ typedef Cult::Containers::Vector<NarrowString> Values;
+
+ for (Values::ConstIterator i (v.begin ()), e (v.end ()); i != e; ++i)
+ {
+ Size p (i->find ('='));
+
+ if (p == NarrowString::npos)
+ {
+ if (key[0] != '\0')
+ continue;
+ }
+ else
+ {
+ NarrowString k (*i, 0, p);
+
+ // Unless it is one of the valid keys, assume there is no key.
+ //
+ if (!(k.empty () || k == "*" || k == "pskel" ||
+ k == "pimpl" || k == "sskel" || k == "simpl"))
+ {
+ k.clear ();
+ p = NarrowString::npos;
+ }
+
+ if (k != key && k != "*")
+ continue;
+ }
+
+ return NarrowString (
+ *i, p == NarrowString::npos ? 0 : p + 1, NarrowString::npos);
+ }
+
+ return NarrowString ();
+ }
+
+ Void
+ copy_values (Cult::Containers::Vector<NarrowString>& dst,
+ Cult::Containers::Vector<NarrowString> const& src,
+ Char const* key)
+ {
+ typedef Cult::Containers::Vector<NarrowString> Values;
+
+ for (Values::ConstIterator i (src.begin ()), e (src.end ()); i != e; ++i)
+ {
+ Size p (i->find ('='));
+
+ if (p == NarrowString::npos)
+ {
+ if (key[0] != '\0')
+ continue;
+ }
+ else
+ {
+ NarrowString k (*i, 0, p);
+
+ // Unless it is one of the valid keys, assume there is no key.
+ //
+ if (!(k.empty () || k == "*" || k == "pskel" ||
+ k == "pimpl" || k == "sskel" || k == "simpl"))
+ {
+ k.clear ();
+ p = NarrowString::npos;
+ }
+
+ if (k != key && k != "*")
+ continue;
+ }
+
+ dst.push_back (
+ NarrowString (
+ *i, p == NarrowString::npos ? 0 : p + 1, NarrowString::npos));
+ }
+ }
+ }
+
+ Parser::CLI::Options* Hybrid::Generator::
+ parser_options (CLI::Options const& h)
+ {
+ namespace H = CLI;
+ namespace P = Parser::CLI;
+
+ Evptr<P::Options> r (new P::Options);
+
+ r->value<P::no_stl> () = h.value<H::no_stl> ();
+ r->value<P::no_iostream> () = h.value<H::no_iostream> ();
+ r->value<P::no_exceptions> () = h.value<H::no_exceptions> ();
+ r->value<P::no_long_long> () = h.value<H::no_long_long> ();
+ r->value<P::reuse_style_mixin> () = h.value<H::reuse_style_mixin> ();
+ r->value<P::reuse_style_none> () = false;
+ r->value<P::generate_inline> () = h.value<H::generate_inline> ();
+ r->value<P::suppress_validation> () = h.value<H::suppress_validation> ()
+ || h.value<H::suppress_parser_val> ();
+ 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::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> ();
+ r->value<P::impl_type_suffix> () = h.value<H::pimpl_type_suffix> ();
+ r->value<P::namespace_map> () = h.value<H::namespace_map> ();
+ r->value<P::namespace_regex> () = h.value<H::namespace_regex> ();
+ r->value<P::namespace_regex_trace> () = h.value<H::namespace_regex_trace> ();
+ r->value<P::reserved_name> () = h.value<H::reserved_name> ();
+ r->value<P::include_with_brackets> () = h.value<H::include_with_brackets> ();
+ r->value<P::include_prefix> () = h.value<H::include_prefix> ();
+ r->value<P::include_regex> () = h.value<H::include_regex> ();
+ r->value<P::include_regex_trace> () = h.value<H::include_regex_trace> ();
+ r->value<P::guard_prefix> () = h.value<H::guard_prefix> ();
+
+ r->value<P::hxx_suffix> () = h.value<H::hxx_suffix> ();
+ r->value<P::ixx_suffix> () = h.value<H::ixx_suffix> ();
+ r->value<P::cxx_suffix> () = h.value<H::cxx_suffix> ();
+
+ Char const* k = "pskel";
+
+ r->value<P::hxx_regex> () =
+ find_value (h.value<H::hxx_regex> (), k);
+ r->value<P::ixx_regex> () =
+ find_value (h.value<H::ixx_regex> (), k);
+ r->value<P::cxx_regex> () =
+ find_value (h.value<H::cxx_regex> (), k);
+
+ r->value<P::hxx_prologue_file> () = find_value (
+ h.value<H::hxx_prologue_file> (), k);
+ r->value<P::ixx_prologue_file> () = find_value (
+ h.value<H::ixx_prologue_file> (), k);
+ r->value<P::cxx_prologue_file> () = find_value (
+ h.value<H::cxx_prologue_file> (), k);
+ r->value<P::prologue_file> () = find_value (
+ h.value<H::prologue_file> (), k);
+ r->value<P::hxx_epilogue_file> () = find_value (
+ h.value<H::hxx_epilogue_file> (), k);
+ r->value<P::ixx_epilogue_file> () = find_value (
+ h.value<H::ixx_epilogue_file> (), k);
+ r->value<P::cxx_epilogue_file> () = find_value (
+ h.value<H::cxx_epilogue_file> (), k);
+ r->value<P::epilogue_file> () = find_value (
+ h.value<H::epilogue_file> (), k);
+
+ copy_values (r->value<P::hxx_prologue> (), h.value<H::hxx_prologue> (), k);
+ copy_values (r->value<P::ixx_prologue> (), h.value<H::ixx_prologue> (), k);
+ copy_values (r->value<P::cxx_prologue> (), h.value<H::cxx_prologue> (), k);
+ copy_values (r->value<P::prologue> (), h.value<H::prologue> (), k);
+ copy_values (r->value<P::hxx_epilogue> (), h.value<H::hxx_epilogue> (), k);
+ copy_values (r->value<P::ixx_epilogue> (), h.value<H::ixx_epilogue> (), k);
+ copy_values (r->value<P::cxx_epilogue> (), h.value<H::cxx_epilogue> (), k);
+ copy_values (r->value<P::epilogue> (), h.value<H::epilogue> (), k);
+
+ r->value<P::show_sloc> () = h.value<H::show_sloc> ();
+ r->value<P::proprietary_license> () = h.value<H::proprietary_license> ();
+
+ return r.release ();
+ }
+
+ Serializer::CLI::Options* Hybrid::Generator::
+ serializer_options (CLI::Options const& h)
+ {
+ namespace H = CLI;
+ namespace S = Serializer::CLI;
+
+ Evptr<S::Options> r (new S::Options);
+
+ r->value<S::no_stl> () = h.value<H::no_stl> ();
+ r->value<S::no_iostream> () = h.value<H::no_iostream> ();
+ r->value<S::no_exceptions> () = h.value<H::no_exceptions> ();
+ r->value<S::no_long_long> () = h.value<H::no_long_long> ();
+ r->value<S::reuse_style_mixin> () = h.value<H::reuse_style_mixin> ();
+ r->value<S::reuse_style_none> () = false;
+ r->value<S::generate_inline> () = h.value<H::generate_inline> ();
+ r->value<S::suppress_validation> () = h.value<H::suppress_validation> ()
+ || h.value<H::suppress_serializer_val> ();
+ 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::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> ();
+ r->value<S::impl_type_suffix> () = h.value<H::simpl_type_suffix> ();
+ r->value<S::namespace_map> () = h.value<H::namespace_map> ();
+ r->value<S::namespace_regex> () = h.value<H::namespace_regex> ();
+ r->value<S::namespace_regex_trace> () = h.value<H::namespace_regex_trace> ();
+ r->value<S::reserved_name> () = h.value<H::reserved_name> ();
+ r->value<S::include_with_brackets> () = h.value<H::include_with_brackets> ();
+ r->value<S::include_prefix> () = h.value<H::include_prefix> ();
+ r->value<S::include_regex> () = h.value<H::include_regex> ();
+ r->value<S::include_regex_trace> () = h.value<H::include_regex_trace> ();
+ r->value<S::guard_prefix> () = h.value<H::guard_prefix> ();
+
+ r->value<S::hxx_suffix> () = h.value<H::hxx_suffix> ();
+ r->value<S::ixx_suffix> () = h.value<H::ixx_suffix> ();
+ r->value<S::cxx_suffix> () = h.value<H::cxx_suffix> ();
+
+ Char const* k = "sskel";
+
+ r->value<S::hxx_regex> () =
+ find_value (h.value<H::hxx_regex> (), k);
+ r->value<S::ixx_regex> () =
+ find_value (h.value<H::ixx_regex> (), k);
+ r->value<S::cxx_regex> () =
+ find_value (h.value<H::cxx_regex> (), k);
+
+ r->value<S::hxx_prologue_file> () = find_value (
+ h.value<H::hxx_prologue_file> (), k);
+ r->value<S::ixx_prologue_file> () = find_value (
+ h.value<H::ixx_prologue_file> (), k);
+ r->value<S::cxx_prologue_file> () = find_value (
+ h.value<H::cxx_prologue_file> (), k);
+ r->value<S::prologue_file> () = find_value (
+ h.value<H::prologue_file> (), k);
+ r->value<S::hxx_epilogue_file> () = find_value (
+ h.value<H::hxx_epilogue_file> (), k);
+ r->value<S::ixx_epilogue_file> () = find_value (
+ h.value<H::ixx_epilogue_file> (), k);
+ r->value<S::cxx_epilogue_file> () = find_value (
+ h.value<H::cxx_epilogue_file> (), k);
+ r->value<S::epilogue_file> () = find_value (
+ h.value<H::epilogue_file> (), k);
+
+ copy_values (r->value<S::hxx_prologue> (), h.value<H::hxx_prologue> (), k);
+ copy_values (r->value<S::ixx_prologue> (), h.value<H::ixx_prologue> (), k);
+ copy_values (r->value<S::cxx_prologue> (), h.value<H::cxx_prologue> (), k);
+ copy_values (r->value<S::prologue> (), h.value<H::prologue> (), k);
+ copy_values (r->value<S::hxx_epilogue> (), h.value<H::hxx_epilogue> (), k);
+ copy_values (r->value<S::ixx_epilogue> (), h.value<H::ixx_epilogue> (), k);
+ copy_values (r->value<S::cxx_epilogue> (), h.value<H::cxx_epilogue> (), k);
+ copy_values (r->value<S::epilogue> (), h.value<H::epilogue> (), k);
+
+ r->value<S::show_sloc> () = h.value<H::show_sloc> ();
+ r->value<S::proprietary_license> () = h.value<H::proprietary_license> ();
+
+ return r.release ();
+ }
+
+ Void Hybrid::Generator::
+ calculate_size (CLI::Options const& ops,
+ XSDFrontend::SemanticGraph::Schema& schema,
+ XSDFrontend::SemanticGraph::Path const& file)
+ {
+ // Determine which types are fixed/variable-sized.
+ //
+ TreeSizeProcessor proc;
+ proc.process (ops, schema, file);
+ }
+
+ namespace
+ {
+ template <typename S>
+ Void
+ open (S& ifs, NarrowString const& path)
+ {
+ try
+ {
+ Path fs_path (path, boost::filesystem::native);
+ ifs.open (fs_path, std::ios_base::in | std::ios_base::binary);
+
+ if (!ifs.is_open ())
+ {
+ wcerr << path.c_str () << ": error: unable to open in read mode"
+ << endl;
+
+ throw Hybrid::Generator::Failed ();
+ }
+ }
+ catch (InvalidPath const&)
+ {
+ wcerr << "error: '" << path.c_str () << "' is not a valid "
+ << "filesystem path" << endl;
+
+ throw Hybrid::Generator::Failed ();
+ }
+ }
+
+ Void
+ append (WideOutputFileStream& os,
+ NarrowString const& path,
+ WideInputFileStream& default_is)
+ {
+ using std::ios_base;
+
+ if (path)
+ {
+ WideInputFileStream is;
+ open (is, path);
+ os << is.rdbuf ();
+ }
+ else if (default_is.is_open ())
+ {
+ os << default_is.rdbuf ();
+ default_is.seekg (0, ios_base::beg);
+ }
+ }
+
+ Void
+ append (WideOutputFileStream& os,
+ Cult::Containers::Vector<NarrowString> const& primary,
+ Cult::Containers::Vector<NarrowString> const& def,
+ Char const* primary_key,
+ Char const* def_key)
+ {
+ typedef Cult::Containers::Vector<NarrowString> Values;
+
+ for (Values const* v = &primary; v != 0; v = (v == &def ? 0 : &def))
+ {
+ Boolean found (false);
+ Char const* key (v == &primary ? primary_key : def_key);
+
+ for (Values::ConstIterator i (v->begin ()), e (v->end ()); i != e; ++i)
+ {
+ if (key == 0)
+ os << i->c_str () << endl;
+ else
+ {
+ Size p (i->find ('='));
+
+ if (p == NarrowString::npos)
+ {
+ if (key[0] != '\0')
+ continue;
+ }
+ else
+ {
+ NarrowString k (*i, 0, p);
+
+ // Unless it is one of the valid keys, assume there is no key.
+ //
+ if (!(k.empty () || k == "*" || k == "pskel" ||
+ k == "pimpl" || k == "sskel" || k == "simpl"))
+ {
+ k.clear ();
+ p = NarrowString::npos;
+ }
+
+ if (k != key && k != "*")
+ continue;
+ }
+
+ NarrowString s (
+ *i, p == NarrowString::npos ? 0 : p + 1, NarrowString::npos);
+ os << s.c_str () << endl;
+ }
+
+ found = true;
+ }
+
+ if (found)
+ break;
+ }
+ }
+
+ Void
+ append (WideOutputFileStream& os,
+ Cult::Containers::Vector<NarrowString> const& primary,
+ Cult::Containers::Vector<NarrowString> const& def,
+ Char const* key)
+ {
+ append (os, primary, def, key, key);
+ }
+ }
+
+
+ UnsignedLong Hybrid::Generator::
+ generate_tree (Hybrid::CLI::Options const& ops,
+ Schema& schema,
+ Path const& file_path,
+ const WarningSet& disabled_warnings,
+ TypeMap::Namespaces& parser_type_map,
+ TypeMap::Namespaces& serializer_type_map,
+ FileList& file_list,
+ AutoUnlinks& unlinks)
+ {
+ using std::ios_base;
+ namespace Indentation = BackendElements::Indentation;
+
+ typedef Context::Regex Regex;
+
+ try
+ {
+ Boolean generate_xml_schema (ops.value<CLI::generate_xml_schema> ());
+
+ // We could be compiling several schemas at once in which case
+ // handling of the --generate-xml-schema option gets tricky: we
+ // will need to rely on the presence of the --extern-xml-schema
+ // to tell us which (fake) schema file corresponds to XML Schema.
+ //
+ if (generate_xml_schema)
+ {
+ if (NarrowString name = ops.value<CLI::extern_xml_schema> ())
+ {
+ if (file_path.native_file_string () != name)
+ generate_xml_schema = false;
+ }
+ }
+
+ // Evaluate the graph for possibility of generating something useful.
+ //
+ {
+ Validator validator;
+ if (!validator.validate (ops, schema, file_path, disabled_warnings))
+ throw Failed ();
+ }
+
+ // Process names.
+ //
+ {
+ TreeNameProcessor proc;
+ proc.process (ops, schema, file_path);
+ }
+
+ // Generate code.
+ //
+ Boolean inline_ (ops.value<CLI::generate_inline> () &&
+ !generate_xml_schema);
+
+ Boolean forward (ops.value<CLI::generate_forward> () &&
+ !generate_xml_schema);
+
+ Boolean source (!generate_xml_schema);
+
+ NarrowString name (file_path.leaf ());
+
+ NarrowString hxx_suffix (ops.value <CLI::hxx_suffix> ());
+ NarrowString ixx_suffix (ops.value <CLI::ixx_suffix> ());
+ NarrowString cxx_suffix (ops.value <CLI::cxx_suffix> ());
+ NarrowString fwd_suffix (ops.value <CLI::fwd_suffix> ());
+
+ NarrowString hxx_regex (find_value (ops.value <CLI::hxx_regex> (), ""));
+ NarrowString ixx_regex (find_value (ops.value <CLI::ixx_regex> (), ""));
+ NarrowString cxx_regex (find_value (ops.value <CLI::cxx_regex> (), ""));
+
+ Regex hxx_expr (
+ hxx_regex.empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + hxx_suffix + "#"
+ : hxx_regex);
+
+ Regex ixx_expr (
+ ixx_regex.empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + ixx_suffix + "#"
+ : ixx_regex);
+
+ Regex cxx_expr (
+ cxx_regex.empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + cxx_suffix + "#"
+ : cxx_regex);
+
+ Regex fwd_expr (
+ ops.value <CLI::fwd_regex> ().empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + fwd_suffix + "#"
+ : ops.value <CLI::fwd_regex> ());
+
+ if (!hxx_expr.match (name))
+ {
+ wcerr << "error: header expression '" <<
+ hxx_expr.pattern () << "' does not match '" <<
+ name.c_str () << "'" << endl;
+ throw Failed ();
+ }
+
+ if (inline_ && !ixx_expr.match (name))
+ {
+ wcerr << "error: inline expression '" <<
+ ixx_expr.pattern () << "' does not match '" <<
+ name.c_str () << "'" << endl;
+ throw Failed ();
+ }
+
+ if (source && !cxx_expr.match (name))
+ {
+ wcerr << "error: source expression '" <<
+ cxx_expr.pattern () << "' does not match '" <<
+ name.c_str () << "'" << endl;
+ throw Failed ();
+ }
+
+ if (forward && !fwd_expr.match (name))
+ {
+ wcerr << "error: forward expression '" <<
+ fwd_expr.pattern () << "' does not match '" <<
+ name.c_str () << "'" << endl;
+ throw Failed ();
+ }
+
+ NarrowString hxx_name (hxx_expr.merge (name));
+ NarrowString ixx_name (inline_ ? ixx_expr.merge (name) : NarrowString ());
+ NarrowString cxx_name (source ? cxx_expr.merge (name) : NarrowString ());
+ NarrowString fwd_name (forward ? fwd_expr.merge (name) : NarrowString ());
+
+ Path hxx_path (hxx_name, boost::filesystem::native);
+ Path ixx_path (ixx_name, boost::filesystem::native);
+ Path cxx_path (cxx_name, boost::filesystem::native);
+ Path fwd_path (fwd_name, boost::filesystem::native);
+
+ if (NarrowString dir = ops.value<CLI::output_dir> ())
+ {
+ try
+ {
+ Path path (dir, boost::filesystem::native);
+
+ hxx_path = path / hxx_path;
+ ixx_path = path / ixx_path;
+ cxx_path = path / cxx_path;
+ fwd_path = path / fwd_path;
+ }
+ catch (InvalidPath const&)
+ {
+ wcerr << dir.c_str () << ": error: invalid path" << endl;
+ throw Failed ();
+ }
+ }
+
+ // Open the tree files.
+ //
+ WideOutputFileStream hxx (hxx_path, ios_base::out);
+ WideOutputFileStream ixx;
+ WideOutputFileStream cxx;
+ WideOutputFileStream fwd;
+
+ // FWD
+ //
+ if (forward)
+ {
+ fwd.open (fwd_path, ios_base::out);
+
+ if (!fwd.is_open ())
+ {
+ wcerr << fwd_path << ": error: unable to open in write mode" << endl;
+ throw Failed ();
+ }
+
+ unlinks.add (fwd_path);
+ file_list.push_back (fwd_path.native_file_string ());
+ }
+
+ if (!hxx.is_open ())
+ {
+ wcerr << hxx_path << ": error: unable to open in write mode" << endl;
+ throw Failed ();
+ }
+
+ unlinks.add (hxx_path);
+ file_list.push_back (hxx_path.native_file_string ());
+
+ if (inline_)
+ {
+ ixx.open (ixx_path, ios_base::out);
+
+ if (!ixx.is_open ())
+ {
+ wcerr << ixx_path << ": error: unable to open in write mode" << endl;
+ throw Failed ();
+ }
+
+ unlinks.add (ixx_path);
+ file_list.push_back (ixx_path.native_file_string ());
+ }
+
+ if (source)
+ {
+ cxx.open (cxx_path, ios_base::out);
+
+ if (!cxx.is_open ())
+ {
+ wcerr << cxx_path << ": error: unable to open in write mode" << endl;
+ throw Failed ();
+ }
+
+ unlinks.add (cxx_path);
+ file_list.push_back (cxx_path.native_file_string ());
+ }
+
+ // Print copyright and license.
+ //
+ Char const* copyright (
+ ops.value<CLI::proprietary_license> ()
+ ? copyright_proprietary
+ : copyright_gpl);
+
+ if (forward)
+ fwd << copyright;
+
+ hxx << copyright;
+
+ if (inline_)
+ ixx << copyright;
+
+ if (source)
+ cxx << copyright;
+
+ // Prologue.
+ //
+ WideInputFileStream prologue;
+ {
+ NarrowString name (
+ find_value (ops.value<CLI::prologue_file> (), ""));
+
+ if (name)
+ open (prologue, name);
+ }
+
+ // Epilogue.
+ //
+ WideInputFileStream epilogue;
+ {
+ NarrowString name (
+ find_value (ops.value<CLI::epilogue_file> (), ""));
+
+ if (name)
+ open (epilogue, name);
+ }
+
+
+ // SLOC counter.
+ //
+ UnsignedLong sloc (0);
+ Boolean show_sloc (ops.value<CLI::show_sloc> ());
+
+
+ //
+ //
+ Regex guard_expr ("/([a-z])([A-Z])/$1_$2/"); // Split words.
+
+ NarrowString guard_prefix (ops.value<CLI::guard_prefix> ());
+
+ if (!guard_prefix)
+ guard_prefix = file_path.branch_path ().native_directory_string ();
+
+ if (guard_prefix)
+ guard_prefix += '_';
+
+
+ // FWD
+ //
+ if (forward)
+ {
+ Context ctx (fwd, schema, ops, &fwd_expr, &hxx_expr, &ixx_expr);
+
+ Indentation::Clip<Indentation::SLOC, WideChar> fwd_sloc (fwd);
+
+ String guard (guard_expr.merge (guard_prefix + fwd_name));
+ guard = ctx.escape (guard); // Make it a C++ id.
+ std::transform (guard.begin (), guard.end(), guard.begin (), upcase);
+
+ fwd << "#ifndef " << guard << endl
+ << "#define " << guard << endl
+ << endl;
+
+ // Copy prologue.
+ //
+ fwd << "// Begin prologue." << endl
+ << "//" << endl;
+
+ append (fwd,
+ ops.value<CLI::fwd_prologue> (),
+ ops.value<CLI::prologue> (),
+ 0,
+ "");
+ append (fwd, ops.value<CLI::fwd_prologue_file> (), prologue);
+
+ fwd << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ // Version check.
+ //
+ fwd << "#include <xsde/cxx/version.hxx>" << endl
+ << endl
+ << "#if (XSDE_INT_VERSION != " << XSDE_INT_VERSION << "L)" << endl
+ << "#error XSD/e runtime version mismatch" << endl
+ << "#endif" << endl
+ << endl;
+
+ fwd << "#include <xsde/cxx/pre.hxx>" << endl
+ << endl;
+
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> fwd_clip (fwd);
+
+ // Generate.
+ //
+ generate_tree_forward (ctx, false);
+
+ fwd << "#include <xsde/cxx/post.hxx>" << endl
+ << endl;
+ }
+
+ // Copy epilogue.
+ //
+ fwd << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (fwd, ops.value<CLI::fwd_epilogue_file> (), epilogue);
+ append (fwd,
+ ops.value<CLI::fwd_epilogue> (),
+ ops.value<CLI::epilogue> (),
+ 0,
+ "");
+
+ fwd << "//" << endl
+ << "// End epilogue." << endl
+ << endl;
+
+ fwd << "#endif // " << guard << endl;
+
+ if (show_sloc)
+ {
+ wcerr << fwd_path << ": "
+ << fwd_sloc.buffer ().count () << endl;
+
+ sloc += fwd_sloc.buffer ().count ();
+ }
+ }
+
+
+ // HXX
+ //
+ {
+ Context ctx (hxx, schema, ops, &fwd_expr, &hxx_expr, &ixx_expr);
+
+ Indentation::Clip<Indentation::SLOC, WideChar> hxx_sloc (hxx);
+
+ String guard (guard_expr.merge (guard_prefix + hxx_name));
+ guard = ctx.escape (guard); // Make it a C++ id.
+ std::transform (guard.begin (), guard.end(), guard.begin (), upcase);
+
+ hxx << "#ifndef " << guard << endl
+ << "#define " << guard << endl
+ << endl;
+
+ // Copy prologue.
+ //
+ hxx << "// Begin prologue." << endl
+ << "//" << endl;
+
+ append (hxx,
+ ops.value<CLI::hxx_prologue> (),
+ ops.value<CLI::prologue> (),
+ "");
+ append (hxx,
+ find_value (ops.value<CLI::hxx_prologue_file> (), ""),
+ prologue);
+
+ hxx << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ // Version check.
+ //
+ hxx << "#include <xsde/cxx/version.hxx>" << endl
+ << endl
+ << "#if (XSDE_INT_VERSION != " << XSDE_INT_VERSION << "L)" << endl
+ << "#error XSD/e runtime version mismatch" << endl
+ << "#endif" << endl
+ << endl;
+
+ // Runtime/generated code compatibility checks.
+ //
+
+ hxx << "#include <xsde/cxx/config.hxx>" << endl
+ << endl;
+
+ if (ops.value<CLI::no_stl> ())
+ {
+ hxx << "#ifdef XSDE_STL" << endl
+ << "#error the XSD/e runtime uses STL while the " <<
+ "generated code does not (reconfigure the runtime or " <<
+ "remove --no-stl)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+ else
+ {
+ hxx << "#ifndef XSDE_STL" << endl
+ << "#error the generated code uses STL while the " <<
+ "XSD/e runtime does not (reconfigure the runtime or " <<
+ "add --no-stl)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+
+ if (ops.value<CLI::no_exceptions> ())
+ {
+ hxx << "#ifdef XSDE_EXCEPTIONS" << endl
+ << "#error the XSD/e runtime uses exceptions while the " <<
+ "generated code does not (reconfigure the runtime or " <<
+ "remove --no-exceptions)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+ else
+ {
+ hxx << "#ifndef XSDE_EXCEPTIONS" << endl
+ << "#error the generated code uses exceptions while the " <<
+ "XSD/e runtime does not (reconfigure the runtime or " <<
+ "add --no-exceptions)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+
+ if (ops.value<CLI::no_long_long> ())
+ {
+ hxx << "#ifdef XSDE_LONGLONG" << endl
+ << "#error the XSD/e runtime uses long long while the " <<
+ "generated code does not (reconfigure the runtime or " <<
+ "remove --no-long-long)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+ else
+ {
+ hxx << "#ifndef XSDE_LONGLONG" << endl
+ << "#error the generated code uses long long while the " <<
+ "XSD/e runtime does not (reconfigure the runtime or " <<
+ "add --no-long-long)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+
+ //
+ //
+
+ hxx << "#include <xsde/cxx/pre.hxx>" << endl
+ << endl;
+
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> hxx_clip (hxx);
+
+ // Generate.
+ //
+ if (!generate_xml_schema)
+ {
+ if (forward)
+ hxx << "#include " << ctx.process_include_path (fwd_name)
+ << endl << endl;
+ else
+ generate_tree_forward (ctx, false);
+
+ generate_tree_header (ctx);
+ }
+ else
+ generate_tree_forward (ctx, true);
+
+ if (inline_)
+ {
+ hxx << "#ifndef XSDE_DONT_INCLUDE_INLINE" << endl
+ << "#include " << ctx.process_include_path (ixx_name) << endl
+ << "#endif // XSDE_DONT_INCLUDE_INLINE" << endl
+ << endl;
+ }
+
+ hxx << "#include <xsde/cxx/post.hxx>" << endl
+ << endl;
+ }
+
+ // Copy epilogue.
+ //
+ hxx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (hxx,
+ find_value (ops.value<CLI::hxx_epilogue_file> (), ""),
+ epilogue);
+ append (hxx,
+ ops.value<CLI::hxx_epilogue> (),
+ ops.value<CLI::epilogue> (),
+ "");
+
+ hxx << "//" << endl
+ << "// End epilogue." << endl
+ << endl;
+
+ hxx << "#endif // " << guard << endl;
+
+ if (show_sloc)
+ {
+ wcerr << hxx_path << ": "
+ << hxx_sloc.buffer ().count () << endl;
+
+ sloc += hxx_sloc.buffer ().count ();
+ }
+ }
+
+
+ // IXX
+ //
+ if (inline_)
+ {
+ Context ctx (ixx, schema, ops, &fwd_expr, &hxx_expr, &ixx_expr);
+
+ Indentation::Clip<Indentation::SLOC, WideChar> ixx_sloc (ixx);
+ // Guard
+ //
+ String guard (guard_expr.merge (guard_prefix + ixx_name));
+ guard = ctx.escape (guard); // make a c++ id
+ std::transform (guard.begin (), guard.end(), guard.begin (), upcase);
+
+ ixx << "#ifndef " << guard.c_str () << endl
+ << "#define " << guard.c_str () << endl
+ << endl;
+
+ // Copy prologue.
+ //
+ ixx << "// Begin prologue." << endl
+ << "//" << endl;
+
+ append (ixx,
+ ops.value<CLI::ixx_prologue> (),
+ ops.value<CLI::prologue> (),
+ "");
+ append (ixx,
+ find_value (ops.value<CLI::ixx_prologue_file> (), ""),
+ prologue);
+
+ ixx << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> ixx_clip (ixx);
+
+ // Generate.
+ //
+ generate_tree_inline (ctx);
+ }
+
+ // Copy epilogue.
+ //
+ ixx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (ixx,
+ find_value (ops.value<CLI::ixx_epilogue_file> (), ""),
+ epilogue);
+ append (ixx,
+ ops.value<CLI::ixx_epilogue> (),
+ ops.value<CLI::epilogue> (),
+ "");
+
+ ixx << "//" << endl
+ << "// End epilogue." << endl
+ << endl;
+
+ ixx << "#endif // " << guard.c_str () << endl;
+
+ if (show_sloc)
+ {
+ wcerr << ixx_path << ": "
+ << ixx_sloc.buffer ().count () << endl;
+
+ sloc += ixx_sloc.buffer ().count ();
+ }
+ }
+
+
+ // CXX
+ //
+ if (source)
+ {
+ Context ctx (cxx, schema, ops, &fwd_expr, &hxx_expr, &ixx_expr);
+
+ Indentation::Clip<Indentation::SLOC, WideChar> cxx_sloc (cxx);
+
+ // Copy prologue.
+ //
+ cxx << "// Begin prologue." << endl
+ << "//" << endl;
+
+ append (cxx,
+ ops.value<CLI::cxx_prologue> (),
+ ops.value<CLI::prologue> (),
+ "");
+ append (cxx,
+ find_value (ops.value<CLI::cxx_prologue_file> (), ""),
+ prologue);
+
+ cxx << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ cxx << "#include <xsde/cxx/pre.hxx>" << endl
+ << endl;
+
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> cxx_clip (cxx);
+
+ cxx << "#include " << ctx.process_include_path (hxx_name) << endl
+ << endl;
+
+ if (!inline_)
+ generate_tree_inline (ctx);
+
+ generate_tree_source (ctx);
+
+ cxx << "#include <xsde/cxx/post.hxx>" << endl
+ << endl;
+ }
+
+ // Copy epilogue.
+ //
+ cxx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (cxx,
+ find_value (ops.value<CLI::cxx_epilogue_file> (), ""),
+ epilogue);
+ append (cxx,
+ ops.value<CLI::cxx_epilogue> (),
+ ops.value<CLI::epilogue> (),
+ "");
+
+ cxx << "//" << endl
+ << "// End epilogue." << endl
+ << endl;
+
+ if (show_sloc)
+ {
+ wcerr << cxx_path << ": "
+ << cxx_sloc.buffer ().count () << endl;
+
+ sloc += cxx_sloc.buffer ().count ();
+ }
+ }
+
+ // Populate the type maps if we are generating parsing or
+ // serialization code.
+ //
+ if (ops.value<CLI::generate_parser> () ||
+ ops.value<CLI::generate_serializer> ())
+ {
+ generate_tree_type_map (
+ ops, schema, hxx_name, parser_type_map, serializer_type_map);
+ }
+
+ return sloc;
+ }
+ catch (NoNamespaceMapping const& e)
+ {
+ wcerr << e.file () << ":" << e.line () << ":" << e.column ()
+ << ": error: unable to map XML Schema namespace '" << e.ns ()
+ << "' to C++ namespace" << endl;
+
+ wcerr << e.file () << ":" << e.line () << ":" << e.column ()
+ << ": info: use the --namespace-map or --namespace-regex option "
+ << "to provide custom mapping" << endl;
+
+ throw Failed ();
+ }
+ catch (InvalidNamespaceMapping const& e)
+ {
+ wcerr << "error: invalid XML to C++ namespace mapping specified: "
+ << "'" << e.mapping () << "': " << e.reason () << endl;
+
+ throw Failed ();
+ }
+ catch (BackendElements::Regex::Format<Char> const& e)
+ {
+ wcerr << "error: invalid regex: '" <<
+ e.expression ().c_str () << "': " <<
+ e.description ().c_str () << endl;
+
+ throw Failed ();
+ }
+ catch (BackendElements::Regex::Format<WideChar> const& e)
+ {
+ wcerr << "error: invalid regex: '" <<
+ e.expression () << "': " << e.description () << endl;
+
+ throw Failed ();
+ }
+ }
+
+ UnsignedLong Hybrid::Generator::
+ generate_parser (Hybrid::CLI::Options const& ops,
+ Schema& schema,
+ Path const& file_path,
+ const WarningSet&,
+ FileList& file_list,
+ AutoUnlinks& unlinks)
+ {
+ using std::ios_base;
+ namespace Indentation = BackendElements::Indentation;
+
+ typedef BackendElements::Regex::Expression<Char> Regex;
+
+ try
+ {
+ {
+ Boolean gen_xml_schema (ops.value<CLI::generate_xml_schema> ());
+
+ // We could be compiling several schemas at once in which case
+ // handling of the --generate-xml-schema option gets tricky: we
+ // will need to rely on the presence of the --extern-xml-schema
+ // to tell us which (fake) schema file corresponds to XML Schema.
+ //
+ if (gen_xml_schema)
+ {
+ if (NarrowString name = ops.value<CLI::extern_xml_schema> ())
+ {
+ if (file_path.native_file_string () != name)
+ gen_xml_schema = false;
+ }
+ }
+
+ if (gen_xml_schema)
+ return 0;
+ }
+
+ // Process names.
+ //
+ {
+ ParserNameProcessor proc;
+ proc.process (ops, schema, file_path);
+ }
+
+ NarrowString name (file_path.leaf ());
+ NarrowString skel_suffix (ops.value <CLI::pskel_file_suffix> ());
+ NarrowString impl_suffix (ops.value <CLI::pimpl_file_suffix> ());
+
+ NarrowString hxx_suffix (ops.value <CLI::hxx_suffix> ());
+ NarrowString cxx_suffix (ops.value <CLI::cxx_suffix> ());
+
+ NarrowString hxx_obj_regex (
+ find_value (ops.value <CLI::hxx_regex> (), ""));
+
+ NarrowString hxx_skel_regex (
+ find_value (ops.value <CLI::hxx_regex> (), "pskel"));
+
+ NarrowString hxx_regex (
+ find_value (ops.value <CLI::hxx_regex> (), "pimpl"));
+ NarrowString cxx_regex (
+ find_value (ops.value <CLI::cxx_regex> (), "pimpl"));
+
+ // Here we need to make sure that hxx_obj_expr is the same
+ // as in generate().
+ //
+ Regex hxx_obj_expr (
+ hxx_obj_regex.empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + hxx_suffix + "#"
+ : hxx_obj_regex);
+
+ // Here we need to make sure that hxx_skel_expr is the same
+ // as in the C++/Parser generator.
+ //
+ Regex hxx_skel_expr (
+ hxx_skel_regex.empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + skel_suffix + hxx_suffix + "#"
+ : hxx_skel_regex);
+
+ Regex hxx_expr (
+ hxx_regex.empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + impl_suffix + hxx_suffix + "#"
+ : hxx_regex);
+
+ Regex cxx_expr (
+ cxx_regex.empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + impl_suffix + cxx_suffix + "#"
+ : cxx_regex);
+
+ if (!hxx_expr.match (name))
+ {
+ wcerr << "error: parser implementation header expression '" <<
+ hxx_expr.pattern () << "' does not match '" <<
+ name.c_str () << "'" << endl;
+ throw Failed ();
+ }
+
+ if (!cxx_expr.match (name))
+ {
+ wcerr << "error: parser implementation source expression '" <<
+ cxx_expr.pattern () << "' does not match '" <<
+ name.c_str () << "'" << endl;
+ throw Failed ();
+ }
+
+ NarrowString hxx_skel_name (hxx_skel_expr.merge (name));
+ NarrowString hxx_name (hxx_expr.merge (name));
+ NarrowString cxx_name (cxx_expr.merge (name));
+
+ Path hxx_path (hxx_name, boost::filesystem::native);
+ Path cxx_path (cxx_name, boost::filesystem::native);
+
+ if (NarrowString dir = ops.value<CLI::output_dir> ())
+ {
+ try
+ {
+ Path path (dir, boost::filesystem::native);
+
+ hxx_path = path / hxx_path;
+ cxx_path = path / cxx_path;
+ }
+ catch (InvalidPath const&)
+ {
+ wcerr << dir.c_str () << ": error: invalid path" << endl;
+ throw Failed ();
+ }
+ }
+
+ WideOutputFileStream hxx (hxx_path, ios_base::out);
+ WideOutputFileStream cxx (cxx_path, ios_base::out);
+
+ if (!hxx.is_open ())
+ {
+ wcerr << hxx_path << ": error: unable to open in write mode" << endl;
+ throw Failed ();
+ }
+
+ unlinks.add (hxx_path);
+ file_list.push_back (hxx_path.native_file_string ());
+
+ if (!cxx.is_open ())
+ {
+ wcerr << cxx_path << ": error: unable to open in write mode" << endl;
+ throw Failed ();
+ }
+
+ unlinks.add (cxx_path);
+ file_list.push_back (cxx_path.native_file_string ());
+
+ // Print copyright and license.
+ //
+ Char const* copyright (
+ ops.value<CLI::proprietary_license> ()
+ ? copyright_proprietary
+ : copyright_gpl);
+
+ hxx << copyright;
+ cxx << copyright;
+
+ // Prologue.
+ //
+ WideInputFileStream prologue;
+ {
+ NarrowString name (
+ find_value (ops.value<CLI::prologue_file> (), "pimpl"));
+
+ if (name)
+ open (prologue, name);
+ }
+
+ // Epilogue.
+ //
+ WideInputFileStream epilogue;
+ {
+ NarrowString name (
+ find_value (ops.value<CLI::epilogue_file> (), "pimpl"));
+
+ if (name)
+ open (epilogue, name);
+ }
+
+ // SLOC counter.
+ //
+ UnsignedLong sloc (0);
+ Boolean show_sloc (ops.value<CLI::show_sloc> ());
+
+ //
+ //
+ Regex guard_expr ("/([a-z])([A-Z])/$1_$2/"); // Split words.
+
+ NarrowString guard_prefix (ops.value<CLI::guard_prefix> ());
+
+ if (!guard_prefix)
+ guard_prefix = file_path.branch_path ().native_directory_string ();
+
+ if (guard_prefix)
+ guard_prefix += '_';
+
+
+ // HXX
+ //
+ {
+ Context ctx (hxx, schema, ops, 0, &hxx_expr, 0);
+
+ Indentation::Clip<Indentation::SLOC, WideChar> hxx_sloc (hxx);
+
+ String guard (guard_expr.merge (guard_prefix + hxx_name));
+ guard = ctx.escape (guard); // Make it a C++ id.
+ std::transform (guard.begin (), guard.end(), guard.begin (), upcase);
+
+ hxx << "#ifndef " << guard << endl
+ << "#define " << guard << endl
+ << endl;
+
+ // Copy prologue.
+ //
+ hxx << "// Begin prologue." << endl
+ << "//" << endl;
+
+ append (hxx,
+ ops.value<CLI::hxx_prologue> (),
+ ops.value<CLI::prologue> (),
+ "pimpl");
+ append (hxx,
+ find_value (ops.value<CLI::hxx_prologue_file> (), "pimpl"),
+ prologue);
+
+ hxx << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ hxx << "#include <xsde/cxx/pre.hxx>" << endl
+ << endl;
+
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> hxx_clip (hxx);
+
+ hxx << "#include " << ctx.process_include_path (hxx_skel_name)
+ << endl << endl;
+
+ generate_parser_header (ctx);
+
+ if (ops.value<CLI::generate_aggregate> ())
+ generate_parser_aggregate_header (ctx);
+
+ hxx << "#include <xsde/cxx/post.hxx>" << endl
+ << endl;
+ }
+
+ // Copy epilogue.
+ //
+ hxx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (hxx,
+ find_value (ops.value<CLI::hxx_epilogue_file> (), "pimpl"),
+ epilogue);
+ append (hxx,
+ ops.value<CLI::hxx_epilogue> (),
+ ops.value<CLI::epilogue> (),
+ "pimpl");
+
+ hxx << "//" << endl
+ << "// End epilogue." << endl
+ << endl;
+
+ hxx << "#endif // " << guard << endl;
+
+ if (show_sloc)
+ {
+ wcerr << hxx_path << ": "
+ << hxx_sloc.buffer ().count () << endl;
+
+ sloc += hxx_sloc.buffer ().count ();
+ }
+ }
+
+ // CXX
+ //
+ {
+ Context ctx (cxx, schema, ops, 0, &hxx_obj_expr, 0);
+
+ Indentation::Clip<Indentation::SLOC, WideChar> cxx_sloc (cxx);
+
+ // Copy prologue.
+ //
+ cxx << "// Begin prologue." << endl
+ << "//" << endl;
+
+ append (cxx,
+ ops.value<CLI::cxx_prologue> (),
+ ops.value<CLI::prologue> (),
+ "pimpl");
+ append (cxx,
+ find_value (ops.value<CLI::cxx_prologue_file> (), "pimpl"),
+ prologue);
+
+ cxx << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> cxx_clip (cxx);
+
+ cxx << "#include " << ctx.process_include_path (hxx_name) << endl
+ << endl;
+
+ generate_parser_source (ctx);
+
+ if (ops.value<CLI::generate_aggregate> ())
+ generate_parser_aggregate_source (ctx);
+ }
+
+ // Copy epilogue.
+ //
+ cxx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (cxx,
+ find_value (ops.value<CLI::cxx_epilogue_file> (), "pimpl"),
+ epilogue);
+ append (cxx,
+ ops.value<CLI::cxx_epilogue> (),
+ ops.value<CLI::epilogue> (),
+ "pimpl");
+
+ cxx << "//" << endl
+ << "// End epilogue." << endl
+ << endl;
+
+ if (show_sloc)
+ {
+ wcerr << cxx_path << ": "
+ << cxx_sloc.buffer ().count () << endl;
+
+ sloc += cxx_sloc.buffer ().count ();
+ }
+ }
+
+ return sloc;
+ }
+ catch (NoNamespaceMapping const& e)
+ {
+ wcerr << e.file () << ":" << e.line () << ":" << e.column ()
+ << ": error: unable to map XML Schema namespace '" << e.ns ()
+ << "' to C++ namespace" << endl;
+
+ wcerr << e.file () << ":" << e.line () << ":" << e.column ()
+ << ": info: use the --namespace-map or --namespace-regex option "
+ << "to provide custom mapping" << endl;
+
+ throw Failed ();
+ }
+ catch (InvalidNamespaceMapping const& e)
+ {
+ wcerr << "error: invalid XML to C++ namespace mapping specified: "
+ << "'" << e.mapping () << "': " << e.reason () << endl;
+
+ throw Failed ();
+ }
+ catch (BackendElements::Regex::Format<Char> const& e)
+ {
+ wcerr << "error: invalid regex: '" <<
+ e.expression ().c_str () << "': " <<
+ e.description ().c_str () << endl;
+
+ throw Failed ();
+ }
+ catch (BackendElements::Regex::Format<WideChar> const& e)
+ {
+ wcerr << "error: invalid regex: '" <<
+ e.expression () << "': " << e.description () << endl;
+
+ throw Failed ();
+ }
+ }
+
+ UnsignedLong Hybrid::Generator::
+ generate_serializer (Hybrid::CLI::Options const& ops,
+ Schema& schema,
+ Path const& file_path,
+ const WarningSet&,
+ FileList& file_list,
+ AutoUnlinks& unlinks)
+ {
+ using std::ios_base;
+ namespace Indentation = BackendElements::Indentation;
+
+ typedef BackendElements::Regex::Expression<Char> Regex;
+
+ try
+ {
+ {
+ Boolean gen_xml_schema (ops.value<CLI::generate_xml_schema> ());
+
+ // We could be compiling several schemas at once in which case
+ // handling of the --generate-xml-schema option gets tricky: we
+ // will need to rely on the presence of the --extern-xml-schema
+ // to tell us which (fake) schema file corresponds to XML Schema.
+ //
+ if (gen_xml_schema)
+ {
+ if (NarrowString name = ops.value<CLI::extern_xml_schema> ())
+ {
+ if (file_path.native_file_string () != name)
+ gen_xml_schema = false;
+ }
+ }
+
+ if (gen_xml_schema)
+ return 0;
+ }
+
+ // Process names.
+ //
+ {
+ SerializerNameProcessor proc;
+ proc.process (ops, schema, file_path);
+ }
+
+ NarrowString name (file_path.leaf ());
+ NarrowString skel_suffix (ops.value <CLI::sskel_file_suffix> ());
+ NarrowString impl_suffix (ops.value <CLI::simpl_file_suffix> ());
+
+ NarrowString hxx_suffix (ops.value <CLI::hxx_suffix> ());
+ NarrowString cxx_suffix (ops.value <CLI::cxx_suffix> ());
+
+ NarrowString hxx_skel_regex (
+ find_value (ops.value <CLI::hxx_regex> (), "sskel"));
+ NarrowString hxx_regex (
+ find_value (ops.value <CLI::hxx_regex> (), "simpl"));
+ NarrowString cxx_regex (
+ find_value (ops.value <CLI::cxx_regex> (), "simpl"));
+
+ // Here we need to make sure that hxx_skel_expr is the same
+ // as in the C++/Serializer generator.
+ //
+ Regex hxx_skel_expr (
+ hxx_skel_regex.empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + skel_suffix + hxx_suffix + "#"
+ : hxx_skel_regex);
+
+ Regex hxx_expr (
+ hxx_regex.empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + impl_suffix + hxx_suffix + "#"
+ : hxx_regex);
+
+ Regex cxx_expr (
+ cxx_regex.empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + impl_suffix + cxx_suffix + "#"
+ : cxx_regex);
+
+ if (!hxx_expr.match (name))
+ {
+ wcerr << "error: serializer implementation header expression '" <<
+ hxx_expr.pattern () << "' does not match '" <<
+ name.c_str () << "'" << endl;
+ throw Failed ();
+ }
+
+ if (!cxx_expr.match (name))
+ {
+ wcerr << "error: serializer implementation source expression '" <<
+ cxx_expr.pattern () << "' does not match '" <<
+ name.c_str () << "'" << endl;
+ throw Failed ();
+ }
+
+ NarrowString hxx_skel_name (hxx_skel_expr.merge (name));
+ NarrowString hxx_name (hxx_expr.merge (name));
+ NarrowString cxx_name (cxx_expr.merge (name));
+
+ Path hxx_path (hxx_name, boost::filesystem::native);
+ Path cxx_path (cxx_name, boost::filesystem::native);
+
+ if (NarrowString dir = ops.value<CLI::output_dir> ())
+ {
+ try
+ {
+ Path path (dir, boost::filesystem::native);
+
+ hxx_path = path / hxx_path;
+ cxx_path = path / cxx_path;
+ }
+ catch (InvalidPath const&)
+ {
+ wcerr << dir.c_str () << ": error: invalid path" << endl;
+ throw Failed ();
+ }
+ }
+
+ WideOutputFileStream hxx (hxx_path, ios_base::out);
+ WideOutputFileStream cxx (cxx_path, ios_base::out);
+
+ if (!hxx.is_open ())
+ {
+ wcerr << hxx_path << ": error: unable to open in write mode" << endl;
+ throw Failed ();
+ }
+
+ unlinks.add (hxx_path);
+ file_list.push_back (hxx_path.native_file_string ());
+
+ if (!cxx.is_open ())
+ {
+ wcerr << cxx_path << ": error: unable to open in write mode" << endl;
+ throw Failed ();
+ }
+
+ unlinks.add (cxx_path);
+ file_list.push_back (cxx_path.native_file_string ());
+
+ // Print copyright and license.
+ //
+ Char const* copyright (
+ ops.value<CLI::proprietary_license> ()
+ ? copyright_proprietary
+ : copyright_gpl);
+
+ hxx << copyright;
+ cxx << copyright;
+
+ // Prologue.
+ //
+ WideInputFileStream prologue;
+ {
+ NarrowString name (
+ find_value (ops.value<CLI::prologue_file> (), "simpl"));
+
+ if (name)
+ open (prologue, name);
+ }
+
+ // Epilogue.
+ //
+ WideInputFileStream epilogue;
+ {
+ NarrowString name (
+ find_value (ops.value<CLI::epilogue_file> (), "simpl"));
+
+ if (name)
+ open (epilogue, name);
+ }
+
+ // SLOC counter.
+ //
+ UnsignedLong sloc (0);
+ Boolean show_sloc (ops.value<CLI::show_sloc> ());
+
+ //
+ //
+ Regex guard_expr ("/([a-z])([A-Z])/$1_$2/"); // Split words.
+
+ NarrowString guard_prefix (ops.value<CLI::guard_prefix> ());
+
+ if (!guard_prefix)
+ guard_prefix = file_path.branch_path ().native_directory_string ();
+
+ if (guard_prefix)
+ guard_prefix += '_';
+
+
+ // HXX
+ //
+ {
+ Context ctx (hxx, schema, ops, 0, &hxx_expr, 0);
+
+ Indentation::Clip<Indentation::SLOC, WideChar> hxx_sloc (hxx);
+
+ String guard (guard_expr.merge (guard_prefix + hxx_name));
+ guard = ctx.escape (guard); // Make it a C++ id.
+ std::transform (guard.begin (), guard.end(), guard.begin (), upcase);
+
+ hxx << "#ifndef " << guard << endl
+ << "#define " << guard << endl
+ << endl;
+
+ // Copy prologue.
+ //
+ hxx << "// Begin prologue." << endl
+ << "//" << endl;
+
+ append (hxx,
+ ops.value<CLI::hxx_prologue> (),
+ ops.value<CLI::prologue> (),
+ "simpl");
+ append (hxx,
+ find_value (ops.value<CLI::hxx_prologue_file> (), "simpl"),
+ prologue);
+
+ hxx << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ hxx << "#include <xsde/cxx/pre.hxx>" << endl
+ << endl;
+
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> hxx_clip (hxx);
+
+ hxx << "#include " << ctx.process_include_path (hxx_skel_name)
+ << endl << endl;
+
+ generate_serializer_header (ctx);
+
+ if (ops.value<CLI::generate_aggregate> ())
+ generate_serializer_aggregate_header (ctx);
+
+ hxx << "#include <xsde/cxx/post.hxx>" << endl
+ << endl;
+ }
+
+ // Copy epilogue.
+ //
+ hxx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (hxx,
+ find_value (ops.value<CLI::hxx_epilogue_file> (), "simpl"),
+ epilogue);
+ append (hxx,
+ ops.value<CLI::hxx_epilogue> (),
+ ops.value<CLI::epilogue> (),
+ "simpl");
+
+ hxx << "//" << endl
+ << "// End epilogue." << endl
+ << endl;
+
+ hxx << "#endif // " << guard << endl;
+
+ if (show_sloc)
+ {
+ wcerr << hxx_path << ": "
+ << hxx_sloc.buffer ().count () << endl;
+
+ sloc += hxx_sloc.buffer ().count ();
+ }
+ }
+
+ // CXX
+ //
+ {
+ Context ctx (cxx, schema, ops, 0, &hxx_expr, 0);
+
+ Indentation::Clip<Indentation::SLOC, WideChar> cxx_sloc (cxx);
+
+ // Copy prologue.
+ //
+ cxx << "// Begin prologue." << endl
+ << "//" << endl;
+
+ append (cxx,
+ ops.value<CLI::cxx_prologue> (),
+ ops.value<CLI::prologue> (),
+ "simpl");
+ append (cxx,
+ find_value (ops.value<CLI::cxx_prologue_file> (), "simpl"),
+ prologue);
+
+ cxx << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> cxx_clip (cxx);
+
+ cxx << "#include " << ctx.process_include_path (hxx_name) << endl
+ << endl;
+
+ generate_serializer_source (ctx);
+
+ if (ops.value<CLI::generate_aggregate> ())
+ generate_serializer_aggregate_source (ctx);
+ }
+
+ // Copy epilogue.
+ //
+ cxx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (cxx,
+ find_value (ops.value<CLI::cxx_epilogue_file> (), "simpl"),
+ epilogue);
+ append (cxx,
+ ops.value<CLI::cxx_epilogue> (),
+ ops.value<CLI::epilogue> (),
+ "simpl");
+
+ cxx << "//" << endl
+ << "// End epilogue." << endl
+ << endl;
+
+ if (show_sloc)
+ {
+ wcerr << cxx_path << ": "
+ << cxx_sloc.buffer ().count () << endl;
+
+ sloc += cxx_sloc.buffer ().count ();
+ }
+ }
+
+ return sloc;
+ }
+ catch (NoNamespaceMapping const& e)
+ {
+ wcerr << e.file () << ":" << e.line () << ":" << e.column ()
+ << ": error: unable to map XML Schema namespace '" << e.ns ()
+ << "' to C++ namespace" << endl;
+
+ wcerr << e.file () << ":" << e.line () << ":" << e.column ()
+ << ": info: use the --namespace-map or --namespace-regex option "
+ << "to provide custom mapping" << endl;
+
+ throw Failed ();
+ }
+ catch (InvalidNamespaceMapping const& e)
+ {
+ wcerr << "error: invalid XML to C++ namespace mapping specified: "
+ << "'" << e.mapping () << "': " << e.reason () << endl;
+
+ throw Failed ();
+ }
+ catch (BackendElements::Regex::Format<Char> const& e)
+ {
+ wcerr << "error: invalid regex: '" <<
+ e.expression ().c_str () << "': " <<
+ e.description ().c_str () << endl;
+
+ throw Failed ();
+ }
+ catch (BackendElements::Regex::Format<WideChar> const& e)
+ {
+ wcerr << "error: invalid regex: '" <<
+ e.expression () << "': " << e.description () << endl;
+
+ throw Failed ();
+ }
+ }
+}
diff --git a/xsde/cxx/hybrid/generator.hxx b/xsde/cxx/hybrid/generator.hxx
new file mode 100644
index 0000000..ff29750
--- /dev/null
+++ b/xsde/cxx/hybrid/generator.hxx
@@ -0,0 +1,90 @@
+// file : xsde/cxx/hybrid/generator.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_GENERATOR_HXX
+#define CXX_HYBRID_GENERATOR_HXX
+
+#include <cult/types.hxx>
+
+#include <cult/containers/vector.hxx>
+
+#include <cult/cli/options.hxx>
+#include <cult/cli/options-spec.hxx>
+
+#include <xsd-frontend/semantic-graph/elements.hxx> // Path
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <xsde.hxx>
+#include <type-map/type-map.hxx>
+#include <cxx/hybrid/cli.hxx>
+
+#include <cxx/parser/cli.hxx>
+#include <cxx/serializer/cli.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ using namespace Cult::Types;
+
+ class Generator
+ {
+ public:
+ static Void
+ usage ();
+
+ static CLI::OptionsSpec
+ options_spec ();
+
+ static Parser::CLI::Options*
+ parser_options (CLI::Options const&);
+
+ static Serializer::CLI::Options*
+ serializer_options (CLI::Options const&);
+
+ struct Failed {};
+
+ static Void
+ calculate_size (
+ CLI::Options const& options,
+ XSDFrontend::SemanticGraph::Schema&,
+ XSDFrontend::SemanticGraph::Path const& file);
+
+ static UnsignedLong
+ generate_tree (
+ CLI::Options const& options,
+ XSDFrontend::SemanticGraph::Schema&,
+ XSDFrontend::SemanticGraph::Path const& file,
+ const WarningSet& disabled_warnings,
+ TypeMap::Namespaces& parser_type_map,
+ TypeMap::Namespaces& serializer_type_map,
+ FileList& file_list,
+ AutoUnlinks& unlinks);
+
+ static UnsignedLong
+ generate_parser (
+ CLI::Options const& options,
+ XSDFrontend::SemanticGraph::Schema&,
+ XSDFrontend::SemanticGraph::Path const& file,
+ const WarningSet& disabled_warnings,
+ FileList& file_list,
+ AutoUnlinks& unlinks);
+
+ static UnsignedLong
+ generate_serializer (
+ CLI::Options const& options,
+ XSDFrontend::SemanticGraph::Schema&,
+ XSDFrontend::SemanticGraph::Path const& file,
+ const WarningSet& disabled_warnings,
+ FileList& file_list,
+ AutoUnlinks& unlinks);
+
+ private:
+ Generator ();
+ };
+ }
+}
+
+#endif // CXX_HYBRID_GENERATOR_HXX
diff --git a/xsde/cxx/hybrid/parser-aggregate-header.cxx b/xsde/cxx/hybrid/parser-aggregate-header.cxx
new file mode 100644
index 0000000..a717c68
--- /dev/null
+++ b/xsde/cxx/hybrid/parser-aggregate-header.cxx
@@ -0,0 +1,837 @@
+// file : xsde/cxx/hybrid/parser-aggregate-header.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/hybrid/parser-aggregate-header.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/map.hxx>
+#include <cult/containers/set.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ 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
+ // base itself.
+ //
+ struct BaseType: Traversal::Complex, Context
+ {
+ BaseType (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ inherits (c);
+
+ if (!restriction_p (c))
+ {
+ names (c);
+ contains_compositor (c);
+ }
+ }
+ };
+
+ struct ParserDef: Traversal::Type,
+ Traversal::List,
+ Traversal::Complex,
+
+ Traversal::AnyType,
+ Traversal::AnySimpleType,
+
+ Traversal::Fundamental::Byte,
+ Traversal::Fundamental::UnsignedByte,
+ Traversal::Fundamental::Short,
+ Traversal::Fundamental::UnsignedShort,
+ Traversal::Fundamental::Int,
+ Traversal::Fundamental::UnsignedInt,
+ Traversal::Fundamental::Long,
+ Traversal::Fundamental::UnsignedLong,
+ Traversal::Fundamental::Integer,
+ Traversal::Fundamental::NonPositiveInteger,
+ Traversal::Fundamental::NonNegativeInteger,
+ Traversal::Fundamental::PositiveInteger,
+ Traversal::Fundamental::NegativeInteger,
+
+ Traversal::Fundamental::Boolean,
+
+ Traversal::Fundamental::Float,
+ Traversal::Fundamental::Double,
+ Traversal::Fundamental::Decimal,
+
+ Traversal::Fundamental::String,
+ Traversal::Fundamental::NormalizedString,
+ Traversal::Fundamental::Token,
+ Traversal::Fundamental::Name,
+ Traversal::Fundamental::NameToken,
+ Traversal::Fundamental::NameTokens,
+ Traversal::Fundamental::NCName,
+ Traversal::Fundamental::Language,
+
+ Traversal::Fundamental::QName,
+
+ Traversal::Fundamental::Id,
+ Traversal::Fundamental::IdRef,
+ Traversal::Fundamental::IdRefs,
+
+ Traversal::Fundamental::AnyURI,
+
+ Traversal::Fundamental::Base64Binary,
+ Traversal::Fundamental::HexBinary,
+
+ Traversal::Fundamental::Date,
+ Traversal::Fundamental::DateTime,
+ Traversal::Fundamental::Duration,
+ Traversal::Fundamental::Day,
+ Traversal::Fundamental::Month,
+ Traversal::Fundamental::MonthDay,
+ Traversal::Fundamental::Year,
+ Traversal::Fundamental::YearMonth,
+ Traversal::Fundamental::Time,
+
+ Traversal::Fundamental::Entity,
+ Traversal::Fundamental::Entities,
+
+ Context
+ {
+ ParserDef (Context& c, TypeInstanceMap& map, InstanceSet& set)
+ : Context (c), map_ (map), set_ (set), 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 (map_.find (&t) == map_.end ())
+ {
+ String inst (find_instance_name (t));
+ map_[&t] = inst;
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::List& l)
+ {
+ if (map_.find (&l) == map_.end ())
+ {
+ String inst (find_instance_name (l));
+ map_[&l] = inst;
+
+ dispatch (l.argumented ().type ());
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ if (map_.find (&c) == map_.end ())
+ {
+ String inst (find_instance_name (c));
+ map_[&c] = inst;
+
+ // Use base type's parsers in case of a restriction
+ // since we are not capable of using a derived type
+ // in place of a base (no virtual d-tor, for one).
+ //
+ inherits (c);
+
+ if (!restriction_p (c))
+ {
+ names (c);
+ contains_compositor (c);
+ }
+ }
+ }
+
+ // anyType & anySimpleType.
+ //
+ virtual Void
+ traverse (SemanticGraph::AnyType& t)
+ {
+ fund_type (t, "any_type");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnySimpleType& t)
+ {
+ fund_type (t, "any_simple_type");
+ }
+
+ // Boolean.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Boolean& t)
+ {
+ fund_type (t, "boolean");
+ }
+
+ // Integral types.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Byte& t)
+ {
+ fund_type (t, "byte");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedByte& t)
+ {
+ fund_type (t, "unsigned_byte");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Short& t)
+ {
+ fund_type (t, "short");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedShort& t)
+ {
+ fund_type (t, "unsigned_short");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Int& t)
+ {
+ fund_type (t, "int");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedInt& t)
+ {
+ fund_type (t, "unsigned_int");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Long& t)
+ {
+ fund_type (t, "long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedLong& t)
+ {
+ fund_type (t, "unsigned_long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Integer& t)
+ {
+ fund_type (t, "integer");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonPositiveInteger& t)
+ {
+ fund_type (t, "non_positive_integer");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonNegativeInteger& t)
+ {
+ fund_type (t, "non_negative_integer");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::PositiveInteger& t)
+ {
+ fund_type (t, "positive_integer");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NegativeInteger& t)
+ {
+ fund_type (t, "negative_integer");
+ }
+
+ // Floats.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Float& t)
+ {
+ fund_type (t, "float");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Double& t)
+ {
+ fund_type (t, "double");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Decimal& t)
+ {
+ fund_type (t, "decimal");
+ }
+
+ // Strings.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::String& t)
+ {
+ fund_type (t, "string");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NormalizedString& t)
+ {
+ fund_type (t, "normalized_string");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Token& t)
+ {
+ fund_type (t, "token");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameToken& t)
+ {
+ fund_type (t, "nmtoken");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameTokens& t)
+ {
+ fund_type (t, "nmtokens");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Name& t)
+ {
+ fund_type (t, "name");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NCName& t)
+ {
+ fund_type (t, "ncname");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Language& t)
+ {
+ fund_type (t, "language");
+ }
+
+
+ // Qualified name.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::QName& t)
+ {
+ fund_type (t, "qname");
+ }
+
+
+ // ID/IDREF.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Id& t)
+ {
+ fund_type (t, "id");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRef& t)
+ {
+ fund_type (t, "idref");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRefs& t)
+ {
+ fund_type (t, "idrefs");
+ }
+
+ // URI.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::AnyURI& t)
+ {
+ fund_type (t, "uri");
+ }
+
+ // Binary.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Base64Binary& t)
+ {
+ fund_type (t, "base64_binary");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::HexBinary& t)
+ {
+ fund_type (t, "hex_binary");
+ }
+
+
+ // Date/time.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Date& t)
+ {
+ fund_type (t, "date");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::DateTime& t)
+ {
+ fund_type (t, "date_time");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Duration& t)
+ {
+ fund_type (t, "duration");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Day& t)
+ {
+ fund_type (t, "day");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Month& t)
+ {
+ fund_type (t, "month");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::MonthDay& t)
+ {
+ fund_type (t, "month_day");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Year& t)
+ {
+ fund_type (t, "year");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::YearMonth& t)
+ {
+ fund_type (t, "year_month");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Time& t)
+ {
+ fund_type (t, "time");
+ }
+
+ // Entity.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entity& t)
+ {
+ fund_type (t, "entity");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entities& t)
+ {
+ fund_type (t, "entities");
+ }
+
+ private:
+ virtual Void
+ fund_type (SemanticGraph::Type& t, String const& name)
+ {
+ if (map_.find (&t) == map_.end ())
+ {
+ String inst (find_instance_name (name));
+ map_[&t] = inst;
+ }
+ }
+
+ String
+ find_instance_name (String const& raw_name)
+ {
+ String name (escape (raw_name + L"_p_"));
+
+ for (UnsignedLong i (1); set_.find (name) != set_.end (); ++i)
+ {
+ std::wostringstream os;
+ os << i;
+ name = escape (raw_name + L"_p" + os.str () + L"_");
+ }
+
+ set_.insert (name);
+ return name;
+ }
+
+ String
+ find_instance_name (SemanticGraph::Type& t)
+ {
+ return find_instance_name (t.name ());
+ }
+
+ TypeInstanceMap& map_;
+ InstanceSet& set_;
+
+ BaseType 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 GlobalType: Traversal::Type, Context
+ {
+ GlobalType (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& t)
+ {
+ SemanticGraph::Context& tc (t.context ());
+
+ if (!tc.count ("paggr"))
+ return;
+
+ String const& name (tc.get<String> ("paggr"));
+
+ String pre (unclash (name, "pre"));
+ String post (unclash (name, "post"));
+ String root_parser (unclash (name, "root_parser"));
+ String error, reset;
+
+ InstanceSet set;
+ set.insert (pre);
+ set.insert (post);
+ set.insert (name);
+ set.insert (root_parser);
+
+ if (!exceptions)
+ {
+ error = unclash (name, "_error");
+ set.insert (error);
+ }
+
+ if (Context::reset)
+ {
+ reset = unclash (name, "reset");
+ set.insert (reset);
+ }
+
+ tc.set ("paggr-map", TypeInstanceMap ());
+ TypeInstanceMap& map (tc.get<TypeInstanceMap> ("paggr-map"));
+
+ ParserDef def (*this, map, set);
+ def.dispatch (t);
+
+ String const& root_member (map.find (&t)->second);
+
+ os << "// Parser aggregate for the " << comment (t.name ()) <<
+ " type." << endl
+ << "//" << endl;
+
+ os << "class " << name
+ << "{"
+ << "public:" << endl;
+
+ // c-tor ()
+ //
+ os << name << " ();"
+ << endl;
+
+ // pre ()
+ //
+ os << "void" << endl
+ << pre << " ()"
+ << "{"
+ << "this->" << root_member << ".pre ();"
+ << "}";
+
+ // post ()
+ //
+ String const& ret (pret_type (t));
+
+ os << ret << endl
+ << post << " ()"
+ << "{"
+ << (ret == L"void" ? "" : "return ") << "this->" <<
+ root_member << "." << post_name (t) << " ();"
+ << "}";
+
+ // root_parser ()
+ //
+ os << fq_name (t, "p:impl") << "&" << endl
+ << root_parser << " ()"
+ << "{"
+ << "return this->" << root_member << ";"
+ << "}";
+
+ // _error ()
+ //
+ if (error)
+ {
+ os << xs_ns_name () << "::parser_error" << endl
+ << error << " ()"
+ << "{"
+ << "return this->" << root_member << "._error ();"
+ << "}";
+ }
+
+ // reset ()
+ //
+ if (reset)
+ {
+ os << "void" << endl
+ << reset << " ()"
+ << "{"
+ << "this->" << root_member << "._reset ();"
+ << "}";
+ }
+
+ os << "public:" << endl;
+
+ for (TypeInstanceMap::Iterator i (map.begin ()), end (map.end ());
+ i != end; ++i)
+ os << fq_name (*i->first, "p:impl") << " " << i->second << ";";
+
+ os << "};";
+ }
+ };
+
+ struct GlobalElement: Traversal::Element, Context
+ {
+ GlobalElement (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ SemanticGraph::Context& ec (e.context ());
+
+ if (!ec.count ("paggr"))
+ return;
+
+ SemanticGraph::Type& t (e.type ());
+ String const& name (ec.get<String> ("paggr"));
+
+ String pre (unclash (name, "pre"));
+ String post (unclash (name, "post"));
+ String root_parser (unclash (name, "root_parser"));
+ String root_name (unclash (name, "root_name"));
+ String root_namespace (unclash (name, "root_namespace"));
+ String error, reset;
+
+ InstanceSet set;
+ set.insert (pre);
+ set.insert (post);
+ set.insert (name);
+ set.insert (root_parser);
+ set.insert (root_name);
+ set.insert (root_namespace);
+
+ if (!exceptions)
+ {
+ error = unclash (name, "_error");
+ set.insert (error);
+ }
+
+ if (Context::reset)
+ {
+ reset = unclash (name, "reset");
+ set.insert (reset);
+ }
+
+ ec.set ("paggr-map", TypeInstanceMap ());
+ TypeInstanceMap& map (ec.get<TypeInstanceMap> ("paggr-map"));
+
+ ParserDef def (*this, map, set);
+ def.dispatch (t);
+
+ String const& root_member (map.find (&t)->second);
+
+ os << "// Parser aggregate for the " << comment (e.name ()) <<
+ " element." << endl
+ << "//" << endl;
+
+ os << "class " << name
+ << "{"
+ << "public:" << endl;
+
+ // c-tor ()
+ //
+ os << name << " ();"
+ << endl;
+
+ // pre ()
+ //
+ os << "void" << endl
+ << pre << " ()"
+ << "{"
+ << "this->" << root_member << ".pre ();"
+ << "}";
+
+ // post ()
+ //
+ String const& ret (pret_type (t));
+
+ os << ret << endl
+ << post << " ()"
+ << "{"
+ << (ret == L"void" ? "" : "return ") << "this->" <<
+ root_member << "." << post_name (t) << " ();"
+ << "}";
+
+ // root_parser ()
+ //
+ os << fq_name (t, "p:impl") << "&" << endl
+ << root_parser << " ()"
+ << "{"
+ << "return this->" << root_member << ";"
+ << "}";
+
+ // root_name ()
+ //
+ os << "static const char*" << endl
+ << root_name << " ();"
+ << endl;
+
+ // root_namespace ()
+ //
+ os << "static const char*" << endl
+ << root_namespace << " ();"
+ << endl;
+
+ // _error ()
+ //
+ if (error)
+ {
+ os << xs_ns_name () << "::parser_error" << endl
+ << error << " ()"
+ << "{"
+ << "return this->" << root_member << "._error ();"
+ << "}";
+ }
+
+ // reset ()
+ //
+ if (reset)
+ {
+ os << "void" << endl
+ << reset << " ()"
+ << "{"
+ << "this->" << root_member << "._reset ();"
+ << "}";
+ }
+
+ os << "public:" << endl;
+
+ for (TypeInstanceMap::Iterator i (map.begin ()), end (map.end ());
+ i != end; ++i)
+ os << fq_name (*i->first, "p:impl") << " " << i->second << ";";
+
+ os << "};";
+ }
+ };
+ }
+
+ Void
+ generate_parser_aggregate_header (Context& ctx)
+ {
+ Boolean gen (false);
+
+ {
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+
+ schema >> sources >> schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names names;
+ AggregateTest test (gen, "paggr");
+
+ schema >> schema_names >> ns >> names >> test;
+
+ schema.dispatch (ctx.schema_root);
+ }
+
+ if (gen)
+ {
+ // Emit "weak" header includes that are used in the file-per-type
+ // compilation model.
+ //
+ {
+ Traversal::Schema schema;
+ Includes includes (ctx, Includes::source);
+
+ schema >> includes;
+
+ schema.dispatch (ctx.schema_root);
+ }
+
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+
+ schema >> sources >> schema;
+
+ Traversal::Names schema_names;
+ Namespace ns (ctx);
+ Traversal::Names names;
+
+ schema >> schema_names >> ns >> names;
+
+ GlobalType type (ctx);
+ GlobalElement element (ctx);
+
+ names >> type;
+ names >> element;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+ }
+}
diff --git a/xsde/cxx/hybrid/parser-aggregate-header.hxx b/xsde/cxx/hybrid/parser-aggregate-header.hxx
new file mode 100644
index 0000000..ea10495
--- /dev/null
+++ b/xsde/cxx/hybrid/parser-aggregate-header.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/hybrid/parser-aggregate-header.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_PARSER_AGGREGATE_HEADER_HXX
+#define CXX_HYBRID_PARSER_AGGREGATE_HEADER_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/hybrid/elements.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ Void
+ generate_parser_aggregate_header (Context&);
+ }
+}
+
+#endif // CXX_HYBRID_PARSER_AGGREGATE_HEADER_HXX
diff --git a/xsde/cxx/hybrid/parser-aggregate-source.cxx b/xsde/cxx/hybrid/parser-aggregate-source.cxx
new file mode 100644
index 0000000..6e80318
--- /dev/null
+++ b/xsde/cxx/hybrid/parser-aggregate-source.cxx
@@ -0,0 +1,330 @@
+// file : xsde/cxx/hybrid/parser-aggregate-source.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/hybrid/parser-aggregate-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/map.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ namespace
+ {
+ typedef
+ Cult::Containers::Map<SemanticGraph::Type*, String>
+ TypeInstanceMap;
+
+ //
+ //
+ struct ParticleArg: Traversal::Element, Context
+ {
+ ParticleArg (Context& c, TypeInstanceMap& map, Boolean& first)
+ : Context (c), map_ (map), first_ (first)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (!first_)
+ os << "," << endl;
+ else
+ first_ = false;
+
+ os << "this->" << map_[&e.type ()];
+ }
+
+ private:
+ TypeInstanceMap& map_;
+ Boolean& first_;
+ };
+
+ struct AttributeArg: Traversal::Attribute, Context
+ {
+ AttributeArg (Context& c, TypeInstanceMap& map, Boolean& first)
+ : Context (c), map_ (map), first_ (first)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ if (!first_)
+ os << "," << endl;
+ else
+ first_ = false;
+
+ os << "this->" << map_[&a.type ()];
+ }
+
+ private:
+ TypeInstanceMap& map_;
+ Boolean& first_;
+ };
+
+ struct ArgList : Traversal::Complex,
+ Traversal::List,
+ Context
+ {
+ ArgList (Context& c, TypeInstanceMap& map)
+ : Context (c),
+ map_ (map),
+ particle_ (c, map, first_),
+ attribute_ (c, map, first_),
+ first_ (true)
+ {
+ inherits_ >> *this;
+
+ contains_compositor_ >> compositor_;
+ compositor_ >> contains_particle_;
+ contains_particle_ >> compositor_;
+ contains_particle_ >> particle_;
+
+ names_ >> attribute_;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ inherits (c, inherits_);
+
+ if (!restriction_p (c))
+ {
+ names (c, names_);
+ contains_compositor (c, contains_compositor_);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::List& l)
+ {
+ if (!first_)
+ os << "," << endl;
+ else
+ first_ = false;
+
+ os << "this->" << map_[&l.argumented ().type ()];
+ }
+
+ private:
+ TypeInstanceMap& map_;
+
+ Traversal::Inherits inherits_;
+
+ Traversal::Compositor compositor_;
+ ParticleArg particle_;
+ Traversal::ContainsCompositor contains_compositor_;
+ Traversal::ContainsParticle contains_particle_;
+
+ Traversal::Names names_;
+ AttributeArg attribute_;
+
+ Boolean first_;
+ };
+
+ struct ParserConnect: Traversal::List,
+ Traversal::Complex,
+ Context
+ {
+ ParserConnect (Context& c, TypeInstanceMap& map)
+ : Context (c), map_ (map)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::List& l)
+ {
+ os << "this->" << map_[&l] << ".parsers (this->" <<
+ map_[&l.argumented ().type ()] << ");"
+ << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ if (has_members (c))
+ {
+ os << "this->" << map_[&c] << ".parsers (";
+
+ ArgList args (*this, map_);
+ args.dispatch (c);
+
+ os << ");"
+ << endl;
+ }
+ }
+
+ private:
+ Boolean
+ has_members (SemanticGraph::Complex& c)
+ {
+ using SemanticGraph::Complex;
+
+ if (has<Traversal::Member> (c))
+ return true;
+
+ if (c.inherits_p ())
+ {
+ SemanticGraph::Type& b (c.inherits ().base ());
+
+ if (Complex* cb = dynamic_cast<Complex*> (&b))
+ return has_members (*cb);
+
+ return b.is_a<SemanticGraph::List> ();
+ }
+
+ return false;
+ }
+
+ private:
+ TypeInstanceMap& map_;
+ };
+
+ struct GlobalType: Traversal::Type, Context
+ {
+ GlobalType (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& t)
+ {
+ SemanticGraph::Context& tc (t.context ());
+
+ if (!tc.count ("paggr"))
+ return;
+
+ String const& name (tc.get<String> ("paggr"));
+ TypeInstanceMap& map (tc.get<TypeInstanceMap> ("paggr-map"));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ // c-tor ()
+ //
+ os << name << "::" << endl
+ << name << " ()"
+ << "{";
+
+ ParserConnect connect (*this, map);
+
+ for (TypeInstanceMap::Iterator i (map.begin ()), end (map.end ());
+ i != end; ++i)
+ connect.dispatch (*i->first);
+
+ os << "}";
+ }
+ };
+
+ struct GlobalElement: Traversal::Element, Context
+ {
+ GlobalElement (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ SemanticGraph::Context& ec (e.context ());
+
+ if (!ec.count ("paggr"))
+ return;
+
+ String const& name (ec.get<String> ("paggr"));
+ TypeInstanceMap& map (ec.get<TypeInstanceMap> ("paggr-map"));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ // c-tor ()
+ //
+ os << name << "::" << endl
+ << name << " ()"
+ << "{";
+
+ ParserConnect connect (*this, map);
+
+ for (TypeInstanceMap::Iterator i (map.begin ()), end (map.end ());
+ i != end; ++i)
+ connect.dispatch (*i->first);
+
+ os << "}";
+
+ // root_name ()
+ //
+ String root_name (unclash (name, "root_name"));
+
+ os << "const char* " << name << "::" << endl
+ << root_name << " ()"
+ << "{"
+ << "return " << strlit (e.name ()) << ";"
+ << "}";
+
+ // root_namespace ()
+ //
+ String root_namespace (unclash (name, "root_namespace"));
+
+ os << "const char* " << name << "::" << endl
+ << root_namespace << " ()"
+ << "{"
+ << "return " << strlit (e.namespace_ ().name ()) << ";"
+ << "}";
+ }
+ };
+ }
+
+ Void
+ generate_parser_aggregate_source (Context& ctx)
+ {
+ Boolean gen (false);
+
+ {
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+
+ schema >> sources >> schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names names;
+ AggregateTest test (gen, "paggr");
+
+ schema >> schema_names >> ns >> names >> test;
+
+ schema.dispatch (ctx.schema_root);
+ }
+
+ if (gen)
+ {
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+
+ schema >> sources >> schema;
+
+ Traversal::Names schema_names;
+ Namespace ns (ctx);
+ Traversal::Names names;
+
+ schema >> schema_names >> ns >> names;
+
+ GlobalType type (ctx);
+ GlobalElement element (ctx);
+
+ names >> type;
+ names >> element;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+ }
+}
diff --git a/xsde/cxx/hybrid/parser-aggregate-source.hxx b/xsde/cxx/hybrid/parser-aggregate-source.hxx
new file mode 100644
index 0000000..bb5b947
--- /dev/null
+++ b/xsde/cxx/hybrid/parser-aggregate-source.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/hybrid/parser-aggregate-source.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_PARSER_AGGREGATE_SOURCE_HXX
+#define CXX_HYBRID_PARSER_AGGREGATE_SOURCE_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/hybrid/elements.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ Void
+ generate_parser_aggregate_source (Context&);
+ }
+}
+
+#endif // CXX_HYBRID_PARSER_AGGREGATE_SOURCE_HXX
diff --git a/xsde/cxx/hybrid/parser-header.cxx b/xsde/cxx/hybrid/parser-header.cxx
new file mode 100644
index 0000000..450a27e
--- /dev/null
+++ b/xsde/cxx/hybrid/parser-header.cxx
@@ -0,0 +1,574 @@
+// file : xsde/cxx/hybrid/parser-header.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/hybrid/parser-header.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ namespace
+ {
+ struct List: Traversal::List, Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String const& name (epimpl_custom (l));
+
+ // We may not need to generate the class if this parser is
+ // being customized.
+ //
+ if (name)
+ {
+ String item (unclash (epskel (l), "item"));
+
+ os << "class " << name << ": public " <<
+ (mixin ? "virtual " : "") << epskel (l)
+ << "{"
+ << "public:" << endl;
+
+ // d-tor & c-tor
+ //
+ os << "~" << name << " ();"
+ << name << " (bool = false);"
+ << endl;
+
+ // reset
+ //
+ if (reset)
+ os << "virtual void" << endl
+ << "_reset ();"
+ << endl;
+
+ // pre
+ //
+ os << "virtual void" << endl
+ << "pre ();"
+ << endl;
+
+ // item
+ //
+ String const& arg (parg_type (l.argumented ().type ()));
+
+ os << "virtual void" << endl
+ << item << " (" << arg << ");"
+ << endl;
+
+ // post
+ //
+ String const& ret (pret_type (l));
+
+ os << "virtual " << ret << endl
+ << post_name (l) << " ();"
+ << endl;
+
+ // pre_impl
+ //
+ String const& type (fq_name (l));
+
+ os << "void" << endl
+ << pre_impl_name (l) << " (" << type << "*);"
+ << endl;
+
+ os << (tiein ? "public:" : "protected:") << endl;
+
+ // State.
+ //
+ os << type << "* " << epstate_member (l) << ";"
+ << "bool " << epstate_base (l) << ";"
+ << "};";
+ }
+
+ // Generate include for custom parser.
+ //
+ if (l.context ().count ("p:impl-include"))
+ {
+ close_ns ();
+
+ os << "#include " << process_include_path (
+ l.context ().get<String> ("p:impl-include")) << endl
+ << endl;
+
+ open_ns ();
+ }
+ }
+ };
+
+ struct Union: Traversal::Union, Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ String const& name (epimpl_custom (u));
+
+ // We may not need to generate the class if this parser is
+ // being customized.
+ //
+ if (name)
+ {
+ Boolean fl (fixed_length (u));
+
+ os << "class " << name << ": public " <<
+ (mixin ? "virtual " : "") << epskel (u)
+ << "{"
+ << "public:" << endl;
+
+ if (!fl)
+ {
+ // d-tor & c-tor
+ //
+ os << "~" << name << " ();"
+ << name << " (bool = false);"
+ << endl;
+
+ // reset
+ //
+ if (reset)
+ os << "virtual void" << endl
+ << "_reset ();"
+ << endl;
+ }
+
+ // pre
+ //
+ os << "virtual void" << endl
+ << "pre ();"
+ << endl;
+
+ // _characters
+ //
+ os << "virtual void" << endl
+ << "_characters (const " << string_type << "&);"
+ << endl;
+
+ // post
+ //
+ String const& ret (pret_type (u));
+
+ os << "virtual " << ret << endl
+ << post_name (u) << " ();"
+ << endl;
+
+ String const& type (fq_name (u));
+
+ // pre_impl
+ //
+ if (!fl)
+ os << "void" << endl
+ << pre_impl_name (u) << " (" << type << "*);"
+ << endl;
+
+ os << (tiein ? "public:" : "protected:") << endl;
+
+ // State.
+ //
+ String const& state_type (epstate_type (u));
+
+ os << "struct " << state_type
+ << "{";
+
+ if (!fl)
+ os << type << "* " << "x_;";
+
+ if (stl)
+ os << "::std::string str_;";
+ else
+ os << "::xsde::cxx::string str_;";
+
+ os << "};"
+ << state_type << " " << epstate (u) << ";";
+
+ if (!fl)
+ os << "bool " << epstate_base (u) << ";";
+
+ os << "};";
+ }
+
+ // Generate include for custom parser.
+ //
+ if (u.context ().count ("p:impl-include"))
+ {
+ close_ns ();
+
+ os << "#include " << process_include_path (
+ u.context ().get<String> ("p:impl-include")) << endl
+ << endl;
+
+ open_ns ();
+ }
+ }
+ };
+
+ //
+ // State.
+ //
+
+ struct CompositorState: Traversal::Compositor, Context
+ {
+ CompositorState (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Compositor& c)
+ {
+ if (c.max () != 1)
+ {
+ String scope (fq_scope (c));
+
+ os << scope << "::" << etype (c) << "* " <<
+ epstate_member (c) << ";";
+ }
+
+ Compositor::traverse (c);
+ }
+ };
+
+
+ //
+ // Callbacks.
+ //
+
+ struct CompositorCallback: Traversal::All,
+ Traversal::Choice,
+ Traversal::Sequence,
+ Context
+ {
+ CompositorCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ // For the all compositor, maxOccurs=1 and minOccurs={0,1}.
+ //
+ if (a.min () == 0)
+ {
+ os << "virtual void" << endl
+ << eppresent (a) << " ();"
+ << endl;
+ }
+
+ Traversal::All::traverse (a);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ os << "virtual void" << endl
+ << eparm (c) << " (" << eparm_tag (c) << ");"
+ << endl;
+
+ Traversal::Choice::traverse (c);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ if (s.max () != 1)
+ {
+ os << "virtual void" << endl
+ << epnext (s) << " ();"
+ << endl;
+ }
+ else if (s.min () == 0)
+ {
+ os << "virtual void" << endl
+ << eppresent (s) << " ();"
+ << endl;
+ }
+
+ Traversal::Sequence::traverse (s);
+ }
+ };
+
+ struct ParticleCallback: Traversal::Element, Context
+ {
+ ParticleCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ String const& arg (parg_type (e.type ()));
+
+ os << "virtual void" << endl
+ << epname (e) << " (";
+
+ if (arg != L"void")
+ os << arg;
+
+ os << ");"
+ << endl;
+ }
+ };
+
+ struct AttributeCallback: Traversal::Attribute, Context
+ {
+ AttributeCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ String const& arg (parg_type (a.type ()));
+
+ os << "virtual void" << endl
+ << epname (a) << " (";
+
+ if (arg != L"void")
+ os << arg;
+
+ os << ");"
+ << endl;
+ }
+ };
+
+
+ //
+ //
+ struct Complex : Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c),
+ // State.
+ //
+ compositor_state_ (c),
+
+ // Callbacks.
+ //
+ compositor_callback_ (c),
+ particle_callback_ (c),
+ attribute_callback_ (c)
+ {
+ // State.
+ //
+ contains_compositor_state_ >> compositor_state_;
+ compositor_state_ >> contains_particle_state_;
+ contains_particle_state_ >> compositor_state_;
+
+ // Callbacks.
+ //
+ contains_compositor_callback_ >> compositor_callback_;
+ compositor_callback_ >> contains_particle_callback_;
+ contains_particle_callback_ >> compositor_callback_;
+ contains_particle_callback_ >> particle_callback_;
+
+ names_attribute_callback_ >> attribute_callback_;
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ String const& name (epimpl_custom (c));
+
+ // We may not need to generate the class if this parser is
+ // being customized.
+ //
+ if (name)
+ {
+ Boolean hb (c.inherits_p ());
+ Boolean he (has<Traversal::Element> (c));
+ Boolean ha (has<Traversal::Attribute> (c));
+ Boolean hae (has_particle<Traversal::Any> (c));
+
+ Boolean restriction (restriction_p (c));
+ Boolean fixed (fixed_length (c));
+
+ String const& ret (pret_type (c));
+
+ os << "class " << name << ": public " <<
+ (mixin ? "virtual " : "") << epskel (c);
+
+ if (mixin && hb)
+ os << "," << endl
+ << " public " << fq_name (c.inherits ().base (), "p:impl");
+
+ os << "{"
+ << "public:" << endl;
+
+ // c-tor
+ //
+ if (!fixed || (hb && tiein))
+ os << name << " (" << (fixed ? "" : "bool = false") << ");"
+ << endl;
+
+ if (!fixed)
+ {
+ // d-tor
+ //
+ os << "~" << name << " ();"
+ << endl;
+
+ // reset
+ //
+ if (reset)
+ os << "virtual void" << endl
+ << "_reset ();"
+ << endl;
+ }
+
+ // pre
+ //
+ os << "virtual void" << endl
+ << "pre ();"
+ << endl;
+
+ // In case of an inheritance-by-restriction, we don't need to
+ // generate parser callbacks, etc. since they are the same as
+ // in the base.
+ //
+ if (!restriction)
+ {
+ if (ha)
+ {
+ os << "// Attributes." << endl
+ << "//" << endl;
+
+ names (c, names_attribute_callback_);
+ }
+
+ if (he || hae)
+ {
+ os << "// Elements." << endl
+ << "//" << endl;
+
+ contains_compositor (c, contains_compositor_callback_);
+ }
+ }
+
+ // post
+ //
+ os << "virtual " << ret << endl
+ << post_name (c) << " ();"
+ << endl;
+
+ // pre_impl
+ //
+ String const& type (fq_name (c));
+
+ if (!fixed)
+ os << (tiein ? "public:" : "protected:") << endl
+ << "void" << endl
+ << pre_impl_name (c) << " (" << type << "*);"
+ << endl;
+
+ // State.
+ //
+ String const& state_type (epstate_type (c));
+ String const& member (epstate_member (c));
+
+ os << (tiein ? "public:" : "protected:") << endl
+ << "struct " << state_type
+ << "{";
+
+ if (fixed)
+ os << type << " " << member << ";";
+ else
+ os << type << "* " << member << ";";
+
+ if (!restriction && c.contains_compositor_p ())
+ contains_compositor (c, contains_compositor_state_);
+
+ os << "};"
+ << state_type << " " << epstate (c) << ";";
+
+ if (!fixed)
+ os << "bool " << epstate_base (c) << ";";
+
+ os << endl;
+
+ // Base implementation.
+ //
+ if (tiein && hb)
+ os << (tiein ? "public:" : "protected:") << endl
+ << fq_name (c.inherits ().base (), "p:impl") << " base_impl_;"
+ << endl;
+
+ os << "};";
+ }
+
+ // Generate include for custom parser.
+ //
+ if (c.context ().count ("p:impl-include"))
+ {
+ close_ns ();
+
+ os << "#include " << process_include_path (
+ c.context ().get<String> ("p:impl-include")) << endl
+ << endl;
+
+ open_ns ();
+ }
+ }
+
+ private:
+ // State.
+ //
+ CompositorState compositor_state_;
+ Traversal::ContainsCompositor contains_compositor_state_;
+ Traversal::ContainsParticle contains_particle_state_;
+
+ // Callbacks.
+ //
+ CompositorCallback compositor_callback_;
+ ParticleCallback particle_callback_;
+ Traversal::ContainsCompositor contains_compositor_callback_;
+ Traversal::ContainsParticle contains_particle_callback_;
+
+ AttributeCallback attribute_callback_;
+ Traversal::Names names_attribute_callback_;
+ };
+ }
+
+ Void
+ generate_parser_header (Context& ctx)
+ {
+ Traversal::Schema schema;
+
+ Traversal::Sources sources;
+ Includes includes (ctx, Includes::impl_header);
+ Traversal::Names schema_names;
+
+ Namespace ns (ctx, true);
+ Traversal::Names names;
+
+ schema >> includes;
+ schema >> sources >> schema;
+ schema >> schema_names >> ns >> names;
+
+ List list (ctx);
+ Union union_ (ctx);
+ Complex complex (ctx);
+
+ names >> list;
+ names >> union_;
+ names >> complex;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+}
diff --git a/xsde/cxx/hybrid/parser-header.hxx b/xsde/cxx/hybrid/parser-header.hxx
new file mode 100644
index 0000000..1663b3b
--- /dev/null
+++ b/xsde/cxx/hybrid/parser-header.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/hybrid/parser-header.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_PARSER_HEADER_HXX
+#define CXX_HYBRID_PARSER_HEADER_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/hybrid/elements.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ Void
+ generate_parser_header (Context&);
+ }
+}
+
+#endif // CXX_HYBRID_PARSER_HEADER_HXX
diff --git a/xsde/cxx/hybrid/parser-name-processor.cxx b/xsde/cxx/hybrid/parser-name-processor.cxx
new file mode 100644
index 0000000..482c195
--- /dev/null
+++ b/xsde/cxx/hybrid/parser-name-processor.cxx
@@ -0,0 +1,709 @@
+// file : xsde/cxx/hybrid/parser-name-processor.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/elements.hxx>
+#include <cxx/hybrid/parser-name-processor.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/set.hxx>
+#include <cult/containers/map.hxx>
+
+#include <sstream>
+#include <iostream>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ namespace
+ {
+ //
+ //
+ typedef Cult::Containers::Set<String> NameSet;
+
+ class Context: public CXX::Context
+ {
+ public:
+ Context (CLI::Options const& ops,
+ SemanticGraph::Schema& root,
+ SemanticGraph::Path const& file)
+ : CXX::Context (std::wcerr,
+ root,
+ "name",
+ "char",
+ ops.value<CLI::include_with_brackets> (),
+ ops.value<CLI::include_prefix> (),
+ "", // export symbol
+ ops.value<CLI::namespace_map> (),
+ ops.value<CLI::namespace_regex> (),
+ ops.value<CLI::namespace_regex_trace> (),
+ ops.value<CLI::include_regex> (),
+ ops.value<CLI::include_regex_trace> (),
+ ops.value<CLI::generate_inline> (),
+ ops.value<CLI::reserved_name> ()),
+ schema_path_ (file),
+ impl_suffix_ (ops.value<CLI::pimpl_type_suffix> ()),
+ aggr_suffix_ (ops.value<CLI::paggr_type_suffix> ()),
+ options (ops),
+ schema (root),
+ schema_path (schema_path_),
+ aggregate (ops.value<CLI::generate_aggregate> ()),
+ impl_suffix (impl_suffix_),
+ aggr_suffix (aggr_suffix_),
+ custom_parser_map (custom_parser_map_),
+ global_type_names (global_type_names_)
+ {
+ // Custom parser mapping.
+ //
+ typedef Containers::Vector<NarrowString> Vector;
+ Vector const& v (ops.value<CLI::custom_parser> ());
+
+ for (Vector::ConstIterator i (v.begin ()), e (v.end ());
+ i != e; ++i)
+ {
+ String s (*i);
+
+ if (s.empty ())
+ continue;
+
+ // Split the string in two parts at the last '='.
+ //
+ Size pos (s.rfind ('='));
+
+ // If no delimiter found then both base and include are empty.
+ //
+ if (pos == String::npos)
+ {
+ custom_parser_map_[s].base.clear ();
+ custom_parser_map_[s].include.clear ();
+ continue;
+ }
+
+ String name (s, 0, pos);
+ String rest (s, pos + 1);
+
+ // See if we've got the include part after '/'.
+ //
+ pos = rest.find ('/');
+
+ String base, include;
+
+ if (pos != String::npos)
+ {
+ base.assign (rest, 0, pos);
+ include.assign (rest, pos + 1, String::npos);
+ }
+ else
+ base = rest;
+
+ custom_parser_map_[name].base = base;
+ custom_parser_map_[name].include = include;
+ }
+ }
+
+ protected:
+ Context (Context& c)
+ : CXX::Context (c),
+ options (c.options),
+ schema (c.schema),
+ schema_path (c.schema_path),
+ aggregate (c.aggregate),
+ impl_suffix (c.impl_suffix),
+ aggr_suffix (c.aggr_suffix),
+ custom_parser_map (c.custom_parser_map),
+ global_type_names (c.global_type_names)
+ {
+ }
+
+ public:
+ Boolean
+ fixed_length (SemanticGraph::Type& t)
+ {
+ return t.context ().get<Boolean> ("fixed");
+ }
+
+ public:
+ String
+ find_name (String const& n, String const& suffix, NameSet& set)
+ {
+ String name (escape (n + suffix));
+
+ for (UnsignedLong i (1); set.find (name) != set.end (); ++i)
+ {
+ std::wostringstream os;
+ os << i;
+ name = escape (n + os.str () + suffix);
+ }
+
+ set.insert (name);
+ return name;
+ }
+
+ String
+ find_name (String const& n, NameSet& set)
+ {
+ return find_name (n, L"", set);
+ }
+
+ public:
+ using CXX::Context::ename;
+
+ static String const&
+ ename (SemanticGraph::Compositor& c)
+ {
+ return c.context ().get<String> ("name");
+ }
+
+ String
+ state_name (SemanticGraph::Compositor& c)
+ {
+ using namespace SemanticGraph;
+
+ String r;
+
+ for (Compositor* p (&c);;
+ p = &p->contained_particle ().compositor ())
+ {
+ if (p->context ().count ("type"))
+ {
+ // Not a see-through compositor.
+ //
+ if (!r)
+ r = ename (*p);
+ else
+ {
+ String tmp;
+ tmp.swap (r);
+ r = ename (*p);
+ r += L"_";
+ r += tmp;
+ }
+ }
+
+ if (p->contained_compositor_p ())
+ break;
+ }
+
+ return r;
+ }
+
+ String
+ state_name (SemanticGraph::Element& e)
+ {
+ String r (state_name (e.contained_particle ().compositor ()));
+
+ if (!r)
+ r = ename (e);
+ else
+ {
+ r += L"_";
+ r += ename (e);
+ }
+
+ return r;
+ }
+
+ public:
+ struct CustomParser
+ {
+ CustomParser (String const& b = L"", String const& i = L"")
+ : base (b), include (i)
+ {
+ }
+
+ String base;
+ String include;
+ };
+
+ typedef
+ Cult::Containers::Map<String, CustomParser>
+ CustomParserMap;
+
+ private:
+ SemanticGraph::Path const schema_path_;
+ String const impl_suffix_;
+ String const aggr_suffix_;
+ CustomParserMap custom_parser_map_;
+
+ Cult::Containers::Map<String, NameSet*> global_type_names_;
+
+ public:
+ CLI::Options const& options;
+ SemanticGraph::Schema& schema;
+ SemanticGraph::Path const& schema_path;
+ Boolean aggregate;
+ String const& impl_suffix;
+ String const& aggr_suffix;
+ CustomParserMap const& custom_parser_map;
+
+ Cult::Containers::Map<String, NameSet*>& global_type_names;
+ };
+
+ //
+ //
+ struct List: Traversal::List, Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ SemanticGraph::Context& lc (l.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 (lc.count ("p:impl-base")
+ ? lc.get<String> ("p:impl-base")
+ : lc.get<String> ("p:impl"));
+ if (!name)
+ return;
+
+ NameSet set;
+ set.insert (name);
+ set.insert (unclash (lc.get<String> ("p:name"), "item"));
+
+ lc.set ("pstate-member",
+ find_name (lc.get<String> ("name"), "_", set));
+
+ lc.set ("pstate-base", find_name (name + L"_base", "_", set));
+ }
+ };
+
+ //
+ //
+ struct Union: Traversal::Union, Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ SemanticGraph::Context& uc (u.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 (uc.count ("p:impl-base")
+ ? uc.get<String> ("p:impl-base")
+ : uc.get<String> ("p:impl"));
+ if (!name)
+ return;
+
+ NameSet set;
+ set.insert (name);
+
+ String state_type (find_name (name + L"_state", set));
+
+ uc.set ("pstate-type", state_type);
+ uc.set ("pstate", find_name (state_type, "_", set));
+
+ if (!fixed_length (u))
+ uc.set ("pstate-base", find_name (name + L"_base", "_", set));
+ }
+ };
+
+ // State names.
+ //
+
+ struct CompositorState: Traversal::Compositor, Context
+ {
+ CompositorState (Context& c, NameSet& set)
+ : Context (c), set_ (set)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Compositor& c)
+ {
+ if (c.max () != 1)
+ {
+ SemanticGraph::Context& cc (c.context ());
+ cc.set ("pstate-member", find_name (state_name (c), L"_", set_));
+ }
+
+ Compositor::traverse (c);
+ }
+
+ private:
+ NameSet& set_;
+ };
+
+ //
+ //
+ struct Complex: Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ Boolean restriction (false);
+
+ if (c.inherits_p ())
+ restriction = c.inherits ().is_a<SemanticGraph::Restricts> () &&
+ !c.inherits ().base ().is_a<SemanticGraph::AnyType> ();
+
+ SemanticGraph::Context& cc (c.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& base (cc.count ("p:impl-base")
+ ? cc.get<String> ("p:impl-base")
+ : cc.get<String> ("p:impl"));
+
+ if (!base)
+ return;
+
+ // Use skeleton's name set to make sure we don't clash
+ // with callbacks which we are overriding.
+ //
+ NameSet& set (
+ cc.get<NameSet> ("cxx-parser-name-processor-member-set"));
+
+ String state_type (find_name (base + L"_state", set));
+
+ cc.set ("pstate-type", state_type);
+ cc.set ("pstate", find_name (state_type, "_", set));
+ cc.set ("pstate-base", find_name (base + L"_base", "_", set));
+
+ // State members are in a nested struct so use a new and
+ // empty name set.
+ //
+ NameSet state_set;
+
+ String member (
+ find_name (cc.get<String> ("name"), "_", state_set));
+
+ cc.set ("pstate-member", member);
+ state_set.insert (member);
+
+ // Assign state names.
+ //
+ if (!restriction && c.contains_compositor_p ())
+ {
+ CompositorState compositor (*this, state_set);
+ Traversal::ContainsCompositor contains_compositor;
+ Traversal::ContainsParticle contains_particle;
+
+ contains_compositor >> compositor;
+ contains_particle >> compositor >> contains_particle;
+
+ Complex::contains_compositor (c, contains_compositor);
+ }
+ }
+ };
+
+ //
+ //
+ struct GlobalType: Traversal::Type, Context
+ {
+ GlobalType (Context& c, NameSet& set)
+ : Context (c), set_ (set)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& t)
+ {
+ SemanticGraph::Context& tc (t.context ());
+ String const& name (t.name ());
+
+ tc.set ("p:impl", find_name (name + impl_suffix, set_));
+
+ // See if this parser is being customized.
+ //
+ CustomParserMap::ConstIterator i (custom_parser_map.find (name));
+
+ if (i != custom_parser_map.end ())
+ {
+ tc.set ("p:impl-base", i->second.base
+ ? find_name (i->second.base, set_)
+ : i->second.base);
+
+ if (i->second.include)
+ tc.set ("p:impl-include", i->second.include);
+ }
+
+ if (aggregate)
+ {
+ typedef Cult::Containers::Vector<NarrowString> Names;
+ Names const& names (options.value<CLI::root_type> ());
+
+ // Hopefully nobody will specify more than a handful of names.
+ //
+ for (Names::ConstIterator i (names.begin ());
+ i != names.end (); ++i)
+ {
+ if (name == String (*i))
+ {
+ tc.set ("paggr", find_name (name + aggr_suffix, set_));
+ break;
+ }
+ }
+ }
+ }
+
+ private:
+ NameSet& set_;
+ };
+
+ //
+ //
+ struct GlobalElement: Traversal::Element, Context
+ {
+ GlobalElement (Context& c, NameSet& set)
+ : Context (c), set_ (set), last_ (0)
+ {
+ }
+
+ ~GlobalElement ()
+ {
+ if (last_ != 0 && options.value<CLI::root_element_last> ())
+ process (*last_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ Boolean p (false);
+
+ if (last_ == 0 && options.value<CLI::root_element_first> ())
+ p = true;
+
+ last_ = &e;
+
+ if (!p &&
+ !options.value<CLI::root_element_first> () &&
+ !options.value<CLI::root_element_last> () &&
+ !options.value<CLI::root_element_all> () &&
+ !options.value<CLI::root_element_none> () &&
+ options.value<CLI::root_element> ().empty ())
+ {
+ // By default process them all.
+ //
+ p = true;
+ }
+
+ if (!p && options.value<CLI::root_element_all> ())
+ p = true;
+
+ if (!p)
+ {
+ typedef Cult::Containers::Vector<NarrowString> Names;
+ Names const& names (options.value<CLI::root_element> ());
+
+ // Hopefully nobody will specify more than a handful of names.
+ //
+ for (Names::ConstIterator i (names.begin ());
+ !p && i != names.end ();
+ ++i)
+ {
+ if (e.name () == String (*i))
+ p = true;
+ }
+ }
+
+ if (p)
+ process (e);
+ }
+
+ private:
+ Void
+ process (SemanticGraph::Element& e)
+ {
+ SemanticGraph::Context& ec (e.context ());
+
+ if (!ec.count ("paggr"))
+ {
+ ec.set ("paggr", find_name (e.name () + aggr_suffix, set_));
+ }
+ }
+
+ private:
+ NameSet& set_;
+ SemanticGraph::Element* last_;
+ };
+
+ struct Namespace: Traversal::Namespace, Context
+ {
+ Namespace (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& ns)
+ {
+ SemanticGraph::Context& nsc (ns.context ());
+ String const& name (ns.name ());
+
+ // Use a name set associated with this namespace if present.
+ // This will make sure that we don't get any conflicts in the
+ // multi-mapping translation case. Note that here we assume
+ // that all mappings traverse schemas in the same order which
+ // is currently the case.
+ //
+ if (global_type_names.find (name) == global_type_names.end ())
+ {
+ if (!nsc.count ("name-set"))
+ nsc.set ("name-set", NameSet ());
+
+ NameSet& s (nsc.get<NameSet> ("name-set"));
+ global_type_names[name] = &s;
+ }
+
+ NameSet& type_set (*global_type_names[name]);
+
+ // Parser implementations.
+ //
+ {
+ GlobalType type (*this, type_set);
+ Traversal::Names names (type);
+
+ Traversal::Namespace::names (ns, names);
+ }
+
+ // Parser aggregates.
+ //
+ if (aggregate)
+ {
+ GlobalElement element (*this, type_set);
+ Traversal::Names names (element);
+
+ Traversal::Namespace::names (ns, names);
+ }
+ }
+ };
+
+ // Go into sourced/included/imported schemas while making sure
+ // we don't process the same stuff more than once.
+ //
+ struct Uses: Traversal::Sources,
+ Traversal::Includes,
+ Traversal::Imports
+ {
+ virtual Void
+ traverse (SemanticGraph::Sources& sr)
+ {
+ SemanticGraph::Schema& s (sr.schema ());
+
+ if (!s.context ().count (seen_key))
+ {
+ s.context ().set (seen_key, true);
+ Traversal::Sources::traverse (sr);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Includes& i)
+ {
+ SemanticGraph::Schema& s (i.schema ());
+
+ if (!s.context ().count (seen_key))
+ {
+ s.context ().set (seen_key, true);
+ Traversal::Includes::traverse (i);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Imports& i)
+ {
+ SemanticGraph::Schema& s (i.schema ());
+
+ if (!s.context ().count (seen_key))
+ {
+ s.context ().set (seen_key, true);
+ Traversal::Imports::traverse (i);
+ }
+ }
+
+ static Char const* seen_key;
+ };
+
+ Char const* Uses::seen_key = "cxx-hybrid-parser-name-processor-seen";
+
+ Void
+ process_impl (CLI::Options const& ops,
+ SemanticGraph::Schema& tu,
+ SemanticGraph::Path const& file)
+ {
+ Context ctx (ops, tu, file);
+
+ // Pass one - assign names to global types. This pass cannot
+ // be combined with pass two because of possible recursive
+ // schema inclusions. Also note that we check first if this
+ // schema has already been processed which may happen in the
+ // file-per-type compilation mode.
+ //
+ if (!tu.context ().count (Uses::seen_key))
+ {
+ Traversal::Schema schema;
+ Uses uses;
+
+ schema >> uses >> schema;
+
+ Traversal::Names schema_names;
+ Namespace ns (ctx);
+
+ schema >> schema_names >> ns;
+
+ // Some twisted schemas do recusive self-inclusion.
+ //
+ tu.context ().set (Uses::seen_key, true);
+
+ schema.dispatch (tu);
+ }
+
+ // Pass two - assign names inside complex types. Here we don't
+ // need to go into included/imported schemas.
+ //
+ {
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+
+ schema >> sources >> schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+
+ schema >> schema_names >> ns >> ns_names;
+
+ List list (ctx);
+ Union union_ (ctx);
+ Complex complex (ctx);
+
+ ns_names >> list;
+ ns_names >> union_;
+ ns_names >> complex;
+
+ schema.dispatch (tu);
+ }
+ }
+ }
+
+ Void ParserNameProcessor::
+ process (CLI::Options const& ops,
+ SemanticGraph::Schema& tu,
+ SemanticGraph::Path const& file)
+ {
+ process_impl (ops, tu, file);
+ }
+ }
+}
diff --git a/xsde/cxx/hybrid/parser-name-processor.hxx b/xsde/cxx/hybrid/parser-name-processor.hxx
new file mode 100644
index 0000000..ea3e985
--- /dev/null
+++ b/xsde/cxx/hybrid/parser-name-processor.hxx
@@ -0,0 +1,32 @@
+// file : xsde/cxx/hybrid/parser-name-processor.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CXX_HYBRID_PARSER_NAME_PROCESSOR_HXX
+#define CXX_HYBRID_PARSER_NAME_PROCESSOR_HXX
+
+#include <cult/types.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+
+#include <cxx/hybrid/cli.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ using namespace Cult::Types;
+
+ class ParserNameProcessor
+ {
+ public:
+ Void
+ process (CLI::Options const& options,
+ XSDFrontend::SemanticGraph::Schema&,
+ XSDFrontend::SemanticGraph::Path const& file);
+ };
+ }
+}
+
+#endif // CXX_HYBRID_PARSER_NAME_PROCESSOR_HXX
diff --git a/xsde/cxx/hybrid/parser-source.cxx b/xsde/cxx/hybrid/parser-source.cxx
new file mode 100644
index 0000000..4f5fc38
--- /dev/null
+++ b/xsde/cxx/hybrid/parser-source.cxx
@@ -0,0 +1,1185 @@
+// file : xsde/cxx/hybrid/parser-source.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/hybrid/parser-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ namespace
+ {
+ struct List: Traversal::List, Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String const& name (epimpl_custom (l));
+
+ if (!name)
+ return;
+
+ String const& type (fq_name (l));
+ String const& base (epstate_base (l));
+ String const& member (epstate_member (l));
+ String item (unclash (epskel (l), "item"));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ // c-tor
+ //
+ os << name << "::" << endl
+ << name << " (bool b)"
+ << "{"
+ << "this->" << base << " = b;"
+ << "this->" << member << " = 0;"
+ << "}";
+
+ // d-tor
+ //
+ os << name << "::" << endl
+ << "~" << name << " ()"
+ << "{"
+ << "if (!this->" << base << ")" << endl
+ << "delete this->" << member << ";"
+ << "}";
+
+ // reset
+ //
+ if (reset)
+ os << "void " << name << "::" << endl
+ << "_reset ()"
+ << "{"
+ << epskel (l) << "::_reset ();"
+ << endl
+ << "if (!this->" << base << ")"
+ << "{"
+ << "delete this->" << member << ";"
+ << "this->" << member << " = 0;"
+ << "}"
+ << "}";
+
+ // pre_impl
+ //
+ os << "void " << name << "::" << endl
+ << pre_impl_name (l) << " (" << type << "* x)"
+ << "{"
+ << "this->" << member << " = x;"
+ << "}";
+
+ // pre
+ //
+ os << "void " << name << "::" << endl
+ << "pre ()"
+ << "{";
+
+ if (exceptions)
+ os << "this->" << pre_impl_name (l) << " (new " << type << ");";
+ else
+ os << type << "* x = new " << type << ";"
+ << "if (x)" << endl
+ << "this->" << pre_impl_name (l) << " (x);"
+ << "else" << endl
+ << "this->_sys_error (::xsde::cxx::sys_error::no_memory);";
+
+ os << "}";
+
+ // item
+ //
+ String const& arg (parg_type (l.argumented ().type ()));
+
+ os << "void " << name << "::" << endl
+ << item << " (" << arg << " i)"
+ << "{";
+
+ if (exceptions)
+ os << "this->" << member << "->push_back (i);";
+ else
+ os << "if (this->" << member << "->push_back (i))" << endl
+ << "this->_sys_error (::xsde::cxx::sys_error::no_memory);";
+
+ os << "}";
+
+ // post
+ //
+ String const& ret (pret_type (l));
+
+ os << ret << " " << name << "::" << endl
+ << post_name (l) << " ()"
+ << "{"
+ << type << "* r = this->" << member << ";"
+ << "this->" << member << " = 0;"
+ << "return r;"
+ << "}";
+ }
+ };
+
+ //
+ //
+ struct Union: Traversal::Union, Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ String const& name (epimpl_custom (u));
+
+ if (!name)
+ return;
+
+ String const& type (fq_name (u));
+ String const& state (epstate (u));
+ String const& ret (pret_type (u));
+ String const& value (u.context ().get<String> ("value"));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ if (stl)
+ {
+ // pre
+ //
+ os << "void " << name << "::" << endl
+ << "pre ()"
+ << "{"
+ << "this->" << state << ".str_.clear ();"
+ << "}";
+
+ // _characters
+ //
+ os << "void " << name << "::" << endl
+ << "_characters (const " << string_type << "& s)"
+ << "{"
+ << "this->" << state << ".str_.append (s.data (), s.size ());"
+ << "}";
+
+ // post
+ //
+ os << ret << " " << name << "::" << endl
+ << post_name (u) << " ()"
+ << "{"
+ << "::std::string s;"
+ << "s.swap (this->" << state << ".str_);"
+ << type << " r;"
+ << "r." << value << " (s);"
+ << "return r;"
+ << "}";
+ }
+ else
+ {
+ String const& base (epstate_base (u));
+
+ // c-tor
+ //
+ os << name << "::" << endl
+ << name << " (bool b)"
+ << "{"
+ << "this->" << base << " = b;"
+ << "this->" << state << ".x_ = 0;"
+ << "}";
+
+ // d-tor
+ //
+ os << name << "::" << endl
+ << "~" << name << " ()"
+ << "{"
+ << "if (!this->" << base << ")" << endl
+ << "delete this->" << state << ".x_;"
+ << "}";
+
+ // reset
+ //
+ if (reset)
+ os << "void " << name << "::" << endl
+ << "_reset ()"
+ << "{"
+ << epskel (u) << "::_reset ();"
+ << endl
+ << "if (!this->" << base << ")"
+ << "{"
+ << "delete this->" << state << ".x_;"
+ << "this->" << state << ".x_ = 0;"
+ << "}"
+ << "}";
+
+ // pre_impl
+ //
+ os << "void " << name << "::" << endl
+ << pre_impl_name (u) << " (" << type << "* x)"
+ << "{"
+ << "this->" << state << ".x_ = x;";
+
+ 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 (exceptions)
+ os << "this->" << pre_impl_name (u) << " (new " << type << ");";
+ else
+ os << type << "* x = new " << type << ";"
+ << "if (x)" << endl
+ << "this->" << pre_impl_name (u) << " (x);"
+ << "else" << endl
+ << "this->_sys_error (::xsde::cxx::sys_error::no_memory);";
+
+ os << "}";
+
+ // _characters
+ //
+ os << "void " << name << "::" << endl
+ << "_characters (const " << string_type << "& s)"
+ << "{";
+
+ 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
+ //
+ os << ret << " " << name << "::" << endl
+ << post_name (u) << " ()"
+ << "{"
+ << type << "* r = this->" << state << ".x_;"
+ << "this->" << state << ".x_ = 0;"
+ << "r->" << value << " (this->" << state << ".str_.detach ());"
+ << "return r;"
+ << "}";
+ }
+ }
+ };
+
+ struct ParserContext: Context
+ {
+ ParserContext (Context& c)
+ : Context (c)
+ {
+ }
+
+ // Return the access sequence up until this particle. If
+ // element is false then the access sequence for the
+ // container is returned. Otherwise the access sequence
+ // for the current element in the container is returned.
+ //
+ String
+ access_seq (SemanticGraph::Particle& p, Boolean element = true)
+ {
+ using namespace SemanticGraph;
+
+ String r;
+
+ Boolean seq (false);
+
+ Compositor* c;
+
+ if (p.contained_particle_p ())
+ {
+ c = &p.contained_particle ().compositor ();
+
+ // Check if this particle is a sequence. In this case
+ // we just need the top-level struct member.
+ //
+ if (element && p.max () != 1 && p.is_a<Compositor> ())
+ {
+ seq = true;
+ }
+ else
+ {
+ for (;; c = &c->contained_particle ().compositor ())
+ {
+ if (c->context ().count ("type"))
+ {
+ // Not a see-through compositor.
+ //
+ if (c->max () != 1)
+ {
+ String const& ptr (epstate_member (*c));
+
+ if (!r)
+ {
+ r = ptr;
+ r += L"->";
+ }
+ else
+ {
+ String tmp;
+ tmp.swap (r);
+ r = ptr;
+ r += L"->";
+ r += tmp;
+ }
+
+ seq = true;
+ break;
+ }
+ else
+ {
+ String const& func (ename (*c));
+
+ if (!r)
+ {
+ r = func;
+ r += L" ().";
+ }
+ else
+ {
+ String tmp;
+ tmp.swap (r);
+ r = func;
+ r += L" ().";
+ r += tmp;
+ }
+ }
+ }
+
+ if (c->contained_compositor_p ())
+ break;
+ }
+ }
+
+ // Get to the top in case we bailed out on a sequence.
+ //
+ while (!c->contained_compositor_p ())
+ c = &c->contained_particle ().compositor ();
+ }
+ else
+ {
+ // This particle is a top-level compositor.
+ //
+ c = &dynamic_cast<Compositor&> (p);
+ seq = element && c->max () != 1;
+ }
+
+ Complex& t (
+ dynamic_cast<Complex&> (
+ c->contained_compositor ().container ()));
+
+ if (!seq)
+ {
+ Boolean fixed (fixed_length (t));
+ String const& s (epstate_member (t));
+
+ if (!r)
+ {
+ r = s;
+ r += fixed ? L"." : L"->";
+ }
+ else
+ {
+ String tmp;
+ tmp.swap (r);
+ r = s;
+ r += fixed ? L"." : L"->";
+ r += tmp;
+ }
+ }
+
+ String tmp;
+ tmp.swap (r);
+ r = epstate (t);
+ r += L".";
+ r += tmp;
+
+ return r;
+ }
+
+ String
+ access_seq (SemanticGraph::Attribute& a)
+ {
+ using namespace SemanticGraph;
+
+ Complex& t (dynamic_cast<Complex&> (a.scope ()));
+
+ String r (epstate (t));
+ r += L".";
+ r += epstate_member (t);
+ r += fixed_length (t) ? L"." : L"->";
+
+ return r;
+ }
+ };
+
+ //
+ // Test for presence of var-length compositor in choice
+ // that need initialization.
+ //
+
+ struct CompositorTest: Traversal::Compositor
+ {
+ CompositorTest (Boolean& p)
+ : p_ (p)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Compositor& c)
+ {
+ // We are only interested in var-length required compositors.
+ //
+ if (c.max () == 1 &&
+ c.min () == 1 &&
+ !c.context ().get<Boolean> ("fixed"))
+ p_ = true;
+ }
+
+ private:
+ Boolean& p_;
+ };
+
+ //
+ // Callbacks.
+ //
+
+ struct CompositorCallback: Traversal::All,
+ Traversal::Choice,
+ Traversal::Sequence,
+ ParserContext
+ {
+ CompositorCallback (Context& c)
+ : ParserContext (c), compositor_test_ (init_)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ // For the all compositor, maxOccurs=1 and minOccurs={0,1}.
+ //
+ if (a.min () == 0)
+ {
+ String const& s (epimpl_custom (scope (a)));
+
+ os << "void " << s << "::" << endl
+ << eppresent (a) << " ()"
+ << "{";
+
+ String access (access_seq (a));
+
+ if (fixed_length (a))
+ os << "this->" << access << epresent (a) << " (true);";
+ else
+ {
+ String const& name (ename (a));
+ String const& type (etype (a));
+ String const& scope (fq_scope (a));
+
+ if (exceptions)
+ os << "this->" << access << name << " (new " <<
+ scope << "::" << type << ");";
+ else
+ os << scope << "::" << type << "* x = new " <<
+ scope << "::" << type << ";"
+ << "if (x)" << endl
+ << "this->" << access << name << " (x);"
+ << "else" << endl
+ << "this->_sys_error (::xsde::cxx::sys_error::no_memory);";
+ }
+
+ os << "}";
+ }
+
+ Traversal::All::traverse (a);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ String const& s (epimpl_custom (scope (c)));
+ String const& access (access_seq (c));
+ String const& type_scope (fq_scope (c));
+
+ os << "void " << s << "::" << endl
+ << eparm (c) << " (" << eparm_tag (c) << " t)"
+ << "{";
+
+ if (c.max () != 1)
+ {
+ String const& name (ename (c));
+ String const& type (etype (c));
+ String const& access_s (access_seq (c, false));
+ String const& ptr (epstate_member (c));
+
+ if (fixed_length (c))
+ {
+ if (exceptions)
+ os << "this->" << access_s << name << " ().push_back (" <<
+ type_scope << "::" << type << " ());";
+ else
+ os << "if (this->" << access_s << name << " ().push_back (" <<
+ type_scope << "::" << type << " ()))"
+ << "{"
+ << "this->_sys_error (::xsde::cxx::sys_error::no_memory);"
+ << "return;"
+ << "}";
+
+ os << "this->" << access << ptr << " = &this->" <<
+ access_s << name << " ().back ();";
+ }
+ else
+ {
+ os << "this->" << access << ptr << " = new " <<
+ type_scope << "::" << type << ";";
+
+ if (exceptions)
+ os << "this->" << access_s << name << " ().push_back (" <<
+ "this->" << access << ptr << ");";
+ else
+ os << "if (!this->" << access << ptr << " ||" << endl
+ << "this->" << access_s << name << " ().push_back (" <<
+ "this->" << access << ptr << "))"
+ << "{"
+ << "this->_sys_error (::xsde::cxx::sys_error::no_memory);"
+ << "return;"
+ << "}";
+ }
+
+ os << "this->" << access << ptr << "->";
+ }
+ else if (c.min () == 0)
+ {
+ String const& name (ename (c));
+
+ if (fixed_length (c))
+ os << "this->" << access << epresent (c) << " (true);";
+ else
+ {
+ String const& type (etype (c));
+
+ if (exceptions)
+ os << "this->" << access << name << " (new " <<
+ type_scope << "::" << type << ");";
+ else
+ os << type_scope << "::" << type << "* x = new " <<
+ type_scope << "::" << type << ";"
+ << "if (x)" << endl
+ << "this->" << access << name << " (x);"
+ << "else"
+ << "{"
+ << "this->_sys_error (::xsde::cxx::sys_error::no_memory);"
+ << "return;"
+ << "}";
+ }
+
+ os << "this->" << access << name << " ().";
+ }
+ else
+ {
+ // We may be in a choice in which case we get a nested
+ // type (and accessor function) even for min == max == 1.
+ //
+ if (c.context ().count ("type"))
+ os << "this->" << access << ename (c) << " ().";
+ else
+ os << "this->" << access;
+ }
+
+ os << earm (c) << " (static_cast< " << type_scope;
+
+ if (c.context ().count ("type"))
+ os << "::" << etype (c);
+
+ os << "::" << earm_tag (c) << " > (t));"
+ << endl;
+
+ // Test whether we have any arms that need initialization.
+ // Those are var-length required compositors.
+ //
+ init_ = false;
+
+ for (SemanticGraph::Choice::ContainsIterator
+ i (c.contains_begin ()), e (c.contains_end ());
+ !init_ && i != e; ++i)
+ {
+ compositor_test_.dispatch (i->particle ());
+ }
+
+ if (init_)
+ {
+ os << "switch (t)"
+ << "{";
+
+ for (SemanticGraph::Choice::ContainsIterator
+ i (c.contains_begin ()), e (c.contains_end ());
+ i != e; ++i)
+ {
+ // Test if this arm needs initialization.
+ //
+ init_ = false;
+ compositor_test_.dispatch (i->particle ());
+
+ if (init_)
+ {
+ SemanticGraph::Compositor& p (
+ dynamic_cast<SemanticGraph::Compositor&> (
+ i->particle ()));
+
+ os << "case " << eptag (p) << ":"
+ << "{";
+
+ String const& type (etype (p));
+ String const& scope (fq_scope (p));
+
+ if (exceptions)
+ os << "this->" << access_seq (p) << ename (p) <<
+ " (new " << scope << "::" << type << ");";
+ else
+ os << scope << "::" << type << "* x = new " <<
+ scope << "::" << type << ";"
+ << "if (x)" << endl
+ << "this->" << access_seq (p) << ename (p) << " (x);"
+ << "else" << endl
+ << "this->_sys_error (::xsde::cxx::sys_error::no_memory);";
+
+ os << "break;"
+ << "}";
+ }
+ }
+
+ os << "default:"
+ << "{"
+ << "break;"
+ << "}"
+ << "}";
+ }
+
+ os << "}";
+
+ Traversal::Choice::traverse (c);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ if (s.max () != 1)
+ {
+ String const& sc (epimpl_custom (scope (s)));
+
+ String const& access (access_seq (s));
+ String const& access_s (access_seq (s, false));
+ String const& name (ename (s));
+ String const& type (etype (s));
+ String const& scope (fq_scope (s));
+ String const& ptr (epstate_member (s));
+
+ os << "void " << sc << "::" << endl
+ << epnext (s) << " ()"
+ << "{";
+
+ if (fixed_length (s))
+ {
+ if (exceptions)
+ os << "this->" << access_s << name << " ().push_back (" <<
+ scope << "::" << type << " ());";
+ else
+ os << "if (this->" << access_s << name << " ().push_back (" <<
+ scope << "::" << type << " ()))"
+ << "{"
+ << "this->_sys_error (::xsde::cxx::sys_error::no_memory);"
+ << "return;"
+ << "}";
+
+ os << "this->" << access << ptr << " = &this->" <<
+ access_s << name << " ().back ();";
+ }
+ else
+ {
+ os << "this->" << access << ptr << " = new " <<
+ scope << "::" << type << ";";
+
+ if (exceptions)
+ os << "this->" << access_s << name << " ().push_back (" <<
+ "this->" << access << ptr << ");";
+ else
+ os << "if (!this->" << access << ptr << " ||" << endl
+ << "this->" << access_s << name << " ().push_back (" <<
+ "this->" << access << ptr << "))" << endl
+ << "this->_sys_error (::xsde::cxx::sys_error::no_memory);";
+ }
+
+ os << "}";
+ }
+ else if (s.min () == 0)
+ {
+ String const& sc (epimpl_custom (scope (s)));
+
+ os << "void " << sc << "::" << endl
+ << eppresent (s) << " ()"
+ << "{";
+
+ String access (access_seq (s));
+
+ if (fixed_length (s))
+ os << "this->" << access << epresent (s) << " (true);";
+ else
+ {
+ String const& name (ename (s));
+ String const& type (etype (s));
+ String const& scope (fq_scope (s));
+
+ if (exceptions)
+ os << "this->" << access << name << " (new " <<
+ scope << "::" << type << ");";
+ else
+ os << scope << "::" << type << "* x = new " <<
+ scope << "::" << type << ";"
+ << "if (x)" << endl
+ << "this->" << access << name << " (x);"
+ << "else" << endl
+ << "this->_sys_error (::xsde::cxx::sys_error::no_memory);";
+ }
+
+ os << "}";
+ }
+
+ Traversal::Sequence::traverse (s);
+ }
+
+ private:
+ SemanticGraph::Complex&
+ scope (SemanticGraph::Compositor& c)
+ {
+ SemanticGraph::Compositor* root (&c);
+
+ while (root->contained_particle_p ())
+ root = &root->contained_particle ().compositor ();
+
+ return dynamic_cast<SemanticGraph::Complex&> (
+ root->contained_compositor ().container ());
+ }
+
+ private:
+ Boolean init_;
+ CompositorTest compositor_test_;
+ };
+
+ struct ParticleCallback: Traversal::Element, ParserContext
+ {
+ ParticleCallback (Context& c)
+ : ParserContext (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ using SemanticGraph::Complex;
+
+ String const& name (epname (e));
+ String const& arg (parg_type (e.type ()));
+ Complex& c (dynamic_cast<Complex&> (e.scope ()));
+
+ os << "void " << epimpl_custom (c) << "::" << endl
+ << name << " (";
+
+ if (arg != L"void")
+ {
+ os << arg << " x)"
+ << "{";
+
+ if (e.max () != 1)
+ {
+ if (exceptions)
+ os << "this->" << access_seq (e) << ename (e) <<
+ " ().push_back (x);";
+ else
+ os << "if (this->" << access_seq (e) << ename (e) <<
+ " ().push_back (x))" << endl
+ << "this->_sys_error (::xsde::cxx::sys_error::no_memory);";
+ }
+ else
+ {
+ os << "this->" << access_seq (e) << ename (e) << " (x);";
+ }
+
+ os << "}";
+ }
+ else
+ {
+ os << ")"
+ << "{"
+ << "}";
+ }
+ }
+ };
+
+ struct AttributeCallback: Traversal::Attribute, ParserContext
+ {
+ AttributeCallback (Context& c)
+ : ParserContext (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ using SemanticGraph::Complex;
+
+ String const& name (epname (a));
+ String const& arg (parg_type (a.type ()));
+ Complex& c (dynamic_cast<Complex&> (a.scope ()));
+
+ os << "void " << epimpl_custom (c) << "::" << endl
+ << name << " (";
+
+ if (arg != L"void")
+ {
+ os << arg << " x)"
+ << "{"
+ << "this->" << access_seq (a) << ename (a) << " (x);"
+ << "}";
+ }
+ else
+ {
+ os << ")"
+ << "{"
+ << "}";
+ }
+ }
+ };
+
+ //
+ //
+ struct Complex : Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c),
+ base_name_ (c, TypeName::base),
+ compositor_callback_ (c),
+ particle_callback_ (c),
+ attribute_callback_ (c)
+ {
+ contains_compositor_callback_ >> compositor_callback_;
+ compositor_callback_ >> contains_particle_callback_;
+ contains_particle_callback_ >> compositor_callback_;
+ contains_particle_callback_ >> particle_callback_;
+
+ names_attribute_callback_ >> attribute_callback_;
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ String const& name (epimpl_custom (c));
+
+ if (!name)
+ return;
+
+ Boolean hb (c.inherits_p ());
+ Boolean restriction (restriction_p (c));
+ Boolean fixed (fixed_length (c));
+ Boolean c_string_base (false);
+
+ if (!stl && hb)
+ {
+ StringType test (c_string_base);
+ test.dispatch (c.inherits ().base ());
+ }
+
+ String const& ret (pret_type (c));
+
+ String const& state (epstate (c));
+ String const& member (epstate_member (c));
+ String const& type (fq_name (c));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ // c-tor
+ //
+ if (!fixed || (hb && tiein))
+ {
+ os << name << "::" << endl
+ << name << " (" << (fixed ? "" : "bool b") << ")";
+
+ if (hb)
+ {
+ if (tiein)
+ os << endl
+ << ": " << epskel (c) << " (&base_impl_)";
+
+ SemanticGraph::Type& b (c.inherits ().base ());
+
+ // C-string-based built-in parser implementations don't
+ // have c-tor (bool base).
+ //
+ if (!c_string_base && !fixed_length (b))
+ {
+ if (tiein)
+ os << "," << endl
+ << " " << "base_impl_" << " (true)";
+ else
+ os << endl
+ << ": " << fq_name (b, "p:impl") << " (true)";
+ }
+ }
+
+ os << "{";
+
+ if (!fixed)
+ os << "this->" << epstate_base (c) << " = b;"
+ << "this->" << state << "." << member << " = 0;";
+
+ os << "}";
+ }
+
+ if (!fixed)
+ {
+ // d-tor
+ //
+ os << name << "::" << endl
+ << "~" << name << " ()"
+ << "{"
+ << "if (!this->" << epstate_base (c) << ")" << endl
+ << "delete this->" << state << "." << member << ";"
+ << "}";
+
+ // reset
+ //
+ if (reset)
+ os << "void " << name << "::" << endl
+ << "_reset ()"
+ << "{";
+
+ if (mixin && hb)
+ os << epimpl (c); //@@ fq-name
+ else
+ os << epskel (c); //@@ fq-name
+
+ os << "::_reset ();"
+ << endl;
+
+ os << "if (!this->" << epstate_base (c) << ")"
+ << "{"
+ << "delete this->" << state << "." << member << ";"
+ << "this->" << state << "." << member << " = 0;"
+ << "}"
+ << "}";
+ }
+
+ // pre_impl
+ //
+ if (!fixed)
+ {
+ os << "void " << name << "::" << endl
+ << pre_impl_name (c) << " (" << type << "* x)"
+ << "{"
+ << "this->" << state << "." << member << " = x;";
+
+ // Call base pre_impl (var-length) or pre (fix-length). C-string-
+ // based built-in parser implementations don't have pre_impl().
+ //
+ if (hb && !c_string_base)
+ {
+ SemanticGraph::Type& b (c.inherits ().base ());
+
+ 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);";
+ }
+
+ os << "}";
+ }
+
+ // pre
+ //
+ os << "void " << name << "::" << endl
+ << "pre ()"
+ << "{";
+
+ if (fixed)
+ {
+ if (hb)
+ {
+ // Our base is also fixed-length so call its pre()
+ //
+ if (tiein)
+ os << "this->base_impl_.";
+ else
+ os << epimpl (c.inherits ().base ()) << "::"; //@@ fq-name.
+
+ os << "pre ();";
+ }
+
+ os << "this->" << state << "." << member << " = " <<
+ type << " ();";
+ }
+ else
+ {
+ if (exceptions)
+ os << "this->" << pre_impl_name (c) << " (new " << type << ");";
+ else
+ os << type << "* x = new " << type << ";"
+ << "if (x)" << endl
+ << "this->" << pre_impl_name (c) << " (x);"
+ << "else" << endl
+ << "this->_sys_error (::xsde::cxx::sys_error::no_memory);";
+ }
+
+ os << "}";
+
+ // Parser callbacks.
+ //
+ if (!restriction)
+ {
+ names (c, names_attribute_callback_);
+ contains_compositor (c, contains_compositor_callback_);
+ }
+
+ // post
+ //
+ os << ret << " " << name << "::" << endl
+ << post_name (c) << " ()"
+ << "{";
+
+ if (hb)
+ {
+ SemanticGraph::Type& b (c.inherits ().base ());
+
+ // Default parser implementations for anyType and
+ // anySimpleType return void.
+ //
+ if (!b.is_a<SemanticGraph::AnyType> () &&
+ !b.is_a<SemanticGraph::AnySimpleType> ())
+ {
+ // If our base is a fixed-length type or C-string-base, then
+ // copy the data over.
+ //
+ if (fixed_length (b))
+ {
+ os << "static_cast< ";
+
+ base_name_.dispatch (b);
+
+ os << "& > (" << (fixed ? "" : "*") << "this->" <<
+ state << "." << member << ") = ";
+ }
+
+ if (c_string_base)
+ {
+ os << "static_cast< ";
+
+ base_name_.dispatch (b);
+
+ os << "* > (this->" <<
+ state << "." << member << ")->base_value (";
+ }
+
+ if (tiein)
+ os << "this->base_impl_.";
+ else
+ os << epimpl (b) << "::"; //@@ fq-name.
+
+ os << post_name (b) << " ()";
+
+ if (c_string_base)
+ os << ")";
+
+ os << ";";
+ }
+ }
+
+ if (fixed)
+ os << "return this->" << state << "." << member << ";";
+ else
+ os << type << "* r = this->" << state << "." << member << ";"
+ << "this->" << state << "." << member << " = 0;"
+ << "return r;";
+
+ os << "}";
+ }
+
+ private:
+ TypeName base_name_;
+
+ CompositorCallback compositor_callback_;
+ ParticleCallback particle_callback_;
+ Traversal::ContainsCompositor contains_compositor_callback_;
+ Traversal::ContainsParticle contains_particle_callback_;
+
+ AttributeCallback attribute_callback_;
+ Traversal::Names names_attribute_callback_;
+ };
+ }
+
+ Void
+ generate_parser_source (Context& ctx)
+ {
+ {
+ // Emit "weak" header includes for the object model types.
+ // Otherwise we cannot delete the objects of forward-declared
+ // classes in the parser implementations.
+ //
+ Traversal::Schema schema;
+ Includes includes (ctx, Includes::source);
+
+ schema >> includes;
+
+ schema.dispatch (ctx.schema_root);
+ }
+
+ Traversal::Schema schema;
+
+ Traversal::Sources sources;
+ Traversal::Names schema_names;
+
+ Namespace ns (ctx);
+ Traversal::Names names;
+
+ schema >> sources >> schema;
+ schema >> schema_names >> ns >> names;
+
+ List list (ctx);
+ Union union_ (ctx);
+ Complex complex (ctx);
+
+ names >> list;
+ names >> union_;
+ names >> complex;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+}
diff --git a/xsde/cxx/hybrid/parser-source.hxx b/xsde/cxx/hybrid/parser-source.hxx
new file mode 100644
index 0000000..23f1399
--- /dev/null
+++ b/xsde/cxx/hybrid/parser-source.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/hybrid/parser-source.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_PARSER_SOURCE_HXX
+#define CXX_HYBRID_PARSER_SOURCE_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/hybrid/elements.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ Void
+ generate_parser_source (Context&);
+ }
+}
+
+#endif // CXX_HYBRID_PARSER_SOURCE_HXX
diff --git a/xsde/cxx/hybrid/serializer-aggregate-header.cxx b/xsde/cxx/hybrid/serializer-aggregate-header.cxx
new file mode 100644
index 0000000..b697715
--- /dev/null
+++ b/xsde/cxx/hybrid/serializer-aggregate-header.cxx
@@ -0,0 +1,847 @@
+// file : xsde/cxx/hybrid/serializer-aggregate-header.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/hybrid/serializer-aggregate-header.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/map.hxx>
+#include <cult/containers/set.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ 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
+ // base itself.
+ //
+ struct BaseType: Traversal::Complex, Context
+ {
+ BaseType (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ inherits (c);
+
+ if (!restriction_p (c))
+ {
+ names (c);
+ contains_compositor (c);
+ }
+ }
+ };
+
+ struct SerializerDef: Traversal::Type,
+ Traversal::List,
+ Traversal::Complex,
+
+ Traversal::AnyType,
+ Traversal::AnySimpleType,
+
+ Traversal::Fundamental::Byte,
+ Traversal::Fundamental::UnsignedByte,
+ Traversal::Fundamental::Short,
+ Traversal::Fundamental::UnsignedShort,
+ Traversal::Fundamental::Int,
+ Traversal::Fundamental::UnsignedInt,
+ Traversal::Fundamental::Long,
+ Traversal::Fundamental::UnsignedLong,
+ Traversal::Fundamental::Integer,
+ Traversal::Fundamental::NonPositiveInteger,
+ Traversal::Fundamental::NonNegativeInteger,
+ Traversal::Fundamental::PositiveInteger,
+ Traversal::Fundamental::NegativeInteger,
+
+ Traversal::Fundamental::Boolean,
+
+ Traversal::Fundamental::Float,
+ Traversal::Fundamental::Double,
+ Traversal::Fundamental::Decimal,
+
+ Traversal::Fundamental::String,
+ Traversal::Fundamental::NormalizedString,
+ Traversal::Fundamental::Token,
+ Traversal::Fundamental::Name,
+ Traversal::Fundamental::NameToken,
+ Traversal::Fundamental::NameTokens,
+ Traversal::Fundamental::NCName,
+ Traversal::Fundamental::Language,
+
+ Traversal::Fundamental::QName,
+
+ Traversal::Fundamental::Id,
+ Traversal::Fundamental::IdRef,
+ Traversal::Fundamental::IdRefs,
+
+ Traversal::Fundamental::AnyURI,
+
+ Traversal::Fundamental::Base64Binary,
+ Traversal::Fundamental::HexBinary,
+
+ Traversal::Fundamental::Date,
+ Traversal::Fundamental::DateTime,
+ Traversal::Fundamental::Duration,
+ Traversal::Fundamental::Day,
+ Traversal::Fundamental::Month,
+ Traversal::Fundamental::MonthDay,
+ Traversal::Fundamental::Year,
+ Traversal::Fundamental::YearMonth,
+ Traversal::Fundamental::Time,
+
+ Traversal::Fundamental::Entity,
+ Traversal::Fundamental::Entities,
+
+ Context
+ {
+ SerializerDef (Context& c, TypeInstanceMap& map, InstanceSet& set)
+ : Context (c), map_ (map), set_ (set), 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 (map_.find (&t) == map_.end ())
+ {
+ String inst (find_instance_name (t));
+ map_[&t] = inst;
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::List& l)
+ {
+ if (map_.find (&l) == map_.end ())
+ {
+ String inst (find_instance_name (l));
+ map_[&l] = inst;
+
+ dispatch (l.argumented ().type ());
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ if (map_.find (&c) == map_.end ())
+ {
+ String inst (find_instance_name (c));
+ map_[&c] = inst;
+
+ // Use base type's serializers in case of a restriction
+ // since we are not capable of using a derived type
+ // in place of a base (need upcasting, ect).
+ //
+ inherits (c);
+
+ if (!restriction_p (c))
+ {
+ names (c);
+ contains_compositor (c);
+ }
+ }
+ }
+
+ // anyType & anySimpleType.
+ //
+ virtual Void
+ traverse (SemanticGraph::AnyType& t)
+ {
+ fund_type (t, "any_type");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnySimpleType& t)
+ {
+ fund_type (t, "any_simple_type");
+ }
+
+ // Boolean.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Boolean& t)
+ {
+ fund_type (t, "boolean");
+ }
+
+ // Integral types.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Byte& t)
+ {
+ fund_type (t, "byte");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedByte& t)
+ {
+ fund_type (t, "unsigned_byte");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Short& t)
+ {
+ fund_type (t, "short");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedShort& t)
+ {
+ fund_type (t, "unsigned_short");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Int& t)
+ {
+ fund_type (t, "int");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedInt& t)
+ {
+ fund_type (t, "unsigned_int");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Long& t)
+ {
+ fund_type (t, "long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedLong& t)
+ {
+ fund_type (t, "unsigned_long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Integer& t)
+ {
+ fund_type (t, "integer");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonPositiveInteger& t)
+ {
+ fund_type (t, "non_positive_integer");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonNegativeInteger& t)
+ {
+ fund_type (t, "non_negative_integer");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::PositiveInteger& t)
+ {
+ fund_type (t, "positive_integer");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NegativeInteger& t)
+ {
+ fund_type (t, "negative_integer");
+ }
+
+ // Floats.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Float& t)
+ {
+ fund_type (t, "float");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Double& t)
+ {
+ fund_type (t, "double");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Decimal& t)
+ {
+ fund_type (t, "decimal");
+ }
+
+ // Strings.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::String& t)
+ {
+ fund_type (t, "string");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NormalizedString& t)
+ {
+ fund_type (t, "normalized_string");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Token& t)
+ {
+ fund_type (t, "token");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameToken& t)
+ {
+ fund_type (t, "nmtoken");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameTokens& t)
+ {
+ fund_type (t, "nmtokens");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Name& t)
+ {
+ fund_type (t, "name");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NCName& t)
+ {
+ fund_type (t, "ncname");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Language& t)
+ {
+ fund_type (t, "language");
+ }
+
+
+ // Qualified name.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::QName& t)
+ {
+ fund_type (t, "qname");
+ }
+
+
+ // ID/IDREF.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Id& t)
+ {
+ fund_type (t, "id");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRef& t)
+ {
+ fund_type (t, "idref");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRefs& t)
+ {
+ fund_type (t, "idrefs");
+ }
+
+ // URI.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::AnyURI& t)
+ {
+ fund_type (t, "uri");
+ }
+
+ // Binary.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Base64Binary& t)
+ {
+ fund_type (t, "base64_binary");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::HexBinary& t)
+ {
+ fund_type (t, "hex_binary");
+ }
+
+
+ // Date/time.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Date& t)
+ {
+ fund_type (t, "date");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::DateTime& t)
+ {
+ fund_type (t, "date_time");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Duration& t)
+ {
+ fund_type (t, "duration");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Day& t)
+ {
+ fund_type (t, "day");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Month& t)
+ {
+ fund_type (t, "month");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::MonthDay& t)
+ {
+ fund_type (t, "month_day");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Year& t)
+ {
+ fund_type (t, "year");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::YearMonth& t)
+ {
+ fund_type (t, "year_month");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Time& t)
+ {
+ fund_type (t, "time");
+ }
+
+ // Entity.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entity& t)
+ {
+ fund_type (t, "entity");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entities& t)
+ {
+ fund_type (t, "entities");
+ }
+
+ private:
+ virtual Void
+ fund_type (SemanticGraph::Type& t, String const& name)
+ {
+ if (map_.find (&t) == map_.end ())
+ {
+ String inst (find_instance_name (name));
+ map_[&t] = inst;
+ }
+ }
+
+ String
+ find_instance_name (String const& raw_name)
+ {
+ String name (escape (raw_name + L"_s_"));
+
+ for (UnsignedLong i (1); set_.find (name) != set_.end (); ++i)
+ {
+ std::wostringstream os;
+ os << i;
+ name = escape (raw_name + L"_s" + os.str () + L"_");
+ }
+
+ set_.insert (name);
+ return name;
+ }
+
+ String
+ find_instance_name (SemanticGraph::Type& t)
+ {
+ return find_instance_name (t.name ());
+ }
+
+ TypeInstanceMap& map_;
+ InstanceSet& set_;
+
+ BaseType 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 GlobalType: Traversal::Type, Context
+ {
+ GlobalType (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& t)
+ {
+ SemanticGraph::Context& tc (t.context ());
+
+ if (!tc.count ("saggr"))
+ return;
+
+ String const& name (tc.get<String> ("saggr"));
+
+ String pre (unclash (name, "pre"));
+ String post (unclash (name, "post"));
+ String root_serializer (unclash (name, "root_serializer"));
+ String error, reset;
+
+ InstanceSet set;
+ set.insert (pre);
+ set.insert (post);
+ set.insert (name);
+ set.insert (root_serializer);
+
+ if (!exceptions)
+ {
+ error = unclash (name, "_error");
+ set.insert (error);
+ }
+
+ if (Context::reset)
+ {
+ reset = unclash (name, "reset");
+ set.insert (reset);
+ }
+
+ tc.set ("saggr-map", TypeInstanceMap ());
+ TypeInstanceMap& map (tc.get<TypeInstanceMap> ("saggr-map"));
+
+ SerializerDef def (*this, map, set);
+ def.dispatch (t);
+
+ String const& root_member (map.find (&t)->second);
+
+ os << "// Serializer aggregate for the " << comment (t.name ()) <<
+ " type." << endl
+ << "//" << endl;
+
+ os << "class " << name
+ << "{"
+ << "public:" << endl;
+
+ // c-tor ()
+ //
+ os << name << " ();"
+ << endl;
+
+ // pre ()
+ //
+ String const& arg (sarg_type (t));
+
+ os << "void" << endl
+ << pre << " (";
+
+ if (arg != L"void")
+ os << arg << " x";
+
+ os <<")"
+ << "{"
+ << "this->" << root_member << ".pre (" <<
+ (arg != L"void" ? "x" : "") << ");"
+ << "}";
+
+ // post ()
+ //
+ os << "void" << endl
+ << post << " ()"
+ << "{"
+ << "this->" << root_member << ".post ();"
+ << "}";
+
+ // root_serializer ()
+ //
+ os << fq_name (t, "s:impl") << "&" << endl
+ << root_serializer << " ()"
+ << "{"
+ << "return this->" << root_member << ";"
+ << "}";
+
+ // _error ()
+ //
+ if (error)
+ {
+ os << xs_ns_name () << "::serializer_error" << endl
+ << error << " ()"
+ << "{"
+ << "return this->" << root_member << "._error ();"
+ << "}";
+ }
+
+ // reset ()
+ //
+ if (reset)
+ {
+ os << "void" << endl
+ << reset << " ()"
+ << "{"
+ << "this->" << root_member << "._reset ();"
+ << "}";
+ }
+
+ os << "public:" << endl;
+
+ for (TypeInstanceMap::Iterator i (map.begin ()), end (map.end ());
+ i != end; ++i)
+ os << fq_name (*i->first, "s:impl") << " " << i->second << ";";
+
+ os << "};";
+ }
+ };
+
+ struct GlobalElement: Traversal::Element, Context
+ {
+ GlobalElement (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ SemanticGraph::Context& ec (e.context ());
+
+ if (!ec.count ("saggr"))
+ return;
+
+ SemanticGraph::Type& t (e.type ());
+ String const& name (ec.get<String> ("saggr"));
+
+ String pre (unclash (name, "pre"));
+ String post (unclash (name, "post"));
+ String root_serializer (unclash (name, "root_serializer"));
+ String root_name (unclash (name, "root_name"));
+ String root_namespace (unclash (name, "root_namespace"));
+ String error, reset;
+
+ InstanceSet set;
+ set.insert (pre);
+ set.insert (post);
+ set.insert (name);
+ set.insert (root_serializer);
+ set.insert (root_name);
+ set.insert (root_namespace);
+
+ if (!exceptions)
+ {
+ error = unclash (name, "_error");
+ set.insert (error);
+ }
+
+ if (Context::reset)
+ {
+ reset = unclash (name, "reset");
+ set.insert (reset);
+ }
+
+ ec.set ("saggr-map", TypeInstanceMap ());
+ TypeInstanceMap& map (ec.get<TypeInstanceMap> ("saggr-map"));
+
+ SerializerDef def (*this, map, set);
+ def.dispatch (t);
+
+ String const& root_member (map.find (&t)->second);
+
+ os << "// Serializer aggregate for the " << comment (e.name ()) <<
+ " element." << endl
+ << "//" << endl;
+
+ os << "class " << name
+ << "{"
+ << "public:" << endl;
+
+ // c-tor ()
+ //
+ os << name << " ();"
+ << endl;
+
+ // pre ()
+ //
+ String const& arg (sarg_type (t));
+
+ os << "void" << endl
+ << pre << " (";
+
+ if (arg != L"void")
+ os << arg << " x";
+
+ os <<")"
+ << "{"
+ << "this->" << root_member << ".pre (" <<
+ (arg != L"void" ? "x" : "") << ");"
+ << "}";
+
+ // post ()
+ //
+ os << "void" << endl
+ << post << " ()"
+ << "{"
+ << "this->" << root_member << ".post ();"
+ << "}";
+
+ // root_serializer ()
+ //
+ os << fq_name (t, "s:impl") << "&" << endl
+ << root_serializer << " ()"
+ << "{"
+ << "return this->" << root_member << ";"
+ << "}";
+
+ // root_name ()
+ //
+ os << "static const char*" << endl
+ << root_name << " ();"
+ << endl;
+
+ // root_namespace ()
+ //
+ os << "static const char*" << endl
+ << root_namespace << " ();"
+ << endl;
+
+ // _error ()
+ //
+ if (error)
+ {
+ os << xs_ns_name () << "::serializer_error" << endl
+ << error << " ()"
+ << "{"
+ << "return this->" << root_member << "._error ();"
+ << "}";
+ }
+
+ // reset ()
+ //
+ if (reset)
+ {
+ os << "void" << endl
+ << reset << " ()"
+ << "{"
+ << "this->" << root_member << "._reset ();"
+ << "}";
+ }
+
+ os << "public:" << endl;
+
+ for (TypeInstanceMap::Iterator i (map.begin ()), end (map.end ());
+ i != end; ++i)
+ os << fq_name (*i->first, "s:impl") << " " << i->second << ";";
+
+ os << "};";
+ }
+ };
+ }
+
+ Void
+ generate_serializer_aggregate_header (Context& ctx)
+ {
+ Boolean gen (false);
+
+ {
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+
+ schema >> sources >> schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names names;
+ AggregateTest test (gen, "saggr");
+
+ schema >> schema_names >> ns >> names >> test;
+
+ schema.dispatch (ctx.schema_root);
+ }
+
+ if (gen)
+ {
+ // Emit "weak" header includes that are used in the file-per-type
+ // compilation model.
+ //
+ {
+ Traversal::Schema schema;
+ Includes includes (ctx, Includes::source);
+
+ schema >> includes;
+
+ schema.dispatch (ctx.schema_root);
+ }
+
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+
+ schema >> sources >> schema;
+
+ Traversal::Names schema_names;
+ Namespace ns (ctx);
+ Traversal::Names names;
+
+ schema >> schema_names >> ns >> names;
+
+ GlobalType type (ctx);
+ GlobalElement element (ctx);
+
+ names >> type;
+ names >> element;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+ }
+}
diff --git a/xsde/cxx/hybrid/serializer-aggregate-header.hxx b/xsde/cxx/hybrid/serializer-aggregate-header.hxx
new file mode 100644
index 0000000..3fde7b4
--- /dev/null
+++ b/xsde/cxx/hybrid/serializer-aggregate-header.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/hybrid/serializer-aggregate-header.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_SERIALIZER_AGGREGATE_HEADER_HXX
+#define CXX_HYBRID_SERIALIZER_AGGREGATE_HEADER_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/hybrid/elements.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ Void
+ generate_serializer_aggregate_header (Context&);
+ }
+}
+
+#endif // CXX_HYBRID_SERIALIZER_AGGREGATE_HEADER_HXX
diff --git a/xsde/cxx/hybrid/serializer-aggregate-source.cxx b/xsde/cxx/hybrid/serializer-aggregate-source.cxx
new file mode 100644
index 0000000..7e305b6
--- /dev/null
+++ b/xsde/cxx/hybrid/serializer-aggregate-source.cxx
@@ -0,0 +1,330 @@
+// file : xsde/cxx/hybrid/serializer-aggregate-source.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/hybrid/serializer-aggregate-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/map.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ namespace
+ {
+ typedef
+ Cult::Containers::Map<SemanticGraph::Type*, String>
+ TypeInstanceMap;
+
+ //
+ //
+ struct ParticleArg: Traversal::Element, Context
+ {
+ ParticleArg (Context& c, TypeInstanceMap& map, Boolean& first)
+ : Context (c), map_ (map), first_ (first)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (!first_)
+ os << "," << endl;
+ else
+ first_ = false;
+
+ os << "this->" << map_[&e.type ()];
+ }
+
+ private:
+ TypeInstanceMap& map_;
+ Boolean& first_;
+ };
+
+ struct AttributeArg: Traversal::Attribute, Context
+ {
+ AttributeArg (Context& c, TypeInstanceMap& map, Boolean& first)
+ : Context (c), map_ (map), first_ (first)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ if (!first_)
+ os << "," << endl;
+ else
+ first_ = false;
+
+ os << "this->" << map_[&a.type ()];
+ }
+
+ private:
+ TypeInstanceMap& map_;
+ Boolean& first_;
+ };
+
+ struct ArgList : Traversal::Complex,
+ Traversal::List,
+ Context
+ {
+ ArgList (Context& c, TypeInstanceMap& map)
+ : Context (c),
+ map_ (map),
+ particle_ (c, map, first_),
+ attribute_ (c, map, first_),
+ first_ (true)
+ {
+ inherits_ >> *this;
+
+ contains_compositor_ >> compositor_;
+ compositor_ >> contains_particle_;
+ contains_particle_ >> compositor_;
+ contains_particle_ >> particle_;
+
+ names_ >> attribute_;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ inherits (c, inherits_);
+
+ if (!restriction_p (c))
+ {
+ names (c, names_);
+ contains_compositor (c, contains_compositor_);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::List& l)
+ {
+ if (!first_)
+ os << "," << endl;
+ else
+ first_ = false;
+
+ os << "this->" << map_[&l.argumented ().type ()];
+ }
+
+ private:
+ TypeInstanceMap& map_;
+
+ Traversal::Inherits inherits_;
+
+ Traversal::Compositor compositor_;
+ ParticleArg particle_;
+ Traversal::ContainsCompositor contains_compositor_;
+ Traversal::ContainsParticle contains_particle_;
+
+ Traversal::Names names_;
+ AttributeArg attribute_;
+
+ Boolean first_;
+ };
+
+ struct SerializerConnect: Traversal::List,
+ Traversal::Complex,
+ Context
+ {
+ SerializerConnect (Context& c, TypeInstanceMap& map)
+ : Context (c), map_ (map)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::List& l)
+ {
+ os << "this->" << map_[&l] << ".serializers (this->" <<
+ map_[&l.argumented ().type ()] << ");"
+ << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ if (has_members (c))
+ {
+ os << "this->" << map_[&c] << ".serializers (";
+
+ ArgList args (*this, map_);
+ args.dispatch (c);
+
+ os << ");"
+ << endl;
+ }
+ }
+
+ private:
+ Boolean
+ has_members (SemanticGraph::Complex& c)
+ {
+ using SemanticGraph::Complex;
+
+ if (has<Traversal::Member> (c))
+ return true;
+
+ if (c.inherits_p ())
+ {
+ SemanticGraph::Type& b (c.inherits ().base ());
+
+ if (Complex* cb = dynamic_cast<Complex*> (&b))
+ return has_members (*cb);
+
+ return b.is_a<SemanticGraph::List> ();
+ }
+
+ return false;
+ }
+
+ private:
+ TypeInstanceMap& map_;
+ };
+
+ struct GlobalType: Traversal::Type, Context
+ {
+ GlobalType (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& t)
+ {
+ SemanticGraph::Context& tc (t.context ());
+
+ if (!tc.count ("saggr"))
+ return;
+
+ String const& name (tc.get<String> ("saggr"));
+ TypeInstanceMap& map (tc.get<TypeInstanceMap> ("saggr-map"));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ // c-tor ()
+ //
+ os << name << "::" << endl
+ << name << " ()"
+ << "{";
+
+ SerializerConnect connect (*this, map);
+
+ for (TypeInstanceMap::Iterator i (map.begin ()), end (map.end ());
+ i != end; ++i)
+ connect.dispatch (*i->first);
+
+ os << "}";
+ }
+ };
+
+ struct GlobalElement: Traversal::Element, Context
+ {
+ GlobalElement (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ SemanticGraph::Context& ec (e.context ());
+
+ if (!ec.count ("saggr"))
+ return;
+
+ String const& name (ec.get<String> ("saggr"));
+ TypeInstanceMap& map (ec.get<TypeInstanceMap> ("saggr-map"));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ // c-tor ()
+ //
+ os << name << "::" << endl
+ << name << " ()"
+ << "{";
+
+ SerializerConnect connect (*this, map);
+
+ for (TypeInstanceMap::Iterator i (map.begin ()), end (map.end ());
+ i != end; ++i)
+ connect.dispatch (*i->first);
+
+ os << "}";
+
+ // root_name ()
+ //
+ String root_name (unclash (name, "root_name"));
+
+ os << "const char* " << name << "::" << endl
+ << root_name << " ()"
+ << "{"
+ << "return " << strlit (e.name ()) << ";"
+ << "}";
+
+ // root_namespace ()
+ //
+ String root_namespace (unclash (name, "root_namespace"));
+
+ os << "const char* " << name << "::" << endl
+ << root_namespace << " ()"
+ << "{"
+ << "return " << strlit (e.namespace_ ().name ()) << ";"
+ << "}";
+ }
+ };
+ }
+
+ Void
+ generate_serializer_aggregate_source (Context& ctx)
+ {
+ Boolean gen (false);
+
+ {
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+
+ schema >> sources >> schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names names;
+ AggregateTest test (gen, "saggr");
+
+ schema >> schema_names >> ns >> names >> test;
+
+ schema.dispatch (ctx.schema_root);
+ }
+
+ if (gen)
+ {
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+
+ schema >> sources >> schema;
+
+ Traversal::Names schema_names;
+ Namespace ns (ctx);
+ Traversal::Names names;
+
+ schema >> schema_names >> ns >> names;
+
+ GlobalType type (ctx);
+ GlobalElement element (ctx);
+
+ names >> type;
+ names >> element;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+ }
+}
diff --git a/xsde/cxx/hybrid/serializer-aggregate-source.hxx b/xsde/cxx/hybrid/serializer-aggregate-source.hxx
new file mode 100644
index 0000000..c011366
--- /dev/null
+++ b/xsde/cxx/hybrid/serializer-aggregate-source.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/hybrid/serializer-aggregate-source.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_SERIALIZER_AGGREGATE_SOURCE_HXX
+#define CXX_HYBRID_SERIALIZER_AGGREGATE_SOURCE_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/hybrid/elements.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ Void
+ generate_serializer_aggregate_source (Context&);
+ }
+}
+
+#endif // CXX_HYBRID_SERIALIZER_AGGREGATE_SOURCE_HXX
diff --git a/xsde/cxx/hybrid/serializer-header.cxx b/xsde/cxx/hybrid/serializer-header.cxx
new file mode 100644
index 0000000..c6fbc6c
--- /dev/null
+++ b/xsde/cxx/hybrid/serializer-header.cxx
@@ -0,0 +1,534 @@
+// file : xsde/cxx/hybrid/serializer-header.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/hybrid/serializer-header.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ namespace
+ {
+ struct List: Traversal::List, Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String const& name (esimpl_custom (l));
+
+ // We may not need to generate the class if this serializer is
+ // being customized.
+ //
+ if (name)
+ {
+ String const& skel (esskel (l));
+ String const& arg (sarg_type (l));
+ String const& ret (sret_type (l.argumented ().type ()));
+
+ String item (unclash (skel, "item"));
+ String item_next (unclash (skel, "item_next"));
+
+ os << "class " << name << ": public " <<
+ (mixin ? "virtual " : "") << skel
+ << "{"
+ << "public:" << endl;
+
+ // pre
+ //
+ os << "virtual void" << endl
+ << "pre (" << arg << ");"
+ << endl;
+
+ // item_next
+ //
+ os << "virtual bool" << endl
+ << item_next << " ();"
+ << endl;
+
+ // item
+ //
+ os << "virtual " << ret << endl
+ << item << " ();"
+ << endl;
+
+ // State.
+ //
+ os << (tiein ? "public:" : "protected:") << endl;
+
+ String const& type (fq_name (l));
+ String const& state_type (esstate_type (l));
+
+ os << "struct " << state_type
+ << "{"
+ << type << "::const_iterator i_;"
+ << type << "::const_iterator end_;"
+ << "};"
+ << state_type << " " << esstate (l) << ";"
+ << "};";
+ }
+
+ // Generate include for custom serializer.
+ //
+ if (l.context ().count ("s:impl-include"))
+ {
+ close_ns ();
+
+ os << "#include " << process_include_path (
+ l.context ().get<String> ("s:impl-include")) << endl
+ << endl;
+
+ open_ns ();
+ }
+ }
+ };
+
+ //
+ //
+ struct Union: Traversal::Union, Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ String const& name (esimpl_custom (u));
+
+ // We may not need to generate the class if this serializer is
+ // being customized.
+ //
+ if (name)
+ {
+ String const& arg (sarg_type (u));
+
+ os << "class " << name << ": public " <<
+ (mixin ? "virtual " : "") << esskel (u)
+ << "{"
+ << "public:" << endl;
+
+ // pre
+ //
+ os << "virtual void" << endl
+ << "pre (" << arg << ");"
+ << endl;
+
+ // _serialize_content
+ //
+ os << "virtual void" << endl
+ << "_serialize_content ();"
+ << endl;
+
+ // State.
+ //
+ os << (tiein ? "public:" : "protected:") << endl
+ << "const " << fq_name (u) << "* " << esstate (u) << ";"
+ << "};";
+ }
+
+ // Generate include for custom serializer.
+ //
+ if (u.context ().count ("s:impl-include"))
+ {
+ close_ns ();
+
+ os << "#include " << process_include_path (
+ u.context ().get<String> ("s:impl-include")) << endl
+ << endl;
+
+ open_ns ();
+ }
+ }
+ };
+
+ //
+ // State.
+ //
+
+ struct CompositorState: Traversal::Compositor, Context
+ {
+ CompositorState (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Compositor& c)
+ {
+ if (c.max () != 1)
+ {
+ String scope (fq_scope (c));
+ String const& const_iterator (econst_iterator (c));
+
+ os << scope << "::" << const_iterator << " " <<
+ esstate_member (c) << ";"
+ << scope << "::" << const_iterator << " " <<
+ esstate_member_end (c) << ";";
+ }
+
+ Compositor::traverse (c);
+ }
+ };
+
+ struct ParticleState: Traversal::Element, Context
+ {
+ ParticleState (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (e.max () != 1)
+ {
+ String scope (fq_scope (e));
+ String const& const_iterator (econst_iterator (e));
+
+ os << scope << "::" << const_iterator << " " <<
+ esstate_member (e) << ";"
+ << scope << "::" << const_iterator << " " <<
+ esstate_member_end (e) << ";";
+ }
+ }
+ };
+
+ //
+ // Callbacks.
+ //
+
+ struct CompositorCallback: Traversal::All,
+ Traversal::Choice,
+ Traversal::Sequence,
+ Context
+ {
+ CompositorCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ // For the all compositor, maxOccurs=1 and minOccurs={0,1}.
+ //
+ if (a.min () == 0)
+ {
+ os << "virtual bool" << endl
+ << espresent (a) << " ();"
+ << endl;
+ }
+
+ Traversal::All::traverse (a);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ if (c.contains_begin () != c.contains_end ())
+ {
+ UnsignedLong min (c.min ()), max (c.max ());
+
+ if (min == 0 && max == 1)
+ {
+ os << "virtual bool" << endl
+ << espresent (c) << " ();"
+ << endl;
+ }
+ else if (max != 1)
+ {
+ os << "virtual bool" << endl
+ << esnext (c) << " ();"
+ << endl;
+ }
+
+ os << "virtual " << esarm_tag (c) << endl
+ << esarm (c) << " ();"
+ << endl;
+
+ Traversal::Choice::traverse (c);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ UnsignedLong min (s.min ()), max (s.max ());
+
+ if (min == 0 && max == 1)
+ {
+ os << "virtual bool" << endl
+ << espresent (s) << " ();"
+ << endl;
+ }
+ else if (max != 1)
+ {
+ os << "virtual bool" << endl
+ << esnext (s) << " ();"
+ << endl;
+ }
+
+ Traversal::Sequence::traverse (s);
+ }
+ };
+
+ struct ParticleCallback: Traversal::Element, Context
+ {
+ ParticleCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ UnsignedLong min (e.min ()), max (e.max ());
+
+ if (min == 0 && max == 1)
+ {
+ os << "virtual bool" << endl
+ << espresent (e) << " ();"
+ << endl;
+ }
+ else if (max != 1)
+ {
+ os << "virtual bool" << endl
+ << esnext (e) << " ();"
+ << endl;
+ }
+
+ String const& ret (sret_type (e.type ()));
+
+ os << "virtual " << ret << endl
+ << esname (e) << " ();"
+ << endl;
+ }
+ };
+
+ struct AttributeCallback: Traversal::Attribute, Context
+ {
+ AttributeCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ if (a.optional ())
+ {
+ os << "virtual bool" << endl
+ << espresent (a) << " ();"
+ << endl;
+ }
+
+ String const& ret (sret_type (a.type ()));
+
+ os << "virtual " << ret << endl
+ << esname (a) << " ();"
+ << endl;
+ }
+ };
+
+ //
+ //
+ struct Complex : Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c),
+
+ // State.
+ //
+ compositor_state_ (c),
+ particle_state_ (c),
+
+ // Callbacks.
+ //
+ compositor_callback_ (c),
+ particle_callback_ (c),
+ attribute_callback_ (c)
+ {
+ // State.
+ //
+ contains_compositor_state_ >> compositor_state_;
+ compositor_state_ >> contains_particle_state_;
+ contains_particle_state_ >> compositor_state_;
+ contains_particle_state_ >> particle_state_;
+
+
+ // Callbacks.
+ //
+ contains_compositor_callback_ >> compositor_callback_;
+ compositor_callback_ >> contains_particle_callback_;
+ contains_particle_callback_ >> compositor_callback_;
+ contains_particle_callback_ >> particle_callback_;
+
+ names_attribute_callback_ >> attribute_callback_;
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ String const& name (esimpl_custom (c));
+
+ // We may not need to generate the class if this serializer is
+ // being customized.
+ //
+ if (name)
+ {
+ // In case of an inheritance-by-restriction, we don't need to
+ // generate serializer callbacks, etc. since they are the same
+ // as in the base. We only need the serialization/validation code.
+ //
+ Boolean restriction (restriction_p (c));
+
+ Boolean hb (c.inherits_p ());
+ Boolean he (has<Traversal::Element> (c));
+ Boolean ha (has<Traversal::Attribute> (c));
+
+ Boolean hae (has_particle<Traversal::Any> (c));
+ Boolean haa (has<Traversal::AnyAttribute> (c));
+
+ String const& arg (sarg_type (c));
+
+ os << "class " << name << ": public " <<
+ (mixin ? "virtual " : "") << esskel (c);
+
+ if (mixin && hb)
+ os << "," << endl
+ << " public " << fq_name (c.inherits ().base (), "s:impl");
+
+ os << "{"
+ << "public:" << endl;
+
+ // c-tor
+ //
+ if (tiein && hb)
+ os << name << " ();"
+ << endl;
+
+ // pre
+ //
+ os << "virtual void" << endl
+ << "pre (" << arg << ");"
+ << endl;
+
+ // Member callbacks.
+ //
+ if (!restriction && (ha || he || hae || haa))
+ {
+ if (ha || haa)
+ {
+ os << "// Attributes." << endl
+ << "//" << endl;
+
+ names (c, names_attribute_callback_);
+ }
+
+ if (he || hae)
+ {
+ os << "// Elements." << endl
+ << "//" << endl;
+
+ contains_compositor (c, contains_compositor_callback_);
+ }
+ }
+
+ if (!restriction)
+ {
+ String const& state_type (esstate_type (c));
+ String const& member (esstate_member (c));
+
+ os << "protected:" << endl
+ << "struct " << state_type
+ << "{"
+ << "const " << fq_name (c) << "* " << member << ";";
+
+ if (c.contains_compositor_p ())
+ contains_compositor (c, contains_compositor_state_);
+
+ os << "};"
+ << state_type << " " << esstate (c) << ";";
+ }
+
+ if (tiein && hb)
+ os << endl
+ << "protected:" << endl
+ << fq_name (c.inherits ().base (), "s:impl") << " base_impl_;";
+
+ os << "};";
+ }
+
+ // Generate include for custom serializer.
+ //
+ if (c.context ().count ("s:impl-include"))
+ {
+ close_ns ();
+
+ os << "#include " << process_include_path (
+ c.context ().get<String> ("s:impl-include")) << endl
+ << endl;
+
+ open_ns ();
+ }
+ }
+
+ private:
+ // State.
+ //
+ CompositorState compositor_state_;
+ ParticleState particle_state_;
+ Traversal::ContainsCompositor contains_compositor_state_;
+ Traversal::ContainsParticle contains_particle_state_;
+
+ // Callbacks.
+ //
+ CompositorCallback compositor_callback_;
+ ParticleCallback particle_callback_;
+ Traversal::ContainsCompositor contains_compositor_callback_;
+ Traversal::ContainsParticle contains_particle_callback_;
+
+ AttributeCallback attribute_callback_;
+ Traversal::Names names_attribute_callback_;
+ };
+ }
+
+ Void
+ generate_serializer_header (Context& ctx)
+ {
+ Traversal::Schema schema;
+
+ Traversal::Sources sources;
+ Includes includes (ctx, Includes::impl_header);
+ Traversal::Names schema_names;
+
+ Namespace ns (ctx, true);
+ Traversal::Names names;
+
+ schema >> includes;
+ schema >> sources >> schema;
+ schema >> schema_names >> ns >> names;
+
+ List list (ctx);
+ Union union_ (ctx);
+ Complex complex (ctx);
+
+ names >> list;
+ names >> union_;
+ names >> complex;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+}
diff --git a/xsde/cxx/hybrid/serializer-header.hxx b/xsde/cxx/hybrid/serializer-header.hxx
new file mode 100644
index 0000000..d24bc6a
--- /dev/null
+++ b/xsde/cxx/hybrid/serializer-header.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/hybrid/serializer-header.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_SERIALIZER_HEADER_HXX
+#define CXX_HYBRID_SERIALIZER_HEADER_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/hybrid/elements.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ Void
+ generate_serializer_header (Context&);
+ }
+}
+
+#endif // CXX_HYBRID_SERIALIZER_HEADER_HXX
diff --git a/xsde/cxx/hybrid/serializer-name-processor.cxx b/xsde/cxx/hybrid/serializer-name-processor.cxx
new file mode 100644
index 0000000..8d3c15d
--- /dev/null
+++ b/xsde/cxx/hybrid/serializer-name-processor.cxx
@@ -0,0 +1,723 @@
+// file : xsde/cxx/hybrid/serializer-name-processor.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/elements.hxx>
+#include <cxx/hybrid/serializer-name-processor.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/set.hxx>
+
+#include <sstream>
+#include <iostream>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ namespace
+ {
+ //
+ //
+ typedef Cult::Containers::Set<String> NameSet;
+
+ class Context: public CXX::Context
+ {
+ public:
+ Context (CLI::Options const& ops,
+ SemanticGraph::Schema& root,
+ SemanticGraph::Path const& file)
+ : CXX::Context (std::wcerr,
+ root,
+ "name",
+ "char",
+ ops.value<CLI::include_with_brackets> (),
+ ops.value<CLI::include_prefix> (),
+ "", // export symbol
+ ops.value<CLI::namespace_map> (),
+ ops.value<CLI::namespace_regex> (),
+ ops.value<CLI::namespace_regex_trace> (),
+ ops.value<CLI::include_regex> (),
+ ops.value<CLI::include_regex_trace> (),
+ ops.value<CLI::generate_inline> (),
+ ops.value<CLI::reserved_name> ()),
+ schema_path_ (file),
+ impl_suffix_ (ops.value<CLI::simpl_type_suffix> ()),
+ aggr_suffix_ (ops.value<CLI::saggr_type_suffix> ()),
+ options (ops),
+ schema (root),
+ schema_path (schema_path_),
+ aggregate (ops.value<CLI::generate_aggregate> ()),
+ impl_suffix (impl_suffix_),
+ aggr_suffix (aggr_suffix_),
+ custom_serializer_map (custom_serializer_map_),
+ global_type_names (global_type_names_)
+ {
+ // Custom serializer mapping.
+ //
+ typedef Containers::Vector<NarrowString> Vector;
+ Vector const& v (ops.value<CLI::custom_serializer> ());
+
+ for (Vector::ConstIterator i (v.begin ()), e (v.end ());
+ i != e; ++i)
+ {
+ String s (*i);
+
+ if (s.empty ())
+ continue;
+
+ // Split the string in two parts at the last '='.
+ //
+ Size pos (s.rfind ('='));
+
+ // If no delimiter found then both base and include are empty.
+ //
+ if (pos == String::npos)
+ {
+ custom_serializer_map_[s].base.clear ();
+ custom_serializer_map_[s].include.clear ();
+ continue;
+ }
+
+ String name (s, 0, pos);
+ String rest (s, pos + 1);
+
+ // See if we've got the include part after '/'.
+ //
+ pos = rest.find ('/');
+
+ String base, include;
+
+ if (pos != String::npos)
+ {
+ base.assign (rest, 0, pos);
+ include.assign (rest, pos + 1, String::npos);
+ }
+ else
+ base = rest;
+
+ custom_serializer_map_[name].base = base;
+ custom_serializer_map_[name].include = include;
+ }
+ }
+
+ protected:
+ Context (Context& c)
+ : CXX::Context (c),
+ options (c.options),
+ schema (c.schema),
+ schema_path (c.schema_path),
+ aggregate (c.aggregate),
+ impl_suffix (c.impl_suffix),
+ aggr_suffix (c.aggr_suffix),
+ custom_serializer_map (c.custom_serializer_map),
+ global_type_names (c.global_type_names)
+ {
+ }
+
+ public:
+ String
+ find_name (String const& n, String const& suffix, NameSet& set)
+ {
+ String name (escape (n + suffix));
+
+ for (UnsignedLong i (1); set.find (name) != set.end (); ++i)
+ {
+ std::wostringstream os;
+ os << i;
+ name = escape (n + os.str () + suffix);
+ }
+
+ set.insert (name);
+ return name;
+ }
+
+ String
+ find_name (String const& n, NameSet& set)
+ {
+ return find_name (n, L"", set);
+ }
+
+ public:
+ using CXX::Context::ename;
+
+ static String const&
+ ename (SemanticGraph::Compositor& c)
+ {
+ return c.context ().get<String> ("name");
+ }
+
+ String
+ state_name (SemanticGraph::Compositor& c)
+ {
+ using namespace SemanticGraph;
+
+ String r;
+
+ for (Compositor* p (&c);;
+ p = &p->contained_particle ().compositor ())
+ {
+ if (p->context ().count ("type"))
+ {
+ // Not a see-through compositor.
+ //
+ if (!r)
+ r = ename (*p);
+ else
+ {
+ String tmp;
+ tmp.swap (r);
+ r = ename (*p);
+ r += L"_";
+ r += tmp;
+ }
+ }
+
+ if (p->contained_compositor_p ())
+ break;
+ }
+
+ return r;
+ }
+
+ String
+ state_name (SemanticGraph::Element& e)
+ {
+ String r (state_name (e.contained_particle ().compositor ()));
+
+ if (!r)
+ r = ename (e);
+ else
+ {
+ r += L"_";
+ r += ename (e);
+ }
+
+ return r;
+ }
+
+ public:
+ struct CustomSerializer
+ {
+ CustomSerializer (String const& b = L"", String const& i = L"")
+ : base (b), include (i)
+ {
+ }
+
+ String base;
+ String include;
+ };
+
+ typedef
+ Cult::Containers::Map<String, CustomSerializer>
+ CustomSerializerMap;
+
+ private:
+ SemanticGraph::Path const schema_path_;
+ String const impl_suffix_;
+ String const aggr_suffix_;
+ CustomSerializerMap custom_serializer_map_;
+
+ Cult::Containers::Map<String, NameSet*> global_type_names_;
+
+ public:
+ CLI::Options const& options;
+ SemanticGraph::Schema& schema;
+ SemanticGraph::Path const& schema_path;
+ Boolean aggregate;
+ String const& impl_suffix;
+ String const& aggr_suffix;
+ CustomSerializerMap const& custom_serializer_map;
+
+ Cult::Containers::Map<String, NameSet*>& global_type_names;
+ };
+
+ //
+ //
+ struct List: Traversal::List, Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ SemanticGraph::Context& lc (l.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 (lc.count ("s:impl-base")
+ ? lc.get<String> ("s:impl-base")
+ : lc.get<String> ("s:impl"));
+ if (!name)
+ return;
+
+ String const& skel (lc.get<String> ("p:name"));
+
+ NameSet set;
+ set.insert (name);
+ set.insert (unclash (skel, "item"));
+ set.insert (unclash (skel, "item_next"));
+
+ String state_type (find_name (name + L"_state", set));
+ lc.set ("sstate-type", state_type);
+ lc.set ("sstate", find_name (state_type, "_", set));
+ }
+ };
+
+ //
+ //
+ struct Union: Traversal::Union, Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ SemanticGraph::Context& uc (l.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 (uc.count ("s:impl-base")
+ ? uc.get<String> ("s:impl-base")
+ : uc.get<String> ("s:impl"));
+ if (!name)
+ return;
+
+ NameSet set;
+ set.insert (name);
+
+ uc.set ("sstate", find_name (name + L"_state", "_", set));
+ }
+ };
+
+ // State names.
+ //
+
+ struct CompositorState: Traversal::Compositor, Context
+ {
+ CompositorState (Context& c, NameSet& set)
+ : Context (c), set_ (set)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Compositor& c)
+ {
+ if (c.max () != 1)
+ {
+ SemanticGraph::Context& cc (c.context ());
+ String b (state_name (c));
+ cc.set ("sstate-member", find_name (b, L"_", set_));
+ cc.set ("sstate-member-end", find_name (b + L"_end", L"_", set_));
+ }
+
+ Compositor::traverse (c);
+ }
+
+ private:
+ NameSet& set_;
+ };
+
+ struct ParticleState: Traversal::Element, Context
+ {
+ ParticleState (Context& c, NameSet& set)
+ : Context (c), set_ (set)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (e.max () != 1)
+ {
+ SemanticGraph::Context& ec (e.context ());
+ String b (state_name (e));
+ ec.set ("sstate-member", find_name (b, L"_", set_));
+ ec.set ("sstate-member-end", find_name (b + L"_end", L"_", set_));
+ }
+ }
+
+ private:
+ NameSet& set_;
+ };
+
+ //
+ //
+ struct Complex: Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ Boolean restriction (false);
+
+ if (c.inherits_p ())
+ restriction = c.inherits ().is_a<SemanticGraph::Restricts> () &&
+ !c.inherits ().base ().is_a<SemanticGraph::AnyType> ();
+
+ SemanticGraph::Context& cc (c.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& base (cc.count ("s:impl-base")
+ ? cc.get<String> ("s:impl-base")
+ : cc.get<String> ("s:impl"));
+ if (!base)
+ return;
+
+ // Use skeleton's name set to make sure we don't clash
+ // with callbacks which we are overriding.
+ //
+ NameSet& set (
+ cc.get<NameSet> ("cxx-serializer-name-processor-member-set"));
+
+ String state_type (find_name (base + L"_state", set));
+ cc.set ("sstate-type", state_type);
+ cc.set ("sstate", find_name (state_type, "_", set));
+
+ // State members are in a nested struct so use a new and
+ // empty name set.
+ //
+ NameSet state_set;
+
+ String member (
+ find_name (cc.get<String> ("name"), "_", state_set));
+
+ cc.set ("sstate-member", member);
+ state_set.insert (member);
+
+ // Assign state names.
+ //
+ if (!restriction && c.contains_compositor_p ())
+ {
+ ParticleState particle (*this, state_set);
+ CompositorState compositor (*this, state_set);
+ Traversal::ContainsCompositor contains_compositor;
+ Traversal::ContainsParticle contains_particle;
+
+ contains_compositor >> compositor >> contains_particle;
+
+ contains_particle >> compositor;
+ contains_particle >> particle;
+
+ Complex::contains_compositor (c, contains_compositor);
+ }
+ }
+ };
+
+ //
+ //
+ struct GlobalType: Traversal::Type, Context
+ {
+ GlobalType (Context& c, NameSet& set)
+ : Context (c), set_ (set)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& t)
+ {
+ SemanticGraph::Context& tc (t.context ());
+ String const& name (t.name ());
+
+ tc.set ("s:impl", find_name (name + impl_suffix, set_));
+
+ // See if this serializer is being customized.
+ //
+ CustomSerializerMap::ConstIterator i (
+ custom_serializer_map.find (name));
+
+ if (i != custom_serializer_map.end ())
+ {
+ tc.set ("s:impl-base", i->second.base
+ ? find_name (i->second.base, set_)
+ : i->second.base);
+
+ if (i->second.include)
+ tc.set ("s:impl-include", i->second.include);
+ }
+
+ if (aggregate)
+ {
+ typedef Cult::Containers::Vector<NarrowString> Names;
+ Names const& names (options.value<CLI::root_type> ());
+
+ // Hopefully nobody will specify more than a handful of names.
+ //
+ for (Names::ConstIterator i (names.begin ());
+ i != names.end (); ++i)
+ {
+ if (name == String (*i))
+ {
+ tc.set ("saggr", find_name (name + aggr_suffix, set_));
+ break;
+ }
+ }
+ }
+ }
+
+ private:
+ NameSet& set_;
+ };
+
+ //
+ //
+ struct GlobalElement: Traversal::Element, Context
+ {
+ GlobalElement (Context& c, NameSet& set)
+ : Context (c), set_ (set), last_ (0)
+ {
+ }
+
+ ~GlobalElement ()
+ {
+ if (last_ != 0 && options.value<CLI::root_element_last> ())
+ process (*last_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ Boolean p (false);
+
+ if (last_ == 0 && options.value<CLI::root_element_first> ())
+ p = true;
+
+ last_ = &e;
+
+ if (!p &&
+ !options.value<CLI::root_element_first> () &&
+ !options.value<CLI::root_element_last> () &&
+ !options.value<CLI::root_element_all> () &&
+ !options.value<CLI::root_element_none> () &&
+ options.value<CLI::root_element> ().empty ())
+ {
+ // By default process them all.
+ //
+ p = true;
+ }
+
+ if (!p && options.value<CLI::root_element_all> ())
+ p = true;
+
+ if (!p)
+ {
+ typedef Cult::Containers::Vector<NarrowString> Names;
+ Names const& names (options.value<CLI::root_element> ());
+
+ // Hopefully nobody will specify more than a handful of names.
+ //
+ for (Names::ConstIterator i (names.begin ());
+ !p && i != names.end ();
+ ++i)
+ {
+ if (e.name () == String (*i))
+ p = true;
+ }
+ }
+
+ if (p)
+ process (e);
+ }
+
+ private:
+ Void
+ process (SemanticGraph::Element& e)
+ {
+ SemanticGraph::Context& ec (e.context ());
+
+ if (!ec.count ("saggr"))
+ {
+ ec.set ("saggr", find_name (e.name () + aggr_suffix, set_));
+ }
+ }
+
+ private:
+ NameSet& set_;
+ SemanticGraph::Element* last_;
+ };
+
+ struct Namespace: Traversal::Namespace, Context
+ {
+ Namespace (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& ns)
+ {
+ SemanticGraph::Context& nsc (ns.context ());
+ String const& name (ns.name ());
+
+ // Use a name set associated with this namespace if present.
+ // This will make sure that we don't get any conflicts in the
+ // multi-mapping translation case. Note that here we assume
+ // that all mappings traverse schemas in the same order which
+ // is currently the case.
+ //
+ if (global_type_names.find (name) == global_type_names.end ())
+ {
+ if (!nsc.count ("name-set"))
+ nsc.set ("name-set", NameSet ());
+
+ NameSet& s (nsc.get<NameSet> ("name-set"));
+ global_type_names[name] = &s;
+ }
+
+ NameSet& type_set (*global_type_names[name]);
+
+ // Serializer implementations.
+ //
+ {
+ GlobalType type (*this, type_set);
+ Traversal::Names names (type);
+
+ Traversal::Namespace::names (ns, names);
+ }
+
+ // Serializer aggregates.
+ //
+ if (aggregate)
+ {
+ GlobalElement element (*this, type_set);
+ Traversal::Names names (element);
+
+ Traversal::Namespace::names (ns, names);
+ }
+ }
+ };
+
+ // Go into sourced/included/imported schemas while making sure
+ // we don't process the same stuff more than once.
+ //
+ struct Uses: Traversal::Sources,
+ Traversal::Includes,
+ Traversal::Imports
+ {
+ virtual Void
+ traverse (SemanticGraph::Sources& sr)
+ {
+ SemanticGraph::Schema& s (sr.schema ());
+
+ if (!s.context ().count (seen_key))
+ {
+ s.context ().set (seen_key, true);
+ Traversal::Sources::traverse (sr);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Includes& i)
+ {
+ SemanticGraph::Schema& s (i.schema ());
+
+ if (!s.context ().count (seen_key))
+ {
+ s.context ().set (seen_key, true);
+ Traversal::Includes::traverse (i);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Imports& i)
+ {
+ SemanticGraph::Schema& s (i.schema ());
+
+ if (!s.context ().count (seen_key))
+ {
+ s.context ().set (seen_key, true);
+ Traversal::Imports::traverse (i);
+ }
+ }
+
+ static Char const* seen_key;
+ };
+
+ Char const* Uses::seen_key = "cxx-hybrid-serializer-name-processor-seen";
+
+ Void
+ process_impl (CLI::Options const& ops,
+ SemanticGraph::Schema& tu,
+ SemanticGraph::Path const& file)
+ {
+ Context ctx (ops, tu, file);
+
+ // Pass one - assign names to global types. This pass cannot
+ // be combined with pass two because of possible recursive
+ // schema inclusions. Also note that we check first if this
+ // schema has already been processed which may happen in the
+ // file-per-type compilation mode.
+ //
+ if (!tu.context ().count (Uses::seen_key))
+ {
+ Traversal::Schema schema;
+ Uses uses;
+
+ schema >> uses >> schema;
+
+ Traversal::Names schema_names;
+ Namespace ns (ctx);
+
+ schema >> schema_names >> ns;
+
+ // Some twisted schemas do recusive self-inclusion.
+ //
+ tu.context ().set (Uses::seen_key, true);
+
+ schema.dispatch (tu);
+ }
+
+ // Pass two - assign names inside complex types. Here we don't
+ // need to go into included/imported schemas.
+ //
+ {
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+
+ schema >> sources >> schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+
+ schema >> schema_names >> ns >> ns_names;
+
+ List list (ctx);
+ Union union_ (ctx);
+ Complex complex (ctx);
+
+ ns_names >> list;
+ ns_names >> union_;
+ ns_names >> complex;
+
+ schema.dispatch (tu);
+ }
+ }
+ }
+
+ Void SerializerNameProcessor::
+ process (CLI::Options const& ops,
+ SemanticGraph::Schema& tu,
+ SemanticGraph::Path const& file)
+ {
+ process_impl (ops, tu, file);
+ }
+ }
+}
diff --git a/xsde/cxx/hybrid/serializer-name-processor.hxx b/xsde/cxx/hybrid/serializer-name-processor.hxx
new file mode 100644
index 0000000..f69dfe4
--- /dev/null
+++ b/xsde/cxx/hybrid/serializer-name-processor.hxx
@@ -0,0 +1,32 @@
+// file : xsde/cxx/hybrid/serializer-name-processor.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CXX_HYBRID_SERIALIZER_NAME_PROCESSOR_HXX
+#define CXX_HYBRID_SERIALIZER_NAME_PROCESSOR_HXX
+
+#include <cult/types.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+
+#include <cxx/hybrid/cli.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ using namespace Cult::Types;
+
+ class SerializerNameProcessor
+ {
+ public:
+ Void
+ process (CLI::Options const& options,
+ XSDFrontend::SemanticGraph::Schema&,
+ XSDFrontend::SemanticGraph::Path const& file);
+ };
+ }
+}
+
+#endif // CXX_HYBRID_SERIALIZER_NAME_PROCESSOR_HXX
diff --git a/xsde/cxx/hybrid/serializer-source.cxx b/xsde/cxx/hybrid/serializer-source.cxx
new file mode 100644
index 0000000..37fff42
--- /dev/null
+++ b/xsde/cxx/hybrid/serializer-source.cxx
@@ -0,0 +1,1001 @@
+// file : xsde/cxx/hybrid/serializer-source.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/hybrid/serializer-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ namespace
+ {
+ // Some built-in types are passed by pointer to built-in serializer
+ // implementations.
+ //
+ struct TypePass: Traversal::Fundamental::NameTokens,
+ Traversal::Fundamental::QName,
+ Traversal::Fundamental::IdRefs,
+ Traversal::Fundamental::Base64Binary,
+ Traversal::Fundamental::HexBinary,
+ Traversal::Fundamental::Entities,
+ Context
+ {
+ TypePass (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameTokens&)
+ {
+ os << "&";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::QName&)
+ {
+ if (!stl)
+ os << "&";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRefs&)
+ {
+ os << "&";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Base64Binary&)
+ {
+ os << "&";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::HexBinary&)
+ {
+ os << "&";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entities&)
+ {
+ os << "&";
+ }
+ };
+
+ //
+ //
+ struct List: Traversal::List, Context
+ {
+ List (Context& c)
+ : Context (c), type_pass_ (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String const& name (esimpl_custom (l));
+
+ if (!name)
+ return;
+
+ SemanticGraph::Type& t (l.argumented ().type ());
+
+ String const& skel (esskel (l));
+ String const& arg (sarg_type (l));
+ String const& ret (sret_type (t));
+
+ String item (unclash (skel, "item"));
+ String item_next (unclash (skel, "item_next"));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ String const& state (esstate (l));
+
+ // pre
+ //
+ os << "void " << name << "::" << endl
+ << "pre (" << arg << " x)"
+ << "{"
+ << "this->" << state << ".i_ = x.begin ();"
+ << "this->" << state << ".end_ = x.end ();"
+ << "}";
+
+ // item_next
+ //
+ os << "bool " << name << "::" << endl
+ << item_next << " ()"
+ << "{"
+ << "return this->" << state << ".i_ != this->" <<
+ state << ".end_;"
+ << "}";
+
+ // item
+ //
+ os << ret << " " << name << "::" << endl
+ << item << " ()"
+ << "{"
+ << "return ";
+
+ type_pass_.dispatch (t);
+
+ os << "*this->" << state << ".i_++;"
+ << "}";
+ }
+
+ private:
+ TypePass type_pass_;
+ };
+
+ //
+ //
+ struct Union: Traversal::Union, Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ String const& name (esimpl_custom (u));
+
+ if (!name)
+ return;
+
+ String const& state (esstate (u));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ // pre
+ //
+ String const& arg (sarg_type (u));
+
+ os << "void " << name << "::" << endl
+ << "pre (" << arg << " x)"
+ << "{"
+ << "this->" << state << " = &x;"
+ << "}";
+
+ // _serialize_content
+ //
+ String const& value (u.context ().get<String> ("value"));
+
+ os << "void " << name << "::" << endl
+ << "_serialize_content ()"
+ << "{";
+
+ if (stl)
+ {
+ os << "const ::std::string& s = this->" << state << "->" <<
+ value << " ();"
+ << "this->_characters (s.c_str (), s.size ());";
+ }
+ else
+ os << "this->_characters (" <<
+ "this->" << state << "->" << value << " ());";
+
+ os << "}";
+ }
+ };
+
+ //
+ //
+ struct SerializerContext: Context
+ {
+ SerializerContext (Context& c)
+ : Context (c)
+ {
+ }
+
+ // Return the access sequence up until this particle. If
+ // element is false then the access sequence for the
+ // container is returned. Otherwise the access sequence
+ // for the current element in the container is returned.
+ //
+ String
+ access_seq (SemanticGraph::Particle& p, Boolean element = true)
+ {
+ using namespace SemanticGraph;
+
+ String r;
+
+ Boolean seq (false);
+
+ Compositor* c;
+
+ if (p.contained_particle_p ())
+ {
+ c = &p.contained_particle ().compositor ();
+
+ // Check if this particle is a sequence. In this case
+ // we just need the top-level struct member.
+ //
+ if (element && p.max () != 1)
+ {
+ seq = true;
+ }
+ else
+ {
+ for (;; c = &c->contained_particle ().compositor ())
+ {
+ if (c->context ().count ("type"))
+ {
+ // Not a see-through compositor.
+ //
+ if (c->max () != 1)
+ {
+ String const& iter (esstate_member (*c));
+
+ if (!r)
+ {
+ r = iter;
+ r += L"->";
+ }
+ else
+ {
+ String tmp;
+ tmp.swap (r);
+ r = iter;
+ r += L"->";
+ r += tmp;
+ }
+
+ seq = true;
+ break;
+ }
+ else
+ {
+ String const& func (ename (*c));
+
+ if (!r)
+ {
+ r = func;
+ r += L" ().";
+ }
+ else
+ {
+ String tmp;
+ tmp.swap (r);
+ r = func;
+ r += L" ().";
+ r += tmp;
+ }
+ }
+ }
+
+ if (c->contained_compositor_p ())
+ break;
+ }
+ }
+
+ // Get to the top in case we bailed out on a sequence.
+ //
+ while (!c->contained_compositor_p ())
+ c = &c->contained_particle ().compositor ();
+ }
+ else
+ {
+ // This particle is a top-level compositor.
+ //
+ c = &dynamic_cast<Compositor&> (p);
+ seq = element && c->max () != 1;
+ }
+
+ Complex& t (
+ dynamic_cast<Complex&> (
+ c->contained_compositor ().container ()));
+
+ if (!seq)
+ {
+ String const& s (esstate_member (t));
+
+ if (!r)
+ {
+ r = s;
+ r += L"->";
+ }
+ else
+ {
+ String tmp;
+ tmp.swap (r);
+ r = s;
+ r += L"->";
+ r += tmp;
+ }
+ }
+
+ String tmp;
+ tmp.swap (r);
+ r = esstate (t);
+ r += L".";
+ r += tmp;
+
+ return r;
+ }
+
+ String
+ access_seq (SemanticGraph::Attribute& a)
+ {
+ using namespace SemanticGraph;
+
+ Complex& t (dynamic_cast<Complex&> (a.scope ()));
+
+ String r (esstate (t));
+ r += L".";
+ r += esstate_member (t);
+ r += L"->";
+
+ return r;
+ }
+ };
+
+ //
+ // Test for presence of sequences.
+ //
+
+ struct CompositorTest: Traversal::Choice,
+ Traversal::Sequence
+ {
+ CompositorTest (Boolean& seq)
+ : seq_ (seq)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ if (c.max () != 1)
+ seq_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ if (s.max () != 1)
+ seq_ = true;
+ else if (s.min () == 1)
+ {
+ // Test nested particles of the see-through sequence.
+ //
+ Sequence::traverse (s);
+ }
+ }
+
+ private:
+ Boolean& seq_;
+ };
+
+ struct ParticleTest: Traversal::Element
+ {
+ ParticleTest (Boolean& seq)
+ : seq_ (seq)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (e.max () != 1)
+ seq_ = true;
+ }
+
+ private:
+ Boolean& seq_;
+ };
+
+ //
+ // State initializers.
+ //
+
+ struct CompositorInit: Traversal::Choice,
+ Traversal::Sequence,
+ SerializerContext
+ {
+ CompositorInit (Context& c)
+ : SerializerContext (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ if (c.max () != 1)
+ {
+ String access (access_seq (c));
+ String access_s (access_seq (c, false));
+ String const& iter (esstate_member (c));
+ String const& end (esstate_member_end (c));
+
+ // Initialize the iterator.
+ //
+ os << "this->" << access << end << " = this->" <<
+ access_s << ename (c) << " ().end ();"
+ << "this->" << access << iter << " = this->" <<
+ access << end << ";";
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ if (s.max () != 1)
+ {
+ String access (access_seq (s));
+ String access_s (access_seq (s, false));
+ String const& iter (esstate_member (s));
+ String const& end (esstate_member_end (s));
+
+ // Initialize the iterator.
+ //
+ os << "this->" << access << end << " = this->" <<
+ access_s << ename (s) << " ().end ();"
+ << "this->" << access << iter << " = this->" <<
+ access << end << ";";
+ }
+ else if (s.min () == 1)
+ {
+ // Initialize nested particles of the see-through sequence.
+ //
+ Sequence::traverse (s);
+ }
+ }
+ };
+
+ struct ParticleInit: Traversal::Element, SerializerContext
+ {
+ ParticleInit (Context& c)
+ : SerializerContext (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (e.max () != 1)
+ {
+ String access (access_seq (e));
+ String access_s (access_seq (e, false));
+ String const& iter (esstate_member (e));
+ String const& end (esstate_member_end (e));
+ String const& name (ename (e));
+
+ // Initialize the iterator.
+ //
+ os << "this->" << access << iter << " = this->" <<
+ access_s << name << " ().begin ();"
+ << "this->" << access << end << " = this->" <<
+ access_s << name << " ().end ();";
+ }
+ }
+ };
+
+ //
+ // Callbacks.
+ //
+
+ struct CompositorCallback: Traversal::All,
+ Traversal::Choice,
+ Traversal::Sequence,
+ SerializerContext
+ {
+ CompositorCallback (Context& c, Traversal::ContainsParticle& init)
+ : SerializerContext (c),
+ init_ (init),
+ compositor_test_ (seq_),
+ particle_test_ (seq_)
+ {
+ compositor_test_ >> contains_particle_test_;
+ contains_particle_test_ >> compositor_test_;
+ contains_particle_test_ >> particle_test_;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ // For the all compositor, maxOccurs=1 and minOccurs={0,1}.
+ //
+ if (a.min () == 0)
+ {
+ String const& s (esimpl_custom (scope (a)));
+
+ os << "bool " << s << "::" << endl
+ << espresent (a) << " ()"
+ << "{"
+ << "return this->" << access_seq (a) << epresent (a) << " ();"
+ << "}";
+ }
+
+ All::traverse (a);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ SemanticGraph::Complex& t (scope (c));
+
+ String access (access_seq (c));
+ String const& s (esimpl_custom (t));
+ String const& arm_tag (esarm_tag (c));
+
+ if (c.max () != 1)
+ {
+ String access_s (access_seq (c, false));
+ String const& iter (esstate_member (c));
+ String const& end (esstate_member_end (c));
+
+ // When iterating over a compositor sequence, there is no
+ // simple place to increment the iterator. So we will need
+ // to increment it in *_next() and make sure we handle the
+ // first call in a special way.
+ //
+ os << "bool " << s << "::" << endl
+ << esnext (c) << " ()"
+ << "{"
+ << "if (this->" << access << iter << " != this->" <<
+ access << end << ")" << endl
+ << "this->" << access << iter << "++;"
+ << "else" << endl
+ << "this->" << access << iter << " = this->" <<
+ access_s << ename (c) << " ().begin ();"
+ << endl
+ << "return this->" << access << iter << " != this->" <<
+ access << end << ";"
+ << "}";
+
+ os << esskel (t) << "::" << arm_tag << " " << s << "::" << endl
+ << esarm (c) << " ()"
+ << "{"
+ << arm_tag << " t (static_cast< " << arm_tag << " > (" << endl
+ << "this->" << access << iter << "->" << earm (c) << " ()));";
+ }
+ else if (c.min () == 0)
+ {
+ os << "bool " << s << "::" << endl
+ << espresent (c) << " ()"
+ << "{"
+ << "return this->" << access << epresent (c) << " ();"
+ << "}";
+
+ os << esskel (t) << "::" << arm_tag << " " << s << "::" << endl
+ << esarm (c) << " ()"
+ << "{"
+ << arm_tag << " t (static_cast< " << arm_tag << " > (" << endl
+ << "this->" << access << ename (c) << " ()." <<
+ earm (c) << " ()));";
+ }
+ else
+ {
+ os << esskel (t) << "::" << arm_tag << " " << s << "::" << endl
+ << esarm (c) << " ()"
+ << "{"
+ << arm_tag << " t (static_cast< " << arm_tag << " > (" << endl;
+
+
+ // We may be in a choice in which case we get a nested
+ // type (and accessor function) even for min == max == 1.
+ //
+ if (c.context ().count ("type"))
+ os << "this->" << access << ename (c) << " ()." <<
+ earm (c) << " ()));";
+ else
+ os << "this->" << access << earm (c) << " ()));";
+ }
+
+ // Test whether we have any arms that need initialization.
+ //
+ seq_ = false;
+
+ for (SemanticGraph::Choice::ContainsIterator
+ i (c.contains_begin ()), e (c.contains_end ());
+ !seq_ && i != e; ++i)
+ {
+ contains_particle_test_.dispatch (*i);
+ }
+
+ if (seq_)
+ {
+ os << "switch (t)"
+ << "{";
+
+ for (SemanticGraph::Choice::ContainsIterator
+ i (c.contains_begin ()), e (c.contains_end ());
+ i != e; ++i)
+ {
+ // Test if this arm needs initialization.
+ //
+ seq_ = false;
+ contains_particle_test_.dispatch (*i);
+
+ if (seq_)
+ {
+ SemanticGraph::Particle& p (i->particle ());
+
+ os << "case " << estag (p) << ":"
+ << "{";
+ init_.dispatch (*i);
+ os << "break;"
+ << "}";
+ }
+ }
+
+ os << "default:"
+ << "{"
+ << "break;"
+ << "}"
+ << "}";
+ }
+
+ os << "return t;"
+ << "}";
+
+ Choice::traverse (c);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ String const& sc (esimpl_custom (scope (s)));
+
+ if (s.max () != 1)
+ {
+ String access (access_seq (s));
+ String access_s (access_seq (s, false));
+ String const& iter (esstate_member (s));
+ String const& end (esstate_member_end (s));
+
+ // When iterating over a compositor sequence, there is no
+ // simple place to increment the iterator. So we will need
+ // to increment it in *_next() and make sure we handle the
+ // first call in a special way.
+ //
+ os << "bool " << sc << "::" << endl
+ << esnext (s) << " ()"
+ << "{"
+ << "if (this->" << access << iter << " != this->" <<
+ access << end << ")" << endl
+ << "this->" << access << iter << "++;"
+ << "else" << endl
+ << "this->" << access << iter << " = this->" <<
+ access_s << ename (s) << " ().begin ();"
+ << endl
+ << "if (this->" << access << iter << " != this->" <<
+ access << end << ")"
+ << "{";
+
+ Sequence::contains (s, init_);
+
+ os << "return true;"
+ << "}"
+ << "else" << endl
+ << "return false;"
+ << "}";
+ }
+ else if (s.min () == 0)
+ {
+ os << "bool " << sc << "::" << endl
+ << espresent (s) << " ()"
+ << "{"
+ << "if (this->" << access_seq (s) << epresent (s) << " ())"
+ << "{";
+
+ Sequence::contains (s, init_);
+
+ os << "return true;"
+ << "}"
+ << "else" << endl
+ << "return false;"
+ << "}";
+ }
+
+ Sequence::traverse (s);
+ }
+
+ private:
+ SemanticGraph::Complex&
+ scope (SemanticGraph::Compositor& c)
+ {
+ SemanticGraph::Compositor* root (&c);
+
+ while (root->contained_particle_p ())
+ root = &root->contained_particle ().compositor ();
+
+ return dynamic_cast<SemanticGraph::Complex&> (
+ root->contained_compositor ().container ());
+ }
+
+ private:
+ Traversal::ContainsParticle& init_;
+
+ Boolean seq_;
+ CompositorTest compositor_test_;
+ ParticleTest particle_test_;
+ Traversal::ContainsParticle contains_particle_test_;
+ };
+
+ struct ParticleCallback: Traversal::Element, SerializerContext
+ {
+ ParticleCallback (Context& c)
+ : SerializerContext (c), type_pass_ (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ String const& s (
+ esimpl_custom (
+ dynamic_cast<SemanticGraph::Complex&> (e.scope ())));
+
+ SemanticGraph::Type& t (e.type ());
+ String const& ret (sret_type (t));
+ String access (access_seq (e));
+
+ if (e.max () != 1)
+ {
+ String const& iter (esstate_member (e));
+
+ os << "bool " << s << "::" << endl
+ << esnext (e) << " ()"
+ << "{"
+ << "return this->" << access << iter << " != this->" <<
+ access << esstate_member_end (e) << ";"
+ << "}";
+
+ os << ret << " " << s << "::" << endl
+ << esname (e) << " ()"
+ << "{";
+
+ if (ret != L"void")
+ {
+ os << "return ";
+ type_pass_.dispatch (t);
+ os << "*this->" << access << iter << "++;";
+ }
+
+ os << "}";
+ }
+ else
+ {
+ if (e.min () == 0)
+ {
+ os << "bool " << s << "::" << endl
+ << espresent (e) << " ()"
+ << "{"
+ << "return this->" << access << epresent (e) << " ();"
+ << "}";
+ }
+
+ os << ret << " " << s << "::" << endl
+ << esname (e) << " ()"
+ << "{";
+
+ if (ret != L"void")
+ {
+ os << "return ";
+ type_pass_.dispatch (t);
+ os << "this->" << access << ename (e) << " ();";
+ }
+
+ os << "}";
+ }
+ }
+
+ private:
+ TypePass type_pass_;
+ };
+
+ struct AttributeCallback: Traversal::Attribute, SerializerContext
+ {
+ AttributeCallback (Context& c)
+ : SerializerContext (c), type_pass_ (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ String const& s (
+ esimpl_custom (
+ dynamic_cast<SemanticGraph::Complex&> (a.scope ())));
+
+ String access (access_seq (a));
+
+ if (a.optional ())
+ {
+ os << "bool " << s << "::" << endl
+ << espresent (a) << " ()"
+ << "{"
+ << "return this->" << access << epresent (a) << " ();"
+ << "}";
+ }
+
+ SemanticGraph::Type& t (a.type ());
+ String const& ret (sret_type (t));
+
+ os << ret << " " << s << "::" << endl
+ << esname (a) << " ()"
+ << "{";
+
+ if (ret != L"void")
+ {
+ os << "return ";
+ type_pass_.dispatch (t);
+ os << "this->" << access << ename (a) << " ();";
+ }
+
+ os << "}";
+ }
+
+ private:
+ TypePass type_pass_;
+ };
+
+ //
+ //
+ struct Complex: Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c),
+ type_pass_ (c),
+
+ // Initializers.
+ //
+ compositor_init_ (c),
+ particle_init_ (c),
+
+ // Callbacks.
+ //
+ compositor_callback_ (c, contains_particle_init_),
+ particle_callback_ (c),
+ attribute_callback_ (c)
+ {
+ // Initializers.
+ //
+ contains_compositor_init_ >> compositor_init_;
+ compositor_init_ >> contains_particle_init_;
+ contains_particle_init_ >> compositor_init_;
+ contains_particle_init_ >> particle_init_;
+
+ // Callbacks.
+ //
+ contains_compositor_callback_ >> compositor_callback_;
+ compositor_callback_ >> contains_particle_callback_;
+ contains_particle_callback_ >> compositor_callback_;
+ contains_particle_callback_ >> particle_callback_;
+
+ names_attribute_callback_ >> attribute_callback_;
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ String const& name (esimpl_custom (c));
+
+ if (!name)
+ return;
+
+ Boolean hb (c.inherits_p ());
+ Boolean restriction (restriction_p (c));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ // c-tor
+ //
+ if (tiein && hb)
+ os << name << "::" << endl
+ << name << " ()" << endl
+ << ": " << esskel (c) << " (&base_impl_)"
+ << "{"
+ << "}";
+
+ // pre
+ //
+ String const& arg (sarg_type (c));
+
+ os << "void " << name << "::" << endl
+ << "pre (" << arg << " x)"
+ << "{";
+
+ if (hb)
+ {
+ SemanticGraph::Type& b (c.inherits ().base ());
+
+ // Default serializer implementations for anyType and
+ // anySimpleType return void.
+ //
+ if (!b.is_a<SemanticGraph::AnyType> () &&
+ !b.is_a<SemanticGraph::AnySimpleType> ())
+ {
+
+ if (tiein)
+ os << "this->base_impl_.pre (";
+ else
+ os << esimpl (b) << "::pre (";
+
+ type_pass_.dispatch (b);
+
+ os << "x);";
+ }
+ }
+
+ if (!restriction)
+ {
+ os << "this->" << esstate (c) << "." << esstate_member (c) <<
+ " = &x;";
+
+ contains_compositor (c, contains_compositor_init_);
+ }
+
+ os << "}";
+
+ // Member callbacks.
+ //
+ if (!restriction)
+ {
+ names (c, names_attribute_callback_);
+ contains_compositor (c, contains_compositor_callback_);
+ }
+ }
+
+ private:
+ TypePass type_pass_;
+
+ // Initializers.
+ //
+ CompositorInit compositor_init_;
+ ParticleInit particle_init_;
+ Traversal::ContainsCompositor contains_compositor_init_;
+ Traversal::ContainsParticle contains_particle_init_;
+
+ // Callbacks.
+ //
+ CompositorCallback compositor_callback_;
+ ParticleCallback particle_callback_;
+ Traversal::ContainsCompositor contains_compositor_callback_;
+ Traversal::ContainsParticle contains_particle_callback_;
+
+ AttributeCallback attribute_callback_;
+ Traversal::Names names_attribute_callback_;
+ };
+ }
+
+ Void
+ generate_serializer_source (Context& ctx)
+ {
+ Traversal::Schema schema;
+
+ Traversal::Sources sources;
+ Traversal::Names schema_names;
+
+ Namespace ns (ctx);
+ Traversal::Names names;
+
+ schema >> sources >> schema;
+ schema >> schema_names >> ns >> names;
+
+ List list (ctx);
+ Union union_ (ctx);
+ Complex complex (ctx);
+
+ names >> list;
+ names >> union_;
+ names >> complex;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+}
diff --git a/xsde/cxx/hybrid/serializer-source.hxx b/xsde/cxx/hybrid/serializer-source.hxx
new file mode 100644
index 0000000..dee3629
--- /dev/null
+++ b/xsde/cxx/hybrid/serializer-source.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/hybrid/serializer-source.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_SERIALIZER_SOURCE_HXX
+#define CXX_HYBRID_SERIALIZER_SOURCE_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/hybrid/elements.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ Void
+ generate_serializer_source (Context&);
+ }
+}
+
+#endif // CXX_HYBRID_SERIALIZER_SOURCE_HXX
diff --git a/xsde/cxx/hybrid/tree-forward.cxx b/xsde/cxx/hybrid/tree-forward.cxx
new file mode 100644
index 0000000..f1c0dfa
--- /dev/null
+++ b/xsde/cxx/hybrid/tree-forward.cxx
@@ -0,0 +1,626 @@
+// file : xsd/cxx/hybrid/tree-forward.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/hybrid/tree-forward.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ namespace
+ {
+ struct List : Traversal::List, Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ os << "class " << ename (l) << ";";
+ }
+ };
+
+ struct Union : Traversal::Union, Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ os << "class " << ename (u) << ";";
+ }
+ };
+
+ struct Complex : Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ os << "class " << ename (c) << ";";
+ }
+ };
+
+ struct FundType : Context,
+
+ Traversal::AnyType,
+ Traversal::AnySimpleType,
+
+ Traversal::Fundamental::Byte,
+ Traversal::Fundamental::UnsignedByte,
+ Traversal::Fundamental::Short,
+ Traversal::Fundamental::UnsignedShort,
+ Traversal::Fundamental::Int,
+ Traversal::Fundamental::UnsignedInt,
+ Traversal::Fundamental::Long,
+ Traversal::Fundamental::UnsignedLong,
+ Traversal::Fundamental::Integer,
+ Traversal::Fundamental::NonPositiveInteger,
+ Traversal::Fundamental::NonNegativeInteger,
+ Traversal::Fundamental::PositiveInteger,
+ Traversal::Fundamental::NegativeInteger,
+
+ Traversal::Fundamental::Boolean,
+
+ Traversal::Fundamental::Float,
+ Traversal::Fundamental::Double,
+ Traversal::Fundamental::Decimal,
+
+ Traversal::Fundamental::String,
+ Traversal::Fundamental::NormalizedString,
+ Traversal::Fundamental::Token,
+ Traversal::Fundamental::Name,
+ Traversal::Fundamental::NameToken,
+ Traversal::Fundamental::NameTokens,
+ Traversal::Fundamental::NCName,
+ Traversal::Fundamental::Language,
+
+ Traversal::Fundamental::QName,
+
+ Traversal::Fundamental::Id,
+ Traversal::Fundamental::IdRef,
+ Traversal::Fundamental::IdRefs,
+
+ Traversal::Fundamental::AnyURI,
+
+ Traversal::Fundamental::Base64Binary,
+ Traversal::Fundamental::HexBinary,
+
+ Traversal::Fundamental::Date,
+ Traversal::Fundamental::DateTime,
+ Traversal::Fundamental::Duration,
+ Traversal::Fundamental::Day,
+ Traversal::Fundamental::Month,
+ Traversal::Fundamental::MonthDay,
+ Traversal::Fundamental::Year,
+ Traversal::Fundamental::YearMonth,
+ Traversal::Fundamental::Time,
+
+ Traversal::Fundamental::Entity,
+ Traversal::Fundamental::Entities
+ {
+ FundType (Context& c)
+ : Context (c)
+ {
+ if (stl)
+ string_type_ = L"::std::string";
+ else
+ string_type_ = L"char*";
+
+ if (options.value<CLI::no_long_long> ())
+ {
+ long_type_ = L"long";
+ unsigned_long_type_ = L"unsigned long";
+ }
+ else
+ {
+ long_type_ = L"long long";
+ unsigned_long_type_ = L"unsigned long long";
+ }
+ }
+
+ // anyType & anySimpleType.
+ //
+ virtual Void
+ traverse (SemanticGraph::AnyType&)
+ {
+ gen_using ("::xsde::cxx::hybrid::any_type");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnySimpleType&)
+ {
+ gen_using ("::xsde::cxx::hybrid::any_simple_type");
+ }
+
+ // Boolean.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Boolean&)
+ {
+ gen_typedef ("boolean", "bool");
+ gen_using ("::xsde::cxx::hybrid::boolean_base");
+ os << endl;
+ }
+
+ // Integral types.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Byte&)
+ {
+ gen_typedef ("byte", "signed char");
+ gen_using ("::xsde::cxx::hybrid::byte_base");
+ os << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedByte&)
+ {
+ gen_typedef ("unsigned_byte", "unsigned char");
+ gen_using ("::xsde::cxx::hybrid::unsigned_byte_base");
+ os << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Short&)
+ {
+ gen_typedef ("short", "short");
+ gen_using ("::xsde::cxx::hybrid::short_base");
+ os << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedShort&)
+ {
+ gen_typedef ("unsigned_short", "unsigned short");
+ gen_using ("::xsde::cxx::hybrid::unsigned_short_base");
+ os << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Int&)
+ {
+ gen_typedef ("int", "int");
+ gen_using ("::xsde::cxx::hybrid::int_base");
+ os << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedInt&)
+ {
+ gen_typedef ("unsigned_int", "unsigned int");
+ gen_using ("::xsde::cxx::hybrid::unsigned_int_base");
+ os << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Long&)
+ {
+ gen_typedef ("long", long_type_);
+ gen_using ("::xsde::cxx::hybrid::long_base");
+ os << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedLong&)
+ {
+ gen_typedef ("unsigned_long", unsigned_long_type_);
+ gen_using ("::xsde::cxx::hybrid::unsigned_long_base");
+ os << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Integer&)
+ {
+ gen_typedef ("integer", "long");
+ gen_using ("::xsde::cxx::hybrid::integer_base");
+ os << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NegativeInteger&)
+ {
+ gen_typedef ("negative_integer", "long");
+ gen_using ("::xsde::cxx::hybrid::negative_integer_base");
+ os << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonPositiveInteger&)
+ {
+ gen_typedef ("non_positive_integer", "long");
+ gen_using ("::xsde::cxx::hybrid::non_positive_integer_base");
+ os << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::PositiveInteger&)
+ {
+ gen_typedef ("positive_integer", "unsigned long");
+ gen_using ("::xsde::cxx::hybrid::positive_integer_base");
+ os << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonNegativeInteger&)
+ {
+ gen_typedef ("non_negative_integer", "unsigned long");
+ gen_using ("::xsde::cxx::hybrid::non_negative_integer_base");
+ os << endl;
+ }
+
+ // Floats.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Float&)
+ {
+ gen_typedef ("float", "float");
+ gen_using ("::xsde::cxx::hybrid::float_base");
+ os << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Double&)
+ {
+ gen_typedef ("double", "double");
+ gen_using ("::xsde::cxx::hybrid::double_base");
+ os << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Decimal&)
+ {
+ gen_typedef ("decimal", "double");
+ gen_using ("::xsde::cxx::hybrid::decimal_base");
+ os << endl;
+ }
+
+ // Strings.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::String&)
+ {
+ gen_typedef ("string", string_type_);
+ gen_using ("::xsde::cxx::hybrid::string_base");
+ os << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NormalizedString&)
+ {
+ gen_typedef ("normalized_string", string_type_);
+
+ if (!stl)
+ gen_typedef ("normalized_string_base",
+ "::xsde::cxx::hybrid::string_base");
+ os << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Token&)
+ {
+ gen_typedef ("token", string_type_);
+ if (!stl)
+ gen_typedef ("token_base", "::xsde::cxx::hybrid::string_base");
+ os << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameToken&)
+ {
+ gen_typedef ("nmtoken", string_type_);
+ if (!stl)
+ gen_typedef ("nmtoken_base", "::xsde::cxx::hybrid::string_base");
+ os << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameTokens&)
+ {
+ gen_typedef ("nmtokens", "::xsde::cxx::string_sequence");
+ os << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Name&)
+ {
+ gen_typedef ("name", string_type_);
+ if (!stl)
+ gen_typedef ("name_base", "::xsde::cxx::hybrid::string_base");
+ os << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NCName&)
+ {
+ gen_typedef ("ncname", string_type_);
+ if (!stl)
+ gen_typedef ("ncname_base", "::xsde::cxx::hybrid::string_base");
+ os << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Language&)
+ {
+ gen_typedef ("language", string_type_);
+ if (!stl)
+ gen_typedef ("language_base", "::xsde::cxx::hybrid::string_base");
+ os << endl;
+ }
+
+ // Qualified name.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::QName&)
+ {
+ gen_using ("::xsde::cxx::qname");
+ os << endl;
+ }
+
+ // ID/IDREF.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Id&)
+ {
+ gen_typedef ("id", string_type_);
+ if (!stl)
+ gen_typedef ("id_base", "::xsde::cxx::hybrid::string_base");
+ os << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRef&)
+ {
+ gen_typedef ("idref", string_type_);
+ if (!stl)
+ gen_typedef ("idref_base", "::xsde::cxx::hybrid::string_base");
+ os << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRefs&)
+ {
+ gen_typedef ("idrefs", "::xsde::cxx::string_sequence");
+ os << endl;
+ }
+
+ // URI.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::AnyURI&)
+ {
+ gen_typedef ("uri", string_type_);
+ if (!stl)
+ gen_typedef ("uri_base", "::xsde::cxx::hybrid::string_base");
+ os << endl;
+ }
+
+ // Binary.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Base64Binary&)
+ {
+ gen_typedef ("base64_binary", "::xsde::cxx::buffer");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::HexBinary&)
+ {
+ gen_typedef ("hex_binary", "::xsde::cxx::buffer");
+ os << endl;
+ }
+
+
+ // Date/time.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Date&)
+ {
+ gen_using ("::xsde::cxx::date");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::DateTime&)
+ {
+ gen_using ("::xsde::cxx::date_time");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Duration&)
+ {
+ gen_using ("::xsde::cxx::duration");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Day&)
+ {
+ gen_using ("::xsde::cxx::gday");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Month&)
+ {
+ gen_using ("::xsde::cxx::gmonth");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::MonthDay&)
+ {
+ gen_using ("::xsde::cxx::gmonth_day");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Year&)
+ {
+ gen_using ("::xsde::cxx::gyear");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::YearMonth&)
+ {
+ gen_using ("::xsde::cxx::gyear_month");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Time&)
+ {
+ gen_using ("::xsde::cxx::time");
+ }
+
+ // Entity.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entity&)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entities&)
+ {
+ }
+
+ private:
+ Void
+ gen_typedef (String const& name, String const& type)
+ {
+ os << "typedef " << type << " " << escape (name) << ";";
+ }
+
+ Void
+ gen_using (String const& name)
+ {
+ os << "using " << name << ";";
+ }
+
+ String string_type_;
+ String long_type_;
+ String unsigned_long_type_;
+ };
+
+ struct FundNamespace : Namespace, Context
+ {
+ FundNamespace (Context& c)
+ : Namespace (c), Context (c)
+ {
+ }
+
+ void
+ traverse (Type& ns)
+ {
+ pre (ns);
+ names (ns);
+
+ // strdupx
+ //
+ if (!stl)
+ {
+ os << endl
+ << "using ::xsde::cxx::strdupx;"
+ << "using ::xsde::cxx::strndupx;";
+ }
+
+ post (ns);
+ }
+ };
+ }
+
+ Void
+ generate_tree_forward (Context& ctx, Boolean generate_xml_schema)
+ {
+ NarrowString xml_schema (ctx.options.value<CLI::extern_xml_schema> ());
+
+ // Inlcude or Emit fundamental types.
+ //
+ if (!generate_xml_schema && xml_schema)
+ {
+ String name (ctx.hxx_expr->merge (xml_schema));
+
+ ctx.os << "#include " << ctx.process_include_path (name) << endl
+ << endl;
+ }
+ else
+ {
+ if (ctx.stl)
+ ctx.os << "#include <string>" << endl;
+ else
+ ctx.os << "#include <xsde/cxx/strdupx.hxx>" << endl;
+
+ ctx.os << "#include <xsde/cxx/hybrid/xml-schema.hxx>" << endl
+ << endl;
+
+ if (generate_xml_schema)
+ {
+ Traversal::Schema schema;
+ Traversal::Names names;
+ FundNamespace ns (ctx);
+
+ schema >> names >> ns;
+
+ Traversal::Names ns_names;
+ FundType type (ctx);
+
+ ns >> ns_names >> type;
+
+ schema.dispatch (ctx.schema_root);
+
+ return;
+ }
+ else
+ {
+ Traversal::Schema schema, xsd;
+ Traversal::Implies implies;
+ Traversal::Names names;
+ FundNamespace ns (ctx);
+
+ schema >> implies >> xsd >> names >> ns;
+
+ Traversal::Names ns_names;
+ FundType type (ctx);
+
+ ns >> ns_names >> type;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+
+ Traversal::Schema schema;
+
+ Traversal::Sources sources;
+ Traversal::Names names_ns, names;
+
+ Namespace ns (ctx);
+
+ List list (ctx);
+ Union union_ (ctx);
+ Complex complex (ctx);
+ //Enumeration enumeration (ctx);
+
+ schema >> sources >> schema;
+ schema >> names_ns >> ns >> names;
+
+ names >> list;
+ names >> union_;
+ names >> complex;
+ //names >> enumeration;
+
+ schema.dispatch (ctx.schema_root);
+
+ ctx.os << endl;
+ }
+ }
+}
diff --git a/xsde/cxx/hybrid/tree-forward.hxx b/xsde/cxx/hybrid/tree-forward.hxx
new file mode 100644
index 0000000..19dbf5d
--- /dev/null
+++ b/xsde/cxx/hybrid/tree-forward.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/hybrid/tree-forward.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_TREE_FORWARD_HXX
+#define CXX_HYBRID_TREE_FORWARD_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/hybrid/elements.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ Void
+ generate_tree_forward (Context&, Boolean generate_xml_schema);
+ }
+}
+
+#endif // CXX_HYBRID_TREE_FORWARD_HXX
diff --git a/xsde/cxx/hybrid/tree-header.cxx b/xsde/cxx/hybrid/tree-header.cxx
new file mode 100644
index 0000000..c7231c9
--- /dev/null
+++ b/xsde/cxx/hybrid/tree-header.cxx
@@ -0,0 +1,2459 @@
+// file : xsd/cxx/hybrid/tree-header.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/hybrid/tree-header.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ namespace
+ {
+ struct List : Traversal::List, Context
+ {
+ List (Context& c)
+ : Context (c), base_name_ (c, TypeName::seq)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String name (ename (l));
+
+ os << "// " << comment (l.name ()) << " (variable-length)" << endl
+ << "//" << endl;
+
+ os << "class " << name << ": public ";
+
+ base_name_.dispatch (l.argumented ().type ());
+
+ os << "{"
+ << "private:" << endl
+ << name << " (const " << name << "&);"
+ << name << "& operator= (const " << name << "&);"
+ << endl;
+
+ // c-tor
+ //
+ os << "public:" << endl
+ << name << " ();";
+
+ // Custom data.
+ //
+ if (l.context ().count ("cd-name"))
+ {
+ 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
+ << "//" << endl;
+
+ // sequence & iterators
+ //
+ os << "typedef ::xsde::cxx::hybrid::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;
+
+ os << "private:" << endl
+ << sequence << " " << ecd_member (l) << ";";
+ }
+
+ os << "};";
+ }
+
+ private:
+ TypeName base_name_;
+ };
+
+ struct Union : Traversal::Union, Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ SemanticGraph::Context& uc (u.context ());
+
+ String name (ename (u));
+ Boolean cd (uc.count ("cd-name"));
+
+ os << "// " << comment (u.name ()) << " (variable-length)" << endl
+ << "//" << endl;
+
+ os << "class " << name
+ << "{";
+
+ if (!fixed_length (u))
+ os << "private:" << endl
+ << name << " (const " << name << "&);"
+ << name << "& operator= (const " << name << "&);"
+ << endl;
+
+ os << "public:" << endl;
+
+ // c-tor
+ //
+ os << name << " ();";
+
+ String const& value (uc.get<String> ("value"));
+ String const& member (uc.get<String> ("value-member"));
+
+ if (stl)
+ {
+ os << endl;
+
+ // const std::string&
+ // name () const
+ //
+ os << "const ::std::string&" << endl
+ << value << " () const;"
+ << endl;
+
+ // std::string&
+ // name ()
+ //
+ os << "::std::string&" << endl
+ << value << " ();"
+ << endl;
+
+ // void
+ // name (const std::string&)
+ //
+ os << "void" << endl
+ << value << " (const ::std::string&);"
+ << endl;
+ }
+ else
+ {
+ // d-tor
+ //
+ os << "~" << name << " ();"
+ << endl;
+
+ // const char*
+ // name () const
+ //
+ os << "const char*" << endl
+ << value << " () const;"
+ << endl;
+
+ // char*
+ // name ()
+ //
+ os << "char*" << endl
+ << value << " ();"
+ << endl;
+
+ // void
+ // name (char*)
+ //
+ os << "void" << endl
+ << value << " (char*);"
+ << endl;
+ }
+
+ // Custom data.
+ //
+ if (cd)
+ {
+ String const& name (ecd_name (u));
+ String const& sequence (ecd_sequence (u));
+ String const& iterator (ecd_iterator (u));
+ String const& const_iterator (ecd_const_iterator (u));
+
+ os << "// Custom data." << endl
+ << "//" << endl;
+
+ // sequence & iterators
+ //
+ os << "typedef ::xsde::cxx::hybrid::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 (stl)
+ {
+ os << "private:" << endl
+ << "::std::string " << member << ";";
+ }
+ else
+ {
+ os << "private:" << endl
+ << "char* " << member << ";";
+ }
+
+ // Custom data.
+ //
+ if (cd)
+ os << ecd_sequence (u) << " " << ecd_member (u) << ";";
+
+ os << "};";
+ }
+ };
+
+ //
+ // Data.
+ //
+
+ struct AlignType: Traversal::Compositor,
+
+ Traversal::List,
+ Traversal::Union,
+ Traversal::Complex,
+
+ Traversal::AnyType,
+ Traversal::AnySimpleType,
+
+ Traversal::Fundamental::Byte,
+ Traversal::Fundamental::UnsignedByte,
+ Traversal::Fundamental::Short,
+ Traversal::Fundamental::UnsignedShort,
+ Traversal::Fundamental::Int,
+ Traversal::Fundamental::UnsignedInt,
+ Traversal::Fundamental::Long,
+ Traversal::Fundamental::UnsignedLong,
+ Traversal::Fundamental::Integer,
+ Traversal::Fundamental::NonPositiveInteger,
+ Traversal::Fundamental::NonNegativeInteger,
+ Traversal::Fundamental::PositiveInteger,
+ Traversal::Fundamental::NegativeInteger,
+
+ Traversal::Fundamental::Boolean,
+
+ Traversal::Fundamental::Float,
+ Traversal::Fundamental::Double,
+ Traversal::Fundamental::Decimal,
+
+ Traversal::Fundamental::String,
+ Traversal::Fundamental::NormalizedString,
+ Traversal::Fundamental::Token,
+ Traversal::Fundamental::Name,
+ Traversal::Fundamental::NameToken,
+ Traversal::Fundamental::NCName,
+ Traversal::Fundamental::Language,
+
+ Traversal::Fundamental::QName,
+
+ Traversal::Fundamental::Id,
+ Traversal::Fundamental::IdRef,
+
+ Traversal::Fundamental::AnyURI,
+
+ Traversal::Fundamental::Date,
+ Traversal::Fundamental::DateTime,
+ Traversal::Fundamental::Duration,
+ Traversal::Fundamental::Day,
+ Traversal::Fundamental::Month,
+ Traversal::Fundamental::MonthDay,
+ Traversal::Fundamental::Year,
+ Traversal::Fundamental::YearMonth,
+ Traversal::Fundamental::Time,
+
+ Traversal::Fundamental::Entity,
+
+ Context
+ {
+ AlignType (Context& c)
+ : Context (c), nested_ (false)
+ {
+ *this >> inherits_ >> *this;
+
+ *this >> attribute_names_ >> attribute_;
+
+ *this >> contains_particle_;
+ contains_particle_ >> particle_;
+ contains_particle_ >> *this;
+ contains_compositor_ >> *this;
+
+ attribute_ >> belongs_;
+ particle_ >> belongs_;
+ belongs_ >> *this;
+ }
+
+ virtual Void
+ dispatch (SemanticGraph::Node& n)
+ {
+ found_ = false;
+ NodeBase::dispatch (n);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Compositor& c)
+ {
+ Boolean top (false);
+
+ if (!nested_)
+ {
+ nested_ = true;
+ top = true;
+ }
+
+ Traversal::Compositor::traverse (c);
+
+ if (top)
+ {
+ nested_ = false;
+
+ if (!found_)
+ os << "char"; // Empty compositor.
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::List&)
+ {
+ align_type ("size_t");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Union&)
+ {
+ align_type ("size_t"); // std::string
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ // Keep track of the nested calls for base types.
+ //
+ Boolean top (false);
+
+ if (!nested_)
+ {
+ nested_ = true;
+ top = true;
+ }
+
+ Complex::inherits (c, inherits_);
+
+ if (!found_)
+ {
+ Complex::names (c, attribute_names_);
+
+ if (!found_ && c.contains_compositor_p ())
+ Complex::contains_compositor (c, contains_compositor_);
+ }
+
+ if (top)
+ {
+ nested_ = false;
+
+ if (!found_)
+ os << "char"; // Empty class.
+ }
+ }
+
+ // anyType & anySimpleType.
+ //
+ virtual Void
+ traverse (SemanticGraph::AnyType&)
+ {
+ align_type ("char");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnySimpleType&)
+ {
+ align_type ("char");
+ }
+
+ // Boolean.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Boolean&)
+ {
+ align_type ("bool");
+ }
+
+ // Integral types.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Byte&)
+ {
+ align_type ("signed char");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedByte&)
+ {
+ align_type ("unsigned char");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Short&)
+ {
+ align_type ("short");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedShort&)
+ {
+ align_type ("unsigned short");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Int&)
+ {
+ align_type ("int");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedInt&)
+ {
+ align_type ("unsigned int");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Long&)
+ {
+ align_type (options.value<CLI::no_long_long> ()
+ ? "long"
+ : "long long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedLong&)
+ {
+ align_type (options.value<CLI::no_long_long> ()
+ ? "unsigned long"
+ : "unsigned long long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Integer&)
+ {
+ align_type ("long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonPositiveInteger&)
+ {
+ align_type ("long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonNegativeInteger&)
+ {
+ align_type ("unsigned long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::PositiveInteger&)
+ {
+ align_type ("unsigned long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NegativeInteger&)
+ {
+ align_type ("long");
+ }
+
+ // Floats.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Float&)
+ {
+ align_type ("float");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Double&)
+ {
+ align_type ("double");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Decimal&)
+ {
+ align_type ("double");
+ }
+
+ // Strings.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::String&)
+ {
+ align_type ("size_t"); // std::string
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NormalizedString&)
+ {
+ align_type ("size_t"); // std::string
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Token&)
+ {
+ align_type ("size_t"); // std::string
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameToken&)
+ {
+ align_type ("size_t"); // std::string
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Name&)
+ {
+ align_type ("size_t"); // std::string
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NCName&)
+ {
+ align_type ("size_t"); // std::string
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Language&)
+ {
+ align_type ("size_t"); // std::string
+ }
+
+ // Qualified name.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::QName&)
+ {
+ align_type ("size_t"); // std::string
+ }
+
+
+ // ID/IDREF.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Id&)
+ {
+ align_type ("size_t"); // std::string
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRef&)
+ {
+ align_type ("size_t"); // std::string
+ }
+
+ // URI.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::AnyURI&)
+ {
+ align_type ("size_t"); // std::string
+ }
+
+
+ // Date/time.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Date&)
+ {
+ align_type ("bool");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::DateTime&)
+ {
+ align_type ("bool");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Duration&)
+ {
+ align_type ("bool");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Day&)
+ {
+ align_type ("bool");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Month&)
+ {
+ align_type ("bool");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::MonthDay&)
+ {
+ align_type ("bool");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Year&)
+ {
+ align_type ("bool");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::YearMonth&)
+ {
+ align_type ("bool");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Time&)
+ {
+ align_type ("bool");
+ }
+
+ // Entity.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entity&)
+ {
+ align_type ("size_t"); // std::string
+ }
+
+ private:
+ Void
+ align_type (Char const* t)
+ {
+ if (!found_)
+ {
+ os << t;
+ found_ = true;
+ }
+ }
+
+ private:
+ Boolean found_;
+ Boolean nested_;
+
+ private:
+ Traversal::Inherits inherits_;
+
+ Traversal::Attribute attribute_;
+ Traversal::Names attribute_names_;
+
+ Traversal::Element particle_;
+ Traversal::ContainsParticle contains_particle_;
+ Traversal::ContainsCompositor contains_compositor_;
+
+ Traversal::Belongs belongs_;
+ };
+
+ struct AttributeData: Traversal::Attribute, Context
+ {
+ AttributeData (Context& c)
+ : Context (c), var_ (c, TypeName::var)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ SemanticGraph::Type& t (a.type ());
+
+ var_.dispatch (t);
+ os << " " << emember (a) << ";";
+
+ if (a.optional () && fixed_length (t))
+ os << "bool " << epresent_member (a) << ";";
+ }
+
+ private:
+ TypeName var_;
+ };
+
+
+ struct ElementData: Traversal::Element, Context
+ {
+ ElementData (Context& c)
+ : Context (c), var_ (c, TypeName::var)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (e.max () != 1)
+ {
+ os << esequence (e) << " " << emember (e) << ";";
+ }
+ else
+ {
+ SemanticGraph::Type& t (e.type ());
+
+ var_.dispatch (t);
+ os << " " << emember (e) << ";";
+
+ if (e.min () == 0 && fixed_length (t))
+ os << "bool " << epresent_member (e) << ";";
+ }
+ }
+
+ private:
+ TypeName var_;
+ };
+
+ struct ElementInChoiceData: Traversal::Element, Context
+ {
+ ElementInChoiceData (Context& c)
+ : Context (c), var_ (c, TypeName::var), align_type_ (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (e.max () != 1)
+ {
+ os << "union"
+ << "{"
+ << "size_t align_;"
+ << "char data_[sizeof (" << esequence (e) << ")];"
+ << "} " << emember (e) << ";";
+ }
+ else
+ {
+ SemanticGraph::Type& t (e.type ());
+
+ if (fixed_length (t))
+ {
+ os << "union"
+ << "{";
+
+ align_type_.dispatch (t);
+
+ os << " align_;"
+ << "char data_[sizeof (";
+
+ var_.dispatch (t);
+
+ os << ")";
+
+ // Reserve an extra byte for the present flag.
+ //
+ if (e.min () == 0)
+ os << " + 1";
+
+ os << "];"
+ << "} " << emember (e) << ";";
+ }
+ else
+ {
+ var_.dispatch (t);
+ os << " " << emember (e) << ";";
+ }
+ }
+ }
+
+ private:
+ TypeName var_;
+ AlignType align_type_;
+ };
+
+ struct AllData: Traversal::All, Context
+ {
+ AllData (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ // For the all compositor, maxOccurs=1 and minOccurs={0,1}
+ // and it can only contain particles.
+ //
+ if (a.min () == 0)
+ {
+ String const& type (etype (a));
+ String const& member (emember(a));
+
+ if (fixed_length (a))
+ {
+ os << type << " " << member << ";"
+ << "bool " << epresent_member (a) << ";";
+ }
+ else
+ os << type << "* " << member << ";";
+ }
+ else
+ All::contains (a);
+ }
+ };
+
+ struct ChoiceInSequenceData: Traversal::Choice, Context
+ {
+ ChoiceInSequenceData (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ if (c.max () != 1)
+ {
+ os << esequence (c) << " " << emember (c) << ";";
+ }
+ else if (c.min () == 0)
+ {
+ String const& type (etype (c));
+ String const& member (emember (c));
+
+ if (fixed_length (c))
+ os << type << " " << member << ";"
+ << "bool " << epresent_member (c) << ";";
+ else
+ os << type << "* " << member << ";";
+ }
+ else
+ {
+ os << "union"
+ << "{";
+
+ Choice::contains (c);
+
+ os << "} " << emember (c) << ";"
+ << earm_tag (c) << " " << earm_member (c) << ";";
+ }
+ }
+ };
+
+ struct ChoiceInChoiceData: Traversal::Choice, Context
+ {
+ ChoiceInChoiceData (Context& c)
+ : Context (c), align_type_ (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ // For choice in choice we always have a nested class.
+ //
+ if (c.max () != 1)
+ {
+ os << "union"
+ << "{"
+ << "size_t align_;"
+ << "char data_[sizeof (" << esequence (c) << ")];"
+ << "} " << emember (c) << ";";
+ }
+ else
+ {
+ if (fixed_length (c))
+ {
+ os << "union"
+ << "{";
+
+ align_type_.dispatch (c);
+
+ os << " align_;"
+ << "char data_[sizeof (" << etype (c) << ")";
+
+ // Reserve an extra byte for the present flag.
+ //
+ if (c.min () == 0)
+ os << " + 1";
+
+ os << "];"
+ << "} " << emember (c) << ";";
+ }
+ else
+ os << etype (c) << "* " << emember (c) << ";";
+ }
+ }
+
+ private:
+ AlignType align_type_;
+ };
+
+ struct SequenceInSequenceData: Traversal::Sequence, Context
+ {
+ SequenceInSequenceData (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ if (s.max () != 1)
+ {
+ os << esequence (s) << " " << emember (s) << ";";
+ }
+ else if (s.min () == 0)
+ {
+ String const& type (etype (s));
+ String const& member (emember (s));
+
+ if (fixed_length (s))
+ os << type << " " << member << ";"
+ << "bool " << epresent_member (s) << ";";
+ else
+ os << type << "* " << member << ";";
+ }
+ else
+ Sequence::contains (s);
+ }
+ };
+
+ struct SequenceInChoiceData: Traversal::Sequence, Context
+ {
+ SequenceInChoiceData (Context& c)
+ : Context (c), align_type_ (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ // For sequence in choice we always have a nested class.
+ //
+ if (s.max () != 1)
+ {
+ os << "union"
+ << "{"
+ << "size_t align_;"
+ << "char data_[sizeof (" << esequence (s) << ")];"
+ << "} " << emember (s) << ";";
+ }
+ else
+ {
+ if (fixed_length (s))
+ {
+ os << "union"
+ << "{";
+
+ align_type_.dispatch (s);
+
+ os << " align_;"
+ << "char data_[sizeof (" << etype (s) << ")";
+
+ // Reserve an extra byte for the present flag.
+ //
+ if (s.min () == 0)
+ os << " + 1";
+
+ os << "];"
+ << "} " << emember (s) << ";";
+ }
+ else
+ os << etype (s) << "* " << emember (s) << ";";
+ }
+ }
+
+ private:
+ AlignType align_type_;
+ };
+
+ //
+ // Accessors/modifiers.
+ //
+
+ struct Attribute: Traversal::Attribute, Context
+ {
+ Attribute (Context& c)
+ : Context (c),
+ ro_ret_ (c, TypeName::ro_ret),
+ ret_ (c, TypeName::ret),
+ arg_ (c, TypeName::arg)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ os << "// " << comment (a.name ()) << endl
+ << "// " << endl;
+
+ String const& name (ename (a));
+ SemanticGraph::Type& t (a.type ());
+
+ if (a.optional ())
+ {
+ String const& present (epresent (a));
+
+ os << "bool" << endl
+ << present << " () const;"
+ << endl;
+
+ os << "void" << endl
+ << present << " (bool);"
+ << endl;
+ }
+
+ // const type&
+ // name () const
+ //
+ ro_ret_.dispatch (t);
+ os << endl
+ << name << " () const;"
+ << endl;
+
+ // type&
+ // name ()
+ //
+ ret_.dispatch (t);
+ os << endl
+ << name << " ();"
+ << endl;
+
+
+ // void
+ // name (const type& | type*)
+ //
+ os << "void" << endl
+ << name << " (";
+ arg_.dispatch (t);
+ os << ");"
+ << endl;
+ }
+
+ private:
+ TypeName ro_ret_;
+ TypeName ret_;
+ TypeName arg_;
+ };
+
+ struct Element: Traversal::Element, virtual Context
+ {
+ Element (Context& c)
+ : Context (c),
+ seq_ (c, TypeName::seq),
+ ro_ret_ (c, TypeName::ro_ret),
+ ret_ (c, TypeName::ret),
+ arg_ (c, TypeName::arg)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ os << "// " << comment (e.name ()) << endl
+ << "// " << endl;
+
+ String const& name (ename (e));
+ SemanticGraph::Type& t (e.type ());
+
+ if (e.max () != 1)
+ {
+ String const& sequence (esequence (e));
+ String const& iterator (eiterator (e));
+ String const& const_iterator (econst_iterator (e));
+
+ // sequence & iterators
+ //
+ os << "typedef ";
+ seq_.dispatch (t);
+ os << " " << 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;
+ }
+ else
+ {
+ if (e.min () == 0)
+ {
+ // optional
+ //
+ String const& present (epresent (e));
+
+ os << "bool" << endl
+ << present << " () const;"
+ << endl;
+
+ os << "void" << endl
+ << present << " (bool);"
+ << endl;
+ }
+
+ // const type&
+ // name () const
+ //
+ ro_ret_.dispatch (t);
+ os << endl
+ << name << " () const;"
+ << endl;
+
+ // type&
+ // name ()
+ //
+ ret_.dispatch (t);
+ os << endl
+ << name << " ();"
+ << endl;
+
+
+ // void
+ // name (const type& | type*)
+ //
+ os << "void" << endl
+ << name << " (";
+ arg_.dispatch (t);
+ os << ");"
+ << endl;
+ }
+ }
+
+ private:
+ TypeName seq_;
+ TypeName ro_ret_;
+ TypeName ret_;
+ TypeName arg_;
+ };
+
+ struct All: Traversal::All, Context
+ {
+ All (Context& c, Traversal::ContainsParticle& contains_data)
+ : Context (c), contains_data_ (contains_data)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ // For the all compositor, maxOccurs=1 and minOccurs={0,1}
+ // and it can only contain particles.
+ //
+ if (a.min () == 0)
+ {
+ Boolean fl (fixed_length (a));
+ Boolean cd (a.context ().count ("cd-name"));
+
+ String const& name (ename (a));
+ String const& type (etype (a));
+ String const& present (epresent (a));
+
+ os << "// " << comment (name) << " (" <<
+ (fl ? "fixed-length" : "variable-length") << ")" << endl
+ << "// " << endl;
+
+ os << "class " << type
+ << "{";
+
+ // c-tor & d-tor
+ //
+ os << "public:" << endl
+ << type << " ();"
+ << "~" << type << " ();";
+
+ // copy c-tor & operator=
+ //
+ if (!fl)
+ os << endl
+ << "private:" << endl;
+
+ os << type << " (const " << type << "&);"
+ << type << "& operator= (const " << type << "&);"
+ << endl;
+
+ if (!fl)
+ os << "public:" << endl;
+
+ All::contains (a);
+
+ // Custom data.
+ //
+ if (cd)
+ {
+ String const& name (ecd_name (a));
+ String const& sequence (ecd_sequence (a));
+ String const& iterator (ecd_iterator (a));
+ String const& const_iterator (ecd_const_iterator (a));
+
+ os << "// Custom data." << endl
+ << "//" << endl;
+
+ // sequence & iterators
+ //
+ os << "typedef ::xsde::cxx::hybrid::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;
+ }
+
+ os << "private:" << endl;
+
+ All::contains (a, contains_data_);
+
+ // Custom data.
+ //
+ if (cd)
+ os << ecd_sequence (a) << " " << ecd_member (a) << ";";
+
+ os << "};";
+
+ // name_present
+ //
+ os << "bool" << endl
+ << present << " () const;"
+ << endl;
+
+ os << "void" << endl
+ << present << " (bool);"
+ << endl;
+
+ // const type&
+ // name () const
+ //
+ os << "const " << type << "&" << endl
+ << name << " () const;"
+ << endl;
+
+ // type&
+ // name ()
+ //
+ os << type << "&" << endl
+ << name << " ();"
+ << endl;
+
+ // void
+ // name (const type& | type*)
+ //
+ os << "void" << endl
+ << name << " (";
+
+ if (fl)
+ os << "const " << type << "&";
+ else
+ os << type << "*";
+
+ os << ");"
+ << endl;
+ }
+ else
+ All::contains (a);
+ }
+
+ private:
+ Traversal::ContainsParticle& contains_data_;
+ };
+
+ struct ParticleTag: Traversal::Element,
+ Traversal::Any,
+ Traversal::Choice,
+ Traversal::Sequence,
+ Context
+ {
+ ParticleTag (Context& c)
+ : Context (c), first_ (true)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ emit_tag (etag (e));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ emit_tag (etag (a));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ emit_tag (etag (c));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ emit_tag (etag (s));
+ }
+
+ virtual Void
+ emit_tag (String const& tag)
+ {
+ if (first_)
+ first_ = false;
+ else
+ os << "," << endl;
+
+ os << tag;
+ }
+
+ private:
+ Boolean first_;
+ };
+
+ struct ChoiceInSequence: Traversal::Choice, Context
+ {
+ ChoiceInSequence (Context& c,
+ Traversal::ContainsParticle& contains_data)
+ : Context (c), contains_data_ (contains_data)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ UnsignedLong min (c.min ()), max (c.max ());
+
+ String const& name (ename (c));
+
+ Boolean fl;
+ String type;
+
+ if (max != 1 || min == 0)
+ {
+ type = etype (c);
+
+ fl = fixed_length (c);
+
+ os << "// " << comment (name) << " (" <<
+ (fl ? "fixed-length" : "variable-length") << ")" << endl
+ << "// " << endl;
+
+ os << "class " << type
+ << "{";
+
+ // c-tor & d-tor
+ //
+ os << "public:" << endl
+ << type << " ();"
+ << "~" << type << " ();";
+
+ // copy c-tor & operator=
+ //
+ if (!fl)
+ os << endl
+ << "private:" << endl;
+
+ os << type << " (const " << type << "&);"
+ << type << "& operator= (const " << type << "&);"
+ << endl;
+
+ if (!fl)
+ os << "public:" << endl;
+ }
+ else
+ {
+ os << "// " << comment (name) << endl
+ << "// " << endl;
+ }
+
+ String const& arm_tag (earm_tag (c));
+ String const& arm (earm (c));
+
+ os << "enum " << arm_tag
+ << "{";
+
+ {
+ ParticleTag particle (*this);
+ Traversal::ContainsParticle contains_particle (particle);
+ Traversal::Choice::contains (c, contains_particle);
+ }
+
+ os << "};";
+
+ // arm_tag
+ // arm () const;
+ //
+ os << arm_tag << endl
+ << arm << " () const;"
+ << endl;
+
+ // void
+ // arm (arm_tag);
+ //
+ os << "void" << endl
+ << arm << " (" << arm_tag << ");"
+ << endl;
+
+ Choice::contains (c);
+
+ if (max != 1 || min == 0)
+ {
+ Boolean cd (c.context ().count ("cd-name"));
+
+ // Custom data.
+ //
+ if (cd)
+ {
+ String const& name (ecd_name (c));
+ String const& sequence (ecd_sequence (c));
+ String const& iterator (ecd_iterator (c));
+ String const& const_iterator (ecd_const_iterator (c));
+
+ os << "// Custom data." << endl
+ << "//" << endl;
+
+ // sequence & iterators
+ //
+ os << "typedef ::xsde::cxx::hybrid::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;
+ }
+
+ os << "private:" << endl
+ << "union"
+ << "{";
+
+ Choice::contains (c, contains_data_);
+
+ os << "} " << emember (c) << ";"
+ << arm_tag << " " << earm_member (c) << ";";
+
+ // Custom data.
+ //
+ if (cd)
+ os << ecd_sequence (c) << " " << ecd_member (c) << ";";
+
+ os << "};";
+ }
+
+ if (max != 1)
+ {
+ String const& sequence (esequence (c));
+ String const& iterator (eiterator (c));
+ String const& const_iterator (econst_iterator (c));
+
+ // sequence & iterators
+ //
+ os << "typedef ::xsde::cxx::hybrid::";
+
+ if (fl)
+ os << "fix_seq";
+ else
+ os << "var_seq";
+
+ os << "< " << type << " > " << 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;
+
+ }
+ else if (min == 0)
+ {
+ String const& present (epresent (c));
+
+ // name_present
+ //
+ os << "bool" << endl
+ << present << " () const;"
+ << endl;
+
+ os << "void" << endl
+ << present << " (bool);"
+ << endl;
+
+ // const type&
+ // name () const
+ //
+ os << "const " << type << "&" << endl
+ << name << " () const;"
+ << endl;
+
+ // type&
+ // name ()
+ //
+ os << type << "&" << endl
+ << name << " ();"
+ << endl;
+
+ // void
+ // name (const type& | type*)
+ //
+ os << "void" << endl
+ << name << " (";
+
+ if (fl)
+ os << "const " << type << "&";
+ else
+ os << type << "*";
+
+ os << ");"
+ << endl;
+ }
+ }
+
+ private:
+ Traversal::ContainsParticle& contains_data_;
+ };
+
+ struct ChoiceInChoice: Traversal::Choice, Context
+ {
+ ChoiceInChoice (Context& c,
+ Traversal::ContainsParticle& contains_data)
+ : Context (c), contains_data_ (contains_data)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ // When shoice is in choice we generate nested class even
+ // for min == max == 1.
+ //
+ UnsignedLong min (c.min ()), max (c.max ());
+
+ Boolean fl (fixed_length (c));
+ Boolean cd (c.context ().count ("cd-name"));
+
+ String const& name (ename (c));
+ String const& type (etype (c));
+
+ os << "// " << comment (name) << " (" <<
+ (fl ? "fixed-length" : "variable-length") << ")" << endl
+ << "// " << endl;
+
+ os << "class " << type
+ << "{";
+
+ // c-tor & d-tor
+ //
+ os << "public:" << endl
+ << type << " ();"
+ << "~" << type << " ();";
+
+ // copy c-tor & operator=
+ //
+ if (!fl)
+ os << endl
+ << "private:" << endl;
+
+ os << type << " (const " << type << "&);"
+ << type << "& operator= (const " << type << "&);"
+ << endl;
+
+ if (!fl)
+ os << "public:" << endl;
+
+ String const& arm_tag (earm_tag (c));
+ String const& arm (earm (c));
+
+ os << "enum " << arm_tag
+ << "{";
+
+ {
+ ParticleTag particle (*this);
+ Traversal::ContainsParticle contains_particle (particle);
+ Traversal::Choice::contains (c, contains_particle);
+ }
+
+ os << "};";
+
+ // arm_tag
+ // arm () const;
+ //
+ os << arm_tag << endl
+ << arm << " () const;"
+ << endl;
+
+ // void
+ // arm (arm_tag);
+ //
+ os << "void" << endl
+ << arm << " (" << arm_tag << ");"
+ << endl;
+
+ Choice::contains (c);
+
+ // Custom data.
+ //
+ if (cd)
+ {
+ String const& name (ecd_name (c));
+ String const& sequence (ecd_sequence (c));
+ String const& iterator (ecd_iterator (c));
+ String const& const_iterator (ecd_const_iterator (c));
+
+ os << "// Custom data." << endl
+ << "//" << endl;
+
+ // sequence & iterators
+ //
+ os << "typedef ::xsde::cxx::hybrid::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;
+ }
+
+ os << "private:" << endl
+ << "union"
+ << "{";
+
+ Choice::contains (c, contains_data_);
+
+ os << "} " << emember (c) << ";"
+ << arm_tag << " " << earm_member (c) << ";";
+
+ // Custom data.
+ //
+ if (cd)
+ os << ecd_sequence (c) << " " << ecd_member (c) << ";";
+
+ os << "};";
+
+ if (max != 1)
+ {
+ String const& sequence (esequence (c));
+ String const& iterator (eiterator (c));
+ String const& const_iterator (econst_iterator (c));
+
+ // sequence & iterators
+ //
+ os << "typedef ::xsde::cxx::hybrid::";
+
+ if (fl)
+ os << "fix_seq";
+ else
+ os << "var_seq";
+
+ os << "< " << type << " > " << 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;
+ }
+ else
+ {
+ if (min == 0)
+ {
+ String const& present (epresent (c));
+
+ // name_present
+ //
+ os << "bool" << endl
+ << present << " () const;"
+ << endl;
+
+ os << "void" << endl
+ << present << " (bool);"
+ << endl;
+ }
+
+ // const type&
+ // name () const
+ //
+ os << "const " << type << "&" << endl
+ << name << " () const;"
+ << endl;
+
+ // type&
+ // name ()
+ //
+ os << type << "&" << endl
+ << name << " ();"
+ << endl;
+
+ // void
+ // name (const type& | type*)
+ //
+ os << "void" << endl
+ << name << " (";
+
+ if (fl)
+ os << "const " << type << "&";
+ else
+ os << type << "*";
+
+ os << ");"
+ << endl;
+ }
+ }
+
+ private:
+ Traversal::ContainsParticle& contains_data_;
+ };
+
+
+ struct SequenceInSequence: Traversal::Sequence, Context
+ {
+ SequenceInSequence (Context& c,
+ Traversal::ContainsParticle& contains_data)
+ : Context (c), contains_data_ (contains_data)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ UnsignedLong min (s.min ()), max (s.max ());
+
+ if (max == 1 && min == 1)
+ {
+ Sequence::contains (s);
+ return;
+ }
+
+ Boolean fl (fixed_length (s));
+ Boolean cd (s.context ().count ("cd-name"));
+
+ String const& name (ename (s));
+ String const& type (etype (s));
+
+ os << "// " << comment (name) << " (" <<
+ (fl ? "fixed-length" : "variable-length") << ")" << endl
+ << "// " << endl;
+
+ os << "class " << type
+ << "{";
+
+ // c-tor & d-tor
+ //
+ os << "public:" << endl
+ << type << " ();"
+ << "~" << type << " ();";
+
+ // copy c-tor & operator=
+ //
+ if (!fl)
+ os << endl
+ << "private:" << endl;
+
+ os << type << " (const " << type << "&);"
+ << type << "& operator= (const " << type << "&);"
+ << endl;
+
+ if (!fl)
+ os << "public:" << endl;
+
+ Sequence::contains (s);
+
+ // Custom data.
+ //
+ if (cd)
+ {
+ String const& name (ecd_name (s));
+ String const& sequence (ecd_sequence (s));
+ String const& iterator (ecd_iterator (s));
+ String const& const_iterator (ecd_const_iterator (s));
+
+ os << "// Custom data." << endl
+ << "//" << endl;
+
+ // sequence & iterators
+ //
+ os << "typedef ::xsde::cxx::hybrid::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;
+ }
+
+ os << "private:" << endl;
+
+ Sequence::contains (s, contains_data_);
+
+ // Custom data.
+ //
+ if (cd)
+ os << ecd_sequence (s) << " " << ecd_member (s) << ";";
+
+ os << "};";
+
+ if (max != 1)
+ {
+ String const& sequence (esequence (s));
+ String const& iterator (eiterator (s));
+ String const& const_iterator (econst_iterator (s));
+
+ // sequence & iterators
+ //
+ os << "typedef ::xsde::cxx::hybrid::";
+
+ if (fl)
+ os << "fix_seq";
+ else
+ os << "var_seq";
+
+ os << "< " << type << " > " << 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;
+
+ }
+ else if (min == 0)
+ {
+ String const& present (epresent (s));
+
+ // name_present
+ //
+ os << "bool" << endl
+ << present << " () const;"
+ << endl;
+
+ os << "void" << endl
+ << present << " (bool);"
+ << endl;
+
+ // const type&
+ // name () const
+ //
+ os << "const " << type << "&" << endl
+ << name << " () const;"
+ << endl;
+
+ // type&
+ // name ()
+ //
+ os << type << "&" << endl
+ << name << " ();"
+ << endl;
+
+ // void
+ // name (const type& | type*)
+ //
+ os << "void" << endl
+ << name << " (";
+
+ if (fl)
+ os << "const " << type << "&";
+ else
+ os << type << "*";
+
+ os << ");"
+ << endl;
+ }
+ }
+
+ private:
+ Traversal::ContainsParticle& contains_data_;
+ };
+
+ struct SequenceInChoice: Traversal::Sequence, Context
+ {
+ SequenceInChoice (Context& c,
+ Traversal::ContainsParticle& contains_data)
+ : Context (c), contains_data_ (contains_data)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ // When sequence is in choice we generate nested class even
+ // for min == max == 1.
+ //
+ Boolean fl (fixed_length (s));
+ Boolean cd (s.context ().count ("cd-name"));
+
+ String const& name (ename (s));
+ String const& type (etype (s));
+
+ os << "// " << comment (name) << " (" <<
+ (fl ? "fixed-length" : "variable-length") << ")" << endl
+ << "// " << endl;
+
+ os << "class " << type
+ << "{";
+
+ // c-tor & d-tor
+ //
+ os << "public:" << endl
+ << type << " ();"
+ << "~" << type << " ();";
+
+ // copy c-tor & operator=
+ //
+ if (!fl)
+ os << endl
+ << "private:" << endl;
+
+ os << type << " (const " << type << "&);"
+ << type << "& operator= (const " << type << "&);"
+ << endl;
+
+ if (!fl)
+ os << "public:" << endl;
+
+ Sequence::contains (s);
+
+ if (cd)
+ {
+ String const& name (ecd_name (s));
+ String const& sequence (ecd_sequence (s));
+ String const& iterator (ecd_iterator (s));
+ String const& const_iterator (ecd_const_iterator (s));
+
+ os << "// Custom data." << endl
+ << "//" << endl;
+
+ // sequence & iterators
+ //
+ os << "typedef ::xsde::cxx::hybrid::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;
+ }
+
+ os << "private:" << endl;
+
+ Sequence::contains (s, contains_data_);
+
+ // Custom data.
+ //
+ if (cd)
+ os << ecd_sequence (s) << " " << ecd_member (s) << ";";
+
+ os << "};";
+
+ if (s.max () != 1)
+ {
+ String const& sequence (esequence (s));
+ String const& iterator (eiterator (s));
+ String const& const_iterator (econst_iterator (s));
+
+ // sequence & iterators
+ //
+ os << "typedef ::xsde::cxx::hybrid::";
+
+ if (fl)
+ os << "fix_seq";
+ else
+ os << "var_seq";
+
+ os << "< " << type << " > " << 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;
+
+ }
+ else
+ {
+ if (s.min () == 0)
+ {
+ String const& present (epresent (s));
+
+ // name_present
+ //
+ os << "bool" << endl
+ << present << " () const;"
+ << endl;
+
+ os << "void" << endl
+ << present << " (bool);"
+ << endl;
+ }
+
+ // const type&
+ // name () const
+ //
+ os << "const " << type << "&" << endl
+ << name << " () const;"
+ << endl;
+
+ // type&
+ // name ()
+ //
+ os << type << "&" << endl
+ << name << " ();"
+ << endl;
+
+ // void
+ // name (const type& | type*)
+ //
+ os << "void" << endl
+ << name << " (";
+
+ if (fl)
+ os << "const " << type << "&";
+ else
+ os << type << "*";
+
+ os << ");"
+ << endl;
+ }
+ }
+
+ private:
+ Traversal::ContainsParticle& contains_data_;
+ };
+
+ struct Complex : Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c),
+ base_name_ (c, TypeName::base),
+
+ // Data.
+ //
+ attribute_data_ (c),
+ element_data_ (c),
+ element_in_choice_data_ (c),
+ all_data_ (c),
+ choice_in_choice_data_ (c),
+ choice_in_sequence_data_ (c),
+ sequence_in_choice_data_ (c),
+ sequence_in_sequence_data_ (c),
+
+ // Functions and nested classes.
+ //
+ attribute_ (c),
+ element_ (c),
+ all_ (c, all_contains_data_),
+ choice_in_choice_ (c, choice_contains_data_),
+ choice_in_sequence_ (c, choice_contains_data_),
+ sequence_in_choice_ (c, sequence_contains_data_),
+ sequence_in_sequence_ (c, sequence_contains_data_)
+ {
+ // Data
+ //
+ attribute_names_data_ >> attribute_data_;
+
+ all_data_ >> all_contains_data_ >> element_data_;
+
+ sequence_in_choice_data_ >> sequence_contains_data_;
+ sequence_in_sequence_data_ >> sequence_contains_data_;
+ sequence_contains_data_ >> element_data_;
+ sequence_contains_data_ >> choice_in_sequence_data_;
+ sequence_contains_data_ >> sequence_in_sequence_data_;
+
+ choice_in_choice_data_ >> choice_contains_data_;
+ choice_in_sequence_data_ >> choice_contains_data_;
+ choice_contains_data_ >> element_in_choice_data_;
+ choice_contains_data_ >> choice_in_choice_data_;
+ choice_contains_data_ >> sequence_in_choice_data_;
+
+ contains_compositor_data_ >> all_data_;
+ contains_compositor_data_ >> choice_in_sequence_data_;
+ contains_compositor_data_ >> sequence_in_sequence_data_;
+
+ // Functions and nested classes.
+ //
+ attribute_names_ >> attribute_;
+
+ all_ >> all_contains_ >> element_;
+
+ choice_in_choice_ >> choice_contains_;
+ choice_in_sequence_ >> choice_contains_;
+ choice_contains_ >> element_;
+ choice_contains_ >> choice_in_choice_;
+ choice_contains_ >> sequence_in_choice_;
+
+ sequence_in_choice_ >> sequence_contains_;
+ sequence_in_sequence_ >> sequence_contains_;
+ sequence_contains_ >> element_;
+ sequence_contains_ >> choice_in_sequence_;
+ sequence_contains_ >> sequence_in_sequence_;
+
+ contains_compositor_ >> all_;
+ contains_compositor_ >> choice_in_sequence_;
+ contains_compositor_ >> sequence_in_sequence_;
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ String name (ename (c));
+ Boolean fl (fixed_length (c));
+ Boolean restriction (restriction_p (c));
+ Boolean cd (c.context ().count ("cd-name"));
+
+ os << "// " << comment (c.name ()) << " (" <<
+ (fl ? "fixed-length" : "variable-length") << ")" << endl
+ << "//" << endl;
+
+ os << "class " << name;
+
+ if (c.inherits_p ())
+ {
+ os << ": public ";
+ base_name_.dispatch (c.inherits ().base ());
+ }
+
+ os << "{";
+
+ // c-tor
+ //
+ os << "public:" << endl
+ << name << " ();";
+
+ // d-tor
+ //
+ if (!restriction)
+ os << "~" << name << " ();";
+
+ // copy c-tor & operator=
+ //
+ if (!fl)
+ os << endl
+ << "private:" << endl;
+
+ if (!fl || !restriction)
+ os << name << " (const " << name << "&);"
+ << name << "& operator= (const " << name << "&);"
+ << endl;
+
+ if ((!restriction && !fl) || cd)
+ os << "public:" << endl;
+
+ if (!restriction)
+ {
+ Complex::names (c, attribute_names_);
+
+ if (c.contains_compositor_p ())
+ Complex::contains_compositor (c, contains_compositor_);
+ }
+
+ // Custom data.
+ //
+ if (cd)
+ {
+ String const& name (ecd_name (c));
+ String const& sequence (ecd_sequence (c));
+ String const& iterator (ecd_iterator (c));
+ String const& const_iterator (ecd_const_iterator (c));
+
+ os << "// Custom data." << endl
+ << "//" << endl;
+
+ // sequence & iterators
+ //
+ os << "typedef ::xsde::cxx::hybrid::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 (!restriction || cd)
+ os << "private:" << endl;
+
+ if (!restriction)
+ {
+ Complex::names (c, attribute_names_data_);
+
+ if (c.contains_compositor_p ())
+ Complex::contains_compositor (c, contains_compositor_data_);
+ }
+
+ // Custom data.
+ //
+ if (cd)
+ os << ecd_sequence (c) << " " << ecd_member (c) << ";";
+
+ os << "};";
+ }
+
+ private:
+ TypeName base_name_;
+
+ // Data.
+ //
+ AttributeData attribute_data_;
+ Traversal::Names attribute_names_data_;
+
+ ElementData element_data_;
+ ElementInChoiceData element_in_choice_data_;
+ AllData all_data_;
+ ChoiceInChoiceData choice_in_choice_data_;
+ ChoiceInSequenceData choice_in_sequence_data_;
+ SequenceInChoiceData sequence_in_choice_data_;
+ SequenceInSequenceData sequence_in_sequence_data_;
+ Traversal::ContainsParticle all_contains_data_;
+ Traversal::ContainsParticle choice_contains_data_;
+ Traversal::ContainsParticle sequence_contains_data_;
+
+ Traversal::ContainsCompositor contains_compositor_data_;
+
+ // Functions and nested classes.
+ //
+ Attribute attribute_;
+ Traversal::Names attribute_names_;
+
+ Element element_;
+ All all_;
+ ChoiceInChoice choice_in_choice_;
+ ChoiceInSequence choice_in_sequence_;
+ SequenceInChoice sequence_in_choice_;
+ SequenceInSequence sequence_in_sequence_;
+ Traversal::ContainsParticle all_contains_;
+ Traversal::ContainsParticle choice_contains_;
+ Traversal::ContainsParticle sequence_contains_;
+
+ Traversal::ContainsCompositor contains_compositor_;
+ };
+ }
+
+ Void
+ generate_tree_header (Context& ctx)
+ {
+ ctx.os << "#include <xsde/cxx/hybrid/sequence.hxx>" << endl
+ << endl;
+
+ Boolean inline_ (ctx.options.value<CLI::generate_inline> ());
+
+ // Emit header includes.
+ //
+ {
+ if (inline_)
+ {
+ ctx.os << "#ifndef XSDE_DONT_INCLUDE_INLINE" << endl
+ << "#define XSDE_DONT_INCLUDE_INLINE" << endl
+ << endl;
+ }
+
+ Traversal::Schema schema;
+ Includes includes (ctx, Includes::header);
+
+ schema >> includes;
+
+ schema.dispatch (ctx.schema_root);
+
+ if (inline_)
+ {
+ ctx.os << "#undef XSDE_DONT_INCLUDE_INLINE" << endl
+ << "#else" << endl
+ << endl;
+
+ schema.dispatch (ctx.schema_root);
+
+ ctx.os << "#endif // XSDE_DONT_INCLUDE_INLINE" << endl
+ << endl;
+ }
+ }
+
+ {
+ Traversal::Schema schema;
+
+ Traversal::Sources sources;
+ Traversal::Names names_ns, names;
+
+ Namespace ns (ctx);
+
+ List list (ctx);
+ Union union_ (ctx);
+ Complex complex (ctx);
+ //Enumeration enumeration (ctx);
+
+ schema >> sources >> schema;
+ schema >> names_ns >> ns >> names;
+
+ names >> list;
+ names >> union_;
+ names >> complex;
+ //names >> enumeration;
+
+ schema.dispatch (ctx.schema_root);
+ }
+
+ // Emit inline includes.
+ //
+ if (inline_)
+ {
+ ctx.os << "#ifndef XSDE_DONT_INCLUDE_INLINE" << endl
+ << endl;
+
+ Traversal::Schema schema;
+ Includes ixx_includes (ctx, Includes::inline_);
+ schema >> ixx_includes;
+
+ schema.dispatch (ctx.schema_root);
+
+ ctx.os << "#endif // XSDE_DONT_INCLUDE_INLINE" << endl
+ << endl;
+ }
+ }
+ }
+}
diff --git a/xsde/cxx/hybrid/tree-header.hxx b/xsde/cxx/hybrid/tree-header.hxx
new file mode 100644
index 0000000..2ef9573
--- /dev/null
+++ b/xsde/cxx/hybrid/tree-header.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/hybrid/tree-header.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_TREE_HEADER_HXX
+#define CXX_HYBRID_TREE_HEADER_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/hybrid/elements.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ Void
+ generate_tree_header (Context&);
+ }
+}
+
+#endif // CXX_HYBRID_TREE_HEADER_HXX
diff --git a/xsde/cxx/hybrid/tree-inline.cxx b/xsde/cxx/hybrid/tree-inline.cxx
new file mode 100644
index 0000000..72d2d8f
--- /dev/null
+++ b/xsde/cxx/hybrid/tree-inline.cxx
@@ -0,0 +1,1817 @@
+// file : xsd/cxx/hybrid/tree-inline.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/hybrid/tree-inline.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ namespace
+ {
+ struct List : Traversal::List, Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String name (ename (l));
+
+ os << "// " << comment (l.name ()) << endl
+ << "//" << endl
+ << endl;
+
+ // c-tor
+ //
+ os << inl
+ << name << "::" << endl
+ << name << " ()"
+ << "{"
+ << "}";
+
+ // Custom data.
+ //
+ if (l.context ().count ("cd-name"))
+ {
+ String const& cd_name (ecd_name (l));
+ String const& member (ecd_member (l));
+ String const& sequence (ecd_sequence (l));
+
+ // 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 << ";"
+ << "}";
+ }
+ }
+ };
+
+ //
+ //
+ struct Union : Traversal::Union, Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ String name (ename (u));
+
+ os << "// " << comment (u.name ()) << endl
+ << "//" << endl
+ << endl;
+
+ SemanticGraph::Context& uc (u.context ());
+ String const& value (uc.get<String> ("value"));
+ String const& member (uc.get<String> ("value-member"));
+
+ // c-tor
+ //
+ os << inl
+ << name << "::" << endl
+ << name << " ()"
+ << "{";
+
+ if (!stl)
+ os << "this->" << member << " = 0;";
+
+ os << "}";
+
+ if (stl)
+ {
+ // const std::string&
+ // name () const
+ //
+ os << inl
+ << "const ::std::string& " << name << "::" << endl
+ << value << " () const"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+
+ // std::string&
+ // name ()
+ //
+ os << inl
+ << "::std::string& " << name << "::" << endl
+ << value << " ()"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+
+ // void
+ // name (const std::string&)
+ //
+ os << inl
+ << "void " << name << "::" << endl
+ << value << " (const ::std::string& x)"
+ << "{"
+ << "this->" << member << " = x;"
+ << "}";
+ }
+ else
+ {
+ // d-tor
+ //
+ os << inl
+ << name << "::" << endl
+ << "~" << name << " ()"
+ << "{"
+ << "delete[] this->" << member << ";"
+ << "}";
+
+ // const char*
+ // name () const
+ //
+ os << inl
+ << "const char* " << name << "::" << endl
+ << value << " () const"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+
+ // char*
+ // name ()
+ //
+ os << inl
+ << "char* " << name << "::" << endl
+ << value << " ()"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+
+ // void
+ // name (char*)
+ //
+ os << inl
+ << "void " << name << "::" << endl
+ << value << " (char* x)"
+ << "{"
+ << "delete[] this->" << member << ";"
+ << "this->" << member << " = x;"
+ << "}";
+ }
+
+ // Custom data.
+ //
+ if (uc.count ("cd-name"))
+ {
+ String const& cd_name (ecd_name (u));
+ String const& member (ecd_member (u));
+ String const& sequence (ecd_sequence (u));
+
+ // 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 << ";"
+ << "}";
+ }
+ }
+ };
+
+ //
+ //
+ struct AttributeFunc: Traversal::Attribute, Context
+ {
+ AttributeFunc (Context& c)
+ : Context (c),
+ ro_ret_ (c, TypeName::ro_ret),
+ ret_ (c, TypeName::ret),
+ arg_ (c, TypeName::arg),
+ deref_ (c, TypeOps::deref),
+ delete_ (c, TypeOps::delete_)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ String const& name (ename (a));
+ String const& member (emember (a));
+
+ SemanticGraph::Type& t (a.type ());
+ Boolean fl (fixed_length (t));
+ String scope (Context::scope (a));
+
+ if (a.optional ())
+ {
+ String const& present (epresent (a));
+
+ // bool
+ // preset () const;
+ //
+ os << inl
+ << "bool " << scope << "::" << endl
+ << present << " () const"
+ << "{";
+
+ if (fl)
+ os << "return this->" << epresent_member (a) << ";";
+ else
+ os << "return this->" << member << " != 0;";
+
+ os << "}";
+
+ // void
+ // preset (bool);
+ //
+ os << inl
+ << "void " << scope << "::" << endl
+ << present << " (bool x)"
+ << "{";
+
+ if (fl)
+ os << "this->" << epresent_member (a) << " = x;";
+ else
+ {
+ os << "if (!x)"
+ << "{";
+ delete_.dispatch (t);
+ os << " this->" << member << ";"
+ << "this->" << member << " = 0;"
+ << "}";
+ }
+
+ os << "}";
+ }
+
+ // const type&
+ // name () const
+ //
+ os << inl;
+ ro_ret_.dispatch (t);
+ os << " " << scope << "::" << endl
+ << name << " () const"
+ << "{"
+ << "return ";
+ deref_.dispatch (t);
+ os << "this->" << member << ";"
+ << "}";
+
+ // type&
+ // name ()
+ //
+ os << inl;
+ ret_.dispatch (t);
+ os << " " << scope << "::" << endl
+ << name << " ()"
+ << "{"
+ << "return ";
+ deref_.dispatch (t);
+ os << "this->" << member << ";"
+ << "}";
+
+
+ // void
+ // name (const type& | type*)
+ //
+ os << inl
+ << "void " << scope << "::" << endl
+ << name << " (";
+ arg_.dispatch (t);
+ os << " x)"
+ << "{";
+
+ if (!fl)
+ {
+ delete_.dispatch (t);
+ os << " this->" << member << ";";
+ }
+
+ os << "this->" << member << " = x;";
+
+ if (fl && a.optional ())
+ os << "this->" << epresent_member (a) << " = true;";
+
+ os << "}";
+ }
+
+ private:
+ TypeName ro_ret_;
+ TypeName ret_;
+ TypeName arg_;
+ TypeOps deref_;
+ TypeOps delete_;
+ };
+
+ struct ElementFunc: Traversal::Element, Context
+ {
+ ElementFunc (Context& c)
+ : Context (c),
+ ro_ret_ (c, TypeName::ro_ret),
+ ret_ (c, TypeName::ret),
+ arg_ (c, TypeName::arg),
+ deref_ (c, TypeOps::deref),
+ delete_ (c, TypeOps::delete_)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ String const& name (ename (e));
+ String const& member (emember (e));
+
+ SemanticGraph::Type& t (e.type ());
+ Boolean fl (fixed_length (t));
+ String scope (Context::scope (e));
+
+ if (e.max () != 1)
+ {
+ String const& sequence (esequence (e));
+
+ // const seq&
+ // name () const
+ //
+ os << inl
+ << "const " << scope << "::" << sequence << "& " <<
+ scope << "::" << endl
+ << name << " () const"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+
+ // seq&
+ // name ()
+ //
+ os << inl
+ << scope << "::" << sequence << "& " << scope << "::" << endl
+ << name << " ()"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+ }
+ else
+ {
+ if (e.min () == 0)
+ {
+ String const& present (epresent (e));
+
+ // bool
+ // preset () const;
+ //
+ os << inl
+ << "bool " << scope << "::" << endl
+ << present << " () const"
+ << "{";
+
+ if (fl)
+ os << "return this->" << epresent_member (e) << ";";
+ else
+ os << "return this->" << member << " != 0;";
+
+ os << "}";
+
+ // void
+ // preset (bool);
+ //
+ os << inl
+ << "void " << scope << "::" << endl
+ << present << " (bool x)"
+ << "{";
+
+ if (fl)
+ os << "this->" << epresent_member (e) << " = x;";
+ else
+ {
+ os << "if (!x)"
+ << "{";
+ delete_.dispatch (t);
+ os << " this->" << member << ";"
+ << "this->" << member << " = 0;"
+ << "}";
+ }
+
+ os << "}";
+ }
+
+ // const type&
+ // name () const
+ //
+ os << inl;
+ ro_ret_.dispatch (t);
+ os << " " << scope << "::" << endl
+ << name << " () const"
+ << "{"
+ << "return ";
+ deref_.dispatch (t);
+ os << "this->" << member << ";"
+ << "}";
+
+ // type&
+ // name ()
+ //
+ os << inl;
+ ret_.dispatch (t);
+ os << " " << scope << "::" << endl
+ << name << " ()"
+ << "{"
+ << "return ";
+ deref_.dispatch (t);
+ os << "this->" << member << ";"
+ << "}";
+
+ // void
+ // name (const type& | type*)
+ //
+ os << inl
+ << "void " << scope << "::" << endl
+ << name << " (";
+ arg_.dispatch (t);
+ os << " x)"
+ << "{";
+
+ if (!fl)
+ {
+ delete_.dispatch (t);
+ os << " this->" << member << ";";
+ }
+
+ os << "this->" << member << " = x;";
+
+ if (fl && e.min () == 0)
+ os << "this->" << epresent_member (e) << " = true;";
+
+ os << "}";
+ }
+ }
+
+ private:
+ TypeName ro_ret_;
+ TypeName ret_;
+ TypeName arg_;
+ TypeOps deref_;
+ TypeOps delete_;
+ };
+
+ struct ElementInChoiceFunc: Traversal::Element, Context
+ {
+ ElementInChoiceFunc (Context& c)
+ : Context (c),
+ ro_ret_ (c, TypeName::ro_ret),
+ ret_ (c, TypeName::ret),
+ arg_ (c, TypeName::arg),
+ var_ (c, TypeName::var),
+ deref_ (c, TypeOps::deref),
+ delete_ (c, TypeOps::delete_)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ String const& name (ename (e));
+ String const& member (emember (e));
+
+ SemanticGraph::Choice& c (
+ dynamic_cast<SemanticGraph::Choice&> (
+ e.contained_particle ().compositor ()));
+
+ String const& arm (earm (c));
+ String const& umember (emember (c));
+
+ String scope (Context::scope (e));
+
+ if (e.max () != 1)
+ {
+ String const& sequence (esequence (e));
+
+ // const seq&
+ // name () const
+ //
+ os << inl
+ << "const " << scope << "::" << sequence << "& " <<
+ scope << "::" << endl
+ << name << " () const"
+ << "{"
+ << "return reinterpret_cast< const " << sequence << "& > (" <<
+ "this->" << umember << "." << member << ");"
+ << "}";
+
+ // seq&
+ // name ()
+ //
+ os << inl
+ << scope << "::" << sequence << "& " << scope << "::" << endl
+ << name << " ()"
+ << "{"
+ << "return reinterpret_cast< " << sequence << "& > (" <<
+ "this->" << umember << "." << member << ");"
+ << "}";
+ }
+ else
+ {
+ UnsignedLong min (e.min ());
+
+ SemanticGraph::Type& t (e.type ());
+ Boolean fl (fixed_length (t));
+
+ String const& tag (etag (e));
+ String const& arm_member (earm_member (c));
+
+ if (min == 0)
+ {
+ String const& present (epresent (e));
+
+ // bool
+ // preset () const;
+ //
+ os << inl
+ << "bool " << scope << "::" << endl
+ << present << " () const"
+ << "{";
+
+ if (fl)
+ {
+ os << "return this->" << umember << "." << member <<
+ ".data_[sizeof (";
+ var_.dispatch (t);
+ os << ")];";
+ }
+ else
+ os << "return this->" << umember << "." << member << " != 0;";
+
+ os << "}";
+
+ // void
+ // preset (bool);
+ //
+ os << inl
+ << "void " << scope << "::" << endl
+ << present << " (bool x)"
+ << "{"
+ << "if (this->" << arm_member << " != " << tag << ")" << endl
+ << "this->" << arm << " (" << tag << ");";
+
+ if (fl)
+ {
+ os << endl
+ << "this->" << umember << "." << member <<
+ ".data_[sizeof (";
+ var_.dispatch (t);
+ os << ")] = x;";
+ }
+ else
+ {
+ os << "else if (!x)"
+ << "{";
+ delete_.dispatch (t);
+ os << " this->" << umember << "." << member << ";"
+ << "this->" << umember << "." << member << " = 0;"
+ << "}";
+ }
+
+ os << "}";
+ }
+
+ // const type&
+ // name () const
+ //
+ os << inl;
+ ro_ret_.dispatch (t);
+ os << " " << scope << "::" << endl
+ << name << " () const"
+ << "{"
+ << "return ";
+
+ if (fl)
+ {
+ os << "reinterpret_cast< const ";
+ var_.dispatch (t);
+ os << "& > (this->" << umember << "." << member << ");";
+ }
+ else
+ {
+ deref_.dispatch (t);
+ os << "this->" << umember << "." << member << ";";
+ }
+
+ os << "}";
+
+ // type&
+ // name ()
+ //
+ os << inl;
+ ret_.dispatch (t);
+ os << " " << scope << "::" << endl
+ << name << " ()"
+ << "{"
+ << "return ";
+
+ if (fl)
+ {
+ os << "reinterpret_cast< ";
+ var_.dispatch (t);
+ os << "& > (this->" << umember << "." << member << ");";
+ }
+ else
+ {
+ deref_.dispatch (t);
+ os << "this->" << umember << "." << member << ";";
+ }
+
+ os << "}";
+
+ // void
+ // name (const type& | type*)
+ //
+ os << inl
+ << "void " << scope << "::" << endl
+ << name << " (";
+ arg_.dispatch (t);
+ os << " x)"
+ << "{"
+ << "if (this->" << arm_member << " != " << tag << ")" << endl
+ << "this->" << arm << " (" << tag << ");";
+
+ if (fl)
+ {
+ os << endl
+ << "reinterpret_cast< ";
+ var_.dispatch (t);
+ os << "& > (this->" << umember << "." << member << ") = x;";
+
+ if (min == 0)
+ {
+ os << "this->" << umember << "." << member <<
+ ".data_[sizeof (";
+ var_.dispatch (t);
+ os << ")] = true;";
+ }
+ }
+ else
+ {
+ os << "else" << endl;
+ delete_.dispatch (t);
+ os << " this->" << umember << "." << member << ";"
+ << endl
+ << "this->" << umember << "." << member << " = x;";
+ }
+
+ os << "}";
+ }
+ }
+
+ private:
+ TypeName ro_ret_;
+ TypeName ret_;
+ TypeName arg_;
+ TypeName var_;
+ TypeOps deref_;
+ TypeOps delete_;
+ };
+
+ struct AllFunc: Traversal::All, Context
+ {
+ AllFunc (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ // For the all compositor, maxOccurs=1 and minOccurs={0,1}
+ // and it can only contain particles.
+ //
+ if (a.min () == 0)
+ {
+ String const& name (ename (a));
+ String const& type (etype (a));
+ String const& present (epresent (a));
+ String const& member (emember (a));
+
+ Boolean fl (fixed_length (a));
+ String scope (Context::scope (a));
+
+
+ // bool
+ // preset () const;
+ //
+ os << inl
+ << "bool " << scope << "::" << endl
+ << present << " () const"
+ << "{";
+
+ if (fl)
+ os << "return this->" << epresent_member (a) << ";";
+ else
+ os << "return this->" << member << " != 0;";
+
+ os << "}";
+
+
+ // void
+ // preset (bool);
+ //
+ os << inl
+ << "void " << scope << "::" << endl
+ << present << " (bool x)"
+ << "{";
+
+ if (fl)
+ os << "this->" << epresent_member (a) << " = x;";
+ else
+ {
+ os << "if (!x)"
+ << "{"
+ << "delete this->" << member << ";"
+ << "this->" << member << " = 0;"
+ << "}";
+ }
+
+ os << "}";
+
+
+ // const type&
+ // name () const
+ //
+ os << inl
+ << "const " << scope << "::" << type << "& " <<
+ scope << "::" << endl
+ << name << " () const"
+ << "{";
+
+ if (fl)
+ os << "return this->" << member << ";";
+ else
+ os << "return *this->" << member << ";";
+
+ os << "}";
+
+
+ // type&
+ // name ()
+ //
+ os << inl
+ << scope << "::" << type << "& " << scope << "::" << endl
+ << name << " ()"
+ << "{";
+
+ if (fl)
+ os << "return this->" << member << ";";
+ else
+ os << "return *this->" << member << ";";
+
+ os << "}";
+
+
+ // void
+ // name (const type& | type*)
+ //
+ os << inl
+ << "void " << scope << "::" << endl
+ << name << " (";
+
+ if (fl)
+ os << "const " << type << "&";
+ else
+ os << type << "*";
+
+ os << " x)"
+ << "{";
+
+ if (!fl)
+ os << "delete this->" << member << ";";
+
+ os << "this->" << member << " = x;";
+
+ if (fl)
+ os << "this->" << epresent_member (a) << " = true;";
+
+ os << "}";
+ }
+ else
+ All::contains (a);
+ }
+ };
+
+ struct ChoiceInSequenceFunc: Traversal::Choice, Context
+ {
+ ChoiceInSequenceFunc (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ UnsignedLong min (c.min ()), max (c.max ());
+
+ if (max == 1 && min == 1)
+ {
+ String scope (Context::scope (c));
+
+ // void
+ // arm (arm_tag)
+ //
+ os << inl
+ << scope << "::" << earm_tag (c) << " " << scope << "::" << endl
+ << earm (c) << " () const"
+ << "{"
+ << "return this->" << earm_member (c) << ";"
+ << "}";
+
+ Choice::contains (c);
+ return;
+ }
+
+ String const& name (ename (c));
+ String const& member (emember (c));
+ String scope (Context::scope (c));
+
+ if (max != 1)
+ {
+ String const& sequence (esequence (c));
+
+ // const seq&
+ // name () const
+ //
+ os << inl
+ << "const " << scope << "::" << sequence << "& " <<
+ scope << "::" << endl
+ << name << " () const"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+
+ // seq&
+ // name ()
+ //
+ os << inl
+ << scope << "::" << sequence << "& " << scope << "::" << endl
+ << name << " ()"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+ }
+ else if (min == 0)
+ {
+ Boolean fl (fixed_length (c));
+
+ String const& type (etype (c));
+ String const& present (epresent (c));
+
+ // bool
+ // preset () const;
+ //
+ os << inl
+ << "bool " << scope << "::" << endl
+ << present << " () const"
+ << "{";
+
+ if (fl)
+ os << "return this->" << epresent_member (c) << ";";
+ else
+ os << "return this->" << member << " != 0;";
+
+ os << "}";
+
+
+ // void
+ // preset (bool);
+ //
+ os << inl
+ << "void " << scope << "::" << endl
+ << present << " (bool x)"
+ << "{";
+
+ if (fl)
+ os << "this->" << epresent_member (c) << " = x;";
+ else
+ {
+ os << "if (!x)"
+ << "{"
+ << "delete this->" << member << ";"
+ << "this->" << member << " = 0;"
+ << "}";
+ }
+
+ os << "}";
+
+
+ // const type&
+ // name () const
+ //
+ os << inl
+ << "const " << scope << "::" << type << "& " <<
+ scope << "::" << endl
+ << name << " () const"
+ << "{";
+
+ if (fl)
+ os << "return this->" << member << ";";
+ else
+ os << "return *this->" << member << ";";
+
+ os << "}";
+
+
+ // type&
+ // name ()
+ //
+ os << inl
+ << scope << "::" << type << "& " << scope << "::" << endl
+ << name << " ()"
+ << "{";
+
+ if (fl)
+ os << "return this->" << member << ";";
+ else
+ os << "return *this->" << member << ";";
+
+ os << "}";
+
+
+ // void
+ // name (const type& | type*)
+ //
+ os << inl
+ << "void " << scope << "::" << endl
+ << name << " (";
+
+ if (fl)
+ os << "const " << type << "&";
+ else
+ os << type << "*";
+
+ os << " x)"
+ << "{";
+
+ if (!fl)
+ os << "delete this->" << member << ";";
+
+ os << "this->" << member << " = x;";
+
+ if (fl)
+ os << "this->" << epresent_member (c) << " = true;";
+
+ os << "}";
+ }
+ }
+ };
+
+ struct SequenceInSequenceFunc: Traversal::Sequence, Context
+ {
+ SequenceInSequenceFunc (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ UnsignedLong min (s.min ()), max (s.max ());
+
+ if (max == 1 && min == 1)
+ {
+ Sequence::contains (s);
+ return;
+ }
+
+ String const& name (ename (s));
+ String const& member (emember (s));
+ String scope (Context::scope (s));
+
+ if (max != 1)
+ {
+ String const& sequence (esequence (s));
+
+ // const seq&
+ // name () const
+ //
+ os << inl
+ << "const " << scope << "::" << sequence << "& " <<
+ scope << "::" << endl
+ << name << " () const"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+
+ // seq&
+ // name ()
+ //
+ os << inl
+ << scope << "::" << sequence << "& " << scope << "::" << endl
+ << name << " ()"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+ }
+ else if (min == 0)
+ {
+ Boolean fl (fixed_length (s));
+
+ String const& type (etype (s));
+ String const& present (epresent (s));
+
+ // bool
+ // preset () const;
+ //
+ os << inl
+ << "bool " << scope << "::" << endl
+ << present << " () const"
+ << "{";
+
+ if (fl)
+ os << "return this->" << epresent_member (s) << ";";
+ else
+ os << "return this->" << member << " != 0;";
+
+ os << "}";
+
+
+ // void
+ // preset (bool);
+ //
+ os << inl
+ << "void " << scope << "::" << endl
+ << present << " (bool x)"
+ << "{";
+
+ if (fl)
+ os << "this->" << epresent_member (s) << " = x;";
+ else
+ {
+ os << "if (!x)"
+ << "{"
+ << "delete this->" << member << ";"
+ << "this->" << member << " = 0;"
+ << "}";
+ }
+
+ os << "}";
+
+
+ // const type&
+ // name () const
+ //
+ os << inl
+ << "const " << scope << "::" << type << "& " <<
+ scope << "::" << endl
+ << name << " () const"
+ << "{";
+
+ if (fl)
+ os << "return this->" << member << ";";
+ else
+ os << "return *this->" << member << ";";
+
+ os << "}";
+
+
+ // type&
+ // name ()
+ //
+ os << inl
+ << scope << "::" << type << "& " << scope << "::" << endl
+ << name << " ()"
+ << "{";
+
+ if (fl)
+ os << "return this->" << member << ";";
+ else
+ os << "return *this->" << member << ";";
+
+ os << "}";
+
+
+ // void
+ // name (const type& | type*)
+ //
+ os << inl
+ << "void " << scope << "::" << endl
+ << name << " (";
+
+ if (fl)
+ os << "const " << type << "&";
+ else
+ os << type << "*";
+
+ os << " x)"
+ << "{";
+
+ if (!fl)
+ os << "delete this->" << member << ";";
+
+ os << "this->" << member << " = x;";
+
+ if (fl)
+ os << "this->" << epresent_member (s) << " = true;";
+
+ os << "}";
+ }
+ }
+ };
+
+ struct CompositorInChoiceFunc: Context
+ {
+ CompositorInChoiceFunc (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Compositor& c)
+ {
+ // When compositor is in choice we generate nested class even
+ // for min == max == 1.
+ //
+ String const& name (ename (c));
+ String const& member (emember (c));
+
+ SemanticGraph::Choice& cont (
+ dynamic_cast<SemanticGraph::Choice&> (
+ c.contained_particle ().compositor ()));
+
+ String const& arm (earm (cont));
+ String const& umember (emember (cont));
+
+ String scope (Context::scope (c));
+
+ if (c.max () != 1)
+ {
+ String const& sequence (esequence (c));
+
+ // const seq&
+ // name () const
+ //
+ os << inl
+ << "const " << scope << "::" << sequence << "& " <<
+ scope << "::" << endl
+ << name << " () const"
+ << "{"
+ << "return reinterpret_cast< const " << sequence << "& > (" <<
+ "this->" << umember << "." << member << ");"
+ << "}";
+
+ // seq&
+ // name ()
+ //
+ os << inl
+ << scope << "::" << sequence << "& " << scope << "::" << endl
+ << name << " ()"
+ << "{"
+ << "return reinterpret_cast< " << sequence << "& > (" <<
+ "this->" << umember << "." << member << ");"
+ << "}";
+ }
+ else
+ {
+ UnsignedLong min (c.min ());
+
+ Boolean fl (fixed_length (c));
+
+ String const& type (etype (c));
+ String const& tag (etag (c));
+ String const& arm_member (earm_member (cont));
+
+ if (min == 0)
+ {
+ String const& present (epresent (c));
+
+ // bool
+ // preset () const;
+ //
+ os << inl
+ << "bool " << scope << "::" << endl
+ << present << " () const"
+ << "{";
+
+ if (fl)
+ {
+ os << "return this->" << umember << "." << member <<
+ ".data_[sizeof (" << type << ")];";
+ }
+ else
+ os << "return this->" << umember << "." << member << " != 0;";
+
+ os << "}";
+
+ // void
+ // preset (bool);
+ //
+ os << inl
+ << "void " << scope << "::" << endl
+ << present << " (bool x)"
+ << "{"
+ << "if (this->" << arm_member << " != " << tag << ")" << endl
+ << "this->" << arm << " (" << tag << ");";
+
+ if (fl)
+ {
+ os << endl
+ << "this->" << umember << "." << member <<
+ ".data_[sizeof (" << type << ")] = x;";
+ }
+ else
+ {
+ os << "else if (!x)"
+ << "{"
+ << "delete this->" << umember << "." << member << ";"
+ << "this->" << umember << "." << member << " = 0;"
+ << "}";
+ }
+
+ os << "}";
+ }
+
+ // const type&
+ // name () const
+ //
+ os << inl
+ << "const " << scope << "::" << type << "& " <<
+ scope << "::" << endl
+ << name << " () const"
+ << "{"
+ << "return ";
+
+ if (fl)
+ os << "reinterpret_cast< const " << type << "& > (this->" <<
+ umember << "." << member << ");";
+ else
+ os << "*this->" << umember << "." << member << ";";
+
+ os << "}";
+
+ // type&
+ // name ()
+ //
+ os << inl
+ << scope << "::" << type << "& " << scope << "::" << endl
+ << name << " ()"
+ << "{"
+ << "return ";
+
+ if (fl)
+ os << "reinterpret_cast< " << type << "& > (this->" <<
+ umember << "." << member << ");";
+ else
+ os << "*this->" << umember << "." << member << ";";
+
+ os << "}";
+
+ // void
+ // name (const type& | type*)
+ //
+ os << inl
+ << "void " << scope << "::" << endl
+ << name << " (";
+
+ if (fl)
+ os << "const " << type << "&";
+ else
+ os << type << "*";
+
+ os << " x)"
+ << "{"
+ << "if (this->" << arm_member << " != " << tag << ")" << endl
+ << "this->" << arm << " (" << tag << ");";
+
+ if (fl)
+ {
+ os << endl
+ << "reinterpret_cast< " << type << "& > (this->" <<
+ umember << "." << member << ") = x;";
+
+ if (min == 0)
+ {
+ os << "this->" << umember << "." << member <<
+ ".data_[sizeof (" << type << ")] = true;";
+ }
+ }
+ else
+ {
+ os << "else" << endl
+ << "delete this->" << umember << "." << member << ";"
+ << endl
+ << "this->" << umember << "." << member << " = x;";
+ }
+
+ os << "}";
+ }
+ }
+ };
+
+ struct ChoiceInChoiceFunc: Traversal::Choice, CompositorInChoiceFunc
+ {
+ ChoiceInChoiceFunc (Context& c)
+ : CompositorInChoiceFunc (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ CompositorInChoiceFunc::traverse (c);
+ }
+ };
+
+ struct SequenceInChoiceFunc: Traversal::Sequence, CompositorInChoiceFunc
+ {
+ SequenceInChoiceFunc (Context& c)
+ : CompositorInChoiceFunc (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ CompositorInChoiceFunc::traverse (s);
+ }
+ };
+
+ //
+ //
+ //
+
+ struct All: Traversal::All, Context
+ {
+ All (Context& c, Traversal::ContainsParticle& contains_func)
+ : Context (c), contains_func_ (contains_func)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ // For the all compositor, maxOccurs=1 and minOccurs={0,1}
+ // and it can only contain particles.
+ //
+ if (a.min () == 0)
+ {
+ All::contains (a, contains_func_);
+
+ // Custom data.
+ //
+ if (a.context ().count ("cd-name"))
+ {
+ String const& scope (Context::scope (a));
+ String const& type (etype (a));
+
+ String const& name (ecd_name (a));
+ String const& member (ecd_member (a));
+ String const& sequence (ecd_sequence (a));
+
+ // const seq&
+ // name () const
+ //
+ os << inl
+ << "const " << scope << "::" << type << "::" <<
+ sequence << "& " << scope << "::" << type << "::" << endl
+ << name << " () const"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+
+ // seq&
+ // name ()
+ //
+ os << inl
+ << scope << "::" << type << "::" << sequence << "& " <<
+ scope << "::" << type << "::" << endl
+ << name << " ()"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+ }
+ }
+ }
+
+ private:
+ Traversal::ContainsParticle& contains_func_;
+ };
+
+ struct Choice: Traversal::Choice, Context
+ {
+ Choice (Context& c,
+ Boolean in_choice,
+ Traversal::ContainsParticle& contains_func)
+ : Context (c),
+ in_choice_ (in_choice),
+ contains_func_ (contains_func)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ // When choice is in choice we generate nested class even
+ // for min == max == 1.
+ //
+ if (in_choice_ || c.max () != 1 || c.min () == 0)
+ {
+ String scope (Context::scope (c));
+ String const& type (etype (c));
+
+ // void
+ // arm (arm_tag)
+ //
+ os << inl
+ << scope << "::" << type << "::" << earm_tag (c) << " " <<
+ scope << "::" << type << "::" << endl
+ << earm (c) << " () const"
+ << "{"
+ << "return this->" << earm_member (c) << ";"
+ << "}";
+
+ Choice::contains (c, contains_func_);
+
+ // Custom data.
+ //
+ if (c.context ().count ("cd-name"))
+ {
+ String const& name (ecd_name (c));
+ String const& member (ecd_member (c));
+ String const& sequence (ecd_sequence (c));
+
+ // const seq&
+ // name () const
+ //
+ os << inl
+ << "const " << scope << "::" << type << "::" <<
+ sequence << "& " << scope << "::" << type << "::" << endl
+ << name << " () const"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+
+ // seq&
+ // name ()
+ //
+ os << inl
+ << scope << "::" << type << "::" << sequence << "& " <<
+ scope << "::" << type << "::" << endl
+ << name << " ()"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+ }
+ }
+
+ Choice::contains (c);
+ }
+
+ private:
+ Boolean in_choice_;
+ Traversal::ContainsParticle& contains_func_;
+ };
+
+
+ struct SequenceInSequence: Traversal::Sequence, Context
+ {
+ SequenceInSequence (Context& c,
+ Traversal::ContainsParticle& contains_func)
+ : Context (c), contains_func_ (contains_func)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ if (s.max () != 1 || s.min () == 0)
+ {
+ Sequence::contains (s, contains_func_);
+
+ // Custom data.
+ //
+ if (s.context ().count ("cd-name"))
+ {
+ String const& scope (Context::scope (s));
+ String const& type (etype (s));
+
+ String const& name (ecd_name (s));
+ String const& member (ecd_member (s));
+ String const& sequence (ecd_sequence (s));
+
+ // const seq&
+ // name () const
+ //
+ os << inl
+ << "const " << scope << "::" << type << "::" <<
+ sequence << "& " << scope << "::" << type << "::" << endl
+ << name << " () const"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+
+ // seq&
+ // name ()
+ //
+ os << inl
+ << scope << "::" << type << "::" << sequence << "& " <<
+ scope << "::" << type << "::" << endl
+ << name << " ()"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+ }
+ }
+
+ Sequence::contains (s);
+ }
+
+ private:
+ Traversal::ContainsParticle& contains_func_;
+ };
+
+ struct SequenceInChoice: Traversal::Sequence, Context
+ {
+ SequenceInChoice (Context& c,
+ Traversal::ContainsParticle& contains_func)
+ : Context (c), contains_func_ (contains_func)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ // When sequence is in choice we generate nested class even
+ // for min == max == 1.
+ //
+ Sequence::contains (s, contains_func_);
+
+ // Custom data.
+ //
+ if (s.context ().count ("cd-name"))
+ {
+ String const& scope (Context::scope (s));
+ String const& type (etype (s));
+
+ String const& name (ecd_name (s));
+ String const& member (ecd_member (s));
+ String const& sequence (ecd_sequence (s));
+
+ // const seq&
+ // name () const
+ //
+ os << inl
+ << "const " << scope << "::" << type << "::" <<
+ sequence << "& " << scope << "::" << type << "::" << endl
+ << name << " () const"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+
+ // seq&
+ // name ()
+ //
+ os << inl
+ << scope << "::" << type << "::" << sequence << "& " <<
+ scope << "::" << type << "::" << endl
+ << name << " ()"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+ }
+
+ Sequence::contains (s);
+ }
+
+ private:
+ Traversal::ContainsParticle& contains_func_;
+ };
+
+ struct Complex : Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c),
+
+ // Functions.
+ //
+ attribute_func_ (c),
+ element_func_ (c),
+ element_in_choice_func_ (c),
+ all_func_ (c),
+ choice_in_choice_func_ (c),
+ choice_in_sequence_func_ (c),
+ sequence_in_choice_func_ (c),
+ sequence_in_sequence_func_ (c),
+
+ // Nested classes.
+ //
+ all_ (c, all_contains_func_),
+ choice_in_choice_ (c, true, choice_contains_func_),
+ choice_in_sequence_ (c, false, choice_contains_func_),
+ sequence_in_choice_ (c, sequence_contains_func_),
+ sequence_in_sequence_ (c, sequence_contains_func_)
+ {
+ // Functions.
+ //
+ attribute_names_func_ >> attribute_func_;
+
+ all_func_ >> all_contains_func_ >> element_func_;
+
+ sequence_in_choice_func_ >> sequence_contains_func_;
+ sequence_in_sequence_func_ >> sequence_contains_func_;
+ sequence_contains_func_ >> element_func_;
+ sequence_contains_func_ >> choice_in_sequence_func_;
+ sequence_contains_func_ >> sequence_in_sequence_func_;
+
+ choice_in_choice_func_ >> choice_contains_func_;
+ choice_in_sequence_func_ >> choice_contains_func_;
+ choice_contains_func_ >> element_in_choice_func_;
+ choice_contains_func_ >> sequence_in_choice_func_;
+ choice_contains_func_ >> choice_in_choice_func_;
+
+ contains_compositor_func_ >> all_func_;
+ contains_compositor_func_ >> choice_in_sequence_func_;
+ contains_compositor_func_ >> sequence_in_sequence_func_;
+
+ // Nested classes.
+ //
+ all_ >> all_contains_;
+
+ choice_in_choice_ >> choice_contains_;
+ choice_in_sequence_ >> choice_contains_;
+ choice_contains_ >> choice_in_choice_;
+ choice_contains_ >> sequence_in_choice_;
+
+ sequence_in_choice_ >> sequence_contains_;
+ sequence_in_sequence_ >> sequence_contains_;
+ sequence_contains_ >> choice_in_sequence_;
+ sequence_contains_ >> sequence_in_sequence_;
+
+ contains_compositor_ >> all_;
+ contains_compositor_ >> choice_in_sequence_;
+ contains_compositor_ >> sequence_in_sequence_;
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ if (!restriction_p (c))
+ {
+ os << "// " << comment (c.name ()) << endl
+ << "//" << endl
+ << endl;
+
+ Complex::names (c, attribute_names_func_);
+
+ if (c.contains_compositor_p ())
+ Complex::contains_compositor (c, contains_compositor_func_);
+
+ // Nested classes.
+ //
+ if (c.contains_compositor_p ())
+ Complex::contains_compositor (c, contains_compositor_);
+ }
+
+ // Custom data.
+ //
+ if (c.context ().count ("cd-name"))
+ {
+ String const& scope (ename (c));
+ String const& name (ecd_name (c));
+ String const& member (ecd_member (c));
+ String const& sequence (ecd_sequence (c));
+
+ // const seq&
+ // name () const
+ //
+ os << inl
+ << "const " << scope << "::" << sequence << "& " <<
+ scope << "::" << endl
+ << name << " () const"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+
+ // seq&
+ // name ()
+ //
+ os << inl
+ << scope << "::" << sequence << "& " << scope << "::" << endl
+ << name << " ()"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+ }
+ }
+
+ private:
+ // Functions.
+ //
+ AttributeFunc attribute_func_;
+ Traversal::Names attribute_names_func_;
+
+ ElementFunc element_func_;
+ ElementInChoiceFunc element_in_choice_func_;
+ AllFunc all_func_;
+ ChoiceInChoiceFunc choice_in_choice_func_;
+ ChoiceInSequenceFunc choice_in_sequence_func_;
+ SequenceInChoiceFunc sequence_in_choice_func_;
+ SequenceInSequenceFunc sequence_in_sequence_func_;
+ Traversal::ContainsParticle all_contains_func_;
+ Traversal::ContainsParticle choice_contains_func_;
+ Traversal::ContainsParticle sequence_contains_func_;
+
+ Traversal::ContainsCompositor contains_compositor_func_;
+
+ // Nested classes.
+ //
+ All all_;
+ Choice choice_in_choice_;
+ Choice choice_in_sequence_;
+ SequenceInChoice sequence_in_choice_;
+ SequenceInSequence sequence_in_sequence_;
+ Traversal::ContainsParticle all_contains_;
+ Traversal::ContainsParticle choice_contains_;
+ Traversal::ContainsParticle sequence_contains_;
+
+ Traversal::ContainsCompositor contains_compositor_;
+ };
+ }
+
+ Void
+ generate_tree_inline (Context& ctx)
+ {
+ // Generate includes.
+ //
+ if (ctx.options.value<CLI::generate_inline> ())
+ {
+ Traversal::Schema schema;
+ Includes includes (ctx, Includes::inline_);
+
+ schema >> includes;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ else
+ {
+ // Emit "weak" header includes that are used in the file-per-type
+ // compilation model.
+ //
+ Traversal::Schema schema;
+ Includes includes (ctx, Includes::source);
+
+ schema >> includes;
+
+ schema.dispatch (ctx.schema_root);
+ }
+
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+ Traversal::Names names_ns, names;
+
+ Namespace ns (ctx);
+
+ List list (ctx);
+ Union union_ (ctx);
+ Complex complex (ctx);
+ //Enumeration enumeration (ctx);
+
+ schema >> sources >> schema;
+ schema >> names_ns >> ns >> names;
+
+ names >> list;
+ names >> union_;
+ names >> complex;
+ //names >> enumeration;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+}
diff --git a/xsde/cxx/hybrid/tree-inline.hxx b/xsde/cxx/hybrid/tree-inline.hxx
new file mode 100644
index 0000000..9c8866d
--- /dev/null
+++ b/xsde/cxx/hybrid/tree-inline.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/hybrid/tree-inline.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_TREE_INLINE_HXX
+#define CXX_HYBRID_TREE_INLINE_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/hybrid/elements.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ Void
+ generate_tree_inline (Context&);
+ }
+}
+
+#endif // CXX_HYBRID_TREE_INLINE_HXX
diff --git a/xsde/cxx/hybrid/tree-name-processor.cxx b/xsde/cxx/hybrid/tree-name-processor.cxx
new file mode 100644
index 0000000..c828250
--- /dev/null
+++ b/xsde/cxx/hybrid/tree-name-processor.cxx
@@ -0,0 +1,1993 @@
+// file : xsde/cxx/hybrid/tree-name-processor.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/elements.hxx>
+#include <cxx/hybrid/tree-name-processor.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/set.hxx>
+#include <cult/containers/map.hxx>
+
+#include <sstream>
+#include <iostream>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ namespace
+ {
+ //
+ //
+ typedef Cult::Containers::Set<String> NameSet;
+ Char const* member_set_key = "cxx-hybrid-name-processor-member-set";
+
+ class Context: public CXX::Context
+ {
+ public:
+ Context (CLI::Options const& ops,
+ SemanticGraph::Schema& root,
+ SemanticGraph::Path const& file)
+ : CXX::Context (std::wcerr,
+ root,
+ "name",
+ "char",
+ ops.value<CLI::include_with_brackets> (),
+ ops.value<CLI::include_prefix> (),
+ "", // export symbol
+ ops.value<CLI::namespace_map> (),
+ ops.value<CLI::namespace_regex> (),
+ ops.value<CLI::namespace_regex_trace> (),
+ ops.value<CLI::include_regex> (),
+ ops.value<CLI::include_regex_trace> (),
+ ops.value<CLI::generate_inline> (),
+ ops.value<CLI::reserved_name> ()),
+ schema_path_ (file),
+ schema (root),
+ schema_path (schema_path_),
+ custom_data_map (custom_data_map_),
+ global_type_names (global_type_names_)
+ {
+ // Translate the type names with custom data.
+ //
+ {
+ typedef Cult::Containers::Vector<NarrowString> CustomData;
+ CustomData const& cd (ops.value<CLI::custom_data> ());
+
+ for (CustomData::ConstIterator i (cd.begin ());
+ i != cd.end (); ++i)
+ {
+ String name (*i);
+ CustomDataMap* map (&custom_data_map);
+ String::size_type b (0), e;
+
+ do
+ {
+ e = name.find (L"::", b);
+ String entry (name, b, e == String::npos ? e : e - b);
+
+ Shptr<CustomDataMap>& p ((*map)[entry]);
+
+ if (p == 0)
+ p = Shptr<CustomDataMap> (new CustomDataMap);
+
+ b = e;
+
+ if (b == String::npos)
+ {
+ // Last name. Add an empty string to indicate this.
+ //
+ (*p)[L""] = Shptr<CustomDataMap> (0);
+ break;
+ }
+
+ map = p.get ();
+ b += 2;
+
+ } while (true);
+ }
+ }
+ }
+
+ protected:
+ Context (Context& c)
+ : CXX::Context (c),
+ schema (c.schema),
+ schema_path (c.schema_path),
+ custom_data_map (c.custom_data_map),
+ global_type_names (c.global_type_names)
+ {
+ }
+
+ public:
+ Boolean
+ fixed_length (SemanticGraph::Type& t)
+ {
+ return t.context ().get<Boolean> ("fixed");
+ }
+
+ Boolean
+ fixed_length (SemanticGraph::Compositor& c)
+ {
+ return c.context ().get<Boolean> ("fixed");
+ }
+
+ Void
+ mark_variable (SemanticGraph::Compositor& c)
+ {
+ SemanticGraph::Compositor* p (&c);
+
+ while (true)
+ {
+ p->context ().set ("fixed", false);
+
+ if (p->contained_compositor_p ())
+ break;
+
+ p = &p->contained_particle ().compositor ();
+
+ if (!p->context ().get<Boolean> ("fixed"))
+ break;
+ }
+ }
+
+ public:
+ String
+ find_name (String const& n, String const& suffix, NameSet& set)
+ {
+ String name (escape (n + suffix));
+
+ for (UnsignedLong i (1); set.find (name) != set.end (); ++i)
+ {
+ std::wostringstream os;
+ os << i;
+ name = Hybrid::Context::escape (n + os.str () + suffix);
+ }
+
+ set.insert (name);
+ return name;
+ }
+
+ String
+ find_name (String const& n, NameSet& set)
+ {
+ return find_name (n, L"", set);
+ }
+
+ public:
+ struct CustomDataMap:
+ Cult::Containers::Map<String, Shptr<CustomDataMap> >
+ {
+ };
+
+ private:
+ SemanticGraph::Path const schema_path_;
+
+ CustomDataMap custom_data_map_;
+ Cult::Containers::Map<String, NameSet*> global_type_names_;
+
+ public:
+ SemanticGraph::Schema& schema;
+ SemanticGraph::Path const& schema_path;
+
+ CustomDataMap& custom_data_map;
+ Cult::Containers::Map<String, NameSet*>& global_type_names;
+ };
+
+ //
+ //
+ struct List: Traversal::List, Context
+ {
+ List (Context& c, Boolean data_members)
+ : Context (c), data_members_ (data_members)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ if (!data_members_)
+ {
+ // Check if this type has custom data.
+ //
+ CustomDataMap::Iterator i (custom_data_map.find (l.name ()));
+
+ if (i != custom_data_map.end () &&
+ i->second->find (L"") != i->second->end ())
+ {
+ SemanticGraph::Context& lc (l.context ());
+
+ // Use processed name.
+ //
+ String const& name (lc.get<String> ("name"));
+
+ lc.set (member_set_key, NameSet ());
+ NameSet& set (lc.get<NameSet> (member_set_key));
+ set.insert (name);
+
+ {
+ String name (find_name ("custom_data", set));
+
+ lc.set ("cd-name", name);
+ lc.set ("cd-sequence", find_name (name + L"_sequence", set));
+ lc.set ("cd-iterator", find_name (name + L"_iterator", set));
+ lc.set ("cd-const-iterator",
+ find_name (name + L"_const_iterator", set));
+ }
+ }
+ }
+ else
+ {
+ SemanticGraph::Context& lc (l.context ());
+
+ // Custom data.
+ //
+ if (lc.count ("cd-name"))
+ {
+ NameSet& set (lc.get<NameSet> (member_set_key));
+ String const& base (lc.get<String> ("cd-name"));
+ lc.set ("cd-member", find_name (base + L"_", set));
+ }
+ }
+ }
+
+ private:
+ Boolean data_members_;
+ };
+
+ //
+ //
+ struct Union: Traversal::Union, Context
+ {
+ Union (Context& c, Boolean data_members)
+ : Context (c), data_members_ (data_members)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ SemanticGraph::Context& uc (u.context ());
+
+ if (!data_members_)
+ {
+ // Use processed name.
+ //
+ String const& name (uc.get<String> ("name"));
+
+ uc.set (member_set_key, NameSet ());
+ NameSet& set (uc.get<NameSet> (member_set_key));
+ set.insert (name);
+
+ uc.set ("value", find_name ("value", set));
+
+ // Check if this type has custom data.
+ //
+ CustomDataMap::Iterator i (custom_data_map.find (u.name ()));
+
+ if (i != custom_data_map.end () &&
+ i->second->find (L"") != i->second->end ())
+ {
+ String name (find_name ("custom_data", set));
+
+ uc.set ("cd-name", name);
+ uc.set ("cd-sequence", find_name (name + L"_sequence", set));
+ uc.set ("cd-iterator", find_name (name + L"_iterator", set));
+ uc.set ("cd-const-iterator",
+ find_name (name + L"_const_iterator", set));
+ }
+ }
+ else
+ {
+ NameSet& set (uc.get<NameSet> (member_set_key));
+ uc.set ("value-member", find_name ("value_", set));
+
+ // Custom data.
+ //
+ if (uc.count ("cd-name"))
+ {
+ String const& base (uc.get<String> ("cd-name"));
+ uc.set ("cd-member", find_name (base + L"_", set));
+ }
+ }
+ }
+
+ private:
+ Boolean data_members_;
+ };
+
+ //
+ // Primary names.
+ //
+
+ struct PrimaryAttribute: Traversal::Attribute, Context
+ {
+ PrimaryAttribute (Context& c, NameSet& set)
+ : Context (c), set_ (set)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ a.context ().set ("name", find_name (a.name (), set_));
+ }
+
+ private:
+ NameSet& set_;
+ };
+
+ struct PrimaryElement: Traversal::Element, Context
+ {
+ PrimaryElement (Context& c, NameSet& set)
+ : Context (c), set_ (set)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ e.context ().set ("name", find_name (e.name (), set_));
+ }
+
+ private:
+ NameSet& set_;
+ };
+
+ struct PrimaryAll: Traversal::All, Context
+ {
+ PrimaryAll (Context& c, NameSet& set)
+ : Context (c), set_ (set)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ // For the all compositor, maxOccurs=1 and minOccurs={0,1}
+ // and it can only contain particles.
+ //
+ if (a.min () == 0)
+ a.context ().set ("name", find_name ("all", set_));
+ else
+ All::contains (a);
+ }
+
+ private:
+ NameSet& set_;
+ };
+
+ struct PrimaryChoice: Traversal::Choice, Context
+ {
+ PrimaryChoice (Context& c, NameSet& set, Boolean in_choice)
+ : Context (c), set_ (set), in_choice_ (in_choice)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ // In case of choice assign primary name even if there is
+ // no nested class. It is used to derive names for arm
+ // functions.
+ //
+ c.context ().set ("name", find_name ("choice", set_));
+
+ if (!in_choice_ && c.max () == 1 && c.min () == 1)
+ Choice::contains (c);
+ }
+
+ private:
+ NameSet& set_;
+ Boolean in_choice_;
+ };
+
+ struct PrimarySequence: Traversal::Sequence, Context
+ {
+ PrimarySequence (Context& c, NameSet& set, Boolean in_choice)
+ : Context (c), set_ (set), in_choice_ (in_choice)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ // When sequence is in choice we have nested class even
+ // for min == max == 1.
+ //
+ if (in_choice_ || s.max () != 1 || s.min () == 0)
+ s.context ().set ("name", find_name ("sequence", set_));
+ else
+ Sequence::contains (s);
+ }
+
+ private:
+ NameSet& set_;
+ Boolean in_choice_;
+ };
+
+ //
+ // Secondary names.
+ //
+
+ struct SecondaryAttribute: Traversal::Attribute, Context
+ {
+ SecondaryAttribute (Context& c, NameSet& set, Boolean data_members)
+ : Context (c), set_ (set), data_members_ (data_members)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ SemanticGraph::Context& ac (a.context ());
+
+ if (!data_members_)
+ {
+ if (a.optional ())
+ ac.set (
+ "present",
+ find_name (ac.get<String> ("name") + L"_present", set_));
+ }
+ else
+ {
+ String const& base (ac.get<String> ("name"));
+
+ if (a.optional ())
+ {
+ if (fixed_length (a.type ()))
+ ac.set ("present-member",
+ find_name (ac.get<String> ("present") + L"_", set_));
+ }
+
+ ac.set ("member", find_name (base + L"_", set_));
+ }
+ }
+
+ private:
+ NameSet& set_;
+ Boolean data_members_;
+ };
+
+ struct SecondaryElement: Traversal::Element, Context
+ {
+ SecondaryElement (Context& c, NameSet& set, Boolean data_members)
+ : Context (c), set_ (set), data_members_ (data_members)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ SemanticGraph::Context& ec (e.context ());
+
+ if (!data_members_)
+ {
+ if (e.max () != 1)
+ {
+ String const& base (ec.get<String> ("name"));
+
+ ec.set ("sequence", find_name (base + L"_sequence", set_));
+ ec.set ("iterator", find_name (base + L"_iterator", set_));
+ ec.set ("const-iterator",
+ find_name (base + L"_const_iterator", set_));
+ }
+ else if (e.min () == 0)
+ {
+ ec.set (
+ "present",
+ find_name (ec.get<String> ("name") + L"_present", set_));
+ }
+ }
+ else
+ {
+ String const& base (ec.get<String> ("name"));
+
+ if (e.max () == 1 && e.min () == 0)
+ {
+ if (fixed_length (e.type ()))
+ ec.set ("present-member",
+ find_name (ec.get<String> ("present") + L"_", set_));
+ }
+
+ ec.set ("member", find_name (base + L"_", set_));
+ }
+ }
+
+
+ private:
+ NameSet& set_;
+ Boolean data_members_;
+ };
+
+ struct SecondaryAll: Traversal::All, Context
+ {
+ SecondaryAll (Context& c,
+ NameSet& set,
+ CustomDataMap* map,
+ Boolean data_members)
+ : Context (c),
+ set_ (set),
+ map_ (map),
+ data_members_ (data_members)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ // For the all compositor, maxOccurs=1 and minOccurs={0,1}
+ // and it can only contain particles.
+ //
+ if (a.min () == 0)
+ {
+ SemanticGraph::Context& ac (a.context ());
+ String const& base (ac.get<String> ("name"));
+
+ if (!data_members_)
+ {
+ // Check if this type has custom data.
+ //
+ CustomDataMap* map (0);
+
+ if (map_)
+ {
+ CustomDataMap::Iterator i (map_->find (base));
+ if (i != map_->end ())
+ map = i->second.get ();
+ }
+
+ String type (find_name (base + L"_type", set_));
+ ac.set ("type", type);
+
+ // Handle the nested class.
+ //
+ {
+ ac.set (member_set_key, NameSet ());
+ NameSet& name_set (ac.get<NameSet> (member_set_key));
+
+ name_set.insert (type);
+
+ {
+ PrimaryElement element (*this, name_set);
+ Traversal::ContainsParticle contains_particle (element);
+ All::contains (a, contains_particle);
+ }
+
+ {
+ SecondaryElement element (*this, name_set, false);
+ Traversal::ContainsParticle contains_particle (element);
+ All::contains (a, contains_particle);
+ }
+
+ // Custom data.
+ //
+ if (map && map->find (L"") != map->end ())
+ {
+ // Make the type var-length if we have custom data.
+ //
+ if (fixed_length (a))
+ mark_variable (a);
+
+ String name (find_name ("custom_data", name_set));
+
+ ac.set ("cd-name", name);
+
+ ac.set ("cd-sequence",
+ find_name (name + L"_sequence", name_set));
+
+ ac.set ("cd-iterator",
+ find_name (name + L"_iterator", name_set));
+
+ ac.set ("cd-const-iterator",
+ find_name (name + L"_const_iterator", name_set));
+ }
+ }
+
+ ac.set ("present", find_name (base + L"_present", set_));
+ }
+ else
+ {
+ // Handle the nested class.
+ //
+ {
+ NameSet& name_set (ac.get<NameSet> (member_set_key));
+
+ SecondaryElement element (*this, name_set, true);
+ Traversal::ContainsParticle contains_particle (element);
+ All::contains (a, contains_particle);
+
+ // Custom data.
+ //
+ if (ac.count ("cd-name"))
+ {
+ String const& base (ac.get<String> ("cd-name"));
+ ac.set ("cd-member", find_name (base + L"_", name_set));
+ }
+ }
+
+ if (fixed_length (a))
+ ac.set ("present-member",
+ find_name (ac.get<String> ("present") + L"_", set_));
+
+ ac.set ("member", find_name (base + L"_", set_));
+ }
+ }
+ else
+ All::contains (a);
+ }
+
+ private:
+ NameSet& set_;
+ CustomDataMap* map_;
+ Boolean data_members_;
+ };
+
+ struct ParticleTag: Traversal::Element,
+ Traversal::Any,
+ Traversal::Choice,
+ Traversal::Sequence,
+ Context
+ {
+ ParticleTag (Context& c, NameSet& set)
+ : Context (c), set_ (set)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ String const& base (e.context ().get<String> ("name"));
+ e.context ().set ("tag", find_name (base, L"_tag", set_));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ a.context ().set ("tag", find_name (L"any", L"_tag", set_));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ String const& base (c.context ().get<String> ("name"));
+ c.context ().set ("tag", find_name (base, L"_tag", set_));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ String const& base (s.context ().get<String> ("name"));
+ s.context ().set ("tag", find_name (base, L"_tag", set_));
+ }
+
+ private:
+ NameSet& set_;
+ };
+
+ struct SecondaryChoice: Traversal::Choice, Context
+ {
+ SecondaryChoice (Context& c,
+ NameSet& set,
+ CustomDataMap* map,
+ Boolean in_choice,
+ Boolean data_members)
+ : Context (c),
+ set_ (set),
+ map_ (map),
+ in_choice_ (in_choice),
+ data_members_ (data_members)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice&);
+
+ Void
+ traverse_nested (SemanticGraph::Choice&, NameSet&, CustomDataMap*);
+
+ private:
+ NameSet& set_;
+ CustomDataMap* map_;
+ Boolean in_choice_;
+ Boolean data_members_;
+ };
+
+ struct SecondarySequence: Traversal::Sequence, Context
+ {
+ SecondarySequence (Context& c,
+ NameSet& set,
+ CustomDataMap* map,
+ Boolean in_choice,
+ Boolean data_members)
+ : Context (c),
+ set_ (set),
+ map_ (map),
+ in_choice_ (in_choice),
+ data_members_ (data_members)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence&);
+
+ Void
+ traverse_nested (SemanticGraph::Sequence&, NameSet&, CustomDataMap*);
+
+ private:
+ NameSet& set_;
+ CustomDataMap* map_;
+ Boolean in_choice_;
+ Boolean data_members_;
+ };
+
+
+ Void SecondaryChoice::
+ traverse (SemanticGraph::Choice& c)
+ {
+ SemanticGraph::Context& cc (c.context ());
+ String const& base (cc.get<String> ("name"));
+
+ // When choice is in choice we have nested class even
+ // for min == max == 1.
+ //
+ if (in_choice_ || c.max () != 1 || c.min () == 0)
+ {
+ if (!data_members_)
+ {
+ // Check if this type or any of its nested types have
+ // custom data.
+ //
+ CustomDataMap* map (0);
+
+ if (map_)
+ {
+ CustomDataMap::Iterator i (map_->find (base));
+ if (i != map_->end ())
+ map = i->second.get ();
+ }
+
+ //
+ //
+ String type (find_name (base + L"_type", set_));
+ cc.set ("type", type);
+
+ // Handle the nested class.
+ //
+ {
+ cc.set (member_set_key, NameSet ());
+ NameSet& name_set (cc.get<NameSet> (member_set_key));
+
+ // Add both base and type names so that we get consistent
+ // naming for nested choices if any.
+ //
+ name_set.insert (base);
+ name_set.insert (type);
+
+ traverse_nested (c, name_set, map);
+
+ // Tags.
+ //
+ String arm (find_name (base + L"_arm", name_set));
+ cc.set ("arm", arm);
+ cc.set ("arm-tag", find_name (arm + L"_tag", name_set));
+
+ {
+ UnsignedLong count (name_set.size ());
+
+ ParticleTag particle (*this, name_set);
+ Traversal::ContainsParticle contains (particle);
+
+ Choice::contains (c, contains);
+
+ count = name_set.size () - count;
+ cc.set ("arm-tag-count", count);
+ }
+
+ // Custom data.
+ //
+ if (map && map->find (L"") != map->end ())
+ {
+ // Make the type var-length if we have custom data.
+ //
+ if (fixed_length (c))
+ mark_variable (c);
+
+ String name (find_name ("custom_data", name_set));
+
+ cc.set ("cd-name", name);
+
+ cc.set ("cd-sequence",
+ find_name (name + L"_sequence", name_set));
+
+ cc.set ("cd-iterator",
+ find_name (name + L"_iterator", name_set));
+
+ cc.set ("cd-const-iterator",
+ find_name (name + L"_const_iterator", name_set));
+ }
+ }
+
+ if (c.max () != 1)
+ {
+ cc.set ("sequence", find_name (base + L"_sequence", set_));
+ cc.set ("iterator", find_name (base + L"_iterator", set_));
+ cc.set ("const-iterator",
+ find_name (base + L"_const_iterator", set_));
+ }
+ else if (c.min () == 0)
+ cc.set ("present", find_name (base + L"_present", set_));
+ }
+ else
+ {
+ // Handle the nested class.
+ //
+ {
+ NameSet& name_set (cc.get<NameSet> (member_set_key));
+ traverse_nested (c, name_set, 0);
+
+ // Tags.
+ //
+ cc.set ("arm-member",
+ find_name (cc.get<String> ("arm") + L"_", name_set));
+ cc.set ("member", find_name (base + L"_", name_set));
+
+ // Custom data.
+ //
+ if (cc.count ("cd-name"))
+ {
+ String const& base (cc.get<String> ("cd-name"));
+ cc.set ("cd-member", find_name (base + L"_", name_set));
+ }
+ }
+
+ if (c.max () == 1 && c.min () == 0)
+ {
+ if (fixed_length (c))
+ cc.set ("present-member",
+ find_name (cc.get<String> ("present") + L"_", set_));
+ }
+
+ cc.set ("member", find_name (base + L"_", set_));
+ }
+ }
+ else
+ {
+ Choice::contains (c);
+
+ if (!data_members_)
+ {
+ String arm (find_name (base + L"_arm", set_));
+ cc.set ("arm", arm);
+ cc.set ("arm-tag", find_name (arm + L"_tag", set_));
+
+ {
+ UnsignedLong count (set_.size ());
+
+ ParticleTag particle (*this, set_);
+ Traversal::ContainsParticle contains (particle);
+
+ Choice::contains (c, contains);
+
+ count = set_.size () - count;
+ cc.set ("arm-tag-count", count);
+ }
+ }
+ else
+ {
+ cc.set ("arm-member",
+ find_name (cc.get<String> ("arm") + L"_", set_));
+ cc.set ("member", find_name (base + L"_", set_));
+ }
+ }
+ }
+
+ Void SecondaryChoice::
+ traverse_nested (SemanticGraph::Choice& c,
+ NameSet& name_set,
+ CustomDataMap* map)
+ {
+ if (!data_members_)
+ {
+ PrimaryElement element (*this, name_set);
+ PrimaryChoice choice_in_sequence (*this, name_set, false);
+ PrimarySequence sequence_in_sequence (*this, name_set, false);
+ Traversal::ContainsParticle sequence_contains_particle;
+
+ sequence_contains_particle >> element;
+ sequence_contains_particle >> choice_in_sequence;
+ sequence_contains_particle >> sequence_in_sequence;
+ sequence_in_sequence >> sequence_contains_particle;
+
+ PrimaryChoice choice_in_choice (*this, name_set, true);
+ PrimarySequence sequence_in_choice (*this, name_set, true);
+ Traversal::ContainsParticle choice_contains_particle;
+
+ sequence_in_choice >> sequence_contains_particle;
+ choice_contains_particle >> element;
+ choice_contains_particle >> choice_in_choice;
+ choice_contains_particle >> sequence_in_choice;
+ choice_in_choice >> choice_contains_particle;
+ choice_in_sequence >> choice_contains_particle;
+
+ Choice::contains (c, choice_contains_particle);
+ }
+
+ SecondaryElement element (*this, name_set, data_members_);
+ SecondaryChoice choice_in_sequence (
+ *this, name_set, map, false, data_members_);
+ SecondarySequence sequence_in_sequence (
+ *this, name_set, map, false, data_members_);
+ Traversal::ContainsParticle sequence_contains_particle;
+
+ sequence_contains_particle >> element;
+ sequence_contains_particle >> choice_in_sequence;
+ sequence_contains_particle >> sequence_in_sequence;
+ sequence_in_sequence >> sequence_contains_particle;
+
+ SecondaryChoice choice_in_choice (
+ *this, name_set, map, true, data_members_);
+ SecondarySequence sequence_in_choice (
+ *this, name_set, map, true, data_members_);
+ Traversal::ContainsParticle choice_contains_particle;
+
+ sequence_in_choice >> sequence_contains_particle;
+ choice_contains_particle >> element;
+ choice_contains_particle >> choice_in_choice;
+ choice_contains_particle >> sequence_in_choice;
+ choice_in_choice >> choice_contains_particle;
+ choice_in_sequence >> choice_contains_particle;
+
+ Choice::contains (c, choice_contains_particle);
+ }
+
+ Void SecondarySequence::
+ traverse (SemanticGraph::Sequence& s)
+ {
+ // When sequence is in choice we have nested class even
+ // for min == max == 1.
+ //
+ if (in_choice_ || s.max () != 1 || s.min () == 0)
+ {
+ SemanticGraph::Context& sc (s.context ());
+ String const& base (sc.get<String> ("name"));
+
+ if (!data_members_)
+ {
+ // Check if this type or any of its nested types have
+ // custom data.
+ //
+ CustomDataMap* map (0);
+
+ if (map_)
+ {
+ CustomDataMap::Iterator i (map_->find (base));
+ if (i != map_->end ())
+ map = i->second.get ();
+ }
+
+ String type (find_name (base + L"_type", set_));
+ sc.set ("type", type);
+
+ // Handle the nested class.
+ //
+ {
+ sc.set (member_set_key, NameSet ());
+ NameSet& name_set (sc.get<NameSet> (member_set_key));
+
+ // Add both base and type names so that we get consistent
+ // naming for nested sequences if any.
+ //
+ name_set.insert (base);
+ name_set.insert (type);
+
+ traverse_nested (s, name_set, map);
+
+ // Custom data.
+ //
+ if (map && map->find (L"") != map->end ())
+ {
+ // Make the type var-length if we have custom data.
+ //
+ if (fixed_length (s))
+ mark_variable (s);
+
+ String name (find_name ("custom_data", name_set));
+
+ sc.set ("cd-name", name);
+
+ sc.set ("cd-sequence",
+ find_name (name + L"_sequence", name_set));
+
+ sc.set ("cd-iterator",
+ find_name (name + L"_iterator", name_set));
+
+ sc.set ("cd-const-iterator",
+ find_name (name + L"_const_iterator", name_set));
+ }
+ }
+
+ if (s.max () != 1)
+ {
+ sc.set ("sequence", find_name (base + L"_sequence", set_));
+ sc.set ("iterator", find_name (base + L"_iterator", set_));
+ sc.set ("const-iterator",
+ find_name (base + L"_const_iterator", set_));
+ }
+ else if (s.min () == 0)
+ sc.set ("present", find_name (base + L"_present", set_));
+ }
+ else
+ {
+ // Handle the nested class.
+ //
+ {
+ NameSet& name_set (sc.get<NameSet> (member_set_key));
+ traverse_nested (s, name_set, 0);
+
+ // Custom data.
+ //
+ if (sc.count ("cd-name"))
+ {
+ String const& base (sc.get<String> ("cd-name"));
+ sc.set ("cd-member", find_name (base + L"_", name_set));
+ }
+ }
+
+ if (s.max () == 1 && s.min () == 0)
+ {
+ if (fixed_length (s))
+ sc.set ("present-member",
+ find_name (sc.get<String> ("present") + L"_", set_));
+ }
+
+ sc.set ("member", find_name (base + L"_", set_));
+ }
+ }
+ else
+ Sequence::contains (s);
+ }
+
+ Void SecondarySequence::
+ traverse_nested (SemanticGraph::Sequence& s,
+ NameSet& name_set,
+ CustomDataMap* map)
+ {
+ if (!data_members_)
+ {
+ PrimaryElement element (*this, name_set);
+ PrimaryChoice choice_in_sequence (*this, name_set, false);
+ PrimarySequence sequence_in_sequence (*this, name_set, false);
+ Traversal::ContainsParticle sequence_contains_particle;
+
+ sequence_contains_particle >> element;
+ sequence_contains_particle >> choice_in_sequence;
+ sequence_contains_particle >> sequence_in_sequence;
+ sequence_in_sequence >> sequence_contains_particle;
+
+ PrimaryChoice choice_in_choice (*this, name_set, true);
+ PrimarySequence sequence_in_choice (*this, name_set, true);
+ Traversal::ContainsParticle choice_contains_particle;
+
+ sequence_in_choice >> sequence_contains_particle;
+ choice_contains_particle >> element;
+ choice_contains_particle >> choice_in_choice;
+ choice_contains_particle >> sequence_in_choice;
+ choice_in_choice >> choice_contains_particle;
+ choice_in_sequence >> choice_contains_particle;
+
+ Sequence::contains (s, sequence_contains_particle);
+ }
+
+ SecondaryElement element (*this, name_set, data_members_);
+ SecondaryChoice choice_in_sequence (
+ *this, name_set, map, false, data_members_);
+ SecondarySequence sequence_in_sequence (
+ *this, name_set, map, false, data_members_);
+ Traversal::ContainsParticle sequence_contains_particle;
+
+ sequence_contains_particle >> element;
+ sequence_contains_particle >> choice_in_sequence;
+ sequence_contains_particle >> sequence_in_sequence;
+ sequence_in_sequence >> sequence_contains_particle;
+
+ SecondaryChoice choice_in_choice (
+ *this, name_set, map, true, data_members_);
+ SecondarySequence sequence_in_choice (
+ *this, name_set, map, true, data_members_);
+ Traversal::ContainsParticle choice_contains_particle;
+
+ sequence_in_choice >> sequence_contains_particle;
+ choice_contains_particle >> element;
+ choice_contains_particle >> choice_in_choice;
+ choice_contains_particle >> sequence_in_choice;
+ choice_in_choice >> choice_contains_particle;
+ choice_in_sequence >> choice_contains_particle;
+
+ Sequence::contains (s, sequence_contains_particle);
+ }
+
+ //
+ //
+ struct Complex: Traversal::Complex, Context
+ {
+ Complex (Context& c, Boolean data_members)
+ : Context (c), data_members_ (data_members)
+ {
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ if (data_members_)
+ assign_data (c);
+ else
+ assign_names (c);
+ }
+
+ virtual Void
+ assign_names (Type& c)
+ {
+ SemanticGraph::Context& cc (c.context ());
+
+ // Check if this type or any of its nested types have
+ // custom data.
+ //
+ CustomDataMap* map (0);
+ {
+ CustomDataMap::Iterator i (custom_data_map.find (c.name ()));
+ if (i != custom_data_map.end ())
+ map = i->second.get ();
+ }
+
+ // Use processed name.
+ //
+ String const& name (cc.get<String> ("name"));
+
+ cc.set (member_set_key, NameSet ());
+ NameSet& member_set (cc.get<NameSet> (member_set_key));
+
+ member_set.insert (name);
+
+ // Add our base's members to the initial list.
+ //
+ Boolean restriction (false);
+
+ if (c.inherits_p ())
+ {
+ SemanticGraph::Type& b (c.inherits ().base ());
+
+ if (b.is_a<SemanticGraph::Complex> ())
+ {
+ SemanticGraph::Context& bc (b.context ());
+
+ if (!bc.count (member_set_key))
+ dispatch (b);
+
+ NameSet const& bset (bc.get<NameSet> (member_set_key));
+ member_set.insert (bset.begin (), bset.end ());
+ }
+
+ // Inheritance by restriction from anyType is a special case.
+ //
+ restriction = c.inherits ().is_a<SemanticGraph::Restricts> () &&
+ !b.is_a<SemanticGraph::AnyType> ();
+ }
+
+ if (!restriction)
+ {
+ // First assign the "primary" names.
+ //
+ PrimaryAttribute pri_attribute (*this, member_set);
+ Traversal::Names pri_names (pri_attribute);
+
+ Complex::names (c, pri_names);
+
+ if (c.contains_compositor_p ())
+ {
+ PrimaryElement element (*this, member_set);
+ PrimaryAll all (*this, member_set);
+ Traversal::ContainsParticle all_contains_particle;
+
+ all >> all_contains_particle >> element;
+
+ PrimaryChoice choice_in_sequence (*this, member_set, false);
+ PrimarySequence sequence_in_sequence (*this, member_set, false);
+ Traversal::ContainsParticle sequence_contains_particle;
+
+ sequence_contains_particle >> element;
+ sequence_contains_particle >> choice_in_sequence;
+ sequence_contains_particle >> sequence_in_sequence;
+ sequence_in_sequence >> sequence_contains_particle;
+
+ PrimaryChoice choice_in_choice (*this, member_set, true);
+ PrimarySequence sequence_in_choice (*this, member_set, true);
+ Traversal::ContainsParticle choice_contains_particle;
+
+ sequence_in_choice >> sequence_contains_particle;
+ choice_contains_particle >> element;
+ choice_contains_particle >> choice_in_choice;
+ choice_contains_particle >> sequence_in_choice;
+ choice_in_choice >> choice_contains_particle;
+ choice_in_sequence >> choice_contains_particle;
+
+ Traversal::ContainsCompositor contains_compositor;
+
+ contains_compositor >> all;
+ contains_compositor >> choice_in_sequence;
+ contains_compositor >> sequence_in_sequence;
+
+ Complex::contains_compositor (c, contains_compositor);
+ }
+
+ // Assign "secondary" names.
+ //
+ SecondaryAttribute sec_attribute (*this, member_set, false);
+ Traversal::Names sec_names (sec_attribute);
+
+ Complex::names (c, sec_names);
+
+ if (c.contains_compositor_p ())
+ {
+ SecondaryElement element (*this, member_set, false);
+ SecondaryAll all (*this, member_set, map, false);
+ Traversal::ContainsParticle all_contains_particle;
+
+ all >> all_contains_particle >> element;
+
+ SecondaryChoice choice_in_sequence (
+ *this, member_set, map, false, false);
+ SecondarySequence sequence_in_sequence (
+ *this, member_set, map, false, false);
+ Traversal::ContainsParticle sequence_contains_particle;
+
+ sequence_contains_particle >> element;
+ sequence_contains_particle >> choice_in_sequence;
+ sequence_contains_particle >> sequence_in_sequence;
+ sequence_in_sequence >> sequence_contains_particle;
+
+ SecondaryChoice choice_in_choice (
+ *this, member_set, map, true, false);
+ SecondarySequence sequence_in_choice (
+ *this, member_set, map, true, false);
+ Traversal::ContainsParticle choice_contains_particle;
+
+ sequence_in_choice >> sequence_contains_particle;
+ choice_contains_particle >> element;
+ choice_contains_particle >> choice_in_choice;
+ choice_contains_particle >> sequence_in_choice;
+ choice_in_choice >> choice_contains_particle;
+ choice_in_sequence >> choice_contains_particle;
+
+ Traversal::ContainsCompositor contains_compositor;
+
+ contains_compositor >> all;
+ contains_compositor >> choice_in_sequence;
+ contains_compositor >> sequence_in_sequence;
+
+ Complex::contains_compositor (c, contains_compositor);
+ }
+ }
+
+ // Custom data.
+ //
+ if (map && map->find (L"") != map->end ())
+ {
+ String name (find_name ("custom_data", member_set));
+
+ cc.set ("cd-name", name);
+
+ cc.set ("cd-sequence",
+ find_name (name + L"_sequence", member_set));
+
+ cc.set ("cd-iterator",
+ find_name (name + L"_iterator", member_set));
+
+ cc.set ("cd-const-iterator",
+ find_name (name + L"_const_iterator", member_set));
+ }
+ }
+
+ virtual Void
+ assign_data (Type& c)
+ {
+ SemanticGraph::Context& cc (c.context ());
+ Boolean restriction (false);
+
+ if (c.inherits_p ())
+ restriction = c.inherits ().is_a<SemanticGraph::Restricts> () &&
+ !c.inherits ().base ().is_a<SemanticGraph::AnyType> ();
+
+ NameSet& member_set (cc.get<NameSet> (member_set_key));
+
+ if (!restriction)
+ {
+ SecondaryAttribute sec_attribute (*this, member_set, true);
+ Traversal::Names sec_names (sec_attribute);
+
+ Complex::names (c, sec_names);
+
+ if (c.contains_compositor_p ())
+ {
+ SecondaryElement element (*this, member_set, true);
+ SecondaryAll all (*this, member_set, 0, true);
+ Traversal::ContainsParticle all_contains_particle;
+
+ all >> all_contains_particle >> element;
+
+ SecondaryChoice choice_in_sequence (
+ *this, member_set, 0, false, true);
+
+ SecondarySequence sequence_in_sequence (
+ *this, member_set, 0, false, true);
+
+ Traversal::ContainsParticle sequence_contains_particle;
+
+ sequence_contains_particle >> element;
+ sequence_contains_particle >> choice_in_sequence;
+ sequence_contains_particle >> sequence_in_sequence;
+ sequence_in_sequence >> sequence_contains_particle;
+
+ SecondaryChoice choice_in_choice (
+ *this, member_set, 0, true, true);
+
+ SecondarySequence sequence_in_choice (
+ *this, member_set, 0, true, true);
+
+ Traversal::ContainsParticle choice_contains_particle;
+
+ sequence_in_choice >> sequence_contains_particle;
+ choice_contains_particle >> element;
+ choice_contains_particle >> choice_in_choice;
+ choice_contains_particle >> sequence_in_choice;
+ choice_in_choice >> choice_contains_particle;
+ choice_in_sequence >> choice_contains_particle;
+
+ Traversal::ContainsCompositor contains_compositor;
+
+ contains_compositor >> all;
+ contains_compositor >> choice_in_sequence;
+ contains_compositor >> sequence_in_sequence;
+
+ Complex::contains_compositor (c, contains_compositor);
+ }
+ }
+
+ // Custom data.
+ //
+ if (cc.count ("cd-name"))
+ {
+ String const& base (cc.get<String> ("cd-name"));
+ cc.set ("cd-member", find_name (base + L"_", member_set));
+ }
+ }
+
+ private:
+ Boolean data_members_;
+ };
+
+ //
+ //
+ struct GlobalType: Traversal::Type, Context
+ {
+ GlobalType (Context& c, NameSet& set)
+ : Context (c), set_ (set)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& t)
+ {
+ String name (find_name (t.name (), set_));
+ t.context ().set ("name", name);
+ }
+
+ private:
+ NameSet& set_;
+ };
+
+
+ struct Namespace: Traversal::Namespace, Context
+ {
+ Namespace (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& ns)
+ {
+ SemanticGraph::Context& nsc (ns.context ());
+ String const& name (ns.name ());
+
+ // Use a name set associated with this namespace if present.
+ // This will make sure that we don't get any conflicts in the
+ // multi-mapping translation case. Note that here we assume
+ // that all mappings traverse schemas in the same order which
+ // is currently the case.
+ //
+ if (global_type_names.find (name) == global_type_names.end ())
+ {
+ if (!nsc.count ("name-set"))
+ nsc.set ("name-set", NameSet ());
+
+ NameSet& s (nsc.get<NameSet> ("name-set"));
+ global_type_names[name] = &s;
+ }
+
+ NameSet& type_set (*global_type_names[name]);
+
+ GlobalType type (*this, type_set);
+ Traversal::Names names (type);
+
+ Traversal::Namespace::names (ns, names);
+ }
+ };
+
+ struct FundType : Traversal::AnyType,
+ Traversal::AnySimpleType,
+
+ Traversal::Fundamental::Byte,
+ Traversal::Fundamental::UnsignedByte,
+ Traversal::Fundamental::Short,
+ Traversal::Fundamental::UnsignedShort,
+ Traversal::Fundamental::Int,
+ Traversal::Fundamental::UnsignedInt,
+ Traversal::Fundamental::Long,
+ Traversal::Fundamental::UnsignedLong,
+ Traversal::Fundamental::Integer,
+ Traversal::Fundamental::NonPositiveInteger,
+ Traversal::Fundamental::NonNegativeInteger,
+ Traversal::Fundamental::PositiveInteger,
+ Traversal::Fundamental::NegativeInteger,
+
+ Traversal::Fundamental::Boolean,
+
+ Traversal::Fundamental::Float,
+ Traversal::Fundamental::Double,
+ Traversal::Fundamental::Decimal,
+
+ Traversal::Fundamental::String,
+ Traversal::Fundamental::NormalizedString,
+ Traversal::Fundamental::Token,
+ Traversal::Fundamental::Name,
+ Traversal::Fundamental::NameToken,
+ Traversal::Fundamental::NameTokens,
+ Traversal::Fundamental::NCName,
+ Traversal::Fundamental::Language,
+
+ Traversal::Fundamental::QName,
+
+ Traversal::Fundamental::Id,
+ Traversal::Fundamental::IdRef,
+ Traversal::Fundamental::IdRefs,
+
+ Traversal::Fundamental::AnyURI,
+
+ Traversal::Fundamental::Base64Binary,
+ Traversal::Fundamental::HexBinary,
+
+ Traversal::Fundamental::Date,
+ Traversal::Fundamental::DateTime,
+ Traversal::Fundamental::Duration,
+ Traversal::Fundamental::Day,
+ Traversal::Fundamental::Month,
+ Traversal::Fundamental::MonthDay,
+ Traversal::Fundamental::Year,
+ Traversal::Fundamental::YearMonth,
+ Traversal::Fundamental::Time,
+
+ Traversal::Fundamental::Entity,
+ Traversal::Fundamental::Entities,
+
+ Context
+
+ {
+ FundType (Context& c)
+ : Context (c)
+ {
+ }
+
+ // anyType & anySimpleType.
+ //
+ virtual Void
+ traverse (SemanticGraph::AnyType& t)
+ {
+ set_name (t, "any_type");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnySimpleType& t)
+ {
+ set_name (t, "any_simple_type");
+ }
+
+ // Boolean.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Boolean& t)
+ {
+ set_name (t, "boolean");
+ }
+
+ // Integral types.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Byte& t)
+ {
+ set_name (t, "byte");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedByte& t)
+ {
+ set_name (t, "unsigned_byte");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Short& t)
+ {
+ set_name (t, "short");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedShort& t)
+ {
+ set_name (t, "unsigned_short");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Int& t)
+ {
+ set_name (t, "int");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedInt& t)
+ {
+ set_name (t, "unsigned_int");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Long& t)
+ {
+ set_name (t, "long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedLong& t)
+ {
+ set_name (t, "unsigned_long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Integer& t)
+ {
+ set_name (t, "integer");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonPositiveInteger& t)
+ {
+ set_name (t, "non_positive_integer");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonNegativeInteger& t)
+ {
+ set_name (t, "non_negative_integer");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::PositiveInteger& t)
+ {
+ set_name (t, "positive_integer");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NegativeInteger& t)
+ {
+ set_name (t, "negative_integer");
+ }
+
+ // Floats.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Float& t)
+ {
+ set_name (t, "float");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Double& t)
+ {
+ set_name (t, "double");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Decimal& t)
+ {
+ set_name (t, "decimal");
+ }
+
+ // Strings.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::String& t)
+ {
+ set_name (t, "string");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NormalizedString& t)
+ {
+ set_name (t, "normalized_string");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Token& t)
+ {
+ set_name (t, "token");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameToken& t)
+ {
+ set_name (t, "nmtoken");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameTokens& t)
+ {
+ set_name (t, "nmtokens");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Name& t)
+ {
+ set_name (t, "name");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NCName& t)
+ {
+ set_name (t, "ncname");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Language& t)
+ {
+ set_name (t, "language");
+ }
+
+
+ // Qualified name.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::QName& t)
+ {
+ set_name (t, "qname");
+ }
+
+
+ // ID/IDREF.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Id& t)
+ {
+ set_name (t, "id");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRef& t)
+ {
+ set_name (t, "idref");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRefs& t)
+ {
+ set_name (t, "idrefs");
+ }
+
+ // URI.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::AnyURI& t)
+ {
+ set_name (t, "uri");
+ }
+
+ // Binary.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Base64Binary& t)
+ {
+ set_name (t, "base64_binary");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::HexBinary& t)
+ {
+ set_name (t, "hex_binary");
+ }
+
+
+ // Date/time.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Date& t)
+ {
+ set_name (t, "date");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::DateTime& t)
+ {
+ set_name (t, "date_time");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Duration& t)
+ {
+ set_name (t, "duration");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Day& t)
+ {
+ set_name (t, "gday");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Month& t)
+ {
+ set_name (t, "gmonth");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::MonthDay& t)
+ {
+ set_name (t, "gmonth_day");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Year& t)
+ {
+ set_name (t, "gyear");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::YearMonth& t)
+ {
+ set_name (t, "gyear_month");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Time& t)
+ {
+ set_name (t, "time");
+ }
+
+ // Entity.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entity& t)
+ {
+ set_name (t, "entity");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entities& t)
+ {
+ set_name (t, "entities");
+ }
+
+ private:
+ Void
+ set_name (SemanticGraph::Type& t, String const& name)
+ {
+ SemanticGraph::Context& c (t.context ());
+ c.set ("name", escape (name));
+ }
+ };
+
+ // Go into sourced/included/imported schemas while making sure
+ // we don't process the same stuff more than once.
+ //
+ struct Uses: Traversal::Sources,
+ Traversal::Includes,
+ Traversal::Imports
+ {
+ virtual Void
+ traverse (SemanticGraph::Sources& sr)
+ {
+ SemanticGraph::Schema& s (sr.schema ());
+
+ if (!s.context ().count ("cxx-hybrid-name-processor-seen"))
+ {
+ s.context ().set ("cxx-hybrid-name-processor-seen", true);
+ Traversal::Sources::traverse (sr);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Includes& i)
+ {
+ SemanticGraph::Schema& s (i.schema ());
+
+ if (!s.context ().count ("cxx-hybrid-name-processor-seen"))
+ {
+ s.context ().set ("cxx-hybrid-name-processor-seen", true);
+ Traversal::Includes::traverse (i);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Imports& i)
+ {
+ SemanticGraph::Schema& s (i.schema ());
+
+ if (!s.context ().count ("cxx-hybrid-name-processor-seen"))
+ {
+ s.context ().set ("cxx-hybrid-name-processor-seen", true);
+ Traversal::Imports::traverse (i);
+ }
+ }
+ };
+
+ // Go into implied schemas while making sure we don't process
+ // the same stuff more than once.
+ //
+ struct Implies: Traversal::Implies
+ {
+ virtual Void
+ traverse (SemanticGraph::Implies& i)
+ {
+ SemanticGraph::Schema& s (i.schema ());
+
+ if (!s.context ().count ("cxx-hybrid-name-processor-seen"))
+ {
+ s.context ().set ("cxx-hybrid-name-processor-seen", true);
+ Traversal::Implies::traverse (i);
+ }
+ }
+ };
+
+ Void
+ process_impl (CLI::Options const& ops,
+ SemanticGraph::Schema& tu,
+ SemanticGraph::Path const& file)
+ {
+ Context ctx (ops, tu, file);
+
+ if (tu.names_begin ()->named ().name () ==
+ L"http://www.w3.org/2001/XMLSchema")
+ {
+ // XML Schema namespace.
+ //
+ Traversal::Schema schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+ FundType fund_type (ctx);
+
+ schema >> schema_names >> ns >> ns_names >> fund_type;
+
+ schema.dispatch (tu);
+ }
+ else
+ {
+ // Pass one - assign names to fundamental types.
+ //
+ {
+ Traversal::Schema schema;
+ Implies implies;
+ Traversal::Schema xs_schema;
+
+ schema >> implies >> xs_schema;
+
+ Traversal::Names xs_schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+ FundType fund_type (ctx);
+
+ xs_schema >> xs_schema_names >> ns >> ns_names >> fund_type;
+
+ schema.dispatch (tu);
+ }
+
+ // Pass two - assign names to global types. This pass cannot
+ // be combined with pass three because of possible recursive
+ // schema inclusions. Also note that we check first if this
+ // schema has already been processed which may happen in the
+ // file-per-type compilation mode.
+ //
+ if (!tu.context ().count ("cxx-hybrid-name-processor-seen"))
+ {
+ Traversal::Schema schema;
+ Uses uses;
+
+ schema >> uses >> schema;
+
+ Traversal::Names schema_names;
+ Namespace ns (ctx);
+
+ schema >> schema_names >> ns;
+
+ // Some twisted schemas do recusive self-inclusion.
+ //
+ tu.context ().set ("cxx-hybrid-name-processor-seen", true);
+
+ schema.dispatch (tu);
+ }
+
+ // Pass three - assign names inside complex types. Here we don't
+ // need to go into included/imported schemas.
+ //
+ {
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+
+ schema >> sources >> schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+
+ schema >> schema_names >> ns >> ns_names;
+
+ List list (ctx, false);
+ Union union_ (ctx, false);
+ Complex complex (ctx, false);
+
+ ns_names >> list;
+ ns_names >> union_;
+ ns_names >> complex;
+
+ schema.dispatch (tu);
+ }
+
+ // Pass four - assign names to data memeber. Here we aslo don't
+ // need to go into included/imported schemas.
+ //
+ {
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+
+ schema >> sources >> schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+
+ schema >> schema_names >> ns >> ns_names;
+
+ List list (ctx, true);
+ Union union_ (ctx, true);
+ Complex complex (ctx, true);
+
+ ns_names >> list;
+ ns_names >> union_;
+ ns_names >> complex;
+
+ schema.dispatch (tu);
+ }
+ }
+ }
+ }
+
+ Void TreeNameProcessor::
+ process (CLI::Options const& ops,
+ SemanticGraph::Schema& tu,
+ SemanticGraph::Path const& file)
+ {
+ process_impl (ops, tu, file);
+ }
+ }
+}
diff --git a/xsde/cxx/hybrid/tree-name-processor.hxx b/xsde/cxx/hybrid/tree-name-processor.hxx
new file mode 100644
index 0000000..4d884bc
--- /dev/null
+++ b/xsde/cxx/hybrid/tree-name-processor.hxx
@@ -0,0 +1,32 @@
+// file : xsde/cxx/hybrid/tree-name-processor.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CXX_HYBRID_TREE_NAME_PROCESSOR_HXX
+#define CXX_HYBRID_TREE_NAME_PROCESSOR_HXX
+
+#include <cult/types.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+
+#include <cxx/hybrid/cli.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ using namespace Cult::Types;
+
+ class TreeNameProcessor
+ {
+ public:
+ Void
+ process (CLI::Options const& options,
+ XSDFrontend::SemanticGraph::Schema&,
+ XSDFrontend::SemanticGraph::Path const& file);
+ };
+ }
+}
+
+#endif // CXX_HYBRID_TREE_NAME_PROCESSOR_HXX
diff --git a/xsde/cxx/hybrid/tree-size-processor.cxx b/xsde/cxx/hybrid/tree-size-processor.cxx
new file mode 100644
index 0000000..43fa2fc
--- /dev/null
+++ b/xsde/cxx/hybrid/tree-size-processor.cxx
@@ -0,0 +1,850 @@
+// file : xsde/cxx/hybrid/tree-size-processor.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/hybrid/elements.hxx>
+#include <cxx/hybrid/tree-size-processor.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/set.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ namespace
+ {
+ typedef Cult::Containers::Set<String> TypeSet;
+
+ Boolean
+ test (SemanticGraph::Type& t)
+ {
+ return t.context ().count ("fixed") != 0;
+ }
+
+ Void
+ set (SemanticGraph::Type& t, Boolean v)
+ {
+ t.context ().set ("fixed", v);
+ }
+
+ Void
+ set (SemanticGraph::Compositor& c, Boolean v)
+ {
+ c.context ().set ("fixed", v);
+ }
+
+ Boolean
+ get (SemanticGraph::Type& t)
+ {
+ return t.context ().get<Boolean> ("fixed");
+ }
+
+ //
+ //
+ struct Particle: Traversal::Element
+ {
+ Particle (Boolean& fixed, Traversal::NodeBase& type_traverser)
+ : fixed_ (fixed), type_traverser_ (type_traverser)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (fixed_)
+ {
+ // Check cardinality.
+ //
+ if (e.max () != 1)
+ {
+ fixed_ = false;
+ return;
+ }
+
+ // Check the type.
+ //
+ SemanticGraph::Type& t (e.type ());
+
+ if (!test (t))
+ type_traverser_.dispatch (t);
+
+ fixed_ = get (t);
+ }
+ }
+
+ /*
+ virtual Void
+ traverse (SemanticGraph::Any&)
+ {
+ // Types with wildcards are always variable length.
+ //
+ if (fixed_)
+ fixed_ = false;
+ }
+ */
+
+ private:
+ Boolean& fixed_;
+ Traversal::NodeBase& type_traverser_;
+ };
+
+ struct Compositor: Traversal::All,
+ Traversal::Choice,
+ Traversal::Sequence
+ {
+ Compositor (Boolean& fixed, Traversal::NodeBase& type_traverser)
+ : fixed_ (fixed), type_traverser_ (type_traverser)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ // For the all compositor, maxOccurs=1 and minOccurs={0,1}
+ // and it can only contain particles. In case of an optional
+ // compositor we need to assign the size for the nested class.
+ //
+ if (a.min () == 0)
+ {
+ Boolean fixed = true;
+
+ {
+ Particle particle (fixed, type_traverser_);
+ Traversal::ContainsParticle contains_particle;
+
+ contains_particle >> particle;
+
+ All::contains (a, contains_particle);
+ }
+
+ set (a, fixed);
+
+ if (!fixed)
+ fixed_ = false;
+ }
+ else
+ All::contains (a);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ // Here we need to assign the size for the nested class in
+ // all three cases because this choice might be in choice.
+ //
+ Boolean fixed = true;
+
+ {
+ Particle particle (fixed, type_traverser_);
+ Compositor compositor (fixed, type_traverser_);
+ Traversal::ContainsParticle contains_particle;
+
+ contains_particle >> compositor >> contains_particle;
+ contains_particle >> particle;
+
+ Choice::contains (c, contains_particle);
+ }
+
+ set (c, fixed);
+
+ if (c.max () != 1 || !fixed)
+ fixed_ = false;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ // Here we need to assign the size for the nested class in
+ // all three cases because this sequence might be in choice.
+ //
+ Boolean fixed = true;
+
+ {
+ Particle particle (fixed, type_traverser_);
+ Compositor compositor (fixed, type_traverser_);
+ Traversal::ContainsParticle contains_particle;
+
+ contains_particle >> compositor >> contains_particle;
+ contains_particle >> particle;
+
+ Sequence::contains (s, contains_particle);
+ }
+
+ set (s, fixed);
+
+ if (s.max () != 1 || !fixed)
+ fixed_ = false;
+ }
+
+ private:
+ Boolean& fixed_;
+ Traversal::NodeBase& type_traverser_;
+ };
+
+ struct Attribute: Traversal::Attribute
+ {
+ Attribute (Boolean& fixed, Traversal::NodeBase& type_traverser)
+ : fixed_ (fixed), type_traverser_ (type_traverser)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ if (fixed_)
+ {
+ SemanticGraph::Type& t (a.type ());
+
+ if (!test (t))
+ type_traverser_.dispatch (t);
+
+ fixed_ = get (t);
+ }
+ }
+
+ /*
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute&)
+ {
+ // Types with wildcards are always variable length.
+ //
+ if (fixed_)
+ fixed_ = false;
+ }
+ */
+
+ private:
+ Boolean& fixed_;
+ Traversal::NodeBase& type_traverser_;
+ };
+
+ //
+ //
+ struct Type: Traversal::List,
+ Traversal::Union,
+ Traversal::Complex
+ {
+ Type (TypeSet& custom_data, Boolean stl_)
+ : custom_data_ (custom_data), stl (stl_)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::List& l)
+ {
+ if (!test (l))
+ set (l, false);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Union& u)
+ {
+ if (!test (u))
+ {
+ Boolean fixed (stl);
+
+ // Check for custom data.
+ //
+ if (fixed)
+ {
+ if (custom_data_.find (u.name ()) != custom_data_.end ())
+ fixed = false;
+ }
+
+ set (u, fixed);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ SemanticGraph::Context& ctx (c.context ());
+
+ if (test (c))
+ return;
+
+ if (ctx.count ("recurse"))
+ set (c, false);
+ else
+ {
+ ctx.set ("recurse", true);
+
+ Boolean fixed = true;
+
+ // First check our base.
+ //
+ if (c.inherits_p ())
+ {
+ SemanticGraph::Type& b (c.inherits ().base ());
+
+ if (!test (b))
+ dispatch (b);
+
+ fixed = get (b);
+ }
+
+ // Check particles. Do this even if fixed is already false
+ // because we need to calculate sizes for nested classes.
+ //
+ if (c.contains_compositor_p ())
+ {
+ Particle particle (fixed, *this);
+ Compositor compositor (fixed, *this);
+ Traversal::ContainsCompositor contains_compositor;
+ Traversal::ContainsParticle contains_particle;
+
+ contains_compositor >> compositor;
+
+ contains_particle >> compositor >> contains_particle;
+ contains_particle >> particle;
+
+ Complex::contains_compositor (c, contains_compositor);
+ }
+
+ // Check attributes.
+ //
+ if (fixed)
+ {
+ Attribute attr (fixed, *this);
+ Traversal::Names names (attr);
+
+ Complex::names (c, names);
+ }
+
+ // Check for custom data.
+ //
+ if (fixed)
+ {
+ if (custom_data_.find (c.name ()) != custom_data_.end ())
+ fixed = false;
+ }
+
+ // If we recursed then we should have the value already set.
+ //
+ if (!test (c))
+ set (c, fixed);
+
+ ctx.remove ("recurse");
+ }
+ }
+
+ private:
+ TypeSet& custom_data_;
+ Boolean stl;
+ };
+
+ struct FundType : Traversal::AnyType,
+ Traversal::AnySimpleType,
+
+ Traversal::Fundamental::Byte,
+ Traversal::Fundamental::UnsignedByte,
+ Traversal::Fundamental::Short,
+ Traversal::Fundamental::UnsignedShort,
+ Traversal::Fundamental::Int,
+ Traversal::Fundamental::UnsignedInt,
+ Traversal::Fundamental::Long,
+ Traversal::Fundamental::UnsignedLong,
+ Traversal::Fundamental::Integer,
+ Traversal::Fundamental::NonPositiveInteger,
+ Traversal::Fundamental::NonNegativeInteger,
+ Traversal::Fundamental::PositiveInteger,
+ Traversal::Fundamental::NegativeInteger,
+
+ Traversal::Fundamental::Boolean,
+
+ Traversal::Fundamental::Float,
+ Traversal::Fundamental::Double,
+ Traversal::Fundamental::Decimal,
+
+ Traversal::Fundamental::String,
+ Traversal::Fundamental::NormalizedString,
+ Traversal::Fundamental::Token,
+ Traversal::Fundamental::Name,
+ Traversal::Fundamental::NameToken,
+ Traversal::Fundamental::NameTokens,
+ Traversal::Fundamental::NCName,
+ Traversal::Fundamental::Language,
+
+ Traversal::Fundamental::QName,
+
+ Traversal::Fundamental::Id,
+ Traversal::Fundamental::IdRef,
+ Traversal::Fundamental::IdRefs,
+
+ Traversal::Fundamental::AnyURI,
+
+ Traversal::Fundamental::Base64Binary,
+ Traversal::Fundamental::HexBinary,
+
+ Traversal::Fundamental::Date,
+ Traversal::Fundamental::DateTime,
+ Traversal::Fundamental::Duration,
+ Traversal::Fundamental::Day,
+ Traversal::Fundamental::Month,
+ Traversal::Fundamental::MonthDay,
+ Traversal::Fundamental::Year,
+ Traversal::Fundamental::YearMonth,
+ Traversal::Fundamental::Time,
+
+ Traversal::Fundamental::Entity,
+ Traversal::Fundamental::Entities
+
+ {
+ FundType (Boolean stl_)
+ : stl (stl_)
+ {
+ }
+
+ // anyType & anySimpleType.
+ //
+ virtual Void
+ traverse (SemanticGraph::AnyType& t)
+ {
+ set (t, true);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnySimpleType& t)
+ {
+ set (t, true);
+ }
+
+ // Boolean.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Boolean& t)
+ {
+ set (t, true);
+ }
+
+ // Integral types.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Byte& t)
+ {
+ set (t, true);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedByte& t)
+ {
+ set (t, true);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Short& t)
+ {
+ set (t, true);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedShort& t)
+ {
+ set (t, true);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Int& t)
+ {
+ set (t, true);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedInt& t)
+ {
+ set (t, true);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Long& t)
+ {
+ set (t, true);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedLong& t)
+ {
+ set (t, true);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Integer& t)
+ {
+ set (t, true);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonPositiveInteger& t)
+ {
+ set (t, true);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonNegativeInteger& t)
+ {
+ set (t, true);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::PositiveInteger& t)
+ {
+ set (t, true);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NegativeInteger& t)
+ {
+ set (t, true);
+ }
+
+ // Floats.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Float& t)
+ {
+ set (t, true);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Double& t)
+ {
+ set (t, true);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Decimal& t)
+ {
+ set (t, true);
+ }
+
+ // Strings.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::String& t)
+ {
+ set (t, stl);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NormalizedString& t)
+ {
+ set (t, stl);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Token& t)
+ {
+ set (t, stl);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameToken& t)
+ {
+ set (t, stl);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameTokens& t)
+ {
+ set (t, false);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Name& t)
+ {
+ set (t, stl);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NCName& t)
+ {
+ set (t, stl);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Language& t)
+ {
+ set (t, stl);
+ }
+
+
+ // Qualified name.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::QName& t)
+ {
+ set (t, stl);
+ }
+
+
+ // ID/IDREF.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Id& t)
+ {
+ set (t, stl);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRef& t)
+ {
+ set (t, stl);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRefs& t)
+ {
+ set (t, false);
+ }
+
+ // URI.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::AnyURI& t)
+ {
+ set (t, stl);
+ }
+
+ // Binary.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Base64Binary& t)
+ {
+ set (t, false);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::HexBinary& t)
+ {
+ set (t, false);
+ }
+
+
+ // Date/time.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Date& t)
+ {
+ set (t, true);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::DateTime& t)
+ {
+ set (t, true);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Duration& t)
+ {
+ set (t, true);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Day& t)
+ {
+ set (t, true);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Month& t)
+ {
+ set (t, true);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::MonthDay& t)
+ {
+ set (t, true);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Year& t)
+ {
+ set (t, true);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::YearMonth& t)
+ {
+ set (t, true);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Time& t)
+ {
+ set (t, true);
+ }
+
+ // Entity.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entity& t)
+ {
+ set (t, stl);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entities& t)
+ {
+ set (t, false);
+ }
+
+ private:
+ Boolean stl;
+ };
+
+ // Go into sourced/included/imported schemas while making sure
+ // we don't process the same stuff more than once.
+ //
+ struct Uses: Traversal::Sources,
+ Traversal::Includes,
+ Traversal::Imports
+ {
+ virtual Void
+ traverse (SemanticGraph::Sources& sr)
+ {
+ SemanticGraph::Schema& s (sr.schema ());
+
+ if (!s.context ().count ("cxx-hybrid-size-processor-seen"))
+ {
+ s.context ().set ("cxx-hybrid-size-processor-seen", true);
+ Traversal::Sources::traverse (sr);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Includes& i)
+ {
+ SemanticGraph::Schema& s (i.schema ());
+
+ if (!s.context ().count ("cxx-hybrid-size-processor-seen"))
+ {
+ s.context ().set ("cxx-hybrid-size-processor-seen", true);
+ Traversal::Includes::traverse (i);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Imports& i)
+ {
+ SemanticGraph::Schema& s (i.schema ());
+
+ if (!s.context ().count ("cxx-hybrid-size-processor-seen"))
+ {
+ s.context ().set ("cxx-hybrid-size-processor-seen", true);
+ Traversal::Imports::traverse (i);
+ }
+ }
+ };
+
+ Void
+ process_impl (CLI::Options const& ops,
+ SemanticGraph::Schema& tu,
+ SemanticGraph::Path const&)
+ {
+ Boolean stl (!ops.value<CLI::no_stl> ());
+
+ // Root schema in the file-per-type mode is just a bunch
+ // of includes without a namespace.
+ //
+ SemanticGraph::Schema::NamesIterator i (tu.names_begin ());
+
+ if (i != tu.names_end () &&
+ i->named ().name () == L"http://www.w3.org/2001/XMLSchema")
+ {
+ // XML Schema namespace.
+ //
+ Traversal::Schema schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+ FundType fund_type (stl);
+
+ schema >> schema_names >> ns >> ns_names >> fund_type;
+
+ schema.dispatch (tu);
+ }
+ else
+ {
+ // Pass one - assign sizes to fundamental types.
+ //
+ {
+ Traversal::Schema schema;
+ Traversal::Implies implies;
+ Traversal::Schema xs_schema;
+
+ schema >> implies >> xs_schema;
+
+ Traversal::Names xs_schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+ FundType fund_type (stl);
+
+ xs_schema >> xs_schema_names >> ns >> ns_names >> fund_type;
+
+ schema.dispatch (tu);
+ }
+
+ // Note that we check first if this schema has already been
+ // processed which may happen in the file-per-type compilation
+ // mode.
+ //
+ if (!tu.context ().count ("cxx-hybrid-size-processor-seen"))
+ {
+ // Prepare a set of types with custom data. Here we are
+ // only interested in detecting global types. If a type
+ // has a nested compositor type which has custom data
+ // then the type itself will automatically be variable
+ // size.
+ //
+ TypeSet custom_data_types;
+
+ {
+ typedef Cult::Containers::Vector<NarrowString> CustomData;
+ CustomData const& cd (ops.value<CLI::custom_data> ());
+
+ for (CustomData::ConstIterator i (cd.begin ());
+ i != cd.end (); ++i)
+ {
+ String n (*i);
+ custom_data_types.insert (String (n, 0, n.find (L"::")));
+ }
+ }
+
+ Traversal::Schema schema;
+ Uses uses;
+
+ schema >> uses >> schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+ Type type (custom_data_types, stl);
+
+ schema >> schema_names >> ns >> ns_names >> type;
+
+ // Some twisted schemas do recusive self-inclusion.
+ //
+ tu.context ().set ("cxx-hybrid-size-processor-seen", true);
+
+ schema.dispatch (tu);
+ }
+ }
+ }
+ }
+
+ Void TreeSizeProcessor::
+ process (CLI::Options const& ops,
+ SemanticGraph::Schema& tu,
+ SemanticGraph::Path const& file)
+ {
+ process_impl (ops, tu, file);
+ }
+ }
+}
diff --git a/xsde/cxx/hybrid/tree-size-processor.hxx b/xsde/cxx/hybrid/tree-size-processor.hxx
new file mode 100644
index 0000000..130451f
--- /dev/null
+++ b/xsde/cxx/hybrid/tree-size-processor.hxx
@@ -0,0 +1,32 @@
+// file : xsde/cxx/hybrid/tree-size-processor.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CXX_HYBRID_TREE_SIZE_PROCESSOR_HXX
+#define CXX_HYBRID_TREE_SIZE_PROCESSOR_HXX
+
+#include <cult/types.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+
+#include <cxx/hybrid/cli.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ using namespace Cult::Types;
+
+ class TreeSizeProcessor
+ {
+ public:
+ Void
+ process (CLI::Options const& options,
+ XSDFrontend::SemanticGraph::Schema&,
+ XSDFrontend::SemanticGraph::Path const& file);
+ };
+ }
+}
+
+#endif // CXX_HYBRID_TREE_SIZE_PROCESSOR_HXX
diff --git a/xsde/cxx/hybrid/tree-source.cxx b/xsde/cxx/hybrid/tree-source.cxx
new file mode 100644
index 0000000..d6c3672
--- /dev/null
+++ b/xsde/cxx/hybrid/tree-source.cxx
@@ -0,0 +1,1672 @@
+// file : xsd/cxx/hybrid/tree-source.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/hybrid/tree-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ namespace
+ {
+ struct ChoiceParticle: Traversal::Element,
+ Traversal::Compositor,
+ Context
+ {
+ enum Action
+ {
+ alloc,
+ free,
+ copy,
+ assign
+ };
+
+ ChoiceParticle (Context& c, Action action)
+ : Context (c),
+ action_ (action),
+ var_ (c, TypeName::var),
+ delete_ (c, TypeOps::delete_)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ SemanticGraph::Type& t (e.type ());
+
+ Boolean fund (false);
+ {
+ FundamentalType test (fund);
+ test.dispatch (t);
+ }
+
+ // Detect cases where we don't need to generate anything.
+ //
+ if (fund)
+ {
+ switch (action_)
+ {
+ case alloc:
+ {
+ if (e.max () == 1 && e.min () == 1)
+ return;
+
+ break;
+ }
+ case free:
+ {
+ if (e.max () == 1)
+ return;
+
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ String const& member (emember (e));
+ String const& umember (
+ emember (e.contained_particle ().compositor ()));
+
+ os << "case " << etag (e) << ":"
+ << "{";
+
+ switch (action_)
+ {
+ case alloc:
+ {
+ if (e.max () != 1)
+ {
+ os << "new (&this->" << umember << "." << member << ") " <<
+ esequence (e) << ";";
+ }
+ else
+ {
+ if (fixed_length (t))
+ {
+ if (!fund)
+ {
+ os << "new (&this->" << umember << "." << member << ") ";
+ var_.dispatch (t);
+ os << ";";
+ }
+
+ if (e.min () == 0)
+ {
+ os << "this->" << umember << "." << member <<
+ ".data_[sizeof (";
+ var_.dispatch (t);
+ os << ")] = false;";
+ }
+ }
+ else
+ os << "this->" << umember << "." << member << " = 0;";
+ }
+
+ break;
+ }
+ case free:
+ {
+ if (e.max () != 1)
+ {
+ String const& sequence (esequence (e));
+
+ os << "typedef " << sequence << " _dtor;"
+ << "reinterpret_cast< " << sequence << "& > (this->" <<
+ umember << "." << member << ").~_dtor ();";
+ }
+ else
+ {
+ if (fixed_length (t))
+ {
+ os << "typedef ";
+ var_.dispatch (t);
+ os << " _dtor;";
+
+ os << "reinterpret_cast< ";
+ var_.dispatch (t);
+ os << "& > (this->" << umember << "." << member << ")."
+ << "~_dtor ();";
+ }
+ else
+ {
+ delete_.dispatch (t);
+ os << " this->" << umember << "." << member << ";";
+ }
+ }
+
+ break;
+ }
+ case copy:
+ {
+ // Here we only need to handle the fixed-length situation.
+ //
+ if (fund)
+ {
+ // Use POD copying.
+ //
+ os << "this->" << umember << "." << member << " = x." <<
+ umember << "." << member << ";";
+ }
+ else
+ {
+ if (e.min () == 0)
+ {
+ os << "this->" << umember << "." << member <<
+ ".data_[sizeof (";
+ var_.dispatch (t);
+ os << ")] = x." << umember << "." << member <<
+ ".data_[sizeof (";
+ var_.dispatch (t);
+ os << ")];"
+ << "if (this->" << umember << "." << member <<
+ ".data_[sizeof (";
+ var_.dispatch (t);
+ os << ")])" << endl;
+ }
+
+ os << "new (&this->" << umember << "." << member << ") ";
+ var_.dispatch (t);
+ os << " (reinterpret_cast< const ";
+ var_.dispatch (t);
+ os << "& > (x." << umember << "." << member << "));";
+ }
+
+ break;
+ }
+ case assign:
+ {
+ // Here we only need to handle the fixed-length situation.
+ //
+ if (fund)
+ {
+ // Use POD assignment.
+ //
+ os << "this->" << umember << "." << member << " = x." <<
+ umember << "." << member << ";";
+ }
+ else
+ {
+ if (e.min () == 0)
+ {
+ os << "this->" << umember << "." << member <<
+ ".data_[sizeof (";
+ var_.dispatch (t);
+ os << ")] = x." << umember << "." << member <<
+ ".data_[sizeof (";
+ var_.dispatch (t);
+ os << ")];"
+ << "if (this->" << umember << "." << member <<
+ ".data_[sizeof (";
+ var_.dispatch (t);
+ os << ")])" << endl;
+ }
+
+ os << "reinterpret_cast< ";
+ var_.dispatch (t);
+ os << "& > (this->" << umember << "." << member << ") = " <<
+ "reinterpret_cast< const ";
+ var_.dispatch (t);
+ os << "& > (x." << umember << "." << member << ");";
+ }
+
+ break;
+ }
+ }
+
+ os << "break;"
+ << "}";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Compositor& c)
+ {
+ String const& member (emember (c));
+ String const& umember (
+ emember (c.contained_particle ().compositor ()));
+
+ os << "case " << etag (c) << ":"
+ << "{";
+
+ switch (action_)
+ {
+ case alloc:
+ {
+ if (c.max () != 1)
+ {
+ os << "new (&this->" << umember << "." << member << ") " <<
+ esequence (c) << ";";
+ }
+ else
+ {
+ if (fixed_length (c))
+ {
+ String const& type (etype (c));
+
+ os << "new (&this->" << umember << "." << member << ") " <<
+ type << ";";
+
+ if (c.min () == 0)
+ os << "this->" << umember << "." << member <<
+ ".data_[sizeof (" << type << ")] = false;";
+ }
+ else
+ os << "this->" << umember << "." << member << " = 0;";
+ }
+
+ break;
+ }
+ case free:
+ {
+ if (c.max () != 1)
+ {
+ String const& sequence (esequence (c));
+
+ os << "typedef " << sequence << " _dtor;"
+ << "reinterpret_cast< " << sequence << "& > (this->" <<
+ umember << "." << member << ").~_dtor ();";
+ }
+ else
+ {
+ if (fixed_length (c))
+ {
+ String const& type (etype (c));
+
+ os << "reinterpret_cast< " << type << "& > (this->" <<
+ umember << "." << member << ").~" << type << " ();";
+ }
+ else
+ os << "delete this->" << umember << "." << member << ";";
+ }
+
+ break;
+ }
+ case copy:
+ {
+ // Here we only need to handle the fixed-length situation.
+ //
+ String const& type (etype (c));
+
+ if (c.min () == 0)
+ {
+ os << "this->" << umember << "." << member <<
+ ".data_[sizeof (" << type << ")] = x." << umember <<
+ "." << member << ".data_[sizeof (" << type << ")];"
+ << "if (this->" << umember << "." << member <<
+ ".data_[sizeof (" << type << ")])" << endl;
+ }
+
+ os << "new (&this->" << umember << "." << member << ") " <<
+ type << " (reinterpret_cast< const " << type << "& > (x." <<
+ umember << "." << member << "));";
+
+ break;
+ }
+ case assign:
+ {
+ // Here we only need to handle the fixed-length situation.
+ //
+ String const& type (etype (c));
+
+ if (c.min () == 0)
+ {
+ os << "this->" << umember << "." << member <<
+ ".data_[sizeof (" << type << ")] = x." << umember <<
+ "." << member << ".data_[sizeof (" << type << ")];"
+ << "if (this->" << umember << "." << member <<
+ ".data_[sizeof (" << type << ")])" << endl;
+ }
+
+ os << "reinterpret_cast< " << type << "& > (this->" <<
+ umember << "." << member << ") = " <<
+ "reinterpret_cast< const " << type << "& > (x." <<
+ umember << "." << member << ");";
+
+ break;
+ }
+ }
+
+ os << "break;"
+ << "}";
+ }
+
+ private:
+ Action action_;
+ TypeName var_;
+ TypeOps delete_;
+ };
+
+ //
+ // Functions.
+ //
+
+ struct ChoiceFunc: Traversal::Choice, Context
+ {
+ ChoiceFunc (Context& c, Boolean in_choice)
+ : Context (c),
+ in_choice_ (in_choice),
+ particle_free_ (c, ChoiceParticle::free),
+ particle_alloc_ (c, ChoiceParticle::alloc)
+ {
+ contains_free_ >> particle_free_;
+ contains_alloc_ >> particle_alloc_;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ if (!in_choice_ && c.max () == 1 && c.min () == 1)
+ {
+ String const& arm_tag (earm_tag (c));
+ String const& arm_member (earm_member (c));
+ UnsignedLong bad_tag (arm_tag_count (c));
+
+ // void
+ // arm (arm_tag)
+ //
+ os << "void " << scope (c) << "::" << endl
+ << earm (c) << " (" << arm_tag << " x)"
+ << "{"
+ << "if (this->" << arm_member << " == x)" << endl
+ << "return;"
+ << endl
+ << "switch (this->" << arm_member << ")"
+ << "{";
+
+ Choice::contains (c, contains_free_);
+
+ os << "default:" << endl
+ << "break;"
+ << "}"
+ << "this->" << arm_member << " = " <<
+ arm_tag << " (" << bad_tag << ");"
+ << endl
+ << "switch (x)"
+ << "{";
+
+ Choice::contains (c, contains_alloc_);
+
+ os << "default:" << endl
+ << "break;"
+ << "}"
+ << "this->" << arm_member << " = x;"
+ << "}";
+ }
+ }
+
+ private:
+ Boolean in_choice_;
+
+ ChoiceParticle particle_free_;
+ Traversal::ContainsParticle contains_free_;
+
+ ChoiceParticle particle_alloc_;
+ Traversal::ContainsParticle contains_alloc_;
+ };
+
+ struct SequenceFunc: Traversal::Sequence, Context
+ {
+ SequenceFunc (Context& c, Boolean in_choice)
+ : Context (c), in_choice_ (in_choice)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ // When sequence is in choice we generate nested class even
+ // for min == max == 1.
+ //
+ if (!in_choice_ && s.max () == 1 && s.min () == 1)
+ Sequence::contains (s);
+ }
+
+ private:
+ Boolean in_choice_;
+ };
+
+ //
+ // C-tor initialization.
+ //
+
+ struct AttributeCtor: Traversal::Attribute, Context
+ {
+ AttributeCtor (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ Boolean fl (fixed_length (a.type ()));
+
+ if (!fl)
+ os << "this->" << emember (a) << " = 0;";
+
+ if (fl && a.optional ())
+ os << "this->" << epresent_member (a) << " = false;";
+ }
+ };
+
+
+ struct ElementCtor: Traversal::Element, Context
+ {
+ ElementCtor (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (e.max () == 1)
+ {
+ Boolean fl (fixed_length (e.type ()));
+
+ if (!fl)
+ os << "this->" << emember (e) << " = 0;";
+
+ if (fl && e.min () == 0)
+ os << "this->" << epresent_member (e) << " = false;";
+ }
+ }
+ };
+
+ struct AllCtor: Traversal::All, Context
+ {
+ AllCtor (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ // For the all compositor, maxOccurs=1 and minOccurs={0,1}
+ // and it can only contain particles.
+ //
+ if (a.min () == 0)
+ {
+ if (fixed_length (a))
+ os << "this->" << epresent_member (a) << " = false;";
+ else
+ os << "this->" << emember (a) << " = 0;";
+ }
+ else
+ All::contains (a);
+ }
+ };
+
+ struct ChoiceInSequenceCtor: Traversal::Choice, Context
+ {
+ ChoiceInSequenceCtor (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ if (c.max () == 1)
+ {
+ if (c.min () == 0)
+ {
+ if (fixed_length (c))
+ os << "this->" << epresent_member (c) << " = false;";
+ else
+ os << "this->" << emember (c) << " = 0;";
+ }
+ else
+ {
+ os << "this->" << earm_member (c) << " = " <<
+ earm_tag (c) << " (" << arm_tag_count (c) << ");";
+ }
+ }
+ }
+ };
+
+ struct SequenceInSequenceCtor: Traversal::Sequence, Context
+ {
+ SequenceInSequenceCtor (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ if (s.max () == 1)
+ {
+ if (s.min () == 0)
+ {
+ if (fixed_length (s))
+ os << "this->" << epresent_member (s) << " = false;";
+ else
+ os << "this->" << emember (s) << " = 0;";
+ }
+ else
+ Sequence::contains (s);
+ }
+ }
+ };
+
+ //
+ // D-tor cleanup.
+ //
+
+ struct AttributeDtor: Traversal::Attribute, Context
+ {
+ AttributeDtor (Context& c)
+ : Context (c), delete_ (c, TypeOps::delete_)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ SemanticGraph::Type& t (a.type ());
+
+ if (!fixed_length (t))
+ {
+ delete_.dispatch (t);
+ os << " this->" << emember (a) << ";";
+ }
+ }
+
+ private:
+ TypeOps delete_;
+ };
+
+
+ struct ElementDtor: Traversal::Element, Context
+ {
+ ElementDtor (Context& c)
+ : Context (c), delete_ (c, TypeOps::delete_)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (e.max () == 1)
+ {
+ SemanticGraph::Type& t (e.type ());
+
+ if (!fixed_length (t))
+ {
+ delete_.dispatch (t);
+ os << " this->" << emember (e) << ";";
+ }
+ }
+ }
+
+ private:
+ TypeOps delete_;
+ };
+
+ struct AllDtor: Traversal::All, Context
+ {
+ AllDtor (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ // For the all compositor, maxOccurs=1 and minOccurs={0,1}
+ // and it can only contain particles.
+ //
+ if (a.min () == 0)
+ {
+ if (!fixed_length (a))
+ os << "delete this->" << emember (a) << ";";
+ }
+ else
+ All::contains (a);
+ }
+ };
+
+ struct ChoiceInSequenceDtor: Traversal::Choice, Context
+ {
+ ChoiceInSequenceDtor (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ if (c.max () == 1)
+ {
+ if (c.min () == 0)
+ {
+ if (!fixed_length (c))
+ os << "delete this->" << emember (c) << ";";
+ }
+ else
+ {
+ os << "this->" << earm (c) << " (" <<
+ earm_tag (c) << " (" << arm_tag_count (c) << "));";
+ }
+ }
+ }
+ };
+
+ struct SequenceInSequenceDtor: Traversal::Sequence, Context
+ {
+ SequenceInSequenceDtor (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ if (s.max () == 1)
+ {
+ if (s.min () == 0)
+ {
+ if (!fixed_length (s))
+ os << "delete this->" << emember (s) << ";";
+ }
+ else
+ Sequence::contains (s);
+ }
+ }
+ };
+
+ //
+ // Copy c-tor.
+ //
+
+ struct AttributeCopy: Traversal::Attribute, Context
+ {
+ AttributeCopy (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ String const& member (emember (a));
+
+ if (a.optional ())
+ {
+ String const& present_member (epresent_member (a));
+
+ os << "this->" << present_member << " = x." << present_member << ";"
+ << "if (this->" << present_member << ")" << endl;
+ }
+
+ os << "this->" << member << " = x." << member << ";";
+ }
+ };
+
+ struct ElementCopy: Traversal::Element, Context
+ {
+ ElementCopy (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ String const& member (emember (e));
+
+ if (e.min () == 0)
+ {
+ String const& present_member (epresent_member (e));
+
+ os << "this->" << present_member << " = x." << present_member << ";"
+ << "if (this->" << present_member << ")" << endl;
+ }
+
+ os << "this->" << member << " = x." << member << ";";
+ }
+ };
+
+ struct AllCopy: Traversal::All, Context
+ {
+ AllCopy (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ if (a.min () == 0)
+ {
+ String const& member (emember (a));
+ String const& present_member (epresent_member (a));
+
+ os << "this->" << present_member << " = x." << present_member << ";"
+ << "if (this->" << present_member << ")" << endl
+ << "this->" << member << " = x." << member << ";";
+ }
+ else
+ All::contains (a);
+ }
+ };
+
+ struct ChoiceInSequenceCopy: Traversal::Choice, Context
+ {
+ ChoiceInSequenceCopy (Context& c)
+ : Context (c), particle_copy_ (c, ChoiceParticle::copy)
+ {
+ contains_copy_ >> particle_copy_;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ if (c.min () == 0)
+ {
+ String const& member (emember (c));
+ String const& present_member (epresent_member (c));
+
+ os << "this->" << present_member << " = x." << present_member << ";"
+ << "if (this->" << present_member << ")" << endl
+ << "this->" << member << " = x." << member << ";";
+ }
+ else
+ {
+ String const& arm_member (earm_member (c));
+
+ os << "this->" << arm_member << " = x." << arm_member << ";"
+ << "switch (this->" << arm_member << ")"
+ << "{";
+
+ Choice::contains (c, contains_copy_);
+
+ os << "default:" << endl
+ << "break;"
+ << "}";
+ }
+ }
+
+ private:
+ ChoiceParticle particle_copy_;
+ Traversal::ContainsParticle contains_copy_;
+ };
+
+ struct SequenceInSequenceCopy: Traversal::Sequence, Context
+ {
+ SequenceInSequenceCopy (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ if (s.min () == 0)
+ {
+ String const& member (emember (s));
+ String const& present_member (epresent_member (s));
+
+ os << "this->" << present_member << " = x." << present_member << ";"
+ << "if (this->" << present_member << ")" << endl
+ << "this->" << member << " = x." << member << ";";
+ }
+ else
+ Sequence::contains (s);
+ }
+ };
+
+ //
+ // Assign c-tor.
+ //
+
+ struct AttributeAssign: Traversal::Attribute, Context
+ {
+ AttributeAssign (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ String const& member (emember (a));
+
+ if (a.optional ())
+ {
+ String const& present_member (epresent_member (a));
+
+ os << "this->" << present_member << " = x." << present_member << ";"
+ << "if (this->" << present_member << ")" << endl;
+ }
+
+ os << "this->" << member << " = x." << member << ";";
+ }
+ };
+
+ struct ElementAssign: Traversal::Element, Context
+ {
+ ElementAssign (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ String const& member (emember (e));
+
+ if (e.min () == 0)
+ {
+ String const& present_member (epresent_member (e));
+
+ os << "this->" << present_member << " = x." << present_member << ";"
+ << "if (this->" << present_member << ")" << endl;
+ }
+
+ os << "this->" << member << " = x." << member << ";";
+ }
+ };
+
+ struct AllAssign: Traversal::All, Context
+ {
+ AllAssign (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ if (a.min () == 0)
+ {
+ String const& member (emember (a));
+ String const& present_member (epresent_member (a));
+
+ os << "this->" << present_member << " = x." << present_member << ";"
+ << "if (this->" << present_member << ")" << endl
+ << "this->" << member << " = x." << member << ";";
+ }
+ else
+ All::contains (a);
+ }
+ };
+
+ struct ChoiceInSequenceAssign: Traversal::Choice, Context
+ {
+ ChoiceInSequenceAssign (Context& c)
+ : Context (c), particle_assign_ (c, ChoiceParticle::assign)
+ {
+ contains_assign_ >> particle_assign_;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ if (c.min () == 0)
+ {
+ String const& member (emember (c));
+ String const& present_member (epresent_member (c));
+
+ os << "this->" << present_member << " = x." << present_member << ";"
+ << "if (this->" << present_member << ")" << endl
+ << "this->" << member << " = x." << member << ";";
+ }
+ else
+ {
+ String const& arm_member (earm_member (c));
+
+ os << "this->" << earm (c) << " (x." << arm_member << ");"
+ << "switch (this->" << arm_member << ")"
+ << "{";
+
+ Choice::contains (c, contains_assign_);
+
+ os << "default:" << endl
+ << "break;"
+ << "}";
+ }
+ }
+
+ private:
+ ChoiceParticle particle_assign_;
+ Traversal::ContainsParticle contains_assign_;
+ };
+
+ struct SequenceInSequenceAssign: Traversal::Sequence, Context
+ {
+ SequenceInSequenceAssign (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ if (s.min () == 0)
+ {
+ String const& member (emember (s));
+ String const& present_member (epresent_member (s));
+
+ os << "this->" << present_member << " = x." << present_member << ";"
+ << "if (this->" << present_member << ")" << endl
+ << "this->" << member << " = x." << member << ";";
+ }
+ else
+ Sequence::contains (s);
+ }
+ };
+
+ //
+ // Nested classes.
+ //
+
+ struct All: Traversal::All, Context
+ {
+ All (Context& c,
+ Traversal::ContainsParticle& contains_ctor,
+ Traversal::ContainsParticle& contains_dtor,
+ Traversal::ContainsParticle& contains_copy,
+ Traversal::ContainsParticle& contains_assign)
+ : Context (c),
+ contains_ctor_ (contains_ctor),
+ contains_dtor_ (contains_dtor),
+ contains_copy_ (contains_copy),
+ contains_assign_ (contains_assign)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ // For the all compositor, maxOccurs=1 and minOccurs={0,1}
+ // and it can only contain particles.
+ //
+ if (a.min () == 0)
+ {
+ String const& type (etype (a));
+ String const& scope (Context::scope (a));
+
+ // c-tor
+ //
+ os << scope << "::" << type << "::" << endl
+ << type << " ()"
+ << "{";
+
+ All::contains (a, contains_ctor_);
+
+ os << "}";
+
+ // d-tor
+ //
+ os << scope << "::" << type << "::" << endl
+ << "~" << type << " ()"
+ << "{";
+
+ All::contains (a, contains_dtor_);
+
+ os << "}";
+
+ if (fixed_length (a))
+ {
+ // copy c-tor
+ //
+ os << scope << "::" << type << "::" << endl
+ << type << " (const " << type << "& x)"
+ << "{"
+ << "XSDE_UNUSED (x);";
+
+ All::contains (a, contains_copy_);
+
+ os << "}";
+
+ // operator=
+ //
+ os << scope << "::" << type << "& " << scope << "::" <<
+ type << "::" << endl
+ << "operator= (const " << type << "& x)"
+ << "{"
+ << "XSDE_UNUSED (x);";
+
+ All::contains (a, contains_assign_);
+
+ os << "return *this;"
+ << "}";
+ }
+ }
+ }
+
+ private:
+ Traversal::ContainsParticle& contains_ctor_;
+ Traversal::ContainsParticle& contains_dtor_;
+ Traversal::ContainsParticle& contains_copy_;
+ Traversal::ContainsParticle& contains_assign_;
+ };
+
+ struct Choice: Traversal::Choice, Context
+ {
+ Choice (Context& c,
+ Boolean in_choice,
+ Traversal::ContainsParticle& contains_func)
+ : Context (c),
+ in_choice_ (in_choice),
+ contains_func_ (contains_func),
+ particle_free_ (c, ChoiceParticle::free),
+ particle_alloc_ (c, ChoiceParticle::alloc),
+ particle_copy_ (c, ChoiceParticle::copy),
+ particle_assign_ (c, ChoiceParticle::assign)
+ {
+ contains_free_ >> particle_free_;
+ contains_alloc_ >> particle_alloc_;
+ contains_copy_ >> particle_copy_;
+ contains_assign_ >> particle_assign_;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ // When choice is in choice we generate nested class even
+ // for min == max == 1.
+ //
+ if (in_choice_ || c.max () != 1 || c.min () == 0)
+ {
+ String const& type (etype (c));
+ String const& arm (earm (c));
+ String const& arm_tag (earm_tag (c));
+ String const& arm_member (earm_member (c));
+ UnsignedLong bad_tag (arm_tag_count (c));
+
+ String const& scope (Context::scope (c));
+
+ // c-tor ()
+ //
+ os << scope << "::" << type << "::" << endl
+ << type << " ()"
+ << "{"
+ << "this->" << arm_member << " = " <<
+ arm_tag << " (" << bad_tag << ");"
+ << "}";
+
+ // d-tor ()
+ //
+ os << scope << "::" << type << "::" << endl
+ << "~" << type << " ()"
+ << "{"
+ << "this->" << arm << " (" <<
+ arm_tag << " (" << bad_tag << "));"
+ << "}";
+
+ if (fixed_length (c))
+ {
+ // copy c-tor
+ //
+ os << scope << "::" << type << "::" << endl
+ << type << " (const " << type << "& x)"
+ << "{"
+ << "this->" << arm_member << " = x." << arm_member << ";"
+ << "switch (this->" << arm_member << ")"
+ << "{";
+
+ Choice::contains (c, contains_copy_);
+
+ os << "default:" << endl
+ << "break;"
+ << "}"
+ << "}";
+
+ // operator=
+ //
+ os << scope << "::" << type << "& " << scope << "::" <<
+ type << "::" << endl
+ << "operator= (const " << type << "& x)"
+ << "{"
+ << "this->" << arm << " (x." << arm_member << ");"
+ << "switch (this->" << arm_member << ")"
+ << "{";
+
+ Choice::contains (c, contains_assign_);
+
+ os << "default:" << endl
+ << "break;"
+ << "}"
+ << "return *this;"
+ << "}";
+ }
+
+ // void
+ // arm (arm_tag)
+ //
+ os << "void " << scope << "::" << type << "::" << endl
+ << arm << " (" << arm_tag << " x)"
+ << "{"
+ << "if (this->" << arm_member << " == x)" << endl
+ << "return;"
+ << endl
+ << "switch (this->" << arm_member << ")"
+ << "{";
+
+ Choice::contains (c, contains_free_);
+
+ os << "default:" << endl
+ << "break;"
+ << "}"
+ << "this->" << arm_member << " = " <<
+ arm_tag << " (" << bad_tag << ");"
+ << endl
+ << "switch (x)"
+ << "{";
+
+ Choice::contains (c, contains_alloc_);
+
+ os << "default:" << endl
+ << "break;"
+ << "}"
+ << "this->" << arm_member << " = x;"
+ << "}";
+
+ Choice::contains (c, contains_func_);
+ }
+
+ Choice::contains (c);
+ }
+
+ private:
+ Boolean in_choice_;
+ Traversal::ContainsParticle& contains_func_;
+
+ ChoiceParticle particle_free_;
+ Traversal::ContainsParticle contains_free_;
+
+ ChoiceParticle particle_alloc_;
+ Traversal::ContainsParticle contains_alloc_;
+
+ ChoiceParticle particle_copy_;
+ Traversal::ContainsParticle contains_copy_;
+
+ ChoiceParticle particle_assign_;
+ Traversal::ContainsParticle contains_assign_;
+ };
+
+
+ struct Sequence: Traversal::Sequence, Context
+ {
+ Sequence (Context& c,
+ Boolean in_choice,
+ Traversal::ContainsParticle& contains_ctor,
+ Traversal::ContainsParticle& contains_dtor,
+ Traversal::ContainsParticle& contains_copy,
+ Traversal::ContainsParticle& contains_assign,
+ Traversal::ContainsParticle& contains_func)
+ : Context (c),
+ in_choice_ (in_choice),
+ contains_ctor_ (contains_ctor),
+ contains_dtor_ (contains_dtor),
+ contains_copy_ (contains_copy),
+ contains_assign_ (contains_assign),
+ contains_func_ (contains_func)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ // When sequence is in choice we generate nested class even
+ // for min == max == 1.
+ //
+ if (in_choice_ || s.max () != 1 || s.min () == 0)
+ {
+ String const& type (etype (s));
+ String const& scope (Context::scope (s));
+
+ // c-tor ()
+ //
+ os << scope << "::" << type << "::" << endl
+ << type << " ()"
+ << "{";
+
+ Sequence::contains (s, contains_ctor_);
+
+ os << "}";
+
+ // d-tor ()
+ //
+ os << scope << "::" << type << "::" << endl
+ << "~" << type << " ()"
+ << "{";
+
+ Sequence::contains (s, contains_dtor_);
+
+ os << "}";
+
+ if (fixed_length (s))
+ {
+ // copy c-tor
+ //
+ os << scope << "::" << type << "::" << endl
+ << type << " (const " << type << "& x)"
+ << "{"
+ << "XSDE_UNUSED (x);";
+
+ Sequence::contains (s, contains_copy_);
+
+ os << "}";
+
+ // operator=
+ //
+ os << scope << "::" << type << "& " << scope << "::" <<
+ type << "::" << endl
+ << "operator= (const " << type << "& x)"
+ << "{"
+ << "XSDE_UNUSED (x);";
+
+ Sequence::contains (s, contains_assign_);
+
+ os << "return *this;"
+ << "}";
+ }
+
+ Sequence::contains (s, contains_func_);
+ }
+
+ Sequence::contains (s);
+ }
+
+ private:
+ Boolean in_choice_;
+ Traversal::ContainsParticle& contains_ctor_;
+ Traversal::ContainsParticle& contains_dtor_;
+ Traversal::ContainsParticle& contains_copy_;
+ Traversal::ContainsParticle& contains_assign_;
+ Traversal::ContainsParticle& contains_func_;
+ };
+
+ struct Complex : Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c),
+ base_name_ (c, TypeName::base),
+
+ // Functions.
+ //
+ choice_in_choice_func_ (c, true),
+ choice_in_sequence_func_ (c, false),
+ sequence_in_choice_func_ (c, true),
+ sequence_in_sequence_func_ (c, false),
+
+ // C-tor initialization.
+ //
+ attribute_ctor_ (c),
+ element_ctor_ (c),
+ all_ctor_ (c),
+ choice_in_sequence_ctor_ (c),
+ sequence_in_sequence_ctor_ (c),
+
+ // D-tor cleanup.
+ //
+ attribute_dtor_ (c),
+ element_dtor_ (c),
+ all_dtor_ (c),
+ choice_in_sequence_dtor_ (c),
+ sequence_in_sequence_dtor_ (c),
+
+ // Copy.
+ //
+ attribute_copy_ (c),
+ element_copy_ (c),
+ all_copy_ (c),
+ choice_in_sequence_copy_ (c),
+ sequence_in_sequence_copy_ (c),
+
+ // Assign.
+ //
+ attribute_assign_ (c),
+ element_assign_ (c),
+ all_assign_ (c),
+ choice_in_sequence_assign_ (c),
+ sequence_in_sequence_assign_ (c),
+
+ // Nested c-tors, etc.
+ //
+ all_ (c,
+ all_contains_ctor_,
+ all_contains_dtor_,
+ all_contains_copy_,
+ all_contains_assign_),
+ choice_in_choice_ (c, true, choice_contains_func_),
+ choice_in_sequence_ (c, false, choice_contains_func_),
+ sequence_in_choice_ (
+ c,
+ true,
+ sequence_contains_ctor_,
+ sequence_contains_dtor_,
+ sequence_contains_copy_,
+ sequence_contains_assign_,
+ sequence_contains_func_),
+ sequence_in_sequence_ (
+ c,
+ false,
+ sequence_contains_ctor_,
+ sequence_contains_dtor_,
+ sequence_contains_copy_,
+ sequence_contains_assign_,
+ sequence_contains_func_)
+ {
+ // Functions.
+ //
+ sequence_in_choice_func_ >> sequence_contains_func_;
+ sequence_in_sequence_func_ >> sequence_contains_func_;
+ sequence_contains_func_ >> choice_in_sequence_func_;
+ sequence_contains_func_ >> sequence_in_sequence_func_;
+
+ choice_in_choice_func_ >> choice_contains_func_;
+ choice_in_sequence_func_ >> choice_contains_func_;
+ choice_contains_func_ >> sequence_in_choice_func_;
+ choice_contains_func_ >> choice_in_choice_func_;
+
+ contains_compositor_func_ >> choice_in_sequence_func_;
+ contains_compositor_func_ >> sequence_in_sequence_func_;
+
+ // C-tor initialization.
+ //
+ attribute_names_ctor_ >> attribute_ctor_;
+
+ all_ctor_ >> all_contains_ctor_ >> element_ctor_;
+
+ sequence_in_sequence_ctor_ >> sequence_contains_ctor_;
+ sequence_contains_ctor_ >> element_ctor_;
+ sequence_contains_ctor_ >> choice_in_sequence_ctor_;
+ sequence_contains_ctor_ >> sequence_in_sequence_ctor_;
+
+ contains_compositor_ctor_ >> all_ctor_;
+ contains_compositor_ctor_ >> choice_in_sequence_ctor_;
+ contains_compositor_ctor_ >> sequence_in_sequence_ctor_;
+
+ // D-tor cleanup.
+ //
+ attribute_names_dtor_ >> attribute_dtor_;
+
+ all_dtor_ >> all_contains_dtor_ >> element_dtor_;
+
+ sequence_in_sequence_dtor_ >> sequence_contains_dtor_;
+ sequence_contains_dtor_ >> element_dtor_;
+ sequence_contains_dtor_ >> choice_in_sequence_dtor_;
+ sequence_contains_dtor_ >> sequence_in_sequence_dtor_;
+
+ contains_compositor_dtor_ >> all_dtor_;
+ contains_compositor_dtor_ >> choice_in_sequence_dtor_;
+ contains_compositor_dtor_ >> sequence_in_sequence_dtor_;
+
+ // Copy.
+ //
+ attribute_names_copy_ >> attribute_copy_;
+
+ all_copy_ >> all_contains_copy_ >> element_copy_;
+
+ sequence_in_sequence_copy_ >> sequence_contains_copy_;
+ sequence_contains_copy_ >> element_copy_;
+ sequence_contains_copy_ >> choice_in_sequence_copy_;
+ sequence_contains_copy_ >> sequence_in_sequence_copy_;
+
+ contains_compositor_copy_ >> all_copy_;
+ contains_compositor_copy_ >> choice_in_sequence_copy_;
+ contains_compositor_copy_ >> sequence_in_sequence_copy_;
+
+ // Assign.
+ //
+ attribute_names_assign_ >> attribute_assign_;
+
+ all_assign_ >> all_contains_assign_ >> element_assign_;
+
+ sequence_in_sequence_assign_ >> sequence_contains_assign_;
+ sequence_contains_assign_ >> element_assign_;
+ sequence_contains_assign_ >> choice_in_sequence_assign_;
+ sequence_contains_assign_ >> sequence_in_sequence_assign_;
+
+ contains_compositor_assign_ >> all_assign_;
+ contains_compositor_assign_ >> choice_in_sequence_assign_;
+ contains_compositor_assign_ >> sequence_in_sequence_assign_;
+
+ // Nested c-tors, etc.
+ //
+ all_ >> all_contains_;
+
+ choice_in_choice_ >> choice_contains_;
+ choice_in_sequence_ >> choice_contains_;
+ choice_contains_ >> choice_in_choice_;
+ choice_contains_ >> sequence_in_choice_;
+
+ sequence_in_choice_ >> sequence_contains_;
+ sequence_in_sequence_ >> sequence_contains_;
+ sequence_contains_ >> choice_in_sequence_;
+ sequence_contains_ >> sequence_in_sequence_;
+
+ contains_compositor_ >> all_;
+ contains_compositor_ >> choice_in_sequence_;
+ contains_compositor_ >> sequence_in_sequence_;
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ Boolean restriction (restriction_p (c));
+
+ String name (ename (c));
+
+ os << "// " << comment (c.name ()) << endl
+ << "//" << endl
+ << endl;
+
+ // c-tor ()
+ //
+ os << name << "::" << endl
+ << name << " ()"
+ << "{";
+
+ if (!restriction)
+ {
+ Complex::names (c, attribute_names_ctor_);
+
+ if (c.contains_compositor_p ())
+ Complex::contains_compositor (c, contains_compositor_ctor_);
+ }
+
+ os << "}";
+
+
+ if (!restriction)
+ {
+ // d-tor ()
+ //
+ os << name << "::" << endl
+ << "~" << name << " ()"
+ << "{";
+
+ Complex::names (c, attribute_names_dtor_);
+
+ if (c.contains_compositor_p ())
+ Complex::contains_compositor (c, contains_compositor_dtor_);
+
+ os << "}";
+
+ if (fixed_length (c))
+ {
+ // copy c-tor
+ //
+ os << name << "::" << endl
+ << name << " (const " << name << "& x)";
+
+ if (c.inherits_p ())
+ {
+ os << endl
+ << ": ";
+ base_name_.dispatch (c.inherits ().base ());
+ os << " (x)";
+ }
+
+ os << "{"
+ << "XSDE_UNUSED (x);";
+
+ Complex::names (c, attribute_names_copy_);
+
+ if (c.contains_compositor_p ())
+ Complex::contains_compositor (c, contains_compositor_copy_);
+
+ os << "}";
+
+ // operator=
+ //
+ os << name << "& " << name << "::" << endl
+ << "operator= (const " << name << "& x)"
+ << "{"
+ << "XSDE_UNUSED (x);";
+
+ if (c.inherits_p ())
+ {
+ os << "static_cast< ";
+ base_name_.dispatch (c.inherits ().base ());
+ os << "& > (*this) = x;";
+ }
+
+ Complex::names (c, attribute_names_assign_);
+
+ if (c.contains_compositor_p ())
+ Complex::contains_compositor (c, contains_compositor_assign_);
+
+ os << "return *this;"
+ << "}";
+ }
+
+ // Functions.
+ //
+ if (c.contains_compositor_p ())
+ Complex::contains_compositor (c, contains_compositor_func_);
+
+ // Nested c-tors, etc.
+ //
+ if (c.contains_compositor_p ())
+ Complex::contains_compositor (c, contains_compositor_);
+ }
+ }
+
+ private:
+ TypeName base_name_;
+
+ // Functions.
+ //
+ ChoiceFunc choice_in_choice_func_;
+ ChoiceFunc choice_in_sequence_func_;
+ SequenceFunc sequence_in_choice_func_;
+ SequenceFunc sequence_in_sequence_func_;
+ Traversal::ContainsParticle choice_contains_func_;
+ Traversal::ContainsParticle sequence_contains_func_;
+
+ Traversal::ContainsCompositor contains_compositor_func_;
+
+ // C-tor initialization.
+ //
+ AttributeCtor attribute_ctor_;
+ Traversal::Names attribute_names_ctor_;
+
+ ElementCtor element_ctor_;
+ AllCtor all_ctor_;
+ ChoiceInSequenceCtor choice_in_sequence_ctor_;
+ SequenceInSequenceCtor sequence_in_sequence_ctor_;
+ Traversal::ContainsParticle all_contains_ctor_;
+ Traversal::ContainsParticle sequence_contains_ctor_;
+
+ Traversal::ContainsCompositor contains_compositor_ctor_;
+
+ // D-tor cleanup.
+ //
+ AttributeDtor attribute_dtor_;
+ Traversal::Names attribute_names_dtor_;
+
+ ElementDtor element_dtor_;
+ AllDtor all_dtor_;
+ ChoiceInSequenceDtor choice_in_sequence_dtor_;
+ SequenceInSequenceDtor sequence_in_sequence_dtor_;
+ Traversal::ContainsParticle all_contains_dtor_;
+ Traversal::ContainsParticle sequence_contains_dtor_;
+
+ Traversal::ContainsCompositor contains_compositor_dtor_;
+
+ // Copy.
+ //
+ AttributeCopy attribute_copy_;
+ Traversal::Names attribute_names_copy_;
+
+ ElementCopy element_copy_;
+ AllCopy all_copy_;
+ ChoiceInSequenceCopy choice_in_sequence_copy_;
+ SequenceInSequenceCopy sequence_in_sequence_copy_;
+ Traversal::ContainsParticle all_contains_copy_;
+ Traversal::ContainsParticle sequence_contains_copy_;
+
+ Traversal::ContainsCompositor contains_compositor_copy_;
+
+ // Assign.
+ //
+ AttributeAssign attribute_assign_;
+ Traversal::Names attribute_names_assign_;
+
+ ElementAssign element_assign_;
+ AllAssign all_assign_;
+ ChoiceInSequenceAssign choice_in_sequence_assign_;
+ SequenceInSequenceAssign sequence_in_sequence_assign_;
+ Traversal::ContainsParticle all_contains_assign_;
+ Traversal::ContainsParticle sequence_contains_assign_;
+
+ Traversal::ContainsCompositor contains_compositor_assign_;
+
+ // Nested c-tors, etc.
+ //
+ All all_;
+ Choice choice_in_choice_;
+ Choice choice_in_sequence_;
+ Sequence sequence_in_choice_;
+ Sequence sequence_in_sequence_;
+ Traversal::ContainsParticle all_contains_;
+ Traversal::ContainsParticle choice_contains_;
+ Traversal::ContainsParticle sequence_contains_;
+
+ Traversal::ContainsCompositor contains_compositor_;
+ };
+ }
+
+ Void
+ generate_tree_source (Context& ctx)
+ {
+ // Needed for placement new.
+ //
+ ctx.os << "#include <new>" << endl
+ << endl;
+
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+ Traversal::Names names_ns, names;
+
+ Namespace ns (ctx);
+
+ //Union union_ (ctx);
+ Complex complex (ctx);
+ //Enumeration enumeration (ctx);
+
+ schema >> sources >> schema;
+ schema >> names_ns >> ns >> names;
+
+ //names >> union_;
+ names >> complex;
+ //names >> enumeration;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+}
diff --git a/xsde/cxx/hybrid/tree-source.hxx b/xsde/cxx/hybrid/tree-source.hxx
new file mode 100644
index 0000000..7bd6b9e
--- /dev/null
+++ b/xsde/cxx/hybrid/tree-source.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/hybrid/tree-source.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_TREE_SOURCE_HXX
+#define CXX_HYBRID_TREE_SOURCE_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/hybrid/elements.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ Void
+ generate_tree_source (Context&);
+ }
+}
+
+#endif // CXX_HYBRID_TREE_SOURCE_HXX
diff --git a/xsde/cxx/hybrid/tree-type-map.cxx b/xsde/cxx/hybrid/tree-type-map.cxx
new file mode 100644
index 0000000..990d62e
--- /dev/null
+++ b/xsde/cxx/hybrid/tree-type-map.cxx
@@ -0,0 +1,248 @@
+// file : xsde/cxx/hybrid/tree-type-map.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/elements.hxx>
+#include <cxx/hybrid/tree-type-map.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/set.hxx>
+
+#include <iostream>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ namespace
+ {
+ class Context: public CXX::Context
+ {
+ public:
+ Context (CLI::Options const& ops, SemanticGraph::Schema& root)
+ : CXX::Context (std::wcerr,
+ root,
+ "name",
+ "char",
+ ops.value<CLI::include_with_brackets> (),
+ ops.value<CLI::include_prefix> (),
+ "", // export symbol
+ ops.value<CLI::namespace_map> (),
+ ops.value<CLI::namespace_regex> (),
+ ops.value<CLI::namespace_regex_trace> (),
+ ops.value<CLI::include_regex> (),
+ ops.value<CLI::include_regex_trace> (),
+ ops.value<CLI::generate_inline> (),
+ ops.value<CLI::reserved_name> ())
+ {
+ }
+
+ protected:
+ Context (Context& c)
+ : CXX::Context (c)
+ {
+ }
+ };
+
+ //
+ //
+ struct GlobalType: Traversal::Type, Context
+ {
+ GlobalType (Context& c,
+ TypeMap::Namespace* parser,
+ TypeMap::Namespace* serializer)
+ : Context (c), parser_ (parser), serializer_ (serializer)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& t)
+ {
+ String const& xn (t.name ());
+ String qn (fq_name (t));
+
+ if (parser_ != 0)
+ {
+ if (t.context ().get<Boolean> ("fixed"))
+ parser_->types_push_back (xn, qn);
+ else
+ parser_->types_push_back (xn, qn + L"*");
+ }
+
+ if (serializer_ != 0)
+ serializer_->types_push_back (xn, L"const " + qn + L"&");
+ }
+
+ private:
+ TypeMap::Namespace* parser_;
+ TypeMap::Namespace* serializer_;
+ };
+
+
+ struct Namespace: Traversal::Namespace, Context
+ {
+ Namespace (Context& c,
+ String const* hxx_name,
+ TypeMap::Namespaces* parser_map,
+ TypeMap::Namespaces* serializer_map)
+ : Context (c),
+ hxx_name_ (hxx_name),
+ parser_map_ (parser_map),
+ serializer_map_ (serializer_map)
+ {
+ }
+
+ virtual Void
+ traverse (Type& ns)
+ {
+ String include;
+
+ if (hxx_name_ != 0)
+ include = process_include_path (*hxx_name_);
+
+ String const& name (ns.name ());
+
+ if (parser_map_ != 0)
+ {
+ if (name)
+ parser_map_->push_back (TypeMap::Namespace (name));
+ else
+ parser_map_->push_back (
+ TypeMap::Namespace (TypeMap::Pattern ()));
+
+ if (include)
+ parser_map_->back ().includes_push_back (include);
+ }
+
+ if (serializer_map_ != 0)
+ {
+ if (name)
+ serializer_map_->push_back (TypeMap::Namespace (name));
+ else
+ serializer_map_->push_back (
+ TypeMap::Namespace (TypeMap::Pattern ()));
+
+ if (include)
+ serializer_map_->back ().includes_push_back (include);
+ }
+
+ GlobalType type (*this,
+ (parser_map_ ? &parser_map_->back () : 0),
+ (serializer_map_ ? &serializer_map_->back () : 0));
+
+ Traversal::Names names (type);
+ Namespace::names (ns, names);
+ }
+
+ private:
+ String const* hxx_name_;
+ TypeMap::Namespaces* parser_map_;
+ TypeMap::Namespaces* serializer_map_;
+ };
+
+ // Go into sourced/included/imported schemas while making sure
+ // we don't process the same stuff more than once.
+ //
+ struct Uses: Traversal::Sources,
+ Traversal::Includes,
+ Traversal::Imports
+ {
+ Uses (SemanticGraph::Schema& root)
+ {
+ schema_set_.insert (&root);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sources& sr)
+ {
+ SemanticGraph::Schema& s (sr.schema ());
+ SemanticGraph::Context& sc (s.context ());
+
+ if (!sc.count ("cxx-hybrid-tree-type-map-seen"))
+ {
+ sc.set ("cxx-hybrid-tree-type-map-seen", true);
+ Traversal::Sources::traverse (sr);
+ sc.remove ("cxx-hybrid-tree-type-map-seen");
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Includes& i)
+ {
+ SemanticGraph::Schema& s (i.schema ());
+
+ if (schema_set_.find (&s) == schema_set_.end ())
+ {
+ schema_set_.insert (&s);
+ Traversal::Includes::traverse (i);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Imports& i)
+ {
+ SemanticGraph::Schema& s (i.schema ());
+
+ if (schema_set_.find (&s) == schema_set_.end ())
+ {
+ schema_set_.insert (&s);
+ Traversal::Imports::traverse (i);
+ }
+ }
+
+ private:
+ Containers::Set<SemanticGraph::Schema*> schema_set_;
+ };
+ }
+
+ Void
+ generate_tree_type_map (CLI::Options const& ops,
+ XSDFrontend::SemanticGraph::Schema& tu,
+ String const& hxx_name,
+ TypeMap::Namespaces& parser_map,
+ TypeMap::Namespaces& serializer_map)
+ {
+ if (tu.names_begin ()->named ().name () !=
+ L"http://www.w3.org/2001/XMLSchema")
+ {
+ Context ctx (ops, tu);
+
+ // We don't want include in the included/imported/sources
+ // schema so split the traversal into two part.
+ //
+ Traversal::Schema schema;
+ Traversal::Schema used_schema;
+ Uses uses (tu);
+
+ schema >> uses >> used_schema >> uses;
+
+ Traversal::Names schema_names;
+ Namespace ns (
+ ctx, &hxx_name,
+ (ops.value<CLI::generate_parser> () ? &parser_map : 0),
+ (ops.value<CLI::generate_serializer> () ? &serializer_map : 0));
+
+ schema >> schema_names >> ns;
+
+ Traversal::Names used_schema_names;
+ Namespace used_ns (
+ ctx, 0,
+ (ops.value<CLI::generate_parser> () ? &parser_map : 0),
+ (ops.value<CLI::generate_serializer> () ? &serializer_map : 0));
+
+ used_schema >> used_schema_names >> used_ns;
+
+ // Some twisted schemas do recusive self-inclusion.
+ //
+ SemanticGraph::Context& tuc (tu.context ());
+
+ tuc.set ("cxx-hybrid-tree-type-map-seen", true);
+ schema.dispatch (tu);
+ tuc.remove ("cxx-hybrid-tree-type-map-seen");
+ }
+ }
+ }
+}
diff --git a/xsde/cxx/hybrid/tree-type-map.hxx b/xsde/cxx/hybrid/tree-type-map.hxx
new file mode 100644
index 0000000..e5ad7f5
--- /dev/null
+++ b/xsde/cxx/hybrid/tree-type-map.hxx
@@ -0,0 +1,32 @@
+// file : xsde/cxx/hybrid/tree-type-map.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2006-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CXX_HYBRID_TREE_TYPE_MAP_HXX
+#define CXX_HYBRID_TREE_TYPE_MAP_HXX
+
+#include <cult/types.hxx>
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <type-map/type-map.hxx>
+
+#include <cxx/hybrid/cli.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ using namespace Cult::Types;
+
+ Void
+ generate_tree_type_map (CLI::Options const& options,
+ XSDFrontend::SemanticGraph::Schema&,
+ String const& hxx_name,
+ TypeMap::Namespaces& parser_type_map,
+ TypeMap::Namespaces& serializer_type_map);
+ }
+}
+
+#endif // CXX_HYBRID_TREE_TYPE_MAP_HXX
diff --git a/xsde/cxx/hybrid/validator.cxx b/xsde/cxx/hybrid/validator.cxx
new file mode 100644
index 0000000..65dd3e2
--- /dev/null
+++ b/xsde/cxx/hybrid/validator.cxx
@@ -0,0 +1,584 @@
+// file : xsde/cxx/hybrid/validator.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/hybrid/validator.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cxx/hybrid/elements.hxx>
+
+#include <iostream>
+
+using std::wcerr;
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ namespace
+ {
+ class ValidationContext: public Context
+ {
+ public:
+ ValidationContext (SemanticGraph::Schema& root,
+ CLI::Options const& options,
+ const WarningSet& disabled_warnings,
+ Boolean& valid_)
+ : Context (std::wcerr, root, options, 0, 0, 0),
+ disabled_warnings_ (disabled_warnings),
+ disabled_warnings_all_ (false),
+ valid (valid_),
+ subst_group_warning_issued (subst_group_warning_issued_),
+ subst_group_warning_issued_ (false)
+ {
+ }
+
+ public:
+ Boolean
+ is_disabled (Char const* w)
+ {
+ return disabled_warnings_all_ ||
+ disabled_warnings_.find (w) != disabled_warnings_.end ();
+ }
+
+ public:
+ String
+ xpath (SemanticGraph::Nameable& n)
+ {
+ if (n.is_a<SemanticGraph::Namespace> ())
+ return L"<namespace-level>"; // There is a bug if you see this.
+
+ assert (n.named ());
+
+ SemanticGraph::Scope& scope (n.scope ());
+
+ if (scope.is_a<SemanticGraph::Namespace> ())
+ return n.name ();
+
+ return xpath (scope) + L"/" + n.name ();
+ }
+
+ protected:
+ ValidationContext (ValidationContext& c)
+ : Context (c),
+ disabled_warnings_ (c.disabled_warnings_),
+ disabled_warnings_all_ (c.disabled_warnings_all_),
+ valid (c.valid),
+ subst_group_warning_issued (c.subst_group_warning_issued)
+ {
+ }
+
+ protected:
+ const WarningSet& disabled_warnings_;
+ Boolean disabled_warnings_all_;
+ Boolean& valid;
+ Boolean& subst_group_warning_issued;
+ Boolean subst_group_warning_issued_;
+ };
+
+ //
+ //
+ struct Traverser : Traversal::Schema,
+ Traversal::Complex,
+ Traversal::Type,
+ Traversal::Element,
+ ValidationContext
+ {
+ Traverser (ValidationContext& c)
+ : ValidationContext (c)
+ {
+ *this >> sources_ >> *this;
+ *this >> schema_names_ >> ns_ >> names_ >> *this;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ using SemanticGraph::Schema;
+
+ traverse (static_cast<SemanticGraph::Type&> (c));
+
+ if (c.inherits_p ())
+ {
+ SemanticGraph::Type& t (c.inherits ().base ());
+
+ if (t.named () &&
+ types_.find (
+ t.scope ().name () + L"#" + t.name ()) == types_.end ())
+ {
+ // Don't worry about types that are in included/imported
+ // schemas.
+ //
+ Schema& s (dynamic_cast<Schema&> (t.scope ().scope ()));
+
+ if (&s == &schema_root || sources_p (schema_root, s))
+ {
+ valid = false;
+
+ wcerr << c.file () << ":" << c.line () << ":" << c.column ()
+ << ": error: type '" << xpath (c) << "' inherits from "
+ << "yet undefined type '" << xpath (t) << "'" << endl;
+
+ wcerr << t.file () << ":" << t.line () << ":" << t.column ()
+ << ": info: '" << xpath (t) << "' is defined here"
+ << endl;
+
+ wcerr << c.file () << ":" << c.line () << ":" << c.column ()
+ << ": info: inheritance from a yet-undefined type is "
+ << "not supported" << endl;
+
+ wcerr << c.file () << ":" << c.line () << ":" << c.column ()
+ << ": info: re-arrange your schema and try again"
+ << endl;
+ }
+ }
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& t)
+ {
+ if (t.named ())
+ {
+ types_.insert (t.scope ().name () + L"#" + t.name ());
+ }
+ }
+
+ /*
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (is_disabled ("H001"))
+ return;
+
+ if (e.substitutes_p () &&
+ !options.value<CLI::generate_polymorphic> () &&
+ !subst_group_warning_issued)
+ {
+ subst_group_warning_issued = true;
+
+ os << e.file () << ":" << e.line () << ":" << e.column ()
+ << ": warning H001: substitution groups are used but "
+ << "--generate-polymorphic was not specified" << endl;
+
+ os << e.file () << ":" << e.line () << ":" << e.column ()
+ << ": info: generated code may not be able to serialize "
+ << "some conforming instances" << endl;
+ }
+ }
+ */
+
+ // 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:
+ Containers::Set<String> types_;
+
+ Traversal::Sources sources_;
+
+ Traversal::Names schema_names_;
+ Traversal::Namespace ns_;
+
+ Traversal::Names names_;
+ };
+
+ //
+ //
+ struct AnonymousMember: protected ValidationContext
+ {
+ AnonymousMember (ValidationContext& c, Boolean& error_issued)
+ : ValidationContext (c), error_issued_ (error_issued)
+ {
+ }
+
+ Boolean
+ traverse_common (SemanticGraph::Member& m)
+ {
+ SemanticGraph::Type& t (m.type ());
+
+ if (!t.named ()
+ && !t.is_a<SemanticGraph::Fundamental::IdRef> ()
+ && !t.is_a<SemanticGraph::Fundamental::IdRefs> ())
+ {
+ if (!error_issued_)
+ {
+ valid = false;
+ error_issued_ = true;
+
+ wcerr << t.file ()
+ << ": error: anonymous types detected"
+ << endl;
+
+ wcerr << t.file ()
+ << ": info: "
+ << "anonymous types are not supported in this mapping"
+ << endl;
+
+ wcerr << t.file ()
+ << ": info: consider explicitly naming these types or "
+ << "remove the --preserve-anonymous option to "
+ << "automatically name them"
+ << endl;
+
+ if (!options.value<CLI::show_anonymous> ())
+ wcerr << t.file ()
+ << ": info: use --show-anonymous option to see these "
+ << "types" << endl;
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ private:
+ Boolean& error_issued_;
+ };
+
+ struct AnonymousElement: Traversal::Element,
+ AnonymousMember
+ {
+ AnonymousElement (ValidationContext& c, Boolean& error_issued)
+ : AnonymousMember (c, error_issued)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (traverse_common (e))
+ {
+ if (options.value<CLI::show_anonymous> ())
+ {
+ wcerr << e.file () << ":" << e.line () << ":" << e.column ()
+ << ": error: element '" << xpath (e) << "' "
+ << "is of anonymous type" << endl;
+ }
+ }
+ else
+ Traversal::Element::traverse (e);
+ }
+ };
+
+ struct AnonymousAttribute: Traversal::Attribute,
+ AnonymousMember
+ {
+ AnonymousAttribute (ValidationContext& c, Boolean& error_issued)
+ : AnonymousMember (c, error_issued)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ if (traverse_common (a))
+ {
+ if (options.value<CLI::show_anonymous> ())
+ {
+ wcerr << a.file () << ":" << a.line () << ":" << a.column ()
+ << ": error: attribute '" << xpath (a) << "' "
+ << "is of anonymous type" << endl;
+ }
+ }
+ else
+ Traversal::Attribute::traverse (a);
+ }
+ };
+
+ struct AnonymousType : Traversal::Schema,
+ Traversal::Complex,
+ ValidationContext
+ {
+ AnonymousType (ValidationContext& c)
+ : ValidationContext (c),
+ error_issued_ (false),
+ element_ (c, error_issued_),
+ attribute_ (c, error_issued_)
+ {
+ *this >> sources_ >> *this;
+ *this >> schema_names_ >> ns_ >> names_ >> *this;
+
+ *this >> contains_compositor_ >> compositor_;
+ compositor_ >> contains_particle_;
+ contains_particle_ >> compositor_;
+ contains_particle_ >> element_;
+
+ *this >> names_attribute_ >> attribute_;
+ }
+
+ private:
+ Boolean error_issued_;
+
+ Containers::Set<String> types_;
+
+ Traversal::Sources sources_;
+
+ Traversal::Names schema_names_;
+ Traversal::Namespace ns_;
+ Traversal::Names names_;
+
+ Traversal::Compositor compositor_;
+ AnonymousElement element_;
+ Traversal::ContainsCompositor contains_compositor_;
+ Traversal::ContainsParticle contains_particle_;
+
+ AnonymousAttribute attribute_;
+ Traversal::Names names_attribute_;
+ };
+
+ struct GlobalElementCount: Traversal::Element
+ {
+ GlobalElementCount (UnsignedLong& count)
+ : count_ (count)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element&)
+ {
+ count_++;
+ }
+
+ private:
+ UnsignedLong& count_;
+ };
+
+ struct ParserValidation: Traversal::All,
+ Traversal::Choice,
+ Traversal::Sequence,
+ Traversal::Complex,
+ ValidationContext
+
+ {
+ ParserValidation (ValidationContext& c)
+ : ValidationContext (c), issued_ (false)
+ {
+ contains_compositor_ >> *this;
+ *this >> contains_particle_ >> *this;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ // For the all compositor, maxOccurs=1 and minOccurs={0,1}.
+ //
+ if (!issued_ && a.min () == 0)
+ {
+ valid = false;
+ issued_ = true;
+
+ wcerr << a.file () << ":" << a.line () << ":" << a.column ()
+ << ": error: complex type '" << type (a).name () << "' "
+ << "contains optional all compositor" << endl;
+
+ wcerr << a.file () << ":" << a.line () << ":" << a.column ()
+ << ": error: parser validation is required to handle this "
+ << "construct" << endl;
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ if (!issued_)
+ {
+ valid = false;
+ issued_ = true;
+
+ wcerr << c.file () << ":" << c.line () << ":" << c.column ()
+ << ": error: complex type '" << type (c).name () << "' "
+ << "contains choice compositor" << endl;
+
+ wcerr << c.file () << ":" << c.line () << ":" << c.column ()
+ << ": error: parser validation is required to handle this "
+ << "construct" << endl;
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ if (!issued_)
+ {
+ if (s.max () != 1)
+ {
+ issued_ = true;
+ wcerr << s.file () << ":" << s.line () << ":" << s.column ()
+ << ": error: complex type '" << type (s).name () << "' "
+ << "contains sequence of sequence compositor" << endl;
+ }
+ else if (s.min () == 0)
+ {
+ issued_ = true;
+ wcerr << s.file () << ":" << s.line () << ":" << s.column ()
+ << ": error: complex type '" << type (s).name () << "' "
+ << "contains optional sequence compositor" << endl;
+ }
+
+ if (issued_)
+ {
+ valid = false;
+ wcerr << s.file () << ":" << s.line () << ":" << s.column ()
+ << ": error: parser validation is required to handle "
+ << "this construct" << endl;
+ }
+ }
+
+ Traversal::Sequence::traverse (s);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ if (!issued_ && !restriction_p (c))
+ contains_compositor (c, contains_compositor_);
+ }
+
+ private:
+ SemanticGraph::Complex&
+ type (SemanticGraph::Compositor& c)
+ {
+ SemanticGraph::Compositor* root (&c);
+
+ while (root->contained_particle_p ())
+ root = &root->contained_particle ().compositor ();
+
+ return dynamic_cast<SemanticGraph::Complex&> (
+ root->contained_compositor ().container ());
+ }
+
+ private:
+ Boolean issued_;
+
+ Traversal::ContainsCompositor contains_compositor_;
+ Traversal::ContainsParticle contains_particle_;
+ };
+ }
+
+ Boolean Validator::
+ validate (CLI::Options const& options,
+ SemanticGraph::Schema& root,
+ SemanticGraph::Path const&,
+ const WarningSet& disabled_warnings)
+ {
+ Boolean valid (true);
+ ValidationContext ctx (root, options, disabled_warnings, valid);
+
+ Boolean par (options.value<CLI::generate_parser> ());
+ Boolean ser (options.value<CLI::generate_serializer> ());
+ Boolean agg (options.value<CLI::generate_aggregate> ());
+
+ if (agg && !par && !ser && !ctx.is_disabled ("H002"))
+ {
+ wcerr << root.file () << ": warning H002: --generate-aggregate " <<
+ "is specified but neither parsing nor serialization code is " <<
+ "generated" << endl;
+ }
+
+ // Issue a warning if there are more than one global element and we
+ // are generating aggregate types.
+ //
+ if (agg &&
+ !options.value<CLI::root_element_first> () &&
+ !options.value<CLI::root_element_last> () &&
+ !options.value<CLI::root_element_all> () &&
+ !options.value<CLI::root_element_none> () &&
+ options.value<CLI::root_element> ().empty () &&
+ !ctx.is_disabled ("H003"))
+ {
+ UnsignedLong count (0);
+
+ {
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+
+ schema >> sources >> schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names names;
+
+ schema >> schema_names >> ns >> names;
+
+ GlobalElementCount element (count);
+
+ names >> element;
+
+ schema.dispatch (root);
+ }
+
+ if (count > 1)
+ {
+ wcerr << root.file () << ": warning H003: generating aggregate " <<
+ "types for " << count << " global elements" << endl;
+
+ wcerr << root.file () << ": info: use --root-element-* options "
+ << "to specify document root(s)" << endl;
+ }
+ }
+
+ // Test for anonymout types.
+ //
+ {
+ AnonymousType traverser (ctx);
+ traverser.dispatch (root);
+ }
+
+ // Test for constructs that require validation in parser.
+ //
+ if (valid && par &&
+ (options.value<CLI::suppress_validation> () ||
+ options.value<CLI::suppress_parser_val> ()))
+ {
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+
+ schema >> sources >> schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names names;
+
+ schema >> schema_names >> ns >> names;
+
+ ParserValidation type (ctx);
+
+ names >> type;
+
+ schema.dispatch (root);
+ }
+
+ // Test the rest.
+ //
+ if (valid)
+ {
+ Traverser traverser (ctx);
+ traverser.dispatch (root);
+ }
+
+ return valid;
+ }
+ }
+}
diff --git a/xsde/cxx/hybrid/validator.hxx b/xsde/cxx/hybrid/validator.hxx
new file mode 100644
index 0000000..0fb6df6
--- /dev/null
+++ b/xsde/cxx/hybrid/validator.hxx
@@ -0,0 +1,35 @@
+// file : xsde/cxx/hybrid/validator.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_VALIDATOR_HXX
+#define CXX_HYBRID_VALIDATOR_HXX
+
+#include <cult/types.hxx>
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/hybrid/cli.hxx>
+
+#include <xsde.hxx>
+
+namespace CXX
+{
+ namespace Hybrid
+ {
+ using namespace Cult::Types;
+
+ class Validator
+ {
+ public:
+ Boolean
+ validate (CLI::Options const& options,
+ XSDFrontend::SemanticGraph::Schema&,
+ XSDFrontend::SemanticGraph::Path const& tu,
+ const WarningSet& disabled_warnings);
+ };
+ }
+}
+
+#endif // CXX_HYBRID_VALIDATOR_HXX