aboutsummaryrefslogtreecommitdiff
path: root/xsde/cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2009-02-24 15:16:26 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2009-02-24 15:16:26 +0200
commit707cc94fe52463870a9c6c8e2e66eaaa389e601d (patch)
tree13e10ff28bf4455d915f9d59b401bdbb62a393cb /xsde/cxx
Start tracking XSD/e with git after version 3.0.03.0.0
Diffstat (limited to 'xsde/cxx')
-rw-r--r--xsde/cxx/elements.cxx1089
-rw-r--r--xsde/cxx/elements.hxx599
-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
-rw-r--r--xsde/cxx/parser/attribute-validation-source.cxx468
-rw-r--r--xsde/cxx/parser/attribute-validation-source.hxx22
-rw-r--r--xsde/cxx/parser/characters-validation-source.cxx76
-rw-r--r--xsde/cxx/parser/characters-validation-source.hxx22
-rw-r--r--xsde/cxx/parser/cli.hxx156
-rw-r--r--xsde/cxx/parser/driver-source.cxx1139
-rw-r--r--xsde/cxx/parser/driver-source.hxx22
-rw-r--r--xsde/cxx/parser/element-validation-source.cxx2120
-rw-r--r--xsde/cxx/parser/element-validation-source.hxx22
-rw-r--r--xsde/cxx/parser/elements.cxx258
-rw-r--r--xsde/cxx/parser/elements.hxx431
-rw-r--r--xsde/cxx/parser/generator.cxx1615
-rw-r--r--xsde/cxx/parser/generator.hxx56
-rw-r--r--xsde/cxx/parser/impl-header.cxx309
-rw-r--r--xsde/cxx/parser/impl-header.hxx22
-rw-r--r--xsde/cxx/parser/impl-source.cxx543
-rw-r--r--xsde/cxx/parser/impl-source.hxx22
-rw-r--r--xsde/cxx/parser/name-processor.cxx1326
-rw-r--r--xsde/cxx/parser/name-processor.hxx32
-rw-r--r--xsde/cxx/parser/parser-forward.cxx112
-rw-r--r--xsde/cxx/parser/parser-forward.hxx22
-rw-r--r--xsde/cxx/parser/parser-header.cxx1818
-rw-r--r--xsde/cxx/parser/parser-header.hxx22
-rw-r--r--xsde/cxx/parser/parser-inline.cxx721
-rw-r--r--xsde/cxx/parser/parser-inline.hxx22
-rw-r--r--xsde/cxx/parser/parser-source.cxx1626
-rw-r--r--xsde/cxx/parser/parser-source.hxx22
-rw-r--r--xsde/cxx/parser/print-impl-common.hxx1063
-rw-r--r--xsde/cxx/parser/state-processor.cxx319
-rw-r--r--xsde/cxx/parser/state-processor.hxx28
-rw-r--r--xsde/cxx/parser/type-processor.cxx352
-rw-r--r--xsde/cxx/parser/type-processor.hxx34
-rw-r--r--xsde/cxx/parser/validator.cxx704
-rw-r--r--xsde/cxx/parser/validator.hxx36
-rw-r--r--xsde/cxx/serializer/attribute-validation-source.cxx463
-rw-r--r--xsde/cxx/serializer/attribute-validation-source.hxx22
-rw-r--r--xsde/cxx/serializer/cli.hxx154
-rw-r--r--xsde/cxx/serializer/driver-source.cxx1047
-rw-r--r--xsde/cxx/serializer/driver-source.hxx22
-rw-r--r--xsde/cxx/serializer/element-validation-source.cxx903
-rw-r--r--xsde/cxx/serializer/element-validation-source.hxx22
-rw-r--r--xsde/cxx/serializer/elements.cxx278
-rw-r--r--xsde/cxx/serializer/elements.hxx443
-rw-r--r--xsde/cxx/serializer/generator.cxx1600
-rw-r--r--xsde/cxx/serializer/generator.hxx56
-rw-r--r--xsde/cxx/serializer/impl-header.cxx488
-rw-r--r--xsde/cxx/serializer/impl-header.hxx22
-rw-r--r--xsde/cxx/serializer/impl-source.cxx664
-rw-r--r--xsde/cxx/serializer/impl-source.hxx22
-rw-r--r--xsde/cxx/serializer/name-processor.cxx1409
-rw-r--r--xsde/cxx/serializer/name-processor.hxx32
-rw-r--r--xsde/cxx/serializer/serializer-forward.cxx112
-rw-r--r--xsde/cxx/serializer/serializer-forward.hxx22
-rw-r--r--xsde/cxx/serializer/serializer-header.cxx2006
-rw-r--r--xsde/cxx/serializer/serializer-header.hxx22
-rw-r--r--xsde/cxx/serializer/serializer-inline.cxx631
-rw-r--r--xsde/cxx/serializer/serializer-inline.hxx22
-rw-r--r--xsde/cxx/serializer/serializer-source.cxx2703
-rw-r--r--xsde/cxx/serializer/serializer-source.hxx22
-rw-r--r--xsde/cxx/serializer/type-processor.cxx356
-rw-r--r--xsde/cxx/serializer/type-processor.hxx34
-rw-r--r--xsde/cxx/serializer/validator.cxx501
-rw-r--r--xsde/cxx/serializer/validator.hxx36
106 files changed, 54269 insertions, 0 deletions
diff --git a/xsde/cxx/elements.cxx b/xsde/cxx/elements.cxx
new file mode 100644
index 0000000..6116856
--- /dev/null
+++ b/xsde/cxx/elements.cxx
@@ -0,0 +1,1089 @@
+// file : xsde/cxx/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/elements.hxx>
+
+#include <backend-elements/regex.hxx>
+
+#include <sstream>
+#include <iostream>
+#include <algorithm>
+
+using std::wcerr;
+using std::endl;
+
+namespace CXX
+{
+ //
+ //
+ wchar_t
+ upcase (wchar_t c)
+ {
+ return std::toupper (c);
+ }
+
+ // Context
+ //
+
+ Context::
+ Context (std::wostream& o,
+ SemanticGraph::Schema& root,
+ Char const* name_key,
+ NarrowString const& char_type__,
+ Boolean include_with_brackets__,
+ NarrowString const& include_prefix__,
+ NarrowString const& esymbol,
+ Containers::Vector<NarrowString> const& nsm,
+ Containers::Vector<NarrowString> const& nsr,
+ Boolean trace_namespace_regex_,
+ Containers::Vector<NarrowString> const& ir,
+ Boolean trace_include_regex_,
+ Boolean inline_,
+ Containers::Vector<NarrowString> const& reserved_name)
+ : os (o),
+ schema_root (root),
+ ename_key (ename_key_),
+ char_type (char_type_),
+ L (L_),
+ string_type (string_type_),
+ include_with_brackets (include_with_brackets_),
+ include_prefix (include_prefix_),
+ type_exp (type_exp_),
+ inst_exp (inst_exp_),
+ inl (inl_),
+ ns_mapping_cache (ns_mapping_cache_),
+ xs_ns_ (0),
+ ename_key_ (name_key),
+ char_type_ (char_type__),
+ L_ (char_type == L"wchar_t" ? L"L" : L""),
+ include_with_brackets_ (include_with_brackets__),
+ include_prefix_ (include_prefix__),
+ type_exp_ (esymbol ? esymbol + " " : esymbol),
+ inst_exp_ (esymbol ? esymbol + "\n" : esymbol),
+ inl_ (inline_ ? L"inline\n" : L""),
+ cxx_id_expr_ (L"^(::)?([a-zA-Z_]\\w*)(::[a-zA-Z_]\\w*)*$"),
+ cxx_id_expr (cxx_id_expr_),
+ trace_namespace_regex (trace_namespace_regex_),
+ nsr_mapping (nsr_mapping_),
+ nsm_mapping (nsm_mapping_),
+ include_mapping (include_mapping_),
+ trace_include_regex (trace_include_regex_),
+ reserved_name_map (reserved_name_map_)
+ {
+ // Resolve and cache XML Schema namespace.
+ //
+ {
+ SemanticGraph::Nameable* n;
+
+ if (schema_root.names_begin ()->name () ==
+ L"http://www.w3.org/2001/XMLSchema")
+ {
+ // schema_root is the XML Schema itself.
+ //
+ n = &schema_root.names_begin ()->named ();
+ }
+ else
+ {
+ // Otherwise, the first used schema is implied XML Schema.
+ //
+ SemanticGraph::Uses& u = *schema_root.uses_begin ();
+ assert (u.is_a<SemanticGraph::Implies> ());
+ n = &u.schema ().names_begin ()->named ();
+ }
+
+ xs_ns_ = dynamic_cast<SemanticGraph::Namespace*> (n);
+ }
+
+ //
+ //
+ if (char_type == L"char")
+ string_type_ = L"::std::string";
+ else if (char_type == L"wchar_t")
+ string_type_ = L"::std::wstring";
+ else
+ string_type_ = L"::std::basic_string< " + char_type + L" >";
+
+ // Default mapping.
+ //
+ nsr_mapping_.push_back (
+ Regex (L"#^.* (.*?/)??"L"(([a-zA-Z_]\\w*)(/[a-zA-Z_]\\w*)*)/?$#$2#"));
+ nsr_mapping_.push_back (
+ Regex (L"#^.* http://www\\.w3\\.org/2001/XMLSchema$#xml_schema#"));
+
+ // Custom regex mapping.
+ //
+ for (Containers::Vector<NarrowString>::ConstIterator
+ i (nsr.begin ()), e (nsr.end ()); i != e; ++i)
+ {
+ nsr_mapping_.push_back (Regex (*i));
+ }
+
+ // Custom direct mapping.
+ //
+ for (Containers::Vector<NarrowString>::ConstIterator
+ i (nsm.begin ()), e (nsm.end ()); i != e; ++i)
+ {
+ String s (*i);
+
+ // Split the string in two parts at the last '='.
+ //
+ Size pos (s.rfind ('='));
+
+ if (pos == String::npos)
+ throw InvalidNamespaceMapping (s, "delimiter ('=') not found");
+
+ // Empty xml_ns designates the no-namespace case.
+ //
+ String xml_ns (s, 0, pos);
+ String cxx_ns (s, pos + 1);
+
+ if (!cxx_ns.empty () && !cxx_id_expr.match (cxx_ns))
+ throw InvalidNamespaceMapping (s, "invalid C++ identifier");
+
+ nsm_mapping_[xml_ns] = cxx_ns;
+ }
+
+ // Include path regex
+ //
+ for (Containers::Vector<NarrowString>::ConstIterator
+ i (ir.begin ()), e (ir.end ()); i != e; ++i)
+ {
+ include_mapping_.push_back (Regex (*i));
+ }
+
+ // Reserved names.
+ //
+ for (Containers::Vector<NarrowString>::ConstIterator
+ i (reserved_name.begin ()), e (reserved_name.end ()); i != e; ++i)
+ {
+ String s (*i);
+
+ // Split the string in two parts at '='.
+ //
+ Size pos (s.find ('='));
+
+ if (pos == String::npos)
+ reserved_name_map_[s] = L"";
+ else
+ reserved_name_map_[String (s, 0, pos)] = String (s, pos + 1);
+ }
+ }
+
+ String Context::
+ ns_name (SemanticGraph::Namespace& ns) const
+ {
+ using SemanticGraph::Schema;
+ using SemanticGraph::Includes;
+ using SemanticGraph::Imports;
+ using SemanticGraph::Implies;
+ using SemanticGraph::Sources;
+
+ String tmp;
+ MapMapping::ConstIterator i (nsm_mapping.find (ns.name ()));
+
+ if (i != nsm_mapping.end ())
+ {
+ tmp = i->second;
+ }
+ else
+ {
+ SemanticGraph::Path path;
+ Schema& schema (dynamic_cast<Schema&> (ns.scope ()));
+
+ if (schema.used ())
+ {
+ SemanticGraph::Uses& u (*schema.used_begin ());
+ path = u.path ();
+ }
+
+ String pair;
+
+ if (!path.empty ())
+ {
+ // Try to use the portable representation of the path. If that
+ // fails, fall back to the native representation.
+ //
+ try
+ {
+ pair = path.string ();
+ }
+ catch (SemanticGraph::InvalidPath const&)
+ {
+ pair = path.native_file_string ();
+ }
+ }
+
+ pair += L' ' + ns.name ();
+
+ // Check cache first
+ //
+ MappingCache::ConstIterator i (ns_mapping_cache.find (pair));
+
+ if (i != ns_mapping_cache.end ())
+ {
+ tmp = i->second;
+ }
+ else
+ {
+ if (trace_namespace_regex)
+ wcerr << "namespace: '" << pair << "'" << endl;
+
+ Boolean found (false);
+ Regex colon (L"#/#::#");
+
+ for (RegexMapping::ConstReverseIterator e (nsr_mapping.rbegin ());
+ e != nsr_mapping.rend (); ++e)
+ {
+ if (trace_namespace_regex)
+ wcerr << "try: '" << e->pattern () << "' : ";
+
+ if (e->match (pair))
+ {
+ tmp = e->merge (pair);
+ tmp = colon.merge (tmp); // replace `/' with `::'
+
+ // Check the result.
+ //
+ found = cxx_id_expr.match (tmp);
+
+ if (trace_namespace_regex)
+ wcerr << "'" << tmp << "' : ";
+ }
+
+ if (trace_namespace_regex)
+ wcerr << (found ? '+' : '-') << endl;
+
+ if (found)
+ break;
+ }
+
+ if (!found)
+ {
+ // Check if the name is valid by itself.
+ //
+ if (ns.name ().empty ())
+ {
+ // Empty name denotes a no-namespace case.
+ //
+ tmp = ns.name ();
+ }
+ else
+ {
+ tmp = colon.merge (ns.name ()); // replace `/' with `::'
+
+ if (!cxx_id_expr.match (tmp))
+ {
+ throw NoNamespaceMapping (
+ ns.file (), ns.line (), ns.column (), ns.name ());
+ }
+ }
+ }
+
+ // Add the mapping to the cache.
+ //
+ ns_mapping_cache[pair] = tmp;
+ }
+ }
+
+
+ // Parse resulting namespace string and id() each name.
+ //
+ String r;
+ String::size_type b (0), e;
+
+ do
+ {
+ e = tmp.find (L"::", b);
+
+ String name (tmp, b, e == tmp.npos ? e : e - b);
+
+ if (!name.empty ())
+ r += L"::" + escape (name);
+
+ b = e;
+
+ if (b == tmp.npos)
+ break;
+
+ b += 2;
+
+ } while (true);
+
+ return r;
+ }
+
+ SemanticGraph::Namespace& Context::
+ xs_ns ()
+ {
+ return *xs_ns_;
+ }
+
+ String Context::
+ xs_ns_name ()
+ {
+ return ns_name (*xs_ns_);
+ }
+
+ SemanticGraph::Namespace& Context::
+ namespace_ (SemanticGraph::Nameable& n)
+ {
+ // The basic idea goes like this: go up Names edges until you
+ // reach Namespace. There are, however, anonymous types which
+ // need special handling. In the case of an anonymous type we
+ // will go up the first Belongs edge (because the first edge
+ // is where the type was defined.
+ //
+
+ if (n.named ())
+ {
+ SemanticGraph::Scope& s (n.scope ());
+
+ SemanticGraph::Namespace* ns (
+ dynamic_cast<SemanticGraph::Namespace*> (&n));
+
+ return ns ? *ns : namespace_ (s);
+ }
+ else
+ {
+ SemanticGraph::Type& t (dynamic_cast<SemanticGraph::Type&> (n));
+
+ SemanticGraph::Belongs& b (*t.classifies_begin ());
+
+ return namespace_ (b.instance ());
+ }
+ }
+
+ String Context::
+ xml_ns_name (SemanticGraph::Nameable& n)
+ {
+ return namespace_ (n).name ();
+ }
+
+ String Context::
+ fq_name (SemanticGraph::Nameable& n, Char const* name_key) const
+ {
+ using namespace SemanticGraph;
+
+ String r;
+
+ if (dynamic_cast<Schema*> (&n))
+ {
+ return L""; // Map to global namespace.
+ }
+ else if (SemanticGraph::Namespace* ns =
+ dynamic_cast<SemanticGraph::Namespace*> (&n))
+ {
+ r = ns_name (*ns);
+ }
+ else
+ {
+ r = fq_name (n.scope ());
+ r += L"::";
+ r += n.context ().get<String> (
+ name_key ? name_key : ename_key.c_str ());
+ }
+
+ return r;
+ }
+
+ SemanticGraph::Type& Context::
+ ultimate_base (SemanticGraph::Complex& c)
+ {
+ using namespace SemanticGraph;
+
+ Type* b (&c.inherits ().base ());
+
+ while (true)
+ {
+ Complex* cb (dynamic_cast<Complex*> (b));
+
+ if (cb != 0 && cb->inherits_p ())
+ {
+ b = &cb->inherits ().base ();
+ continue;
+ }
+
+ break;
+ }
+
+ return *b;
+ }
+
+ // Restriction correspondance.
+ //
+ SemanticGraph::Element* Context::
+ correspondent (SemanticGraph::Element& r)
+ {
+ SemanticGraph::Context& c (r.context ());
+
+ if (c.count ("xsd-frontend-restriction-correspondence"))
+ {
+ return c.get<SemanticGraph::Element*> (
+ "xsd-frontend-restriction-correspondence");
+ }
+
+ return 0;
+ }
+
+ SemanticGraph::Any* Context::
+ correspondent (SemanticGraph::Any& r)
+ {
+ SemanticGraph::Context& c (r.context ());
+
+ if (c.count ("xsd-frontend-restriction-correspondence"))
+ {
+ return c.get<SemanticGraph::Any*> (
+ "xsd-frontend-restriction-correspondence");
+ }
+
+ return 0;
+ }
+
+ SemanticGraph::Compositor* Context::
+ correspondent (SemanticGraph::Compositor& r)
+ {
+ SemanticGraph::Context& c (r.context ());
+
+ if (c.count ("xsd-frontend-restriction-correspondence"))
+ {
+ return c.get<SemanticGraph::Compositor*> (
+ "xsd-frontend-restriction-correspondence");
+ }
+
+ return 0;
+ }
+
+
+ //
+ //
+ namespace
+ {
+ WideChar const* keywords[] = {
+ L"NULL",
+ L"and",
+ L"asm",
+ L"auto",
+ L"bitand",
+ L"bitor",
+ L"bool",
+ L"break",
+ L"case",
+ L"catch",
+ L"char",
+ L"class",
+ L"compl",
+ L"const",
+ L"const_cast",
+ L"continue",
+ L"default",
+ L"delete",
+ L"do",
+ L"double",
+ L"dynamic_cast",
+ L"else",
+ L"end_eq",
+ L"enum",
+ L"explicit",
+ L"export",
+ L"extern",
+ L"false",
+ L"float",
+ L"for",
+ L"friend",
+ L"goto",
+ L"if",
+ L"inline",
+ L"int",
+ L"long",
+ L"mutable",
+ L"namespace",
+ L"new",
+ L"not",
+ L"not_eq",
+ L"operator",
+ L"or",
+ L"or_eq",
+ L"private",
+ L"protected",
+ L"public",
+ L"register",
+ L"reinterpret_cast",
+ L"return",
+ L"short",
+ L"signed",
+ L"sizeof",
+ L"static",
+ L"static_cast",
+ L"struct",
+ L"switch",
+ L"template",
+ L"this",
+ L"throw",
+ L"true",
+ L"try",
+ L"typedef",
+ L"typeid",
+ L"typename",
+ L"union",
+ L"unsigned",
+ L"using",
+ L"virtual",
+ L"void",
+ L"volatile",
+ L"wchar_t",
+ L"while",
+ L"xor",
+ L"xor_eq"
+ };
+ }
+
+ String Context::
+ escape (String const& name) const
+ {
+ String r;
+ Size n (name.size ());
+
+ // In most common cases we will have that many chars.
+ //
+ r.reserve (n);
+
+ for (Size i (0); i < n; ++i)
+ {
+ Boolean first (i == 0);
+
+ UnsignedLong u (unicode_char (name, i)); // May advance i.
+
+ if (first)
+ {
+ if (!((u >= 'a' && u <= 'z') ||
+ (u >= 'A' && u <= 'Z') ||
+ u == '_'))
+ r = (u >= '0' && u <= '9') ? L"cxx_" : L"cxx";
+ }
+
+ if (!((u >= 'a' && u <= 'z') ||
+ (u >= 'A' && u <= 'Z') ||
+ (u >= '0' && u <= '9') ||
+ u == '_'))
+ r.push_back ('_');
+ else
+ r.push_back (static_cast<WideChar> (u));
+ }
+
+ if (r.empty ())
+ r = L"cxx";
+
+ // Custom reserved words.
+ //
+ ReservedNameMap::ConstIterator i (reserved_name_map.find (r));
+
+ if (i != reserved_name_map.end ())
+ {
+ if (i->second)
+ return i->second;
+ else
+ r += L'_';
+ }
+
+ // Keywords
+ //
+ Size const size (sizeof (keywords) / sizeof (WideChar*));
+
+ if (std::binary_search (keywords, keywords + size, r))
+ {
+ r += L'_';
+
+ // Re-run custom words.
+ //
+ i = reserved_name_map.find (r);
+
+ if (i != reserved_name_map.end ())
+ {
+ if (i->second)
+ return i->second;
+ else
+ r += L'_';
+ }
+ }
+
+ return r;
+ }
+
+ // String escaping.
+ //
+
+ String
+ charlit (UnsignedLong u)
+ {
+ String r ("\\x");
+ Boolean lead (true);
+
+ for (Long i (7); i >= 0; --i)
+ {
+ UnsignedLong x ((u >> (i * 4)) & 0x0F);
+
+ if (lead)
+ {
+ if (x == 0)
+ continue;
+
+ lead = false;
+ }
+
+ r += x < 10 ? ('0' + x) : ('A' + x - 10);
+ }
+
+ return r;
+ }
+
+ const UnsignedLong utf8_first_char_mask[5] =
+ {
+ 0x00, 0x00, 0xC0, 0xE0, 0xF0
+ };
+
+ String
+ strlit_utf8 (String const& str)
+ {
+ String r;
+ Size n (str.size ());
+
+ // In most common cases we will have that many chars.
+ //
+ r.reserve (n + 2);
+
+ r += '"';
+
+ Boolean escape (false);
+
+ for (Size i (0); i < n; ++i)
+ {
+ UnsignedLong u (Context::unicode_char (str, i)); // May advance i.
+
+ // [128 - ] - UTF-8
+ // 127 - \x7F
+ // [32 - 126] - as is
+ // [0 - 31] - \X or \xXX
+ //
+
+ if (u < 32 || u == 127)
+ {
+ switch (u)
+ {
+ case L'\n':
+ {
+ r += L"\\n";
+ break;
+ }
+ case L'\t':
+ {
+ r += L"\\t";
+ break;
+ }
+ case L'\v':
+ {
+ r += L"\\v";
+ break;
+ }
+ case L'\b':
+ {
+ r += L"\\b";
+ break;
+ }
+ case L'\r':
+ {
+ r += L"\\r";
+ break;
+ }
+ case L'\f':
+ {
+ r += L"\\f";
+ break;
+ }
+ case L'\a':
+ {
+ r += L"\\a";
+ break;
+ }
+ default:
+ {
+ r += charlit (u);
+ escape = true;
+ break;
+ }
+ }
+ }
+ else if (u < 127)
+ {
+ if (escape)
+ {
+ // Close and open the string so there are no clashes.
+ //
+ r += '"';
+ r += '"';
+
+ escape = false;
+ }
+
+ switch (u)
+ {
+ case L'"':
+ {
+ r += L"\\\"";
+ break;
+ }
+ case L'\\':
+ {
+ r += L"\\\\";
+ break;
+ }
+ default:
+ {
+ r += static_cast<WideChar> (u);
+ break;
+ }
+ }
+ }
+ else
+ {
+ UnsignedLong count;
+ UnsignedLong tmp[4];
+
+ if (u < 0x800)
+ count = 2;
+ else if (u < 0x10000)
+ count = 3;
+ else if (u < 0x110000)
+ count = 4;
+
+ switch (count)
+ {
+ case 4:
+ {
+ tmp[3] = (u | 0x80UL) & 0xBFUL;
+ u >>= 6;
+ }
+ case 3:
+ {
+ tmp[2] = (u | 0x80UL) & 0xBFUL;
+ u >>= 6;
+ }
+ case 2:
+ {
+ tmp[1] = (u | 0x80UL) & 0xBFUL;
+ u >>= 6;
+ }
+ case 1:
+ {
+ tmp[0] = u | utf8_first_char_mask[count];
+ }
+ }
+
+ for (UnsignedLong j (0); j < count; ++j)
+ r += charlit (tmp[j]);
+
+ escape = true;
+ }
+ }
+
+ r += '"';
+
+ return r;
+ }
+
+ String
+ strlit_utf32 (String const& str)
+ {
+ String r;
+ Size n (str.size ());
+
+ // In most common cases we will have that many chars.
+ //
+ r.reserve (n + 2);
+
+ r += '"';
+
+ Boolean escape (false);
+
+ for (Size i (0); i < n; ++i)
+ {
+ UnsignedLong u (Context::unicode_char (str, i)); // May advance i.
+
+ // [128 - ] - \xUUUUUUUU
+ // 127 - \x7F
+ // [32 - 126] - as is
+ // [0 - 31] - \X or \xXX
+ //
+
+ if (u < 32 || u == 127)
+ {
+ switch (u)
+ {
+ case L'\n':
+ {
+ r += L"\\n";
+ break;
+ }
+ case L'\t':
+ {
+ r += L"\\t";
+ break;
+ }
+ case L'\v':
+ {
+ r += L"\\v";
+ break;
+ }
+ case L'\b':
+ {
+ r += L"\\b";
+ break;
+ }
+ case L'\r':
+ {
+ r += L"\\r";
+ break;
+ }
+ case L'\f':
+ {
+ r += L"\\f";
+ break;
+ }
+ case L'\a':
+ {
+ r += L"\\a";
+ break;
+ }
+ default:
+ {
+ r += charlit (u);
+ escape = true;
+ break;
+ }
+ }
+ }
+ else if (u < 127)
+ {
+ if (escape)
+ {
+ // Close and open the string so there are no clashes.
+ //
+ r += '"';
+ r += '"';
+
+ escape = false;
+ }
+
+ switch (u)
+ {
+ case L'"':
+ {
+ r += L"\\\"";
+ break;
+ }
+ case L'\\':
+ {
+ r += L"\\\\";
+ break;
+ }
+ default:
+ {
+ r += static_cast<WideChar> (u);
+ break;
+ }
+ }
+ }
+ else
+ {
+ r += charlit (u);
+ escape = true;
+ }
+ }
+
+ r += '"';
+
+ return r;
+ }
+
+ String Context::
+ strlit (String const& str)
+ {
+ if (char_type == L"char")
+ return strlit_utf8 (str);
+ else
+ return strlit_utf32 (str);
+ }
+
+ String Context::
+ comment (String const& str)
+ {
+ String r;
+
+ WideChar const* s (str.c_str ());
+ Size size (str.size ());
+
+ // In most common cases we will have that many chars.
+ //
+ r.reserve (size);
+
+ for (WideChar const* p (s); p < s + size; ++p)
+ {
+ UnsignedLong u (unicode_char (p)); // May advance p.
+
+ // We are going to treat \v, \f and \n as unrepresentable
+ // here even though they can be present in C++ source code.
+ //
+ if (u > 127 || (u < 32 && u != '\t'))
+ r += L'?';
+ else
+ r += static_cast<WideChar> (u);
+ }
+
+ return r;
+ }
+
+ String Context::
+ process_include_path (String const& name) const
+ {
+ String path (include_prefix + name);
+
+ if (trace_include_regex)
+ wcerr << "include: '" << path << "'" << endl;
+
+ String r;
+ Boolean found (false);
+
+ for (RegexMapping::ConstReverseIterator e (include_mapping.rbegin ());
+ e != include_mapping.rend (); ++e)
+ {
+ if (trace_include_regex)
+ wcerr << "try: '" << e->pattern () << "' : ";
+
+ if (e->match (path))
+ {
+ r = e->merge (path);
+ found = true;
+
+ if (trace_include_regex)
+ wcerr << "'" << r << "' : ";
+ }
+
+ if (trace_include_regex)
+ wcerr << (found ? '+' : '-') << endl;
+
+ if (found)
+ break;
+ }
+
+ if (!found)
+ r = path;
+
+ if (!r.empty () && r[0] != L'"' && r[0] != L'<')
+ {
+ WideChar op (include_with_brackets ? L'<' : L'"');
+ WideChar cl (include_with_brackets ? L'>' : L'"');
+ r = op + r + cl;
+ }
+
+ return r;
+ }
+
+ // Namespace
+ //
+
+ Void Namespace::
+ pre (Type& n)
+ {
+ String ns (ctx_.ns_name (n));
+
+ String::size_type b (0), e;
+
+ if (st_)
+ st_->enter (L"");
+
+ do
+ {
+ e = ns.find (L"::", b);
+
+ String name (ns, b, e == ns.npos ? e : e - b);
+
+ if (!name.empty ())
+ {
+ ctx_.os << "namespace " << name << "{";
+
+ if (st_)
+ st_->enter (name);
+ }
+
+
+ b = e;
+
+ if (b == ns.npos)
+ break;
+
+ b += 2;
+
+ } while (true);
+ }
+
+ Void Namespace::
+ post (Type& n)
+ {
+ String ns (ctx_.ns_name (n));
+
+ String::size_type b (0), e;
+
+ do
+ {
+ e = ns.find (L"::", b);
+
+ String name (ns, b, e == ns.npos ? e : e - b);
+
+ if (!name.empty ())
+ {
+ ctx_.os << "}";
+
+ if (st_)
+ st_->leave ();
+ }
+
+
+ b = e;
+
+ if (b == ns.npos)
+ break;
+
+ b += 2;
+
+ }
+ while (true);
+
+ if (st_)
+ st_->leave ();
+ }
+
+ // Include
+ //
+ Void Includes::
+ traverse (SemanticGraph::Path const& 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 hxx_path (expr_.merge (path_str));
+
+ ctx_.os << "#include " << ctx_.process_include_path (hxx_path) << endl
+ << endl;
+ }
+}
diff --git a/xsde/cxx/elements.hxx b/xsde/cxx/elements.hxx
new file mode 100644
index 0000000..3125cd6
--- /dev/null
+++ b/xsde/cxx/elements.hxx
@@ -0,0 +1,599 @@
+// file : xsde/cxx/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_ELEMENTS_HXX
+#define CXX_ELEMENTS_HXX
+
+#include <cult/types.hxx>
+#include <cult/containers/map.hxx>
+#include <cult/containers/vector.hxx>
+
+#include <backend-elements/regex.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <elements.hxx>
+
+#include <ostream>
+
+namespace CXX
+{
+ using std::endl;
+ typedef WideString String;
+
+
+ // On some platforms std::toupper can be something other than a
+ // function with C++ linkage.
+ //
+ wchar_t
+ upcase (wchar_t c);
+
+
+ // Exceptions.
+ //
+
+ struct NoNamespaceMapping
+ {
+ NoNamespaceMapping (SemanticGraph::Path const& file,
+ UnsignedLong line,
+ UnsignedLong column,
+ String const& ns)
+ : file_ (file),
+ line_ (line),
+ column_ (column),
+ ns_ (ns)
+ {
+ }
+
+ SemanticGraph::Path const&
+ file () const
+ {
+ return file_;
+ }
+
+ UnsignedLong
+ line () const
+ {
+ return line_;
+ }
+
+ UnsignedLong
+ column () const
+ {
+ return column_;
+ }
+
+ String const&
+ ns () const
+ {
+ return ns_;
+ }
+
+ private:
+ SemanticGraph::Path file_;
+ UnsignedLong line_;
+ UnsignedLong column_;
+ String ns_;
+ };
+
+ struct InvalidNamespaceMapping
+ {
+ InvalidNamespaceMapping (String const& mapping,
+ String const& reason)
+ : mapping_ (mapping), reason_ (reason)
+ {
+ }
+
+ String const&
+ mapping () const
+ {
+ return mapping_;
+ }
+
+ String const&
+ reason () const
+ {
+ return reason_;
+ }
+
+ private:
+ String mapping_;
+ String reason_;
+ };
+
+
+ //
+ //
+ class Context
+ {
+ public:
+ typedef BackendElements::Regex::Pattern<WideChar> RegexPat;
+ typedef BackendElements::Regex::Expression<WideChar> Regex;
+ typedef Cult::Containers::Vector<Regex> RegexMapping;
+ typedef Cult::Containers::Map<String, String> MapMapping;
+ typedef Cult::Containers::Map<String, String> MappingCache;
+
+ typedef Cult::Containers::Map<String, String> ReservedNameMap;
+
+ public:
+ Context (std::wostream& o,
+ SemanticGraph::Schema& root,
+ Char const* name_key,
+ NarrowString const& char_type__,
+ Boolean include_with_brackets__,
+ NarrowString const& include_prefix__,
+ NarrowString const& esymbol,
+ Containers::Vector<NarrowString> const& nsm,
+ Containers::Vector<NarrowString> const& nsr,
+ Boolean trace_namespace_regex_,
+ Containers::Vector<NarrowString> const& include_regex,
+ Boolean trace_include_regex_,
+ Boolean inline_,
+ Containers::Vector<NarrowString> const& reserved_name);
+
+ protected:
+ Context (Context& c)
+ : os (c.os),
+ schema_root (c.schema_root),
+ ename_key (c.ename_key),
+ char_type (c.char_type),
+ L (c.L),
+ string_type (c.string_type),
+ include_with_brackets (c.include_with_brackets),
+ include_prefix (c.include_prefix),
+ type_exp (c.type_exp),
+ inst_exp (c.inst_exp),
+ inl (c.inl),
+ ns_mapping_cache (c.ns_mapping_cache),
+ xs_ns_ (c.xs_ns_),
+ cxx_id_expr (c.cxx_id_expr),
+ trace_namespace_regex (c.trace_namespace_regex),
+ nsr_mapping (c.nsr_mapping),
+ nsm_mapping (c.nsm_mapping),
+ include_mapping (c.include_mapping),
+ trace_include_regex (c.trace_include_regex),
+ reserved_name_map (c.reserved_name_map)
+ {
+ }
+
+ Context (Context& c, std::wostream& o)
+ : os (o),
+ schema_root (c.schema_root),
+ ename_key (c.ename_key),
+ char_type (c.char_type),
+ L (c.L),
+ string_type (c.string_type),
+ include_with_brackets (c.include_with_brackets),
+ include_prefix (c.include_prefix),
+ type_exp (c.type_exp),
+ inst_exp (c.inst_exp),
+ inl (c.inl),
+ ns_mapping_cache (c.ns_mapping_cache),
+ xs_ns_ (c.xs_ns_),
+ cxx_id_expr (c.cxx_id_expr),
+ trace_namespace_regex (c.trace_namespace_regex),
+ nsr_mapping (c.nsr_mapping),
+ nsm_mapping (c.nsm_mapping),
+ include_mapping (c.include_mapping),
+ trace_include_regex (c.trace_include_regex),
+ reserved_name_map (c.reserved_name_map)
+ {
+ }
+
+ public:
+ static String
+ unclash (String const& name, String const& new_name)
+ {
+ return name == new_name ? (new_name + L'_') : new_name;
+ }
+
+ public:
+ // Return UTF-32 character starting at this position. Position is
+ // advanced by 1 if this Unicode character takes more than one
+ // underlying character.
+ //
+ static UnsignedLong
+ unicode_char (String const& str, Size& pos);
+
+ static UnsignedLong
+ unicode_char (WideChar const*& p);
+
+ // Escape C++ keywords and illegal characters.
+ //
+ String
+ escape (String const&) const;
+
+ // Create a string literal so that it can be used in C++ source
+ // code. It includes "".
+ //
+ String
+ strlit (String const&);
+
+ // Escape the string so that it can be used in C++ comment.
+ //
+ String
+ comment (String const&);
+
+ // Translate XML namespace name to a C++ identifier.
+ //
+ String
+ ns_name (SemanticGraph::Namespace&) const;
+
+ // XML Schema namespace.
+ //
+ SemanticGraph::Namespace&
+ xs_ns ();
+
+ // C++ namespace for XML Schema.
+ //
+ String
+ xs_ns_name ();
+
+ //
+ //
+ SemanticGraph::Namespace&
+ namespace_ (SemanticGraph::Nameable& n);
+
+ // Original XML namespace name.
+ //
+ String
+ xml_ns_name (SemanticGraph::Nameable& ns);
+
+
+ // Fully-qualified C++ name.
+ //
+ String
+ fq_name (SemanticGraph::Nameable& n, Char const* name_key = 0) const;
+
+ public:
+ static SemanticGraph::Type&
+ ultimate_base (SemanticGraph::Complex&);
+
+ public:
+ String
+ process_include_path (String const&) const;
+
+ public:
+ static Boolean
+ anonymous (SemanticGraph::Type& t)
+ {
+ return t.context ().count ("anonymous");
+ }
+
+ // Restriction correspondance.
+ //
+ public:
+ static SemanticGraph::Element*
+ correspondent (SemanticGraph::Element& r);
+
+ static SemanticGraph::Any*
+ correspondent (SemanticGraph::Any& r);
+
+ static SemanticGraph::Compositor*
+ correspondent (SemanticGraph::Compositor& r);
+
+ public:
+ // Get escaped name.
+ //
+ String const&
+ ename (SemanticGraph::Nameable const& n) const
+ {
+ return n.context ().get<String> (ename_key.c_str ());
+ }
+
+ public:
+ std::wostream& os;
+ SemanticGraph::Schema& schema_root;
+
+ NarrowString const& ename_key;
+
+ String& char_type;
+ String& L; // string literal prefix
+ String& string_type;
+
+ Boolean& include_with_brackets;
+ String& include_prefix;
+
+ String& type_exp;
+ String& inst_exp;
+ String& inl;
+
+ public:
+ MappingCache& ns_mapping_cache;
+
+ private:
+ SemanticGraph::Namespace* xs_ns_;
+
+ NarrowString const ename_key_;
+
+ String char_type_;
+ String L_;
+ String string_type_;
+
+ Boolean include_with_brackets_;
+ String include_prefix_;
+
+ String type_exp_;
+ String inst_exp_;
+ String inl_;
+
+ private:
+ RegexPat const cxx_id_expr_;
+ RegexPat const& cxx_id_expr;
+ Boolean trace_namespace_regex;
+ RegexMapping nsr_mapping_;
+ MapMapping nsm_mapping_;
+ RegexMapping const& nsr_mapping;
+ MapMapping const& nsm_mapping;
+ MappingCache ns_mapping_cache_;
+
+ RegexMapping include_mapping_;
+ RegexMapping const& include_mapping;
+ Boolean trace_include_regex;
+
+ ReservedNameMap const& reserved_name_map;
+ ReservedNameMap reserved_name_map_;
+ };
+
+ inline UnsignedLong Context::
+ unicode_char (String const& str, Size& pos)
+ {
+ if (sizeof (WideChar) == 4)
+ {
+ return str[pos];
+ }
+ else if (sizeof (WideChar) == 2)
+ {
+ WideChar x (str[pos]);
+
+ if (x < 0xD800 || x > 0xDBFF)
+ return x;
+ else
+ return ((x - 0xD800) << 10) + (str[++pos] - 0xDC00) + 0x10000;
+ }
+ else
+ return 0;
+ }
+
+ inline UnsignedLong Context::
+ unicode_char (WideChar const*& p)
+ {
+ if (sizeof (WideChar) == 4)
+ {
+ return *p;
+ }
+ else if (sizeof (WideChar) == 2)
+ {
+ WideChar x (*p);
+
+ if (x < 0xD800 || x > 0xDBFF)
+ return x;
+ else
+ return ((x - 0xD800) << 10) + (*(++p) - 0xDC00) + 0x10000;
+ }
+ else
+ return 0;
+ }
+
+ // Usual namespace mapping.
+ //
+ struct Namespace : Traversal::Namespace
+ {
+ struct ScopeTracker
+ {
+ virtual
+ ~ScopeTracker () {}
+
+ virtual Void
+ enter (String const&) = 0;
+
+ virtual Void
+ leave () = 0;
+ };
+
+
+ Namespace (Context& c, ScopeTracker* st = 0)
+ : ctx_ (c), st_ (st)
+ {
+ }
+
+ Namespace (Context& c, ScopeTracker& st)
+ : ctx_ (c), st_ (&st)
+ {
+ }
+
+ virtual Void
+ pre (Type&);
+
+ virtual Void
+ post (Type&);
+
+ private:
+ Context& ctx_;
+ ScopeTracker* st_;
+ };
+
+
+ //
+ //
+ template <typename X>
+ struct Has : X
+ {
+ Has (Boolean& result)
+ : result_ (result)
+ {
+ }
+
+ virtual Void
+ traverse (typename X::Type&)
+ {
+ result_ = true;
+ }
+
+ private:
+ Boolean& result_;
+ };
+
+ // Checks if scope 'Y' names any of 'X'
+ //
+ template <typename X, typename Y>
+ Boolean
+ has (Y& y)
+ {
+ using SemanticGraph::Scope;
+
+ Boolean result (false);
+ Has<X> t (result);
+
+ for (Scope::NamesIterator i (y.names_begin ()), e (y.names_end ());
+ !result && i != e; ++i)
+ t.dispatch (i->named ());
+
+ return result;
+ }
+
+ // Checks if the compositor has any particle of 'X'
+ //
+ template <typename X>
+ Boolean
+ has_particle (SemanticGraph::Compositor& y)
+ {
+ using SemanticGraph::Compositor;
+
+ Boolean result (false);
+ Has<X> t (result);
+
+ for (Compositor::ContainsIterator i (y.contains_begin ()),
+ e (y.contains_end ()); !result && i != e; ++i)
+ {
+ SemanticGraph::Particle& p (i->particle ());
+
+ t.dispatch (p);
+
+ if (!result && p.is_a<Compositor> ())
+ result = has_particle<X> (dynamic_cast<Compositor&> (p));
+ }
+
+ return result;
+ }
+
+ // Specialization for Complex
+ //
+ template <typename X>
+ Boolean
+ has_particle (SemanticGraph::Complex& c)
+ {
+ return c.contains_compositor_p () &&
+ has_particle<X> (c.contains_compositor ().compositor ());
+ }
+
+ // Fundamental type mapping helper.
+ //
+ struct Fundamental : Traversal::Fundamental::Type,
+ Traversal::Fundamental::String,
+ Traversal::Fundamental::NormalizedString,
+ Traversal::Fundamental::Token,
+ Traversal::Fundamental::Name,
+ Traversal::Fundamental::NameToken,
+ Traversal::Fundamental::NCName,
+ Traversal::Fundamental::Id,
+ Traversal::Fundamental::IdRef
+ {
+ virtual Void
+ fundamental_type (SemanticGraph::Fundamental::Type& t) = 0;
+
+ virtual Void
+ fundamental_template (SemanticGraph::Fundamental::Type& t) = 0;
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Type& t)
+ {
+ fundamental_type (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::String& t)
+ {
+ fundamental_template (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NormalizedString& t)
+ {
+ fundamental_template (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Token& t)
+ {
+ fundamental_template (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Name& t)
+ {
+ fundamental_template (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameToken& t)
+ {
+ fundamental_template (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NCName& t)
+ {
+ fundamental_template (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Id& t)
+ {
+ fundamental_template (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRef& t)
+ {
+ fundamental_template (t);
+ }
+ };
+
+ //
+ //
+ struct Includes : Traversal::Imports,
+ Traversal::Includes
+ {
+ typedef BackendElements::Regex::Expression<Char> Regex;
+
+ Includes (Context& c, Regex const& expr)
+ : ctx_ (c), expr_ (expr)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Imports& i)
+ {
+ traverse (i.path ());
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Includes& i)
+ {
+ traverse (i.path ());
+ }
+
+ Void
+ traverse (SemanticGraph::Path const&);
+
+ private:
+ Context& ctx_;
+ Regex expr_;
+ };
+}
+
+#endif // CXX_TREE_ELEMENTS_HXX
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
diff --git a/xsde/cxx/parser/attribute-validation-source.cxx b/xsde/cxx/parser/attribute-validation-source.cxx
new file mode 100644
index 0000000..19c94fa
--- /dev/null
+++ b/xsde/cxx/parser/attribute-validation-source.cxx
@@ -0,0 +1,468 @@
+// file : xsde/cxx/parser/attribute-validation-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/parser/attribute-validation-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ namespace
+ {
+ struct Test: Traversal::Attribute,
+ Traversal::AnyAttribute,
+ Context
+ {
+ Test (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ String const& name (a.name ());
+
+ if (a.qualified () && a.namespace_ ().name ())
+ {
+ String const& ns (a.namespace_ ().name ());
+
+ os << "n == " << L << strlit (name) << " &&" << endl
+ << "ns == " << L << strlit (ns);
+ }
+ else
+ os << "n == " << L << strlit (name) << " && ns.empty ()";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute& a)
+ {
+ String const& ns (a.definition_namespace ().name ());
+
+ for (SemanticGraph::AnyAttribute::NamespaceIterator
+ i (a.namespace_begin ()), e (a.namespace_end ()); i != e;)
+ {
+ if (*i == L"##any")
+ {
+ os << "!n.empty ()";
+ }
+ else if (*i == L"##other")
+ {
+ if (ns)
+ {
+ // Note that here I assume that ##other does not include
+ // unqualified names in a schema with target namespace.
+ // This is not what the spec says but that seems to be
+ // the consensus.
+ //
+ os << "(!ns.empty () && ns != " << L << strlit (ns) << ")";
+ }
+ else
+ os << "!ns.empty ()";
+ }
+ else if (*i == L"##local")
+ {
+ os << "(ns.empty () && !n.empty ())";
+ }
+ else if (*i == L"##targetNamespace")
+ {
+ os << "ns == " << L << strlit (ns);
+ }
+ else
+ {
+ os << "ns == " << L << strlit (*i);
+ }
+
+ if (++i != e)
+ os << " ||" << endl;
+ }
+ }
+ };
+
+ //
+ //
+ struct PhaseOne : Traversal::Attribute, Context
+ {
+ PhaseOne (Context& c)
+ : Context (c), test_ (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ String const& name (ename (a));
+ String const& inst (emember (a));
+
+ SemanticGraph::Type& type (a.type ());
+ String const& post (post_name (type));
+ String const& ret (ret_type (type));
+
+ os << "if (";
+
+ test_.traverse (a);
+
+ os << ")"
+ << "{"
+ << "if (this->" << inst << ")"
+ << "{"
+ << "this->" << inst << "->pre ();"
+ << endl;
+
+ if (!exceptions)
+ os << "if (this->" << inst << "->_error_type ())" << endl
+ << "this->" << inst << "->_copy_error (ctx);"
+ << "else" << endl;
+
+ os << "this->" << inst << "->_pre_impl (ctx);"
+ << endl
+ << "if (!ctx.error_type ())" << endl
+ << "this->" << inst << "->_characters (s);"
+ << endl
+ << "if (!ctx.error_type ())" << endl
+ << "this->" << inst << "->_post_impl ();"
+ << endl
+ << "if (!ctx.error_type ())" << endl;
+
+ if (ret == L"void")
+ os << "this->" << inst << "->" << post << " ();"
+ << endl;
+ else
+ os << "{"
+ << arg_type (type) << " tmp = this->" << inst << "->" <<
+ post << " ();"
+ << endl;
+
+ if (!exceptions)
+ os << "if (this->" << inst << "->_error_type ())" << endl
+ << "this->" << inst << "->_copy_error (ctx);"
+ << "else" << endl;
+
+ if (ret == L"void")
+ os << "this->" << name << " ();";
+ else
+ os << "this->" << name << " (tmp);"
+ << "}";
+
+ os << "}";
+
+ if (!a.optional ())
+ os << "static_cast< v_state_attr_* > (" <<
+ "this->v_state_attr_stack_.top ())->" << name << " = true;";
+
+ os << "return true;"
+ << "}";
+ }
+
+ private:
+ Test test_;
+ };
+
+
+ //
+ //
+ struct PhaseTwo : Traversal::AnyAttribute, Context
+ {
+ PhaseTwo (Context& c)
+ : Context (c), test_ (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ os << "if (";
+
+ test_.traverse (a);
+
+ os << ")" << endl
+ << "{"
+ << "this->_any_attribute (ns, n, s);"
+ << "return true;"
+ << "}";
+ }
+
+ private:
+ Test test_;
+ };
+
+
+ //
+ //
+ struct AttributeStateInit: Traversal::Attribute, Context
+ {
+ AttributeStateInit (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ if (!a.optional ())
+ os << "as." << ename (a) << " = false;";
+ }
+ };
+
+
+ //
+ //
+ struct AttributeStateCheck: Traversal::Attribute, Context
+ {
+ AttributeStateCheck (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ if (!a.optional ())
+ {
+ String ns (a.qualified () ? a.namespace_ ().name () : String ());
+
+ os << "if (!as." << ename (a) << ")"
+ << "{"
+ << "this->_schema_error (" <<
+ "::xsde::cxx::schema_error::expected_attribute);"
+ << "return;"
+ << "}";
+ }
+ }
+ };
+
+ //
+ //
+ struct Complex : Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c),
+ phase_one_ (c),
+ phase_two_ (c),
+ attribute_state_init_ (c),
+ attribute_state_check_ (c)
+ {
+ names_phase_one_ >> phase_one_;
+ names_phase_two_ >> phase_two_;
+
+ names_attribute_state_init_ >> attribute_state_init_;
+ names_attribute_state_check_ >> attribute_state_check_;
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ Boolean has_att (has<Traversal::Attribute> (c));
+ Boolean has_any (has<Traversal::AnyAttribute> (c));
+
+ if (!has_att && !has_any)
+ return;
+
+ Boolean has_req_att (false);
+ if (has_att)
+ {
+ RequiredAttributeTest test (has_req_att);
+ Traversal::Names names_test (test);
+ names (c, names_test);
+ }
+
+ String const& name (ename (c));
+
+ os <<"// Attribute validation and dispatch functions for " <<
+ name << "." << endl
+ <<"//" << endl;
+
+ if (has_att)
+ {
+ // _attribute_impl_phase_one
+ //
+ os << "bool " << name << "::" << endl
+ << "_attribute_impl_phase_one (const " << string_type <<
+ "& ns," << endl
+ << "const " << string_type << "& n," << endl
+ << "const " << string_type << "& s)" << endl
+ << "{"
+ << "::xsde::cxx::parser::context& ctx = this->_context ();"
+ << endl;
+
+ names (c, names_phase_one_);
+
+ // Nothing matched - call our base (extension) or return false
+ // if there is no base (or restriction (even from anyType)).
+ //
+ if (c.inherits_p () &&
+ !c.inherits ().is_a<SemanticGraph::Restricts> ())
+ {
+ // We cannot use the fully-qualified base name directly
+ // because of some broken compilers (EVC 4.0).
+ //
+ String base (unclash (name, "base"));
+
+ os << "typedef " << fq_name (c.inherits ().base ()) << " " <<
+ base << ";"
+ << "return " << base <<
+ "::_attribute_impl_phase_one (ns, n, s);";
+ }
+ else
+ os << "return false;";
+
+ os << "}";
+ }
+
+
+ if (has_any)
+ {
+ // _attribute_impl_phase_two
+ //
+ os << "bool " << name << "::" << endl
+ << "_attribute_impl_phase_two (const " << string_type <<
+ "& ns," << endl
+ << "const " << string_type << "& n," << endl
+ << "const " << string_type << "& s)"
+ << "{";
+
+ names (c, names_phase_two_);
+
+ // Nothing matched - call our base (extension) or return false
+ // if there is no base (or restriction (even from anyType)).
+ //
+ if (c.inherits_p () &&
+ !c.inherits ().is_a<SemanticGraph::Restricts> ())
+ {
+ // We cannot use the fully-qualified base name directly
+ // because of some broken compilers (EVC 4.0).
+ //
+ String base (unclash (name, "base"));
+
+ os << "typedef " << fq_name (c.inherits ().base ()) << " " <<
+ base << ";"
+ << "return " << base <<
+ "::_attribute_impl_phase_two (ns, n, s);";
+ }
+ else
+ os << "return false;";
+
+ os << "}";
+ }
+
+ if (has_req_att)
+ {
+ // _pre_a_validate
+ //
+ os << "void " << name << "::" << endl
+ << "_pre_a_validate ()"
+ << "{";
+
+ if (exceptions)
+ os << "this->v_state_attr_stack_.push ();";
+ else
+ os << "if (this->v_state_attr_stack_.push ())"
+ << "{"
+ << "this->_sys_error (::xsde::cxx::sys_error::no_memory);"
+ << "return;"
+ << "}";
+
+ os << "v_state_attr_& as = *static_cast< v_state_attr_* > (" <<
+ "this->v_state_attr_stack_.top ());"
+ << endl;
+
+ names (c, names_attribute_state_init_);
+
+ // Call our base (extension) last.
+ //
+ if (c.inherits_p () &&
+ !c.inherits ().is_a<SemanticGraph::Restricts> ())
+ {
+ // We cannot use the fully-qualified base name directly
+ // because of some broken compilers (EVC 4.0).
+ //
+ String base (unclash (name, "base"));
+
+ os << "typedef " << fq_name (c.inherits ().base ()) << " " <<
+ base << ";"
+ << base << "::_pre_a_validate ();";
+ }
+
+ os << "}";
+
+
+ // _post_a_validate
+ //
+ os << "void " << name << "::" << endl
+ << "_post_a_validate ()"
+ << "{";
+
+ // Call our base (extension) first.
+ //
+ if (c.inherits_p () &&
+ !c.inherits ().is_a<SemanticGraph::Restricts> ())
+ {
+ // We cannot use the fully-qualified base name directly
+ // because of some broken compilers (EVC 4.0).
+ //
+ String base (unclash (name, "base"));
+
+ os << "typedef " << fq_name (c.inherits ().base ()) << " " <<
+ base << ";"
+ << base << "::_post_a_validate ();"
+ << endl;
+
+ os << "if (this->_context ().error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+
+ os << "v_state_attr_& as = *static_cast< v_state_attr_* > (" <<
+ "this->v_state_attr_stack_.top ());"
+ << endl;
+
+ names (c, names_attribute_state_check_);
+
+ os << endl
+ << "this->v_state_attr_stack_.pop ();"
+ << "}";
+ }
+ }
+
+ private:
+ PhaseOne phase_one_;
+ Traversal::Names names_phase_one_;
+
+ PhaseTwo phase_two_;
+ Traversal::Names names_phase_two_;
+
+ AttributeStateInit attribute_state_init_;
+ Traversal::Names names_attribute_state_init_;
+
+ AttributeStateCheck attribute_state_check_;
+ Traversal::Names names_attribute_state_check_;
+ };
+ }
+
+ Void
+ generate_attribute_validation_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;
+
+ Complex complex (ctx);
+
+ names >> complex;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+}
diff --git a/xsde/cxx/parser/attribute-validation-source.hxx b/xsde/cxx/parser/attribute-validation-source.hxx
new file mode 100644
index 0000000..70101da
--- /dev/null
+++ b/xsde/cxx/parser/attribute-validation-source.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/parser/attribute-validation-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_PARSER_ATTRIBUTE_VALIDATION_SOURCE_HXX
+#define CXX_PARSER_ATTRIBUTE_VALIDATION_SOURCE_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/parser/elements.hxx>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ Void
+ generate_attribute_validation_source (Context&);
+ }
+}
+
+#endif // CXX_PARSER_ATTRIBUTE_VALIDATION_SOURCE_HXX
diff --git a/xsde/cxx/parser/characters-validation-source.cxx b/xsde/cxx/parser/characters-validation-source.cxx
new file mode 100644
index 0000000..c97a859
--- /dev/null
+++ b/xsde/cxx/parser/characters-validation-source.cxx
@@ -0,0 +1,76 @@
+// file : xsde/cxx/parser/characters-validation-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/parser/characters-validation-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ namespace
+ {
+ //
+ //
+ struct Complex : Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ if (!c.mixed ())
+ return;
+
+ String const& name (ename (c));
+
+ os <<"// Character validation functions for " << name << "." << endl
+ <<"//" << endl;
+
+ // _characters_impl
+ //
+ os << "bool " << name << "::" << endl
+ << "_characters_impl (const " << string_type << "& s)"
+ << "{"
+ << "this->_any_characters (s);"
+ << "return true;"
+ << "}";
+ }
+ };
+ }
+
+ Void
+ generate_characters_validation_source (Context& ctx)
+ {
+ //@@ Most of the time there is no mixed content type so
+ // we generate an empty namespace which looks ugly. Will
+ // need to implement smart namespace to handle this at
+ // some point.
+ //
+ Traversal::Schema schema;
+
+ Traversal::Sources sources;
+ Traversal::Names schema_names;
+
+ Namespace ns (ctx);
+ Traversal::Names names;
+
+ schema >> sources >> schema;
+ schema >> schema_names >> ns >> names;
+
+ Complex complex (ctx);
+
+ names >> complex;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+}
+
diff --git a/xsde/cxx/parser/characters-validation-source.hxx b/xsde/cxx/parser/characters-validation-source.hxx
new file mode 100644
index 0000000..5fab5cc
--- /dev/null
+++ b/xsde/cxx/parser/characters-validation-source.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/parser/characters-validation-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_PARSER_CHARACTERS_VALIDATION_SOURCE_HXX
+#define CXX_PARSER_CHARACTERS_VALIDATION_SOURCE_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/parser/elements.hxx>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ Void
+ generate_characters_validation_source (Context&);
+ }
+}
+
+#endif // CXX_PARSER_CHARACTERS_VALIDATION_SOURCE_HXX
diff --git a/xsde/cxx/parser/cli.hxx b/xsde/cxx/parser/cli.hxx
new file mode 100644
index 0000000..485dd91
--- /dev/null
+++ b/xsde/cxx/parser/cli.hxx
@@ -0,0 +1,156 @@
+// file : xsde/cxx/parser/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_PARSER_CLI_HXX
+#define CXX_PARSER_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 Parser
+ {
+ namespace CLI
+ {
+ using namespace Cult::Types;
+
+ typedef Char const Key[];
+
+ extern Key type_map;
+ extern Key no_stl;
+ extern Key no_iostream;
+ extern Key no_exceptions;
+ extern Key no_long_long;
+ extern Key reuse_style_mixin;
+ extern Key reuse_style_none;
+ extern Key generate_inline;
+ extern Key suppress_validation;
+ extern Key generate_polymorphic;
+ extern Key runtime_polymorphic;
+ extern Key suppress_reset;
+ extern Key generate_noop_impl;
+ extern Key generate_print_impl;
+ extern Key generate_test_driver;
+ extern Key force_overwrite;
+ extern Key root_element_first;
+ extern Key root_element_last;
+ extern Key root_element;
+ extern Key generate_xml_schema;
+ extern Key extern_xml_schema;
+ extern Key output_dir;
+ extern Key skel_type_suffix;
+ extern Key skel_file_suffix;
+ extern Key impl_type_suffix;
+ extern Key impl_file_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 hxx_regex;
+ extern Key ixx_regex;
+ extern Key cxx_regex;
+ extern Key hxx_prologue;
+ extern Key ixx_prologue;
+ extern Key cxx_prologue;
+ extern Key prologue;
+ extern Key hxx_epilogue;
+ extern Key ixx_epilogue;
+ extern Key cxx_epilogue;
+ extern Key epilogue;
+ extern Key hxx_prologue_file;
+ extern Key ixx_prologue_file;
+ extern Key cxx_prologue_file;
+ extern Key prologue_file;
+ extern Key hxx_epilogue_file;
+ extern Key ixx_epilogue_file;
+ extern Key cxx_epilogue_file;
+ extern Key epilogue_file;
+ extern Key show_anonymous;
+ extern Key show_sloc;
+ extern Key proprietary_license;
+
+ typedef Cult::CLI::Options<
+ type_map, Cult::Containers::Vector<NarrowString>,
+ no_stl, Boolean,
+ no_iostream, Boolean,
+ no_exceptions, Boolean,
+ no_long_long, Boolean,
+ reuse_style_mixin, Boolean,
+ reuse_style_none, Boolean,
+ generate_inline, Boolean,
+ suppress_validation, Boolean,
+ generate_polymorphic, Boolean,
+ runtime_polymorphic, Boolean,
+ suppress_reset, Boolean,
+ generate_noop_impl, Boolean,
+ generate_print_impl, Boolean,
+ generate_test_driver, Boolean,
+ force_overwrite, Boolean,
+ root_element_first, Boolean,
+ root_element_last, Boolean,
+ root_element, NarrowString,
+ generate_xml_schema, Boolean,
+ extern_xml_schema, NarrowString,
+ output_dir, NarrowString,
+ skel_type_suffix, NarrowString,
+ skel_file_suffix, NarrowString,
+ impl_type_suffix, NarrowString,
+ impl_file_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,
+ hxx_regex, NarrowString,
+ ixx_regex, NarrowString,
+ cxx_regex, NarrowString,
+ hxx_prologue, Cult::Containers::Vector<NarrowString>,
+ ixx_prologue, Cult::Containers::Vector<NarrowString>,
+ cxx_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>,
+ epilogue, Cult::Containers::Vector<NarrowString>,
+ hxx_prologue_file, NarrowString,
+ ixx_prologue_file, NarrowString,
+ cxx_prologue_file, NarrowString,
+ prologue_file, NarrowString,
+ hxx_epilogue_file, NarrowString,
+ ixx_epilogue_file, NarrowString,
+ cxx_epilogue_file, NarrowString,
+ epilogue_file, NarrowString,
+ show_anonymous, Boolean,
+ show_sloc, Boolean,
+ proprietary_license, Boolean
+
+ > Options;
+
+ struct OptionsSpec: Cult::CLI::OptionsSpec<Options> {};
+ }
+ }
+}
+
+#endif // CXX_PARSER_CLI_HXX
diff --git a/xsde/cxx/parser/driver-source.cxx b/xsde/cxx/parser/driver-source.cxx
new file mode 100644
index 0000000..7221741
--- /dev/null
+++ b/xsde/cxx/parser/driver-source.cxx
@@ -0,0 +1,1139 @@
+// file : xsde/cxx/parser/driver-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/parser/driver-source.hxx>
+#include <cxx/parser/print-impl-common.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/map.hxx>
+#include <cult/containers/set.hxx>
+
+#include <sstream>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ 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;
+
+ os << fq_name (t, "p:impl") << " " << inst << ";";
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::List& l)
+ {
+ if (map_.find (&l) == map_.end ())
+ {
+ String inst (find_instance_name (l));
+ map_[&l] = inst;
+
+ os << fq_name (l, "p:impl") << " " << 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;
+
+ os << fq_name (c, "p:impl") << " " << inst << ";";
+
+ 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;
+
+ os << fq_name (t, "p:impl") << " " << inst << ";";
+ }
+ }
+
+ String
+ find_instance_name (String const& raw_name)
+ {
+ String base_name (escape (raw_name + L"_p"));
+ String name (base_name);
+
+ for (UnsignedLong i (1); set_.find (name) != set_.end (); ++i)
+ {
+ std::wostringstream os;
+ os << i;
+ name = base_name + os.str ();
+ }
+
+ 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 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 << 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 << 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 << 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), 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::List& l)
+ {
+ if (type_set_.find (&l) == type_set_.end ())
+ {
+ os << map_[&l] << ".parsers (" <<
+ map_[&l.argumented ().type ()] << ");"
+ << endl;
+
+ type_set_.insert (&l);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ if (type_set_.find (&c) == type_set_.end ())
+ {
+ if (has_members (c))
+ {
+ os << map_[&c] << ".parsers (";
+
+ ArgList args (*this, map_);
+ args.dispatch (c);
+
+ os << ");"
+ << endl;
+ }
+
+ type_set_.insert (&c);
+
+ inherits (c);
+
+ if (!restriction_p (c))
+ {
+ names (c);
+ contains_compositor (c);
+ }
+ }
+ }
+
+ 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_;
+ Cult::Containers::Set<SemanticGraph::Type*> type_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 GlobalElement: Traversal::Element, Context
+ {
+ GlobalElement (Context& c, SemanticGraph::Element*& element)
+ : Context (c), element_ (element)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (options.value<CLI::root_element_first> ())
+ {
+ if (element_ == 0)
+ element_ = &e;
+ }
+ else if (String name = options.value<CLI::root_element> ())
+ {
+ if (e.name () == name)
+ element_ = &e;
+ }
+ else
+ element_ = &e; // Cover root-element-last and no option.
+ }
+
+ private:
+ SemanticGraph::Element*& element_;
+ };
+ }
+
+ Void
+ generate_driver_source (Context& ctx)
+ {
+ // Figure out the root element. Validator should have made sure
+ // it is unique.
+ //
+ SemanticGraph::Element* root (0);
+ {
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+
+ schema >> sources >> schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+ RootElement global_element (ctx.options, root);
+
+ schema >> schema_names >> ns >> ns_names >> global_element;
+
+ schema.dispatch (ctx.schema_root);
+ }
+
+ String xs (ctx.xs_ns_name ());
+ std::wostream& os (ctx.os);
+
+ InstanceSet set;
+ TypeInstanceMap map;
+ SemanticGraph::Type& root_type (root->type ());
+
+ set.insert ("doc_p");
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ os << "#include <stdio.h>" << endl;
+ else
+ os << "#include <iostream>" << endl;
+
+ os << endl
+ << "int" << endl
+ << "main (int argc, char* argv[])"
+ << "{"
+ << "const char* input;"
+ << endl
+ << "if (argc < 2)"
+ << "{"
+ << "input = \"STDIN\";";
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ os << "fprintf (stderr, \"XML file not specified, reading " <<
+ "from STDIN\\n\");";
+ else
+ os << "std::cerr << \"XML file not specified, reading " <<
+ "from STDIN\" << std::endl;";
+
+ os << "}"
+ << "else" << endl
+ << "input = argv[1];"
+ << endl;
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ {
+ os << "FILE* f = argc > 1 ? fopen (argv[1], \"rb\") : stdin;"
+ << endl
+ << "if (f == 0)"
+ << "{"
+ << "fprintf (stderr, \"%s: unable to open\\n\", input);"
+ << "return 1;"
+ << "}";
+ }
+
+ if (ctx.options.value<CLI::no_iostream> () ||
+ ctx.options.value<CLI::no_exceptions> ())
+ os << "int r = 0;"
+ << endl;
+
+ if (!ctx.options.value<CLI::no_exceptions> ())
+ os << "try"
+ << "{";
+
+ os << "// Instantiate individual parsers." << endl
+ << "//" << endl;
+
+ {
+ ParserDef def (ctx, map, set);
+ def.dispatch (root_type);
+ }
+
+ os << endl
+ << "// Connect the parsers together." << endl
+ << "//" << endl;
+
+ {
+ // @@ I can simply iterate over the map instead of traversing
+ // the tree all over again.
+ //
+ ParserConnect connect (ctx, map);
+ connect.dispatch (root_type);
+ }
+
+ String const& root_p (map[&root_type]);
+
+ os << "// Parse the XML document." << endl
+ << "//" << endl;
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ os << "bool io_error = false;";
+
+ if (ctx.options.value<CLI::no_exceptions> ())
+ os << xs << "::parser_error e;"
+ << endl
+ << "do"
+ << "{";
+
+ if (root->namespace_().name ())
+ os << xs << "::document_pimpl doc_p (" << endl
+ << root_p << "," << endl
+ << ctx.strlit (root->namespace_().name ()) << "," << endl
+ << ctx.strlit (root->name ()) << ");"
+ << endl;
+ else
+ os << xs << "::document_pimpl doc_p (" << root_p << ", " <<
+ ctx.strlit (root->name ()) << ");"
+ << endl;
+
+ if (ctx.options.value<CLI::no_exceptions> ())
+ os << "if (e = doc_p._error ())" << endl
+ << "break;"
+ << endl;
+
+ os << root_p << ".pre ();";
+
+ if (ctx.options.value<CLI::no_exceptions> ())
+ os << endl
+ << "if (e = " << root_p << "._error ())" << endl
+ << "break;";
+
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ {
+ os << endl
+ << "char buf[4096];"
+ << endl
+ << "do"
+ << "{"
+ << "size_t s = fread (buf, 1, sizeof (buf), f);"
+ << endl
+ << "if (s != sizeof (buf) && ferror (f))"
+ << "{"
+ << "io_error = true;"
+ << "break;"
+ << "}";
+
+ if (ctx.options.value<CLI::no_exceptions> ())
+ os << "doc_p.parse (buf, s, feof (f) != 0);"
+ << "e = doc_p._error ();"
+ << "}"
+ << "while (!e && !feof (f));"
+ << endl
+ << "if (io_error || e)" << endl
+ << "break;"
+ << endl;
+ else
+ os << "doc_p.parse (buf, s, feof (f) != 0);"
+ << "}"
+ << "while (!feof (f));"
+ << endl
+ << "if (!io_error)"
+ << "{";
+ }
+ else
+ {
+ os << endl
+ << "if (argc < 2)" << endl
+ << "doc_p.parse (std::cin);"
+ << "else" << endl
+ << "doc_p.parse (argv[1]);"
+ << endl;
+
+ if (ctx.options.value<CLI::no_exceptions> ())
+ os << "if (e = doc_p._error ())" << endl
+ << "break;"
+ << endl;
+ }
+
+ String const& ret (Context::ret_type (root_type));
+ String const& post (Context::post_name (root_type));
+
+ if (ret == L"void")
+ {
+ os << root_p << "." << post << " ();";
+
+ if (ctx.options.value<CLI::no_exceptions> ())
+ os << "e = " << root_p << "._error ();";
+ }
+ else
+ {
+ os << Context::arg_type (root_type) << " v = " <<
+ root_p << "." << post << " ());"
+ << endl;
+
+ if (ctx.options.value<CLI::no_exceptions> ())
+ os << "if (e = " << root_p << "._error ())" << endl
+ << "break;"
+ << endl;
+
+ if (ctx.options.value<CLI::generate_print_impl> ())
+ {
+ PrintCall t (ctx, root->name (), "v");
+ t.dispatch (root_type);
+ }
+ else
+ {
+ os << "// TODO" << endl
+ << "//" << endl;
+ }
+
+ {
+ DeleteCall t (ctx, "v");
+ t.dispatch (root_type);
+ }
+ }
+
+ if (ctx.options.value<CLI::no_exceptions> ())
+ os << "}"
+ << "while (false);"
+ << endl;
+ else if (ctx.options.value<CLI::no_iostream> ())
+ os << "}" // if (!io_error)
+ << "else"
+ << "{"
+ << "fprintf (stderr, \"%s: read failure\\n\", input);"
+ << "r = 1;"
+ << "}";
+
+ // Error handling.
+ //
+
+ if (ctx.options.value<CLI::no_exceptions> ())
+ {
+ os << "// Handle errors." << endl
+ << "//" << endl;
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ {
+ os << "if (io_error)"
+ << "{";
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ os << "fprintf (stderr, \"%s: read failure\\n\", input);";
+ else
+ os << "std::cerr << input << \": read failure\" << std::endl;";
+
+ os << "r = 1;"
+ << "}"
+ << "else ";
+ }
+
+ os << "if (e)"
+ << "{"
+ << "switch (e.type ())"
+ << "{"
+ << "case " << xs << "::parser_error::sys:"
+ << "{";
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ os << "fprintf (stderr, \"%s: %s\\n\", input, e.sys_text ());";
+ else
+ os << "std::cerr << input << \": \" << e.sys_text () << std::endl;";
+
+ os << "break;"
+ << "}"
+ << "case " << xs << "::parser_error::xml:"
+ << "{";
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ os << "fprintf (stderr, \"%s:%lu:%lu: %s\\n\"," << endl
+ << "input, e.line (), e.column (), e.xml_text ());";
+ else
+ os << "std::cerr << input << ':' << e.line () << ':'" << endl
+ << " << e.column () << \": \" << e.xml_text () << std::endl;";
+
+ os << "break;"
+ << "}";
+
+ if (!ctx.options.value<CLI::suppress_validation> ())
+ {
+ os << "case " << xs << "::parser_error::schema:"
+ << "{";
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ os << "fprintf (stderr, \"%s:%lu:%lu: %s\\n\"," << endl
+ << "input, e.line (), e.column (), e.schema_text ());";
+ else
+ os << "std::cerr << input << ':' << e.line () << ':'" << endl
+ << " << e.column () << \": \" << e.schema_text () << std::endl;";
+
+ os << "break;"
+ << "}";
+ }
+
+ os << "case " << xs << "::parser_error::app:"
+ << "{";
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ os << "fprintf (stderr, \"%s:%lu:%lu: application error %d\\n\"," << endl
+ << "input, e.line (), e.column (), e.app_code ());";
+ else
+ os << "std::cerr << input << ':' << e.line () << ':'" << endl
+ << " << e.column () << \": application error \"" << endl
+ << " << e.app_code () << std::endl;";
+
+ os << "break;"
+ << "}"
+ << "default:"
+ << "{"
+ << "break;"
+ << "}"
+ << "}" //switch
+ << "r = 1;"
+ << "}"; // else if (e)
+ }
+ else
+ {
+ os << "}" // try
+ << "catch (const " << xs << "::parser_exception& e)"
+ << "{";
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ os << "fprintf (stderr, \"%s:%lu:%lu: %s\\n\"," << endl
+ << "input, e.line (), e.column (), e.text ());"
+ << "r = 1;";
+ else
+ os << "std::cerr << input << ':' << e.line () << ':'" << endl
+ << " << e.column () << \": \" << e.text () << std::endl;"
+ << "return 1;";
+
+ os << "}";
+
+ if (!ctx.options.value<CLI::no_iostream> ())
+ {
+ os << "catch (const std::ios_base::failure&)"
+ << "{"
+ << "std::cerr << input << \": unable to open or " <<
+ "read failure\" << std::endl;"
+ << "return 1;"
+ << "}";
+ }
+ }
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ os << "if (argc > 1)" << endl
+ << "fclose (f);"
+ << endl;
+
+ if (ctx.options.value<CLI::no_iostream> () ||
+ ctx.options.value<CLI::no_exceptions> ())
+ os << "return r;";
+ else
+ os << "return 0;";
+
+ os << "}"; // main
+ }
+ }
+}
diff --git a/xsde/cxx/parser/driver-source.hxx b/xsde/cxx/parser/driver-source.hxx
new file mode 100644
index 0000000..f829d41
--- /dev/null
+++ b/xsde/cxx/parser/driver-source.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/parser/driver-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_PARSER_DRIVER_SOURCE_HXX
+#define CXX_PARSER_DRIVER_SOURCE_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/parser/elements.hxx>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ Void
+ generate_driver_source (Context&);
+ }
+}
+
+#endif // CXX_PARSER_DRIVER_SOURCE_HXX
diff --git a/xsde/cxx/parser/element-validation-source.cxx b/xsde/cxx/parser/element-validation-source.cxx
new file mode 100644
index 0000000..e5d3589
--- /dev/null
+++ b/xsde/cxx/parser/element-validation-source.cxx
@@ -0,0 +1,2120 @@
+// file : xsde/cxx/parser/element-validation-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/parser/element-validation-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/vector.hxx>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ namespace
+ {
+ typedef Cult::Containers::Vector<SemanticGraph::Particle*> Particles;
+
+ // Find particle that can be absent.
+ //
+ struct OptionalParticleTest: Traversal::Choice
+ {
+ OptionalParticleTest (SemanticGraph::Particle*& result)
+ : is_optional_ (optional_), result_ (result)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ using SemanticGraph::Choice;
+ result_ = 0;
+ optional_ = false;
+
+ for (Choice::ContainsIterator i (c.contains_begin ());
+ result_ == 0 && i != c.contains_end ();
+ ++i)
+ {
+ is_optional_.dispatch (i->particle ());
+ if (optional_)
+ result_ = &i->particle ();
+ }
+ }
+
+ struct IsOptional: Traversal::Choice,
+ Traversal::Sequence,
+ Traversal::Element,
+ Traversal::Any
+ {
+ IsOptional (Boolean& r)
+ : r_ (r)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ if (!r_ && c.min () == 0)
+ r_ = true;
+
+ // We need at least one particle to be optional for the whole
+ // choice to be optional.
+ //
+ using SemanticGraph::Choice;
+
+ for (Choice::ContainsIterator i (c.contains_begin ());
+ !r_ && i != c.contains_end ();
+ ++i)
+ {
+ dispatch (i->particle ());
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ if (!r_ && s.min () == 0)
+ r_ = true;
+
+ // We need all particles to be optional for the whole sequence
+ // to be optional.
+ //
+ using SemanticGraph::Sequence;
+
+ for (Sequence::ContainsIterator i (s.contains_begin ());
+ !r_ && i != s.contains_end ();
+ ++i)
+ {
+ Boolean r (false);
+ IsOptional test (r);
+ test.dispatch (i->particle ());
+ if (!r)
+ return;
+ }
+
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (!r_ && e.min () == 0)
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ if (!r_ && a.min () == 0)
+ r_ = true;
+ }
+
+ private:
+ Boolean& r_;
+ };
+
+ private:
+ Boolean optional_;
+ IsOptional is_optional_;
+ SemanticGraph::Particle*& result_;
+ };
+
+ //
+ //
+ Void
+ choice_arm_call (SemanticGraph::Particle* p,
+ SemanticGraph::Choice* c,
+ Context* ctx)
+ {
+ using SemanticGraph::Choice;
+
+ ctx->os << "this->" << Context::earm (*c) << " (" <<
+ Context::etag (*p) << ");";
+
+ if ((c = dynamic_cast<Choice*> (p)))
+ {
+ OptionalParticleTest test (p);
+ test.traverse (*c);
+
+ if (p)
+ choice_arm_call (p, c, ctx);
+ }
+ }
+
+ //
+ //
+ struct ParticleTest: Traversal::Compositor,
+ Traversal::Element,
+ Traversal::Any,
+ Context
+ {
+ ParticleTest (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ String const& name (e.name ());
+ Boolean subst (poly_code && e.global ());
+
+ if (subst)
+ os << "(";
+
+ if (e.qualified () && e.namespace_ ().name ())
+ {
+ String const& ns (e.namespace_ ().name ());
+
+ os << "n == " << L << strlit (name) << " &&" << endl
+ << "ns == " << L << strlit (ns);
+ }
+ else
+ os << "n == " << L << strlit (name) << " && ns.empty ()";
+
+
+ // Only a globally-defined element can be a subst-group root.
+ //
+ if (subst)
+ {
+ String root_id (e.name ());
+
+ if (String const& ns = e.namespace_ ().name ())
+ {
+ root_id += L' ';
+ root_id += ns;
+ }
+
+ os << ") ||" << endl
+ << "::xsde::cxx::parser::substitution_map_instance ()" <<
+ ".check (" << endl
+ << "ns, n, " << strlit (root_id) << ", t)";
+ }
+
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ String const& ns (a.definition_namespace ().name ());
+
+ // Note that we need to make sure the "flush" element (both name
+ // and namespace are empty) does not match any compositor.
+ //
+ for (SemanticGraph::Any::NamespaceIterator i (a.namespace_begin ()),
+ e (a.namespace_end ()); i != e;)
+ {
+ if (*i == L"##any")
+ {
+ os << "!n.empty ()";
+ }
+ else if (*i == L"##other")
+ {
+ if (ns)
+ {
+ // Note that here I assume that ##other does not include
+ // unqualified names in a schema with target namespace.
+ // This is not what the spec says but that seems to be
+ // the consensus.
+ //
+ os << "(!ns.empty () && ns != " << L << strlit (ns) << ")";
+ }
+ else
+ os << "!ns.empty ()";
+ }
+ else if (*i == L"##local")
+ {
+ os << "(ns.empty () && !n.empty ())";
+ }
+ else if (*i == L"##targetNamespace")
+ {
+ os << "ns == " << L << strlit (ns);
+ }
+ else
+ {
+ os << "ns == " << L << strlit (*i);
+ }
+
+ if (++i != e)
+ os << " ||" << endl;
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Compositor& c)
+ {
+ // This compositor should already have been tested for
+ // triviality (empty).
+ //
+ Particles const& p (c.context ().get<Particles> ("p:prefixes"));
+
+ Boolean paren (p.size () != 1);
+
+ for (Particles::ConstIterator i (p.begin ()), e (p.end ());
+ i != e;)
+ {
+ if (paren)
+ os << "(";
+
+ dispatch (**i);
+
+ if (paren)
+ os << ")";
+
+ if (++i != e)
+ os << " ||" << endl;
+ }
+ }
+ };
+
+
+ // Generates particle namespace-name pair. Used to generate
+ // the _expected_element call.
+ //
+ struct ParticleName: Traversal::Compositor,
+ Traversal::Element,
+ Traversal::Any,
+ Context
+ {
+ ParticleName (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ String ns (e.qualified () ? e.namespace_ ().name () : String ());
+
+ os << L << strlit (ns) << ", " << L << strlit (e.name ());
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ String const& ns (*a.namespace_begin ());
+
+ os << L << strlit (ns) << ", " << L << "\"*\"";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Compositor& c)
+ {
+ Particles const& p (c.context ().get<Particles> ("p:prefixes"));
+
+ dispatch (**p.begin ());
+ }
+ };
+
+
+ // Common base for the ParticleIn{All, Choice, Sequence} treversers.
+ //
+ struct ParticleInCompositor: protected Context
+ {
+ protected:
+ ParticleInCompositor (Context& c, SemanticGraph::Complex& type)
+ : Context (c), type_ (type), particle_test_ (c)
+ {
+ }
+
+
+ // Generate sub-parser setup code as well as the pre/post calls.
+ //
+ Void
+ pre_post_calls (SemanticGraph::Particle& p)
+ {
+ using SemanticGraph::Element;
+ using SemanticGraph::Complex;
+
+ if (Element* e = dynamic_cast<Element*> (&p))
+ {
+ SemanticGraph::Type& type (e->type ());
+ Boolean poly (poly_code && !anonymous (type));
+
+ String const& name (ename (*e));
+ String inst (poly ? emember_cache (*e) : emember (*e));
+
+ String def_parser, map;
+
+ if (poly)
+ {
+ def_parser = emember (*e);
+ map = emember_map (*e);
+ }
+
+ if (poly)
+ {
+ String cast (mixin ? L"dynamic_cast" : L"static_cast");
+ String fq_type (fq_name (type));
+
+ os << "if (t == 0 && this->" << def_parser << " != 0)" << endl
+ << "this->" << inst << " = this->" << def_parser << ";"
+ << "else"
+ << "{"
+ << "const char* ts = " << fq_type << "::_static_type ();"
+ << endl
+ << "if (t == 0)" << endl
+ << "t = ts;"
+ << endl
+ << "if (this->" << def_parser << " != 0 && " <<
+ "strcmp (t, ts) == 0)" << endl
+ << "this->" << inst << " = this->" << def_parser << ";"
+ << "else"
+ << "{";
+
+ // Check that the types are related by inheritance.
+ //
+ os << "if (t != ts &&" << endl
+ << "!::xsde::cxx::parser::validating::" <<
+ "inheritance_map_instance ().check (t, ts))"
+ << "{"
+ << "ctx.schema_error (::xsde::cxx::schema_error::not_derived);"
+ << "return;"
+ << "}";
+
+ os << "if (this->" << map << " != 0)" << endl
+ << "this->" << inst << " = " << cast << "< " <<
+ fq_type << "* > (" << endl
+ << "this->" << map << "->find (t));"
+ << "else" << endl
+ << "this->" << inst << " = 0;"
+ << "}"
+ << "}";
+ }
+
+ String const& post (post_name (type));
+
+ os << "if (this->" << inst << ")"
+ << "{"
+ << "this->" << inst << "->pre ();";
+
+ if (!exceptions)
+ {
+ // Note that after pre() we need to check both parser and
+ // context error states because of the recursive parsing.
+ //
+ os << endl
+ << "if (this->" << inst << "->_error_type ())" << endl
+ << "this->" << inst << "->_copy_error (ctx);"
+ << endl
+ << "if (!ctx.error_type ())" << endl;
+ }
+
+ os << "this->" << inst << "->_pre_impl (ctx);"
+ << "}"
+ << "else" << endl
+ << "ctx.current_.depth_++;" // Ignoring document fragment.
+ << endl
+ << "}"
+ << "else" // start
+ << "{"
+ << "if (this->" << inst << ")"
+ << "{";
+
+ String const& ret (ret_type (type));
+
+ if (ret == L"void")
+ os << "this->" << inst << "->" << post << " ();";
+ else
+ os << arg_type (type) << " tmp = this->" << inst << "->" <<
+ post << " ();";
+
+ if (!exceptions)
+ {
+ // Note that after post() we need to check both parser and
+ // context error states because of the recursive parsing.
+ //
+ os << endl
+ << "if (this->" << inst << "->_error_type ())" << endl
+ << "this->" << inst << "->_copy_error (ctx);"
+ << endl
+ << "if (!ctx.error_type ())" << endl;
+ }
+
+ if (ret == L"void")
+ os << "this->" << name << " ();";
+ else
+ os << "this->" << name << " (tmp);";
+
+ os << "}";
+ }
+ else
+ {
+ os << "ctx.current_.any_ = true;"
+ << "ctx.current_.depth_++;"
+ << endl
+ << "this->_start_any_element (ns, n" <<
+ (poly_runtime ? (poly_code ? ", t" : ", 0") : "") << ");"
+ << "}"
+ << "else" // start
+ << "{"
+ << "this->_end_any_element (ns, n);";
+ }
+ }
+
+
+ protected:
+ SemanticGraph::Complex& type_;
+ ParticleTest particle_test_;
+ };
+
+
+
+ // The 'all' compositor can only contain elements with min={0,1}, max=1.
+ //
+ struct ParticleInAll: Traversal::Element,
+ ParticleInCompositor
+ {
+ ParticleInAll (Context& c, SemanticGraph::Complex& type)
+ : ParticleInCompositor (c, type)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ UnsignedLong state (e.context ().get<UnsignedLong> ("p:state"));
+
+ SemanticGraph::Compositor& c (
+ e.contained_particle ().compositor ());
+
+ if (state != 0)
+ os << "else ";
+
+ os << "if (";
+
+ particle_test_.traverse (e);
+
+ os << ")"
+ << "{"
+ << "if (count[" << state << "UL] == 0)"
+ << "{"
+ << "if (start)"
+ << "{";
+
+ if (c.min () == 0)
+ {
+ // Make the call to _present if we haven't seen any
+ // elements yet.
+ //
+ UnsignedLong state_count (
+ c.context().get<UnsignedLong> ("p:state-count"));
+
+ if (state_count > 1)
+ {
+ os << "if (";
+
+ Boolean sub (false);
+
+ for (UnsignedLong i (0); i < state_count; ++i)
+ {
+ if (i == state)
+ continue;
+
+ if (sub)
+ os << " &&" << endl;
+ else
+ sub = true;
+
+ os << "count[" << i << "UL] == 0";
+ }
+
+ os << ")" << endl
+ << "this->" << epresent (c) << " ();"
+ << endl;
+ }
+ }
+
+ pre_post_calls (e);
+
+ os << "count[" << state << "UL] = 1;"
+ << "}"
+ << "}"
+ << "else" // count != 0
+ << "{"
+ << "assert (start);" // Assuming well-formed XML.
+
+ // Since there is never more content after 'all', we could have
+ // as well thrown here. But instead we will let the code in
+ // start_element handle this along with other unexpected
+ // elements.
+ //
+ << "state = ~0UL;"
+ << "}"
+ << "}";
+ }
+ };
+
+
+ //
+ //
+ struct ParticleInChoice: Traversal::Particle,
+ Traversal::Compositor,
+ ParticleInCompositor
+ {
+ ParticleInChoice (Context& c, SemanticGraph::Complex& type)
+ : ParticleInCompositor (c, type), particle_name_ (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Particle& p)
+ {
+ using SemanticGraph::Element;
+
+ UnsignedLong state (p.context ().get<UnsignedLong> ("p:state"));
+
+ UnsignedLong min (p.min ()), max (p.max ());
+
+ os << "case " << state << "UL:" << endl
+ << "{";
+
+ if (max != 1) // We don't need the test if max == 1.
+ {
+ os << "if (";
+
+ particle_test_.dispatch (p);
+
+ os << ")"
+ << "{";
+ }
+
+ os << "if (start)"
+ << "{";
+
+ pre_post_calls (p);
+
+ switch (max)
+ {
+ case 0:
+ {
+ os << "count++;";
+ break;
+ }
+ case 1:
+ {
+ // We do not need to increment count because min <= max and
+ // we do not generate min check for min <= 1 (see below).
+ //
+ os << "state = ~0UL;";
+ break;
+ }
+ default:
+ {
+ os << "if (++count == " << max << "UL)" << endl
+ << "state = ~0UL;";
+ }
+ };
+
+ os << "}"; // start
+
+ // We've already moved to the final state if max == 1.
+ //
+ if (max != 1)
+ {
+ os << "}"
+ << "else"
+ << "{"
+ << "assert (start);"; // Assuming well-formed XML
+
+ // Check if min cardinality requirements have been met. Since
+ // count is always >= 1, don't generate dead code if min <= 1.
+ //
+ if (min > 1)
+ {
+ os << "if (count < " << min << "UL)" << endl
+ << "this->_schema_error (" <<
+ "::xsde::cxx::schema_error::expected_element);";
+
+ /*
+ << "this->_expected_element (" << endl;
+ particle_name_.dispatch (p);
+ os << "," << endl
+ << "ns, n);";
+ */
+ }
+
+
+ os << "state = ~0UL;"
+ << "}";
+ }
+
+ os << "break;"
+ << "}"; // case
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Compositor& c)
+ {
+ using SemanticGraph::Choice;
+ using SemanticGraph::Sequence;
+ using SemanticGraph::Compositor;
+
+ Boolean choice (c.is_a<Choice> ());
+ SemanticGraph::Context& cc (c.context ());
+
+ UnsignedLong max (c.max ());
+ UnsignedLong min (cc.get<UnsignedLong> ("p:effective-min"));
+ UnsignedLong n (cc.get<UnsignedLong> ("p:comp-number"));
+ UnsignedLong state (cc.get<UnsignedLong> ("p:state"));
+
+ String func (choice ? "choice_" : "sequence_");
+
+ os << "case " << state << "UL:" << endl
+ << "{"
+ << "unsigned long s = ~0UL;"
+ << endl;
+
+ Boolean first (true);
+
+ for (Compositor::ContainsIterator ci (c.contains_begin ());
+ ci != c.contains_end (); ++ci)
+ {
+ SemanticGraph::Particle& p (ci->particle ());
+
+ if (p.is_a<Compositor> () && !cc.count ("p:comp-number"))
+ continue; // Empty compositor.
+
+ if (!p.context ().count ("p:prefix"))
+ break;
+
+ UnsignedLong state (p.context ().get<UnsignedLong> ("p:state"));
+
+ if (first)
+ first = false;
+ else
+ os << "else ";
+
+ os << "if (";
+
+ particle_test_.dispatch (p);
+
+ os << ")" << endl
+ << "s = " << state << "UL;";
+ }
+
+ if (!choice)
+ {
+ for (Compositor::ContainsIterator ci (c.contains_begin ());
+ ci != c.contains_end (); ++ci)
+ {
+ Choice* pc = dynamic_cast<Choice*> (&ci->particle ());
+
+ if (pc && pc->min () == 1 && pc->max () == 1 &&
+ pc->context ().get<UnsignedLong> ("p:effective-min") == 0)
+ {
+ // This is a required choice with effective-min == 0 (i.e.,
+ // it contains optional particle). We need to call the arm
+ // callback with that optional particle's tag.
+ //
+
+ SemanticGraph::Particle* p (0);
+ OptionalParticleTest test (p);
+ test.traverse (*pc);
+
+ if (p)
+ {
+ UnsignedLong state (
+ pc->context ().get<UnsignedLong> ("p:state"));
+
+ os << endl
+ << "if (s > " << state << "UL)" << endl
+ << "{";
+ choice_arm_call (p, pc, this);
+ os << "}";
+ }
+ }
+ }
+ }
+
+ // This compositor.
+ //
+ os << endl
+ << "if (s != ~0UL)"
+ << "{"
+ << "assert (start);"; // End is handled by the sub-machine.
+
+ switch (max)
+ {
+ case 0:
+ {
+ os << "count++;";
+ break;
+ }
+ case 1:
+ {
+ // We do not need to increment count because min <= max and
+ // we do not generate min check for min <= 1 (see below).
+ //
+ os << "state = ~0UL;";
+ break;
+ }
+ default:
+ {
+ os << "if (++count == " << max << "UL)" << endl
+ << "state = ~0UL;";
+ }
+ };
+
+ // Delegate to the sub-machine and call _arm, _present, or _next
+ // if necessary.
+ //
+
+ os << endl
+ << "v_state_& vs = *static_cast< v_state_* > (" <<
+ "this->v_state_stack_.top ());"
+ << "v_state_descr_& vd = vs.data[vs.size++];" // push
+ << endl
+ << "vd.func = &" << ename (type_) << "::" << func << n << ";"
+ << "vd.state = s;"
+ << "vd.count = 0;"
+ << endl;
+
+ if (Choice* pc = dynamic_cast<Choice*> (&c))
+ {
+ os << "this->" << earm (*pc) << " (static_cast< " <<
+ earm_tag (*pc) << " > (s));";
+ }
+ else
+ {
+ Sequence& s (dynamic_cast<Sequence&> (c));
+
+ if (max != 1)
+ os << "this->" << enext (s) << " ();";
+ else if (c.min () == 0)
+ os << "this->" << epresent (s) << " ();";
+ }
+
+ os << "this->" << func << n << " (vd.state, vd.count, ns, n, " <<
+ (poly_runtime ? (poly_code ? "t, " : "0, ") : "") << "true);"
+ << "}";
+
+
+ // Not this compositor. We've elready moved to the final state
+ // if max == 1.
+ //
+ if (max != 1)
+ {
+ os << "else"
+ << "{"
+ << "assert (start);"; // Assuming well-formed XML
+
+ // Check if min cardinality requirements have been met. Since
+ // count is always >= 1, don't generate dead code if min <= 1.
+ //
+ if (min > 1)
+ {
+ os << "if (count < " << min << "UL)" << endl
+ << "this->_schema_error (" <<
+ "::xsde::cxx::schema_error::expected_element);";
+
+ /*
+ << "this->_expected_element (" << endl;
+ particle_name_.dispatch (c);
+ os << "," << endl
+ << "ns, n);";
+ */
+ }
+
+ os << "state = ~0UL;"
+ << "}";
+ }
+
+ os << "break;"
+ << "}"; // case
+ }
+
+ private:
+ ParticleName particle_name_;
+ };
+
+
+ //
+ //
+ struct ParticleInSequence: Traversal::Particle,
+ Traversal::Compositor,
+ ParticleInCompositor
+ {
+ ParticleInSequence (Context& c,
+ UnsignedLong state,
+ UnsignedLong next_state,
+ SemanticGraph::Complex& type)
+ : ParticleInCompositor (c, type),
+ state_ (state), particle_name_ (c)
+ {
+ // next_state == 0 indicates the terminal state (~0UL).
+ //
+ if (next_state != 0)
+ {
+ std::wostringstream ostr;
+ ostr << next_state;
+ next_state_ = ostr.str ();
+ }
+ else
+ next_state_ = L"~0";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Particle& p)
+ {
+ UnsignedLong min (p.min ()), max (p.max ());
+
+ os << "case " << state_ << "UL:" << endl
+ << "{"
+ << "if (";
+
+ particle_test_.dispatch (p);
+
+ os << ")"
+ << "{";
+
+ // This element.
+ //
+
+ os << "if (start)"
+ << "{";
+
+ pre_post_calls (p);
+
+ switch (max)
+ {
+ case 0:
+ {
+ os << "count++;";
+ break;
+ }
+ case 1:
+ {
+ os << "count = 0;"
+ << "state = " << next_state_ << "UL;";
+ break;
+ }
+ default:
+ {
+ os << "if (++count == " << max << "UL)"
+ << "{"
+ << "count = 0;"
+ << "state = " << next_state_ << "UL;"
+ << "}";
+ }
+ };
+
+ os << "}" // start
+ << "break;"
+ << "}";
+
+ // Not this element.
+ //
+
+ os << "else"
+ << "{"
+ << "assert (start);"; // Assuming well-formed XML.
+
+ // Check if min cardinality requirements have been met. Since
+ // count is always >= 0, don't generate dead code if min == 0.
+ //
+ if (min != 0)
+ {
+ os << "if (count < " << min << "UL)"
+ << "{"
+ << "this->_schema_error (" <<
+ "::xsde::cxx::schema_error::expected_element);"
+ << "break;"
+ << "}";
+
+ /*
+ << "this->_expected_element (" << endl;
+ particle_name_.dispatch (p);
+ os << "," << endl
+ << "ns, n);";
+ */
+ }
+
+ os << "count = 0;"
+ << "state = " << next_state_ << "UL;"
+ << "// Fall through." << endl
+ << "}" // else
+ << "}"; // case
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Compositor& c)
+ {
+ using SemanticGraph::Choice;
+ using SemanticGraph::Sequence;
+ using SemanticGraph::Compositor;
+
+ Boolean choice (c.is_a<Choice> ());
+ SemanticGraph::Context& cc (c.context ());
+
+ UnsignedLong max (c.max ());
+ UnsignedLong min (cc.get<UnsignedLong> ("p:effective-min"));
+ UnsignedLong n (cc.get<UnsignedLong> ("p:comp-number"));
+
+ String func (choice ? "choice_" : "sequence_");
+
+ os << "case " << state_ << "UL:" << endl
+ << "{"
+ << "unsigned long s = ~0UL;"
+ << endl;
+
+ Boolean first (true);
+
+ for (Compositor::ContainsIterator ci (c.contains_begin ());
+ ci != c.contains_end (); ++ci)
+ {
+ SemanticGraph::Particle& p (ci->particle ());
+
+ if (p.is_a<Compositor> () && !cc.count ("p:comp-number"))
+ continue; // Empty compositor.
+
+ if (!p.context ().count ("p:prefix"))
+ break;
+
+ UnsignedLong state (p.context ().get<UnsignedLong> ("p:state"));
+
+ if (first)
+ first = false;
+ else
+ os << "else ";
+
+ os << "if (";
+
+ particle_test_.dispatch (p);
+
+ os << ")" << endl
+ << "s = " << state << "UL;";
+ }
+
+ if (!choice)
+ {
+ for (Compositor::ContainsIterator ci (c.contains_begin ());
+ ci != c.contains_end (); ++ci)
+ {
+ Choice* pc = dynamic_cast<Choice*> (&ci->particle ());
+
+ if (pc && pc->min () == 1 && pc->max () == 1 &&
+ pc->context ().get<UnsignedLong> ("p:effective-min") == 0)
+ {
+ // This is a required choice with effective-min == 0 (i.e.,
+ // it contains optional particle). We need to call the arm
+ // callback with that optional particle's tag.
+ //
+
+ SemanticGraph::Particle* p (0);
+ OptionalParticleTest test (p);
+ test.traverse (*pc);
+
+ if (p)
+ {
+ UnsignedLong state (
+ pc->context ().get<UnsignedLong> ("p:state"));
+
+ os << endl
+ << "if (s > " << state << "UL)" << endl
+ << "{";
+ choice_arm_call (p, pc, this);
+ os << "}";
+ }
+ }
+ }
+ }
+
+ // This element.
+ //
+
+ os << endl
+ << "if (s != ~0UL)"
+ << "{"
+ << "assert (start);"; // End is handled by the sub-machine.
+
+ switch (max)
+ {
+ case 0:
+ {
+ os << "count++;"
+ << endl;
+ break;
+ }
+ case 1:
+ {
+ os << "count = 0;"
+ << "state = " << next_state_ << "UL;"
+ << endl;
+ break;
+ }
+ default:
+ {
+ os << "if (++count == " << max << "UL)"
+ << "{"
+ << "count = 0;"
+ << "state = " << next_state_ << "UL;"
+ << "}";
+ }
+ };
+
+ // Delegate to the sub-machine and call _arm, _present, or _next
+ // if necessary.
+ //
+
+ os << "v_state_& vs = *static_cast< v_state_* > (" <<
+ "this->v_state_stack_.top ());"
+ << "v_state_descr_& vd = vs.data[vs.size++];" // push
+ << endl
+ << "vd.func = &" << ename (type_) << "::" << func << n << ";"
+ << "vd.state = s;"
+ << "vd.count = 0;"
+ << endl;
+
+ Choice* pc = dynamic_cast<Choice*> (&c);
+
+ if (pc)
+ {
+ os << "this->" << earm (*pc) << " (static_cast< " <<
+ earm_tag (*pc) << " > (s));";
+ }
+ else
+ {
+ Sequence& s (dynamic_cast<Sequence&> (c));
+
+ if (max != 1)
+ os << "this->" << enext (s) << " ();";
+ else if (c.min () == 0)
+ os << "this->" << epresent (s) << " ();";
+ }
+
+ os << "this->" << func << n << " (vd.state, vd.count, ns, n, " <<
+ (poly_runtime ? (poly_code ? "t, " : "0, ") : "") << "true);"
+ << "break;"
+ << "}";
+
+ // Not this compositor.
+ //
+
+ os << "else"
+ << "{"
+ << "assert (start);"; // Assuming well-formed XML
+
+ if (pc && c.min () == 1 && min == 0 && max == 1)
+ {
+ // This is a required choice with effective-min == 0 (i.e.,
+ // it contains optional particle). We need to call the arm
+ // callback with that optional particle's tag.
+ //
+ SemanticGraph::Particle* p (0);
+ OptionalParticleTest test (p);
+ test.traverse (*pc);
+
+ if (p)
+ choice_arm_call (p, pc, this);
+ }
+
+ // Check if min cardinality requirements have been met. Since
+ // count is always >= 0, don't generate dead code if min == 0.
+ //
+ if (min != 0)
+ {
+ os << "if (count < " << min << "UL)"
+ << "{"
+ << "this->_schema_error (" <<
+ "::xsde::cxx::schema_error::expected_element);"
+ << "break;"
+ << "}";
+ }
+
+ os << "count = 0;"
+ << "state = " << next_state_ << "UL;"
+ << "// Fall through." << endl
+ << "}" // else
+ << "}"; // case
+ }
+
+ private:
+ UnsignedLong state_;
+ String next_state_;
+
+ ParticleName particle_name_;
+ };
+
+
+ //
+ //
+ struct ParticleFunction: Traversal::All,
+ Traversal::Choice,
+ Traversal::Sequence,
+ Context
+ {
+ ParticleFunction (Context& c, SemanticGraph::Complex& type)
+ : Context (c), type_ (type)
+ {
+ *this >> contains_particle_ >> *this;
+ }
+
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ if (!a.context().count ("p:comp-number")) // Empty compositor.
+ return;
+
+ using SemanticGraph::Element;
+ using SemanticGraph::Compositor;
+
+ os << "void " << ename (type_) << "::" << endl
+ << "all_0 (unsigned long& state," << endl
+ << "unsigned char* count," << endl
+ << "const " << string_type << "& ns," << endl
+ << "const " << string_type << "& n," << endl;
+
+ if (poly_runtime)
+ os << "const char*" << (poly_code ? " t" : "") << "," << endl;
+
+ os << "bool start)"
+ << "{";
+
+ if (poly_code)
+ os << "XSDE_UNUSED (t);"
+ << endl;
+
+ os << "::xsde::cxx::parser::context& ctx = this->_context ();"
+ << endl;
+
+ for (Compositor::ContainsIterator ci (a.contains_begin ()),
+ ce (a.contains_end ()); ci != ce; ++ci)
+ {
+ ParticleInAll t (*this, type_);
+ t.dispatch (ci->particle ());
+ }
+
+ // Handle the flush.
+ //
+ os << "else if (n.empty () && ns.empty ())"
+ << "{";
+
+ for (Compositor::ContainsIterator ci (a.contains_begin ()),
+ ce (a.contains_end ()); ci != ce; ++ci)
+ {
+ if (ci->min () == 0)
+ continue;
+
+ Element& e (dynamic_cast<Element&> (ci->particle ()));
+ String ns (e.qualified () ? e.namespace_ ().name () : String ());
+ UnsignedLong state (e.context ().get<UnsignedLong> ("p:state"));
+
+ os << "if (count[" << state << "UL] == 0)"
+ << "{"
+ << "this->_schema_error (" <<
+ "::xsde::cxx::schema_error::expected_element);"
+ << "return;"
+ << "}";
+
+ /*
+ << "this->_expected_element (" << endl
+ << L << "\"" << ns << "\", " <<
+ L << "\"" << e.name () << "\");";
+ */
+ }
+
+ // Error handling code relies on the fact that there is no
+ // code after the if-else block.
+ //
+ os << "state = ~0UL;"
+ << "}"
+ << "else" << endl
+ << "state = ~0UL;"
+ << "}";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ using SemanticGraph::Compositor;
+
+ SemanticGraph::Context& cc (c.context ());
+
+ if (!cc.count ("p:comp-number")) // Empty compositor.
+ return;
+
+ UnsignedLong n (cc.get<UnsignedLong> ("p:comp-number"));
+
+ os << "void " << ename (type_) << "::" << endl
+ << "choice_" << n << " (unsigned long& state," << endl
+ << "unsigned long& count," << endl
+ << "const " << string_type << "& ns," << endl
+ << "const " << string_type << "& n," << endl;
+
+ if (poly_runtime)
+ os << "const char*" << (poly_code ? " t" : "") << "," << endl;
+
+ os << "bool start)"
+ << "{"
+ << "::xsde::cxx::parser::context& ctx = this->_context ();"
+ << endl;
+
+ os << "XSDE_UNUSED (count);"
+ << "XSDE_UNUSED (ns);"
+ << "XSDE_UNUSED (n);"
+ << "XSDE_UNUSED (ctx);";
+
+ if (poly_code)
+ os << "XSDE_UNUSED (t);";
+
+
+ os << endl
+ << "switch (state)"
+ << "{";
+
+ for (Compositor::ContainsIterator ci (c.contains_begin ()),
+ ce (c.contains_end ()); ci != ce; ++ci)
+ {
+ SemanticGraph::Particle& p (ci->particle ());
+
+ if (p.is_a<Compositor> () && !p.context().count ("p:comp-number"))
+ continue; // Empty compositor.
+
+ ParticleInChoice t (*this, type_);
+ t.dispatch (p);
+ }
+
+ // Error handling code relies on the fact that there is no
+ // code after the switch statement.
+ //
+ os << "}" // switch
+ << "}";
+
+
+ // Generate nested compositor functions.
+ //
+ Traversal::Choice::traverse (c);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ if (!s.context().count ("p:comp-number")) // Empty compositor.
+ return;
+
+ using SemanticGraph::Compositor;
+
+ UnsignedLong n (s.context ().get<UnsignedLong> ("p:comp-number"));
+
+ os << "void " << ename (type_) << "::" << endl
+ << "sequence_" << n << " (unsigned long& state," << endl
+ << "unsigned long& count," << endl
+ << "const " << string_type << "& ns," << endl
+ << "const " << string_type << "& n," << endl;
+
+ if (poly_runtime)
+ os << "const char*" << (poly_code ? " t" : "") << "," << endl;
+
+ os << "bool start)"
+ << "{"
+ << "::xsde::cxx::parser::context& ctx = this->_context ();"
+ << endl;
+
+ if (poly_code)
+ os << "XSDE_UNUSED (t);";
+
+ os << "XSDE_UNUSED (ctx);"
+ << endl;
+
+ os << "switch (state)"
+ << "{";
+
+ UnsignedLong state (0);
+
+ for (Compositor::ContainsIterator ci (s.contains_begin ()),
+ ce (s.contains_end ()); ci != ce;)
+ {
+ SemanticGraph::Particle& p (ci->particle ());
+
+ if (p.is_a<Compositor> () && !p.context().count ("p:comp-number"))
+ {
+ // Empty compositor.
+ //
+ ++ci;
+ continue;
+ }
+
+ // Find the next state.
+ //
+ do
+ ++ci;
+ while (ci != ce &&
+ ci->particle ().is_a<Compositor> () &&
+ !ci->particle ().context().count ("p:comp-number"));
+
+ UnsignedLong next (ci == ce ? 0 : state + 1);
+
+ ParticleInSequence t (*this, state++, next, type_);
+ t.dispatch (p);
+ }
+
+ // Error handling code relies on the fact that there is no
+ // code after the switch statement.
+ //
+ os << "case ~0UL:" << endl
+ << "break;"
+ << "}" // switch
+ << "}";
+
+ // Generate nested compositor functions.
+ //
+ Traversal::Sequence::traverse (s);
+ }
+
+ private:
+ SemanticGraph::Complex& type_;
+ Traversal::ContainsParticle contains_particle_;
+ };
+
+ //
+ //
+ struct CompositorPre: Traversal::All,
+ Traversal::Compositor,
+ Context
+ {
+ CompositorPre (Context& c, SemanticGraph::Complex& type)
+ : Context (c), type_ (type)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ // Clear the counts and push the initial state.
+ //
+ os << "v_all_count_.push ();"
+ << endl;
+
+ SemanticGraph::Compositor& c (a);
+ traverse (c);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Compositor&) // Choice and sequence.
+ {
+ os << "v_state_& vs = *static_cast< v_state_* > (" <<
+ "this->v_state_stack_.top ());"
+ << "v_state_descr_& vd = vs.data[vs.size++];" // push
+ << endl
+ << "vd.func = 0;"
+ << "vd.state = 0;"
+ << "vd.count = 0;";
+ }
+
+ private:
+ SemanticGraph::Complex& type_;
+ };
+
+
+ //
+ //
+ struct CompositorStartElement: Traversal::All,
+ Traversal::Compositor,
+ Context
+ {
+ CompositorStartElement (Context& c, SemanticGraph::Complex& type)
+ : Context (c), type_ (type),
+ particle_test_ (c), particle_name_ (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All&)
+ {
+ // The 'all' state machine reaches the final state only
+ // on an unknown element, in which case we won't get here
+ // again (it would be a validation error). Note that 'all'
+ // compositor cannot contain nested compositors so we don't
+ // need to re-set vd.
+ //
+ os << "all_0 (vd->state, v_all_count_.top (), ns, n, " <<
+ (poly_runtime ? (poly_code ? "t, " : "0, ") : "") << "true);"
+ << endl
+ << "if (vd->state != ~0UL || ctx.error_type ())" << endl
+ << "vd->count++;"
+ << "else" << endl
+ << "return false;" // Let our parent handle this.
+ << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Compositor& c) // Choice and sequence.
+ {
+ using SemanticGraph::Choice;
+ using SemanticGraph::Sequence;
+ using SemanticGraph::Compositor;
+
+ Boolean choice (c.is_a<Choice> ());
+ SemanticGraph::Context& cc (c.context ());
+
+ UnsignedLong max (c.max ());
+ UnsignedLong min (cc.get<UnsignedLong> ("p:effective-min"));
+ UnsignedLong n (cc.get<UnsignedLong> ("p:comp-number"));
+
+ String func (choice ? "choice_" : "sequence_");
+
+ // Invoke the current state machine. If it reaches its
+ // terminal state, pop it and invoke the next one until
+ // we reach the top, which requires special handling.
+ //
+ os << "while (vd->func != 0)"
+ << "{"
+ << "(this->*vd->func) (vd->state, vd->count, ns, n, " <<
+ (poly_runtime ? (poly_code ? "t, " : "0, ") : "") << "true);"
+ << endl
+ << "vd = vs.data + (vs.size - 1);" // re-acquire
+ << endl
+ << "if (vd->state == ~0UL && !ctx.error_type ())" << endl
+ << "vd = vs.data + (--vs.size - 1);" // pop
+ << "else" << endl
+ << "break;"
+ << "}";
+
+
+ // Check if we got to the top. This code is pretty much the
+ // same as the one found in ParticleInSequence.
+ //
+ os << "if (vd->func == 0)"
+ << "{"
+ << "if (vd->state != ~0UL)"
+ << "{"
+ << "unsigned long s = ~0UL;"
+ << endl;
+
+ Boolean first (true);
+
+ // Note that we don't need to worry about the compositor
+ // being empty - this case is handled by our caller.
+ //
+ for (Compositor::ContainsIterator ci (c.contains_begin ());
+ ci != c.contains_end (); ++ci)
+ {
+ SemanticGraph::Particle& p (ci->particle ());
+
+ if (p.is_a<Compositor> () && !cc.count ("p:comp-number"))
+ continue; // Empty compositor.
+
+ if (!p.context ().count ("p:prefix"))
+ break;
+
+ UnsignedLong state (p.context ().get<UnsignedLong> ("p:state"));
+
+ if (first)
+ first = false;
+ else
+ os << "else ";
+
+ os << "if (";
+
+ particle_test_.dispatch (p);
+
+ os << ")" << endl
+ << "s = " << state << "UL;";
+ }
+
+ if (!choice)
+ {
+ for (Compositor::ContainsIterator ci (c.contains_begin ());
+ ci != c.contains_end (); ++ci)
+ {
+ Choice* pc = dynamic_cast<Choice*> (&ci->particle ());
+
+ if (pc && pc->min () == 1 && pc->max () == 1 &&
+ pc->context ().get<UnsignedLong> ("p:effective-min") == 0)
+ {
+ // This is a required choice with effective-min == 0 (i.e.,
+ // it contains optional particle). We need to call the arm
+ // callback with that optional particle's tag.
+ //
+
+ SemanticGraph::Particle* p (0);
+ OptionalParticleTest test (p);
+ test.traverse (*pc);
+
+ if (p)
+ {
+ UnsignedLong state (
+ pc->context ().get<UnsignedLong> ("p:state"));
+
+ os << endl
+ << "if (s > " << state << "UL)" << endl
+ << "{";
+ choice_arm_call (p, pc, this);
+ os << "}";
+ }
+ }
+ }
+ }
+
+ os << endl
+ << "if (s != ~0UL)"
+ << "{";
+
+ // This element is a prefix of the root compositor.
+ //
+
+ switch (max)
+ {
+ case 0:
+ {
+ os << "vd->count++;";
+ break;
+ }
+ case 1:
+ {
+ os << "vd->count++;"
+ << "vd->state = ~0UL;";
+ break;
+ }
+ default:
+ {
+ os << "if (++vd->count == " << max << "UL)" << endl
+ << "vd->state = ~0UL;";
+ }
+ };
+
+ // Delegate to the sub-machine and call _arm, _present, or _next
+ // if necessary.
+ //
+
+ os << endl
+ << "vd = vs.data + vs.size++;" // push
+ << "vd->func = &" << ename (type_) << "::" << func << n << ";"
+ << "vd->state = s;"
+ << "vd->count = 0;"
+ << endl;
+
+ Choice* pc (dynamic_cast<Choice*> (&c));
+
+ if (pc)
+ {
+ os << "this->" << earm (*pc) << " (static_cast< " <<
+ earm_tag (*pc) << " > (s));";
+ }
+ else
+ {
+ Sequence& s (dynamic_cast<Sequence&> (c));
+
+ if (max != 1)
+ os << "this->" << enext (s) << " ();";
+ else if (c.min () == 0)
+ os << "this->" << epresent (s) << " ();";
+ }
+
+ os << "this->" << func << n << " (vd->state, vd->count, ns, n, " <<
+ (poly_runtime ? (poly_code ? "t, " : "0, ") : "") << "true);"
+ << "}";
+
+ // This element is not our prefix.
+ //
+
+ os << "else"
+ << "{";
+
+ if (pc && c.min () == 1 && min == 0 && max == 1)
+ {
+ // This is a required choice with effective-min == 0 (i.e.,
+ // it contains optional particle). We need to call the arm
+ // callback with that optional particle's tag.
+ //
+ SemanticGraph::Particle* p (0);
+ OptionalParticleTest test (p);
+ test.traverse (*pc);
+
+ if (p)
+ choice_arm_call (p, pc, this);
+ }
+
+ // Check if min cardinality requirements have been met. Since
+ // count is always >= 0, don't generate dead code if min == 0.
+ //
+ if (min != 0)
+ {
+ // Note that we are returning true in case of an error to
+ // indicate that no further search is needed.
+ //
+ os << "if (vd->count < " << min << "UL)"
+ << "{"
+ << "this->_schema_error (" <<
+ "::xsde::cxx::schema_error::expected_element);"
+ << "return true;"
+ << "}";
+ }
+
+ // Return false to indicate that we are not handling this element.
+ //
+ os << "return false;"
+ << "}"
+ << "}" // if (state != ~0)
+ << "else" << endl
+ << "return false;"
+ << "}"; // if (function == 0)
+ }
+
+ private:
+ SemanticGraph::Complex& type_;
+ ParticleTest particle_test_;
+ ParticleName particle_name_;
+ };
+
+
+ //
+ //
+ struct CompositorEndElement: Traversal::All,
+ Traversal::Compositor,
+ Context
+ {
+ CompositorEndElement (Context& c, SemanticGraph::Complex& type)
+ : Context (c), type_ (type)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All&)
+ {
+ os << "all_0 (vd.state, v_all_count_.top (), " <<
+ "ns, n, " << (poly_runtime ? "0, " : "") << "false);"
+ << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Compositor&) // Choice and sequence.
+ {
+ os << "assert (vd.func != 0);"
+ << "(this->*vd.func) (vd.state, vd.count, ns, n, " <<
+ (poly_runtime ? "0, " : "") << "false);"
+ << endl
+ << "if (vd.state == ~0UL)" << endl
+ << "vs.size--;" // pop
+ << endl;
+ }
+
+ private:
+ SemanticGraph::Complex& type_;
+ };
+
+
+ //
+ //
+ struct CompositorPost: Traversal::All,
+ Traversal::Compositor,
+ Context
+ {
+ CompositorPost (Context& c, SemanticGraph::Complex& type)
+ : Context (c), type_ (type), particle_name_ (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ using SemanticGraph::Element;
+
+ os << "v_state_& vs = *static_cast< v_state_* > (" <<
+ "this->v_state_stack_.top ());"
+ << "v_state_descr_& vd = vs.data[vs.size - 1];"
+ << endl;
+
+ // Flush the state machine with the empty element name. This
+ // allows us to detect missing content.
+ //
+ os << "if (vd.count != 0)"
+ << "{"
+ << string_type << " empty;"
+ << "all_0 (vd.state, v_all_count_.top (), empty, empty, " <<
+ (poly_runtime ? "0, " : "") << "true);"
+ << "}";
+
+ if (a.context ().get<UnsignedLong> ("p:effective-min") != 0)
+ {
+ os << "else" << endl
+ << "this->_schema_error (" <<
+ "::xsde::cxx::schema_error::expected_element);";
+
+ /*
+ << "this->_expected_element (" << endl;
+ particle_name_.dispatch (a);
+ os << ");";
+ */
+ }
+
+ os << endl
+ << "vs.size--;" // pop
+ << "v_all_count_.pop ();";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Compositor& c) // Choice and sequence.
+ {
+ using SemanticGraph::Choice;
+
+ UnsignedLong min (
+ c.context ().get<UnsignedLong> ("p:effective-min"));
+
+ os << "v_state_& vs = *static_cast< v_state_* > (" <<
+ "this->v_state_stack_.top ());"
+ << "v_state_descr_* vd = vs.data + (vs.size - 1);"
+ << endl;
+
+
+ // Flush unfinished state machines with the empty element name.
+ // This allows us to detect missing content. Note that I am
+ // not re-setting vd since no new compositors are pushed on
+ // flush.
+ //
+ os << string_type << " empty;"
+ << "while (vd->func != 0)"
+ << "{"
+ << "(this->*vd->func) (vd->state, vd->count, empty, empty, " <<
+ (poly_runtime ? "0, " : "") << "true);"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl
+ << "assert (vd->state == ~0UL);"
+ << "vd = vs.data + (--vs.size - 1);" // pop
+ << "}";
+
+
+ Choice* pc (dynamic_cast<Choice*> (&c));
+
+ if (pc && c.min () == 1 && min == 0 && c.max () == 1)
+ {
+ // This is a required choice with effective-min == 0 (i.e.,
+ // it contains optional particle). We need to call the arm
+ // callback with that optional particle's tag.
+ //
+ SemanticGraph::Particle* p (0);
+ OptionalParticleTest test (p);
+ test.traverse (*pc);
+
+ if (p)
+ {
+ os << "if (vd->count == 0)" << endl
+ << "{";
+ choice_arm_call (p, pc, this);
+ os << "}";
+ }
+ }
+
+ // Check if min cardinality requirements have been met. Since
+ // count is always >= 0, don't generate dead code if min == 0.
+ //
+ if (min != 0)
+ {
+ os << "if (vd->count < " << min << "UL)" << endl
+ << "this->_schema_error (" <<
+ "::xsde::cxx::schema_error::expected_element);";
+ }
+ }
+
+ private:
+ SemanticGraph::Complex& type_;
+ ParticleName particle_name_;
+ };
+
+
+ //
+ //
+ struct Complex : Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ // Nothing to generate if we don't have any elements and wildcards.
+ //
+ if (!has<Traversal::Element> (c) &&
+ !has_particle<Traversal::Any> (c))
+ return;
+
+ using SemanticGraph::Compositor;
+
+ String const& name (ename (c));
+ Compositor& comp (c.contains_compositor ().compositor ());
+
+ // Don't use restriction_p here since we don't want special
+ // treatment of anyType.
+ //
+ Boolean restriction (
+ c.inherits_p () &&
+ c.inherits ().is_a<SemanticGraph::Restricts> ());
+
+ os <<"// Element validation and dispatch functions for " <<
+ name << "." << endl
+ <<"//" << endl;
+
+ // _start_element_impl
+ //
+
+ os << "bool " << name << "::" << endl
+ << "_start_element_impl (const " << string_type << "& ns," << endl
+ << "const " << string_type << "& n";
+
+ if (poly_runtime)
+ os << "," << endl
+ << "const char*" << (poly_code ? " t" : "");
+
+ os << ")"
+ << "{";
+
+ if (poly_code)
+ os << "XSDE_UNUSED (t);"
+ << endl;
+
+ os << "::xsde::cxx::parser::context& ctx = this->_context ();"
+ << endl;
+
+
+ os << "v_state_& vs = *static_cast< v_state_* > (" <<
+ "this->v_state_stack_.top ());"
+ << "v_state_descr_* vd = vs.data + (vs.size - 1);"
+ << endl;
+
+ //@@ OPT: I don't really need to call parser_base since it always
+ // returns false.
+ //
+ // In case of an inheritance-by-extension, call our base first.
+ // We don't need to generate this code for the 'all' compositor
+ // because it can only inherit from the empty content model.
+ // Sattes of the root machine for sequence and choice:
+ //
+ // 0 - calling base
+ // 1 - base returned false
+ // ~0 - terminal state
+ //
+ if (!restriction && !comp.is_a<SemanticGraph::All> ())
+ {
+ os << "if (vd->func == 0 && vd->state == 0)"
+ << "{";
+
+ // We cannot use the fully-qualified base name directly
+ // because of some broken compilers (EVC 4.0).
+ //
+ String base (unclash (name, "base"));
+
+ os << "typedef ";
+
+ if (c.inherits_p ())
+ os << fq_name (c.inherits ().base ());
+ else
+ os << complex_base;
+
+ os << " " << base << ";"
+ << "if (" << base << "::";
+
+ if (poly_runtime)
+ os << "_start_element_impl (ns, n, " <<
+ (poly_code ? "t" : "0") << "))" << endl;
+ else
+ os << "_start_element_impl (ns, n))" << endl;
+
+ os << "return true;"
+ << "else" << endl
+ << "vd->state = 1;"
+ << "}";
+ }
+
+ {
+ CompositorStartElement t (*this, c);
+ t.dispatch (comp);
+ }
+
+ os << "return true;"
+ << "}";
+
+
+ // _end_element_impl
+ //
+
+ os << "bool " << name << "::" << endl
+ << "_end_element_impl (const " << string_type << "& ns," << endl
+ << "const " << string_type << "& n)"
+ << "{";
+
+ os << "v_state_& vs = *static_cast< v_state_* > (" <<
+ "this->v_state_stack_.top ());"
+ << "v_state_descr_& vd = vs.data[vs.size - 1];"
+ << endl;
+
+ //@@ OPT: I don't really need to call parser_base since it always
+ // returns false.
+ //
+ // In case of an inheritance-by-extension, call our base first.
+ // We don't need to generate this code for the 'all' compositor
+ // because it can only inherit from the empty content model.
+ //
+ if (!restriction && !comp.is_a<SemanticGraph::All> ())
+ {
+ os << "if (vd.func == 0 && vd.state == 0)"
+ << "{";
+
+ // We cannot use the fully-qualified base name directly
+ // because of some broken compilers (EVC 4.0).
+ //
+ String base (unclash (name, "base"));
+
+ os << "typedef ";
+
+ if (c.inherits_p ())
+ os << fq_name (c.inherits ().base ());
+ else
+ os << complex_base;
+
+ os << " " << base << ";"
+ << "if (!" << base << "::_end_element_impl (ns, n))" << endl
+ << "assert (false);" // Start and end should match.
+ << "return true;"
+ << "}";
+ }
+
+ {
+ CompositorEndElement t (*this, c);
+ t.dispatch (comp);
+ }
+
+ os << "return true;"
+ << "}";
+
+
+ // _pre_e_validate
+ //
+ os << "void " << name << "::" << endl
+ << "_pre_e_validate ()"
+ << "{";
+
+ if (exceptions)
+ os << "this->v_state_stack_.push ();";
+ else
+ os << "if (this->v_state_stack_.push ())"
+ << "{"
+ << "this->_sys_error (::xsde::cxx::sys_error::no_memory);"
+ << "return;"
+ << "}";
+
+ os << "static_cast< v_state_* > (this->v_state_stack_.top ())->" <<
+ "size = 0;"
+ << endl;
+
+ {
+ // Assuming that this code cannot trigger an error.
+ //
+ CompositorPre t (*this, c);
+ t.dispatch (comp);
+ }
+
+ // In case of an inheritance-by-extension, call our base
+ // _pre_e_validate. We don't need to generate this code for the
+ // 'all' compositor because it can only inherit from the empty
+ // content model.
+ //
+ if (!restriction && !comp.is_a<SemanticGraph::All> ())
+ {
+ // We don't need to call parser_base's implementation
+ // since it does nothing.
+ //
+ if (c.inherits_p ())
+ {
+ // We cannot use the fully-qualified base name directly
+ // because of some broken compilers (EVC 4.0).
+ //
+ String base (unclash (name, "base"));
+
+ os << "typedef " << fq_name (c.inherits ().base ()) << " " <<
+ base << ";"
+ << base << "::_pre_e_validate ();";
+ }
+ }
+
+ os << "}";
+
+
+ // _post_e_validate
+ //
+ os << "void " << name << "::" << endl
+ << "_post_e_validate ()"
+ << "{";
+
+ if (!comp.is_a<SemanticGraph::All> ())
+ os << "::xsde::cxx::parser::context& ctx = this->_context ();"
+ << endl;
+
+ // In case of an inheritance-by-extension, call our base
+ // _post_e_validate. We don't need to generate this code for
+ // the 'all' compositor because it can only inherit from
+ // the empty content model.
+ //
+ if (!restriction && !comp.is_a<SemanticGraph::All> ())
+ {
+ // We don't need to call parser_base's implementation
+ // since it does nothing.
+ //
+ if (c.inherits_p ())
+ {
+ // We cannot use the fully-qualified base name directly
+ // because of some broken compilers (EVC 4.0).
+ //
+ String base (unclash (name, "base"));
+
+ os << "typedef " << fq_name (c.inherits ().base ()) << " " <<
+ base << ";"
+ << base << "::_post_e_validate ();"
+ << endl;
+
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+ }
+
+ {
+ CompositorPost t (*this, c);
+ t.dispatch (c.contains_compositor ().compositor ());
+ }
+
+ os << endl
+ << "this->v_state_stack_.pop ();"
+ << "}";
+
+ //
+ //
+ ParticleFunction t (*this, c);
+ t.dispatch (c.contains_compositor ().compositor ());
+ }
+ };
+ }
+
+ Void
+ generate_element_validation_source (Context& ctx)
+ {
+ ctx.os << "#include <assert.h>" << endl
+ << endl;
+
+ Traversal::Schema schema;
+
+ Traversal::Sources sources;
+ Traversal::Names schema_names;
+
+ Namespace ns (ctx);
+ Traversal::Names names;
+
+ schema >> sources >> schema;
+ schema >> schema_names >> ns >> names;
+
+ Complex complex (ctx);
+
+ names >> complex;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+}
diff --git a/xsde/cxx/parser/element-validation-source.hxx b/xsde/cxx/parser/element-validation-source.hxx
new file mode 100644
index 0000000..4dbf5e3
--- /dev/null
+++ b/xsde/cxx/parser/element-validation-source.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/parser/element-validation-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_PARSER_ELEMENT_VALIDATION_SOURCE_HXX
+#define CXX_PARSER_ELEMENT_VALIDATION_SOURCE_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/parser/elements.hxx>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ Void
+ generate_element_validation_source (Context&);
+ }
+}
+
+#endif // CXX_PARSER_ELEMENT_VALIDATION_SOURCE_HXX
diff --git a/xsde/cxx/parser/elements.cxx b/xsde/cxx/parser/elements.cxx
new file mode 100644
index 0000000..e4d9cde
--- /dev/null
+++ b/xsde/cxx/parser/elements.cxx
@@ -0,0 +1,258 @@
+// file : xsde/cxx/parser/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/parser/elements.hxx>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ Context::
+ Context (std::wostream& o,
+ SemanticGraph::Schema& root,
+ CLI::Options const& ops,
+ Regex const* he,
+ Regex const* ie,
+ Regex const* hie)
+ : CXX::Context (o,
+ root,
+ "p: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),
+ xml_parser (xml_parser_),
+ simple_base (simple_base_),
+ complex_base (complex_base_),
+ list_base (list_base_),
+ parser_map (parser_map_),
+ validation (!ops.value<CLI::suppress_validation> ()),
+ exceptions (!ops.value<CLI::no_exceptions> ()),
+ poly_code (ops.value<CLI::generate_polymorphic> ()),
+ poly_runtime (poly_code || ops.value<CLI::runtime_polymorphic> ()),
+ reset (!ops.value<CLI::suppress_reset> ()),
+ mixin (ops.value<CLI::reuse_style_mixin> ()),
+ tiein (!mixin && !ops.value<CLI::reuse_style_none> ()),
+ hxx_expr (he),
+ ixx_expr (ie),
+ hxx_impl_expr (hie),
+ xml_parser_ ("expat")
+ {
+ string_type = L"::xsde::cxx::ro_string";
+
+ simple_base_ = L"::xsde::cxx::parser::";
+ simple_base_ += (validation ? L"validating" : L"non_validating");
+ simple_base_ += L"::simple_content";
+
+ complex_base_ = L"::xsde::cxx::parser::";
+ complex_base_ += (validation ? L"validating" : L"non_validating");
+ complex_base_ += L"::complex_content";
+
+ list_base_ = L"::xsde::cxx::parser::";
+ list_base_ += (validation ? L"validating" : L"non_validating");
+ list_base_ += L"::list_base";
+
+ if (poly_code)
+ parser_map_ = xs_ns_name () + L"::parser_map";
+ }
+
+ String Context::
+ real_fq_name (SemanticGraph::Nameable& n)
+ {
+ SemanticGraph::Context& c (n.context ());
+
+ if (c.count ("p:real-name"))
+ return c.get<String> ("p:real-name");
+ else
+ return fq_name (n);
+ }
+
+ Content::Value Context::
+ content (SemanticGraph::Complex& c)
+ {
+ using namespace SemanticGraph;
+
+ if (c.mixed ())
+ return Content::mixed;
+
+ if (c.inherits_p ())
+ {
+ Type& base (c.inherits ().base ());
+
+ if (Complex* cb = dynamic_cast<Complex*> (&base))
+ return content (*cb);
+
+ if (base.is_a<AnyType> ())
+ return Content::complex;
+
+ // Everyhting else (built-in type and AnySimpleType) is simple
+ // content.
+ //
+ return Content::simple;
+ }
+ else
+ return Content::complex;
+ }
+
+
+ String const& Context::
+ ret_type (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("p:ret-type");
+ }
+
+ String const& Context::
+ arg_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");
+ }
+
+ String const& Context::
+ epresent (SemanticGraph::Compositor& c)
+ {
+ return c.context ().get<String> ("p:present");
+ }
+
+ String const& Context::
+ enext (SemanticGraph::Sequence& s)
+ {
+ return s.context ().get<String> ("p:next");
+ }
+
+ String const& Context::
+ etag (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("p:tag");
+ }
+
+ String const& Context::
+ earm (SemanticGraph::Choice& c)
+ {
+ return c.context ().get<String> ("p:arm");
+ }
+
+ String const& Context::
+ earm_tag (SemanticGraph::Choice& c)
+ {
+ return c.context ().get<String> ("p:arm-tag");
+ }
+
+ String const& Context::
+ eparser (SemanticGraph::Member& m)
+ {
+ return m.context ().get<String> ("p:parser");
+ }
+
+ String const& Context::
+ emember (SemanticGraph::Member& m)
+ {
+ return m.context ().get<String> ("p:member");
+ }
+
+ String const& Context::
+ emember_cache (SemanticGraph::Member& m)
+ {
+ return m.context ().get<String> ("p:member-cache");
+ }
+
+ String const& Context::
+ emember_map (SemanticGraph::Member& m)
+ {
+ return m.context ().get<String> ("p:member-map");
+ }
+
+ String const& Context::
+ etiein (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("p:tiein");
+ }
+
+ String const& Context::
+ eimpl (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("p:impl");
+ }
+
+ // Includes
+ //
+ Void TypeForward::
+ traverse (SemanticGraph::Type& t)
+ {
+ os << "class " << t.context ().get<String> (name_key_) << ";";
+ }
+
+ Void Includes::
+ traverse_ (SemanticGraph::Uses& u)
+ {
+ // Support for weak (forward) inclusion used in the file-per-type
+ // compilation model.
+ //
+ Boolean weak (u.context ().count ("weak"));
+
+ if (weak && (type_ == header || type_ == impl_header))
+ {
+ // Generate forward declarations. We don't really need them
+ // in the impl files.
+ //
+ if (type_ == header)
+ schema_.dispatch (u.schema ());
+
+ return;
+ }
+
+ if (type_ == 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 (type_)
+ {
+ case header:
+ case source:
+ {
+ inc_path = ctx_.hxx_expr->merge (path_str);
+ break;
+ }
+ case impl_header:
+ {
+ inc_path = ctx_.hxx_impl_expr->merge (path_str);
+ break;
+ }
+ }
+
+ ctx_.os << "#include " << ctx_.process_include_path (inc_path) << endl
+ << endl;
+ }
+ }
+}
diff --git a/xsde/cxx/parser/elements.hxx b/xsde/cxx/parser/elements.hxx
new file mode 100644
index 0000000..0bb226e
--- /dev/null
+++ b/xsde/cxx/parser/elements.hxx
@@ -0,0 +1,431 @@
+// file : xsde/cxx/parser/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_PARSER_ELEMENTS_HXX
+#define CXX_PARSER_ELEMENTS_HXX
+
+#include <sstream>
+
+#include <backend-elements/regex.hxx>
+
+#include <cxx/elements.hxx>
+
+#include <cxx/parser/cli.hxx>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ struct Content
+ {
+ enum Value
+ {
+ simple,
+ complex,
+ mixed
+ };
+ };
+
+ //
+ //
+ class Context: public CXX::Context
+ {
+ public:
+ typedef BackendElements::Regex::Expression<Char> Regex;
+
+ public:
+ Context (std::wostream&,
+ SemanticGraph::Schema&,
+ CLI::Options const&,
+ Regex const* hxx_expr,
+ Regex const* ixx_expr,
+ Regex const* hxx_impl_expr);
+
+ protected:
+ Context (Context& c)
+ : CXX::Context (c),
+ options (c.options),
+ xml_parser (c.xml_parser),
+ simple_base (c.simple_base),
+ complex_base (c.complex_base),
+ list_base (c.list_base),
+ parser_map (c.parser_map),
+ validation (c.validation),
+ exceptions (c.exceptions),
+ poly_code (c.poly_code),
+ poly_runtime (c.poly_runtime),
+ reset (c.reset),
+ mixin (c.mixin),
+ tiein (c.tiein),
+ hxx_expr (c.hxx_expr),
+ ixx_expr (c.ixx_expr),
+ hxx_impl_expr (c.hxx_impl_expr)
+ {
+ }
+
+ Context (Context& c, std::wostream& o)
+ : CXX::Context (c, o),
+ options (c.options),
+ xml_parser (c.xml_parser),
+ simple_base (c.simple_base),
+ complex_base (c.complex_base),
+ list_base (c.list_base),
+ parser_map (c.parser_map),
+ validation (c.validation),
+ exceptions (c.exceptions),
+ poly_code (c.poly_code),
+ poly_runtime (c.poly_runtime),
+ reset (c.reset),
+ mixin (c.mixin),
+ tiein (c.tiein),
+ hxx_expr (c.hxx_expr),
+ ixx_expr (c.ixx_expr),
+ hxx_impl_expr (c.hxx_impl_expr)
+ {
+ }
+
+ 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;
+ }
+
+ // Real (e.g., non-typedef) fq-name.
+ //
+ String
+ real_fq_name (SemanticGraph::Nameable& n);
+
+ public:
+ static Content::Value
+ content (SemanticGraph::Complex&);
+
+ public:
+ static String const&
+ ret_type (SemanticGraph::Type&);
+
+ static String const&
+ arg_type (SemanticGraph::Type&);
+
+ static String const&
+ post_name (SemanticGraph::Type&);
+
+ public:
+ // Optional.
+ //
+ static String const&
+ epresent (SemanticGraph::Compositor&);
+
+ // Sequence.
+ //
+ static String const&
+ enext (SemanticGraph::Sequence&);
+
+ // Choice.
+ //
+ static String const&
+ etag (SemanticGraph::Particle&);
+
+ static String const&
+ earm (SemanticGraph::Choice&);
+
+ static String const&
+ earm_tag (SemanticGraph::Choice&);
+
+ public:
+ static String const&
+ eparser (SemanticGraph::Member&);
+
+ static String const&
+ emember (SemanticGraph::Member&);
+
+ static String const&
+ emember_cache (SemanticGraph::Member&);
+
+ static String const&
+ emember_map (SemanticGraph::Member&);
+
+ static String const&
+ etiein (SemanticGraph::Type&);
+
+ public:
+ static String const&
+ eimpl (SemanticGraph::Type&);
+
+ public:
+ CLI::Options const& options;
+ String& xml_parser;
+ String& simple_base;
+ String& complex_base;
+ String& list_base;
+ String& parser_map;
+
+ Boolean validation;
+ Boolean exceptions;
+ Boolean poly_code;
+ Boolean poly_runtime;
+ Boolean reset;
+ Boolean mixin;
+ Boolean tiein;
+
+ Regex const* hxx_expr;
+ Regex const* ixx_expr;
+ Regex const* hxx_impl_expr;
+
+ private:
+ String xml_parser_;
+ String simple_base_;
+ String complex_base_;
+ String list_base_;
+ String parser_map_;
+ };
+
+ //
+ //
+ struct RequiredAttributeTest: Traversal::Attribute
+ {
+ RequiredAttributeTest (Boolean& result)
+ : result_ (result)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ if (!result_ && !a.optional ())
+ result_ = true;
+ }
+
+ private:
+ Boolean& result_;
+ };
+
+
+ //
+ //
+ struct ParticleParamDecl: Traversal::Element, Context
+ {
+ ParticleParamDecl (Context& c, Boolean& first, Boolean name_arg)
+ : Context (c), first_ (first), name_arg_ (name_arg)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (!first_)
+ os << "," << endl;
+ else
+ first_ = false;
+
+ os << fq_name (e.type ()) << "&";
+
+ if (name_arg_)
+ os << " " << ename (e);
+ else
+ os << " /* " << comment (e.name ()) << " */";
+ }
+
+ private:
+ Boolean& first_;
+ Boolean name_arg_;
+ };
+
+ struct AttributeParamDecl: Traversal::Attribute, Context
+ {
+ AttributeParamDecl (Context& c, Boolean& first, Boolean name_arg)
+ : Context (c), first_ (first), name_arg_ (name_arg)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ if (!first_)
+ os << "," << endl;
+ else
+ first_ = false;
+
+ os << fq_name (a.type ()) << "&";
+
+ if (name_arg_)
+ os << " " << ename (a);
+ else
+ os << " /* " << comment (a.name ()) << " */";
+ }
+
+ private:
+ Boolean& first_;
+ Boolean name_arg_;
+ };
+
+ struct ParserParamDecl : Traversal::Complex,
+ Traversal::List,
+ Context
+ {
+ ParserParamDecl (Context& c, Boolean name_arg)
+ : Context (c),
+ particle_ (c, first_, name_arg),
+ attribute_ (c, first_, name_arg),
+ first_ (true),
+ name_arg_ (name_arg)
+ {
+ inherits_ >> *this;
+
+ contains_compositor_ >> compositor_ >> contains_particle_;
+ contains_particle_ >> particle_;
+ contains_particle_ >> compositor_;
+
+ 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 << fq_name (l.argumented ().type ()) << "&";
+
+ if (name_arg_)
+ os << " " << ename (l) << "_item";
+ else
+ os << " /* " << comment (l.name ()) << " item */";
+ }
+
+ private:
+ Traversal::Inherits inherits_;
+
+ Traversal::Compositor compositor_;
+ ParticleParamDecl particle_;
+ Traversal::ContainsCompositor contains_compositor_;
+ Traversal::ContainsParticle contains_particle_;
+
+ AttributeParamDecl attribute_;
+ Traversal::Names names_;
+
+ Boolean first_;
+ Boolean name_arg_;
+ };
+
+ //
+ //
+ struct TypeForward: Traversal::Type, Context
+ {
+ TypeForward (Context& c, Char const* name_key)
+ : Context (c), name_key_ (name_key)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& t);
+
+ private:
+ Char const* name_key_;
+ };
+
+ struct Includes : Traversal::Imports,
+ Traversal::Includes
+ {
+ enum Type
+ {
+ header,
+ source,
+ impl_header
+ };
+
+ Includes (Context& c, Type t)
+ : ctx_ (c),
+ type_ (t),
+ namespace_ (c),
+ type_forward_ (c, t == header ? "p:name" : "p:impl")
+ {
+ 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_;
+
+ Traversal::Schema schema_;
+ Traversal::Names schema_names_;
+ Namespace namespace_;
+ Traversal::Names names_;
+ TypeForward type_forward_;
+ };
+
+ // Find root element for the test driver.
+ //
+ struct RootElement: Traversal::Element
+ {
+ RootElement (CLI::Options const& options,
+ SemanticGraph::Element*& element)
+ : options_ (options), element_ (element)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (options_.value<CLI::root_element_first> ())
+ {
+ if (element_ == 0)
+ element_ = &e;
+ }
+ else if (String name = options_.value<CLI::root_element> ())
+ {
+ if (e.name () == name)
+ element_ = &e;
+ }
+ else
+ element_ = &e; // Cover root-element-last and no option.
+ }
+
+ private:
+ CLI::Options const& options_;
+ SemanticGraph::Element*& element_;
+ };
+ }
+}
+
+#endif // CXX_PARSER_ELEMENTS_HXX
diff --git a/xsde/cxx/parser/generator.cxx b/xsde/cxx/parser/generator.cxx
new file mode 100644
index 0000000..e552c92
--- /dev/null
+++ b/xsde/cxx/parser/generator.cxx
@@ -0,0 +1,1615 @@
+// file : xsde/cxx/parser/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 <type-map/lexer.hxx>
+#include <type-map/parser.hxx>
+
+#include <cxx/parser/elements.hxx>
+#include <cxx/parser/generator.hxx>
+
+#include <cxx/parser/validator.hxx>
+#include <cxx/parser/name-processor.hxx>
+#include <cxx/parser/state-processor.hxx>
+#include <cxx/parser/type-processor.hxx>
+
+#include <cxx/parser/parser-forward.hxx>
+#include <cxx/parser/parser-header.hxx>
+#include <cxx/parser/parser-inline.hxx>
+#include <cxx/parser/parser-source.hxx>
+
+#include <cxx/parser/impl-header.hxx>
+#include <cxx/parser/impl-source.hxx>
+#include <cxx/parser/driver-source.hxx>
+
+#include <cxx/parser/element-validation-source.hxx>
+#include <cxx/parser/attribute-validation-source.hxx>
+#include <cxx/parser/characters-validation-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";
+
+ Char const copyright_impl[] =
+ "// Not copyrighted - public domain.\n"
+ "//\n"
+ "// This sample parser implementation was generated by CodeSynthesis XSD/e,\n"
+ "// an XML Schema to C++ data binding compiler for embedded systems. You\n"
+ "// may use it in your programs without any restrictions.\n"
+ "//\n\n";
+ }
+
+ namespace Parser
+ {
+ namespace CLI
+ {
+ extern Key type_map = "type-map";
+ 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 reuse_style_mixin = "reuse-style-mixin";
+ extern Key reuse_style_none = "reuse-style-none";
+ extern Key generate_inline = "generate-inline";
+ extern Key suppress_validation = "suppress-validation";
+ extern Key generate_polymorphic = "generate-polymorphic";
+ extern Key runtime_polymorphic = "runtime-polymorphic";
+ extern Key suppress_reset = "suppress-reset";
+ extern Key generate_noop_impl = "generate-noop-impl";
+ extern Key generate_print_impl = "generate-print-impl";
+ extern Key generate_test_driver = "generate-test-driver";
+ extern Key force_overwrite = "force-overwrite";
+ extern Key root_element_first = "root-element-first";
+ extern Key root_element_last = "root-element-last";
+ extern Key root_element = "root-element";
+ extern Key generate_xml_schema = "generate-xml-schema";
+ extern Key extern_xml_schema = "extern-xml-schema";
+ extern Key output_dir = "output-dir";
+ extern Key skel_type_suffix = "skel-type-suffix";
+ extern Key skel_file_suffix = "skel-file-suffix";
+ extern Key impl_type_suffix = "impl-type-suffix";
+ extern Key impl_file_suffix = "impl-file-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 hxx_regex = "hxx-regex";
+ extern Key ixx_regex = "ixx-regex";
+ extern Key cxx_regex = "cxx-regex";
+ extern Key hxx_prologue = "hxx-prologue";
+ extern Key ixx_prologue = "ixx-prologue";
+ extern Key cxx_prologue = "cxx-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 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 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 epilogue_file = "epilogue-file";
+ extern Key show_anonymous = "show-anonymous";
+ extern Key show_sloc = "show-sloc";
+ extern Key proprietary_license = "proprietary-license";
+ }
+ }
+
+ Void Parser::Generator::
+ usage ()
+ {
+ std::wostream& e (wcerr);
+ ::CLI::Indent::Clip< ::CLI::OptionsUsage, WideChar> clip (e);
+
+ e << "--type-map <mapfile>" << endl
+ << " Read XML Schema to C++ type mapping information\n"
+ << " from <mapfile>. Repeat this option to specify\n"
+ << " several type maps. Type maps are considered in\n"
+ << " order of appearance and the first match is used."
+ << endl;
+
+ 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 << "--reuse-style-mixin" << endl
+ << " Generate code that supports the mixin base parser\n"
+ << " implementation reuse style."
+ << endl;
+
+ e << "--reuse-style-none" << endl
+ << " Do not generate any support for base parser\n"
+ << " implementation reuse."
+ << endl;
+
+ e << "--generate-inline" << endl
+ << " Generate certain functions inline."
+ << endl;
+
+ e << "--suppress-validation" << endl
+ << " Suppress the generation of validation code."
+ << endl;
+
+ e << "--generate-polymorphic" << endl
+ << " Generate polymorphism-aware code. Specify this\n"
+ << " option if you use substitution groups or xsi:type."
+ << endl;
+
+ e << "--runtime-polymorphic" << endl
+ << " Generate non-polymorphic code that uses the\n"
+ << " runtime library configured with polymorphism\n"
+ << " support."
+ << endl;
+
+ e << "--suppress-reset" << endl
+ << " Suppress the generation of parser reset code."
+ << endl;
+
+ e << "--generate-noop-impl" << endl
+ << " Generate a sample parser implementation that\n"
+ << " does nothing (no operation)."
+ << endl;
+
+ e << "--generate-print-impl" << endl
+ << " Generate a sample parser implementation that\n"
+ << " prints the XML data to STDOUT."
+ << endl;
+
+ e << "--generate-test-driver" << endl
+ << " Generate a test driver for the sample parser\n"
+ << " implementation."
+ << endl;
+
+ e << "--force-overwrite" << endl
+ << " Force overwriting of the existing implementation\n"
+ << " and test driver files."
+ << endl;
+
+ e << "--root-element-first" << endl
+ << " Indicate that the first global element is the\n"
+ << " document root."
+ << endl;
+
+ e << "--root-element-last" << endl
+ << " Indicate that the last global element is the\n"
+ << " document root."
+ << endl;
+
+ e << "--root-element <element>" << endl
+ << " Indicate that <element> is the document root."
+ << endl;
+
+ e << "--generate-xml-schema" << endl
+ << " Generate a C++ header file 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 << "--output-dir <dir>" << endl
+ << " Write generated files to <dir> instead of the\n"
+ << " current directory."
+ << endl;
+
+ e << "--skel-type-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '_pskel' to\n"
+ << " construct the names of generated parser skeletons."
+ << endl;
+
+ e << "--skel-file-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '-pskel' to\n"
+ << " construct the names of generated parser skeleton\n"
+ << " files."
+ << endl;
+
+ e << "--impl-type-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '_pimpl' to\n"
+ << " construct the names of parser implementations for\n"
+ << " the built-in XML Schema types and sample parser\n"
+ << " implementations."
+ << endl;
+
+ e << "--impl-file-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '-pimpl' to\n"
+ << " construct the names of generated sample parser\n"
+ << " implementation files."
+ << 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;
+
+ e << "--hxx-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '.hxx' to\n"
+ << " construct the name of the header file."
+ << endl;
+
+ e << "--ixx-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '.ixx' to\n"
+ << " construct the name of the inline file."
+ << endl;
+
+ e << "--cxx-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '.cxx' to\n"
+ << " construct the name of the source file."
+ << endl;
+
+ e << "--hxx-regex <regex>" << endl
+ << " Use <regex> to construct the name of the header\n"
+ << " file."
+ << endl;
+
+ e << "--ixx-regex <regex>" << endl
+ << " Use <regex> to construct the name of the inline\n"
+ << " file."
+ << endl;
+
+ e << "--cxx-regex <regex>" << endl
+ << " Use <regex> to construct the name of the source\n"
+ << " file."
+ << endl;
+
+
+ // Prologues.
+ //
+ e << "--hxx-prologue <text>" << endl
+ << " Insert <text> at the beginning of the header file."
+ << endl;
+
+ e << "--ixx-prologue <text>" << endl
+ << " Insert <text> at the beginning of the inline file."
+ << endl;
+
+ e << "--cxx-prologue <text>" << endl
+ << " Insert <text> at the beginning of the source 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 file."
+ << endl;
+
+ e << "--ixx-epilogue <text>" << endl
+ << " Insert <text> at the end of the inline file."
+ << endl;
+
+ e << "--cxx-epilogue <text>" << endl
+ << " Insert <text> at the end of the source 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 file."
+ << endl;
+
+ e << "--ixx-prologue-file <file>" << endl
+ << " Insert the content of the <file> at the beginning\n"
+ << " of the inline file."
+ << endl;
+
+ e << "--cxx-prologue-file <file>" << endl
+ << " Insert the content of the <file> at the beginning\n"
+ << " of the source 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 file."
+ << endl;
+
+ e << "--ixx-epilogue-file <file>" << endl
+ << " Insert the content of the <file> at the end of\n"
+ << " the inline file."
+ << endl;
+
+ e << "--cxx-epilogue-file <file>" << endl
+ << " Insert the content of the <file> at the end of\n"
+ << " the source 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;
+ }
+
+ Parser::CLI::OptionsSpec Parser::Generator::
+ options_spec ()
+ {
+ CLI::OptionsSpec spec;
+
+ spec.option<CLI::skel_file_suffix> ().default_value ("-pskel");
+ spec.option<CLI::skel_type_suffix> ().default_value ("_pskel");
+ spec.option<CLI::impl_file_suffix> ().default_value ("-pimpl");
+ spec.option<CLI::impl_type_suffix> ().default_value ("_pimpl");
+
+ spec.option<CLI::hxx_suffix> ().default_value (".hxx");
+ spec.option<CLI::ixx_suffix> ().default_value (".ixx");
+ spec.option<CLI::cxx_suffix> ().default_value (".cxx");
+
+ return spec;
+ }
+
+
+ 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 Parser::Generator::Failed ();
+ }
+ }
+ catch (InvalidPath const&)
+ {
+ wcerr << "error: '" << path.c_str () << "' is not a valid "
+ << "filesystem path" << endl;
+
+ throw Parser::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)
+ {
+ Cult::Containers::Vector<NarrowString> const& v (
+ primary.empty () ? def : primary);
+
+ for (Containers::Vector<NarrowString>::ConstIterator
+ i (v.begin ()), e (v.end ()); i != e; ++i)
+ {
+ os << i->c_str () << endl;
+ }
+ }
+ }
+
+
+ UnsignedLong Parser::Generator::
+ generate (Parser::CLI::Options const& ops,
+ Schema& schema,
+ Path const& file_path,
+ TypeMap::Namespaces& type_map,
+ Boolean gen_driver,
+ const WarningSet& disabled_warnings,
+ FileList& file_list,
+ AutoUnlinks& unlinks)
+ {
+ using std::ios_base;
+ namespace Indentation = BackendElements::Indentation;
+
+ typedef BackendElements::Regex::Expression<Char> 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;
+ }
+ }
+
+ Boolean impl (!generate_xml_schema &&
+ (ops.value<CLI::generate_noop_impl> () ||
+ ops.value<CLI::generate_print_impl> ()));
+
+ Boolean driver (gen_driver && !generate_xml_schema &&
+ ops.value<CLI::generate_test_driver> ());
+
+
+ // Evaluate the graph for possibility of generating something useful.
+ //
+ {
+ Validator validator;
+ if (!validator.validate (
+ ops, schema, file_path, driver, disabled_warnings))
+ throw Failed ();
+ }
+
+ // Process names.
+ //
+ {
+ NameProcessor proc;
+ proc.process (ops, schema, file_path);
+ }
+
+ Boolean validation (!ops.value<CLI::suppress_validation> ());
+
+ // Compute state machine info.
+ //
+ if (validation)
+ {
+ StateProcessor proc;
+ proc.process (schema, file_path);
+ }
+
+ // Read-in type maps.
+ //
+ {
+ using namespace TypeMap;
+ typedef Containers::Vector<NarrowString> Files;
+
+ Files const& files (ops.value<CLI::type_map> ());
+
+ for (Files::ConstIterator f (files.begin ()); f != files.end (); ++f )
+ {
+ NarrowInputFileStream ifs;
+ open (ifs, *f);
+
+ Lexer l (ifs, *f);
+ TypeMap::Parser p (l, *f);
+
+ if (!p.parse (type_map))
+ throw Failed ();
+ }
+
+ // Add the built-in mappings at the end.
+ //
+ String xns;
+ {
+ Context ctx (std::wcerr, schema, ops, 0, 0, 0);
+ xns = ctx.xs_ns_name ();
+ }
+
+ if (ops.value<CLI::no_stl> ())
+ {
+ TypeMap::Namespace xsd_std ("http://www\\.w3\\.org/2001/XMLSchema");
+
+ String qname (xns + L"::qname*");
+ String string_seq (xns + L"::string_sequence*");
+
+ xsd_std.types_push_back ("string", "char*", "char*");
+ xsd_std.types_push_back ("normalizedString", "char*", "char*");
+ xsd_std.types_push_back ("token", "char*", "char*");
+ xsd_std.types_push_back ("Name", "char*", "char*");
+ xsd_std.types_push_back ("NMTOKEN", "char*", "char*");
+ xsd_std.types_push_back ("NMTOKENS", string_seq, string_seq);
+ xsd_std.types_push_back ("NCName", "char*", "char*");
+
+ xsd_std.types_push_back ("ID", "char*", "char*");
+ xsd_std.types_push_back ("IDREF", "char*", "char*");
+ xsd_std.types_push_back ("IDREFS", string_seq, string_seq);
+
+ xsd_std.types_push_back ("language", "char*", "char*");
+ xsd_std.types_push_back ("anyURI", "char*", "char*");
+ xsd_std.types_push_back ("QName", qname, qname);
+
+ type_map.push_back (xsd_std);
+ }
+ else
+ {
+ TypeMap::Namespace xsd_std ("http://www\\.w3\\.org/2001/XMLSchema");
+
+ String qname (xns + L"::qname");
+ String string_seq (xns + L"::string_sequence*");
+
+ xsd_std.types_push_back ("string", "::std::string");
+ xsd_std.types_push_back ("normalizedString", "::std::string");
+ xsd_std.types_push_back ("token", "::std::string");
+ xsd_std.types_push_back ("Name", "::std::string");
+ xsd_std.types_push_back ("NMTOKEN", "::std::string");
+ xsd_std.types_push_back ("NMTOKENS", string_seq, string_seq);
+ xsd_std.types_push_back ("NCName", "::std::string");
+
+ xsd_std.types_push_back ("ID", "::std::string");
+ xsd_std.types_push_back ("IDREF", "::std::string");
+ xsd_std.types_push_back ("IDREFS", string_seq, string_seq);
+
+ xsd_std.types_push_back ("language", "::std::string");
+ xsd_std.types_push_back ("anyURI", "::std::string");
+ xsd_std.types_push_back ("QName", qname);
+
+ type_map.push_back (xsd_std);
+ }
+
+ String buffer (xns + L"::buffer*");
+
+ TypeMap::Namespace xsd ("http://www\\.w3\\.org/2001/XMLSchema");
+
+ xsd.types_push_back ("boolean", "bool", "bool");
+
+ xsd.types_push_back ("byte", "signed char", "signed char");
+ xsd.types_push_back ("unsignedByte", "unsigned char", "unsigned char");
+
+ xsd.types_push_back ("short", "short", "short");
+ xsd.types_push_back ("unsignedShort", "unsigned short", "unsigned short");
+
+ xsd.types_push_back ("int", "int", "int");
+ xsd.types_push_back ("unsignedInt", "unsigned int", "unsigned int");
+
+ if (ops.value<CLI::no_long_long> ())
+ {
+ xsd.types_push_back ("long", "long", "long");
+ xsd.types_push_back ("unsignedLong", "unsigned long", "unsigned long");
+ }
+ else
+ {
+ xsd.types_push_back ("long", "long long", "long long");
+ xsd.types_push_back ("unsignedLong", "unsigned long long", "unsigned long long");
+ }
+
+ xsd.types_push_back ("integer", "long", "long");
+
+ xsd.types_push_back ("negativeInteger", "long", "long");
+ xsd.types_push_back ("nonPositiveInteger", "long", "long");
+
+ xsd.types_push_back ("positiveInteger", "unsigned long", "unsigned long");
+ xsd.types_push_back ("nonNegativeInteger", "unsigned long", "unsigned long");
+
+ xsd.types_push_back ("float", "float", "float");
+ xsd.types_push_back ("double", "double", "double");
+ xsd.types_push_back ("decimal", "double", "double");
+
+ xsd.types_push_back ("base64Binary", buffer, buffer);
+ xsd.types_push_back ("hexBinary", buffer, buffer);
+
+ xsd.types_push_back ("gDay", xns + L"::gday");
+ xsd.types_push_back ("gMonth", xns + L"::gmonth");
+ xsd.types_push_back ("gYear", xns + L"::gyear");
+ xsd.types_push_back ("gMonthDay", xns + L"::gmonth_day");
+ xsd.types_push_back ("gYearMonth", xns + L"::gyear_month");
+ xsd.types_push_back ("date", xns + L"::date");
+ xsd.types_push_back ("time", xns + L"::time");
+ xsd.types_push_back ("dateTime", xns + L"::date_time");
+ xsd.types_push_back ("duration", xns + L"::duration");
+
+ type_map.push_back (xsd);
+
+ // Everyhting else maps to void.
+ //
+ TypeMap::Namespace rest (".*");
+ rest.types_push_back (".*", "void", "void");
+ type_map.push_back (rest);
+ }
+
+ // Process types.
+ //
+ {
+ TypeProcessor proc;
+ proc.process (ops, schema, type_map);
+ }
+
+ // Generate code.
+ //
+ Boolean inline_ (ops.value<CLI::generate_inline> () &&
+ !generate_xml_schema);
+
+ Boolean source (!generate_xml_schema);
+
+ NarrowString name (file_path.leaf ());
+ NarrowString skel_suffix (ops.value <CLI::skel_file_suffix> ());
+ NarrowString impl_suffix (ops.value <CLI::impl_file_suffix> ());
+
+ NarrowString hxx_suffix (ops.value <CLI::hxx_suffix> ());
+ NarrowString ixx_suffix (ops.value <CLI::ixx_suffix> ());
+ NarrowString cxx_suffix (ops.value <CLI::cxx_suffix> ());
+
+ Regex hxx_expr (
+ ops.value <CLI::hxx_regex> ().empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + skel_suffix + hxx_suffix + "#"
+ : ops.value <CLI::hxx_regex> ());
+
+ Regex ixx_expr (
+ ops.value <CLI::ixx_regex> ().empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + skel_suffix + ixx_suffix + "#"
+ : ops.value <CLI::ixx_regex> ());
+
+ Regex cxx_expr (
+ ops.value <CLI::cxx_regex> ().empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + skel_suffix + cxx_suffix + "#"
+ : ops.value <CLI::cxx_regex> ());
+
+ Regex hxx_impl_expr;
+ Regex cxx_impl_expr;
+ Regex cxx_driver_expr;
+
+ if (impl || driver)
+ {
+ hxx_impl_expr =
+ "#^(.+?)(\\.[^./\\\\]+)?$#$1" + impl_suffix + hxx_suffix + "#";
+
+ cxx_impl_expr =
+ "#^(.+?)(\\.[^./\\\\]+)?$#$1" + impl_suffix + cxx_suffix + "#";
+
+ cxx_driver_expr =
+ "#^(.+?)(\\.[^./\\\\]+)?$#$1-pdriver" + cxx_suffix + "#";
+ }
+
+ 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 (impl || driver)
+ {
+ if (!hxx_impl_expr.match (name))
+ {
+ wcerr << "error: implementation header expression '" <<
+ hxx_impl_expr.pattern () << "' does not match '" <<
+ name.c_str () << "'" << endl;
+ throw Failed ();
+ }
+
+ if (!cxx_impl_expr.match (name))
+ {
+ wcerr << "error: implementation source expression '" <<
+ cxx_impl_expr.pattern () << "' does not match '" <<
+ name.c_str () << "'" << endl;
+ throw Failed ();
+ }
+
+ if (!cxx_driver_expr.match (name))
+ {
+ wcerr << "error: driver source expression '" <<
+ cxx_driver_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 hxx_impl_name;
+ NarrowString cxx_impl_name;
+ NarrowString cxx_driver_name;
+
+ if (impl || driver)
+ {
+ hxx_impl_name = hxx_impl_expr.merge (name);
+ cxx_impl_name = cxx_impl_expr.merge (name);
+ cxx_driver_name = cxx_driver_expr.merge (name);
+ }
+
+ 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 hxx_impl_path;
+ Path cxx_impl_path;
+ Path cxx_driver_path;
+
+ if (impl || driver)
+ {
+ hxx_impl_path = Path (hxx_impl_name, boost::filesystem::native);
+ cxx_impl_path = Path (cxx_impl_name, boost::filesystem::native);
+ cxx_driver_path = Path (cxx_driver_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;
+
+ if (impl || driver)
+ {
+ hxx_impl_path = path / hxx_impl_path;
+ cxx_impl_path = path / cxx_impl_path;
+ cxx_driver_path = path /cxx_driver_path;
+ }
+
+ }
+ catch (InvalidPath const&)
+ {
+ wcerr << dir.c_str () << ": error: invalid path" << endl;
+ throw Failed ();
+ }
+ }
+
+ // Open the impl files first so that if open fails, the skel files
+ // are not deleted.
+ //
+ WideOutputFileStream hxx_impl;
+ WideOutputFileStream cxx_impl;
+ WideOutputFileStream cxx_driver;
+
+ if (impl)
+ {
+ if (!ops.value<CLI::force_overwrite> ())
+ {
+ WideInputFileStream tmp (hxx_impl_path, ios_base::in);
+
+ if (tmp.is_open ())
+ {
+ wcerr << hxx_impl_path << ": error: cowardly refusing to " <<
+ "overwrite an existing file" << endl;
+ throw Failed ();
+ }
+
+ tmp.close ();
+ }
+
+ hxx_impl.open (hxx_impl_path, ios_base::out);
+
+ if (!hxx_impl.is_open ())
+ {
+ wcerr << hxx_impl_path << ": error: unable to open in write mode"
+ << endl;
+ throw Failed ();
+ }
+
+ unlinks.add (hxx_impl_path);
+ file_list.push_back (hxx_impl_path.native_file_string ());
+
+ if (!ops.value<CLI::force_overwrite> ())
+ {
+ WideInputFileStream tmp (cxx_impl_path, ios_base::in);
+
+ if (tmp.is_open ())
+ {
+ wcerr << cxx_impl_path << ": error: cowardly refusing to " <<
+ "overwrite an existing file" << endl;
+ throw Failed ();
+ }
+
+ tmp.close ();
+ }
+
+ cxx_impl.open (cxx_impl_path, ios_base::out);
+
+ if (!cxx_impl.is_open ())
+ {
+ wcerr << cxx_impl_path << ": error: unable to open in write mode"
+ << endl;
+ throw Failed ();
+ }
+
+ unlinks.add (cxx_impl_path);
+ file_list.push_back (cxx_impl_path.native_file_string ());
+ }
+
+ if (driver)
+ {
+ if (!ops.value<CLI::force_overwrite> ())
+ {
+ WideInputFileStream tmp (cxx_driver_path, ios_base::in);
+
+ if (tmp.is_open ())
+ {
+ wcerr << cxx_driver_path << ": error: cowardly refusing to " <<
+ "overwrite an existing file" << endl;
+ throw Failed ();
+ }
+
+ tmp.close ();
+ }
+
+ cxx_driver.open (cxx_driver_path, ios_base::out);
+
+ if (!cxx_driver.is_open ())
+ {
+ wcerr << cxx_driver_path << ": error: unable to open in write " <<
+ "mode" << endl;
+ throw Failed ();
+ }
+
+ unlinks.add (cxx_driver_path);
+ file_list.push_back (cxx_driver_path.native_file_string ());
+ }
+
+ // Open the skel files.
+ //
+ WideOutputFileStream hxx (hxx_path, ios_base::out);
+ WideOutputFileStream ixx;
+ WideOutputFileStream cxx;
+
+ 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);
+
+ hxx << copyright;
+
+ if (inline_)
+ ixx << copyright;
+
+ if (source)
+ cxx << copyright;
+
+ if (impl)
+ {
+ hxx_impl << copyright_impl;
+ cxx_impl << copyright_impl;
+ }
+
+ if (driver)
+ cxx_driver << copyright_impl;
+
+ // Prologue.
+ //
+ WideInputFileStream prologue;
+ {
+ NarrowString name (ops.value<CLI::prologue_file> ());
+
+ if (name)
+ open (prologue, name);
+ }
+
+ // Epilogue.
+ //
+ WideInputFileStream epilogue;
+ {
+ NarrowString name (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 += '_';
+
+
+ // HXX
+ //
+ {
+ Context ctx (hxx, schema, ops, &hxx_expr, &ixx_expr, &hxx_impl_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, 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_iostream> ())
+ {
+ hxx << "#ifdef XSDE_IOSTREAM" << endl
+ << "#error the XSD/e runtime uses iostream while the " <<
+ "generated code does not (reconfigure the runtime or " <<
+ "remove --no-iostream)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+ else
+ {
+ hxx << "#ifndef XSDE_IOSTREAM" << endl
+ << "#error the generated code uses iostream while the " <<
+ "XSD/e runtime does not (reconfigure the runtime or " <<
+ "add --no-iostream)" << 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;
+ }
+
+ if (ops.value<CLI::suppress_validation> ())
+ {
+ hxx << "#ifdef XSDE_PARSER_VALIDATION" << endl
+ << "#error the XSD/e runtime uses validation while the " <<
+ "generated code does not (reconfigure the runtime or " <<
+ "remove --suppress-validation)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+ else
+ {
+ hxx << "#ifndef XSDE_PARSER_VALIDATION" << endl
+ << "#error the generated code uses validation while the " <<
+ "XSD/e runtime does not (reconfigure the runtime or " <<
+ "add --suppress-validation)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+
+ if (ops.value<CLI::generate_polymorphic> () ||
+ ops.value<CLI::runtime_polymorphic> ())
+ {
+ hxx << "#ifndef XSDE_POLYMORPHIC" << endl
+ << "#error the generated code expects XSD/e runtime with " <<
+ "polymorphism support (reconfigure the runtime or remove " <<
+ "--generate-polymorphic/--runtime-polymorphic)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+ else
+ {
+ hxx << "#ifdef XSDE_POLYMORPHIC" << endl
+ << "#error the generated code expects XSD/e runtime " <<
+ "without polymorphism support (reconfigure the runtime or " <<
+ "add --generate-polymorphic/--runtime-polymorphic)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+
+ if (ops.value<CLI::reuse_style_mixin> ())
+ {
+ hxx << "#ifndef XSDE_REUSE_STYLE_MIXIN" << endl
+ << "#error the generated code uses the mixin reuse style " <<
+ "while the XSD/e runtime does not (reconfigure the runtime " <<
+ "or remove --reuse-style-mixin)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+ else if (ops.value<CLI::reuse_style_none> ())
+ {
+ hxx << "#ifndef XSDE_REUSE_STYLE_NONE" << endl
+ << "#error the generated code does not provide support " <<
+ "for parser reuse while the XSD/e runtime does (reconfigure " <<
+ "the runtime or remove --reuse-style-none)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+ else
+ {
+ hxx << "#ifndef XSDE_REUSE_STYLE_TIEIN" << endl
+ << "#error the generated code uses the tiein reuse style " <<
+ "while the XSD/e runtime does not (reconfigure the runtime " <<
+ "or add --reuse-style-mixin or --reuse-style-none)" << 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)
+ generate_parser_forward (ctx);
+
+ generate_parser_header (ctx, generate_xml_schema);
+
+ if (inline_)
+ hxx << "#include " << ctx.process_include_path (ixx_name) << endl
+ << endl;
+
+ hxx << "#include <xsde/cxx/post.hxx>" << endl
+ << endl;
+ }
+
+ // Copy epilogue.
+ //
+ hxx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (hxx, 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, &hxx_expr, &ixx_expr, &hxx_impl_expr);
+
+ Indentation::Clip<Indentation::SLOC, WideChar> ixx_sloc (ixx);
+
+
+ // Copy prologue.
+ //
+ ixx << "// Begin prologue." << endl
+ << "//" << endl;
+
+ append (
+ ixx, ops.value<CLI::ixx_prologue> (), ops.value<CLI::prologue> ());
+ append (ixx, 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_parser_inline (ctx);
+ }
+
+ // Copy epilogue.
+ //
+ ixx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (ixx, ops.value<CLI::ixx_epilogue_file> (), epilogue);
+ append (
+ ixx, ops.value<CLI::ixx_epilogue> (), ops.value<CLI::epilogue> ());
+
+ ixx << "//" << endl
+ << "// End epilogue." << endl
+ << 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, &hxx_expr, &ixx_expr, &hxx_impl_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, ops.value<CLI::cxx_prologue_file> (), 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;
+
+ if (!inline_)
+ generate_parser_inline (ctx);
+
+ generate_parser_source (ctx);
+
+ if (validation)
+ {
+ generate_element_validation_source (ctx);
+ generate_attribute_validation_source (ctx);
+ generate_characters_validation_source (ctx);
+ }
+ }
+
+ // Copy epilogue.
+ //
+ cxx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (cxx, 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 ();
+ }
+ }
+
+ // HXX impl
+ //
+ if (impl)
+ {
+ Context ctx (hxx_impl, schema, ops,
+ &hxx_expr, &ixx_expr, &hxx_impl_expr);
+
+ String guard (guard_expr.merge (guard_prefix + hxx_impl_name));
+ guard = ctx.escape (guard); // Make it a C++ id.
+ std::transform (guard.begin (), guard.end(), guard.begin (), upcase);
+
+ hxx_impl << "#ifndef " << guard << endl
+ << "#define " << guard << endl
+ << endl;
+
+ {
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> clip (hxx_impl);
+
+ hxx_impl << "#include " << ctx.process_include_path (hxx_name)
+ << endl << endl;
+
+ generate_impl_header (ctx);
+ }
+
+ hxx_impl << "#endif // " << guard << endl;
+ }
+
+ // CXX impl
+ //
+ if (impl)
+ {
+ Context ctx (cxx_impl, schema, ops,
+ &hxx_expr, &ixx_expr, &hxx_impl_expr);
+
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> clip (cxx_impl);
+
+ cxx_impl << "#include " << ctx.process_include_path (hxx_impl_name)
+ << endl << endl;
+
+ generate_impl_source (ctx);
+ }
+
+ // CXX driver
+ //
+ if (driver)
+ {
+ Context ctx (cxx_driver, schema, ops,
+ &hxx_expr, &ixx_expr, &hxx_impl_expr);
+
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> clip (cxx_driver);
+
+ cxx_driver << "#include " << ctx.process_include_path (hxx_impl_name)
+ << endl << endl;
+
+ generate_driver_source (ctx);
+ }
+
+ 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/parser/generator.hxx b/xsde/cxx/parser/generator.hxx
new file mode 100644
index 0000000..a261eca
--- /dev/null
+++ b/xsde/cxx/parser/generator.hxx
@@ -0,0 +1,56 @@
+// file : xsde/cxx/parser/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_PARSER_GENERATOR_HXX
+#define CXX_PARSER_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/parser/cli.hxx>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ using namespace Cult::Types;
+
+ class Generator
+ {
+ public:
+ static Void
+ usage ();
+
+ static CLI::OptionsSpec
+ options_spec ();
+
+ struct Failed {};
+
+ static UnsignedLong
+ generate (CLI::Options const& options,
+ XSDFrontend::SemanticGraph::Schema&,
+ XSDFrontend::SemanticGraph::Path const& file,
+ TypeMap::Namespaces& type_map,
+ Boolean gen_driver,
+ const WarningSet& disabled_warnings,
+ FileList& file_list,
+ AutoUnlinks& unlinks);
+
+ private:
+ Generator ();
+ };
+ }
+}
+
+#endif // CXX_PARSER_GENERATOR_HXX
diff --git a/xsde/cxx/parser/impl-header.cxx b/xsde/cxx/parser/impl-header.cxx
new file mode 100644
index 0000000..5d15ed2
--- /dev/null
+++ b/xsde/cxx/parser/impl-header.cxx
@@ -0,0 +1,309 @@
+// file : xsde/cxx/parser/impl-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/parser/impl-header.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ namespace
+ {
+ struct Enumeration: Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ String const& name (eimpl (e));
+ String const& ret (ret_type (e));
+ SemanticGraph::Type& base (e.inherits ().base ());
+
+ os << "class " << name << ": " << "public " <<
+ (mixin ? "virtual " : "") << ename (e);
+
+ if (mixin)
+ os << "," << endl
+ << " public " << fq_name (base, "p:impl");
+
+ os << "{"
+ << "public:" << endl;
+
+ if (tiein)
+ os << name << " ();"
+ << endl;
+
+ os << "virtual void" << endl
+ << "pre ();"
+ << endl
+ << "virtual " << ret << endl
+ << post_name (e) << " ();";
+
+ if (tiein)
+ os << endl
+ << "private:" << endl
+ << fq_name (base, "p:impl") << " base_impl_;";
+
+ os << "};";
+ }
+ };
+
+ //
+ //
+ struct List: Traversal::List, Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String const& name (eimpl (l));
+ SemanticGraph::Type& t (l.argumented ().type ());
+
+ String item (unclash (ename (l), "item"));
+
+ os << "class " << name << ": public " <<
+ (mixin ? "virtual " : "") << ename (l)
+ << "{"
+ << "public:" << endl
+ << "virtual void" << endl
+ << "pre ();"
+ << endl;
+
+ // item
+ //
+ String const& arg (arg_type (t));
+
+ os << "virtual void" << endl
+ << item;
+
+ if (arg == L"void")
+ os << " ();";
+ else
+ os << " (" << arg << ");";
+
+ os << endl;
+
+ // post
+ //
+ String const& ret (ret_type (l));
+
+ os << "virtual " << ret << endl
+ << post_name (l) << " ();"
+ << "};";
+ }
+ };
+
+ struct Union: Traversal::Union, Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ String const& name (eimpl (u));
+ String const& ret (ret_type (u));
+
+ os << "class " << name << ": public " <<
+ (mixin ? "virtual " : "") << ename (u)
+ << "{"
+ << "public:" << endl
+ << "virtual void" << endl
+ << "pre ();"
+ << endl
+ << "virtual void" << endl
+ << "_characters (const " << string_type << "&);"
+ << endl
+ << "virtual " << ret << endl
+ << post_name (u) << " ();"
+ << "};";
+ }
+ };
+
+
+ //
+ //
+ struct ParticleCallback: Traversal::Element, Context
+ {
+ ParticleCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ String const& arg (arg_type (e.type ()));
+
+ os << "virtual void" << endl
+ << ename (e);
+
+ if (arg == L"void")
+ os << " ();";
+ else
+ os << " (" << arg << ");";
+
+ os << endl;
+ }
+ };
+
+ struct AttributeCallback: Traversal::Attribute, Context
+ {
+ AttributeCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ String const& arg (arg_type (a.type ()));
+
+ os << "virtual void" << endl
+ << ename (a);
+
+ if (arg == L"void")
+ os << " ();";
+ else
+ os << " (" << arg << ");";
+
+ os << endl;
+ }
+ };
+
+
+ //
+ //
+ struct Complex : Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (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)
+ {
+ Boolean hb (c.inherits_p ());
+ Boolean he (has<Traversal::Element> (c));
+ Boolean ha (has<Traversal::Attribute> (c));
+
+ String const& name (eimpl (c));
+ String const& ret (ret_type (c));
+
+ os << "class " << name << ": public " <<
+ (mixin ? "virtual " : "") << ename (c);
+
+ if (mixin && hb)
+ os << "," << endl
+ << " public " << fq_name (c.inherits ().base (), "p:impl");
+
+ os << "{"
+ << "public:" << endl;
+
+ if (tiein && hb)
+ os << name << " ();"
+ << endl;
+
+ 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_p (c))
+ {
+ if (ha)
+ {
+ os << "// Attributes." << endl
+ << "//" << endl;
+
+ names (c, names_attribute_callback_);
+ }
+
+ if (he)
+ {
+ os << "// Elements." << endl
+ << "//" << endl;
+
+ contains_compositor (c, contains_compositor_callback_);
+ }
+ }
+
+ os << "virtual " << ret << endl
+ << post_name (c) << " ();";
+
+ if (tiein && hb)
+ os << endl
+ << "private:" << endl
+ << fq_name (c.inherits ().base (), "p:impl") << " base_impl_;";
+
+ os << "};";
+ }
+
+ private:
+ Traversal::Compositor 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_impl_header (Context& ctx)
+ {
+ Traversal::Schema schema;
+
+ Traversal::Sources sources;
+ Includes includes (ctx, Includes::impl_header);
+ Traversal::Names schema_names;
+
+ Namespace ns (ctx);
+ Traversal::Names names;
+
+ schema >> includes;
+ schema >> sources >> schema;
+ schema >> schema_names >> ns >> names;
+
+ List list (ctx);
+ Union union_ (ctx);
+ Complex complex (ctx);
+ Enumeration enumeration (ctx);
+
+ names >> list;
+ names >> union_;
+ names >> complex;
+ names >> enumeration;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+}
diff --git a/xsde/cxx/parser/impl-header.hxx b/xsde/cxx/parser/impl-header.hxx
new file mode 100644
index 0000000..43a7584
--- /dev/null
+++ b/xsde/cxx/parser/impl-header.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/parser/impl-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_PARSER_IMPL_HEADER_HXX
+#define CXX_PARSER_IMPL_HEADER_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/parser/elements.hxx>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ Void
+ generate_impl_header (Context&);
+ }
+}
+
+#endif // CXX_PARSER_IMPL_HEADER_HXX
diff --git a/xsde/cxx/parser/impl-source.cxx b/xsde/cxx/parser/impl-source.cxx
new file mode 100644
index 0000000..6b02425
--- /dev/null
+++ b/xsde/cxx/parser/impl-source.cxx
@@ -0,0 +1,543 @@
+// file : xsde/cxx/parser/impl-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/parser/impl-source.hxx>
+#include <cxx/parser/print-impl-common.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ namespace
+ {
+ struct Enumeration: Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ String const& name (eimpl (e));
+ String const& ret (ret_type (e));
+ SemanticGraph::Type& base (e.inherits ().base ());
+ String const& base_ret (ret_type (base));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ // c-tor
+ //
+ if (tiein)
+ os << name << "::" << endl
+ << name << " ()" << endl
+ << ": " << ename (e) << " (&base_impl_)"
+ << "{"
+ << "}";
+
+ // pre
+ //
+ os << "void " << name << "::" << endl
+ << "pre ()"
+ << "{"
+ << "}";
+
+ // post
+ //
+ os << ret << " " << name << "::" << endl
+ << post_name (e) << " ()"
+ << "{";
+
+ if (ret == base_ret)
+ {
+ os << (ret != L"void" ? "return " : "") <<
+ post_name (base) << " ();";
+ }
+ else if (ret == L"void")
+ {
+ os << arg_type (base) << " v = " << post_name (base) << " ();"
+ << endl;
+
+ if (options.value<CLI::no_exceptions> ())
+ os << "if (!_error ())"
+ << "{";
+
+ if (options.value<CLI::generate_print_impl> ())
+ {
+ PrintCall t (*this, e.name (), "v");
+ t.dispatch (base);
+ }
+ else
+ os << "// TODO" << endl
+ << "//" << endl;
+
+ {
+ DeleteCall t (*this, "v");
+ t.dispatch (base);
+ }
+
+ if (options.value<CLI::no_exceptions> ())
+ os << "}";
+ }
+ else
+ {
+ if (base_ret == L"void")
+ os << post_name (base) << " ();";
+ else
+ {
+ os << arg_type (base) << " v = " << post_name (base) << " ();"
+ << endl;
+
+ if (options.value<CLI::no_exceptions> ())
+ os << "if (!_error ())"
+ << "{";
+
+ os << "// TODO" << endl
+ << "//" << endl
+ << "// return ... ;" << endl;
+
+ {
+ DeleteCall t (*this, "v");
+ t.dispatch (base);
+ }
+
+ if (options.value<CLI::no_exceptions> ())
+ os << "}";
+ }
+ }
+
+ os << "}";
+ }
+ };
+
+ //
+ //
+ struct List: Traversal::List, Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String const& name (eimpl (l));
+ SemanticGraph::Type& type (l.argumented ().type ());
+
+ String item (unclash (ename (l), "item"));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ // pre
+ //
+ os << "void " << name << "::" << endl
+ << "pre ()"
+ << "{"
+ << "}";
+
+ // item
+ //
+ String const& arg (arg_type (type));
+
+ os << "void " << name << "::" << endl
+ << item;
+
+ if (arg == L"void")
+ os << " ()";
+ else
+ os << " (" << arg << " " << item << ")";
+
+ os << "{";
+
+ if (arg != L"void")
+ {
+ if (options.value<CLI::generate_print_impl> ())
+ {
+ PrintCall t (*this, type.name (), item);
+ t.dispatch (type);
+ }
+ else
+ os << "// TODO" << endl
+ << "//" << endl;
+
+ {
+ DeleteCall t (*this, item);
+ t.dispatch (type);
+ }
+ }
+
+ os << "}";
+
+ // post
+ //
+ String const& ret (ret_type (l));
+
+ os << ret << " " << name << "::" << endl
+ << post_name (l) << " ()"
+ << "{";
+
+ if (ret != L"void")
+ os << "// TODO" << endl
+ << "//" << endl
+ << "// return ... ;" << endl;
+
+ os << "}";
+ }
+ };
+
+ //
+ //
+ struct Union: Traversal::Union, Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ String const& name (eimpl (u));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ // pre
+ //
+ os << "void " << name << "::" << endl
+ << "pre ()"
+ << "{"
+ << "}";
+
+ // _characters
+ //
+ os << "void " << name << "::" << endl
+ << "_characters (const " << string_type << "& s)"
+ << "{";
+
+ if (options.value<CLI::generate_print_impl> ())
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "if (s.size () != 0)"
+ << "{"
+ << "printf (" << strlit (u.name () + L": ") << ");"
+ << "fwrite (s.data (), s.size (), 1, stdout);"
+ << "printf (\"\\n\");"
+ << "}";
+ else
+ os << "std::cout << " << strlit (u.name () + L": ") <<
+ " << s << std::endl;";
+ }
+ else
+ os << "// TODO" << endl
+ << "//" << endl;
+
+ os << "}";
+
+ // post
+ //
+ String const& ret (ret_type (u));
+
+ os << ret << " " << name << "::" << endl
+ << post_name (u) << " ()"
+ << "{";
+
+ if (ret != L"void")
+ os << "// TODO" << endl
+ << "//" << endl
+ << "// return ... ;" << endl;
+
+ os << "}";
+ }
+ };
+
+ //
+ //
+ struct ParticleCallback: Traversal::Element, Context
+ {
+ ParticleCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ using SemanticGraph::Complex;
+
+ String const& name (ename (e));
+ String const& arg (arg_type (e.type ()));
+ Complex& c (dynamic_cast<Complex&> (e.scope ()));
+
+ os << "void " << eimpl (c) << "::" << endl
+ << name;
+
+ if (arg == L"void")
+ os << " ()";
+ else
+ os << " (" << arg << " " << name << ")";
+
+ os << "{";
+
+ if (arg != L"void")
+ {
+ if (options.value<CLI::generate_print_impl> ())
+ {
+ PrintCall t (*this, e.name (), name);
+ t.dispatch (e.type ());
+ }
+ else
+ os << "// TODO" << endl
+ << "//" << endl;
+
+ {
+ DeleteCall t (*this, name);
+ t.dispatch (e.type ());
+ }
+ }
+
+ os << "}";
+ }
+ };
+
+ struct AttributeCallback: Traversal::Attribute, Context
+ {
+ AttributeCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ using SemanticGraph::Complex;
+
+ String const& name (ename (a));
+ String const& arg (arg_type (a.type ()));
+ Complex& c (dynamic_cast<Complex&> (a.scope ()));
+
+ os << "void " << eimpl (c) << "::" << endl
+ << name;
+
+ if (arg == L"void")
+ os << " ()";
+ else
+ os << " (" << arg << " " << name << ")";
+
+ os << "{";
+
+ if (arg != L"void")
+ {
+ if (options.value<CLI::generate_print_impl> ())
+ {
+ PrintCall t (*this, a.name (), name);
+ t.dispatch (a.type ());
+ }
+ else
+ os << "// TODO" << endl
+ << "//" << endl;
+
+ {
+ DeleteCall t (*this, name);
+ t.dispatch (a.type ());
+ }
+ }
+
+ os << "}";
+ }
+ };
+
+ //
+ //
+ struct Complex : Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (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)
+ {
+ Boolean hb (c.inherits_p ());
+
+ String const& name (eimpl (c));
+ String const& ret (ret_type (c));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ // c-tor
+ //
+ if (tiein && hb)
+ os << name << "::" << endl
+ << name << " ()" << endl
+ << ": " << ename (c) << " (&base_impl_)"
+ << "{"
+ << "}";
+
+ // pre
+ //
+ os << "void " << name << "::" << endl
+ << "pre ()"
+ << "{"
+ << "}";
+
+ // Parser callbacks.
+ //
+ if (!restriction_p (c))
+ {
+ names (c, names_attribute_callback_);
+ contains_compositor (c, contains_compositor_callback_);
+ }
+
+ // post
+ //
+ os << ret << " " << name << "::" << endl
+ << post_name (c) << " ()"
+ << "{";
+
+ if (hb)
+ {
+ SemanticGraph::Type& base (c.inherits ().base ());
+ String const& base_ret (ret_type (base));
+
+ if (ret == base_ret)
+ {
+ os << (ret != L"void" ? "return " : "") <<
+ post_name (base) << " ();";
+ }
+ else if (ret == L"void")
+ {
+ os << arg_type (base) << " v = " << post_name (base) << " ();"
+ << endl;
+
+ if (options.value<CLI::no_exceptions> ())
+ os << "if (!_error ())"
+ << "{";
+
+ if (options.value<CLI::generate_print_impl> ())
+ {
+ PrintCall t (*this, c.name (), "v");
+ t.dispatch (base);
+ }
+ else
+ os << "// TODO" << endl
+ << "//" << endl;
+
+ {
+ DeleteCall t (*this, "v");
+ t.dispatch (base);
+ }
+
+ if (options.value<CLI::no_exceptions> ())
+ os << "}";
+ }
+ else
+ {
+ if (base_ret == L"void")
+ os << post_name (base) << " ();";
+ else
+ {
+ os << arg_type (base) << " v = " << post_name (base) << " ();"
+ << endl;
+
+ if (options.value<CLI::no_exceptions> ())
+ os << "if (!_error ())"
+ << "{";
+
+ os << "// TODO" << endl
+ << "//" << endl
+ << "// return ... ;" << endl;
+
+ {
+ DeleteCall t (*this, "v");
+ t.dispatch (base);
+ }
+
+ if (options.value<CLI::no_exceptions> ())
+ os << "}";
+ }
+ }
+ }
+ else
+ {
+ if (ret != L"void")
+ os << "// TODO" << endl
+ << "//" << endl
+ << "// return ... ;" << endl;
+ }
+
+ os << "}";
+ }
+
+ private:
+ Traversal::Compositor 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_impl_source (Context& ctx)
+ {
+ if (ctx.options.value<CLI::generate_print_impl> ())
+ {
+ if (ctx.options.value<CLI::no_iostream> ())
+ ctx.os << "#include <stdio.h>" << endl
+ << endl;
+ else
+ ctx.os << "#include <iostream>" << endl
+ << endl;
+ }
+
+ 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);
+ Enumeration enumeration (ctx);
+
+ names >> list;
+ names >> union_;
+ names >> complex;
+ names >> enumeration;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+}
diff --git a/xsde/cxx/parser/impl-source.hxx b/xsde/cxx/parser/impl-source.hxx
new file mode 100644
index 0000000..98c7961
--- /dev/null
+++ b/xsde/cxx/parser/impl-source.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/parser/impl-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_PARSER_IMPL_SOURCE_HXX
+#define CXX_PARSER_IMPL_SOURCE_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/parser/elements.hxx>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ Void
+ generate_impl_source (Context&);
+ }
+}
+
+#endif // CXX_PARSER_IMPL_SOURCE_HXX
diff --git a/xsde/cxx/parser/name-processor.cxx b/xsde/cxx/parser/name-processor.cxx
new file mode 100644
index 0000000..bc0e7a5
--- /dev/null
+++ b/xsde/cxx/parser/name-processor.cxx
@@ -0,0 +1,1326 @@
+// file : xsde/cxx/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/parser/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 Parser
+ {
+ 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,
+ "p: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),
+ skel_suffix_ (ops.value<CLI::skel_type_suffix> ()),
+ impl_suffix_ (ops.value<CLI::impl_type_suffix> ()),
+ schema (root),
+ schema_path (schema_path_),
+ impl (ops.value<CLI::generate_noop_impl> () ||
+ ops.value<CLI::generate_print_impl> () ||
+ ops.value<CLI::generate_test_driver> ()),
+ tiein (!ops.value<CLI::reuse_style_mixin> () &&
+ !ops.value<CLI::reuse_style_none> ()),
+ skel_suffix (skel_suffix_),
+ impl_suffix (impl_suffix_),
+ global_type_names (global_type_names_),
+ validation (!ops.value<CLI::suppress_validation> ()),
+ polymorphic (ops.value<CLI::generate_polymorphic> ())
+ {
+ }
+
+ protected:
+ Context (Context& c)
+ : CXX::Context (c),
+ schema (c.schema),
+ schema_path (c.schema_path),
+ impl (c.impl),
+ tiein (c.tiein),
+ skel_suffix (c.skel_suffix),
+ impl_suffix (c.impl_suffix),
+ global_type_names (c.global_type_names),
+ validation (c.validation),
+ polymorphic (c.polymorphic)
+ {
+ }
+
+ 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);
+ }
+
+ private:
+ SemanticGraph::Path const schema_path_;
+ String const skel_suffix_;
+ String const impl_suffix_;
+
+ Cult::Containers::Map<String, NameSet*> global_type_names_;
+
+ public:
+ SemanticGraph::Schema& schema;
+ SemanticGraph::Path const& schema_path;
+ Boolean const impl;
+ Boolean const tiein;
+ String const& skel_suffix;
+ String const& impl_suffix;
+
+ Cult::Containers::Map<String, NameSet*>& global_type_names;
+
+ Boolean validation;
+ Boolean polymorphic;
+ };
+
+ // Primary names.
+ //
+ struct PrimaryParticle: Traversal::Element, Context
+ {
+ PrimaryParticle (Context& c, NameSet& set, Boolean restriction)
+ : Context (c), set_ (set), restriction_ (restriction)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ using SemanticGraph::Element;
+
+ SemanticGraph::Context& ec (e.context ());
+
+ if (!restriction_)
+ {
+ ec.set ("p:name", find_name (e.name (), set_));
+ }
+ else
+ {
+ Element* prot (
+ ec.get<Element*> ("xsd-frontend-restriction-correspondence"));
+
+ ec.set ("p:name", prot->context ().get<String> ("p:name"));
+ }
+ }
+
+ private:
+ NameSet& set_;
+ Boolean restriction_;
+ };
+
+ struct PrimaryAttribute: Traversal::Attribute, Context
+ {
+ PrimaryAttribute (Context& c, NameSet& set, Boolean restriction)
+ : Context (c), set_ (set), restriction_ (restriction)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ using SemanticGraph::Attribute;
+
+ SemanticGraph::Context& ac (a.context ());
+
+ if (!restriction_)
+ {
+ ac.set ("p:name", find_name (a.name (), set_));
+ }
+ else
+ {
+ Attribute* prot (
+ ac.get<Attribute*> ("xsd-frontend-restriction-correspondence"));
+
+ ac.set ("p:name", prot->context ().get<String> ("p:name"));
+ }
+ }
+
+ private:
+ NameSet& set_;
+ Boolean restriction_;
+ };
+
+
+ //
+ // Secondary names.
+ //
+
+ struct ParticleTag: Traversal::Element,
+ Traversal::Any,
+ Traversal::Choice,
+ Traversal::Sequence,
+ Context
+ {
+ ParticleTag (Context& c, NameSet& set, Boolean restriction)
+ : Context (c), set_ (set), restriction_ (restriction)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ using SemanticGraph::Element;
+
+ SemanticGraph::Context& ec (e.context ());
+
+ if (!restriction_)
+ {
+ String const base (ec.get<String> ("p:name"));
+ ec.set ("p:tag", find_name (base, L"_tag", set_));
+ }
+ else
+ {
+ Element* prot = ec.get<Element*> (
+ "xsd-frontend-restriction-correspondence");
+
+ ec.set ("p:tag", prot->context ().get<String> ("p:tag"));
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ using SemanticGraph::Any;
+
+ SemanticGraph::Context& ac (a.context ());
+
+ if (!restriction_)
+ ac.set ("p:tag", find_name (L"any", L"_tag", set_));
+ else
+ {
+ Any* prot = ac.get<Any*> (
+ "xsd-frontend-restriction-correspondence");
+
+ ac.set ("p:tag", prot->context ().get<String> ("p:tag"));
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ using SemanticGraph::Compositor;
+
+ SemanticGraph::Context& cc (c.context ());
+
+ if (!restriction_)
+ {
+ cc.set ("p:tag", find_name (L"choice", L"_tag", set_));
+ }
+ else
+ {
+ Compositor* prot = cc.get<Compositor*> (
+ "xsd-frontend-restriction-correspondence");
+
+ cc.set ("p:tag", prot->context ().get<String> ("p:tag"));
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ using SemanticGraph::Compositor;
+
+ SemanticGraph::Context& sc (s.context ());
+
+ if (!restriction_)
+ {
+ sc.set ("p:tag", find_name (L"sequence", L"_tag", set_));
+ }
+ else
+ {
+ Compositor* prot = sc.get<Compositor*> (
+ "xsd-frontend-restriction-correspondence");
+
+ sc.set ("p:tag", prot->context ().get<String> ("p:tag"));
+ }
+ }
+
+ private:
+ NameSet& set_;
+ Boolean restriction_;
+ };
+
+ struct SecondaryCompositor: Traversal::All,
+ Traversal::Choice,
+ Traversal::Sequence,
+ Context
+ {
+ SecondaryCompositor (Context& c, NameSet& set, Boolean restriction)
+ : Context (c),
+ set_ (set),
+ restriction_ (restriction),
+ particle_tag_ (c, set, restriction)
+ {
+ contain_particle_tag_ >> particle_tag_;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ // For the all compositor, maxOccurs=1 and minOccurs={0,1}
+ // and it cannot be used in restriction.
+ //
+ if (a.min () == 0)
+ {
+ a.context ().set (
+ "p:present", find_name (L"all", L"_present", set_));
+ }
+
+ Traversal::All::traverse (a);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ if (c.contains_begin () == c.contains_end ())
+ return;
+
+ SemanticGraph::Context& cc (c.context ());
+
+ if (!restriction_)
+ {
+ cc.set ("p:arm-tag", find_name (L"choice", L"_arm_tag", set_));
+ Traversal::Choice::contains (c, contain_particle_tag_);
+ cc.set ("p:arm", find_name (L"choice", L"_arm", set_));
+ }
+ else
+ {
+ SemanticGraph::Compositor& b (
+ *cc.get<SemanticGraph::Compositor*> (
+ "xsd-frontend-restriction-correspondence"));
+
+ SemanticGraph::Context& bc (b.context ());
+
+ cc.set ("p:arm-tag", bc.get<String> ("p:arm-tag"));
+ Traversal::Choice::contains (c, contain_particle_tag_);
+ cc.set ("p:arm", bc.get<String> ("p:arm"));
+ }
+
+ Traversal::Choice::traverse (c);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ SemanticGraph::Context& sc (s.context ());
+
+ if (!restriction_)
+ {
+ if (s.max () != 1)
+ sc.set ("p:next", find_name (L"sequence", L"_next", set_));
+ else if (s.min () == 0)
+ sc.set ("p:present", find_name (L"sequence", L"_present", set_));
+ }
+ else
+ {
+ // Root compositor that models inheritance by extension
+ // may not have an association.
+ //
+ if (sc.count ("xsd-frontend-restriction-correspondence"))
+ {
+ SemanticGraph::Compositor& b (
+ *sc.get<SemanticGraph::Compositor*> (
+ "xsd-frontend-restriction-correspondence"));
+
+ SemanticGraph::Context& bc (b.context ());
+
+ if (b.max () != 1)
+ {
+ sc.set ("p:next", bc.get<String> ("p:next"));
+
+ // Add the *_present callback if this is a restriction
+ // of sequence to optional.
+ //
+ if (s.min () == 0)
+ sc.set ("p:present",
+ find_name (L"sequence", L"_present", set_));
+ }
+ else if (b.min () == 0)
+ sc.set ("p:present", bc.get<String> ("p:present"));
+ }
+ }
+
+ Traversal::Sequence::traverse (s);
+ }
+
+ private:
+ NameSet& set_;
+ Boolean restriction_;
+
+ ParticleTag particle_tag_;
+ Traversal::ContainsParticle contain_particle_tag_;
+ };
+
+ struct SecondaryParticle: Traversal::Element, Context
+ {
+ SecondaryParticle (Context& c, NameSet& set, Boolean restriction)
+ : Context (c), set_ (set), restriction_ (restriction)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ Boolean poly (
+ polymorphic && !e.type ().context ().count ("anonymous"));
+
+ SemanticGraph::Context& ec (e.context ());
+
+ if (!restriction_)
+ {
+ String const& base (ec.get<String> ("p:name"));
+
+ ec.set ("p:parser", find_name (base + L"_parser", set_));
+ ec.set ("p:member", find_name (base + L"_parser_", set_));
+
+ if (poly)
+ {
+ ec.set (
+ "p:member-cache", find_name (base + L"_parser_cache_", set_));
+
+ ec.set (
+ "p:member-map", find_name (base + L"_parser_map_", set_));
+ }
+ }
+ else
+ {
+ SemanticGraph::Context& bc (
+ ec.get<SemanticGraph::Element*> (
+ "xsd-frontend-restriction-correspondence")->context ());
+
+ ec.set ("p:parser", bc.get<String> ("p:parser"));
+ ec.set ("p:member", bc.get<String> ("p:member"));
+
+ if (poly)
+ {
+ ec.set ("p:member-cache", bc.get<String> ("p:member-cache"));
+ ec.set ("p:member-map", bc.get<String> ("p:member-map"));
+ }
+ }
+ }
+
+ private:
+ NameSet& set_;
+ Boolean restriction_;
+ };
+
+ struct SecondaryAttribute: Traversal::Attribute, Context
+ {
+ SecondaryAttribute (Context& c, NameSet& set, Boolean restriction)
+ : Context (c), set_ (set), restriction_ (restriction)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ using SemanticGraph::Attribute;
+
+ SemanticGraph::Context& ac (a.context ());
+
+ if (!restriction_)
+ {
+ String const& base (ac.get<String> ("p:name"));
+
+ a.context ().set (
+ "p:parser", find_name (base + L"_parser", set_));
+
+ a.context ().set (
+ "p:member", find_name (base + L"_parser_", set_));
+ }
+ else
+ {
+ SemanticGraph::Context& bc (
+ ac.get<SemanticGraph::Attribute*> (
+ "xsd-frontend-restriction-correspondence")->context ());
+
+ ac.set ("p:parser", bc.get<String> ("p:parser"));
+ ac.set ("p:member", bc.get<String> ("p:member"));
+ }
+ }
+
+ private:
+ NameSet& set_;
+ Boolean restriction_;
+ };
+
+
+ //
+ //
+ struct Complex: Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ SemanticGraph::Context& cc (c.context ());
+
+ // Use processed name.
+ //
+ String const& name (cc.get<String> ("p:name"));
+
+ // We leave this set around to allow other mappings to use
+ // this information.
+ //
+ cc.set ("cxx-parser-name-processor-member-set", NameSet ());
+ NameSet& member_set (
+ cc.get<NameSet> ("cxx-parser-name-processor-member-set"));
+
+ member_set.insert (name);
+
+ // Add our base's members to the initial list unless we are
+ // inheriting by restriction in which case we need to have
+ // the same names as our base.
+ //
+ Boolean restriction (false);
+
+ if (c.inherits_p ())
+ {
+ // @@ What if this types name is the same as one of base's
+ // members?
+ //
+ SemanticGraph::Type& base (c.inherits ().base ());
+
+ if (base.is_a<SemanticGraph::Complex> ())
+ {
+ if (!base.context ().count (
+ "cxx-parser-name-processor-member-set"))
+ {
+ dispatch (base);
+ }
+
+ NameSet const& base_set (
+ base.context ().get<NameSet> (
+ "cxx-parser-name-processor-member-set"));
+
+ member_set.insert (base_set.begin (), base_set.end ());
+
+ // Inheritance by restriction from anyType is a special case.
+ //
+ restriction = c.inherits ().is_a<SemanticGraph::Restricts> () &&
+ !c.inherits ().base ().is_a<SemanticGraph::AnyType> ();
+ }
+ }
+
+ // First assign the "primary" names.
+ //
+ {
+ if (c.contains_compositor_p ())
+ {
+ PrimaryParticle particle (*this, member_set, restriction);
+ Traversal::Compositor compositor;
+ 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);
+ }
+
+ //
+ //
+ PrimaryAttribute attribute (*this, member_set, restriction);
+ Traversal::Names names (attribute);
+
+ Complex::names (c, names);
+ }
+
+ // Assign "secondary" names.
+ //
+ {
+ if (c.contains_compositor_p ())
+ {
+ // In case of validation we generate some extra callbacks
+ // for compositors.
+ //
+ if (validation)
+ {
+ SecondaryParticle particle (*this, member_set, restriction);
+ SecondaryCompositor compositor (*this, member_set, restriction);
+ 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);
+ }
+ else
+ {
+ SecondaryParticle particle (*this, member_set, restriction);
+ Traversal::Compositor compositor;
+ 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);
+ }
+ }
+
+ //
+ //
+ SecondaryAttribute attribute (*this, member_set, restriction);
+ Traversal::Names names (attribute);
+
+ Complex::names (c, names);
+ }
+ }
+ };
+
+
+ //
+ //
+ struct GlobalType: Traversal::Type, Context
+ {
+ GlobalType (Context& c, NameSet& set)
+ : Context (c), set_ (set)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& t)
+ {
+ SemanticGraph::Context& c (t.context ());
+ String const& n (t.name ());
+
+ String name (find_name (n + skel_suffix, set_));
+ c.set ("p:name", name);
+
+ // Assign the post_* name.
+ //
+ c.set ("p:post", find_post_name (t));
+
+ if (tiein)
+ c.set ("p:tiein", escape (n + L"_impl_"));
+
+ // Note that we do not add this name to the set so that it
+ // does not influence other names.
+ //
+ if (impl)
+ c.set ("p:impl", escape (n + impl_suffix));
+ }
+
+ private:
+ String
+ find_post_name (SemanticGraph::Type& t)
+ {
+ String const& n (t.name ());
+
+ // It is possible that our base has the same type name (just
+ // in a different namespaces). Avoid name clash in this case.
+ //
+ using SemanticGraph::Complex;
+
+ Complex* c = dynamic_cast<Complex*> (&t);
+
+ if (c == 0 || !c->inherits_p ())
+ {
+ return escape (L"post_" + n);
+ }
+ else
+ {
+ NameSet set;
+
+ // Collect all base's post_*. In some mutual inclusion cases it
+ // is possible that our base won't have the post name assigned
+ // yet. In this situation will will have to figure it out
+ // ourselves (we can do it since we use the "raw" type name).
+ //
+ SemanticGraph::Type* b (&c->inherits ().base ());
+
+ while (true)
+ {
+ if (b->context ().count ("p:post"))
+ set.insert (b->context ().get<String> ("p:post"));
+ else
+ set.insert (find_post_name (*b));
+
+ Complex* cb (dynamic_cast<Complex*> (b));
+
+ if (cb != 0 && cb->inherits_p ())
+ {
+ b = &cb->inherits ().base ();
+ continue;
+ }
+
+ break;
+ }
+
+ String base_name (escape (L"post_" + n));
+ String post (base_name);
+
+ for (UnsignedLong i (1); set.find (post) != set.end (); ++i)
+ {
+ std::wostringstream os;
+ os << i;
+ post = base_name + os.str ();
+ }
+
+ return post;
+ }
+ }
+
+ 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_names (t, "any_type");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnySimpleType& t)
+ {
+ set_names (t, "any_simple_type");
+ }
+
+ // Boolean.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Boolean& t)
+ {
+ set_names (t, "boolean");
+ }
+
+ // Integral types.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Byte& t)
+ {
+ set_names (t, "byte");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedByte& t)
+ {
+ set_names (t, "unsigned_byte");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Short& t)
+ {
+ set_names (t, "short");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedShort& t)
+ {
+ set_names (t, "unsigned_short");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Int& t)
+ {
+ set_names (t, "int");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedInt& t)
+ {
+ set_names (t, "unsigned_int");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Long& t)
+ {
+ set_names (t, "long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedLong& t)
+ {
+ set_names (t, "unsigned_long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Integer& t)
+ {
+ set_names (t, "integer");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonPositiveInteger& t)
+ {
+ set_names (t, "non_positive_integer");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonNegativeInteger& t)
+ {
+ set_names (t, "non_negative_integer");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::PositiveInteger& t)
+ {
+ set_names (t, "positive_integer");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NegativeInteger& t)
+ {
+ set_names (t, "negative_integer");
+ }
+
+ // Floats.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Float& t)
+ {
+ set_names (t, "float");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Double& t)
+ {
+ set_names (t, "double");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Decimal& t)
+ {
+ set_names (t, "decimal");
+ }
+
+ // Strings.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::String& t)
+ {
+ set_names (t, "string");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NormalizedString& t)
+ {
+ set_names (t, "normalized_string");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Token& t)
+ {
+ set_names (t, "token");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameToken& t)
+ {
+ set_names (t, "nmtoken");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameTokens& t)
+ {
+ set_names (t, "nmtokens");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Name& t)
+ {
+ set_names (t, "name");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NCName& t)
+ {
+ set_names (t, "ncname");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Language& t)
+ {
+ set_names (t, "language");
+ }
+
+
+ // Qualified name.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::QName& t)
+ {
+ set_names (t, "qname");
+ }
+
+
+ // ID/IDREF.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Id& t)
+ {
+ set_names (t, "id");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRef& t)
+ {
+ set_names (t, "idref");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRefs& t)
+ {
+ set_names (t, "idrefs");
+ }
+
+ // URI.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::AnyURI& t)
+ {
+ set_names (t, "uri");
+ }
+
+ // Binary.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Base64Binary& t)
+ {
+ set_names (t, "base64_binary");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::HexBinary& t)
+ {
+ set_names (t, "hex_binary");
+ }
+
+
+ // Date/time.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Date& t)
+ {
+ set_names (t, "date");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::DateTime& t)
+ {
+ set_names (t, "date_time");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Duration& t)
+ {
+ set_names (t, "duration");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Day& t)
+ {
+ set_names (t, "gday");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Month& t)
+ {
+ set_names (t, "gmonth");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::MonthDay& t)
+ {
+ set_names (t, "gmonth_day");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Year& t)
+ {
+ set_names (t, "gyear");;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::YearMonth& t)
+ {
+ set_names (t, "gyear_month");
+
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Time& t)
+ {
+ set_names (t, "time");
+ }
+
+ // Entity.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entity& t)
+ {
+ set_names (t, "entity");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entities& t)
+ {
+ set_names (t, "entities");
+ }
+
+ private:
+ String
+ make_skel_name (String const& base)
+ {
+ return escape (base + skel_suffix);
+ }
+
+ String
+ make_impl_name (String const& base)
+ {
+ return escape (base + impl_suffix);
+ }
+
+ Void
+ set_names (SemanticGraph::Type& t, String const& name)
+ {
+ SemanticGraph::Context& c (t.context ());
+
+ WideChar const* ns = validation
+ ? L"::xsde::cxx::parser::validating::"
+ : L"::xsde::cxx::parser::non_validating::";
+
+ String skel (make_skel_name (name));
+ c.set ("p:name", skel);
+ c.set ("p:real-name", ns + skel);
+
+ String impl (make_impl_name (name));
+ c.set ("p:impl", impl);
+ c.set ("p:real-impl", ns + impl);
+
+ c.set ("p:post", L"post_" + name);
+
+ if (tiein)
+ c.set ("p:tiein", name + L"_impl_");
+ }
+ };
+
+ // 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-parser-name-processor-seen"))
+ {
+ s.context ().set ("cxx-parser-name-processor-seen", true);
+ Traversal::Sources::traverse (sr);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Includes& i)
+ {
+ SemanticGraph::Schema& s (i.schema ());
+
+ if (!s.context ().count ("cxx-parser-name-processor-seen"))
+ {
+ s.context ().set ("cxx-parser-name-processor-seen", true);
+ Traversal::Includes::traverse (i);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Imports& i)
+ {
+ SemanticGraph::Schema& s (i.schema ());
+
+ if (!s.context ().count ("cxx-parser-name-processor-seen"))
+ {
+ s.context ().set ("cxx-parser-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-parser-name-processor-seen"))
+ {
+ s.context ().set ("cxx-parser-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-parser-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-parser-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;
+
+ Complex complex (ctx);
+
+ ns_names >> complex;
+
+ schema.dispatch (tu);
+ }
+ }
+ }
+ }
+
+ Void NameProcessor::
+ process (CLI::Options const& ops,
+ SemanticGraph::Schema& tu,
+ SemanticGraph::Path const& file)
+ {
+ process_impl (ops, tu, file);
+ }
+ }
+}
diff --git a/xsde/cxx/parser/name-processor.hxx b/xsde/cxx/parser/name-processor.hxx
new file mode 100644
index 0000000..8d55f30
--- /dev/null
+++ b/xsde/cxx/parser/name-processor.hxx
@@ -0,0 +1,32 @@
+// file : xsde/cxx/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_PARSER_NAME_PROCESSOR_HXX
+#define CXX_PARSER_NAME_PROCESSOR_HXX
+
+#include <cult/types.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+
+#include <cxx/parser/cli.hxx>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ using namespace Cult::Types;
+
+ class NameProcessor
+ {
+ public:
+ Void
+ process (CLI::Options const& options,
+ XSDFrontend::SemanticGraph::Schema&,
+ XSDFrontend::SemanticGraph::Path const& file);
+ };
+ }
+}
+
+#endif // CXX_PARSER_NAME_PROCESSOR_HXX
diff --git a/xsde/cxx/parser/parser-forward.cxx b/xsde/cxx/parser/parser-forward.cxx
new file mode 100644
index 0000000..3ce73de
--- /dev/null
+++ b/xsde/cxx/parser/parser-forward.cxx
@@ -0,0 +1,112 @@
+// file : xsde/cxx/parser/parser-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/parser/parser-forward.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ namespace
+ {
+ struct Enumeration: Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ os << "class " << ename (e) << ";";
+ }
+ };
+
+ //
+ //
+ 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) << ";";
+ }
+ };
+ }
+
+ Void
+ generate_parser_forward (Context& ctx)
+ {
+ ctx.os << "// Forward declarations" << endl
+ << "//" << endl;
+
+ 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);
+ Enumeration enumeration (ctx);
+
+ names >> list;
+ names >> union_;
+ names >> complex;
+ names >> enumeration;
+
+ schema.dispatch (ctx.schema_root);
+
+ ctx.os << endl;
+ }
+ }
+}
diff --git a/xsde/cxx/parser/parser-forward.hxx b/xsde/cxx/parser/parser-forward.hxx
new file mode 100644
index 0000000..1ddeb39
--- /dev/null
+++ b/xsde/cxx/parser/parser-forward.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/parser/parser-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_PARSER_PARSER_FORWARD_HXX
+#define CXX_PARSER_PARSER_FORWARD_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/parser/elements.hxx>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ Void
+ generate_parser_forward (Context&);
+ }
+}
+
+#endif // CXX_PARSER_PARSER_FORWARD_HXX
diff --git a/xsde/cxx/parser/parser-header.cxx b/xsde/cxx/parser/parser-header.cxx
new file mode 100644
index 0000000..95642ab
--- /dev/null
+++ b/xsde/cxx/parser/parser-header.cxx
@@ -0,0 +1,1818 @@
+// file : xsde/cxx/parser/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/parser/parser-header.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ namespace
+ {
+ struct Enumeration: Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ String const& name (ename (e));
+ SemanticGraph::Type& base (e.inherits ().base ());
+ String fq_base (fq_name (base));
+
+ os << "class " << name << ": public " <<
+ (mixin ? "virtual " : "") << fq_base
+ << "{"
+ << "public:" << endl
+ << "// Parser callbacks. Override them in your " <<
+ "implementation." << endl
+ << "//" << endl;
+
+ os << "// virtual void" << endl
+ << "// pre ();" << endl
+ << endl;
+
+ String const& ret (ret_type (e));
+ String const& base_ret (ret_type (base));
+
+ Boolean same (ret == base_ret);
+
+ os << "virtual " << ret << endl
+ << post_name (e) << " ()" <<
+ (same || ret == L"void" ? ";" : " = 0;");
+
+ if (poly_code)
+ {
+ os << endl
+ << "public:" << endl
+ << "static const char*" << endl
+ << "_static_type ();"
+ << endl
+ << "virtual const char*" << endl
+ << "_dynamic_type () const;";
+ }
+
+ if (tiein)
+ {
+ os << endl
+ << "// Constructor." << endl
+ << "//" << endl
+ << name << " (" << fq_base << "* tiein);"
+ << endl;
+
+ os << "// Implementation details." << endl
+ << "//" << endl;
+
+ // If our base has pure virtual post, override it here.
+ //
+ Boolean base_same (
+ base.inherits_p () &&
+ base_ret == ret_type (base.inherits ().base ()));
+
+ if (!(base_same || base_ret == L"void"))
+ os << "virtual " << base_ret << endl
+ << post_name (base) << " ();"
+ << endl;
+
+ os << "protected:" << endl
+ << name << "* " << etiein (e) << ";"
+ << name << " (" << name << "*, void*);";
+ }
+
+ os << "};";
+ }
+ };
+
+
+ //
+ //
+ struct List: Traversal::List, Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String const& name (ename (l));
+ SemanticGraph::Type& t (l.argumented ().type ());
+ String item_type (fq_name (t));
+
+ String item (unclash (name, "item"));
+
+ os << "class " << name << ": public " << list_base
+ << "{"
+ << "public:" << endl
+ << "// Parser callbacks. Override them in your " <<
+ "implementation." << endl
+ << "//" << endl;
+
+ // pre
+ //
+ os << "// virtual void" << endl
+ << "// pre ();" << endl
+ << endl;
+
+ // item
+ //
+ String const& arg (arg_type (t));
+
+ os << "virtual void" << endl
+ << item;
+
+ if (arg == L"void")
+ os << " ();";
+ else
+ os << " (" << arg << ");";
+
+ os << endl;
+
+ // post
+ //
+ String const& ret (ret_type (l));
+
+ os << "virtual " << ret << endl
+ << post_name (l) << " ()" << (ret == L"void" ? ";" : " = 0;")
+ << endl;
+
+
+ //
+ //
+ os << "// Parser construction API." << endl
+ << "//" << endl;
+
+ // item_parser
+ //
+ os << "void" << endl
+ << unclash (name, "item_parser") << " (" << item_type << "&);"
+ << endl;
+
+ // parsers
+ //
+ os << "void" << endl
+ << "parsers (" << item_type << "& /* item */);"
+ << endl;
+
+ if (reset)
+ os << "virtual void" << endl
+ << "_reset ();"
+ << endl;
+
+ // c-tor
+ //
+ os << "// Constructor." << endl
+ << "//" << endl
+ << name << " ();"
+ << endl;
+
+ if (poly_code)
+ {
+ os << "public:" << endl
+ << "static const char*" << endl
+ << "_static_type ();"
+ << endl
+ << "virtual const char*" << endl
+ << "_dynamic_type () const;"
+ << endl;
+ }
+
+ //
+ //
+ os << "// Implementation details." << endl
+ << "//" << endl
+ << "protected:" << endl;
+
+ if (tiein)
+ {
+ os << name << "* " << etiein (l) << ";"
+ << name << " (" << name << "*, void*);"
+ << endl;
+ }
+
+ os << "virtual void" << endl
+ << "_xsde_parse_item (const " << string_type << "&);"
+ << endl;
+
+ os << "protected:" << endl
+ << item_type << "* _xsde_" << item << "_;"
+ << "};";
+ }
+ };
+
+
+ struct Union: Traversal::Union, Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ String const& name (ename (u));
+
+ os << "class " << name << ": public " << simple_base
+ << "{"
+ << "public:" << endl
+ << "// Parser callbacks. Override them in your " <<
+ "implementation." << endl
+ << "//" << endl;
+
+ os << "// virtual void" << endl
+ << "// pre ();" << endl
+ << "//" << endl
+ << "// virtual void" << endl
+ << "// _characters (const " << string_type << "&);" << endl
+ << endl;
+
+ String const& ret (ret_type (u));
+
+ os << "virtual " << ret << endl
+ << post_name (u) << " ()" << (ret == L"void" ? ";" : " = 0;");
+
+ if (poly_code)
+ {
+ os << endl
+ << "public:" << endl
+ << "static const char*" << endl
+ << "_static_type ();"
+ << endl
+ << "virtual const char*" << endl
+ << "_dynamic_type () const;";
+ }
+
+ if (tiein)
+ {
+ // c-tor
+ //
+ os << endl
+ << "// Constructor." << endl
+ << "//" << endl
+ << name << " ();"
+ << endl;
+
+ //
+ //
+ os << "// Implementation details." << endl
+ << "//" << endl
+ << "protected:" << endl
+ << name << "* " << etiein (u) << ";"
+ << name << " (" << name << "*, void*);";
+ }
+
+ os << "};";
+ }
+ };
+
+ //
+ // Callbacks.
+ //
+
+ struct ParticleTag: Traversal::Particle, Context
+ {
+ ParticleTag (Context& c)
+ : Context (c), first_ (true)
+ {
+ }
+
+ virtual Void
+ traverse (Type& p)
+ {
+ if (first_)
+ first_ = false;
+ else
+ os << "," << endl;
+
+ os << etag (p);
+ }
+
+ private:
+ Boolean first_;
+ };
+
+ struct CompositorCallback: Traversal::All,
+ Traversal::Choice,
+ Traversal::Sequence,
+ Context
+ {
+ CompositorCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ if (correspondent (a) == 0)
+ {
+ // For the all compositor, maxOccurs=1 and minOccurs={0,1}.
+ //
+ if (a.min () == 0)
+ {
+ os << "virtual void" << endl
+ << epresent (a) << " ();"
+ << endl;
+ }
+ }
+
+ Traversal::All::traverse (a);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ if (c.contains_begin () == c.contains_end ())
+ return;
+
+ if (correspondent (c) == 0)
+ {
+ os << "enum " << earm_tag (c)
+ << "{";
+
+ {
+ ParticleTag particle (*this);
+ Traversal::ContainsParticle contain_particle (particle);
+ Traversal::Choice::contains (c, contain_particle);
+ }
+
+ os << "};";
+
+ os << "virtual void" << endl
+ << earm (c) << " (" << earm_tag (c) << ");"
+ << endl;
+ }
+
+ Traversal::Choice::traverse (c);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ // Root compositor that models inheritance by extension
+ // may not have an association so we may fall through
+ // in to the 'if' case even though this is a restriction.
+ // This is ok since such a compositor always has max ==
+ // min == 1 and so nothing is generated.
+ //
+ if (SemanticGraph::Compositor* b = correspondent (s))
+ {
+ // Add the *_present callback if this is a restriction
+ // of sequence to optional.
+ //
+ if (b->max () != 1 && s.min () == 0)
+ {
+ os << "virtual void" << endl
+ << epresent (s) << " ();"
+ << endl;
+ }
+ }
+ else
+ {
+ if (s.max () != 1)
+ {
+ os << "virtual void" << endl
+ << enext (s) << " ();"
+ << endl;
+ }
+ else if (s.min () == 0)
+ {
+ os << "virtual void" << endl
+ << epresent (s) << " ();"
+ << endl;
+ }
+ }
+
+ Traversal::Sequence::traverse (s);
+ }
+ };
+
+ struct ParticleCallback: Traversal::Element, Context
+ {
+ ParticleCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (correspondent (e) == 0)
+ {
+ String const& arg (arg_type (e.type ()));
+
+ os << "virtual void" << endl
+ << ename (e);
+
+ if (arg == L"void")
+ os << " ();";
+ else
+ os << " (" << arg << ");";
+
+ os << endl;
+ }
+ }
+ };
+
+ struct AttributeCallback: Traversal::Attribute, Context
+ {
+ AttributeCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ String const& arg (arg_type (a.type ()));
+
+ os << "virtual void" << endl
+ << ename (a);
+
+ if (arg == L"void")
+ os << " ();";
+ else
+ os << " (" << arg << ");";
+
+ os << endl;
+ }
+ };
+
+
+ //
+ //
+ struct ParticleAccessor: Traversal::Element, Context
+ {
+ ParticleAccessor (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ String const& parser (eparser (e));
+
+ os << "void" << endl
+ << parser << " (" << fq_name (e.type ()) << "&);"
+ << endl;
+
+ if (poly_code && !anonymous (e.type ()))
+ {
+ os << "void" << endl
+ << parser << " (" << parser_map << "&);"
+ << endl;
+ }
+ }
+ };
+
+ struct AttributeAccessor: Traversal::Attribute, Context
+ {
+ AttributeAccessor (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ os << "void" << endl
+ << eparser (a) << " (" << fq_name (a.type ()) << "&);"
+ << endl;
+ }
+ };
+
+
+ //
+ //
+ struct ParticleMember: Traversal::Element, Context
+ {
+ ParticleMember (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ String type (fq_name (e.type ()));
+
+ os << type << "* " << emember (e) << ";";
+
+ if (poly_code && !anonymous (e.type ()))
+ {
+ os << type << "* " << emember_cache (e) << ";"
+ << parser_map << "* " << emember_map (e) << ";"
+ << endl;
+ }
+ }
+ };
+
+ struct AttributeMember: Traversal::Attribute, Context
+ {
+ AttributeMember (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ os << fq_name (a.type ()) << "* " << emember (a) << ";";
+ }
+ };
+
+ //
+ //
+ struct Particle: Traversal::All,
+ Traversal::Choice,
+ Traversal::Sequence,
+ Context
+ {
+ Particle (Context& c)
+ : Context (c)
+ {
+ *this >> contains_particle_ >> *this;
+ }
+
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ if (!a.context().count ("p:comp-number"))
+ return;
+
+ UnsignedLong state_count (
+ a.context().get<UnsignedLong> ("p:state-count"));
+
+ os << "void" << endl
+ << "all_0 (unsigned long&," << endl
+ << "unsigned char*," << endl
+ << "const " << string_type << "&," << endl
+ << "const " << string_type << "&," << endl;
+
+ if (poly_runtime)
+ os << "const char*," << endl;
+
+ os << "bool);"
+ << endl
+ << "unsigned char v_all_first_[" << state_count << "UL];"
+ << "::xsde::cxx::parser::validating::all_stack v_all_count_;"
+ << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ if (!c.context().count ("p:comp-number"))
+ return;
+
+ UnsignedLong n (c.context ().get<UnsignedLong> ("p:comp-number"));
+
+ os << "void" << endl
+ << "choice_" << n << " (unsigned long&," << endl
+ << "unsigned long&," << endl
+ << "const " << string_type << "&," << endl
+ << "const " << string_type << "&," << endl;
+
+ if (poly_runtime)
+ os << "const char*," << endl;
+
+ os << "bool);"
+ << endl;
+
+ Traversal::Choice::traverse (c);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ if (!s.context().count ("p:comp-number"))
+ return;
+
+ UnsignedLong n (s.context ().get<UnsignedLong> ("p:comp-number"));
+
+ os << "void" << endl
+ << "sequence_" << n << " (unsigned long&," << endl
+ << "unsigned long&," << endl
+ << "const " << string_type << "&," << endl
+ << "const " << string_type << "&," << endl;
+
+ if (poly_runtime)
+ os << "const char*," << endl;
+
+ os << "bool);"
+ << endl;
+
+ Traversal::Sequence::traverse (s);
+ }
+
+ private:
+ Traversal::ContainsParticle contains_particle_;
+ };
+
+
+ //
+ //
+ struct AttributeValidationState: Traversal::Attribute, Context
+ {
+ AttributeValidationState (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ if (!a.optional ())
+ {
+ os << "bool " << ename (a) << ";";
+ }
+ }
+ };
+
+ //
+ //
+ struct Complex : Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c),
+ compositor_callback_val_ (c),
+ particle_callback_ (c),
+ attribute_callback_ (c),
+ particle_accessor_ (c),
+ attribute_accessor_ (c),
+ particle_member_ (c),
+ attribute_member_ (c),
+ attribute_validation_state_ (c)
+ {
+ // Callback.
+ //
+ if (validation)
+ {
+ contains_compositor_callback_ >> compositor_callback_val_;
+ compositor_callback_val_ >> contains_particle_callback_;
+ contains_particle_callback_ >> compositor_callback_val_;
+ }
+ else
+ {
+ contains_compositor_callback_ >> compositor_callback_non_val_;
+ compositor_callback_non_val_ >> contains_particle_callback_;
+ contains_particle_callback_ >> compositor_callback_non_val_;
+ }
+
+ contains_particle_callback_ >> particle_callback_;
+
+ names_attribute_callback_ >> attribute_callback_;
+
+ // Accessor.
+ //
+ contains_compositor_accessor_ >> compositor_accessor_;
+ compositor_accessor_ >> contains_particle_accessor_;
+ contains_particle_accessor_ >> compositor_accessor_;
+ contains_particle_accessor_ >> particle_accessor_;
+
+ names_attribute_accessor_ >> attribute_accessor_;
+
+ // Member.
+ //
+ contains_compositor_member_ >> compositor_member_;
+ compositor_member_ >> contains_particle_member_;
+ contains_particle_member_ >> compositor_member_;
+ contains_particle_member_ >> particle_member_;
+
+ names_attribute_member_ >> attribute_member_;
+
+ //
+ //
+ names_attribute_validation_state_ >> attribute_validation_state_;
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ String const& name (ename (c));
+
+ // 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. We only need the parsing/validation code.
+ //
+ Boolean hb (c.inherits_p ());
+ Boolean restriction (restriction_p (c));
+
+ 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));
+
+ Boolean hra (false); // Has required attribute.
+ if (ha)
+ {
+ RequiredAttributeTest test (hra);
+ Traversal::Names names_test (test);
+ names (c, names_test);
+ }
+
+ //
+ //
+ os << "class " << name << ": public ";
+
+ if (hb)
+ os << (mixin ? "virtual " : "") << fq_name (c.inherits ().base ());
+ else
+ os << complex_base;
+
+ os << "{"
+ << "public:" << endl
+ << "// Parser callbacks. Override them in your " <<
+ "implementation." << endl
+ << "//" << endl;
+
+ // pre
+ //
+ os << "// virtual void" << endl
+ << "// pre ();" << endl
+ << endl;
+
+ // Member callbacks.
+ //
+ if (!restriction)
+ {
+ if (ha)
+ {
+ os << "// Attributes." << endl
+ << "//" << endl;
+
+ names (c, names_attribute_callback_);
+ }
+ }
+
+ if (!restriction || validation)
+ {
+ if (he || hae)
+ {
+ if (!restriction)
+ os << "// Elements." << endl
+ << "//" << endl;
+
+ contains_compositor (c, contains_compositor_callback_);
+ }
+ }
+
+ // post
+ //
+ String const& ret (ret_type (c));
+ Boolean same (hb && ret == ret_type (c.inherits ().base ()));
+
+ os << "virtual " << ret << endl
+ << post_name (c) << " ()" <<
+ (same || ret == L"void" ? ";" : " = 0;")
+ << endl;
+
+ //
+ //
+ if (!restriction && (he || ha))
+ {
+ os << "// Parser construction API." << endl
+ << "//" << endl;
+
+ os << "void" << endl
+ << "parsers (";
+
+ {
+ ParserParamDecl decl (*this, false);
+ decl.traverse (c);
+ }
+
+ os << ");"
+ << endl;
+
+ if (ha)
+ {
+ os << "// Individual attribute parsers." << endl
+ << "//" << endl;
+
+ names (c, names_attribute_accessor_);
+ }
+
+ if (he)
+ {
+ os << "// Individual element parsers." << endl
+ << "//" << endl;
+
+ contains_compositor (c, contains_compositor_accessor_);
+ }
+ }
+
+ if (!restriction && (he || ha) && reset)
+ {
+ os << "virtual void" << endl
+ << "_reset ();"
+ << endl;
+ }
+
+ // Default c-tor.
+ //
+ if (tiein ||
+ (!restriction && (he || ha)) ||
+ (validation && (he || hae || hra)))
+ {
+ os << "// Constructor." << endl
+ << "//" << endl;
+
+ if (hb && tiein)
+ os << name << " (" << fq_name (c.inherits ().base ()) <<
+ "* tiein);"
+ << endl;
+ else
+ os << name << " ();"
+ << endl;
+ }
+
+ if (poly_code)
+ {
+ os << "public:" << endl
+ << "static const char*" << endl
+ << "_static_type ();"
+ << endl
+ << "virtual const char*" << endl
+ << "_dynamic_type () const;"
+ << endl;
+ }
+
+ // Implementation.
+ //
+ if (tiein || he || ha || (validation && (hae || haa)))
+ {
+ os << "// Implementation details." << endl
+ << "//" << endl;
+ }
+
+ if (tiein)
+ {
+ if (hb)
+ {
+ // If our base has pure virtual post, override it here.
+ //
+ SemanticGraph::Type& base (c.inherits ().base ());
+
+ String const& base_ret (ret_type (base));
+
+ Boolean base_same (
+ base.inherits_p () &&
+ base_ret == ret_type (base.inherits ().base ()));
+
+ if (!(base_same || base_ret == L"void"))
+ os << "virtual " << base_ret << endl
+ << post_name (base) << " ();"
+ << endl;
+ }
+
+ os << "protected:" << endl
+ << name << "* " << etiein (c) << ";"
+ << name << " (" << name << "*, void*);"
+ << endl;
+ }
+
+ // element
+ //
+ if (he || (validation && hae))
+ {
+ os << "protected:" << endl;
+
+ // _start_element_impl
+ //
+ os << "virtual bool" << endl
+ << "_start_element_impl (const " << string_type << "&," << endl
+ << "const " << string_type << "&";
+
+ if (poly_runtime)
+ os << "," << endl
+ << "const char*";
+
+ os << ");"
+ << endl;
+
+ // end_element
+ //
+ os << "virtual bool" << endl
+ << "_end_element_impl (const " << string_type << "&," << endl
+ << "const " << string_type << "&);"
+ << endl;
+ }
+
+ // attribute
+ //
+ if (validation)
+ {
+ if (ha || haa)
+ os << "protected:" << endl;
+
+ if (ha)
+ {
+ os << "virtual bool" << endl
+ << "_attribute_impl_phase_one (const " << string_type <<
+ "&," << endl
+ << "const " << string_type << "&," << endl
+ << "const " << string_type << "&);" << endl
+ << endl;
+ }
+
+ if (haa)
+ {
+ os << "virtual bool" << endl
+ << "_attribute_impl_phase_two (const " << string_type <<
+ "&," << endl
+ << "const " << string_type << "&," << endl
+ << "const " << string_type << "&);"
+ << endl;
+ }
+ }
+ else
+ {
+ if (ha)
+ {
+ os << "protected:" << endl
+ << "virtual bool" << endl
+ << "_attribute_impl (const " << string_type << "&," << endl
+ << "const " << string_type << "&," << endl
+ << "const " << string_type << "&);"
+ << endl;
+ }
+ }
+
+ // characters
+ //
+ if (validation && c.mixed ())
+ {
+ os << "protected:" << endl
+ << "virtual bool" << endl
+ << "_characters_impl (const " << string_type << "&);"
+ << endl;
+ }
+
+ if (!restriction && (he || ha))
+ {
+ os << "protected:" << endl;
+
+ if (ha)
+ names (c, names_attribute_member_);
+
+ if (he)
+ contains_compositor (c, contains_compositor_member_);
+
+ os << endl;
+ }
+
+ if (validation && (he || hae))
+ {
+ UnsignedLong depth (c.context ().get<UnsignedLong> ("p:depth"));
+
+ os << "protected:" << endl;
+
+ os << "struct v_state_descr_"
+ << "{"
+ << "void (" << fq_name (c) << "::*func) (" << endl
+ << "unsigned long&," << endl
+ << "unsigned long&," << endl
+ << "const " << string_type << "&," << endl
+ << "const " << string_type << "&," << endl;
+
+ if (poly_runtime)
+ os << "const char*," << endl;
+
+ os << "bool);"
+ << "unsigned long state;"
+ << "unsigned long count;"
+ << "};";
+
+ // Allocate one extra slot for the special state.
+ //
+ os << "struct v_state_"
+ << "{"
+ << "v_state_descr_ data[" << depth + 1 << "UL];"
+ << "unsigned long size;"
+ << "};";
+
+ os << "v_state_ v_state_first_;"
+ << "::xsde::cxx::parser::stack v_state_stack_;"
+ << endl;
+
+ os << "virtual void" << endl
+ << "_pre_e_validate ();"
+ << endl;
+
+ os << "virtual void" << endl
+ << "_post_e_validate ();"
+ << endl;
+
+ Particle t (*this);
+ t.dispatch (c.contains_compositor ().compositor ());
+ }
+
+ if (validation && hra)
+ {
+ os << "protected:" << endl;
+
+ os << "struct v_state_attr_"
+ << "{";
+
+ names (c, names_attribute_validation_state_);
+
+ os << "};";
+
+ os << "v_state_attr_ v_state_attr_first_;"
+ << "::xsde::cxx::parser::stack v_state_attr_stack_;"
+ << endl;
+
+ os << "virtual void" << endl
+ << "_pre_a_validate ();"
+ << endl;
+
+ os << "virtual void" << endl
+ << "_post_a_validate ();"
+ << endl;
+ }
+
+ os << "};";
+ }
+
+ private:
+ //
+ //
+ CompositorCallback compositor_callback_val_;
+ Traversal::Compositor compositor_callback_non_val_;
+ ParticleCallback particle_callback_;
+ Traversal::ContainsCompositor contains_compositor_callback_;
+ Traversal::ContainsParticle contains_particle_callback_;
+
+ AttributeCallback attribute_callback_;
+ Traversal::Names names_attribute_callback_;
+
+ //
+ //
+ Traversal::Compositor compositor_accessor_;
+ ParticleAccessor particle_accessor_;
+ Traversal::ContainsCompositor contains_compositor_accessor_;
+ Traversal::ContainsParticle contains_particle_accessor_;
+
+ AttributeAccessor attribute_accessor_;
+ Traversal::Names names_attribute_accessor_;
+
+ //
+ //
+ Traversal::Compositor compositor_member_;
+ ParticleMember particle_member_;
+ Traversal::ContainsCompositor contains_compositor_member_;
+ Traversal::ContainsParticle contains_particle_member_;
+
+ AttributeMember attribute_member_;
+ Traversal::Names names_attribute_member_;
+
+ //
+ //
+ AttributeValidationState attribute_validation_state_;
+ Traversal::Names names_attribute_validation_state_;
+ };
+
+ 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), xs_ns_ (xs_ns_name ())
+ {
+ impl_ns_ = "::xsde::cxx::parser::";
+ impl_ns_ += (validation ? L"validating" : L"non_validating");
+
+ if (options.value<CLI::no_stl> ())
+ {
+ qname_type_ = xs_ns_ + L"::qname*";
+ string_type_ = L"char*";
+ }
+ else
+ {
+ qname_type_ = xs_ns_ + L"::qname";
+ string_type_ = L"::std::string";
+ }
+
+ string_seq_type_ = xs_ns_ + L"::string_sequence*";
+ buffer_type_ = xs_ns_ + L"::buffer*";
+
+ 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& t)
+ {
+ gen_typedef (t, "void");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnySimpleType& t)
+ {
+ gen_typedef (t, "void");
+ }
+
+ // Boolean.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Boolean& t)
+ {
+ gen_typedef (t, "bool");
+ }
+
+ // Integral types.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Byte& t)
+ {
+ gen_typedef (t, "signed char");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedByte& t)
+ {
+ gen_typedef (t, "unsigned char");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Short& t)
+ {
+ gen_typedef (t, "short");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedShort& t)
+ {
+ gen_typedef (t, "unsigned short");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Int& t)
+ {
+ gen_typedef (t, "int");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedInt& t)
+ {
+ gen_typedef (t, "unsigned int");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Long& t)
+ {
+ gen_typedef (t, long_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedLong& t)
+ {
+ gen_typedef (t, unsigned_long_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Integer& t)
+ {
+ gen_typedef (t, "long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NegativeInteger& t)
+ {
+ gen_typedef (t, "long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonPositiveInteger& t)
+ {
+ gen_typedef (t, "long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::PositiveInteger& t)
+ {
+ gen_typedef (t, "unsigned long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonNegativeInteger& t)
+ {
+ gen_typedef (t, "unsigned long");
+ }
+
+ // Floats.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Float& t)
+ {
+ gen_typedef (t, "float");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Double& t)
+ {
+ gen_typedef (t, "double");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Decimal& t)
+ {
+ gen_typedef (t, "double");
+ }
+
+ // Strings.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::String& t)
+ {
+ gen_typedef (t, string_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NormalizedString& t)
+ {
+ gen_typedef (t, string_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Token& t)
+ {
+ gen_typedef (t, string_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameToken& t)
+ {
+ nmtoken_ = gen_typedef (t, string_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameTokens& t)
+ {
+ // NMTOKENS uses NMTOKEN implementation to parse individual items.
+ // As a result, we don't generate NMTOKENS if we didn't generate
+ // NMTOKEN. Here we assume NMTOKEN is handled before NMTOKENS.
+ //
+ if(nmtoken_)
+ gen_typedef (t, string_seq_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Name& t)
+ {
+ gen_typedef (t, string_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NCName& t)
+ {
+ gen_typedef (t, string_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Language& t)
+ {
+ gen_typedef (t, string_type_);
+ }
+
+ // Qualified name.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::QName& t)
+ {
+ gen_typedef (t, qname_type_);
+ }
+
+ // ID/IDREF.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Id& t)
+ {
+ gen_typedef (t, string_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRef& t)
+ {
+ idref_ = gen_typedef (t, string_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRefs& t)
+ {
+ // IDREFS uses IDREF implementation to parse individual items.
+ // As a result, we don't generate IDREFS if we didn't generate
+ // IDREF. Here we assume IDREF is handled before IDREFS.
+ //
+ if (idref_)
+ gen_typedef (t, string_seq_type_);
+ }
+
+ // URI.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::AnyURI& t)
+ {
+ gen_typedef (t, string_type_);
+ }
+
+ // Binary.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Base64Binary& t)
+ {
+ gen_typedef (t, buffer_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::HexBinary& t)
+ {
+ gen_typedef (t, buffer_type_);
+ }
+
+
+ // Date/time.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Date& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::date");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::DateTime& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::date_time");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Duration& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::duration");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Day& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::gday");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Month& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::gmonth");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::MonthDay& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::gmonth_day");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Year& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::gyear");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::YearMonth& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::gyear_month");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Time& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::time");
+ }
+
+ // Entity.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entity&)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entities&)
+ {
+ }
+
+ private:
+ Boolean
+ gen_typedef (SemanticGraph::Type& t, String const& type)
+ {
+ if (ret_type (t) == type)
+ {
+ SemanticGraph::Context& c (t.context ());
+
+ String const& real_name (c.get<String> ("p:real-name"));
+ String const& name (c.get<String> ("p:name"));
+
+ os << "typedef " << real_name << " " << name << ";";
+
+ String const& real_impl (c.get<String> ("p:real-impl"));
+ String const& impl (c.get<String> ("p:impl"));
+
+ os << "typedef " << real_impl << " " << impl << ";"
+ << endl;
+
+ return true;
+ }
+
+ return false;
+ }
+
+ String xs_ns_;
+ String impl_ns_;
+ String qname_type_;
+ String string_type_;
+ String buffer_type_;
+ String string_seq_type_;
+ String long_type_;
+ String unsigned_long_type_;
+
+ Boolean idref_;
+ Boolean nmtoken_;
+ };
+
+ struct FundNamespace : Namespace, Context
+ {
+ FundNamespace (Context& c)
+ : Namespace (c), Context (c)
+ {
+ }
+
+ void
+ traverse (Type& ns)
+ {
+ pre (ns);
+
+ String impl ("::xsde::cxx::parser::");
+ impl += (validation ? L"validating" : L"non_validating");
+
+ String const c (char_type);
+
+ os << "// Built-in XML Schema types mapping." << endl
+ << "//" << endl
+ << "using ::xsde::cxx::string_sequence;"
+ << "using ::xsde::cxx::qname;"
+ << "using ::xsde::cxx::buffer;"
+ << "using ::xsde::cxx::time_zone;"
+ << "using ::xsde::cxx::gday;"
+ << "using ::xsde::cxx::gmonth;"
+ << "using ::xsde::cxx::gyear;"
+ << "using ::xsde::cxx::gmonth_day;"
+ << "using ::xsde::cxx::gyear_month;"
+ << "using ::xsde::cxx::date;"
+ << "using ::xsde::cxx::time;"
+ << "using ::xsde::cxx::date_time;"
+ << "using ::xsde::cxx::duration;"
+ << endl;
+
+ os << "// Base parser skeletons." << endl
+ << "//" << endl
+ << "using ::xsde::cxx::parser::parser_base;"
+ << "typedef " << impl << "::empty_content " <<
+ "parser_empty_content;"
+ << "typedef " << impl << "::simple_content " <<
+ "parser_simple_content;"
+ << "typedef " << impl << "::complex_content " <<
+ "parser_complex_content;"
+ << "typedef " << impl << "::list_base parser_list_base;"
+ << endl;
+
+ if (poly_code)
+ {
+ os << "// Parser map interface and default implementation." << endl
+ << "//" << endl
+ << "using ::xsde::cxx::parser::parser_map;"
+ << "using ::xsde::cxx::parser::parser_map_impl;"
+ << endl;
+
+ os << "// Substitution and inheritance hashmaps load querying." << endl
+ << "//" << endl
+ << "using ::xsde::cxx::parser::parser_smap_buckets;"
+ << "using ::xsde::cxx::parser::parser_smap_elements;";
+
+ if (validation)
+ os << "using ::xsde::cxx::parser::validating::parser_imap_buckets;"
+ << "using ::xsde::cxx::parser::validating::parser_imap_elements;";
+
+ os << endl;
+ }
+
+ os << "// Parser skeletons and implementations for the XML Schema" << endl
+ << "// built-in types." << endl
+ << "//" << endl;
+
+ names (ns);
+
+ os << "// Read-only string." << endl
+ << "//" << endl
+ << "using ::xsde::cxx::ro_string;"
+ << endl;
+
+ os << "// Error codes." << endl
+ << "//" << endl;
+
+ if (!exceptions)
+ os << "using xsde::cxx::sys_error;";
+
+ os << "typedef xsde::cxx::parser::expat::xml_error " <<
+ "parser_xml_error;";
+
+ if (validation)
+ os << "typedef xsde::cxx::schema_error parser_schema_error;";
+
+ os << endl;
+
+ if (exceptions)
+ {
+ os << "// Exceptions." << endl
+ << "//" << endl
+ << "typedef xsde::cxx::parser::exception parser_exception;"
+ << "typedef xsde::cxx::parser::xml parser_xml;";
+
+ if (validation)
+ os << "typedef xsde::cxx::parser::schema parser_schema;";
+
+ os << endl;
+ }
+ else
+ os << "// Error object." << endl
+ << "//" << endl
+ << "typedef xsde::cxx::parser::error parser_error;"
+ << endl;
+
+ os << "// Document parser." << endl
+ << "//" << endl
+ << "using xsde::cxx::parser::expat::document_pimpl;"
+ << endl;
+
+ os << "// Parser context." << endl
+ << "//" << endl
+ << "typedef xsde::cxx::parser::context parser_context;"
+ << endl;
+
+ post (ns);
+ }
+ };
+ }
+
+ Void
+ generate_parser_header (Context& ctx, Boolean generate_xml_schema)
+ {
+ NarrowString extern_xml_schema;
+
+ if (!generate_xml_schema)
+ extern_xml_schema = ctx.options.value<CLI::extern_xml_schema> ();
+
+ if (extern_xml_schema)
+ {
+ String name (ctx.hxx_expr->merge (extern_xml_schema));
+
+ ctx.os << "#include " << ctx.process_include_path (name) << endl
+ << endl;
+
+ // Generate includes that came from the type map.
+ //
+ if (ctx.schema_root.context ().count ("p:includes"))
+ {
+ typedef Cult::Containers::Set<String> Includes;
+
+ Includes& is (
+ ctx.schema_root.context ().get<Includes> ("p:includes"));
+
+ for (Includes::ConstReverseIterator i (is.rbegin ());
+ i != is.rend (); ++i)
+ {
+ ctx.os << "#include " << *i << endl;
+ }
+
+ ctx.os << endl;
+ }
+ }
+ else
+ {
+ ctx.os << "#include <xsde/config.h>" << endl
+ << "#include <xsde/cxx/ro-string.hxx>" << endl
+ << endl;
+
+ // Data types.
+ //
+ ctx.os << "#include <xsde/cxx/parser/xml-schema.hxx>" << endl
+ << endl;
+
+ // Error handling.
+ //
+ if (ctx.exceptions)
+ ctx.os << "#include <xsde/cxx/parser/exceptions.hxx>" << endl
+ << endl;
+ else
+ {
+ ctx.os << "#include <xsde/cxx/sys-error.hxx>" << endl;
+
+ if (ctx.validation)
+ ctx.os << "#include <xsde/cxx/schema-error.hxx>" << endl;
+
+ ctx.os << "#include <xsde/cxx/parser/error.hxx>" << endl
+ << "#include <xsde/cxx/parser/expat/xml-error.hxx>" << endl
+ << endl;
+ }
+
+ // Polymorphism support.
+ //
+ if (ctx.poly_code)
+ {
+ ctx.os << "#include <xsde/cxx/parser/map.hxx>" << endl
+ << "#include <xsde/cxx/parser/substitution-map-load.hxx>" << endl;
+
+ if (ctx.validation)
+ ctx.os << "#include <xsde/cxx/parser/validating/inheritance-map-load.hxx>" << endl;
+
+ ctx.os << endl;
+ }
+
+ // Parsers.
+ //
+ if (ctx.validation)
+ ctx.os << "#include <xsde/cxx/parser/validating/parser.hxx>" << endl
+ << "#include <xsde/cxx/parser/validating/xml-schema-pskel.hxx>" << endl
+ << "#include <xsde/cxx/parser/validating/xml-schema-pimpl.hxx>" << endl
+ << endl;
+ else
+ ctx.os << "#include <xsde/cxx/parser/non-validating/parser.hxx>" << endl
+ << "#include <xsde/cxx/parser/non-validating/xml-schema-pskel.hxx>" << endl
+ << "#include <xsde/cxx/parser/non-validating/xml-schema-pimpl.hxx>" << endl
+ << endl;
+
+ // Document.
+ //
+ ctx.os << "#include <xsde/cxx/parser/expat/document.hxx>" << endl
+ << endl;
+
+ // Generate includes that came from the type map.
+ //
+ if (ctx.schema_root.context ().count ("p:includes"))
+ {
+ typedef Cult::Containers::Set<String> Includes;
+
+ Includes& is (
+ ctx.schema_root.context ().get<Includes> ("p:includes"));
+
+ for (Includes::ConstReverseIterator i (is.rbegin ());
+ i != is.rend (); ++i)
+ {
+ ctx.os << "#include " << *i << endl;
+ }
+
+ ctx.os << endl;
+ }
+
+ // Generate fundamental types.
+ //
+ 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);
+ }
+ 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);
+ }
+ }
+
+ // Generate user type mapping.
+ //
+ if (!generate_xml_schema)
+ {
+ Traversal::Schema schema;
+
+ Traversal::Sources sources;
+ Includes includes (ctx, Includes::header);
+ Traversal::Names schema_names;
+
+ Namespace ns (ctx);
+ Traversal::Names names;
+
+ schema >> includes;
+ schema >> sources >> schema;
+ schema >> schema_names >> ns >> names;
+
+ List list (ctx);
+ Union union_ (ctx);
+ Complex complex (ctx);
+ Enumeration enumeration (ctx);
+
+ names >> list;
+ names >> union_;
+ names >> complex;
+ names >> enumeration;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+ }
+}
diff --git a/xsde/cxx/parser/parser-header.hxx b/xsde/cxx/parser/parser-header.hxx
new file mode 100644
index 0000000..0baf7bc
--- /dev/null
+++ b/xsde/cxx/parser/parser-header.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/parser/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_PARSER_PARSER_HEADER_HXX
+#define CXX_PARSER_PARSER_HEADER_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/parser/elements.hxx>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ Void
+ generate_parser_header (Context&, Boolean generate_xml_schema);
+ }
+}
+
+#endif // CXX_PARSER_PARSER_HEADER_HXX
diff --git a/xsde/cxx/parser/parser-inline.cxx b/xsde/cxx/parser/parser-inline.cxx
new file mode 100644
index 0000000..689f95f
--- /dev/null
+++ b/xsde/cxx/parser/parser-inline.cxx
@@ -0,0 +1,721 @@
+// file : xsde/cxx/parser/parser-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/parser/parser-inline.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ namespace
+ {
+ struct Enumeration: Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (tiein)
+ {
+ String const& name (ename (e));
+ String const& impl (etiein (e));
+
+ // We have to use "real" (non-typedef) base name in base
+ // initializer because of some broken compilers (EVC 4.0).
+ //
+ SemanticGraph::Type& base (e.inherits ().base ());
+ String fq_base (fq_name (base));
+ String real_fq_base (real_fq_name (base));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ os << inl
+ << name << "::" << endl
+ << name << " (" << fq_base << "* tiein)" << endl
+ << ": " << real_fq_base << " (tiein, 0)," << endl
+ << " " << impl << " (0)"
+ << "{"
+ << "}";
+
+ os << inl
+ << name << "::" << endl
+ << name << " (" << name << "* impl, void*)" << endl
+ << ": " << real_fq_base << " (impl, 0)," << endl
+ << " " << impl << " (impl)"
+ << "{"
+ << "}";
+ }
+ }
+ };
+
+ //
+ //
+ struct List: Traversal::List, Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String const& name (ename (l));
+ SemanticGraph::Type& t (l.argumented ().type ());
+ String item_type (fq_name (t));
+
+ String item (unclash (name, "item"));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ // item_parser
+ //
+ os << inl
+ << "void " << name << "::" << endl
+ << unclash (name, "item_parser") << " (" <<
+ item_type << "& " << item << ")"
+ << "{"
+ << "this->_xsde_" << item << "_ = &" << item << ";"
+ << "}";
+
+ // parsers
+ //
+ os << inl
+ << "void " << name << "::" << endl
+ << "parsers (" << item_type << "& " << item << ")"
+ << "{"
+ << "this->_xsde_" << item << "_ = &" << item << ";"
+ << "}";
+
+ // c-tor
+ //
+ os << inl
+ << name << "::" << endl
+ << name << " ()" << endl
+ << ": ";
+
+ if (tiein)
+ os << etiein (l) << " (0)," << endl
+ << " ";
+
+ os << "_xsde_" << item << "_ (0)"
+ << "{"
+ << "}";
+
+ if (tiein)
+ {
+ os << inl
+ << name << "::" << endl
+ << name << " (" << name << "* impl, void*)" << endl
+ << ": " << list_base << " (impl, 0)," << endl
+ << " " << etiein (l) << " (impl)," << endl
+ << " _xsde_" << item << "_ (0)"
+ << "{"
+ << "}";
+ }
+ }
+ };
+
+ struct Union: Traversal::Union, Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ if (tiein)
+ {
+ String const& name (ename (u));
+ String const& impl (etiein (u));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ //
+ //
+ os << inl
+ << name << "::" << endl
+ << name << " ()" << endl
+ << ": " << impl << " (0)"
+ << "{"
+ << "}";
+
+ //
+ //
+ os << inl
+ << name << "::" << endl
+ << name << " (" << name << "* impl, void*)" << endl
+ << ": " << simple_base << " (impl, 0)," << endl
+ << " " << impl << " (impl)"
+ << "{"
+ << "}";
+ }
+ }
+ };
+
+ //
+ //
+ struct ParticleAccessor: Traversal::Element, Context
+ {
+ ParticleAccessor (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ String const& scope (ename (e.scope ()));
+ String const& parser (eparser (e));
+
+ os << inl
+ << "void " << scope << "::" << endl
+ << parser << " (" << fq_name (e.type ()) << "& p)"
+ << "{"
+ << "this->" << emember (e) << " = &p;"
+ << "}";
+
+ if (poly_code && !anonymous (e.type ()))
+ {
+ os << inl
+ << "void " << scope << "::" << endl
+ << parser << " (" << parser_map << "& m)"
+ << "{"
+ << "this->" << emember_map (e) << " = &m;"
+ << "}";
+ }
+ }
+ };
+
+ struct AttributeAccessor: Traversal::Attribute, Context
+ {
+ AttributeAccessor (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ os << inl
+ << "void " << ename (a.scope ()) << "::" << endl
+ << eparser (a) << " (" << fq_name (a.type ()) << "& p)"
+ << "{"
+ << "this->" << emember (a) << " = &p;"
+ << "}";
+ }
+ };
+
+ //
+ //
+ struct ParticleMemberSet: Traversal::Element, Context
+ {
+ ParticleMemberSet (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ os << "this->" << emember (e) << " = &" << ename (e) << ";";
+ }
+ };
+
+ struct AttributeMemberSet: Traversal::Attribute, Context
+ {
+ AttributeMemberSet (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ os << "this->" << emember (a) << " = &" << ename (a) << ";";
+ }
+ };
+
+ struct BaseMemberSet: Traversal::Complex,
+ Traversal::List,
+ Context
+ {
+ BaseMemberSet (Context& c)
+ : Context (c)
+ {
+ inherits_ >> *this;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ inherits (c, inherits_);
+
+ if (!restriction_p (c))
+ {
+ names (c);
+ contains_compositor (c);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::List& l)
+ {
+ String const& name (ename (l));
+ String item (unclash (name, "item"));
+
+ os << "this->_xsde_" << item << "_ = &" << name << "_item;";
+ }
+
+ private:
+ Traversal::Inherits inherits_;
+ };
+
+ //
+ //
+ struct ParticleMemberInit: Traversal::Element, Context
+ {
+ ParticleMemberInit (Context& c, Boolean comma)
+ : Context (c), first_ (!comma)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (first_)
+ first_ = false;
+ else
+ os << "," << endl << " ";
+
+ os << emember (e) << " (0)";
+
+ if (poly_code && !anonymous (e.type ()))
+ {
+ os << "," << endl
+ << " " << emember_map (e) << " (0)";
+ }
+ }
+
+ Boolean
+ comma () const
+ {
+ return !first_;
+ }
+
+ private:
+ Boolean first_;
+ };
+
+ struct AttributeMemberInit: Traversal::Attribute, Context
+ {
+ AttributeMemberInit (Context& c, Boolean comma)
+ : Context (c), first_ (!comma)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ if (first_)
+ first_ = false;
+ else
+ os << "," << endl << " ";
+
+ os << emember (a) << " (0)";
+ }
+
+ Boolean
+ comma () const
+ {
+ return !first_;
+ }
+
+ private:
+ Boolean first_;
+ };
+
+ //
+ //
+ struct Particle: Traversal::All, Context
+ {
+ Particle (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ if (!a.context().count ("p:comp-number"))
+ return;
+
+ UnsignedLong state_count (
+ a.context().get<UnsignedLong> ("p:state-count"));
+
+ os << "," << endl
+ << " v_all_count_ (" << state_count << "UL, v_all_first_)";
+ }
+ };
+
+
+ //
+ //
+ struct Complex: Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c),
+ particle_accessor_ (c),
+ attribute_accessor_ (c),
+ base_set_ (c),
+ particle_set_ (c),
+ attribute_set_ (c),
+ particle_ (c)
+ {
+ // Accessor.
+ //
+ contains_compositor_accessor_ >> compositor_accessor_;
+ compositor_accessor_ >> contains_particle_accessor_;
+ contains_particle_accessor_ >> compositor_accessor_;
+ contains_particle_accessor_ >> particle_accessor_;
+
+ names_attribute_accessor_ >> attribute_accessor_;
+
+ // Member set.
+ //
+ inherits_base_set_ >> base_set_;
+ base_set_ >> contains_compositor_set_;
+ base_set_ >> names_attribute_set_;
+
+ contains_compositor_set_ >> compositor_set_;
+ compositor_set_ >> contains_particle_set_;
+ contains_particle_set_ >> compositor_set_;
+ contains_particle_set_ >> particle_set_;
+
+ names_attribute_set_ >> attribute_set_;
+ }
+
+ virtual Void
+ traverse (Type& 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 hra (false); // Has required attribute.
+ if (ha)
+ {
+ RequiredAttributeTest test (hra);
+ Traversal::Names names_test (test);
+ names (c, names_test);
+ }
+
+ Boolean restriction (restriction_p (c));
+
+ if (!(tiein ||
+ (!restriction && (he || ha)) ||
+ (validation && (he || hae || hra))))
+ return;
+
+ String const& name (ename (c));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ if (!restriction && (he || ha))
+ {
+ // <name>_parser ()
+ //
+ if (ha)
+ names (c, names_attribute_accessor_);
+
+ if (he)
+ contains_compositor (c, contains_compositor_accessor_);
+
+
+ // parsers ()
+ //
+
+ os << inl
+ << "void " << name << "::" << endl
+ << "parsers (";
+
+ {
+ ParserParamDecl decl (*this, true);
+ decl.traverse (c);
+ }
+
+ os << ")"
+ << "{";
+
+ inherits (c, inherits_base_set_);
+
+ if (ha)
+ names (c, names_attribute_set_);
+
+ if (he)
+ contains_compositor (c, contains_compositor_set_);
+
+ os << "}";
+ }
+
+ // We have to use "real" (non-typedef) base name in base
+ // initializer because of some broken compilers (EVC 4.0).
+ //
+ String real_fq_base;
+
+ if (hb && tiein)
+ real_fq_base = real_fq_name (c.inherits ().base ());
+
+ // Default c-tor.
+ //
+ os << inl
+ << name << "::" << endl;
+
+ if (hb && tiein)
+ os << name << " (" << fq_name (c.inherits ().base ()) <<
+ "* tiein)" << endl;
+ else
+ os << name << " ()" << endl;
+
+ os << ": ";
+
+ Boolean comma (false);
+
+ if (hb && tiein)
+ {
+ os << real_fq_base << " (tiein, 0)";
+ comma = true;
+ }
+
+ if (tiein)
+ {
+ if (comma)
+ os << "," << endl << " ";
+
+ os << etiein (c) << " (0)";
+ comma = true;
+ }
+
+ if (!restriction && (he || ha))
+ {
+ if (ha)
+ {
+ AttributeMemberInit attribute_init (*this, comma);
+ Traversal::Names names_attribute_init;
+
+ names_attribute_init >> attribute_init;
+
+ names (c, names_attribute_init);
+
+ comma = attribute_init.comma ();
+ }
+
+ if (he)
+ {
+ Traversal::Compositor compositor_init;
+ ParticleMemberInit particle_init (*this, comma);
+ Traversal::ContainsCompositor contains_compositor_init;
+ Traversal::ContainsParticle contains_particle_init;
+
+ contains_compositor_init >> compositor_init;
+ compositor_init >> contains_particle_init;
+ contains_particle_init >> compositor_init;
+ contains_particle_init >> particle_init;
+
+ contains_compositor (c, contains_compositor_init);
+
+ comma = particle_init.comma ();
+ }
+ }
+
+ if (validation && (he || hae))
+ {
+ if (comma)
+ os << "," << endl << " ";
+
+ os << "v_state_stack_ (sizeof (v_state_), &v_state_first_)";
+
+ particle_.dispatch (c.contains_compositor ().compositor ());
+
+ comma = true;
+ }
+
+ if (validation && (hra))
+ {
+ if (comma)
+ os << "," << endl << " ";
+
+ os << "v_state_attr_stack_ (sizeof (v_state_attr_), " <<
+ "&v_state_attr_first_)";
+ }
+
+ os << "{"
+ << "}";
+
+ // Tiein c-tor.
+ //
+ if (tiein)
+ {
+ os << inl
+ << name << "::" << endl
+ << name << " (" << name << "* impl, void*)" << endl
+ << ": ";
+
+ if (hb)
+ os << real_fq_base << " (impl, 0)," << endl;
+ else
+ os << complex_base << " (impl, 0)," << endl;
+
+ os << " " << etiein (c) << " (impl)";
+
+ Boolean comma (true);
+
+ if (!restriction && (he || ha))
+ {
+ if (ha)
+ {
+ AttributeMemberInit attribute_init (*this, comma);
+ Traversal::Names names_attribute_init;
+
+ names_attribute_init >> attribute_init;
+
+ names (c, names_attribute_init);
+
+ comma = attribute_init.comma ();
+ }
+
+ if (he)
+ {
+ Traversal::Compositor compositor_init;
+ ParticleMemberInit particle_init (*this, comma);
+ Traversal::ContainsCompositor contains_compositor_init;
+ Traversal::ContainsParticle contains_particle_init;
+
+ contains_compositor_init >> compositor_init;
+ compositor_init >> contains_particle_init;
+ contains_particle_init >> compositor_init;
+ contains_particle_init >> particle_init;
+
+ contains_compositor (c, contains_compositor_init);
+
+ comma = particle_init.comma ();
+ }
+ }
+
+ if (validation && (he || hae))
+ {
+ if (comma)
+ os << "," << endl << " ";
+
+ os << "v_state_stack_ (sizeof (v_state_), &v_state_first_)";
+
+ particle_.dispatch (c.contains_compositor ().compositor ());
+
+ comma = true;
+ }
+
+ if (validation && (hra))
+ {
+ if (comma)
+ os << "," << endl << " ";
+
+ os << "v_state_attr_stack_ (sizeof (v_state_attr_), " <<
+ "&v_state_attr_first_)";
+ }
+
+ os << "{"
+ << "}";
+ }
+ }
+
+ private:
+ //
+ //
+ Traversal::Compositor compositor_accessor_;
+ ParticleAccessor particle_accessor_;
+ Traversal::ContainsCompositor contains_compositor_accessor_;
+ Traversal::ContainsParticle contains_particle_accessor_;
+
+ AttributeAccessor attribute_accessor_;
+ Traversal::Names names_attribute_accessor_;
+
+ //
+ //
+ BaseMemberSet base_set_;
+ Traversal::Inherits inherits_base_set_;
+
+ Traversal::Compositor compositor_set_;
+ ParticleMemberSet particle_set_;
+ Traversal::ContainsCompositor contains_compositor_set_;
+ Traversal::ContainsParticle contains_particle_set_;
+
+ AttributeMemberSet attribute_set_;
+ Traversal::Names names_attribute_set_;
+
+ //
+ //
+ Particle particle_;
+ };
+ }
+
+ Void
+ generate_parser_inline (Context& ctx)
+ {
+ // Emit "weak" header includes that are used in the file-per-type
+ // compilation model.
+ //
+ if (!ctx.options.value<CLI::generate_inline> ())
+ {
+ 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;
+
+ Enumeration enumeration (ctx);
+ List list (ctx);
+ Union union_ (ctx);
+ Complex complex (ctx);
+
+ names >> enumeration;
+ names >> list;
+ names >> union_;
+ names >> complex;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+}
diff --git a/xsde/cxx/parser/parser-inline.hxx b/xsde/cxx/parser/parser-inline.hxx
new file mode 100644
index 0000000..c54f537
--- /dev/null
+++ b/xsde/cxx/parser/parser-inline.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/parser/parser-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_PARSER_PARSER_INLINE_HXX
+#define CXX_PARSER_PARSER_INLINE_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/parser/elements.hxx>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ Void
+ generate_parser_inline (Context&);
+ }
+}
+
+#endif // CXX_PARSER_PARSER_INLINE_HXX
diff --git a/xsde/cxx/parser/parser-source.cxx b/xsde/cxx/parser/parser-source.cxx
new file mode 100644
index 0000000..5e1e9bd
--- /dev/null
+++ b/xsde/cxx/parser/parser-source.cxx
@@ -0,0 +1,1626 @@
+// file : xsde/cxx/parser/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/parser/parser-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ namespace
+ {
+ struct Enumeration: Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ String const& name (ename (e));
+ String const& ret (ret_type (e));
+ SemanticGraph::Type& base (e.inherits ().base ());
+ String const& base_ret (ret_type (base));
+
+ Boolean same (ret == base_ret);
+ Boolean base_same (
+ base.inherits_p () &&
+ base_ret == ret_type (base.inherits ().base ()));
+
+ if (same || ret == L"void" || poly_code ||
+ (tiein && !(base_same || base_ret == L"void")))
+ {
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+ }
+
+ if (same || ret == L"void")
+ {
+ String const& post (post_name (e));
+
+ os << ret << " " << name << "::" << endl
+ << post << " ()"
+ << "{";
+
+ if (tiein)
+ {
+ String const& impl (etiein (e));
+
+ os << "if (this->" << impl << ")" << endl
+ << (ret != L"void" ? "return " : "") << "this->" <<
+ impl << "->" << post << " ();";
+ }
+
+ if (same)
+ {
+ if (tiein)
+ os << "else" << endl;
+
+ if (ret == L"void")
+ os << post_name (base) << " ();";
+ else
+ os << "return " << post_name (base) << " ();";
+ }
+
+ os << "}";
+ }
+
+ if (poly_code)
+ {
+ String id (e.name ());
+
+ if (String ns = xml_ns_name (e))
+ {
+ id += L' ';
+ id += ns;
+ }
+
+ os << "const char* " << name << "::" << endl
+ << "_static_type ()"
+ << "{"
+ << "return " << strlit (id) << ";"
+ << "}";
+
+ os << "const char* " << name << "::" << endl
+ << "_dynamic_type () const"
+ << "{"
+ << "return _static_type ();"
+ << "}";
+
+ if (validation)
+ {
+ Boolean gen (!anonymous (e));
+
+ // We normally don't need to enter anonymous types into
+ // the inheritance map. The only exception is when an
+ // anonymous types is defined inside an element that
+ // is a member of a substitution group.
+ //
+ if (!gen)
+ {
+ // The first instance that this anonymous type classifies
+ // is the prototype for others if any.
+ //
+ SemanticGraph::Instance& i (
+ e.classifies_begin ()->instance ());
+
+ if (SemanticGraph::Element* e =
+ dynamic_cast<SemanticGraph::Element*> (&i))
+ {
+ if (e->substitutes_p ())
+ gen = true;
+ }
+ }
+
+ if (gen)
+ {
+ os << "static" << endl
+ << "const ::xsde::cxx::parser::validating::" <<
+ "inheritance_map_entry" << endl
+ << "_xsde_" << name << "_inheritance_map_entry_ (" << endl
+ << name << "::_static_type ()," << endl
+ << fq_name (base) << "::_static_type ());"
+ << endl;
+ }
+ }
+ }
+
+ if (tiein && !(base_same || base_ret == L"void"))
+ {
+ String const& impl (etiein (base));
+ String const& base_post (post_name (base));
+
+ os << base_ret << " " << name << "::" << endl
+ << base_post << " ()"
+ << "{"
+ << "assert (this->" << impl << ");"
+ << "return this->" << impl << "->" << base_post << " ();"
+ << "}";
+ }
+ }
+ };
+
+ //
+ //
+ struct List: Traversal::List, Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String const& name (ename (l));
+ SemanticGraph::Type& t (l.argumented ().type ());
+
+ String item (unclash (name, "item"));
+ String inst (L"_xsde_" + item + L"_");
+ String const& post (post_name (t));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ // item
+ //
+ String const& arg (arg_type (t));
+
+ os << "void " << name << "::" << endl
+ << item;
+
+ if (arg == L"void")
+ os << " ()";
+ else
+ os << " (" << arg << (tiein ? " x" : "") << ")";
+
+ os << "{";
+
+ if (tiein)
+ {
+ String const& impl (etiein (l));
+
+ os << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->" << item << " (" <<
+ (arg != L"void" ? "x" : "") << ");";
+ }
+
+ os << "}";
+
+ // post
+ //
+ if (ret_type (l) == L"void")
+ {
+ String const& post (post_name (l));
+
+ os << "void " << name << "::" << endl
+ << post << " ()"
+ << "{";
+
+ if (tiein)
+ {
+ String const& impl (etiein (l));
+
+ os << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->" << post << " ();";
+ }
+
+ os << "}";
+ }
+
+ // reset
+ //
+ if (reset)
+ {
+ os << "void " << name << "::" << endl
+ << "_reset ()"
+ << "{"
+ << list_base << "::_reset ();"
+ << endl
+ << "if (this->" << inst << ")" << endl
+ << "this->" << inst << "->_reset ();"
+ << "}";
+ }
+
+ // parse_item
+ //
+ os << "void " << name << "::" << endl
+ << "_xsde_parse_item (const " << string_type << "& v)"
+ << "{"
+ << "if (this->" << inst << ")"
+ << "{"
+ << "::xsde::cxx::parser::context& ctx = this->_context ();"
+ << endl;
+
+ // This implementation should work for both validating
+ // and non-validating cases.
+ //
+ if (!exceptions || validation)
+ {
+ String const& ret (ret_type (t));
+
+ os << "this->" << inst << "->pre ();";
+
+ if (!exceptions)
+ os << endl
+ << "if (this->" << inst << "->_error_type ())" << endl
+ << "this->" << inst << "->_copy_error (ctx);"
+ << "else" << endl;
+
+ os << "this->" << inst << "->_pre_impl (ctx);"
+ << endl
+ << "if (!ctx.error_type ())" << endl
+ << "this->" << inst << "->_characters (v);"
+ << endl
+ << "if (!ctx.error_type ())" << endl
+ << "this->" << inst << "->_post_impl ();"
+ << endl
+ << "if (!ctx.error_type ())" << endl;
+
+ if (ret == L"void")
+ os << "this->" << inst << "->" << post << " ();"
+ << endl;
+ else
+ os << "{"
+ << arg_type (t) << " tmp = this->" << inst << "->" <<
+ post << " ();"
+ << endl;
+
+ if (!exceptions)
+ os << "if (this->" << inst << "->_error_type ())" << endl
+ << "this->" << inst << "->_copy_error (ctx);"
+ << "else" << endl;
+
+ if (ret == L"void")
+ os << "this->" << item << " ();";
+ else
+ os << "this->" << item << " (tmp);"
+ << "}";
+ }
+ else
+ {
+ os << "this->" << inst << "->pre ();"
+ << "this->" << inst << "->_pre_impl (ctx);"
+ << "this->" << inst << "->_characters (v);"
+ << "this->" << inst << "->_post_impl ();";
+
+ if (ret_type (t) == L"void")
+ os << "this->" << inst << "->" << post << " ();"
+ << "this->" << item << " ();";
+ else
+ os << "this->" << item << " (this->" << inst << "->" <<
+ post << " ());";
+ }
+
+ os << "}"
+ << "}";
+
+ //
+ //
+ if (poly_code)
+ {
+ String id (l.name ());
+
+ if (String ns = xml_ns_name (l))
+ {
+ id += L' ';
+ id += ns;
+ }
+
+ os << "const char* " << name << "::" << endl
+ << "_static_type ()"
+ << "{"
+ << "return " << strlit (id) << ";"
+ << "}";
+
+ os << "const char* " << name << "::" << endl
+ << "_dynamic_type () const"
+ << "{"
+ << "return _static_type ();"
+ << "}";
+ }
+ }
+ };
+
+
+ //
+ //
+ struct Union: Traversal::Union, Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ String const& name (ename (u));
+ String const& ret (ret_type (u));
+
+ if (ret == L"void" || poly_code)
+ {
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+ }
+
+ if (ret == L"void")
+ {
+ String const& post (post_name (u));
+
+ os << "void " << name << "::" << endl
+ << post << " ()"
+ << "{";
+
+ if (tiein)
+ {
+ String const& impl (etiein (u));
+
+ os << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->" << post << " ();";
+ }
+
+ os << "}";
+ }
+
+ if (poly_code)
+ {
+ String id (u.name ());
+
+ if (String ns = xml_ns_name (u))
+ {
+ id += L' ';
+ id += ns;
+ }
+
+ os << "const char* " << name << "::" << endl
+ << "_static_type ()"
+ << "{"
+ << "return " << strlit (id) << ";"
+ << "}";
+
+ os << "const char* " << name << "::" << endl
+ << "_dynamic_type () const"
+ << "{"
+ << "return _static_type ();"
+ << "}";
+ }
+ }
+ };
+
+ //
+ //
+ struct ParticleReset: Traversal::Element, Context
+ {
+ ParticleReset (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ String const& m (emember (e));
+
+ os << "if (this->" << m << ")" << endl
+ << "this->" << m << "->_reset ();"
+ << endl;
+
+ if (poly_code && !anonymous (e.type ()))
+ {
+ String const& map (emember_map (e));
+
+ os << "if (this->" << map << ")" << endl
+ << "this->" << map << "->reset ();"
+ << endl;
+ }
+ }
+ };
+
+ struct AttributeReset: Traversal::Attribute, Context
+ {
+ AttributeReset (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ String const& m (emember (a));
+
+ os << "if (this->" << m << ")" << endl
+ << "this->" << m << "->_reset ();"
+ << endl;
+ }
+ };
+
+ //
+ //
+ struct StartElement : Traversal::Element, Context
+ {
+ StartElement (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ Boolean poly (poly_code && !anonymous (e.type ()));
+ Boolean subst (poly && e.global ());
+ String const& inst (poly ? emember_cache (e) : emember (e));
+
+ if (e.qualified () && e.namespace_ ().name ())
+ {
+ os << "if (" << (subst ? "(" : "") <<
+ "n == " << strlit (e.name ()) << " &&" << endl
+ << "ns == " << strlit (e.namespace_ ().name ());
+ }
+ else
+ {
+ os << "if (" << (subst ? "(" : "") <<
+ "n == " << L << strlit (e.name ()) << " && ns.empty ()";
+ }
+
+ // Only a globally-defined element can be a subst-group root.
+ //
+ if (subst)
+ {
+ String root_id (e.name ());
+
+ if (String const& ns = e.namespace_ ().name ())
+ {
+ root_id += L' ';
+ root_id += ns;
+ }
+
+ os << ") ||" << endl
+ << "::xsde::cxx::parser::substitution_map_instance ()" <<
+ ".check (" << endl
+ << "ns, n, " << strlit (root_id) << ", t)";
+ }
+
+ os << ")"
+ << "{";
+
+ if (poly)
+ {
+ // In case of mixin we use virtual inheritance and only
+ // dynamic_cast can be used.
+ //
+ String cast (mixin ? L"dynamic_cast" : L"static_cast");
+ String fq_type (fq_name (e.type ()));
+ String const& member (emember (e));
+ String const& member_map (emember_map (e));
+
+ os << "if (t == 0 && this->" << member << " != 0)" << endl
+ << "this->" << inst << " = this->" << member << ";"
+ << "else"
+ << "{"
+ << "const char* ts = " << fq_type << "::_static_type ();"
+ << endl
+ << "if (t == 0)" << endl
+ << "t = ts;"
+ << endl
+ << "if (this->" << member << " != 0 && " <<
+ "strcmp (t, ts) == 0)" << endl
+ << "this->" << inst << " = this->" << member << ";"
+ << "else if (this->" << member_map << " != 0)" << endl
+ << "this->" << inst << " = " << cast << "< " << fq_type <<
+ "* > (" << endl
+ << "this->" << member_map << "->find (t));"
+ << "else" << endl
+ << "this->" << inst << " = 0;"
+ << "}";
+ }
+
+ os << "if (this->" << inst << ")"
+ << "{";
+
+ if (exceptions)
+ {
+ os << "this->" << inst << "->pre ();"
+ << "this->" << inst << "->_pre_impl (ctx);";
+ }
+ else
+ {
+ // Note that after pre() we need to check both parser and
+ // context error states because of the recursive parsing.
+ //
+ os << "this->" << inst << "->pre ();"
+ << endl
+ << "if (this->" << inst << "->_error_type ())" << endl
+ << "this->" << inst << "->_copy_error (ctx);"
+ << endl
+ << "if (!ctx.error_type ())" << endl
+ << "this->" << inst << "->_pre_impl (ctx);";
+ }
+
+ os << "}"
+ << "else" << endl
+ << "ctx.current_.depth_++;" // Ignoring document fragment.
+ << endl
+ << "return true;"
+ << "}";
+ }
+ };
+
+
+ //
+ //
+ struct EndElement : Traversal::Element, Context
+ {
+ EndElement (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ String const& name (ename (e));
+ Boolean poly (poly_code && !anonymous (e.type ()));
+ Boolean subst (poly && e.global ());
+ String const& inst (poly ? emember_cache (e) : emember (e));
+
+ if (e.qualified () && e.namespace_ ().name ())
+ {
+ os << "if (" << (subst ? "(" : "") <<
+ "n == " << strlit (e.name ()) << " &&" << endl
+ << "ns == " << strlit (e.namespace_ ().name ());
+ }
+ else
+ {
+ os << "if (" << (subst ? "(" : "") <<
+ "n == " << strlit (e.name ()) << " && ns.empty ()";
+ }
+
+ // Only a globally-defined element can be a subst-group root.
+ //
+ if (subst)
+ {
+ String root_id (e.name ());
+
+ if (String const& ns = e.namespace_ ().name ())
+ {
+ root_id += L' ';
+ root_id += ns;
+ }
+
+ os << ") ||" << endl
+ << "::xsde::cxx::parser::substitution_map_instance ()" <<
+ ".check (" << endl
+ << "ns, n, " << strlit (root_id) << ")";
+ }
+
+ os << ")"
+ << "{";
+
+ SemanticGraph::Type& type (e.type ());
+ String const& post (post_name (type));
+
+ os << "if (this->" << inst << ")"
+ << "{";
+
+ if (exceptions)
+ {
+ if (ret_type (type) == L"void")
+ os << "this->" << inst << "->" << post << " ();"
+ << "this->" << name << " ();";
+ else
+ os << "this->" << name << " (this->" << inst << "->" <<
+ post << " ());";
+ }
+ else
+ {
+ // Note that after post() we need to check both parser and
+ // context error states because of the recursive parsing.
+ //
+ if (ret_type (type) == L"void")
+ {
+ os << "this->" << inst << "->" << post << " ();"
+ << endl
+ << "if (this->" << inst << "->_error_type ())" << endl
+ << "this->" << inst << "->_copy_error (ctx);"
+ << endl
+ << "if (!ctx.error_type ())" << endl
+ << "this->" << name << " ();";
+ }
+ else
+ {
+ os << arg_type (type) << " tmp = this->" << inst << "->" <<
+ post << " ();"
+ << endl
+ << "if (this->" << inst << "->_error_type ())" << endl
+ << "this->" << inst << "->_copy_error (ctx);"
+ << endl
+ << "if (!ctx.error_type ())" << endl
+ << "this->" << name << " (tmp);";
+ }
+ }
+
+ os << "}"
+ << "return true;"
+ << "}";
+ }
+ };
+
+
+ //
+ //
+ struct Attribute : Traversal::Attribute, Context
+ {
+ Attribute (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ String const& name (ename (a));
+ String const& inst (emember (a));
+
+ if (a.qualified () && a.namespace_ ().name ())
+ {
+ os << "if (n == " << L << strlit (a.name ()) << " &&" << endl
+ << "ns == " << L << strlit (a.namespace_ ().name ()) << ")"
+ << "{";
+ }
+ else
+ {
+ os << "if (n == " << L << strlit (a.name ()) << " && ns.empty ())"
+ << "{";
+ }
+
+ SemanticGraph::Type& type (a.type ());
+ String const& post (post_name (type));
+ String const& ret (ret_type (type));
+
+ os << "if (this->" << inst << ")"
+ << "{";
+
+ if (exceptions)
+ {
+ os << "this->" << inst << "->pre ();"
+ << "this->" << inst << "->_pre_impl (ctx);"
+ << "this->" << inst << "->_characters (v);"
+ << "this->" << inst << "->_post_impl ();";
+
+ if (ret == L"void")
+ os << "this->" << inst << "->" << post << " ();"
+ << "this->" << name << " ();";
+ else
+ os << "this->" << name << " (this->" << inst << "->" <<
+ post << " ());";
+ }
+ else
+ {
+ os << "this->" << inst << "->pre ();"
+ << endl
+ << "if (!this->" << inst << "->_error_type ())" << endl
+ << "this->" << inst << "->_pre_impl (ctx);"
+ << "else" << endl
+ << "this->" << inst << "->_copy_error (ctx);"
+ << endl
+ << "if (!ctx.error_type ())" << endl
+ << "this->" << inst << "->_characters (v);"
+ << endl
+ << "if (!ctx.error_type ())" << endl
+ << "this->" << inst << "->_post_impl ();"
+ << endl
+ << "if (!ctx.error_type ())" << endl;
+
+ if (ret == L"void")
+ os << "this->" << inst << "->" << post << " ();"
+ << endl;
+ else
+ os << "{"
+ << arg_type (type) << " tmp = this->" << inst << "->" <<
+ post << " ();"
+ << endl;
+
+ os << "if (this->" << inst << "->_error_type ())" << endl
+ << "this->" << inst << "->_copy_error (ctx);"
+ << "else" << endl;
+
+ if (ret == L"void")
+ os << "this->" << name << " ();";
+ else
+ os << "this->" << name << " (tmp);"
+ << "}";
+ }
+
+ os << "}"
+ << "return true;"
+ << "}";
+ }
+ };
+
+ //
+ // Callbacks.
+ //
+
+ struct CompositorCallback: Traversal::All,
+ Traversal::Choice,
+ Traversal::Sequence,
+ Context
+ {
+ CompositorCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ if (correspondent (a) == 0)
+ {
+ // For the all compositor, maxOccurs=1 and minOccurs={0,1}.
+ //
+ if (a.min () == 0)
+ {
+ SemanticGraph::Scope& s (scope (a));
+ String const& present (epresent (a));
+
+ os << "void " << ename (s) << "::" << endl
+ << present << " ()"
+ << "{";
+
+ if (tiein)
+ {
+ String const& impl (
+ etiein (dynamic_cast<SemanticGraph::Type&> (s)));
+
+ os << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->" << present << " ();";
+ }
+
+ os << "}";
+ }
+ }
+
+ Traversal::All::traverse (a);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ if (c.contains_begin () == c.contains_end ())
+ return;
+
+ if (correspondent (c) == 0)
+ {
+ SemanticGraph::Scope& s (scope (c));
+ String const& arm (earm (c));
+
+ os << "void " << ename (s) << "::" << endl
+ << arm << " (" << earm_tag (c) << (tiein ? " x" : "") << ")"
+ << "{";
+
+ if (tiein)
+ {
+ String const& impl (
+ etiein (dynamic_cast<SemanticGraph::Type&> (s)));
+
+ os << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->" << arm << " (x);";
+ }
+
+ os << "}";
+
+ }
+
+ Traversal::Choice::traverse (c);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ // Root compositor that models inheritance by extension
+ // may not have an association so we may fall through
+ // in to the 'if' case even though this is a restriction.
+ // This is ok since such a compositor always has max ==
+ // min == 1 and so nothing is generated.
+ //
+ if (SemanticGraph::Compositor* b = correspondent (s))
+ {
+ // Add the *_present callback if this is a restriction
+ // of sequence to optional.
+ //
+ if (b->max () != 1 && s.min () == 0)
+ {
+ SemanticGraph::Scope& ss (scope (s));
+
+ os << "void " << ename (ss) << "::" << endl
+ << epresent (s) << " ()"
+ << "{";
+
+ if (tiein)
+ {
+ String const& impl (
+ etiein (dynamic_cast<SemanticGraph::Type&> (ss)));
+
+ os << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->" << enext (s) << " ();";
+ }
+ else
+ os << "this->" << enext (s) << " ();";
+
+ os << "}";
+ }
+ }
+ else
+ {
+ if (s.max () != 1)
+ {
+ SemanticGraph::Scope& ss (scope (s));
+ String const& next (enext (s));
+
+ os << "void " << ename (ss) << "::" << endl
+ << next << " ()"
+ << "{";
+
+ if (tiein)
+ {
+ String const& impl (
+ etiein (dynamic_cast<SemanticGraph::Type&> (ss)));
+
+ os << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->" << next << " ();";
+ }
+
+ os << "}";
+ }
+ else if (s.min () == 0)
+ {
+ SemanticGraph::Scope& ss (scope (s));
+ String const& present (epresent (s));
+
+ os << "void " << ename (ss) << "::" << endl
+ << present << " ()"
+ << "{";
+
+ if (tiein)
+ {
+ String const& impl (
+ etiein (dynamic_cast<SemanticGraph::Type&> (ss)));
+
+ os << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->" << present << " ();";
+ }
+
+ os << "}";
+ }
+ }
+
+ Traversal::Sequence::traverse (s);
+ }
+
+ private:
+ SemanticGraph::Scope&
+ scope (SemanticGraph::Compositor& c)
+ {
+ SemanticGraph::Compositor* root (&c);
+
+ while (root->contained_particle_p ())
+ root = &root->contained_particle ().compositor ();
+
+ return dynamic_cast<SemanticGraph::Scope&> (
+ root->contained_compositor ().container ());
+ }
+ };
+
+ struct ParticleCallback: Traversal::Element, Context
+ {
+ ParticleCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (correspondent (e) == 0)
+ {
+ String const& name (ename (e));
+ String const& arg (arg_type (e.type ()));
+
+ os << "void " << ename (e.scope ()) << "::" << endl
+ << name;
+
+ if (arg == L"void")
+ os << " ()";
+ else
+ os << " (" << arg << (tiein ? " x" : "") << ")";
+
+ os << "{";
+
+ if (tiein)
+ {
+ String const& impl (
+ etiein (dynamic_cast<SemanticGraph::Type&> (e.scope ())));
+
+ os << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->" << name << " (" <<
+ (arg != L"void" ? "x" : "") << ");";
+ }
+
+ os << "}";
+ }
+ }
+ };
+
+ struct AttributeCallback: Traversal::Attribute, Context
+ {
+ AttributeCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ String const& name (ename (a));
+ String const& arg (arg_type (a.type ()));
+
+ os << "void " << ename (a.scope ()) << "::" << endl
+ << name;
+
+ if (arg == L"void")
+ os << " ()";
+ else
+ os << " (" << arg << (tiein ? " x" : "") << ")";
+
+ os << "{";
+
+ if (tiein)
+ {
+ String const& impl (
+ etiein (dynamic_cast<SemanticGraph::Type&> (a.scope ())));
+
+ os << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->" << name << " (" <<
+ (arg != L"void" ? "x" : "") << ");";
+ }
+
+ os << "}";
+ }
+ };
+
+ //
+ //
+ struct Complex : Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c),
+ compositor_callback_val_ (c),
+ particle_callback_ (c),
+ attribute_callback_ (c),
+ particle_reset_ (c),
+ attribute_reset_ (c),
+ start_element_ (c),
+ end_element_ (c),
+ attribute_ (c)
+ {
+ // Callback.
+ //
+ if (validation)
+ {
+ contains_compositor_callback_ >> compositor_callback_val_;
+ compositor_callback_val_ >> contains_particle_callback_;
+ contains_particle_callback_ >> compositor_callback_val_;
+ }
+ else
+ {
+ contains_compositor_callback_ >> compositor_callback_non_val_;
+ compositor_callback_non_val_ >> contains_particle_callback_;
+ contains_particle_callback_ >> compositor_callback_non_val_;
+ }
+
+ contains_particle_callback_ >> particle_callback_;
+
+ names_attribute_callback_ >> attribute_callback_;
+
+ // Reset.
+ //
+ contains_compositor_reset_ >> compositor_reset_;
+ compositor_reset_ >> contains_particle_reset_;
+ contains_particle_reset_ >> compositor_reset_;
+ contains_particle_reset_ >> particle_reset_;
+
+ names_attribute_reset_ >> attribute_reset_;
+
+ //
+ //
+ contains_compositor_start_ >> start_compositor_;
+ start_compositor_ >> contains_particle_start_;
+ contains_particle_start_ >> start_compositor_;
+ contains_particle_start_ >> start_element_;
+
+ //
+ //
+ contains_compositor_end_ >> end_compositor_;
+ end_compositor_ >> contains_particle_end_;
+ contains_particle_end_ >> end_compositor_;
+ contains_particle_end_ >> end_element_;
+
+ //
+ //
+ names_attribute_ >> attribute_;
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ Boolean hb (c.inherits_p ());
+ Boolean restriction (restriction_p (c));
+ Boolean he (has<Traversal::Element> (c));
+ Boolean ha (has<Traversal::Attribute> (c));
+
+ Boolean hae (has_particle<Traversal::Any> (c));
+
+ Boolean hra (false); // Has required attribute.
+ if (ha)
+ {
+ RequiredAttributeTest test (hra);
+ Traversal::Names names_test (test);
+ names (c, names_test);
+ }
+
+ String const& name (ename (c));
+ String const& ret (ret_type (c));
+ Boolean same (hb && ret == ret_type (c.inherits ().base ()));
+
+ String base_ret;
+ Boolean base_same (true);
+
+ if (tiein && hb)
+ {
+ SemanticGraph::Type& base (c.inherits ().base ());
+
+ base_ret = ret_type (base);
+ base_same = base.inherits_p () &&
+ base_ret == ret_type (base.inherits ().base ());
+ }
+
+ if (he || ha || same || ret == L"void" || poly_code ||
+ (tiein && !(base_same || base_ret == L"void")))
+ {
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+ }
+
+ // Member callbacks.
+ //
+ if (!restriction)
+ {
+ if (ha)
+ names (c, names_attribute_callback_);
+ }
+
+ if (!restriction || validation)
+ {
+ if (he || hae)
+ contains_compositor (c, contains_compositor_callback_);
+ }
+
+ // post
+ //
+ if (same || ret == L"void")
+ {
+ String const& post (post_name (c));
+
+ os << ret << " " << name << "::" << endl
+ << post << " ()"
+ << "{";
+
+ if (tiein)
+ {
+ String const& impl (etiein (c));
+
+ os << "if (this->" << impl << ")" << endl
+ << (ret != L"void" ? "return " : "") << "this->" <<
+ impl << "->" << post << " ();";
+ }
+
+ if (same)
+ {
+ if (tiein)
+ os << "else" << endl;
+
+ SemanticGraph::Type& base (c.inherits ().base ());
+
+ if (ret == L"void")
+ os << post_name (base) << " ();";
+ else
+ os << "return " << post_name (base) << " ();";
+ }
+
+ os << "}";
+ }
+
+ // reset
+ //
+ if (!restriction && (he || ha) && reset)
+ {
+ os << "void " << name << "::" << endl
+ << "_reset ()"
+ << "{";
+
+ // Avoid recursion in case of recursive parsing.
+ //
+ if (he)
+ os << "if (this->resetting_)" << endl
+ << "return;"
+ << endl;
+
+ // Reset the base. We cannot use the fully-qualified base name
+ // directly because of some broken compilers (EVC 4.0).
+ //
+ String base (unclash (name, "base"));
+
+ os << "typedef ";
+
+ if (hb)
+ os << fq_name (c.inherits ().base ());
+ else
+ os << complex_base;
+
+ os << " " << base << ";"
+ << base << "::_reset ();"
+ << endl;
+
+ // Reset validation state.
+ //
+ if (validation)
+ {
+ if (he || hae)
+ {
+ os << "this->v_state_stack_.clear ();"
+ << endl;
+
+ SemanticGraph::Compositor& comp (
+ c.contains_compositor ().compositor ());
+
+ if (comp.is_a<SemanticGraph::All> () &&
+ comp.context().count ("p:comp-number"))
+ {
+ os << "this->v_all_count_.clear ();"
+ << endl;
+ }
+ }
+
+ if (hra)
+ os << "this->v_state_attr_stack_.clear ();"
+ << endl;
+ }
+
+ // Reset member parsers.
+ //
+
+ if (ha)
+ names (c, names_attribute_reset_);
+
+ if (he)
+ {
+ os << "this->resetting_ = true;"
+ << endl;
+
+ contains_compositor (c, contains_compositor_reset_);
+
+ os << "this->resetting_ = false;"
+ << endl;
+ }
+
+ os << "}";
+ }
+
+ //
+ //
+ if (poly_code)
+ {
+ String id (c.name ());
+
+ if (String ns = xml_ns_name (c))
+ {
+ id += L' ';
+ id += ns;
+ }
+
+ os << "const char* " << name << "::" << endl
+ << "_static_type ()"
+ << "{"
+ << "return " << strlit (id) << ";"
+ << "}";
+
+ os << "const char* " << name << "::" << endl
+ << "_dynamic_type () const"
+ << "{"
+ << "return _static_type ();"
+ << "}";
+
+ if (hb && validation)
+ {
+ Boolean gen (!anonymous (c));
+
+ // We normally don't need to enter anonymous types into
+ // the inheritance map. The only exception is when an
+ // anonymous types is defined inside an element that
+ // is a member of a substitution group.
+ //
+ if (!gen)
+ {
+ // The first instance that this anonymous type classifies
+ // is the prototype for others if any.
+ //
+ SemanticGraph::Instance& i (
+ c.classifies_begin ()->instance ());
+
+ if (SemanticGraph::Element* e =
+ dynamic_cast<SemanticGraph::Element*> (&i))
+ {
+ if (e->substitutes_p ())
+ gen = true;
+ }
+ }
+
+ if (gen)
+ {
+ SemanticGraph::Type& base (c.inherits ().base ());
+
+ os << "static" << endl
+ << "const ::xsde::cxx::parser::validating::" <<
+ "inheritance_map_entry" << endl
+ << "_xsde_" << name << "_inheritance_map_entry_ (" << endl
+ << name << "::_static_type ()," << endl
+ << fq_name (base) << "::_static_type ());"
+ << endl;
+ }
+ }
+ }
+
+ // Base post
+ //
+ if (tiein && !(base_same || base_ret == L"void"))
+ {
+ SemanticGraph::Type& base (c.inherits ().base ());
+
+ String const& impl (etiein (base));
+ String const& base_post (post_name (base));
+
+ os << base_ret << " " << name << "::" << endl
+ << base_post << " ()"
+ << "{"
+ << "assert (this->" << impl << ");"
+ << "return this->" << impl << "->" << base_post << " ();"
+ << "}";
+ }
+
+ // The rest is parsing/validation code which is generated in
+ // *-validation-source.cxx.
+ //
+ if (validation)
+ return;
+
+ // Don't use the restriction_p result from here since we don't
+ // want special treatment of anyType.
+ //
+ restriction = hb && c.inherits ().is_a<SemanticGraph::Restricts> ();
+
+ // _start_element_impl & _end_element_impl
+ //
+ if (he)
+ {
+ // _start_element_impl
+ //
+
+ os << "bool " << name << "::" << endl
+ << "_start_element_impl (const " << string_type << "& ns," << endl
+ << "const " << string_type << "& n";
+
+ if (poly_runtime)
+ os << "," << endl
+ << "const char*" << (poly_code ? " t" : "");
+
+ os << ")"
+ << "{";
+
+ if (poly_code)
+ os << "XSDE_UNUSED (t);"
+ << endl;
+
+ if (!restriction)
+ {
+ // We cannot use the fully-qualified base name directly
+ // because of some broken compilers (EVC 4.0).
+ //
+ String base (unclash (name, "base"));
+
+ os << "typedef ";
+
+ if (hb)
+ os << fq_name (c.inherits ().base ());
+ else
+ os << complex_base;
+
+ os << " " << base << ";"
+ << "if (" << base << "::";
+
+ if (poly_runtime)
+ os << "_start_element_impl (ns, n, " <<
+ (poly_code ? "t" : "0") << "))" << endl;
+ else
+ os << "_start_element_impl (ns, n))" << endl;
+
+ os << "return true;"
+ << endl;
+ }
+
+ os << "::xsde::cxx::parser::context& ctx = this->_context ();"
+ << endl;
+
+ contains_compositor (c, contains_compositor_start_);
+
+ os << "return false;"
+ << "}";
+
+
+ // _end_element_impl
+ //
+ os << "bool " << name << "::" << endl
+ << "_end_element_impl (const " << string_type << "& ns," << endl
+ << "const " << string_type << "& n)"
+ << "{";
+
+
+ if (!restriction)
+ {
+ // We cannot use the fully-qualified base name directly
+ // because of some broken compilers (EVC 4.0).
+ //
+ String base (unclash (name, "base"));
+
+ os << "typedef ";
+
+ if (hb)
+ os << fq_name (c.inherits ().base ());
+ else
+ os << complex_base;
+
+ os << " " << base << ";"
+ << "if (" << base << "::_end_element_impl (ns, n))" << endl
+ << "return true;"
+ << endl;
+ }
+
+ if (!exceptions)
+ os << "::xsde::cxx::parser::context& ctx = this->_context ();"
+ << endl;
+
+ contains_compositor (c, contains_compositor_end_);
+
+ os << "return false;"
+ << "}";
+ }
+
+
+ if (ha)
+ {
+ // _attribute_impl
+ //
+
+ os << "bool " << name << "::" << endl
+ << "_attribute_impl (const " << string_type << "& ns," << endl
+ << "const " << string_type << "& n," << endl
+ << "const " << string_type << "& v)"
+ << "{";
+
+ if (!restriction)
+ {
+ // We cannot use the fully-qualified base name directly
+ // because of some broken compilers (EVC 4.0).
+ //
+ String base (unclash (name, "base"));
+
+ os << "typedef ";
+
+ if (hb)
+ os << fq_name (c.inherits ().base ());
+ else
+ os << complex_base;
+
+ os << " " << base << ";"
+ << "if (" << base << "::_attribute_impl (ns, n, v))"
+ << "{"
+ << "return true;"
+ << "}";
+ }
+
+ os << "::xsde::cxx::parser::context& ctx = this->_context ();"
+ << endl;
+
+ names (c, names_attribute_);
+
+ os << "return false;"
+ << "}";
+ }
+ }
+
+ private:
+ //
+ //
+ CompositorCallback compositor_callback_val_;
+ Traversal::Compositor compositor_callback_non_val_;
+ ParticleCallback particle_callback_;
+ Traversal::ContainsCompositor contains_compositor_callback_;
+ Traversal::ContainsParticle contains_particle_callback_;
+
+ AttributeCallback attribute_callback_;
+ Traversal::Names names_attribute_callback_;
+
+ //
+ //
+ Traversal::Compositor compositor_reset_;
+ ParticleReset particle_reset_;
+ Traversal::ContainsCompositor contains_compositor_reset_;
+ Traversal::ContainsParticle contains_particle_reset_;
+
+ AttributeReset attribute_reset_;
+ Traversal::Names names_attribute_reset_;
+
+ //
+ //
+ Traversal::Compositor start_compositor_;
+ StartElement start_element_;
+ Traversal::ContainsCompositor contains_compositor_start_;
+ Traversal::ContainsParticle contains_particle_start_;
+
+ //
+ //
+ Traversal::Compositor end_compositor_;
+ EndElement end_element_;
+ Traversal::ContainsCompositor contains_compositor_end_;
+ Traversal::ContainsParticle contains_particle_end_;
+
+ //
+ //
+ Attribute attribute_;
+ Traversal::Names names_attribute_;
+ };
+
+ // Generate substitution group map entries.
+ //
+ struct GlobalElement: Traversal::Element, Context
+ {
+ GlobalElement (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (e.substitutes_p ())
+ {
+ String name (escape (e.name ()));
+ Type& r (e.substitutes ().root ());
+
+ SemanticGraph::Type& type (e.type ());
+
+ String m_id (e.name ());
+ String r_id (r.name ());
+
+ if (String const& ns = e.namespace_ ().name ())
+ {
+ m_id += L' ';
+ m_id += ns;
+ }
+
+ if (String const& ns = r.namespace_ ().name ())
+ {
+ r_id += L' ';
+ r_id += ns;
+ }
+
+ os << "// Substitution map entry for " << comment (e.name ()) <<
+ "." << endl
+ << "//" << endl
+ << "static" << endl
+ << "const ::xsde::cxx::parser::substitution_map_entry" << endl
+ << "_xsde_" << name << "_substitution_map_entry_ (" << endl
+ << strlit (m_id) << "," << endl
+ << strlit (r_id) << "," << endl
+ << fq_name (type) << "::_static_type ());"
+ << endl;
+ }
+ }
+ };
+ }
+
+ Void
+ generate_parser_source (Context& ctx)
+ {
+ if (ctx.tiein)
+ ctx.os << "#include <assert.h>" << endl
+ << endl;
+
+ if (ctx.poly_code)
+ {
+ ctx.os << "#include <string.h>" << endl
+ << "#include <xsde/cxx/parser/substitution-map.hxx>" << endl;
+
+ if (ctx.validation)
+ ctx.os << "#include <xsde/cxx/parser/validating/inheritance-map.hxx>" << endl
+ << endl;
+ else
+ ctx.os << endl;
+
+ ctx.os << "static" << endl
+ << "const ::xsde::cxx::parser::substitution_map_init" << endl
+ << "_xsde_substitution_map_init_;"
+ << endl;
+
+ if (ctx.validation)
+ {
+ ctx.os << "static" << endl
+ << "const ::xsde::cxx::parser::validating::" <<
+ "inheritance_map_init" << endl
+ << "_xsde_inheritance_map_init_;"
+ << endl;
+ }
+ }
+
+ // Emit "weak" header includes that are used in the file-per-type
+ // compilation model.
+ //
+ if (ctx.options.value<CLI::generate_inline> ())
+ {
+ 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);
+ Enumeration enumeration (ctx);
+ GlobalElement global_element (ctx);
+
+ names >> list;
+ names >> union_;
+ names >> complex;
+ names >> enumeration;
+
+ if (ctx.poly_code)
+ names >> global_element;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+}
diff --git a/xsde/cxx/parser/parser-source.hxx b/xsde/cxx/parser/parser-source.hxx
new file mode 100644
index 0000000..dcf07d6
--- /dev/null
+++ b/xsde/cxx/parser/parser-source.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/parser/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_PARSER_PARSER_SOURCE_HXX
+#define CXX_PARSER_PARSER_SOURCE_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/parser/elements.hxx>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ Void
+ generate_parser_source (Context&);
+ }
+}
+
+#endif // CXX_PARSER_PARSER_SOURCE_HXX
diff --git a/xsde/cxx/parser/print-impl-common.hxx b/xsde/cxx/parser/print-impl-common.hxx
new file mode 100644
index 0000000..1815bb7
--- /dev/null
+++ b/xsde/cxx/parser/print-impl-common.hxx
@@ -0,0 +1,1063 @@
+// file : xsde/cxx/parser/print-impl-common.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_PARSER_PRINT_IMPL_COMMON_HXX
+#define CXX_PARSER_PRINT_IMPL_COMMON_HXX
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cxx/parser/elements.hxx>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ struct PrintCall: Traversal::Type,
+
+ Traversal::Fundamental::Boolean,
+
+ 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::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,
+
+ Context
+ {
+ PrintCall (Context& c, String const& tag, String const& arg)
+ : Context (c), tag_ (tag), arg_ (arg)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type&)
+ {
+ gen_user_type ();
+ }
+
+ // Boolean.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Boolean& t)
+ {
+ if (default_type (t, "bool"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": %u\n") << ", " <<
+ arg_ << ");";
+ else
+ os << "std::cout << " << strlit (tag_ + L": ") << " << " <<
+ arg_ << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ // Integral types.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Byte& t)
+ {
+ if (default_type (t, "signed char"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": %d\n") << ", " <<
+ arg_ << ");";
+ else
+ os << "std::cout << " << strlit (tag_ + L": ") << " << " <<
+ "static_cast<short> (" << arg_ << ") << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedByte& t)
+ {
+ if (default_type (t, "unsigned char"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": %u\n") << ", " <<
+ arg_ << ");";
+ else
+ os << "std::cout << " << strlit (tag_ + L": ") << " << " <<
+ "static_cast<unsigned short> (" << arg_ << ") << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Short& t)
+ {
+ if (default_type (t, "short"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": %d\n") << ", " <<
+ arg_ << ");";
+ else
+ os << "std::cout << " << strlit (tag_ + L": ") << " << " <<
+ arg_ << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedShort& t)
+ {
+ if (default_type (t, "unsigned short"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": %u\n") << ", " <<
+ arg_ << ");";
+ else
+ os << "std::cout << " << strlit (tag_ + L": ") << " << " <<
+ arg_ << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Int& t)
+ {
+ if (default_type (t, "int"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": %d\n") << ", " <<
+ arg_ << ");";
+ else
+ os << "std::cout << " << strlit (tag_ + L": ") << " << " <<
+ arg_ << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedInt& t)
+ {
+ if (default_type (t, "unsigned int"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": %u\n") << ", " <<
+ arg_ << ");";
+ else
+ os << "std::cout << " << strlit (tag_ + L": ") << " << " <<
+ arg_ << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Long& t)
+ {
+ if (options.value<CLI::no_long_long> ())
+ {
+ if (default_type (t, "long"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": %ld\n") << ", " <<
+ arg_ << ");";
+ else
+ os << "std::cout << " << strlit (tag_ + L": ") << " << " <<
+ arg_ << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+ else
+ {
+ if (default_type (t, "long long"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": %lld\n") << ", " <<
+ arg_ << ");";
+ else
+ os << "std::cout << " << strlit (tag_ + L": ") << " << " <<
+ arg_ << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedLong& t)
+ {
+ if (options.value<CLI::no_long_long> ())
+ {
+ if (default_type (t, "unsigned long"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": %lu\n") << ", " <<
+ arg_ << ");";
+ else
+ os << "std::cout << " << strlit (tag_ + L": ") << " << " <<
+ arg_ << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+ else
+ {
+ if (default_type (t, "unsigned long long"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": %llu\n") << ", " <<
+ arg_ << ");";
+ else
+ os << "std::cout << " << strlit (tag_ + L": ") << " << " <<
+ arg_ << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Integer& t)
+ {
+ if (default_type (t, "long"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": %ld\n") << ", " <<
+ arg_ << ");";
+ else
+ os << "std::cout << " << strlit (tag_ + L": ") << " << " <<
+ arg_ << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NegativeInteger& t)
+ {
+ if (default_type (t, "long"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": %ld\n") << ", " <<
+ arg_ << ");";
+ else
+ os << "std::cout << " << strlit (tag_ + L": ") << " << " <<
+ arg_ << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonPositiveInteger& t)
+ {
+ if (default_type (t, "long"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": %ld\n") << ", " <<
+ arg_ << ");";
+ else
+ os << "std::cout << " << strlit (tag_ + L": ") << " << " <<
+ arg_ << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::PositiveInteger& t)
+ {
+ if (default_type (t, "unsigned long"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": %lu\n") << ", " <<
+ arg_ << ");";
+ else
+ os << "std::cout << " << strlit (tag_ + L": ") << " << " <<
+ arg_ << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonNegativeInteger& t)
+ {
+ if (default_type (t, "unsigned long"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": %lu\n") << ", " <<
+ arg_ << ");";
+ else
+ os << "std::cout << " << strlit (tag_ + L": ") << " << " <<
+ arg_ << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ // Floats.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Float& t)
+ {
+ if (default_type (t, "float"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": %g\n") << ", " <<
+ arg_ << ");";
+ else
+ os << "std::cout << " << strlit (tag_ + L": ") << " << " <<
+ arg_ << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Double& t)
+ {
+ if (default_type (t, "double"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": %g\n") << ", " <<
+ arg_ << ");";
+ else
+ os << "std::cout << " << strlit (tag_ + L": ") << " << " <<
+ arg_ << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Decimal& t)
+ {
+ if (default_type (t, "double"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": %g\n") << ", " <<
+ arg_ << ");";
+ else
+ os << "std::cout << " << strlit (tag_ + L": ") << " << " <<
+ arg_ << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ // Strings.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::String& t)
+ {
+ gen_string (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NormalizedString& t)
+ {
+ gen_string (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Token& t)
+ {
+ gen_string (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameToken& t)
+ {
+ gen_string (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Name& t)
+ {
+ gen_string (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NCName& t)
+ {
+ gen_string (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Language& t)
+ {
+ gen_string (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Id& t)
+ {
+ gen_string (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRef& t)
+ {
+ gen_string (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::AnyURI& t)
+ {
+ gen_string (t);
+ }
+
+ // String sequences.
+ //
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameTokens& t)
+ {
+ gen_sequence (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRefs& t)
+ {
+ gen_sequence (t);
+ }
+
+ // QName
+ //
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::QName& t)
+ {
+ if (options.value<CLI::no_stl> ())
+ {
+ if (default_type (t, xs_ns_name () + L"::qname*"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "if (" << arg_ << "->prefix ()[0] == '\\0')" << endl
+ << "printf (" << strlit (tag_ + L": %s\n") << ", " <<
+ arg_ << "->name ());"
+ << "else" << endl
+ << "printf (" << strlit (tag_ + L": %s:%s\n") << "," << endl
+ << arg_ << "->prefix ()," << endl
+ << arg_ << "->name ());";
+ else
+ os << "if (" << arg_ << "->prefix ()[0] == '\\0')" << endl
+ << "std::cout << " << strlit (tag_ + L": ") << " << " <<
+ arg_ << "->name () << std::endl;"
+ << "else" << endl
+ << "std::cout << " << strlit (tag_ + L": ") << " << " <<
+ arg_ << "->prefix ()" << endl
+ << " << ':' << " << arg_ << "->name () << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+ else
+ {
+ if (default_type (t, xs_ns_name () + L"::qname"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "if (" << arg_ << ".prefix ().empty ())" << endl
+ << "printf (" << strlit (tag_ + L": %s\n") << ", " <<
+ arg_ << ".name ().c_str ());"
+ << "else" << endl
+ << "printf (" << strlit (tag_ + L": %s:%s\n") << "," << endl
+ << arg_ << ".prefix ().c_str ()," << endl
+ << arg_ << ".name ().c_str ());";
+ else
+ os << "if (" << arg_ << ".prefix ().empty ())" << endl
+ << "std::cout << " << strlit (tag_ + L": ") << " << " <<
+ arg_ << ".name () << std::endl;"
+ << "else" << endl
+ << "std::cout << " << strlit (tag_ + L": ") << " << " <<
+ arg_ << ".prefix ()" << endl
+ << " << ':' << " << arg_ << ".name () << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+ }
+
+ // Binary.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Base64Binary& t)
+ {
+ gen_buffer (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::HexBinary& t)
+ {
+ gen_buffer (t);
+ }
+
+ // Date/time.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Date& t)
+ {
+ if (default_type (t, xs_ns_name () + L"::date"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": %d-%u-%u") << "," << endl
+ << arg_ << ".year ()," << endl
+ << arg_ << ".month ()," << endl
+ << arg_ << ".day ());" << endl;
+ else
+ os << "std::cout << " << strlit (tag_ + L": ") << endl
+ << " << " << arg_ << ".year () << '-'" << endl
+ << " << " << arg_ << ".month () << '-'" << endl
+ << " << " << arg_ << ".day ();";
+
+ gen_time_zone ();
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::DateTime& t)
+ {
+ if (default_type (t, xs_ns_name () + L"::date_time"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": %d-%u-%uT%u:%u:%g") <<
+ "," << endl
+ << arg_ << ".year ()," << endl
+ << arg_ << ".month ()," << endl
+ << arg_ << ".day ()," << endl
+ << arg_ << ".hours ()," << endl
+ << arg_ << ".minutes ()," << endl
+ << arg_ << ".seconds ());";
+ else
+ os << "std::cout << " << strlit (tag_ + L": ") << endl
+ << " << " << arg_ << ".year () << '-'" << endl
+ << " << " << arg_ << ".month () << '-'" << endl
+ << " << " << arg_ << ".day () << 'T'" << endl
+ << " << " << arg_ << ".hours () << ':'" << endl
+ << " << " << arg_ << ".minutes () << ':'" << endl
+ << " << " << arg_ << ".seconds ();";
+
+ gen_time_zone ();
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Duration& t)
+ {
+ if (default_type (t, xs_ns_name () + L"::duration"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": ") << ");"
+ << endl
+ << "if (" << arg_ << ".negative ())" << endl
+ << "printf (\"-\");"
+ << endl
+ << "printf (\"P%uY%uM%uDT%uH%uM%gS\\n\"," << endl
+ << arg_ << ".years ()," << endl
+ << arg_ << ".months ()," << endl
+ << arg_ << ".days ()," << endl
+ << arg_ << ".hours ()," << endl
+ << arg_ << ".minutes ()," << endl
+ << arg_ << ".seconds ());";
+ else
+ os << "std::cout << " << strlit (tag_ + L": ") << ";"
+ << endl
+ << "if (" << arg_ << ".negative ())" << endl
+ << "std::cout << '-';"
+ << endl
+ << "std::cout << 'P'" << endl
+ << " << " << arg_ << ".years () << 'Y'" << endl
+ << " << " << arg_ << ".months () << 'M'" << endl
+ << " << " << arg_ << ".days () << \"DT\"" << endl
+ << " << " << arg_ << ".hours () << 'H'" << endl
+ << " << " << arg_ << ".minutes () << 'M'" << endl
+ << " << " << arg_ << ".seconds () << 'S'"
+ << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Day& t)
+ {
+ if (default_type (t, xs_ns_name () + L"::gday"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": ---%u") << ", " <<
+ arg_ << ".day ());";
+ else
+ os << "std::cout << " << strlit (tag_ + L": ---") <<
+ " << " << arg_ << ".day ();";
+
+ gen_time_zone ();
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Month& t)
+ {
+ if (default_type (t, xs_ns_name () + L"::gmonth"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": --%u") << ", " <<
+ arg_ << ".month ());";
+ else
+ os << "std::cout << " << strlit (tag_ + L": --") <<
+ " << " << arg_ << ".month ();";
+
+ gen_time_zone ();
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::MonthDay& t)
+ {
+ if (default_type (t, xs_ns_name () + L"::gmonth_day"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": --%u-%u") << "," << endl
+ << arg_ << ".month ()," << endl
+ << arg_ << ".day ());";
+ else
+ os << "std::cout << " << strlit (tag_ + L": --") << endl
+ << " << " << arg_ << ".month () << '-'" << endl
+ << " << " << arg_ << ".day ();";
+
+ gen_time_zone ();
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Year& t)
+ {
+ if (default_type (t, xs_ns_name () + L"::gyear"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": %d") << ", " <<
+ arg_ << ".year ());";
+ else
+ os << "std::cout << " << strlit (tag_ + L": ") <<
+ " << " << arg_ << ".year ();";
+
+ gen_time_zone ();
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::YearMonth& t)
+ {
+ if (default_type (t, xs_ns_name () + L"::gyear_month"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": %d-%u") << "," << endl
+ << arg_ << ".year ()," << endl
+ << arg_ << ".month ());";
+ else
+ os << "std::cout << " << strlit (tag_ + L": ") << endl
+ << " << " << arg_ << ".year () << '-'" << endl
+ << " << " << arg_ << ".month ();";
+
+ gen_time_zone ();
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Time& t)
+ {
+ if (default_type (t, xs_ns_name () + L"::time"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": %u:%u:%g") << "," << endl
+ << arg_ << ".hours ()," << endl
+ << arg_ << ".minutes ()," << endl
+ << arg_ << ".seconds ());";
+ else
+ os << "std::cout << " << strlit (tag_ + L": ") << endl
+ << " << " << arg_ << ".hours () << ':'" << endl
+ << " << " << arg_ << ".minutes () << ':'" << endl
+ << " << " << arg_ << ".seconds ();";
+
+ gen_time_zone ();
+ }
+ else
+ gen_user_type ();
+ }
+
+ private:
+ bool
+ default_type (SemanticGraph::Type& t, String const& def_type)
+ {
+ return ret_type (t) == def_type;
+ }
+
+ void
+ gen_user_type ()
+ {
+ os << "// TODO" << endl
+ << "//" << endl;
+ }
+
+ void
+ gen_string (SemanticGraph::Type& t)
+ {
+ if (options.value<CLI::no_stl> ())
+ {
+ if (default_type (t, "char*"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": %s\n") << ", " <<
+ arg_ << ");";
+ else
+ os << "std::cout << " << strlit (tag_ + L": ") << " << " <<
+ arg_ << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+ else
+ {
+ if (default_type (t, "::std::string"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": %s\n") << ", " <<
+ arg_ << ".c_str ());";
+ else
+ os << "std::cout << " << strlit (tag_ + L": ") << " << " <<
+ arg_ << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+ }
+
+ void
+ gen_sequence (SemanticGraph::Type& t)
+ {
+ String type (xs_ns_name () + L"::string_sequence");
+
+ if (default_type (t, type + L"*"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": ") << ");"
+ << endl;
+ else
+ os << "std::cout << " << strlit (tag_ + L": ") << ";"
+ << endl;
+
+ os << "for (" << type << "::const_iterator i (" << arg_ <<
+ "->begin ()), e (" << arg_ << "->end ());" << endl
+ << "i != e;)"
+ << "{";
+
+ if (options.value<CLI::no_iostream> ())
+ {
+ if (options.value<CLI::no_stl> ())
+ os << "printf (\"%s\", *i++);";
+ else
+ os << "printf (\"%s\", (i++)->c_str ());";
+
+ os << "if (i != e)" << endl
+ << "printf (\" \");"
+ << "}"
+ << "printf (\"\\n\");";
+ }
+ else
+ os << "std::cout << *i++;"
+ << "if (i != e)" << endl
+ << "std::cout << ' ';"
+ << "}"
+ << "std::cout << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ void
+ gen_buffer (SemanticGraph::Type& t)
+ {
+ if (default_type (t, xs_ns_name () + L"::buffer*"))
+ {
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (" << strlit (tag_ + L": %zu bytes\n") << ", " <<
+ arg_ << "->size ());";
+ else
+ os << "std::cout << " << strlit (tag_ + L": ") << " << " <<
+ arg_ << "->size () << \" bytes\" << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ void
+ gen_time_zone ()
+ {
+ os << endl
+ << "if (" << arg_ << ".zone_present ())"
+ << "{";
+
+ if (options.value<CLI::no_iostream> ())
+ os << "if (" << arg_ << ".zone_hours () < 0)" << endl
+ << "printf (\"%d:%d\", " << arg_ << ".zone_hours (), -" <<
+ arg_ << ".zone_minutes ());"
+ << "else" << endl
+ << "printf (\"+%d:%d\", " << arg_ << ".zone_hours (), " <<
+ arg_ << ".zone_minutes ());";
+ else
+ os << "if (" << arg_ << ".zone_hours () < 0)" << endl
+ << "std::cout << " << arg_ << ".zone_hours () << ':' << -" <<
+ arg_ << ".zone_minutes ();"
+ << "else" << endl
+ << "std::cout << '+' << " << arg_ << ".zone_hours () << " <<
+ "':' << " << arg_ << ".zone_minutes ();";
+
+ os << "}";
+
+ if (options.value<CLI::no_iostream> ())
+ os << "printf (\"\\n\");";
+ else
+ os << "std::cout << std::endl;";
+ }
+
+ private:
+ String tag_;
+ String arg_;
+ };
+
+ struct DeleteCall: 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,
+
+ Context
+ {
+ DeleteCall (Context& c, String const& arg)
+ : Context (c), arg_ (arg)
+ {
+ }
+
+ // Strings.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::String& t)
+ {
+ gen_string (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NormalizedString& t)
+ {
+ gen_string (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Token& t)
+ {
+ gen_string (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameToken& t)
+ {
+ gen_string (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Name& t)
+ {
+ gen_string (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NCName& t)
+ {
+ gen_string (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Language& t)
+ {
+ gen_string (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Id& t)
+ {
+ gen_string (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRef& t)
+ {
+ gen_string (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::AnyURI& t)
+ {
+ gen_string (t);
+ }
+
+ // String sequences.
+ //
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameTokens& t)
+ {
+ gen_sequence (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRefs& t)
+ {
+ gen_sequence (t);
+ }
+
+ // QName
+ //
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::QName& t)
+ {
+ if (options.value<CLI::no_stl> () &&
+ default_type (t, xs_ns_name () + L"::qname*"))
+ {
+ os << endl
+ << "delete " << arg_ << ";";
+ }
+ }
+
+ // Binary.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Base64Binary& t)
+ {
+ gen_buffer (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::HexBinary& t)
+ {
+ gen_buffer (t);
+ }
+
+ private:
+ bool
+ default_type (SemanticGraph::Type& t, String const& def_type)
+ {
+ return ret_type (t) == def_type;
+ }
+
+ void
+ gen_string (SemanticGraph::Type& t)
+ {
+ if (options.value<CLI::no_stl> () && default_type (t, "char*"))
+ {
+ os << endl
+ << "delete[] " << arg_ << ";";
+ }
+ }
+
+ void
+ gen_sequence (SemanticGraph::Type& t)
+ {
+ if (default_type (t, xs_ns_name () + L"::string_sequence*"))
+ {
+ os << endl
+ << "delete " << arg_ << ";";
+ }
+ }
+
+ void
+ gen_buffer (SemanticGraph::Type& t)
+ {
+ if (default_type (t, xs_ns_name () + L"::buffer*"))
+ {
+ os << endl
+ << "delete " << arg_ << ";";
+ }
+ }
+
+ private:
+ String arg_;
+ };
+ }
+}
+
+#endif // CXX_PARSER_PRINT_IMPL_COMMON_HXX
diff --git a/xsde/cxx/parser/state-processor.cxx b/xsde/cxx/parser/state-processor.cxx
new file mode 100644
index 0000000..3ecc77a
--- /dev/null
+++ b/xsde/cxx/parser/state-processor.cxx
@@ -0,0 +1,319 @@
+// file : xsde/cxx/parser/state-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/parser/state-processor.hxx>
+
+#include <cxx/parser/elements.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/vector.hxx>
+
+#include <iostream>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ namespace
+ {
+ typedef Cult::Containers::Vector<SemanticGraph::Particle*> Particles;
+
+ void
+ print (Particles const& p)
+ {
+ using std::wcerr;
+ using std::endl;
+
+ wcerr << "prefixes: " << endl;
+
+ for (Particles::ConstIterator i (p.begin ()); i != p.end (); ++i)
+ {
+ if (SemanticGraph::Element* e =
+ dynamic_cast<SemanticGraph::Element*> (*i))
+ {
+ wcerr << e->name () << endl;
+ }
+ else
+ {
+ wcerr << "<any>" << endl;
+ }
+ }
+
+ wcerr << endl;
+ }
+
+ //
+ //
+ struct Particle: Traversal::All,
+ Traversal::Choice,
+ Traversal::Sequence
+ {
+ Particle (UnsignedLong& all,
+ UnsignedLong& choice,
+ UnsignedLong& sequence,
+ UnsignedLong& depth)
+ : all_ (all),
+ choice_ (choice),
+ sequence_ (sequence),
+ depth_ (depth)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ using SemanticGraph::Compositor;
+
+ // Go over particles, collecting "prefix" particles in prefixes_,
+ // assigning state numbers and calculating effective minOccurs.
+ // If all prefixes of this compositor have minOccurs = 0, then
+ // the compositor itself effectively has minOccurs = 0 regardless
+ // of the actual value specified in the schema.
+ //
+ // Note that we don't need to care about depth since the 'all'
+ // compositor cannot contain any nested compositors.
+ //
+
+ UnsignedLong state (0);
+ UnsignedLong min (0);
+
+ for (Compositor::ContainsIterator ci (a.contains_begin ());
+ ci != a.contains_end (); ++ci)
+ {
+ SemanticGraph::Particle& p (ci->particle ());
+
+ // The 'all' compositor can only include elements.
+ //
+ prefixes_.push_back (&p);
+
+ if (min == 0 && ci->min () != 0)
+ min = 1;
+
+ p.context ().set ("p:prefix", true);
+ p.context ().set ("p:state", state++);
+ }
+
+ if (!prefixes_.empty ())
+ {
+ a.context ().set ("p:comp-number", choice_++);
+ a.context ().set ("p:prefixes", prefixes_);
+ a.context ().set ("p:state-count",
+ UnsignedLong (prefixes_.size ()));
+
+ // effective-min = min * actual-min
+ //
+ if (min == 1)
+ min = a.min ();
+
+ a.context ().set ("p:effective-min", min);
+
+ // print (prefixes_);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ using SemanticGraph::Compositor;
+
+ // Go over particles, collecting "prefix" particles in prefixes_,
+ // assigning state numbers and calculating effective minOccurs.
+ // If any prefix of this compositor have minOccurs = 0, then the
+ // compositor itself effectively has minOccurs = 0 regardless of
+ // the actual value specified in the schema.
+ //
+
+ UnsignedLong state (0);
+ UnsignedLong min (1);
+
+ for (Compositor::ContainsIterator ci (c.contains_begin ());
+ ci != c.contains_end (); ++ci)
+ {
+ SemanticGraph::Particle& p (ci->particle ());
+
+ if (p.is_a<SemanticGraph::Element> () ||
+ p.is_a<SemanticGraph::Any> ())
+ {
+ prefixes_.push_back (&p);
+
+ if (min == 1 && ci->min () == 0)
+ min = 0;
+ }
+ else
+ {
+ UnsignedLong depth (0);
+ Particle t (all_, choice_, sequence_, depth);
+ t.dispatch (p);
+
+ if (t.prefixes_.empty ())
+ continue; // Skip empty compositors.
+
+ if (++depth > depth_) // One for this compositor.
+ depth_ = depth;
+
+ prefixes_.insert (prefixes_.end (),
+ t.prefixes_.begin ().base (),
+ t.prefixes_.end ().base ());
+
+ if (min == 1 &&
+ p.context ().get<UnsignedLong> ("p:effective-min") == 0)
+ min = 0;
+ }
+
+ p.context ().set ("p:prefix", true);
+ p.context ().set ("p:state", state++);
+ }
+
+ if (!prefixes_.empty ())
+ {
+ c.context ().set ("p:comp-number", choice_++);
+ c.context ().set ("p:prefixes", prefixes_);
+
+ // effective-min = min * actual-min
+ //
+ if (min == 1)
+ min = c.min ();
+
+ c.context ().set ("p:effective-min", min);
+
+ // print (prefixes_);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ using SemanticGraph::Compositor;
+
+ // Go over particles, collecting "prefix" particles in prefixes_,
+ // assigning state numbers and calculating effective minOccurs.
+ // If all prefixes of this compositor have minOccurs = 0, then
+ // the compositor itself effectively has minOccurs = 0 regardless
+ // of the actual value specified in the schema.
+ //
+
+ Boolean prefix (true);
+ UnsignedLong state (0);
+ UnsignedLong min (0);
+
+ for (Compositor::ContainsIterator ci (s.contains_begin ());
+ ci != s.contains_end (); ++ci)
+ {
+ SemanticGraph::Particle& p (ci->particle ());
+
+ if (p.is_a<SemanticGraph::Element> () ||
+ p.is_a<SemanticGraph::Any> ())
+ {
+ if (prefix)
+ {
+ prefixes_.push_back (&p);
+
+ if (ci->min () != 0)
+ min = 1;
+ }
+ }
+ else
+ {
+ UnsignedLong depth (0);
+ Particle t (all_, choice_, sequence_, depth);
+ t.dispatch (p);
+
+ if (t.prefixes_.empty ())
+ continue; // Skip empty compositors.
+
+ if (++depth > depth_) // One for this compositor.
+ depth_ = depth;
+
+ if (prefix)
+ {
+ prefixes_.insert (prefixes_.end (),
+ t.prefixes_.begin ().base (),
+ t.prefixes_.end ().base ());
+
+ if (p.context ().get<UnsignedLong> ("p:effective-min") != 0)
+ min = 1;
+ }
+ }
+
+ p.context ().set ("p:state", state++);
+
+ if (prefix)
+ p.context ().set ("p:prefix", true);
+
+ if (prefix && min != 0)
+ prefix = false;
+ }
+
+ if (!prefixes_.empty ())
+ {
+ s.context ().set ("p:comp-number", sequence_++);
+ s.context ().set ("p:prefixes", prefixes_);
+
+ // effective-min = min * actual-min
+ //
+ if (min == 1)
+ min = s.min ();
+
+ s.context ().set ("p:effective-min", min);
+
+ // print (prefixes_);
+ }
+ }
+
+ private:
+ Particles prefixes_;
+
+ UnsignedLong& all_;
+ UnsignedLong& choice_;
+ UnsignedLong& sequence_;
+
+ UnsignedLong& depth_;
+ };
+
+
+ //
+ //
+ struct Complex: Traversal::Complex
+ {
+ virtual Void
+ traverse (Type& c)
+ {
+ if (c.contains_compositor_p ())
+ {
+ UnsignedLong all (0), choice (0), sequence (0), depth (0);
+ Particle t (all, choice, sequence, depth);
+ t.dispatch (c.contains_compositor ().compositor ());
+
+ // Set the maximum stack depth for this type. Used to
+ // allocate fixed-size state stack.
+ //
+ c.context ().set ("p:depth", depth + 1);
+ }
+ }
+ };
+ }
+
+ Void StateProcessor::
+ process (SemanticGraph::Schema& tu, SemanticGraph::Path const&)
+ {
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+
+ schema >> sources >> schema;
+ schema >> schema_names >> ns >> ns_names;
+
+ Complex complex_type;
+
+ ns_names >> complex_type;
+
+ schema.dispatch (tu);
+ }
+ }
+}
diff --git a/xsde/cxx/parser/state-processor.hxx b/xsde/cxx/parser/state-processor.hxx
new file mode 100644
index 0000000..c276d54
--- /dev/null
+++ b/xsde/cxx/parser/state-processor.hxx
@@ -0,0 +1,28 @@
+// file : xsde/cxx/parser/state-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_PARSER_STATE_PROCESSOR_HXX
+#define CXX_PARSER_STATE_PROCESSOR_HXX
+
+#include <cult/types.hxx>
+#include <xsd-frontend/semantic-graph.hxx>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ using namespace Cult::Types;
+
+ class StateProcessor
+ {
+ public:
+ Void
+ process (XSDFrontend::SemanticGraph::Schema&,
+ XSDFrontend::SemanticGraph::Path const& file);
+ };
+ }
+}
+
+#endif // CXX_PARSER_STATE_PROCESSOR_HXX
diff --git a/xsde/cxx/parser/type-processor.cxx b/xsde/cxx/parser/type-processor.cxx
new file mode 100644
index 0000000..4e7f65a
--- /dev/null
+++ b/xsde/cxx/parser/type-processor.cxx
@@ -0,0 +1,352 @@
+// file : xsde/cxx/parser/type-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 <cult/containers/set.hxx>
+
+#include <cxx/parser/elements.hxx>
+#include <cxx/parser/type-processor.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ namespace
+ {
+ //
+ //
+ struct Type: Traversal::Type
+ {
+ Type (SemanticGraph::Schema& schema,
+ TypeMap::Namespaces& type_map,
+ Boolean add_includes)
+ : schema_ (schema),
+ type_map_ (type_map),
+ add_includes_ (add_includes)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& type)
+ {
+ using TypeMap::Namespace;
+ using TypeMap::Namespaces;
+
+ SemanticGraph::Context& tc (type.context ());
+
+ // There are two situations where we may try to process the
+ // same type more than once. The first is when the type is
+ // used in several element declarations in the same schema.
+ // The second situation only occurs when we are in the file-
+ // per-type mode. In this case the type was processed as part
+ // of another root schema. In the second case, while the ret
+ // and arg types are assumed to be the same, we need to re-
+ // match the type in order to add include directives to the
+ // new root schema.
+ //
+ Boolean set (true);
+
+ if (tc.count ("p:ret-type"))
+ {
+ SemanticGraph::Schema* s (
+ tc.get<SemanticGraph::Schema*> ("p:root-schema"));
+
+ if (&schema_ == s)
+ return;
+
+ set = false;
+ }
+
+ SemanticGraph::Namespace& ns (
+ dynamic_cast<SemanticGraph::Namespace&> (type.scope ()));
+
+ String const& ns_name (ns.name ());
+ String const& t_name (type.name ());
+
+ // std::wcerr << "traversing: " << ns_name << "#" << t_name << endl;
+
+ for (Namespaces::ConstIterator n (type_map_.begin ());
+ n != type_map_.end (); ++n)
+ {
+ // Check if the namespace matches.
+ //
+ Boolean ns_match;
+
+ if (!n->xsd_name ().empty ())
+ {
+ ns_match = n->xsd_name ().match (ns_name);
+ }
+ else
+ ns_match = ns_name.empty ();
+
+ // std::wcerr << "considering ns expr: " << n->xsd_name () << endl;
+
+ if (ns_match)
+ {
+ // Namespace matched. See if there is a type that matches.
+ //
+ for (Namespace::TypesIterator t (n->types_begin ());
+ t != n->types_end (); ++t)
+ {
+ if (t->xsd_name ().match (t_name))
+ {
+ if (set)
+ {
+ // Got a match. See if the namespace has the C++
+ // namespace mapping.
+ //
+ String cxx_ns;
+
+ if (n->has_cxx_name ())
+ {
+ if (!n->xsd_name ().empty ())
+ {
+ cxx_ns = n->xsd_name ().merge (
+ n->cxx_name (), ns_name, true);
+ }
+ else
+ cxx_ns = n->cxx_name ();
+
+ cxx_ns += L"::";
+ }
+
+ // Figure out ret and arg type names.
+ //
+ String ret_type (cxx_ns);
+
+ ret_type += t->xsd_name ().merge (
+ t->cxx_ret_name (), t_name, true);
+
+ String arg_type;
+
+ if (t->cxx_arg_name ())
+ {
+ arg_type = cxx_ns;
+ arg_type += t->xsd_name ().merge (
+ t->cxx_arg_name (), t_name, true);
+ }
+ else
+ {
+ if (ret_type == L"void")
+ arg_type = ret_type;
+ else
+ {
+ WideChar last (ret_type[ret_type.size () - 1]);
+
+ // If it is already a pointer or reference then use
+ // it as is.
+ //
+ if (last == L'*' || last == L'&')
+ arg_type = ret_type;
+ else
+ arg_type = L"const " + ret_type + L"&";
+ }
+ }
+
+ tc.set ("p:ret-type", ret_type);
+ tc.set ("p:arg-type", arg_type);
+ }
+
+ tc.set ("p:root-schema", &schema_);
+
+ //std::wcerr << t_name << " -> " << ret_type << endl;
+
+ // See of we need to add any includes to the translations
+ // unit.
+ //
+ if (add_includes_)
+ {
+ if (n->includes_begin () != n->includes_end ())
+ {
+ typedef Cult::Containers::Set<String> Includes;
+
+ SemanticGraph::Context& sc (schema_.context ());
+
+ if (!sc.count ("p:includes"))
+ sc.set ("p:includes", Includes ());
+
+ Includes& is (sc.get<Includes> ("p:includes"));
+
+ for (Namespace::IncludesIterator i (n->includes_begin ());
+ i != n->includes_end (); ++i)
+ {
+ is.insert (*i);
+ }
+ }
+ }
+
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ private:
+ SemanticGraph::Schema& schema_;
+ TypeMap::Namespaces& type_map_;
+ Boolean add_includes_;
+ };
+
+ //
+ //
+ struct BaseType: Traversal::Complex
+ {
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ Complex::inherits (c);
+ }
+ };
+
+ //
+ //
+ struct GlobalType: Traversal::Type,
+ Traversal::List,
+ Traversal::Complex,
+ Traversal::Enumeration
+ {
+ GlobalType (SemanticGraph::Schema& schema,
+ TypeMap::Namespaces& type_map,
+ Boolean add_includes,
+ Boolean tiein)
+ : type_ (schema, type_map, add_includes)
+ {
+ inherits_ >> type_;
+ names_ >> instance_ >> belongs_ >> type_;
+ argumented_ >> type_;
+
+ if (tiein)
+ {
+ // In case of a tiein support, we also need to process base's
+ // base type.
+ //
+ inherits_base_ >> base_type_ >> inherits_level_2_ >> type_;
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& t)
+ {
+ type_.traverse (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::List& l)
+ {
+ type_.traverse (l);
+ Traversal::List::argumented (l, argumented_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ type_.traverse (c);
+ Complex::inherits (c, inherits_);
+ Complex::inherits (c, inherits_base_);
+ Complex::names (c, names_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Enumeration& e)
+ {
+ type_.traverse (e);
+ Complex::inherits (e, inherits_);
+ }
+
+ private:
+ Parser::Type type_;
+ BaseType base_type_;
+ Traversal::Names names_;
+ Traversal::Instance instance_;
+ Traversal::Inherits inherits_;
+ Traversal::Inherits inherits_base_;
+ Traversal::Inherits inherits_level_2_;
+ Traversal::Belongs belongs_;
+ Traversal::Argumented argumented_;
+ };
+
+ Void
+ process_impl (CLI::Options const& options,
+ XSDFrontend::SemanticGraph::Schema& tu,
+ TypeMap::Namespaces& type_map)
+ {
+ Boolean tiein (!options.value<CLI::reuse_style_mixin> () &&
+ !options.value<CLI::reuse_style_none> ());
+
+ 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;
+ GlobalType global_type (tu, type_map, true, tiein);
+
+ schema >> schema_names >> ns >> ns_names >> global_type;
+
+ schema.dispatch (tu);
+ }
+ else
+ {
+ // If --extern-xml-schema is specified, then we don't want
+ // includes from the XML Schema type map.
+ //
+ Boolean extern_xml_schema (
+ options.value<CLI::extern_xml_schema> ());
+
+ // Besides types defined in this schema, also process those
+ // referenced by global elements in case we are generating
+ // something for them.
+ //
+ Traversal::Schema schema;
+ Traversal::Schema xs_schema;
+ Traversal::Sources sources;
+ Traversal::Implies implies;
+
+ schema >> sources >> schema;
+ schema >> implies >> xs_schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+ Traversal::Element global_element;
+ GlobalType global_type (tu, type_map, true, tiein);
+
+ schema >> schema_names >> ns >> ns_names;
+
+ ns_names >> global_element;
+ ns_names >> global_type;
+
+ Traversal::Belongs element_belongs;
+ global_element >> element_belongs >> global_type;
+
+ Traversal::Names xs_schema_names;
+ Traversal::Namespace xs_ns;
+ Traversal::Names xs_ns_names;
+ GlobalType xs_global_type (tu, type_map, !extern_xml_schema, tiein);
+
+ xs_schema >> xs_schema_names >> xs_ns >> xs_ns_names >>
+ xs_global_type;
+
+ schema.dispatch (tu);
+ }
+ }
+ }
+
+ Void TypeProcessor::
+ process (CLI::Options const& options,
+ XSDFrontend::SemanticGraph::Schema& s,
+ TypeMap::Namespaces& tm)
+ {
+ process_impl (options, s, tm);
+ }
+ }
+}
diff --git a/xsde/cxx/parser/type-processor.hxx b/xsde/cxx/parser/type-processor.hxx
new file mode 100644
index 0000000..5855569
--- /dev/null
+++ b/xsde/cxx/parser/type-processor.hxx
@@ -0,0 +1,34 @@
+// file : xsde/cxx/parser/type-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_PARSER_TYPE_PROCESSOR_HXX
+#define CXX_PARSER_TYPE_PROCESSOR_HXX
+
+#include <cult/types.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+
+#include <type-map/type-map.hxx>
+
+#include <cxx/parser/cli.hxx>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ using namespace Cult::Types;
+
+ class TypeProcessor
+ {
+ public:
+ Void
+ process (CLI::Options const& options,
+ XSDFrontend::SemanticGraph::Schema&,
+ TypeMap::Namespaces&);
+ };
+ }
+}
+
+#endif // CXX_PARSER_TYPE_PROCESSOR_HXX
diff --git a/xsde/cxx/parser/validator.cxx b/xsde/cxx/parser/validator.cxx
new file mode 100644
index 0000000..570a0bf
--- /dev/null
+++ b/xsde/cxx/parser/validator.cxx
@@ -0,0 +1,704 @@
+// file : xsde/cxx/parser/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/parser/validator.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cxx/parser/elements.hxx>
+
+#include <iostream>
+
+using std::wcerr;
+
+namespace CXX
+{
+ namespace Parser
+ {
+ 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 Any : Traversal::Any, ValidationContext
+ {
+ Any (ValidationContext& c)
+ : ValidationContext (c)
+ {
+ }
+
+ struct Element: Traversal::Element, ValidationContext
+ {
+ Element (ValidationContext& c, SemanticGraph::Any& any)
+ : ValidationContext (c),
+ any_ (any),
+ ns_ (any.definition_namespace ().name ())
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ using SemanticGraph::Any;
+
+ Boolean q (e.qualified ());
+ String ns (q ? e.namespace_ ().name () : "");
+
+ for (Any::NamespaceIterator i (any_.namespace_begin ());
+ i != any_.namespace_end (); ++i)
+ {
+ Boolean failed (false);
+
+ if (*i == L"##any")
+ {
+ failed = true;
+ }
+ else if (*i == L"##other")
+ {
+ if (ns_)
+ {
+ // Note that here I assume that ##other does not
+ // include names without target namespace. This
+ // is not what the spec says but that seems to be
+ // the consensus.
+ //
+ failed = q && ns != ns_;
+ }
+ else
+ {
+ // No target namespace.
+ //
+ failed = q && ns != L"";
+ }
+ }
+ else if (*i == L"##local")
+ {
+ failed = !q || ns == L"";
+ }
+ else if (*i == L"##targetNamespace")
+ {
+ failed = (q && ns_ == ns) || (!q && ns_ == L"");
+ }
+ else
+ {
+ failed = q && *i == ns;
+ }
+
+ if (failed)
+ {
+ Any& a (any_);
+
+ os << a.file () << ":" << a.line () << ":" << a.column ()
+ << ": warning P001: namespace '" << *i << "' allows for "
+ << "element '" << e.name () << "'" << endl;
+
+ os << a.file () << ":" << a.line () << ":" << a.column ()
+ << ": warning P001: generated code may not associate "
+ << "element '" << e.name () << "' correctly if it appears "
+ << "in place of this wildcard" << endl;
+
+ os << e.file () << ":" << e.line () << ":" << e.column ()
+ << ": info: element '" << e.name () << "' is defined "
+ << "here" << endl;
+
+ os << a.file () << ":" << a.line () << ":" << a.column ()
+ << ": info: turn on validation to ensure correct "
+ << "association" << endl;
+ }
+ }
+ }
+
+ private:
+ SemanticGraph::Any& any_;
+ String ns_;
+ };
+
+ struct Complex: Traversal::Complex
+ {
+ Complex ()
+ : up_ (true), down_ (true)
+ {
+ }
+
+ virtual Void
+ post (Type& c)
+ {
+ // Go down the inheritance hierarchy.
+ //
+ if (down_)
+ {
+ Boolean up = up_;
+ up_ = false;
+
+ if (c.inherits_p ())
+ dispatch (c.inherits ().base ());
+
+ up_ = up;
+ }
+
+ // Go up the inheritance hierarchy.
+ //
+ if (up_)
+ {
+ Boolean down = down_;
+ down_ = false;
+
+ for (Type::BegetsIterator i (c.begets_begin ());
+ i != c.begets_end (); ++i)
+ {
+ dispatch (i->derived ());
+ }
+
+ down_ = down;
+ }
+ }
+
+ private:
+ Boolean up_, down_;
+ };
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ using SemanticGraph::Compositor;
+
+ // Find our complex type.
+ //
+ Compositor* c (&a.contained_particle ().compositor ());
+
+ while(!c->contained_compositor_p ())
+ c = &c->contained_particle ().compositor ();
+
+ SemanticGraph::Complex& type (
+ dynamic_cast<SemanticGraph::Complex&> (
+ c->contained_compositor ().container ()));
+
+ Complex complex;
+ Traversal::Compositor compositor;
+ Element element (*this, a);
+ Traversal::ContainsCompositor contains_compositor;
+ Traversal::ContainsParticle contains_particle;
+
+ complex >> contains_compositor;
+ contains_compositor >> compositor;
+ compositor >> contains_particle;
+ contains_particle >> compositor;
+ contains_particle >> element;
+
+ complex.dispatch (type);
+ }
+ };
+
+
+ //
+ //
+ struct Traverser : Traversal::Schema,
+ Traversal::Complex,
+ Traversal::Type,
+ Traversal::Element,
+ ValidationContext
+ {
+ Traverser (ValidationContext& c)
+ : ValidationContext (c),
+ any_ (c)
+ {
+ *this >> sources_ >> *this;
+ *this >> schema_names_ >> ns_ >> names_ >> *this;
+
+ // Any
+ //
+ if (!validation && !is_disabled ("P001"))
+ {
+ *this >> contains_compositor_ >> compositor_ >> contains_particle_;
+ contains_particle_ >> compositor_;
+ contains_particle_ >> any_;
+ }
+ }
+
+ 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;
+ }
+ }
+ }
+
+ Complex::traverse (c);
+ }
+
+ 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 ("P002"))
+ 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 P002: 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 parse "
+ << "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_;
+
+ // Any.
+ //
+ Any any_;
+ Traversal::Compositor compositor_;
+ Traversal::ContainsParticle contains_particle_;
+ Traversal::ContainsCompositor contains_compositor_;
+ };
+
+ //
+ //
+ 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 GlobalElement: Traversal::Element, ValidationContext
+ {
+ GlobalElement (ValidationContext& c, SemanticGraph::Element*& element)
+ : ValidationContext (c), element_ (element)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (!valid)
+ return;
+
+ if (options.value<CLI::root_element_first> ())
+ {
+ if (element_ == 0)
+ element_ = &e;
+ }
+ else if (options.value<CLI::root_element_last> ())
+ {
+ element_ = &e;
+ }
+ else if (String name = options.value<CLI::root_element> ())
+ {
+ if (e.name () == name)
+ element_ = &e;
+ }
+ else
+ {
+ if (element_ == 0)
+ element_ = &e;
+ else
+ {
+ wcerr << schema_root.file () << ": error: unable to generate "
+ << "the test driver without a unique document root"
+ << endl;
+
+ wcerr << schema_root.file () << ": info: use --root-element-* "
+ << "options to specify the document root" << endl;
+
+ valid = false;
+ }
+ }
+ }
+
+ private:
+ SemanticGraph::Element*& element_;
+ };
+ }
+
+ Boolean Validator::
+ validate (CLI::Options const& options,
+ SemanticGraph::Schema& root,
+ SemanticGraph::Path const&,
+ Boolean gen_driver,
+ const WarningSet& disabled_warnings)
+ {
+ Boolean valid (true);
+ ValidationContext ctx (root, options, disabled_warnings, valid);
+
+ //
+ //
+ if (options.value<CLI::generate_noop_impl> () &&
+ options.value<CLI::generate_print_impl> ())
+ {
+ wcerr << "error: mutually exclusive options specified: "
+ << "--generate-noop-impl and --generate-print-impl"
+ << endl;
+
+ return false;
+ }
+
+ //
+ //
+ {
+ Boolean ref (options.value<CLI::root_element_first> ());
+ Boolean rel (options.value<CLI::root_element_last> ());
+ Boolean re (options.value<CLI::root_element> ());
+
+ if ((ref && rel) || (ref && re) || (rel && re))
+ {
+ wcerr << "error: mutually exclusive options specified: "
+ << "--root-element-last, --root-element-first, and "
+ << "--root-element"
+ << endl;
+
+ return false;
+ }
+ }
+
+ //
+ //
+ if (options.value<CLI::reuse_style_mixin> () &&
+ options.value<CLI::reuse_style_none> ())
+ {
+ wcerr << "error: mutually exclusive options specified: "
+ << "--reuse-style-mixin and --reuse-style-none"
+ << endl;
+
+ return false;
+ }
+
+ //
+ //
+ if (options.value<CLI::reuse_style_none> () &&
+ (options.value<CLI::generate_noop_impl> () ||
+ options.value<CLI::generate_print_impl> ()) &&
+ !ctx.is_disabled ("P003"))
+ {
+ wcerr << "warning P003: generating sample implementation without "
+ << "parser reuse support: the resulting code may not compile"
+ << endl;
+
+ return false;
+ }
+
+ // Test for anonymout types.
+ //
+ {
+ AnonymousType traverser (ctx);
+ traverser.dispatch (root);
+ }
+
+ // Test the rest.
+ //
+ if (valid)
+ {
+ Traverser traverser (ctx);
+ traverser.dispatch (root);
+ }
+
+ // Test that the document root is unique.
+ //
+ if (valid && gen_driver)
+ {
+ SemanticGraph::Element* element (0);
+
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+
+ schema >> sources >> schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+ GlobalElement global_element (ctx, element);
+
+ schema >> schema_names >> ns >> ns_names >> global_element;
+
+ schema.dispatch (root);
+
+ if (valid && element == 0)
+ {
+ wcerr << root.file () << ": error: unable to generate the "
+ << "test driver without a global element (document root)"
+ << endl;
+
+ valid = false;
+ }
+ }
+
+ return valid;
+ }
+ }
+}
diff --git a/xsde/cxx/parser/validator.hxx b/xsde/cxx/parser/validator.hxx
new file mode 100644
index 0000000..d602aae
--- /dev/null
+++ b/xsde/cxx/parser/validator.hxx
@@ -0,0 +1,36 @@
+// file : xsde/cxx/parser/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_PARSER_VALIDATOR_HXX
+#define CXX_PARSER_VALIDATOR_HXX
+
+#include <cult/types.hxx>
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/parser/cli.hxx>
+
+#include <xsde.hxx>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ using namespace Cult::Types;
+
+ class Validator
+ {
+ public:
+ Boolean
+ validate (CLI::Options const& options,
+ XSDFrontend::SemanticGraph::Schema&,
+ XSDFrontend::SemanticGraph::Path const& tu,
+ Boolean gen_driver,
+ const WarningSet& disabled_warnings);
+ };
+ }
+}
+
+#endif // CXX_PARSER_VALIDATOR_HXX
diff --git a/xsde/cxx/serializer/attribute-validation-source.cxx b/xsde/cxx/serializer/attribute-validation-source.cxx
new file mode 100644
index 0000000..59d3cb5
--- /dev/null
+++ b/xsde/cxx/serializer/attribute-validation-source.cxx
@@ -0,0 +1,463 @@
+// file : xsde/cxx/serializer/attribute-validation-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/serializer/attribute-validation-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ namespace
+ {
+ struct AnyAttributeTest: Traversal::AnyAttribute, Context
+ {
+ AnyAttributeTest (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute& a)
+ {
+ String const& ns (a.definition_namespace ().name ());
+
+ for (SemanticGraph::AnyAttribute::NamespaceIterator
+ i (a.namespace_begin ()), e (a.namespace_end ()); i != e;)
+ {
+ if (*i == L"##any")
+ {
+ if (stl)
+ os << "!name.empty ()";
+ else
+ os << "(name != 0 && *name != '\\0')";
+ }
+ else if (*i == L"##other")
+ {
+ if (ns)
+ {
+ // Note that here I assume that ##other does not include
+ // unqualified names in a schema with target namespace.
+ // This is not what the spec says but that seems to be
+ // the consensus.
+ //
+ if (stl)
+ os << "(!ns.empty () && ns != " << strlit (ns) << ")";
+ else
+ os << "(ns != 0 && *ns != '\\0' && " <<
+ "strcmp (ns, " << strlit (ns) << ") != 0)";
+ }
+ else
+ {
+ if (stl)
+ os << "!ns.empty ()";
+ else
+ os << "(ns != 0 && *ns != '\\0')";
+ }
+ }
+ else if (*i == L"##local")
+ {
+ if (stl)
+ os << "(ns.empty () && !name.empty ())";
+ else
+ os << "((ns == 0 || *ns == '\\0') && " <<
+ "name != 0 && *name != '\\0')";
+ }
+ else if (*i == L"##targetNamespace")
+ {
+ if (stl)
+ os << "ns == " << strlit (ns);
+ else
+ os << "(ns != 0 && strcmp (ns, " << strlit (ns) << ") == 0)";
+ }
+ else
+ {
+ if (stl)
+ os << "ns == " << strlit (*i);
+ else
+ os << "(ns != 0 && strcmp (ns, " << strlit (*i) << ") == 0)";
+ }
+
+ if (++i != e)
+ os << " ||" << endl;
+ }
+ }
+ };
+
+ struct Attribute: Traversal::Attribute,
+ Traversal::AnyAttribute,
+ Context
+ {
+ Attribute (Context& c)
+ : Context (c), any_attribute_test_ (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ String const& name (ename (a));
+
+ os << "// " << name << endl
+ << "//" << endl;
+
+ if (a.optional ())
+ {
+ os << "if (this->" << epresent (a) << " ())";
+ }
+
+ os << "{";
+
+ String const& inst (emember (a));
+ String const& ret (ret_type (a.type ()));
+ String const& arg (arg_type (a.type ()));
+
+ if (ret == L"void")
+ os << "this->" << name << " ();"
+ << endl;
+ else
+ os << arg << " r = this->" << name << " ();"
+ << endl;
+
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ os << "if (this->" << inst << ")"
+ << "{";
+
+ if (ret == L"void")
+ os << "this->" << inst << "->pre ();";
+ else
+ os << "this->" << inst << "->pre (r);";
+
+ if (!exceptions)
+ os << endl
+ << "if (this->" << inst << "->_error_type ())" << endl
+ << "this->" << inst << "->_copy_error (ctx);"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ if (exceptions)
+ {
+ if (a.qualified () && a.namespace_ ().name ())
+ os << "this->_start_attribute (" <<
+ strlit (a.namespace_ ().name ()) << ", " <<
+ strlit (a.name ()) << ");";
+ else
+ os << "this->_start_attribute (" << strlit (a.name ()) << ");";
+ }
+ else
+ {
+ os << "if (!";
+
+ if (a.qualified () && a.namespace_ ().name ())
+ os << "this->_start_attribute (" <<
+ strlit (a.namespace_ ().name ()) << ", " <<
+ strlit (a.name ()) << ")";
+ else
+ os << "this->_start_attribute (" << strlit (a.name ()) << ")";
+
+ os << ")" << endl
+ << "return;"
+ << endl;
+ }
+
+ os << "this->" << inst << "->_pre_impl (ctx);";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ os << "this->" << inst << "->_serialize_content ();";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ os << "this->" << inst << "->_post_impl ();";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ if (exceptions)
+ os << "this->_end_attribute ();";
+ else
+ os << "if (!this->_end_attribute ())" << endl
+ << "return;"
+ << endl;
+
+ os << "this->" << inst << "->post ();";
+
+ if (!exceptions)
+ os << endl
+ << "if (this->" << inst << "->_error_type ())" << endl
+ << "this->" << inst << "->_copy_error (ctx);"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;";
+
+ os << "}"; // if (inst)
+
+ if (!a.optional ())
+ {
+ os << "else"
+ << "{"
+ << "this->_schema_error (" <<
+ "::xsde::cxx::schema_error::expected_attribute);"
+ << "return;"
+ << "}";
+ }
+
+ os << "}";
+
+ if (a.optional () && !exceptions)
+ {
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute& a)
+ {
+ os << "while (this->" << enext (a) << " ())"
+ << "{";
+
+ if (stl)
+ {
+ os << "::std::string ns, name;"
+ << "this->" << ename (a) << " (ns, name);"
+ << endl;
+
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ os << "if (";
+
+ any_attribute_test_.dispatch (a);
+
+ os << ")"
+ << "{";
+
+ os << "if (ns.empty ())"
+ << "{";
+
+ if (exceptions)
+ os << "this->_start_attribute (name.c_str ());";
+ else
+ os << "if (!this->_start_attribute (name.c_str ()))" << endl
+ << "return;";
+
+ os << "}"
+ << "else"
+ << "{";
+
+ if (exceptions)
+ os << "this->_start_attribute (ns.c_str (), name.c_str ());";
+ else
+ os << "if (!this->_start_attribute (ns.c_str (), " <<
+ "name.c_str ()))" << endl
+ << "return;";
+
+ os << "}"
+ << "this->" << eserialize (a) << " ();"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ if (exceptions)
+ os << "this->_end_attribute ();";
+ else
+ os << "if (!this->_end_attribute ())" << endl
+ << "return;";
+
+ os << "}" // test
+ << "else"
+ << "{"
+ << "this->_schema_error (" <<
+ "::xsde::cxx::schema_error::unexpected_attribute);"
+ << "return;"
+ << "}";
+ }
+ else
+ {
+ os << "const char* ns = 0;"
+ << "const char* name;"
+ << "bool free;"
+ << "this->" << ename (a) << " (ns, name, free);"
+ << endl;
+
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ else
+ os << "::xsde::cxx::string auto_ns, auto_name;"
+ << "if (free)"
+ << "{"
+ << "auto_ns.attach (const_cast< char* > (ns));"
+ << "auto_name.attach (const_cast< char* > (name));"
+ << "}";
+
+ os << "if (";
+
+ any_attribute_test_.dispatch (a);
+
+ os << ")"
+ << "{";
+
+ if (exceptions)
+ os << "if (ns == 0 || *ns == '\\0')" << endl
+ << "this->_start_attribute (name);"
+ << "else" << endl
+ << "this->_start_attribute (ns, name);"
+ << endl;
+ else
+ os << "bool r;"
+ << "if (ns == 0 || *ns == '\\0')" << endl
+ << "r = this->_start_attribute (name);"
+ << "else" << endl
+ << "r = this->_start_attribute (ns, name);"
+ << endl
+ << "if (free)"
+ << "{"
+ << "delete[] ns;"
+ << "delete[] name;"
+ << "}"
+ << "if (!r)" << endl
+ << "return;"
+ << endl;
+
+ os << "this->" << eserialize (a) << " ();"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ if (exceptions)
+ os << "this->_end_attribute ();";
+ else
+ os << "if (!this->_end_attribute ())" << endl
+ << "return;";
+
+ os << "}" // test
+ << "else"
+ << "{"
+ << "this->_schema_error (" <<
+ "::xsde::cxx::schema_error::unexpected_attribute);"
+ << "return;"
+ << "}";
+ }
+
+ os << "}";
+
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+
+ private:
+ AnyAttributeTest any_attribute_test_;
+ };
+
+ struct Complex : Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c),
+ attribute_ (c)
+ {
+ names_attribute_ >> attribute_;
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ if (!has<Traversal::Attribute> (c) &&
+ !has<Traversal::AnyAttribute> (c))
+ return;
+
+ // Don't use restriction_p here since we don't want special
+ // treatment of anyType.
+ //
+ Boolean restriction (
+ c.inherits_p () &&
+ c.inherits ().is_a<SemanticGraph::Restricts> ());
+
+ String const& name (ename (c));
+
+ os <<"// Attribute validation and serialization for " <<
+ name << "." << endl
+ <<"//" << endl;
+
+ os << "void " << name << "::" << endl
+ << "_serialize_attributes ()"
+ << "{"
+ << "::xsde::cxx::serializer::context& ctx = this->_context ();"
+ << endl;
+
+ if (c.inherits_p () && !restriction)
+ {
+ // We cannot use the fully-qualified base name directly
+ // because of some broken compilers (EVC 4.0).
+ //
+ String base (unclash (name, "base"));
+
+ os << "typedef " << fq_name (c.inherits ().base ()) << " " <<
+ base << ";"
+ << base << "::_serialize_attributes ();"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+
+ names (c, names_attribute_);
+
+ os << "}";
+ }
+
+ private:
+ Attribute attribute_;
+ Traversal::Names names_attribute_;
+ };
+ }
+
+ Void
+ generate_attribute_validation_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;
+
+ Complex complex (ctx);
+
+ names >> complex;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+}
diff --git a/xsde/cxx/serializer/attribute-validation-source.hxx b/xsde/cxx/serializer/attribute-validation-source.hxx
new file mode 100644
index 0000000..d06890d
--- /dev/null
+++ b/xsde/cxx/serializer/attribute-validation-source.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/serializer/attribute-validation-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_SERIALIZER_ATTRIBUTE_VALIDATION_SOURCE_HXX
+#define CXX_SERIALIZER_ATTRIBUTE_VALIDATION_SOURCE_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/serializer/elements.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ Void
+ generate_attribute_validation_source (Context&);
+ }
+}
+
+#endif // CXX_SERIALIZER_ATTRIBUTE_VALIDATION_SOURCE_HXX
diff --git a/xsde/cxx/serializer/cli.hxx b/xsde/cxx/serializer/cli.hxx
new file mode 100644
index 0000000..5b1b7fa
--- /dev/null
+++ b/xsde/cxx/serializer/cli.hxx
@@ -0,0 +1,154 @@
+// file : xsde/cxx/serializer/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_SERIALIZER_CLI_HXX
+#define CXX_SERIALIZER_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 Serializer
+ {
+ namespace CLI
+ {
+ using namespace Cult::Types;
+
+ typedef Char const Key[];
+
+ extern Key type_map;
+ extern Key no_stl;
+ extern Key no_iostream;
+ extern Key no_exceptions;
+ extern Key no_long_long;
+ extern Key reuse_style_mixin;
+ extern Key reuse_style_none;
+ extern Key generate_inline;
+ extern Key suppress_validation;
+ extern Key generate_polymorphic;
+ extern Key runtime_polymorphic;
+ extern Key suppress_reset;
+ extern Key generate_empty_impl;
+ extern Key generate_test_driver;
+ extern Key force_overwrite;
+ extern Key root_element_first;
+ extern Key root_element_last;
+ extern Key root_element;
+ extern Key generate_xml_schema;
+ extern Key extern_xml_schema;
+ extern Key output_dir;
+ extern Key skel_type_suffix;
+ extern Key skel_file_suffix;
+ extern Key impl_type_suffix;
+ extern Key impl_file_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 hxx_regex;
+ extern Key ixx_regex;
+ extern Key cxx_regex;
+ extern Key hxx_prologue;
+ extern Key ixx_prologue;
+ extern Key cxx_prologue;
+ extern Key prologue;
+ extern Key hxx_epilogue;
+ extern Key ixx_epilogue;
+ extern Key cxx_epilogue;
+ extern Key epilogue;
+ extern Key hxx_prologue_file;
+ extern Key ixx_prologue_file;
+ extern Key cxx_prologue_file;
+ extern Key prologue_file;
+ extern Key hxx_epilogue_file;
+ extern Key ixx_epilogue_file;
+ extern Key cxx_epilogue_file;
+ extern Key epilogue_file;
+ extern Key show_anonymous;
+ extern Key show_sloc;
+ extern Key proprietary_license;
+
+ typedef Cult::CLI::Options<
+ type_map, Cult::Containers::Vector<NarrowString>,
+ no_stl, Boolean,
+ no_iostream, Boolean,
+ no_exceptions, Boolean,
+ no_long_long, Boolean,
+ reuse_style_mixin, Boolean,
+ reuse_style_none, Boolean,
+ generate_inline, Boolean,
+ suppress_validation, Boolean,
+ generate_polymorphic, Boolean,
+ runtime_polymorphic, Boolean,
+ suppress_reset, Boolean,
+ generate_empty_impl, Boolean,
+ generate_test_driver, Boolean,
+ force_overwrite, Boolean,
+ root_element_first, Boolean,
+ root_element_last, Boolean,
+ root_element, NarrowString,
+ generate_xml_schema, Boolean,
+ extern_xml_schema, NarrowString,
+ output_dir, NarrowString,
+ skel_type_suffix, NarrowString,
+ skel_file_suffix, NarrowString,
+ impl_type_suffix, NarrowString,
+ impl_file_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,
+ hxx_regex, NarrowString,
+ ixx_regex, NarrowString,
+ cxx_regex, NarrowString,
+ hxx_prologue, Cult::Containers::Vector<NarrowString>,
+ ixx_prologue, Cult::Containers::Vector<NarrowString>,
+ cxx_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>,
+ epilogue, Cult::Containers::Vector<NarrowString>,
+ hxx_prologue_file, NarrowString,
+ ixx_prologue_file, NarrowString,
+ cxx_prologue_file, NarrowString,
+ prologue_file, NarrowString,
+ hxx_epilogue_file, NarrowString,
+ ixx_epilogue_file, NarrowString,
+ cxx_epilogue_file, NarrowString,
+ epilogue_file, NarrowString,
+ show_anonymous, Boolean,
+ show_sloc, Boolean,
+ proprietary_license, Boolean
+
+ > Options;
+
+ struct OptionsSpec: Cult::CLI::OptionsSpec<Options> {};
+ }
+ }
+}
+
+#endif // CXX_SERIALIZER_CLI_HXX
diff --git a/xsde/cxx/serializer/driver-source.cxx b/xsde/cxx/serializer/driver-source.cxx
new file mode 100644
index 0000000..4a3c7db
--- /dev/null
+++ b/xsde/cxx/serializer/driver-source.cxx
@@ -0,0 +1,1047 @@
+// file : xsde/cxx/serializer/driver-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/serializer/driver-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/map.hxx>
+#include <cult/containers/set.hxx>
+
+#include <sstream>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ 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;
+
+ os << fq_name (t, "s:impl") << " " << inst << ";";
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::List& l)
+ {
+ if (map_.find (&l) == map_.end ())
+ {
+ String inst (find_instance_name (l));
+ map_[&l] = inst;
+
+ os << fq_name (l, "s:impl") << " " << 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;
+
+ os << fq_name (c, "s:impl") << " " << inst << ";";
+
+ 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;
+
+ os << fq_name (t, "s:impl") << " " << inst << ";";
+ }
+ }
+
+ String
+ find_instance_name (String const& raw_name)
+ {
+ String base_name (escape (raw_name + L"_s"));
+ String name (base_name);
+
+ for (UnsignedLong i (1); set_.find (name) != set_.end (); ++i)
+ {
+ std::wostringstream os;
+ os << i;
+ name = base_name + os.str ();
+ }
+
+ 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 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 << 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 << 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 << 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), 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::List& l)
+ {
+ if (type_set_.find (&l) == type_set_.end ())
+ {
+ os << map_[&l] << ".serializers (" <<
+ map_[&l.argumented ().type ()] << ");"
+ << endl;
+
+ type_set_.insert (&l);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ if (type_set_.find (&c) == type_set_.end ())
+ {
+ if (has_members (c))
+ {
+ os << map_[&c] << ".serializers (";
+
+ ArgList args (*this, map_);
+ args.dispatch (c);
+
+ os << ");"
+ << endl;
+ }
+
+ type_set_.insert (&c);
+
+ inherits (c);
+
+ if (!restriction_p (c))
+ {
+ names (c);
+ contains_compositor (c);
+ }
+ }
+ }
+
+ 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_;
+ Cult::Containers::Set<SemanticGraph::Type*> type_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 GlobalElement: Traversal::Element, Context
+ {
+ GlobalElement (Context& c, SemanticGraph::Element*& element)
+ : Context (c), element_ (element)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (options.value<CLI::root_element_first> ())
+ {
+ if (element_ == 0)
+ element_ = &e;
+ }
+ else if (String name = options.value<CLI::root_element> ())
+ {
+ if (e.name () == name)
+ element_ = &e;
+ }
+ else
+ element_ = &e; // Cover root-element-last and no option.
+ }
+
+ private:
+ SemanticGraph::Element*& element_;
+ };
+ }
+
+ Void
+ generate_driver_source (Context& ctx)
+ {
+ // Figure out the root element. Validator should have made sure
+ // it is unique.
+ //
+ SemanticGraph::Element* root (0);
+ {
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+
+ schema >> sources >> schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+ RootElement global_element (ctx.options, root);
+
+ schema >> schema_names >> ns >> ns_names >> global_element;
+
+ schema.dispatch (ctx.schema_root);
+ }
+
+ String xs (ctx.xs_ns_name ());
+ std::wostream& os (ctx.os);
+
+ InstanceSet set;
+ TypeInstanceMap map;
+ SemanticGraph::Type& root_type (root->type ());
+
+ set.insert ("doc_s");
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ os << "#include <stdio.h>" << endl
+ << endl;
+ else
+ os << "#include <iostream>" << endl
+ << endl;
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ {
+ if (ctx.options.value<CLI::no_exceptions> ())
+ {
+ os << "struct writer: " << xs << "::writer"
+ << "{"
+ << "virtual bool" << endl
+ << "write (const char* s, size_t n)"
+ << "{"
+ << "return fwrite (s, n, 1, stdout) == 1;"
+ << "}"
+ << "virtual bool" << endl
+ << "flush ()"
+ << "{"
+ << "return fflush (stdout) == 0;"
+ << "}"
+ << "};";
+ }
+ else
+ {
+ os << "struct io_failure"
+ << "{"
+ << "};";
+
+ os << "struct writer: " << xs << "::writer"
+ << "{"
+ << "virtual void" << endl
+ << "write (const char* s, size_t n)"
+ << "{"
+ << "if (fwrite (s, n, 1, stdout) != 1)" << endl
+ << "throw io_failure ();"
+ << "}"
+ << "virtual void" << endl
+ << "flush ()"
+ << "{"
+ << "if (fflush (stdout) != 0)" << endl
+ << "throw io_failure ();"
+ << "}"
+ << "};";
+ }
+ }
+
+ os << "int" << endl
+ << "main ()"
+ << "{";
+
+ if (!ctx.options.value<CLI::no_exceptions> ())
+ os << "try"
+ << "{";
+
+ os << "// Instantiate individual serializers." << endl
+ << "//" << endl;
+
+ {
+ SerializerDef def (ctx, map, set);
+ def.dispatch (root_type);
+ }
+
+ os << endl
+ << "// Connect the serializers together." << endl
+ << "//" << endl;
+
+ {
+ // @@ I can simply iterate over the map instead of traversing
+ // the tree all over again.
+ //
+ SerializerConnect connect (ctx, map);
+ connect.dispatch (root_type);
+ }
+
+ String const& root_s (map[&root_type]);
+
+ os << "// Serialize the XML document." << endl
+ << "//" << endl;
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ os << "writer w;";
+
+ if (ctx.options.value<CLI::no_exceptions> ())
+ os << xs << "::serializer_error e;"
+ << endl
+ << "do"
+ << "{";
+
+ if (root->namespace_().name ())
+ os << xs << "::document_simpl doc_s (" << endl
+ << root_s << "," << endl
+ << ctx.strlit (root->namespace_().name ()) << "," << endl
+ << ctx.strlit (root->name ()) << ");"
+ << endl;
+ else
+ os << xs << "::document_simpl doc_s (" << root_s << ", " <<
+ ctx.strlit (root->name ()) << ");"
+ << endl;
+
+ if (ctx.options.value<CLI::no_exceptions> ())
+ os << "if (e = doc_s._error ())" << endl
+ << "break;"
+ << endl;
+
+ if (Context::arg_type (root->type ()) != L"void")
+ os << "// TODO: pass the " << root->name () << " element data " <<
+ "to pre()" << endl
+ << "//" << endl;
+
+ os << root_s << ".pre ();"
+ << endl;
+
+ if (ctx.options.value<CLI::no_exceptions> ())
+ os << "if (e = " << root_s << "._error ())" << endl
+ << "break;"
+ << endl;
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ os << "doc_s.serialize (w);"
+ << endl;
+ else
+ os << "doc_s.serialize (std::cout);"
+ << endl;
+
+ if (ctx.options.value<CLI::no_exceptions> ())
+ os << "if (e = doc_s._error ())" << endl
+ << "break;"
+ << endl;
+
+ os << root_s << ".post ();";
+
+ if (ctx.options.value<CLI::no_exceptions> ())
+ os << endl
+ << "e = " << root_s << "._error ();";
+
+ if (ctx.options.value<CLI::no_exceptions> ())
+ os << "}"
+ << "while (false);"
+ << endl;
+
+ // Error handling.
+ //
+
+ if (ctx.options.value<CLI::no_exceptions> ())
+ {
+ os << "// Handle errors." << endl
+ << "//" << endl
+ << "if (e)"
+ << "{"
+ << "switch (e.type ())"
+ << "{"
+ << "case " << xs << "::serializer_error::sys:"
+ << "{";
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ os << "fprintf (stderr, \"%s\\n\", e.sys_text ());";
+ else
+ os << "std::cerr << e.sys_text () << std::endl;";
+
+ os << "break;"
+ << "}"
+ << "case " << xs << "::serializer_error::xml:"
+ << "{";
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ os << "fprintf (stderr, \"%s\\n\", e.xml_text ());";
+ else
+ os << "std::cerr << e.xml_text () << std::endl;";
+
+ os << "break;"
+ << "}";
+
+ if (!ctx.options.value<CLI::suppress_validation> ())
+ {
+ os << "case " << xs << "::serializer_error::schema:"
+ << "{";
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ os << "fprintf (stderr, \"%s\\n\", e.schema_text ());";
+ else
+ os << "std::cerr << e.schema_text () << std::endl;";
+
+ os << "break;"
+ << "}";
+ }
+
+ os << "case " << xs << "::serializer_error::app:"
+ << "{";
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ os << "fprintf (stderr, \"application error %d\\n\", e.app_code ());";
+ else
+ os << "std::cerr << \"application error \" << e.app_code () " <<
+ "<< std::endl;";
+
+ os << "break;"
+ << "}"
+ << "default:"
+ << "{"
+ << "break;"
+ << "}"
+ << "}" //switch
+ << "return 1;"
+ << "}"; // if (e)
+ }
+ else
+ {
+ os << "}" // try
+ << "catch (const " << xs << "::serializer_exception& e)"
+ << "{";
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ os << "fprintf (stderr, \"error: %s\\n\", e.text ());";
+ else
+ os << "std::cerr << \"error: \" << e.text () << std::endl;";
+
+ os << "return 1;"
+ << "}";
+
+ if (ctx.options.value<CLI::no_iostream> ())
+ os << "catch (const io_failure&)"
+ << "{"
+ << "fprintf (stderr, \"error: write failure\\n\");"
+ << "return 1;"
+ << "}";
+ else
+ os << "catch (const std::ios_base::failure&)"
+ << "{"
+ << "std::cerr << \"error: write failure\" << std::endl;"
+ << "return 1;"
+ << "}";
+ }
+
+ os << "return 0;"
+ << "}"; // main
+ }
+ }
+}
diff --git a/xsde/cxx/serializer/driver-source.hxx b/xsde/cxx/serializer/driver-source.hxx
new file mode 100644
index 0000000..b29cf34
--- /dev/null
+++ b/xsde/cxx/serializer/driver-source.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/serializer/driver-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_SERIALIZER_DRIVER_SOURCE_HXX
+#define CXX_SERIALIZER_DRIVER_SOURCE_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/serializer/elements.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ Void
+ generate_driver_source (Context&);
+ }
+}
+
+#endif // CXX_SERIALIZER_DRIVER_SOURCE_HXX
diff --git a/xsde/cxx/serializer/element-validation-source.cxx b/xsde/cxx/serializer/element-validation-source.cxx
new file mode 100644
index 0000000..fd0dfb4
--- /dev/null
+++ b/xsde/cxx/serializer/element-validation-source.cxx
@@ -0,0 +1,903 @@
+// file : xsde/cxx/serializer/element-validation-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/serializer/element-validation-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ namespace
+ {
+ struct AnyTest: Traversal::Any, Context
+ {
+ AnyTest (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ String const& ns (a.definition_namespace ().name ());
+
+ for (SemanticGraph::Any::NamespaceIterator i (a.namespace_begin ()),
+ e (a.namespace_end ()); i != e;)
+ {
+ if (*i == L"##any")
+ {
+ if (stl)
+ os << "!name.empty ()";
+ else
+ os << "(name != 0 && *name != '\\0')";
+ }
+ else if (*i == L"##other")
+ {
+ if (ns)
+ {
+ // Note that here I assume that ##other does not include
+ // unqualified names in a schema with target namespace.
+ // This is not what the spec says but that seems to be
+ // the consensus.
+ //
+ if (stl)
+ os << "(!ns.empty () && ns != " << strlit (ns) << ")";
+ else
+ os << "(ns != 0 && *ns != '\\0' && " <<
+ "strcmp (ns, " << strlit (ns) << ") != 0)";
+ }
+ else
+ {
+ if (stl)
+ os << "!ns.empty ()";
+ else
+ os << "(ns != 0 && *ns != '\\0')";
+ }
+ }
+ else if (*i == L"##local")
+ {
+ if (stl)
+ os << "(ns.empty () && !name.empty ())";
+ else
+ os << "((ns == 0 || *ns == '\\0') && " <<
+ "name != 0 && *name != '\\0')";
+ }
+ else if (*i == L"##targetNamespace")
+ {
+ if (stl)
+ os << "ns == " << strlit (ns);
+ else
+ os << "(ns != 0 && strcmp (ns, " << strlit (ns) << ") == 0)";
+ }
+ else
+ {
+ if (stl)
+ os << "ns == " << strlit (*i);
+ else
+ os << "(ns != 0 && strcmp (ns, " << strlit (*i) << ") == 0)";
+ }
+
+ if (++i != e)
+ os << " ||" << endl;
+ }
+ }
+ };
+
+ struct Compositor: Traversal::All,
+ Traversal::Choice,
+ Traversal::Sequence,
+ Context
+ {
+ Compositor (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ // For the all compositor, maxOccurs=1 and minOccurs={0,1}.
+ //
+ UnsignedLong min (a.min ());
+
+ if (min == 0)
+ os << "if (this->" << epresent (a) << " ())"
+ << "{";
+
+ Traversal::All::traverse (a);
+
+ if (min == 0)
+ {
+ os << "}";
+
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+ }
+
+ 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 << "if (this->" << epresent (c) << " ())"
+ << "{";
+ }
+ else if (max != 1)
+ {
+ // We only need to count if max != unbounded || min != 0.
+ //
+ if (max != 0 || min != 0)
+ {
+ os << "{"
+ << "size_t i = 0;"
+ << "for (; ";
+
+ if (max != 0)
+ os << "i < " << max << "UL && ";
+
+ os << "this->" << enext (c) << " (); ++i)"
+ << "{";
+ }
+ else
+ os << "while (this->" << enext (c) << " ())"
+ << "{";
+ }
+ else if (!exceptions)
+ {
+ // Only sequence can have several choice compositors in a row.
+ //
+ os << "{";
+ }
+
+ if (exceptions)
+ os << "switch (this->" << earm (c) << " ())";
+ else
+ os << earm_tag (c) << " t = this->" << earm (c) << " ();"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl
+ << "switch (t)";
+
+
+ os << "{";
+
+ for (SemanticGraph::Choice::ContainsIterator
+ i (c.contains_begin ()); i != c.contains_end (); ++i)
+ {
+ os << "case " << etag (i->particle ()) << ":"
+ << "{";
+
+ edge_traverser ().dispatch (*i);
+
+ os << "break;"
+ << "}";
+ }
+
+ os << "default:"
+ << "{"
+ << "this->_schema_error (" <<
+ "::xsde::cxx::schema_error::unexpected_element);"
+ << "return;"
+ << "}"
+ << "}"; // switch
+
+ if (min == 0 && max == 1)
+ {
+ os << "}";
+
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+ else if (max != 1)
+ {
+ os << "}";
+
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ if (max != 0 || min != 0)
+ {
+ if (min != 0)
+ {
+ os << "if (i < " << min << "UL)"
+ << "{"
+ << "this->_schema_error (" <<
+ "::xsde::cxx::schema_error::expected_element);"
+ << "return;"
+ << "}";
+ }
+
+ os << "}";
+ }
+ }
+ else if (!exceptions)
+ {
+ os << "}";
+ }
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ UnsignedLong min (s.min ()), max (s.max ());
+
+ if (min == 0 && max == 1)
+ {
+ os << "if (this->" << epresent (s) << " ())"
+ << "{";
+ }
+ else if (max != 1)
+ {
+ // We only need to count if max != unbounded || min != 0.
+ //
+ if (max != 0 || min != 0)
+ {
+ os << "{"
+ << "size_t i = 0;"
+ << "for (; ";
+
+ if (max != 0)
+ os << "i < " << max << "UL && ";
+
+ os << "this->" << enext (s) << " (); ++i)"
+ << "{";
+ }
+ else
+ os << "while (this->" << enext (s) << " ())"
+ << "{";
+ }
+
+ Traversal::Sequence::traverse (s);
+
+ if (min == 0 && max == 1)
+ {
+ os << "}";
+
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+ else if (max != 1)
+ {
+ os << "}";
+
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ if (max != 0 || min != 0)
+ {
+ if (min != 0)
+ {
+ os << "if (i < " << min << "UL)"
+ << "{"
+ << "this->_schema_error (" <<
+ "::xsde::cxx::schema_error::expected_element);"
+ << "return;"
+ << "}";
+ }
+
+ os << "}";
+ }
+ }
+ }
+ };
+
+ struct Particle: Traversal::Element,
+ Traversal::Any,
+ Context
+ {
+ Particle (Context& c)
+ : Context (c), any_test_ (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ UnsignedLong min (e.min ()), max (e.max ());
+
+ String const& name (ename (e));
+
+ os << "// " << name << endl
+ << "//" << endl;
+
+ if (min == 0 && max == 1)
+ {
+ os << "if (this->" << epresent (e) << " ())";
+ }
+ else if (max != 1)
+ {
+ // We only need to count if max != unbounded || min != 0.
+ //
+ if (max != 0 || min != 0)
+ {
+ os << "{"
+ << "size_t i = 0;"
+ << "for (; ";
+
+ if (max != 0)
+ os << "i < " << max << "UL && ";
+
+ os << "this->" << enext (e) << " (); ++i)";
+ }
+ else
+ os << "while (this->" << enext (e) << " ())";
+ }
+
+ os << "{";
+
+ String const& ret (ret_type (e.type ()));
+ String const& arg (arg_type (e.type ()));
+ String fq_type (fq_name (e.type ()));
+
+ Boolean poly (poly_code && !anonymous (e.type ()));
+ String inst (poly ? String (L"s") : L"this->" + emember (e));
+
+ if (poly)
+ os << "ctx.type_id (0);";
+
+ if (ret == L"void")
+ os << "this->" << name << " ();"
+ << endl;
+ else
+ os << arg << " r = this->" << name << " ();"
+ << endl;
+
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ if (poly)
+ {
+ // In case of mixin we use virtual inheritance and only
+ // dynamic_cast can be used.
+ //
+ String cast (mixin ? L"dynamic_cast" : L"static_cast");
+
+ os << "const void* t = ctx.type_id ();"
+ << "const char* dt = 0;"
+ << fq_type << "* " << inst << " = 0;"
+ << endl
+ << "if (t == 0 && this->" << emember (e) << " != 0)" << endl
+ << inst << " = this->" << emember (e) << ";"
+ << "else if (this->" << emember_map (e) << " != 0)"
+ << "{"
+ << serializer_base << "* b = this->" << emember_map (e) <<
+ "->find (t);"
+ << endl
+ << "if (b != 0)"
+ << "{"
+ << "dt = b->_dynamic_type ();"
+ << "const char* st = " << fq_type << "::_static_type ();"
+ << endl
+ << "if (strcmp (dt, st) == 0)" << endl
+ << "dt = 0;"
+ << endl;
+
+ // Check that the types are related by inheritance.
+ //
+ os << "if (dt != 0 && !::xsde::cxx::serializer::validating::" <<
+ "inheritance_map_instance ().check (dt, st))"
+ << "{"
+ << "ctx.schema_error (::xsde::cxx::schema_error::not_derived);"
+ << "return;"
+ << "}";
+
+ os << inst << " = " << cast << "< " << fq_type << "* > (b);"
+ << "}"
+ << "}";
+ }
+
+ os << "if (" << inst << ")"
+ << "{";
+
+ if (ret == L"void")
+ os << inst << "->pre ();";
+ else
+ os << inst << "->pre (r);";
+
+ if (!exceptions)
+ {
+ // Note that after pre() we need to check both parser and
+ // context error states because of the recursive parsing.
+ //
+ os << endl
+ << "if (" << inst << "->_error_type ())" << endl
+ << inst << "->_copy_error (ctx);"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+
+ // Only a globally-defined element can be a subst-group root.
+ //
+ if (poly && e.global ())
+ {
+ if (e.qualified () && e.namespace_ ().name ())
+ os << "const char* ns = " <<
+ strlit (e.namespace_ ().name ()) << ";";
+ else
+ os << "const char* ns = 0;";
+
+ os << "const char* n = " << strlit (e.name ()) << ";"
+ << endl;
+
+ os << "if (dt != 0 && " <<
+ "::xsde::cxx::serializer::substitution_map_instance ()" <<
+ ".check (ns, n, dt))" << endl
+ << "dt = 0;"
+ << endl;
+
+ if (exceptions)
+ {
+ os << "if (ns != 0)" << endl
+ << "this->_start_element (ns, n);"
+ << "else" << endl
+ << "this->_start_element (n);"
+ << endl;
+ }
+ else
+ {
+ os << "if (ns != 0)"
+ << "{"
+ << "if (!this->_start_element (ns, n))" << endl
+ << "return;"
+ << "}"
+ << "else"
+ << "{"
+ << "if (!this->_start_element (n))" << endl
+ << "return;"
+ << "}";
+ }
+ }
+ else
+ {
+ if (exceptions)
+ {
+ if (e.qualified () && e.namespace_ ().name ())
+ os << "this->_start_element (" <<
+ strlit (e.namespace_ ().name ()) << ", " <<
+ strlit (e.name ()) << ");";
+ else
+ os << "this->_start_element (" << strlit (e.name ()) << ");";
+ }
+ else
+ {
+ os << "if (!";
+
+ if (e.qualified () && e.namespace_ ().name ())
+ os << "this->_start_element (" <<
+ strlit (e.namespace_ ().name ()) << ", " <<
+ strlit (e.name ()) << ")";
+ else
+ os << "this->_start_element (" << strlit (e.name ()) << ")";
+
+ os << ")" << endl
+ << "return;"
+ << endl;
+ }
+ }
+
+ if (poly)
+ {
+ // Set xsi:type if necessary.
+ //
+ if (exceptions)
+ os << "if (dt != 0)" << endl
+ << "this->_set_type (dt);"
+ << endl;
+ else
+ os << "if (dt != 0)"
+ << "{"
+ << "if (!this->_set_type (dt))" << endl
+ << "return;"
+ << "}";
+ }
+
+ os << inst << "->_pre_impl (ctx);";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ os << inst << "->_serialize_attributes ();";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ os << inst << "->_serialize_content ();";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ os << inst << "->_post_impl ();";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ if (exceptions)
+ os << "this->_end_element ();";
+ else
+ os << "if (!this->_end_element ())" << endl
+ << "return;"
+ << endl;
+
+ os << inst << "->post ();";
+
+ if (!exceptions)
+ {
+ // Note that after post() we need to check both parser and
+ // context error states because of the recursive parsing.
+ //
+ os << endl
+ << "if (" << inst << "->_error_type ())" << endl
+ << inst << "->_copy_error (ctx);"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;";
+ }
+
+ os << "}"; // if (inst)
+
+ if (min != 0)
+ {
+ os << "else"
+ << "{"
+ << "this->_schema_error (" <<
+ "::xsde::cxx::schema_error::expected_element);"
+ << "return;"
+ << "}";
+ }
+
+ os << "}";
+
+ if (min == 0 && max == 1)
+ {
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+ else if (max != 1)
+ {
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ if (max != 0 || min != 0)
+ {
+ if (min != 0)
+ {
+ os << "if (i < " << min << "UL)"
+ << "{"
+ << "this->_schema_error (" <<
+ "::xsde::cxx::schema_error::expected_element);"
+ << "return;"
+ << "}";
+ }
+
+ os << "}";
+ }
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ UnsignedLong min (a.min ()), max (a.max ());
+
+ if (min == 0 && max == 1)
+ {
+ os << "if (this->" << epresent (a) << " ())";
+
+ }
+ else if (max != 1)
+ {
+ // We only need to count if max != unbounded || min != 0.
+ //
+ if (max != 0 || min != 0)
+ {
+ os << "{"
+ << "size_t i = 0;"
+ << "for (; ";
+
+ if (max != 0)
+ os << "i < " << max << "UL && ";
+
+ os << "this->" << enext (a) << " (); ++i)";
+ }
+ else
+ os << "while (this->" << enext (a) << " ())";
+ }
+
+ os << "{";
+
+ if (stl)
+ {
+ os << "::std::string ns, name;"
+ << "this->" << ename (a) << " (ns, name);"
+ << endl;
+
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ os << "if (";
+
+ any_test_.dispatch (a);
+
+ os << ")"
+ << "{";
+
+ os << "if (ns.empty ())"
+ << "{";
+
+ if (exceptions)
+ os << "this->_start_element (name.c_str ());";
+ else
+ os << "if (!this->_start_element (name.c_str ()))" << endl
+ << "return;";
+
+ os << "}"
+ << "else"
+ << "{";
+
+ if (exceptions)
+ os << "this->_start_element (ns.c_str (), name.c_str ());";
+ else
+ os << "if (!this->_start_element (ns.c_str (), " <<
+ "name.c_str ()))" << endl
+ << "return;";
+
+ os << "}"
+ << "this->" << eserialize (a) << " ();"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ if (exceptions)
+ os << "this->_end_element ();";
+ else
+ os << "if (!this->_end_element ())" << endl
+ << "return;";
+
+ os << "}" // test
+ << "else"
+ << "{"
+ << "this->_schema_error (" <<
+ "::xsde::cxx::schema_error::unexpected_element);"
+ << "return;"
+ << "}";
+ }
+ else
+ {
+ os << "const char* ns = 0;"
+ << "const char* name;"
+ << "bool free;"
+ << "this->" << ename (a) << " (ns, name, free);"
+ << endl;
+
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ else
+ os << "::xsde::cxx::string auto_ns, auto_name;"
+ << "if (free)"
+ << "{"
+ << "auto_ns.attach (const_cast< char* > (ns));"
+ << "auto_name.attach (const_cast< char* > (name));"
+ << "}";
+
+ os << "if (";
+
+ any_test_.dispatch (a);
+
+ os << ")"
+ << "{";
+
+ if (exceptions)
+ os << "if (ns == 0 || *ns == '\\0')" << endl
+ << "this->_start_element (name);"
+ << "else" << endl
+ << "this->_start_element (ns, name);"
+ << endl;
+ else
+ os << "bool r;"
+ << "if (ns == 0 || *ns == '\\0')" << endl
+ << "r = this->_start_element (name);"
+ << "else" << endl
+ << "r = this->_start_element (ns, name);"
+ << endl
+ << "if (free)"
+ << "{"
+ << "delete[] ns;"
+ << "delete[] name;"
+ << "}"
+ << "if (!r)" << endl
+ << "return;"
+ << endl;
+
+ os << "this->" << eserialize (a) << " ();"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ if (exceptions)
+ os << "this->_end_element ();";
+ else
+ os << "if (!this->_end_element ())" << endl
+ << "return;";
+
+ os << "}" // test
+ << "else"
+ << "{"
+ << "this->_schema_error (" <<
+ "::xsde::cxx::schema_error::unexpected_element);"
+ << "return;"
+ << "}";
+ }
+
+ os << "}";
+
+ if (min == 0 && max == 1)
+ {
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+ else if (max != 1)
+ {
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ if (max != 0 || min != 0)
+ {
+ if (min != 0)
+ {
+ os << "if (i < " << min << "UL)"
+ << "{"
+ << "this->_schema_error (" <<
+ "::xsde::cxx::schema_error::expected_element);"
+ << "return;"
+ << "}";
+ }
+
+ os << "}";
+ }
+ }
+ }
+
+ private:
+ AnyTest any_test_;
+ };
+
+ //
+ //
+ struct Complex : Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c),
+ compositor_ (c),
+ particle_ (c)
+ {
+ contains_compositor_ >> compositor_;
+ compositor_ >> contains_particle_;
+ contains_particle_ >> compositor_;
+ contains_particle_ >> particle_;
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ if (!has<Traversal::Element> (c) &&
+ !has_particle<Traversal::Any> (c))
+ return;
+
+ // Don't use restriction_p here since we don't want special
+ // treatment of anyType.
+ //
+ Boolean restriction (
+ c.inherits_p () &&
+ c.inherits ().is_a<SemanticGraph::Restricts> ());
+
+ String const& name (ename (c));
+
+ os <<"// Element validation and serialization for " <<
+ name << "." << endl
+ <<"//" << endl;
+
+ os << "void " << name << "::" << endl
+ << "_serialize_content ()"
+ << "{"
+ << "::xsde::cxx::serializer::context& ctx = this->_context ();"
+ << endl;
+
+ if (c.inherits_p () && !restriction)
+ {
+ // We cannot use the fully-qualified base name directly
+ // because of some broken compilers (EVC 4.0).
+ //
+ String base (unclash (name, "base"));
+
+ os << "typedef " << fq_name (c.inherits ().base ()) << " " <<
+ base << ";"
+ << base << "::_serialize_content ();"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+
+ contains_compositor (c, contains_compositor_);
+
+ os << "}";
+ }
+
+ private:
+ Compositor compositor_;
+ Particle particle_;
+ Traversal::ContainsCompositor contains_compositor_;
+ Traversal::ContainsParticle contains_particle_;
+ };
+ }
+
+ Void
+ generate_element_validation_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;
+
+ Complex complex (ctx);
+
+ names >> complex;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+}
diff --git a/xsde/cxx/serializer/element-validation-source.hxx b/xsde/cxx/serializer/element-validation-source.hxx
new file mode 100644
index 0000000..5649457
--- /dev/null
+++ b/xsde/cxx/serializer/element-validation-source.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/serializer/element-validation-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_SERIALIZER_ELEMENT_VALIDATION_SOURCE_HXX
+#define CXX_SERIALIZER_ELEMENT_VALIDATION_SOURCE_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/serializer/elements.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ Void
+ generate_element_validation_source (Context&);
+ }
+}
+
+#endif // CXX_SERIALIZER_ELEMENT_VALIDATION_SOURCE_HXX
diff --git a/xsde/cxx/serializer/elements.cxx b/xsde/cxx/serializer/elements.cxx
new file mode 100644
index 0000000..f130254
--- /dev/null
+++ b/xsde/cxx/serializer/elements.cxx
@@ -0,0 +1,278 @@
+// file : xsde/cxx/serializer/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/serializer/elements.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ Context::
+ Context (std::wostream& o,
+ SemanticGraph::Schema& root,
+ CLI::Options const& ops,
+ Regex const* he,
+ Regex const* ie,
+ Regex const* hie)
+ : CXX::Context (o,
+ root,
+ "s: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),
+ xml_serializer (xml_serializer_),
+ serializer_base (serializer_base_),
+ simple_base (simple_base_),
+ complex_base (complex_base_),
+ serializer_map (serializer_map_),
+ validation (!ops.value<CLI::suppress_validation> ()),
+ exceptions (!ops.value<CLI::no_exceptions> ()),
+ stl (!ops.value<CLI::no_stl> ()),
+ poly_code (ops.value<CLI::generate_polymorphic> ()),
+ poly_runtime (poly_code || ops.value<CLI::runtime_polymorphic> ()),
+ reset (!ops.value<CLI::suppress_reset> ()),
+ mixin (ops.value<CLI::reuse_style_mixin> ()),
+ tiein (!mixin && !ops.value<CLI::reuse_style_none> ()),
+ hxx_expr (he),
+ ixx_expr (ie),
+ hxx_impl_expr (hie),
+ xml_serializer_ ("genx")
+ {
+ String xs_ns (xs_ns_name ());
+
+ string_type = L"::xsde::cxx::ro_string";
+
+ serializer_base_ = xs_ns + L"::serializer_base";
+
+ simple_base_ = L"::xsde::cxx::serializer::";
+ simple_base_ += (validation ? L"validating" : L"non_validating");
+ simple_base_ += L"::simple_content";
+
+ complex_base_ = L"::xsde::cxx::serializer::";
+ complex_base_ += (validation ? L"validating" : L"non_validating");
+ complex_base_ += L"::complex_content";
+
+ if (poly_code)
+ serializer_map_ = xs_ns + L"::serializer_map";
+ }
+
+ String Context::
+ real_fq_name (SemanticGraph::Nameable& n)
+ {
+ SemanticGraph::Context& c (n.context ());
+
+ if (c.count ("s:real-name"))
+ return c.get<String> ("s:real-name");
+ else
+ return fq_name (n);
+ }
+
+ Content::Value Context::
+ content (SemanticGraph::Complex& c)
+ {
+ using namespace SemanticGraph;
+
+ if (c.mixed ())
+ return Content::mixed;
+
+ if (c.inherits_p ())
+ {
+ Type& base (c.inherits ().base ());
+
+ if (Complex* cb = dynamic_cast<Complex*> (&base))
+ return content (*cb);
+
+ if (base.is_a<AnyType> ())
+ return Content::complex;
+
+ // Everyhting else (built-in type and AnySimpleType) is simple
+ // content.
+ //
+ return Content::simple;
+ }
+ else
+ return Content::complex;
+ }
+
+ String const& Context::
+ ret_type (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("s:ret-type");
+ }
+
+ String const& Context::
+ arg_type (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("s:arg-type");
+ }
+
+ //
+ //
+ String const& Context::
+ epresent (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("s:present");
+ }
+
+ String const& Context::
+ epresent (SemanticGraph::Attribute& a)
+ {
+ return a.context ().get<String> ("s:present");
+ }
+
+ String const& Context::
+ enext (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("s:next");
+ }
+
+ String const& Context::
+ enext (SemanticGraph::AnyAttribute& a)
+ {
+ return a.context ().get<String> ("s:next");
+ }
+
+ String const& Context::
+ etag (SemanticGraph::Particle& p)
+ {
+ return p.context ().get<String> ("s:tag");
+ }
+
+ String const& Context::
+ earm (SemanticGraph::Choice& c)
+ {
+ return c.context ().get<String> ("s:arm");
+ }
+
+ String const& Context::
+ earm_tag (SemanticGraph::Choice& c)
+ {
+ return c.context ().get<String> ("s:arm-tag");
+ }
+
+ //
+ //
+ String const& Context::
+ eserializer (SemanticGraph::Member& m)
+ {
+ return m.context ().get<String> ("s:serializer");
+ }
+
+ String const& Context::
+ emember (SemanticGraph::Member& m)
+ {
+ return m.context ().get<String> ("s:member");
+ }
+
+ String const& Context::
+ emember_map (SemanticGraph::Member& m)
+ {
+ return m.context ().get<String> ("s:member-map");
+ }
+
+ String const& Context::
+ etiein (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("s:tiein");
+ }
+
+ //
+ //
+ String const& Context::
+ eserialize (SemanticGraph::Any& a)
+ {
+ return a.context ().get<String> ("s:serialize");
+ }
+
+ String const& Context::
+ eserialize (SemanticGraph::AnyAttribute& a)
+ {
+ return a.context ().get<String> ("s:serialize");
+ }
+
+ //
+ //
+ String const& Context::
+ eimpl (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("s:impl");
+ }
+
+ // Includes
+ //
+ Void TypeForward::
+ traverse (SemanticGraph::Type& t)
+ {
+ os << "class " << t.context ().get<String> (name_key_) << ";";
+ }
+
+ Void Includes::
+ traverse_ (SemanticGraph::Uses& u)
+ {
+ // Support for weak (forward) inclusion used in the file-per-type
+ // compilation model.
+ //
+ Boolean weak (u.context ().count ("weak"));
+
+ if (weak && (type_ == header || type_ == impl_header))
+ {
+ // Generate forward declarations. We don't really need them
+ // in the impl files.
+ //
+ if (type_ == header)
+ schema_.dispatch (u.schema ());
+
+ return;
+ }
+
+ if (type_ == 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 (type_)
+ {
+ case header:
+ case source:
+ {
+ inc_path = ctx_.hxx_expr->merge (path_str);
+ break;
+ }
+ case impl_header:
+ {
+ inc_path = ctx_.hxx_impl_expr->merge (path_str);
+ break;
+ }
+ }
+
+ ctx_.os << "#include " << ctx_.process_include_path (inc_path) << endl
+ << endl;
+ }
+ }
+}
diff --git a/xsde/cxx/serializer/elements.hxx b/xsde/cxx/serializer/elements.hxx
new file mode 100644
index 0000000..c80ab5b
--- /dev/null
+++ b/xsde/cxx/serializer/elements.hxx
@@ -0,0 +1,443 @@
+// file : xsde/cxx/serializer/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_SERIALIZER_ELEMENTS_HXX
+#define CXX_SERIALIZER_ELEMENTS_HXX
+
+#include <sstream>
+
+#include <backend-elements/regex.hxx>
+
+#include <cxx/elements.hxx>
+
+#include <cxx/serializer/cli.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ struct Content
+ {
+ enum Value
+ {
+ simple,
+ complex,
+ mixed
+ };
+ };
+
+ //
+ //
+ class Context: public CXX::Context
+ {
+ public:
+ typedef BackendElements::Regex::Expression<Char> Regex;
+
+ public:
+ Context (std::wostream&,
+ SemanticGraph::Schema&,
+ CLI::Options const&,
+ Regex const* hxx_expr,
+ Regex const* ixx_expr,
+ Regex const* hxx_impl_expr);
+
+ protected:
+ Context (Context& c)
+ : CXX::Context (c),
+ options (c.options),
+ xml_serializer (c.xml_serializer),
+ serializer_base (c.serializer_base),
+ simple_base (c.simple_base),
+ complex_base (c.complex_base),
+ serializer_map (c.serializer_map),
+ validation (c.validation),
+ 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),
+ hxx_expr (c.hxx_expr),
+ ixx_expr (c.ixx_expr),
+ hxx_impl_expr (c.hxx_impl_expr)
+ {
+ }
+
+ Context (Context& c, std::wostream& o)
+ : CXX::Context (c, o),
+ options (c.options),
+ xml_serializer (c.xml_serializer),
+ serializer_base (c.serializer_base),
+ simple_base (c.simple_base),
+ complex_base (c.complex_base),
+ serializer_map (c.serializer_map),
+ validation (c.validation),
+ 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),
+ hxx_expr (c.hxx_expr),
+ ixx_expr (c.ixx_expr),
+ hxx_impl_expr (c.hxx_impl_expr)
+ {
+ }
+
+ 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;
+ }
+
+ // Real (e.g., non-typedef) fq-name.
+ //
+ String
+ real_fq_name (SemanticGraph::Nameable& n);
+
+ public:
+ static Content::Value
+ content (SemanticGraph::Complex&);
+
+ public:
+ static String const&
+ ret_type (SemanticGraph::Type&);
+
+ static String const&
+ arg_type (SemanticGraph::Type&);
+
+ public:
+ // Optional.
+ //
+ static String const&
+ epresent (SemanticGraph::Particle&);
+
+ static String const&
+ epresent (SemanticGraph::Attribute&);
+
+ // Sequence.
+ //
+ static String const&
+ enext (SemanticGraph::Particle&);
+
+ static String const&
+ enext (SemanticGraph::AnyAttribute&);
+
+ // Choice.
+ //
+ static String const&
+ etag (SemanticGraph::Particle&);
+
+ static String const&
+ earm (SemanticGraph::Choice&);
+
+ static String const&
+ earm_tag (SemanticGraph::Choice&);
+
+ public:
+ static String const&
+ eserializer (SemanticGraph::Member&);
+
+ static String const&
+ emember (SemanticGraph::Member&);
+
+ static String const&
+ emember_map (SemanticGraph::Member&);
+
+ static String const&
+ etiein (SemanticGraph::Type&);
+
+ // serialize_*
+ //
+ public:
+ static String const&
+ eserialize (SemanticGraph::Any&);
+
+ static String const&
+ eserialize (SemanticGraph::AnyAttribute&);
+
+ public:
+ static String const&
+ eimpl (SemanticGraph::Type&);
+
+ public:
+ CLI::Options const& options;
+ String& xml_serializer;
+ String& serializer_base;
+ String& simple_base;
+ String& complex_base;
+ String& serializer_map;
+
+ Boolean validation;
+ Boolean exceptions;
+ Boolean stl;
+ Boolean poly_code;
+ Boolean poly_runtime;
+ Boolean reset;
+ Boolean mixin;
+ Boolean tiein;
+
+ Regex const* hxx_expr;
+ Regex const* ixx_expr;
+ Regex const* hxx_impl_expr;
+
+ private:
+ String xml_serializer_;
+ String serializer_base_;
+ String simple_base_;
+ String complex_base_;
+ String serializer_map_;
+ };
+
+ //
+ //
+ struct RequiredAttributeTest: Traversal::Attribute
+ {
+ RequiredAttributeTest (Boolean& result)
+ : result_ (result)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ if (!result_ && !a.optional ())
+ result_ = true;
+ }
+
+ private:
+ Boolean& result_;
+ };
+
+
+ //
+ //
+ struct ParticleParamDecl: Traversal::Element, Context
+ {
+ ParticleParamDecl (Context& c, Boolean& first, Boolean name_arg)
+ : Context (c), first_ (first), name_arg_ (name_arg)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (!first_)
+ os << "," << endl;
+ else
+ first_ = false;
+
+ os << fq_name (e.type ()) << "&";
+
+ if (name_arg_)
+ os << " " << ename (e);
+ else
+ os << " /* " << comment (e.name ()) << " */";
+ }
+
+ private:
+ Boolean& first_;
+ Boolean name_arg_;
+ };
+
+ struct AttributeParamDecl: Traversal::Attribute, Context
+ {
+ AttributeParamDecl (Context& c, Boolean& first, Boolean name_arg)
+ : Context (c), first_ (first), name_arg_ (name_arg)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ if (!first_)
+ os << "," << endl;
+ else
+ first_ = false;
+
+ os << fq_name (a.type ()) << "&";
+
+ if (name_arg_)
+ os << " " << ename (a);
+ else
+ os << " /* " << comment (a.name ()) << " */";
+ }
+
+ private:
+ Boolean& first_;
+ Boolean name_arg_;
+ };
+
+ struct SerializerParamDecl : Traversal::Complex,
+ Traversal::List,
+ Context
+ {
+ SerializerParamDecl (Context& c, Boolean name_arg)
+ : Context (c),
+ particle_ (c, first_, name_arg),
+ attribute_ (c, first_, name_arg),
+ first_ (true),
+ name_arg_ (name_arg)
+ {
+ inherits_ >> *this;
+
+ contains_compositor_ >> compositor_ >> contains_particle_;
+ contains_particle_ >> particle_;
+ contains_particle_ >> compositor_;
+
+ 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 << fq_name (l.argumented ().type ()) << "&";
+
+ if (name_arg_)
+ os << " " << ename (l) << "_item";
+ else
+ os << " /* " << comment (l.name ()) << " item */";
+ }
+
+ private:
+ Traversal::Inherits inherits_;
+
+ Traversal::Compositor compositor_;
+ ParticleParamDecl particle_;
+ Traversal::ContainsCompositor contains_compositor_;
+ Traversal::ContainsParticle contains_particle_;
+
+ AttributeParamDecl attribute_;
+ Traversal::Names names_;
+
+ Boolean first_;
+ Boolean name_arg_;
+ };
+
+ //
+ //
+ struct TypeForward: Traversal::Type, Context
+ {
+ TypeForward (Context& c, Char const* name_key)
+ : Context (c), name_key_ (name_key)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& t);
+
+ private:
+ Char const* name_key_;
+ };
+
+ struct Includes : Traversal::Imports,
+ Traversal::Includes
+ {
+ enum Type
+ {
+ header,
+ source,
+ impl_header
+ };
+
+ Includes (Context& c, Type t)
+ : ctx_ (c),
+ type_ (t),
+ namespace_ (c),
+ type_forward_ (c, t == header ? "s:name" : "s:impl")
+ {
+ 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_;
+
+ Traversal::Schema schema_;
+ Traversal::Names schema_names_;
+ Namespace namespace_;
+ Traversal::Names names_;
+ TypeForward type_forward_;
+ };
+
+ // Find root element for the test driver.
+ //
+ struct RootElement: Traversal::Element
+ {
+ RootElement (CLI::Options const& options,
+ SemanticGraph::Element*& element)
+ : options_ (options), element_ (element)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (options_.value<CLI::root_element_first> ())
+ {
+ if (element_ == 0)
+ element_ = &e;
+ }
+ else if (String name = options_.value<CLI::root_element> ())
+ {
+ if (e.name () == name)
+ element_ = &e;
+ }
+ else
+ element_ = &e; // Cover root-element-last and no option.
+ }
+
+ private:
+ CLI::Options const& options_;
+ SemanticGraph::Element*& element_;
+ };
+ }
+}
+
+#endif // CXX_SERIALIZER_ELEMENTS_HXX
diff --git a/xsde/cxx/serializer/generator.cxx b/xsde/cxx/serializer/generator.cxx
new file mode 100644
index 0000000..c27ef09
--- /dev/null
+++ b/xsde/cxx/serializer/generator.cxx
@@ -0,0 +1,1600 @@
+// file : xsde/cxx/serializer/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 <type-map/lexer.hxx>
+#include <type-map/parser.hxx>
+
+#include <cxx/serializer/elements.hxx>
+#include <cxx/serializer/generator.hxx>
+
+#include <cxx/serializer/validator.hxx>
+#include <cxx/serializer/name-processor.hxx>
+#include <cxx/serializer/type-processor.hxx>
+
+#include <cxx/serializer/serializer-forward.hxx>
+#include <cxx/serializer/serializer-header.hxx>
+#include <cxx/serializer/serializer-inline.hxx>
+#include <cxx/serializer/serializer-source.hxx>
+
+#include <cxx/serializer/impl-header.hxx>
+#include <cxx/serializer/impl-source.hxx>
+#include <cxx/serializer/driver-source.hxx>
+
+#include <cxx/serializer/element-validation-source.hxx>
+#include <cxx/serializer/attribute-validation-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";
+
+ Char const copyright_impl[] =
+ "// Not copyrighted - public domain.\n"
+ "//\n"
+ "// This sample serializer implementation was generated by CodeSynthesis XSD/e,\n"
+ "// an XML Schema to C++ data binding compiler for embedded systems. You may\n"
+ "// use it in your programs without any restrictions.\n"
+ "//\n\n";
+ }
+
+ namespace Serializer
+ {
+ namespace CLI
+ {
+ extern Key type_map = "type-map";
+ 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 reuse_style_mixin = "reuse-style-mixin";
+ extern Key reuse_style_none = "reuse-style-none";
+ extern Key generate_inline = "generate-inline";
+ extern Key suppress_validation = "suppress-validation";
+ extern Key generate_polymorphic = "generate-polymorphic";
+ extern Key runtime_polymorphic = "runtime-polymorphic";
+ extern Key suppress_reset = "suppress-reset";
+ extern Key generate_empty_impl = "generate-empty-impl";
+ extern Key generate_test_driver = "generate-test-driver";
+ extern Key force_overwrite = "force-overwrite";
+ extern Key root_element_first = "root-element-first";
+ extern Key root_element_last = "root-element-last";
+ extern Key root_element = "root-element";
+ extern Key generate_xml_schema = "generate-xml-schema";
+ extern Key extern_xml_schema = "extern-xml-schema";
+ extern Key output_dir = "output-dir";
+ extern Key skel_type_suffix = "skel-type-suffix";
+ extern Key skel_file_suffix = "skel-file-suffix";
+ extern Key impl_type_suffix = "impl-type-suffix";
+ extern Key impl_file_suffix = "impl-file-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 hxx_regex = "hxx-regex";
+ extern Key ixx_regex = "ixx-regex";
+ extern Key cxx_regex = "cxx-regex";
+ extern Key hxx_prologue = "hxx-prologue";
+ extern Key ixx_prologue = "ixx-prologue";
+ extern Key cxx_prologue = "cxx-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 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 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 epilogue_file = "epilogue-file";
+ extern Key show_anonymous = "show-anonymous";
+ extern Key show_sloc = "show-sloc";
+ extern Key proprietary_license = "proprietary-license";
+ }
+ }
+
+ Void Serializer::Generator::
+ usage ()
+ {
+ std::wostream& e (wcerr);
+ ::CLI::Indent::Clip< ::CLI::OptionsUsage, WideChar> clip (e);
+
+ e << "--type-map <mapfile>" << endl
+ << " Read XML Schema to C++ type mapping information\n"
+ << " from <mapfile>. Repeat this option to specify\n"
+ << " several type maps. Type maps are considered in\n"
+ << " order of appearance and the first match is used."
+ << endl;
+
+ 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 << "--reuse-style-mixin" << endl
+ << " Generate code that supports the mixin base\n"
+ << " serializer implementation reuse style."
+ << endl;
+
+ e << "--reuse-style-none" << endl
+ << " Do not generate any support for base serializer\n"
+ << " implementation reuse."
+ << endl;
+
+ e << "--generate-inline" << endl
+ << " Generate certain functions inline."
+ << endl;
+
+ e << "--suppress-validation" << endl
+ << " Suppress the generation of validation code."
+ << endl;
+
+ e << "--generate-polymorphic" << endl
+ << " Generate polymorphism-aware code. Specify this\n"
+ << " option if you use substitution groups or xsi:type."
+ << endl;
+
+ e << "--runtime-polymorphic" << endl
+ << " Generate non-polymorphic code that uses the\n"
+ << " runtime library configured with polymorphism\n"
+ << " support."
+ << endl;
+
+ e << "--suppress-reset" << endl
+ << " Suppress the generation of serializer reset code."
+ << endl;
+
+ e << "--generate-empty-impl" << endl
+ << " Generate a sample serializer implementation with\n"
+ << " empty function bodies."
+ << endl;
+
+ e << "--generate-test-driver" << endl
+ << " Generate a test driver for the sample serializer\n"
+ << " implementation."
+ << endl;
+
+ e << "--force-overwrite" << endl
+ << " Force overwriting of the existing implementation\n"
+ << " and test driver files."
+ << endl;
+
+ e << "--root-element-first" << endl
+ << " Indicate that the first global element is the\n"
+ << " document root."
+ << endl;
+
+ e << "--root-element-last" << endl
+ << " Indicate that the last global element is the\n"
+ << " document root."
+ << endl;
+
+ e << "--root-element <element>" << endl
+ << " Indicate that <element> is the document root."
+ << endl;
+
+ e << "--generate-xml-schema" << endl
+ << " Generate a C++ header file 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 << "--output-dir <dir>" << endl
+ << " Write generated files to <dir> instead of the\n"
+ << " current directory."
+ << endl;
+
+ e << "--skel-type-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '_sskel' to\n"
+ << " construct the names of generated serializer\n"
+ << " skeletons."
+ << endl;
+
+ e << "--skel-file-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '-sskel' to\n"
+ << " construct the names of generated serializer\n"
+ << " skeleton files."
+ << endl;
+
+ e << "--impl-type-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '_simpl' to\n"
+ << " construct the names of serializer implementations\n"
+ << " for the built-in XML Schema types and sample\n"
+ << " serializer implementations."
+ << endl;
+
+ e << "--impl-file-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '-simpl' to\n"
+ << " construct the names of generated sample\n"
+ << " serializer implementation files."
+ << 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;
+
+ e << "--hxx-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '.hxx' to\n"
+ << " construct the name of the header file."
+ << endl;
+
+ e << "--ixx-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '.ixx' to\n"
+ << " construct the name of the inline file."
+ << endl;
+
+ e << "--cxx-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '.cxx' to\n"
+ << " construct the name of the source file."
+ << endl;
+
+ e << "--hxx-regex <regex>" << endl
+ << " Use <regex> to construct the name of the header\n"
+ << " file."
+ << endl;
+
+ e << "--ixx-regex <regex>" << endl
+ << " Use <regex> to construct the name of the inline\n"
+ << " file."
+ << endl;
+
+ e << "--cxx-regex <regex>" << endl
+ << " Use <regex> to construct the name of the source\n"
+ << " file."
+ << endl;
+
+
+ // Prologues.
+ //
+ e << "--hxx-prologue <text>" << endl
+ << " Insert <text> at the beginning of the header file."
+ << endl;
+
+ e << "--ixx-prologue <text>" << endl
+ << " Insert <text> at the beginning of the inline file."
+ << endl;
+
+ e << "--cxx-prologue <text>" << endl
+ << " Insert <text> at the beginning of the source 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 file."
+ << endl;
+
+ e << "--ixx-epilogue <text>" << endl
+ << " Insert <text> at the end of the inline file."
+ << endl;
+
+ e << "--cxx-epilogue <text>" << endl
+ << " Insert <text> at the end of the source 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 file."
+ << endl;
+
+ e << "--ixx-prologue-file <file>" << endl
+ << " Insert the content of the <file> at the beginning\n"
+ << " of the inline file."
+ << endl;
+
+ e << "--cxx-prologue-file <file>" << endl
+ << " Insert the content of the <file> at the beginning\n"
+ << " of the source 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 file."
+ << endl;
+
+ e << "--ixx-epilogue-file <file>" << endl
+ << " Insert the content of the <file> at the end of\n"
+ << " the inline file."
+ << endl;
+
+ e << "--cxx-epilogue-file <file>" << endl
+ << " Insert the content of the <file> at the end of\n"
+ << " the source 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;
+ }
+
+ Serializer::CLI::OptionsSpec Serializer::Generator::
+ options_spec ()
+ {
+ CLI::OptionsSpec spec;
+
+ spec.option<CLI::skel_file_suffix> ().default_value ("-sskel");
+ spec.option<CLI::skel_type_suffix> ().default_value ("_sskel");
+ spec.option<CLI::impl_file_suffix> ().default_value ("-simpl");
+ spec.option<CLI::impl_type_suffix> ().default_value ("_simpl");
+
+ spec.option<CLI::hxx_suffix> ().default_value (".hxx");
+ spec.option<CLI::ixx_suffix> ().default_value (".ixx");
+ spec.option<CLI::cxx_suffix> ().default_value (".cxx");
+
+ return spec;
+ }
+
+
+ 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 Serializer::Generator::Failed ();
+ }
+ }
+ catch (InvalidPath const&)
+ {
+ wcerr << "error: '" << path.c_str () << "' is not a valid "
+ << "filesystem path" << endl;
+
+ throw Serializer::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)
+ {
+ Cult::Containers::Vector<NarrowString> const& v (
+ primary.empty () ? def : primary);
+
+ for (Containers::Vector<NarrowString>::ConstIterator
+ i (v.begin ()), e (v.end ()); i != e; ++i)
+ {
+ os << i->c_str () << endl;
+ }
+ }
+ }
+
+
+ UnsignedLong Serializer::Generator::
+ generate (Serializer::CLI::Options const& ops,
+ Schema& schema,
+ Path const& file_path,
+ TypeMap::Namespaces& type_map,
+ Boolean gen_driver,
+ const WarningSet& disabled_warnings,
+ FileList& file_list,
+ AutoUnlinks& unlinks)
+ {
+ using std::ios_base;
+ namespace Indentation = BackendElements::Indentation;
+
+ typedef BackendElements::Regex::Expression<Char> 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;
+ }
+ }
+
+ Boolean impl (!generate_xml_schema &&
+ ops.value<CLI::generate_empty_impl> ());
+
+ Boolean driver (gen_driver && !generate_xml_schema &&
+ ops.value<CLI::generate_test_driver> ());
+
+ // Evaluate the graph for possibility of generating something useful.
+ //
+ {
+ Validator validator;
+ if (!validator.validate (
+ ops, schema, file_path, driver, disabled_warnings))
+ throw Failed ();
+ }
+
+ // Process names.
+ //
+ {
+ NameProcessor proc;
+ proc.process (ops, schema, file_path);
+ }
+
+ //
+ //
+ Boolean validation (!ops.value<CLI::suppress_validation> ());
+
+ // Read-in type maps.
+ //
+ {
+ using namespace TypeMap;
+ typedef Containers::Vector<NarrowString> Files;
+
+ Files const& files (ops.value<CLI::type_map> ());
+
+ for (Files::ConstIterator f (files.begin ()); f != files.end (); ++f )
+ {
+ NarrowInputFileStream ifs;
+ open (ifs, *f);
+
+ Lexer l (ifs, *f);
+ TypeMap::Parser p (l, *f);
+
+ if (!p.parse (type_map))
+ throw Failed ();
+ }
+
+ // Add the built-in mappings at the end.
+ //
+ String xns;
+ {
+ Context ctx (std::wcerr, schema, ops, 0, 0, 0);
+ xns = ctx.xs_ns_name ();
+ }
+
+ if (ops.value<CLI::no_stl> ())
+ {
+ TypeMap::Namespace xsd_std ("http://www\\.w3\\.org/2001/XMLSchema");
+
+ String qname (L"const " + xns + L"::qname*");
+ String string_seq (L"const " + xns + L"::string_sequence*");
+
+ xsd_std.types_push_back ("string", "const char*", "const char*");
+ xsd_std.types_push_back ("normalizedString", "const char*", "const char*");
+ xsd_std.types_push_back ("token", "const char*", "const char*");
+ xsd_std.types_push_back ("Name", "const char*", "const char*");
+ xsd_std.types_push_back ("NMTOKEN", "const char*", "const char*");
+ xsd_std.types_push_back ("NMTOKENS", string_seq, string_seq);
+ xsd_std.types_push_back ("NCName", "const char*", "const char*");
+
+ xsd_std.types_push_back ("ID", "const char*", "const char*");
+ xsd_std.types_push_back ("IDREF", "const char*", "const char*");
+ xsd_std.types_push_back ("IDREFS", string_seq, string_seq);
+
+ xsd_std.types_push_back ("language", "const char*", "const char*");
+ xsd_std.types_push_back ("anyURI", "const char*", "const char*");
+ xsd_std.types_push_back ("QName", qname, qname);
+
+ type_map.push_back (xsd_std);
+ }
+ else
+ {
+ TypeMap::Namespace xsd_std ("http://www\\.w3\\.org/2001/XMLSchema");
+
+ String qname (xns + L"::qname");
+ String string_seq (L"const " + xns + L"::string_sequence*");
+
+ xsd_std.types_push_back ("string", "::std::string");
+ xsd_std.types_push_back ("normalizedString", "::std::string");
+ xsd_std.types_push_back ("token", "::std::string");
+ xsd_std.types_push_back ("Name", "::std::string");
+ xsd_std.types_push_back ("NMTOKEN", "::std::string");
+ xsd_std.types_push_back ("NMTOKENS", string_seq, string_seq);
+ xsd_std.types_push_back ("NCName", "::std::string");
+
+ xsd_std.types_push_back ("ID", "::std::string");
+ xsd_std.types_push_back ("IDREF", "::std::string");
+ xsd_std.types_push_back ("IDREFS", string_seq, string_seq);
+
+ xsd_std.types_push_back ("language", "::std::string");
+ xsd_std.types_push_back ("anyURI", "::std::string");
+ xsd_std.types_push_back ("QName", qname);
+
+ type_map.push_back (xsd_std);
+ }
+
+ String buffer (L"const " + xns + L"::buffer*");
+
+ TypeMap::Namespace xsd ("http://www\\.w3\\.org/2001/XMLSchema");
+
+ xsd.types_push_back ("boolean", "bool", "bool");
+
+ xsd.types_push_back ("byte", "signed char", "signed char");
+ xsd.types_push_back ("unsignedByte", "unsigned char", "unsigned char");
+
+ xsd.types_push_back ("short", "short", "short");
+ xsd.types_push_back ("unsignedShort", "unsigned short", "unsigned short");
+
+ xsd.types_push_back ("int", "int", "int");
+ xsd.types_push_back ("unsignedInt", "unsigned int", "unsigned int");
+
+ if (ops.value<CLI::no_long_long> ())
+ {
+ xsd.types_push_back ("long", "long", "long");
+ xsd.types_push_back ("unsignedLong", "unsigned long", "unsigned long");
+ }
+ else
+ {
+ xsd.types_push_back ("long", "long long", "long long");
+ xsd.types_push_back ("unsignedLong", "unsigned long long", "unsigned long long");
+ }
+
+ xsd.types_push_back ("integer", "long", "long");
+
+ xsd.types_push_back ("negativeInteger", "long", "long");
+ xsd.types_push_back ("nonPositiveInteger", "long", "long");
+
+ xsd.types_push_back ("positiveInteger", "unsigned long", "unsigned long");
+ xsd.types_push_back ("nonNegativeInteger", "unsigned long", "unsigned long");
+
+ xsd.types_push_back ("float", "float", "float");
+ xsd.types_push_back ("double", "double", "double");
+ xsd.types_push_back ("decimal", "double", "double");
+
+ xsd.types_push_back ("base64Binary", buffer, buffer);
+ xsd.types_push_back ("hexBinary", buffer, buffer);
+
+ xsd.types_push_back ("gDay", xns + L"::gday");
+ xsd.types_push_back ("gMonth", xns + L"::gmonth");
+ xsd.types_push_back ("gYear", xns + L"::gyear");
+ xsd.types_push_back ("gMonthDay", xns + L"::gmonth_day");
+ xsd.types_push_back ("gYearMonth", xns + L"::gyear_month");
+ xsd.types_push_back ("date", xns + L"::date");
+ xsd.types_push_back ("time", xns + L"::time");
+ xsd.types_push_back ("dateTime", xns + L"::date_time");
+ xsd.types_push_back ("duration", xns + L"::duration");
+
+ type_map.push_back (xsd);
+
+ // Everyhting else maps to void.
+ //
+ TypeMap::Namespace rest (".*");
+ rest.types_push_back (".*", "void", "void");
+ type_map.push_back (rest);
+ }
+
+ // Process types.
+ //
+ {
+ TypeProcessor proc;
+ proc.process (ops, schema, type_map);
+ }
+
+ // Generate code.
+ //
+ Boolean inline_ (ops.value<CLI::generate_inline> () &&
+ !generate_xml_schema);
+
+ Boolean source (!generate_xml_schema);
+
+ NarrowString name (file_path.leaf ());
+ NarrowString skel_suffix (ops.value <CLI::skel_file_suffix> ());
+ NarrowString impl_suffix (ops.value <CLI::impl_file_suffix> ());
+
+ NarrowString hxx_suffix (ops.value <CLI::hxx_suffix> ());
+ NarrowString ixx_suffix (ops.value <CLI::ixx_suffix> ());
+ NarrowString cxx_suffix (ops.value <CLI::cxx_suffix> ());
+
+
+ Regex hxx_expr (
+ ops.value <CLI::hxx_regex> ().empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + skel_suffix + hxx_suffix + "#"
+ : ops.value <CLI::hxx_regex> ());
+
+ Regex ixx_expr (
+ ops.value <CLI::ixx_regex> ().empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + skel_suffix + ixx_suffix + "#"
+ : ops.value <CLI::ixx_regex> ());
+
+ Regex cxx_expr (
+ ops.value <CLI::cxx_regex> ().empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + skel_suffix + cxx_suffix + "#"
+ : ops.value <CLI::cxx_regex> ());
+
+ Regex hxx_impl_expr;
+ Regex cxx_impl_expr;
+ Regex cxx_driver_expr;
+
+ if (impl || driver)
+ {
+ hxx_impl_expr =
+ "#^(.+?)(\\.[^./\\\\]+)?$#$1" + impl_suffix + hxx_suffix + "#";
+
+ cxx_impl_expr =
+ "#^(.+?)(\\.[^./\\\\]+)?$#$1" + impl_suffix + cxx_suffix + "#";
+
+ cxx_driver_expr =
+ "#^(.+?)(\\.[^./\\\\]+)?$#$1-sdriver" + cxx_suffix + "#";
+ }
+
+ 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 (impl || driver)
+ {
+ if (!hxx_impl_expr.match (name))
+ {
+ wcerr << "error: implementation header expression '" <<
+ hxx_impl_expr.pattern () << "' does not match '" <<
+ name.c_str () << "'" << endl;
+ throw Failed ();
+ }
+
+ if (!cxx_impl_expr.match (name))
+ {
+ wcerr << "error: implementation source expression '" <<
+ cxx_impl_expr.pattern () << "' does not match '" <<
+ name.c_str () << "'" << endl;
+ throw Failed ();
+ }
+
+ if (!cxx_driver_expr.match (name))
+ {
+ wcerr << "error: driver source expression '" <<
+ cxx_driver_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 hxx_impl_name;
+ NarrowString cxx_impl_name;
+ NarrowString cxx_driver_name;
+
+ if (impl || driver)
+ {
+ hxx_impl_name = hxx_impl_expr.merge (name);
+ cxx_impl_name = cxx_impl_expr.merge (name);
+ cxx_driver_name = cxx_driver_expr.merge (name);
+ }
+
+ 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 hxx_impl_path;
+ Path cxx_impl_path;
+ Path cxx_driver_path;
+
+ if (impl || driver)
+ {
+ hxx_impl_path = Path (hxx_impl_name, boost::filesystem::native);
+ cxx_impl_path = Path (cxx_impl_name, boost::filesystem::native);
+ cxx_driver_path = Path (cxx_driver_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;
+
+ if (impl || driver)
+ {
+ hxx_impl_path = path / hxx_impl_path;
+ cxx_impl_path = path / cxx_impl_path;
+ cxx_driver_path = path /cxx_driver_path;
+ }
+
+ }
+ catch (InvalidPath const&)
+ {
+ wcerr << dir.c_str () << ": error: invalid path" << endl;
+ throw Failed ();
+ }
+ }
+
+ // Open the impl files first so that if open fails, the skel files
+ // are not deleted.
+ //
+ WideOutputFileStream hxx_impl;
+ WideOutputFileStream cxx_impl;
+ WideOutputFileStream cxx_driver;
+
+ if (impl)
+ {
+ if (!ops.value<CLI::force_overwrite> ())
+ {
+ WideInputFileStream tmp (hxx_impl_path, ios_base::in);
+
+ if (tmp.is_open ())
+ {
+ wcerr << hxx_impl_path << ": error: cowardly refusing to " <<
+ "overwrite an existing file" << endl;
+ throw Failed ();
+ }
+
+ tmp.close ();
+ }
+
+ hxx_impl.open (hxx_impl_path, ios_base::out);
+
+ if (!hxx_impl.is_open ())
+ {
+ wcerr << hxx_impl_path << ": error: unable to open in write mode"
+ << endl;
+ throw Failed ();
+ }
+
+ unlinks.add (hxx_impl_path);
+ file_list.push_back (hxx_impl_path.native_file_string ());
+
+ if (!ops.value<CLI::force_overwrite> ())
+ {
+ WideInputFileStream tmp (cxx_impl_path, ios_base::in);
+
+ if (tmp.is_open ())
+ {
+ wcerr << cxx_impl_path << ": error: cowardly refusing to " <<
+ "overwrite an existing file" << endl;
+ throw Failed ();
+ }
+
+ tmp.close ();
+ }
+
+ cxx_impl.open (cxx_impl_path, ios_base::out);
+
+ if (!cxx_impl.is_open ())
+ {
+ wcerr << cxx_impl_path << ": error: unable to open in write mode"
+ << endl;
+ throw Failed ();
+ }
+
+ unlinks.add (cxx_impl_path);
+ file_list.push_back (cxx_impl_path.native_file_string ());
+ }
+
+ if (driver)
+ {
+ if (!ops.value<CLI::force_overwrite> ())
+ {
+ WideInputFileStream tmp (cxx_driver_path, ios_base::in);
+
+ if (tmp.is_open ())
+ {
+ wcerr << cxx_driver_path << ": error: cowardly refusing to " <<
+ "overwrite an existing file" << endl;
+ throw Failed ();
+ }
+
+ tmp.close ();
+ }
+
+ cxx_driver.open (cxx_driver_path, ios_base::out);
+
+ if (!cxx_driver.is_open ())
+ {
+ wcerr << cxx_driver_path << ": error: unable to open in write " <<
+ "mode" << endl;
+ throw Failed ();
+ }
+
+ unlinks.add (cxx_driver_path);
+ file_list.push_back (cxx_driver_path.native_file_string ());
+ }
+
+ // Open the skel files.
+ //
+ WideOutputFileStream hxx (hxx_path, ios_base::out);
+ WideOutputFileStream ixx;
+ WideOutputFileStream cxx;
+
+ 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);
+
+ hxx << copyright;
+
+ if (inline_)
+ ixx << copyright;
+
+ if (source)
+ cxx << copyright;
+
+ if (impl)
+ {
+ hxx_impl << copyright_impl;
+ cxx_impl << copyright_impl;
+ }
+
+ if (driver)
+ cxx_driver << copyright_impl;
+
+ // Prologue.
+ //
+ WideInputFileStream prologue;
+ {
+ NarrowString name (ops.value<CLI::prologue_file> ());
+
+ if (name)
+ open (prologue, name);
+ }
+
+ // Epilogue.
+ //
+ WideInputFileStream epilogue;
+ {
+ NarrowString name (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 += '_';
+
+
+ // HXX
+ //
+ {
+ Context ctx (hxx, schema, ops, &hxx_expr, &ixx_expr, &hxx_impl_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, 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_iostream> ())
+ {
+ hxx << "#ifdef XSDE_IOSTREAM" << endl
+ << "#error the XSD/e runtime uses iostream while the " <<
+ "generated code does not (reconfigure the runtime or " <<
+ "remove --no-iostream)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+ else
+ {
+ hxx << "#ifndef XSDE_IOSTREAM" << endl
+ << "#error the generated code uses iostream while the " <<
+ "XSD/e runtime does not (reconfigure the runtime or " <<
+ "add --no-iostream)" << 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;
+ }
+
+ if (ops.value<CLI::suppress_validation> ())
+ {
+ hxx << "#ifdef XSDE_SERIALIZER_VALIDATION" << endl
+ << "#error the XSD/e runtime uses validation while the " <<
+ "generated code does not (reconfigure the runtime or " <<
+ "remove --suppress-validation)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+ else
+ {
+ hxx << "#ifndef XSDE_SERIALIZER_VALIDATION" << endl
+ << "#error the generated code uses validation while the " <<
+ "XSD/e runtime does not (reconfigure the runtime or " <<
+ "add --suppress-validation)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+
+ if (ops.value<CLI::generate_polymorphic> () ||
+ ops.value<CLI::runtime_polymorphic> ())
+ {
+ hxx << "#ifndef XSDE_POLYMORPHIC" << endl
+ << "#error the generated code expects XSD/e runtime with " <<
+ "polymorphism support (reconfigure the runtime or remove " <<
+ "--generate-polymorphic/--runtime-polymorphic)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+ else
+ {
+ hxx << "#ifdef XSDE_POLYMORPHIC" << endl
+ << "#error the generated code expects XSD/e runtime " <<
+ "without polymorphism support (reconfigure the runtime or " <<
+ "add --generate-polymorphic/--runtime-polymorphic)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+
+ if (ops.value<CLI::reuse_style_mixin> ())
+ {
+ hxx << "#ifndef XSDE_REUSE_STYLE_MIXIN" << endl
+ << "#error the generated code uses the mixin reuse style " <<
+ "while the XSD/e runtime does not (reconfigure the runtime " <<
+ "or remove --reuse-style-mixin)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+ else if (ops.value<CLI::reuse_style_none> ())
+ {
+ hxx << "#ifndef XSDE_REUSE_STYLE_NONE" << endl
+ << "#error the generated code does not provide support " <<
+ "for serializer reuse while the XSD/e runtime does (" <<
+ "reconfigure the runtime or remove --reuse-style-none)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+ else
+ {
+ hxx << "#ifndef XSDE_REUSE_STYLE_TIEIN" << endl
+ << "#error the generated code uses the tiein reuse style " <<
+ "while the XSD/e runtime does not (reconfigure the runtime " <<
+ "or add --reuse-style-mixin or --reuse-style-none)" << 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)
+ generate_serializer_forward (ctx);
+
+ generate_serializer_header (ctx, generate_xml_schema);
+
+
+ if (inline_)
+ hxx << "#include " << ctx.process_include_path (ixx_name) << endl
+ << endl;
+
+ hxx << "#include <xsde/cxx/post.hxx>" << endl
+ << endl;
+ }
+
+ // Copy epilogue.
+ //
+ hxx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (hxx, 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, &hxx_expr, &ixx_expr, &hxx_impl_expr);
+
+ Indentation::Clip<Indentation::SLOC, WideChar> ixx_sloc (ixx);
+
+
+ // Copy prologue.
+ //
+ ixx << "// Begin prologue." << endl
+ << "//" << endl;
+
+ append (
+ ixx, ops.value<CLI::ixx_prologue> (), ops.value<CLI::prologue> ());
+ append (ixx, 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_serializer_inline (ctx);
+ }
+
+ // Copy epilogue.
+ //
+ ixx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (ixx, ops.value<CLI::ixx_epilogue_file> (), epilogue);
+ append (
+ ixx, ops.value<CLI::ixx_epilogue> (), ops.value<CLI::epilogue> ());
+
+ ixx << "//" << endl
+ << "// End epilogue." << endl
+ << 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, &hxx_expr, &ixx_expr, &hxx_impl_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, ops.value<CLI::cxx_prologue_file> (), 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;
+
+ if (!inline_)
+ generate_serializer_inline (ctx);
+
+ generate_serializer_source (ctx);
+
+ if (validation)
+ {
+ generate_element_validation_source (ctx);
+ generate_attribute_validation_source (ctx);
+ }
+ }
+
+ // Copy epilogue.
+ //
+ cxx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (cxx, 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 ();
+ }
+ }
+
+ // HXX impl
+ //
+ if (impl)
+ {
+ Context ctx (hxx_impl, schema, ops, &hxx_expr, &ixx_expr, &hxx_impl_expr);
+
+ String guard (guard_expr.merge (guard_prefix + hxx_impl_name));
+ guard = ctx.escape (guard); // Make it a C++ id.
+ std::transform (guard.begin (), guard.end(), guard.begin (), upcase);
+
+ hxx_impl << "#ifndef " << guard << endl
+ << "#define " << guard << endl
+ << endl;
+
+ {
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> clip (hxx_impl);
+
+ hxx_impl << "#include " << ctx.process_include_path (hxx_name)
+ << endl << endl;
+
+ generate_impl_header (ctx);
+ }
+
+ hxx_impl << "#endif // " << guard << endl;
+ }
+
+ // CXX impl
+ //
+ if (impl)
+ {
+ Context ctx (cxx_impl, schema, ops,
+ &hxx_expr, &ixx_expr, &hxx_impl_expr);
+
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> clip (cxx_impl);
+
+ cxx_impl << "#include " << ctx.process_include_path (hxx_impl_name)
+ << endl << endl;
+
+ generate_impl_source (ctx);
+ }
+
+ // CXX driver
+ //
+ if (driver)
+ {
+ Context ctx (cxx_driver, schema, ops,
+ &hxx_expr, &ixx_expr, &hxx_impl_expr);
+
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> clip (cxx_driver);
+
+ cxx_driver << "#include " << ctx.process_include_path (hxx_impl_name)
+ << endl << endl;
+
+ generate_driver_source (ctx);
+ }
+
+ 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/serializer/generator.hxx b/xsde/cxx/serializer/generator.hxx
new file mode 100644
index 0000000..a5b8558
--- /dev/null
+++ b/xsde/cxx/serializer/generator.hxx
@@ -0,0 +1,56 @@
+// file : xsde/cxx/serializer/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_SERIALIZER_GENERATOR_HXX
+#define CXX_SERIALIZER_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/serializer/cli.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ using namespace Cult::Types;
+
+ class Generator
+ {
+ public:
+ static Void
+ usage ();
+
+ static CLI::OptionsSpec
+ options_spec ();
+
+ struct Failed {};
+
+ static UnsignedLong
+ generate (CLI::Options const& options,
+ XSDFrontend::SemanticGraph::Schema&,
+ XSDFrontend::SemanticGraph::Path const& file,
+ TypeMap::Namespaces& type_map,
+ Boolean gen_driver,
+ const WarningSet& disabled_warnings,
+ FileList& file_list,
+ AutoUnlinks& unlinks);
+
+ private:
+ Generator ();
+ };
+ }
+}
+
+#endif // CXX_SERIALIZER_GENERATOR_HXX
diff --git a/xsde/cxx/serializer/impl-header.cxx b/xsde/cxx/serializer/impl-header.cxx
new file mode 100644
index 0000000..d98b6af
--- /dev/null
+++ b/xsde/cxx/serializer/impl-header.cxx
@@ -0,0 +1,488 @@
+// file : xsde/cxx/serializer/impl-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/serializer/impl-header.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ namespace
+ {
+ struct Enumeration: Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ String const& name (eimpl (e));
+ String const& arg (arg_type (e));
+ SemanticGraph::Type& base (e.inherits ().base ());
+
+ os << "class " << name << ": " << "public " <<
+ (mixin ? "virtual " : "") << ename (e);
+
+ if (mixin)
+ os << "," << endl
+ << " public " << fq_name (base, "s:impl");
+
+ os << "{"
+ << "public:" << endl;
+
+ if (tiein)
+ os << name << " ();"
+ << endl;
+
+ os << "virtual void" << endl;
+
+ if (arg == L"void")
+ os << "pre ();";
+ else
+ os << "pre (" << arg << ");";
+
+ os << endl
+ << "virtual void" << endl
+ << "post ();";
+
+ if (tiein)
+ os << endl
+ << "private:" << endl
+ << fq_name (base, "s:impl") << " base_impl_;";
+
+ os << "};";
+ }
+ };
+
+ //
+ //
+ struct List: Traversal::List, Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String const& name (eimpl (l));
+ SemanticGraph::Type& t (l.argumented ().type ());
+
+ String const& arg (arg_type (l));
+ String const& ret (ret_type (t));
+
+ String const& skel (ename (l));
+ String item (unclash (skel, "item"));
+ String item_next (unclash (skel, "item_next"));
+
+ os << "class " << name << ": public " <<
+ (mixin ? "virtual " : "") << ename (l)
+ << "{"
+ << "public:" << endl
+ << "virtual void" << endl;
+
+ if (arg == L"void")
+ os << "pre ();";
+ else
+ os << "pre (" << arg << ");";
+
+ os << endl
+ << "virtual bool" << endl
+ << item_next << " ();"
+ << endl
+ << "virtual " << ret << endl
+ << item << " ();"
+ << endl
+ << "virtual void" << endl
+ << "post ();"
+ << "};";
+ }
+ };
+
+ struct Union: Traversal::Union, Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ String const& name (eimpl (u));
+ String const& arg (arg_type (u));
+
+ os << "class " << name << ": public " <<
+ (mixin ? "virtual " : "") << ename (u)
+ << "{"
+ << "public:" << endl
+ << "virtual void" << endl;
+
+ if (arg == L"void")
+ os << "pre ();";
+ else
+ os << "pre (" << arg << ");";
+
+ os << endl
+ << "virtual void" << endl
+ << "_serialize_content ();"
+ << endl
+ << "virtual void" << endl
+ << "post ();"
+ << "};";
+ }
+ };
+
+
+ //
+ //
+ 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
+ << epresent (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
+ << epresent (c) << " ();"
+ << endl;
+ }
+ else if (max != 1)
+ {
+ os << "virtual bool" << endl
+ << enext (c) << " ();"
+ << endl;
+ }
+
+ os << "virtual " << earm_tag (c) << endl
+ << earm (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
+ << epresent (s) << " ();"
+ << endl;
+ }
+ else if (max != 1)
+ {
+ os << "virtual bool" << endl
+ << enext (s) << " ();"
+ << endl;
+ }
+
+ Traversal::Sequence::traverse (s);
+ }
+ };
+
+ struct ParticleCallback: Traversal::Element,
+ Traversal::Any,
+ 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
+ << epresent (e) << " ();"
+ << endl;
+ }
+ else if (max != 1)
+ {
+ os << "virtual bool" << endl
+ << enext (e) << " ();"
+ << endl;
+ }
+
+ String const& ret (ret_type (e.type ()));
+
+ os << "virtual " << ret << endl
+ << ename (e) << " ();"
+ << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ UnsignedLong min (a.min ()), max (a.max ());
+
+ if (min == 0 && max == 1)
+ {
+ os << "virtual bool" << endl
+ << epresent (a) << " ();"
+ << endl;
+ }
+ else if (max != 1)
+ {
+ os << "virtual bool" << endl
+ << enext (a) << " ();"
+ << endl;
+ }
+
+ if (stl)
+ {
+ os << "virtual void" << endl
+ << ename (a) << " (::std::string& ns, ::std::string& name);"
+ << endl;
+ }
+ else
+ {
+ os << "virtual void" << endl
+ << ename (a) << " (const char*& ns, const char*& name, " <<
+ "bool& free);"
+ << endl;
+ }
+
+ os << "virtual void" << endl
+ << eserialize (a) << " ();"
+ << endl;
+
+ }
+ };
+
+ struct AttributeCallback: Traversal::Attribute,
+ Traversal::AnyAttribute,
+ Context
+ {
+ AttributeCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ if (a.optional ())
+ {
+ os << "virtual bool" << endl
+ << epresent (a) << " ();"
+ << endl;
+ }
+
+ String const& ret (ret_type (a.type ()));
+
+ os << "virtual " << ret << endl
+ << ename (a) << " ();"
+ << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute& a)
+ {
+ os << "virtual bool" << endl
+ << enext (a) << " ();"
+ << endl;
+
+ if (stl)
+ {
+ os << "virtual void" << endl
+ << ename (a) << " (::std::string& ns, ::std::string& name);"
+ << endl;
+ }
+ else
+ {
+ os << "virtual void" << endl
+ << ename (a) << " (const char*& ns, const char*& name, " <<
+ "bool& free);"
+ << endl;
+ }
+
+ os << "virtual void" << endl
+ << eserialize (a) << " ();"
+ << endl;
+ }
+ };
+
+ //
+ //
+ struct Complex : Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c),
+ 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)
+ {
+ // 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& name (eimpl (c));
+ String const& arg (arg_type (c));
+
+ os << "class " << name << ": public " <<
+ (mixin ? "virtual " : "") << ename (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;
+
+ if (arg == L"void")
+ os << "pre ();";
+ else
+ os << "pre (" << arg << ");";
+
+ os << 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_);
+ }
+ }
+
+ // post
+ //
+ os << "virtual void" << endl
+ << "post ();";
+
+ if (tiein && hb)
+ os << endl
+ << "private:" << endl
+ << fq_name (c.inherits ().base (), "s:impl") << " base_impl_;";
+
+ os << "};";
+ }
+
+ private:
+ 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_impl_header (Context& ctx)
+ {
+ Traversal::Schema schema;
+
+ Traversal::Sources sources;
+ Includes includes (ctx, Includes::impl_header);
+ Traversal::Names schema_names;
+
+ Namespace ns (ctx);
+ Traversal::Names names;
+
+ schema >> includes;
+ schema >> sources >> schema;
+ schema >> schema_names >> ns >> names;
+
+ List list (ctx);
+ Union union_ (ctx);
+ Complex complex (ctx);
+ Enumeration enumeration (ctx);
+
+ names >> list;
+ names >> union_;
+ names >> complex;
+ names >> enumeration;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+}
diff --git a/xsde/cxx/serializer/impl-header.hxx b/xsde/cxx/serializer/impl-header.hxx
new file mode 100644
index 0000000..a483eaa
--- /dev/null
+++ b/xsde/cxx/serializer/impl-header.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/serializer/impl-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_SERIALIZER_IMPL_HEADER_HXX
+#define CXX_SERIALIZER_IMPL_HEADER_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/serializer/elements.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ Void
+ generate_impl_header (Context&);
+ }
+}
+
+#endif // CXX_SERIALIZER_IMPL_HEADER_HXX
diff --git a/xsde/cxx/serializer/impl-source.cxx b/xsde/cxx/serializer/impl-source.cxx
new file mode 100644
index 0000000..cc31ced
--- /dev/null
+++ b/xsde/cxx/serializer/impl-source.cxx
@@ -0,0 +1,664 @@
+// file : xsde/cxx/serializer/impl-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/serializer/impl-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ namespace
+ {
+ struct Enumeration: Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ String const& name (eimpl (e));
+ String const& arg (arg_type (e));
+ SemanticGraph::Type& base (e.inherits ().base ());
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ // c-tor
+ //
+ if (tiein)
+ os << name << "::" << endl
+ << name << " ()" << endl
+ << ": " << ename (e) << " (&base_impl_)"
+ << "{"
+ << "}";
+
+ // pre
+ //
+ os << "void " << name << "::" << endl;
+
+ if (arg == L"void")
+ os << "pre ()";
+ else
+ os << "pre (" << arg << " v)";
+
+ os << "{";
+
+ if (arg == arg_type (base))
+ {
+ if (tiein)
+ {
+ os << "base_impl_.pre (" <<
+ (arg != L"void" ? "v" : "") << ");";
+ }
+ else if (mixin)
+ {
+ os << eimpl (base) << "::pre (" <<
+ (arg != L"void" ? "v" : "") << ");";
+ }
+ }
+ else
+ {
+ if (tiein)
+ {
+ os << "// TODO: call base_impl_.pre ()." << endl
+ << "//" << endl;
+ }
+ else if (mixin)
+ {
+ os << "// TODO: call " << eimpl (base) << "::pre ()." << endl
+ << "//" << endl;
+ }
+ }
+
+ os << "}";
+
+ // post
+ //
+ os << "void " << name << "::" << endl
+ << "post ()"
+ << "{"
+ << "}";
+ }
+ };
+
+ //
+ //
+ struct List: Traversal::List, Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String const& name (eimpl (l));
+ SemanticGraph::Type& t (l.argumented ().type ());
+
+ String const& arg (arg_type (l));
+ String const& ret (ret_type (t));
+
+ String const& skel (ename (l));
+ String item (unclash (skel, "item"));
+ String item_next (unclash (skel, "item_next"));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ // pre
+ //
+ os << "void " << name << "::" << endl;
+
+ if (arg == L"void")
+ os << "pre ()"
+ << "{"
+ << "}";
+ else
+ os << "pre (" << arg << " v)"
+ << "{"
+ << "// TODO" << endl
+ << "//" << endl
+ << "}";
+
+ // item
+ //
+ os << "bool " << name << "::" << endl
+ << item_next << " ()"
+ << "{"
+ << "// TODO: return true if there is another item to" << endl
+ << "// serialize." << endl
+ << "//" << endl
+ << "}";
+
+
+ os << ret << " " << name << "::" << endl
+ << item << " ()"
+ << "{"
+ << "// TODO: return the next item." << endl
+ << "//" << endl
+ << "}";
+
+ // post
+ //
+ os << "void " << name << "::" << endl
+ << "post ()"
+ << "{"
+ << "}";
+ }
+ };
+
+ //
+ //
+ struct Union: Traversal::Union, Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ String const& name (eimpl (u));
+ String const& arg (arg_type (u));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ // pre
+ //
+ os << "void " << name << "::" << endl;
+
+ if (arg == L"void")
+ os << "pre ()"
+ << "{"
+ << "}";
+ else
+ os << "pre (" << arg << " v)"
+ << "{"
+ << "// TODO" << endl
+ << "//" << endl
+ << "}";
+
+ // _serialize_content
+ //
+ os << "void " << name << "::" << endl
+ << "_serialize_content ()"
+ << "{"
+ << "// TODO: call the _characters() function to serialize" << endl
+ << "// text content." << endl
+ << "//" << endl
+ << "}";
+
+ // post
+ //
+ os << "void " << name << "::" << endl
+ << "post ()"
+ << "{"
+ << "}";
+ }
+ };
+
+ //
+ //
+ 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)
+ {
+ String const& s (eimpl (scope (a)));
+
+ os << "bool " << s << "::" << endl
+ << epresent (a) << " ()"
+ << "{"
+ << "// TODO: return true if the content corresponding" << endl
+ << "// to the all compositor is present." << endl
+ << "//" << 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 ());
+
+ SemanticGraph::Complex& t (scope (c));
+ String const& s (eimpl (t));
+
+ if (min == 0 && max == 1)
+ {
+ os << "bool " << s << "::" << endl
+ << epresent (c) << " ()"
+ << "{"
+ << "// TODO: return true if the content corresponding" << endl
+ << "// to the choice compositor is present." << endl
+ << "//" << endl
+ << "}";
+ }
+ else if (max != 1)
+ {
+ os << "bool " << s << "::" << endl
+ << enext (c) << " ()"
+ << "{"
+ << "// TODO: return true if there is another choice" << endl
+ << "// item to serialize." << endl
+ << "//" << endl
+ << "}";
+ }
+
+ os << ename (t) << "::" << earm_tag (c) << " " << s << "::" << endl
+ << earm (c) << " ()"
+ << "{"
+ << "// TODO: return the choice arm that is being" << endl
+ << "// serialized." << endl
+ << "//" << endl
+ << "}";
+
+ Traversal::Choice::traverse (c);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ UnsignedLong min (s.min ()), max (s.max ());
+
+ String const& sc (eimpl (scope (s)));
+
+ if (min == 0 && max == 1)
+ {
+ os << "bool " << sc << "::" << endl
+ << epresent (s) << " ()"
+ << "{"
+ << "// TODO: return true if the content corresponding" << endl
+ << "// to the sequence compositor is present." << endl
+ << "//" << endl
+ << "}";
+
+ }
+ else if (max != 1)
+ {
+ os << "bool " << sc << "::" << endl
+ << enext (s) << " ()"
+ << "{"
+ << "// TODO: return true if there is another sequence" << endl
+ << "// item to serialize." << endl
+ << "//" << endl
+ << "}";
+ }
+
+ 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 ());
+ }
+ };
+
+ struct ParticleCallback: Traversal::Element,
+ Traversal::Any,
+ Context
+ {
+ ParticleCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ UnsignedLong min (e.min ()), max (e.max ());
+
+ String const& s (
+ eimpl (dynamic_cast<SemanticGraph::Complex&> (e.scope ())));
+
+ if (min == 0 && max == 1)
+ {
+ os << "bool " << s << "::" << endl
+ << epresent (e) << " ()"
+ << "{"
+ << "// TODO: return true if the element is present." << endl
+ << "//" << endl
+ << "}";
+
+ }
+ else if (max != 1)
+ {
+ os << "bool " << s << "::" << endl
+ << enext (e) << " ()"
+ << "{"
+ << "// TODO: return true if there is another element" << endl
+ << "// to serialize." << endl
+ << "//" << endl
+ << "}";
+ }
+
+ String const& ret (ret_type (e.type ()));
+
+ os << ret << " " << s << "::" << endl
+ << ename (e) << " ()"
+ << "{"
+ << "// TODO: return the element data." << endl
+ << "//" << endl
+ << "}";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ UnsignedLong min (a.min ()), max (a.max ());
+
+ String const& s (
+ eimpl (dynamic_cast<SemanticGraph::Complex&> (a.scope ())));
+
+ if (min == 0 && max == 1)
+ {
+ os << "bool " << s << "::" << endl
+ << epresent (a) << " ()"
+ << "{"
+ << "// TODO: return true if the wildcard content is" << endl
+ << "// present." << endl
+ << "//" << endl
+ << "}";
+ }
+ else if (max != 1)
+ {
+ os << "bool " << s << "::" << endl
+ << enext (a) << " ()"
+ << "{"
+ << "// TODO: return true if there is another wildcard" << endl
+ << "// element to serialize." << endl
+ << "//" << endl
+ << "}";
+ }
+
+ if (stl)
+ {
+ os << "void " << s << "::" << endl
+ << ename (a) << " (::std::string& ns, ::std::string& name)";
+ }
+ else
+ {
+ os << "void " << s << "::" << endl
+ << ename (a) << " (const char*& ns, const char*& name, " <<
+ "bool& free)";
+ }
+
+ os << "{"
+ << "// TODO: return the name and namespace of the element" << endl
+ << "// corresponding to the wildcard." << endl
+ << "//" << endl
+ << "}";
+
+ os << "void " << s << "::" << endl
+ << eserialize (a) << " ()"
+ << "{"
+ << "// TODO: use the _start_element(), _end_element()," << endl
+ << "// _attribute(), and _characters() functions to" << endl
+ << "// serialize the wildcard content." << endl
+ << "//" << endl
+ << "}";
+
+ }
+ };
+
+ struct AttributeCallback: Traversal::Attribute,
+ Traversal::AnyAttribute,
+ Context
+ {
+ AttributeCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ String const& s (
+ eimpl (dynamic_cast<SemanticGraph::Complex&> (a.scope ())));
+
+ if (a.optional ())
+ {
+ os << "bool " << s << "::" << endl
+ << epresent (a) << " ()"
+ << "{"
+ << "// TODO: return true if the attribute is present." << endl
+ << "//" << endl
+ << "}";
+ }
+
+ String const& ret (ret_type (a.type ()));
+
+ os << ret << " " << s << "::" << endl
+ << ename (a) << " ()"
+ << "{"
+ << "// TODO: return the attribute data." << endl
+ << "//" << endl
+ << "}";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute& a)
+ {
+ String const& s (
+ eimpl (dynamic_cast<SemanticGraph::Complex&> (a.scope ())));
+
+ os << "bool " << s << "::" << endl
+ << enext (a) << " ()"
+ << "{"
+ << "// TODO: return true if there is another wildcard" << endl
+ << "// attribute to serialize." << endl
+ << "//" << endl
+ << "}";
+
+ if (stl)
+ {
+ os << "void " << s << "::" << endl
+ << ename (a) << " (::std::string& ns, ::std::string& name)";
+ }
+ else
+ {
+ os << "void " << s << "::" << endl
+ << ename (a) << " (const char*& ns, const char*& name, " <<
+ "bool& free)";
+ }
+
+ os << "{"
+ << "// TODO: return the name and namespace of the attribute" << endl
+ << "// corresponding to the wildcard." << endl
+ << "//" << endl
+ << "}";
+
+ os << "void " << s << "::" << endl
+ << eserialize (a) << " ()"
+ << "{"
+ << "// TODO: use the _characters() function to serialize" << endl
+ << "// the wildcard content." << endl
+ << "//" << endl
+ << "}";
+ }
+ };
+
+ //
+ //
+ struct Complex : Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c),
+ 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)
+ {
+ Boolean hb (c.inherits_p ());
+
+ String const& name (eimpl (c));
+ String const& arg (arg_type (c));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ // c-tor
+ //
+ if (tiein && hb)
+ os << name << "::" << endl
+ << name << " ()" << endl
+ << ": " << ename (c) << " (&base_impl_)"
+ << "{"
+ << "}";
+
+ // pre
+ //
+ os << "void " << name << "::" << endl;
+
+ if (arg == L"void")
+ os << "pre ()";
+ else
+ os << "pre (" << arg << " v)";
+
+ os << "{";
+
+ if (hb)
+ {
+ SemanticGraph::Type& base (c.inherits ().base ());
+
+ if (arg == arg_type (base))
+ {
+ if (tiein)
+ {
+ os << "base_impl_.pre (" <<
+ (arg != L"void" ? "v" : "") << ");";
+ }
+ else if (mixin)
+ {
+ os << eimpl (base) << "::pre (" <<
+ (arg != L"void" ? "v" : "") << ");";
+ }
+ }
+ else
+ {
+ if (tiein)
+ {
+ os << "// TODO: call " << eimpl (base) << "::pre ()." << endl
+ << "//" << endl;
+ }
+ else if (mixin)
+ {
+ os << "// TODO: call base_impl_.pre ()." << endl
+ << "//" << endl;
+ }
+ }
+
+ }
+ else if (arg != L"void")
+ {
+ os << "// TODO" << endl
+ << "//" << endl;
+ }
+
+ os << "}";
+
+ // Member callbacks.
+ //
+ if (!restriction_p (c))
+ {
+ names (c, names_attribute_callback_);
+ contains_compositor (c, contains_compositor_callback_);
+ }
+
+ // post
+ //
+ os << "void " << name << "::" << endl
+ << "post ()"
+ << "{"
+ << "}";
+ }
+
+ private:
+ 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_impl_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);
+ Enumeration enumeration (ctx);
+
+ names >> list;
+ names >> union_;
+ names >> complex;
+ names >> enumeration;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+}
diff --git a/xsde/cxx/serializer/impl-source.hxx b/xsde/cxx/serializer/impl-source.hxx
new file mode 100644
index 0000000..f6303ba
--- /dev/null
+++ b/xsde/cxx/serializer/impl-source.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/serializer/impl-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_SERIALIZER_IMPL_SOURCE_HXX
+#define CXX_SERIALIZER_IMPL_SOURCE_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/serializer/elements.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ Void
+ generate_impl_source (Context&);
+ }
+}
+
+#endif // CXX_SERIALIZER_IMPL_SOURCE_HXX
diff --git a/xsde/cxx/serializer/name-processor.cxx b/xsde/cxx/serializer/name-processor.cxx
new file mode 100644
index 0000000..d68b823
--- /dev/null
+++ b/xsde/cxx/serializer/name-processor.cxx
@@ -0,0 +1,1409 @@
+// file : xsde/cxx/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/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 Serializer
+ {
+ 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,
+ "s: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),
+ skel_suffix_ (ops.value<CLI::skel_type_suffix> ()),
+ impl_suffix_ (ops.value<CLI::impl_type_suffix> ()),
+ schema (root),
+ schema_path (schema_path_),
+ impl (ops.value<CLI::generate_empty_impl> () ||
+ ops.value<CLI::generate_test_driver> ()),
+ tiein (!ops.value<CLI::reuse_style_mixin> () &&
+ !ops.value<CLI::reuse_style_none> ()),
+ skel_suffix (skel_suffix_),
+ impl_suffix (impl_suffix_),
+ global_type_names (global_type_names_),
+ validation (!ops.value<CLI::suppress_validation> ()),
+ polymorphic (ops.value<CLI::generate_polymorphic> ())
+ {
+ }
+
+ protected:
+ Context (Context& c)
+ : CXX::Context (c),
+ schema (c.schema),
+ schema_path (c.schema_path),
+ impl (c.impl),
+ tiein (c.tiein),
+ skel_suffix (c.skel_suffix),
+ impl_suffix (c.impl_suffix),
+ global_type_names (c.global_type_names),
+ validation (c.validation),
+ polymorphic (c.polymorphic)
+ {
+ }
+
+ 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);
+ }
+
+ private:
+ SemanticGraph::Path const schema_path_;
+ String const skel_suffix_;
+ String const impl_suffix_;
+
+ Cult::Containers::Map<String, NameSet*> global_type_names_;
+
+ public:
+ SemanticGraph::Schema& schema;
+ SemanticGraph::Path const& schema_path;
+ Boolean const impl;
+ Boolean const tiein;
+ String const& skel_suffix;
+ String const& impl_suffix;
+
+ Cult::Containers::Map<String, NameSet*>& global_type_names;
+
+ Boolean validation;
+ Boolean polymorphic;
+ };
+
+ // Primary names.
+ //
+ struct PrimaryParticle: Traversal::Element,
+ Traversal::Any,
+ Context
+ {
+ PrimaryParticle (Context& c, NameSet& set, Boolean restriction)
+ : Context (c), set_ (set), restriction_ (restriction)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ using SemanticGraph::Element;
+
+ SemanticGraph::Context& ec (e.context ());
+
+ if (!restriction_)
+ ec.set ("s:name", find_name (e.name (), set_));
+ else
+ {
+ Element* prot = ec.get<Element*> (
+ "xsd-frontend-restriction-correspondence");
+
+ ec.set ("s:name", prot->context ().get<String> ("s:name"));
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ using SemanticGraph::Any;
+
+ SemanticGraph::Context& ac (a.context ());
+
+ if (!restriction_)
+ {
+ ac.set ("s:name", find_name (L"any", set_));
+ }
+ else
+ {
+ Any* prot = ac.get<Any*> (
+ "xsd-frontend-restriction-correspondence");
+
+ ac.set ("s:name", prot->context ().get<String> ("s:name"));
+ }
+ }
+
+ private:
+ NameSet& set_;
+ Boolean restriction_;
+ };
+
+ struct PrimaryAttribute: Traversal::Attribute,
+ Traversal::AnyAttribute,
+ Context
+ {
+ PrimaryAttribute (Context& c, NameSet& set, Boolean restriction)
+ : Context (c), set_ (set), restriction_ (restriction)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ using SemanticGraph::Attribute;
+
+ SemanticGraph::Context& ac (a.context ());
+
+ if (!restriction_)
+ {
+ ac.set ("s:name", find_name (a.name (), set_));
+ }
+ else
+ {
+ Attribute* prot = ac.get<Attribute*> (
+ "xsd-frontend-restriction-correspondence");
+
+ ac.set ("s:name", prot->context ().get<String> ("s:name"));
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute& a)
+ {
+ using SemanticGraph::AnyAttribute;
+
+ SemanticGraph::Context& ac (a.context ());
+
+ if (!restriction_)
+ {
+ ac.set ("s:name", find_name (L"any_attribute", set_));
+ }
+ else
+ {
+ AnyAttribute* prot = ac.get<AnyAttribute*> (
+ "xsd-frontend-restriction-correspondence");
+
+ ac.set ("s:name", prot->context ().get<String> ("s:name"));
+ }
+ }
+
+ private:
+ NameSet& set_;
+ Boolean restriction_;
+ };
+
+ // Secondary names.
+ //
+
+ struct ParticleTag: Traversal::Element,
+ Traversal::Any,
+ Traversal::Choice,
+ Traversal::Sequence,
+ Context
+ {
+ ParticleTag (Context& c, NameSet& set, Boolean restriction)
+ : Context (c), set_ (set), restriction_ (restriction)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ using SemanticGraph::Element;
+
+ SemanticGraph::Context& ec (e.context ());
+
+ if (!restriction_)
+ {
+ String const base (ec.get<String> ("s:name"));
+ ec.set ("s:tag", find_name (base, L"_tag", set_));
+ }
+ else
+ {
+ Element* prot = ec.get<Element*> (
+ "xsd-frontend-restriction-correspondence");
+
+ ec.set ("s:tag", prot->context ().get<String> ("s:tag"));
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ using SemanticGraph::Any;
+
+ SemanticGraph::Context& ac (a.context ());
+
+ if (!restriction_)
+ {
+ String const& base (ac.get<String> ("s:name"));
+ ac.set ("s:tag", find_name (base, L"_tag", set_));
+ }
+ else
+ {
+ Any* prot = ac.get<Any*> (
+ "xsd-frontend-restriction-correspondence");
+
+ ac.set ("s:tag", prot->context ().get<String> ("s:tag"));
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ using SemanticGraph::Compositor;
+
+ SemanticGraph::Context& cc (c.context ());
+
+ if (!restriction_)
+ {
+ cc.set ("s:tag", find_name (L"choice", L"_tag", set_));
+ }
+ else
+ {
+ Compositor* prot = cc.get<Compositor*> (
+ "xsd-frontend-restriction-correspondence");
+
+ cc.set ("s:tag", prot->context ().get<String> ("s:tag"));
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ using SemanticGraph::Compositor;
+
+ SemanticGraph::Context& sc (s.context ());
+
+ if (!restriction_)
+ {
+ sc.set ("s:tag", find_name (L"sequence", L"_tag", set_));
+ }
+ else
+ {
+ Compositor* prot = sc.get<Compositor*> (
+ "xsd-frontend-restriction-correspondence");
+
+ sc.set ("s:tag", prot->context ().get<String> ("s:tag"));
+ }
+ }
+
+ private:
+ NameSet& set_;
+ Boolean restriction_;
+ };
+
+ struct SecondaryCompositor: Traversal::All,
+ Traversal::Choice,
+ Traversal::Sequence,
+ Context
+ {
+ SecondaryCompositor (Context& c, NameSet& set, Boolean restriction)
+ : Context (c),
+ set_ (set),
+ restriction_ (restriction),
+ particle_tag_ (c, set, restriction)
+ {
+ contain_particle_tag_ >> particle_tag_;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ // For the all compositor, maxOccurs=1 and minOccurs={0,1}
+ // and it cannot be used in restriction.
+ //
+ if (a.contained_compositor ().min () == 0)
+ {
+ a.context ().set (
+ "s:present", find_name (L"all", L"_present", set_));
+ }
+
+ Traversal::All::traverse (a);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ if (c.contains_begin () == c.contains_end ())
+ return;
+
+ SemanticGraph::Context& cc (c.context ());
+
+ if (!restriction_)
+ {
+ if (c.max () != 1)
+ cc.set ("s:next", find_name (L"choice", L"_next", set_));
+ else if (c.min () == 0)
+ cc.set ("s:present", find_name (L"choice", L"_present", set_));
+
+ // Tags.
+ //
+ cc.set ("s:arm-tag", find_name (L"choice", L"_arm_tag", set_));
+ Traversal::Choice::contains (c, contain_particle_tag_);
+ cc.set ("s:arm", find_name (L"choice", L"_arm", set_));
+ }
+ else
+ {
+ SemanticGraph::Compositor& b (
+ *cc.get<SemanticGraph::Compositor*> (
+ "xsd-frontend-restriction-correspondence"));
+
+ SemanticGraph::Context& bc (b.context ());
+
+ if (b.max () != 1)
+ {
+ cc.set ("s:next", bc.get<String> ("s:next"));
+
+ // Add the *_present callback if this is a restriction
+ // of sequence to optional.
+ //
+ if (c.min () == 0)
+ cc.set ("s:present",
+ find_name (L"choice", L"_present", set_));
+ }
+ else if (b.min () == 0)
+ cc.set ("s:present", bc.get<String> ("s:present"));
+
+ // Tags.
+ //
+ cc.set ("s:arm-tag", bc.get<String> ("s:arm-tag"));
+ Traversal::Choice::contains (c, contain_particle_tag_);
+ cc.set ("s:arm", bc.get<String> ("s:arm"));
+ }
+
+ Traversal::Choice::traverse (c);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ SemanticGraph::Context& sc (s.context ());
+
+ if (!restriction_)
+ {
+ if (s.max () != 1)
+ sc.set ("s:next", find_name (L"sequence", L"_next", set_));
+ else if (s.min () == 0)
+ sc.set ("s:present", find_name (L"sequence", L"_present", set_));
+ }
+ else
+ {
+ // Root compositor that models inheritance by extension
+ // may not have an association.
+ //
+ if (sc.count ("xsd-frontend-restriction-correspondence"))
+ {
+ SemanticGraph::Compositor& b (
+ *sc.get<SemanticGraph::Compositor*> (
+ "xsd-frontend-restriction-correspondence"));
+
+ SemanticGraph::Context& bc (b.context ());
+
+ if (b.max () != 1)
+ {
+ sc.set ("s:next", bc.get<String> ("s:next"));
+
+ // Add the *_present callback if this is a restriction
+ // of sequence to optional.
+ //
+ if (s.min () == 0)
+ sc.set ("s:present",
+ find_name (L"sequence", L"_present", set_));
+ }
+ else if (b.min () == 0)
+ sc.set ("s:present", bc.get<String> ("s:present"));
+ }
+ }
+
+ Traversal::Sequence::traverse (s);
+ }
+
+ private:
+ NameSet& set_;
+ Boolean restriction_;
+
+ ParticleTag particle_tag_;
+ Traversal::ContainsParticle contain_particle_tag_;
+ };
+
+ struct SecondaryParticle: Traversal::Element,
+ Traversal::Any,
+ Context
+ {
+ SecondaryParticle (Context& c, NameSet& set, Boolean restriction)
+ : Context (c), set_ (set), restriction_ (restriction)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ Boolean poly (
+ polymorphic && !e.type ().context ().count ("anonymous"));
+
+ SemanticGraph::Context& ec (e.context ());
+
+ if (!restriction_)
+ {
+ UnsignedLong min (e.min ()), max (e.max ());
+
+ String const& base (ec.get<String> ("s:name"));
+
+ if (min == 0 && max == 1)
+ ec.set ("s:present", find_name (base + L"_present", set_));
+ else if (max != 1)
+ ec.set ("s:next", find_name (base + L"_next", set_));
+
+ ec.set ("s:serializer", find_name (base + L"_serializer", set_));
+ ec.set ("s:member", find_name (base + L"_serializer_", set_));
+
+ if (poly)
+ ec.set ("s:member-map",
+ find_name (base + L"_serializer_map_", set_));
+ }
+ else
+ {
+ SemanticGraph::Element& b (
+ *ec.get<SemanticGraph::Element*> (
+ "xsd-frontend-restriction-correspondence"));
+
+ SemanticGraph::Context& bc (b.context ());
+ UnsignedLong min (b.min ()), max (b.max ());
+
+ if (min == 0 && max == 1)
+ ec.set ("s:present", bc.get<String> ("s:present"));
+ else if (max != 1)
+ {
+ ec.set ("s:next", bc.get<String> ("s:next"));
+
+ // Add the *_present callback if this is a restriction
+ // of sequence to optional.
+ //
+ if (e.min () == 0)
+ {
+ String const& base (bc.get<String> ("s:name"));
+ ec.set ("s:present", find_name (base + L"_present", set_));
+ }
+ }
+
+ ec.set ("s:serializer", bc.get<String> ("s:serializer"));
+ ec.set ("s:member", bc.get<String> ("s:member"));
+
+ if (poly)
+ ec.set ("s:member-map", bc.get<String> ("s:member-map"));
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ using SemanticGraph::Any;
+
+ SemanticGraph::Context& ac (a.context ());
+
+ if (!restriction_)
+ {
+ UnsignedLong min (a.min ()), max (a.max ());
+ String const& base (ac.get<String> ("s:name"));
+
+ if (min == 0 && max == 1)
+ {
+ ac.set ("s:present", find_name (base + L"_present", set_));
+ }
+ else if (max != 1)
+ {
+ ac.set ("s:next", find_name (base + L"_next", set_));
+ }
+
+ ac.set ("s:serialize", find_name (L"serialize_" + base, set_));
+ }
+ else
+ {
+ Any& b (
+ *ac.get<Any*> ("xsd-frontend-restriction-correspondence"));
+
+ SemanticGraph::Context& bc (b.context ());
+ UnsignedLong min (b.min ()), max (b.max ());
+
+ if (min == 0 && max == 1)
+ {
+ ac.set ("s:present", bc.get<String> ("s:present"));
+ }
+ else if (max != 1)
+ {
+ ac.set ("s:next", bc.get<String> ("s:next"));
+
+ // Add the *_present callback if this is a restriction
+ // of sequence to optional.
+ //
+ if (a.min () == 0)
+ {
+ String const& base (bc.get<String> ("s:name"));
+ ac.set ("s:present", find_name (base + L"_present", set_));
+ }
+ }
+
+ ac.set ("s:serialize", bc.get<String> ("s:serialize"));
+ }
+ }
+
+ private:
+ NameSet& set_;
+ Boolean restriction_;
+ };
+
+ struct SecondaryAttribute: Traversal::Attribute,
+ Traversal::AnyAttribute,
+ Context
+ {
+ SecondaryAttribute (Context& c, NameSet& set, Boolean restriction)
+ : Context (c), set_ (set), restriction_ (restriction)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ using SemanticGraph::Attribute;
+
+ SemanticGraph::Context& ac (a.context ());
+
+ if (!restriction_)
+ {
+ String const& base (ac.get<String> ("s:name"));
+
+ if (a.optional ())
+ ac.set ("s:present", find_name (base + L"_present", set_));
+
+ ac.set ("s:serializer", find_name (base + L"_serializer", set_));
+ ac.set ("s:member", find_name (base + L"_serializer_", set_));
+ }
+ else
+ {
+ Attribute& b (
+ *ac.get<Attribute*> ("xsd-frontend-restriction-correspondence"));
+ SemanticGraph::Context& bc (b.context ());
+
+ if (a.optional ())
+ ac.set ("s:present", bc.get<String> ("s:present"));
+
+ ac.set ("s:serializer", bc.get<String> ("s:serializer"));
+ ac.set ("s:member", bc.get<String> ("s:member"));
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute& a)
+ {
+ using SemanticGraph::AnyAttribute;
+
+ SemanticGraph::Context& ac (a.context ());
+
+ if (!restriction_)
+ {
+ String const& base (ac.get<String> ("s:name"));
+
+ ac.set ("s:next", find_name (base + L"_next", set_));
+ ac.set ("s:serialize", find_name (L"serialize_" + base, set_));
+ }
+ else
+ {
+ AnyAttribute& b (
+ *ac.get<AnyAttribute*> (
+ "xsd-frontend-restriction-correspondence"));
+ SemanticGraph::Context& bc (b.context ());
+
+ ac.set ("s:next", bc.get<String> ("s:next"));
+ ac.set ("s:serialize", bc.get<String> ("s:serialize"));
+ }
+ }
+
+ private:
+ NameSet& set_;
+ Boolean restriction_;
+ };
+
+ //
+ //
+ struct Complex: Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ SemanticGraph::Context& cc (c.context ());
+
+ // Use processed name.
+ //
+ String const& name (cc.get<String> ("s:name"));
+
+ // We leave this set around to allow other mappings to use
+ // this information.
+ //
+ cc.set ("cxx-serializer-name-processor-member-set", NameSet ());
+ NameSet& member_set (
+ cc.get<NameSet> ("cxx-serializer-name-processor-member-set"));
+
+ member_set.insert (name);
+
+ // Add our base's members to the initial list unless we are
+ // inheriting by restriction in which case we need to have
+ // the same names as our base.
+ //
+ Boolean restriction (false);
+
+ if (c.inherits_p ())
+ {
+ // @@ What if this types name is the same as one of base's
+ // members?
+ //
+ SemanticGraph::Type& base (c.inherits ().base ());
+
+ if (base.is_a<SemanticGraph::Complex> ())
+ {
+ if (!base.context ().count (
+ "cxx-serializer-name-processor-member-set"))
+ {
+ dispatch (base);
+ }
+
+ NameSet const& base_set (
+ base.context ().get<NameSet> (
+ "cxx-serializer-name-processor-member-set"));
+
+ member_set.insert (base_set.begin (), base_set.end ());
+
+ // Inheritance by restriction from anyType is a special case.
+ //
+ restriction = c.inherits ().is_a<SemanticGraph::Restricts> () &&
+ !c.inherits ().base ().is_a<SemanticGraph::AnyType> ();
+ }
+ }
+
+ // First assign the "primary" names.
+ //
+ {
+ if (c.contains_compositor_p ())
+ {
+ PrimaryParticle particle (*this, member_set, restriction);
+ Traversal::Compositor compositor;
+ 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);
+ }
+
+ //
+ //
+ PrimaryAttribute attribute (*this, member_set, restriction);
+ Traversal::Names names (attribute);
+
+ Complex::names (c, names);
+ }
+
+ // Assign "secondary" names.
+ //
+ {
+ if (c.contains_compositor_p ())
+ {
+ SecondaryParticle particle (*this, member_set, restriction);
+ SecondaryCompositor compositor (*this, member_set, restriction);
+ 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);
+ }
+
+ //
+ //
+ SecondaryAttribute attribute (*this, member_set, restriction);
+ Traversal::Names names (attribute);
+
+ Complex::names (c, names);
+ }
+ }
+ };
+
+
+ //
+ //
+ struct GlobalType: Traversal::Type, Context
+ {
+ GlobalType (Context& c, NameSet& set)
+ : Context (c), set_ (set)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& t)
+ {
+ String const& n (t.name ());
+ SemanticGraph::Context& tc (t.context ());
+
+ String name (find_name (n + skel_suffix, set_));
+ tc.set ("s:name", name);
+
+ if (tiein)
+ tc.set ("s:tiein", escape (n + L"_impl_"));
+
+ // Note that we do not add this name to the set so that it
+ // does not influence other names.
+ //
+ if (impl)
+ tc.set ("s:impl", escape (n + impl_suffix));
+ }
+
+ 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_names (t, "any_type");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnySimpleType& t)
+ {
+ set_names (t, "any_simple_type");
+ }
+
+ // Boolean.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Boolean& t)
+ {
+ set_names (t, "boolean");
+ }
+
+ // Integral types.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Byte& t)
+ {
+ set_names (t, "byte");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedByte& t)
+ {
+ set_names (t, "unsigned_byte");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Short& t)
+ {
+ set_names (t, "short");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedShort& t)
+ {
+ set_names (t, "unsigned_short");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Int& t)
+ {
+ set_names (t, "int");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedInt& t)
+ {
+ set_names (t, "unsigned_int");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Long& t)
+ {
+ set_names (t, "long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedLong& t)
+ {
+ set_names (t, "unsigned_long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Integer& t)
+ {
+ set_names (t, "integer");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonPositiveInteger& t)
+ {
+ set_names (t, "non_positive_integer");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonNegativeInteger& t)
+ {
+ set_names (t, "non_negative_integer");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::PositiveInteger& t)
+ {
+ set_names (t, "positive_integer");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NegativeInteger& t)
+ {
+ set_names (t, "negative_integer");
+ }
+
+ // Floats.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Float& t)
+ {
+ set_names (t, "float");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Double& t)
+ {
+ set_names (t, "double");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Decimal& t)
+ {
+ set_names (t, "decimal");
+ }
+
+ // Strings.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::String& t)
+ {
+ set_names (t, "string");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NormalizedString& t)
+ {
+ set_names (t, "normalized_string");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Token& t)
+ {
+ set_names (t, "token");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameToken& t)
+ {
+ set_names (t, "nmtoken");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameTokens& t)
+ {
+ set_names (t, "nmtokens");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Name& t)
+ {
+ set_names (t, "name");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NCName& t)
+ {
+ set_names (t, "ncname");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Language& t)
+ {
+ set_names (t, "language");
+ }
+
+
+ // Qualified name.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::QName& t)
+ {
+ set_names (t, "qname");
+ }
+
+
+ // ID/IDREF.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Id& t)
+ {
+ set_names (t, "id");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRef& t)
+ {
+ set_names (t, "idref");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRefs& t)
+ {
+ set_names (t, "idrefs");
+ }
+
+ // URI.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::AnyURI& t)
+ {
+ set_names (t, "uri");
+ }
+
+ // Binary.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Base64Binary& t)
+ {
+ set_names (t, "base64_binary");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::HexBinary& t)
+ {
+ set_names (t, "hex_binary");
+ }
+
+
+ // Date/time.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Date& t)
+ {
+ set_names (t, "date");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::DateTime& t)
+ {
+ set_names (t, "date_time");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Duration& t)
+ {
+ set_names (t, "duration");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Day& t)
+ {
+ set_names (t, "gday");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Month& t)
+ {
+ set_names (t, "gmonth");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::MonthDay& t)
+ {
+ set_names (t, "gmonth_day");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Year& t)
+ {
+ set_names (t, "gyear");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::YearMonth& t)
+ {
+ set_names (t, "gyear_month");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Time& t)
+ {
+ set_names (t, "time");
+ }
+
+ // Entity.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entity& t)
+ {
+ set_names (t, "entity");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entities& t)
+ {
+ set_names (t, "entities");
+ }
+
+ private:
+ String
+ make_skel_name (String const& base)
+ {
+ return escape (base + skel_suffix);
+ }
+
+ String
+ make_impl_name (String const& base)
+ {
+ return escape (base + impl_suffix);
+ }
+
+ Void
+ set_names (SemanticGraph::Type& t, String const& name)
+ {
+ SemanticGraph::Context& c (t.context ());
+
+ WideChar const* ns = validation
+ ? L"::xsde::cxx::serializer::validating::"
+ : L"::xsde::cxx::serializer::non_validating::";
+
+ String skel (make_skel_name (name));
+ c.set ("s:name", skel);
+ c.set ("s:real-name", ns + skel);
+
+ String impl (make_impl_name (name));
+ c.set ("s:impl", impl);
+ c.set ("s:real-impl", ns + impl);
+
+ c.set ("s:post", L"post_" + name);
+
+ if (tiein)
+ c.set ("s:tiein", name + L"_impl_");
+ }
+ };
+
+ // 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-serializer-name-processor-seen"))
+ {
+ s.context ().set ("cxx-serializer-name-processor-seen", true);
+ Traversal::Sources::traverse (sr);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Includes& i)
+ {
+ SemanticGraph::Schema& s (i.schema ());
+
+ if (!s.context ().count ("cxx-serializer-name-processor-seen"))
+ {
+ s.context ().set ("cxx-serializer-name-processor-seen", true);
+ Traversal::Includes::traverse (i);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Imports& i)
+ {
+ SemanticGraph::Schema& s (i.schema ());
+
+ if (!s.context ().count ("cxx-serializer-name-processor-seen"))
+ {
+ s.context ().set ("cxx-serializer-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-serializer-name-processor-seen"))
+ {
+ s.context ().set ("cxx-serializer-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-serializer-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-serializer-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;
+
+ Complex complex (ctx);
+
+ ns_names >> complex;
+
+ schema.dispatch (tu);
+ }
+ }
+ }
+ }
+
+ Void NameProcessor::
+ process (CLI::Options const& ops,
+ SemanticGraph::Schema& tu,
+ SemanticGraph::Path const& file)
+ {
+ process_impl (ops, tu, file);
+ }
+ }
+}
diff --git a/xsde/cxx/serializer/name-processor.hxx b/xsde/cxx/serializer/name-processor.hxx
new file mode 100644
index 0000000..bf69ba6
--- /dev/null
+++ b/xsde/cxx/serializer/name-processor.hxx
@@ -0,0 +1,32 @@
+// file : xsde/cxx/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_SERIALIZER_NAME_PROCESSOR_HXX
+#define CXX_SERIALIZER_NAME_PROCESSOR_HXX
+
+#include <cult/types.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+
+#include <cxx/serializer/cli.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ using namespace Cult::Types;
+
+ class NameProcessor
+ {
+ public:
+ Void
+ process (CLI::Options const& options,
+ XSDFrontend::SemanticGraph::Schema&,
+ XSDFrontend::SemanticGraph::Path const& file);
+ };
+ }
+}
+
+#endif // CXX_SERIALIZER_NAME_PROCESSOR_HXX
diff --git a/xsde/cxx/serializer/serializer-forward.cxx b/xsde/cxx/serializer/serializer-forward.cxx
new file mode 100644
index 0000000..60d5ce5
--- /dev/null
+++ b/xsde/cxx/serializer/serializer-forward.cxx
@@ -0,0 +1,112 @@
+// file : xsde/cxx/serializer/serializer-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/serializer/serializer-forward.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ namespace
+ {
+ struct Enumeration: Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ os << "class " << ename (e) << ";";
+ }
+ };
+
+ //
+ //
+ 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) << ";";
+ }
+ };
+ }
+
+ Void
+ generate_serializer_forward (Context& ctx)
+ {
+ ctx.os << "// Forward declarations" << endl
+ << "//" << endl;
+
+ 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);
+ Enumeration enumeration (ctx);
+
+ names >> list;
+ names >> union_;
+ names >> complex;
+ names >> enumeration;
+
+ schema.dispatch (ctx.schema_root);
+
+ ctx.os << endl;
+ }
+ }
+}
diff --git a/xsde/cxx/serializer/serializer-forward.hxx b/xsde/cxx/serializer/serializer-forward.hxx
new file mode 100644
index 0000000..239d82f
--- /dev/null
+++ b/xsde/cxx/serializer/serializer-forward.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/serializer/serializer-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_SERIALIZER_SERIALIZER_FORWARD_HXX
+#define CXX_SERIALIZER_SERIALIZER_FORWARD_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/serializer/elements.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ Void
+ generate_serializer_forward (Context&);
+ }
+}
+
+#endif // CXX_SERIALIZER_SERIALIZER_FORWARD_HXX
diff --git a/xsde/cxx/serializer/serializer-header.cxx b/xsde/cxx/serializer/serializer-header.cxx
new file mode 100644
index 0000000..6ba57f1
--- /dev/null
+++ b/xsde/cxx/serializer/serializer-header.cxx
@@ -0,0 +1,2006 @@
+// file : xsde/cxx/serializer/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/serializer/serializer-header.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ namespace
+ {
+ // Override classes override pure virtual functions in the base.
+ // Should be in sync with declaration generators below. Used in
+ // tiein implementation.
+ //
+
+ struct CompositorCallbackOverride: Traversal::Choice,
+ Traversal::Sequence,
+ Context
+ {
+ CompositorCallbackOverride (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ if (c.contains_begin () != c.contains_end ())
+ {
+ UnsignedLong min (c.min ()), max (c.max ());
+
+ if (max != 1 && min != 0)
+ {
+ os << "virtual bool" << endl
+ << enext (c) << " ();"
+ << endl;
+ }
+
+ if (min != 0)
+ {
+ os << "virtual " << earm_tag (c) << endl
+ << earm (c) << " ();"
+ << endl;
+ }
+
+ Traversal::Choice::traverse (c);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ UnsignedLong min (s.min ()), max (s.max ());
+
+ if (max != 1 && min != 0)
+ {
+ os << "virtual bool" << endl
+ << enext (s) << " ();"
+ << endl;
+ }
+
+ Traversal::Sequence::traverse (s);
+ }
+ };
+
+ struct ParticleCallbackOverride: Traversal::Element,
+ Traversal::Any,
+ Context
+ {
+ ParticleCallbackOverride (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ UnsignedLong min (e.min ()), max (e.max ());
+
+ if (max != 1 && min != 0)
+ {
+ os << "virtual bool" << endl
+ << enext (e) << " ();"
+ << endl;
+ }
+
+ String const& ret (ret_type (e.type ()));
+
+ if (ret != L"void")
+ {
+ os << "virtual " << ret << endl
+ << ename (e) << " ();"
+ << endl;
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ UnsignedLong min (a.min ()), max (a.max ());
+
+ if (min != 0 &&
+ !a.contained_particle ().compositor ().is_a<
+ SemanticGraph::Choice> ())
+ {
+ if (max != 1)
+ {
+ os << "virtual bool" << endl
+ << enext (a) << " ();"
+ << endl;
+ }
+
+ if (stl)
+ {
+ os << "virtual void" << endl
+ << ename (a) << " (::std::string& ns, ::std::string& name);"
+ << endl;
+ }
+ else
+ {
+ os << "virtual void" << endl
+ << ename (a) << " (const char*& ns, const char*& name, " <<
+ "bool& free);"
+ << endl;
+ }
+
+ os << "virtual void" << endl
+ << eserialize (a) << " ();"
+ << endl;
+ }
+ }
+ };
+
+ struct AttributeCallbackOverride: Traversal::Attribute, Context
+ {
+ AttributeCallbackOverride (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ String const& ret (ret_type (a.type ()));
+
+ if (ret != L"void")
+ {
+ os << "virtual " << ret << endl
+ << ename (a) << " ();"
+ << endl;
+ }
+ }
+ };
+
+ struct BaseOverride: Traversal::Type,
+ Traversal::Enumeration,
+ Traversal::List,
+ Traversal::Union,
+ Traversal::Complex,
+ Context
+ {
+ BaseOverride (Context& c)
+ : Context (c),
+ 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 (SemanticGraph::Type& t)
+ {
+ // pre
+ //
+ String const& arg (arg_type (t));
+
+ if (arg != L"void")
+ {
+ os << "virtual void" << endl
+ << "pre (" << arg << ");"
+ << endl;
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Enumeration& e)
+ {
+ SemanticGraph::Type& t (e);
+ traverse (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::List& l)
+ {
+ SemanticGraph::Type& t (l);
+ traverse (t);
+
+ // item
+ //
+ String const& ret (ret_type (l.argumented ().type ()));
+
+ if (ret != L"void")
+ {
+ os << "virtual " << ret << endl
+ << unclash (ename (l), "item") << " ();"
+ << endl;
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Union& u)
+ {
+ SemanticGraph::Type& t (u);
+ traverse (t);
+
+ // serialize_content
+ //
+ os << "virtual void" << endl
+ << "_serialize_content ();"
+ << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ SemanticGraph::Type& t (c);
+ traverse (t);
+
+ // Member callbacks.
+ //
+ if (!restriction_p (c))
+ {
+ Traversal::Complex::names (c, names_attribute_callback_);
+ Traversal::Complex::contains_compositor (
+ c, contains_compositor_callback_);
+ }
+ }
+
+ private:
+ CompositorCallbackOverride compositor_callback_;
+ ParticleCallbackOverride particle_callback_;
+ Traversal::ContainsCompositor contains_compositor_callback_;
+ Traversal::ContainsParticle contains_particle_callback_;
+
+ AttributeCallbackOverride attribute_callback_;
+ Traversal::Names names_attribute_callback_;
+ };
+
+ //
+ //
+
+ struct Enumeration: Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ String const& name (ename (e));
+ SemanticGraph::Type& base (e.inherits ().base ());
+ String fq_base (fq_name (base));
+
+ os << "class " << name << ": public " <<
+ (mixin ? "virtual " : "") << fq_base
+ << "{"
+ << "public:" << endl
+ << "// Serializer callbacks. Override them in your " <<
+ "implementation." << endl
+ << "//" << endl
+ << endl;
+
+ // pre
+ //
+ String const& arg (arg_type (e));
+ String const& base_arg (arg_type (base));
+
+ if (arg == base_arg)
+ {
+ os << "// virtual void" << endl;
+
+ if (arg == L"void")
+ os << "// pre ();" << endl;
+ else
+ os << "// pre (" << arg << ") = 0;" << endl;
+
+ os << endl;
+ }
+ else
+ {
+ os << "virtual void" << endl;
+
+ if (arg == L"void")
+ os << "pre ();";
+ else
+ os << "pre (" << arg << ") = 0;";
+
+ os << endl;
+ }
+
+ // post
+ //
+ os << "// virtual void" << endl
+ << "// post ();" << endl;
+
+ if (poly_code)
+ {
+ os << endl
+ << "public:" << endl
+ << "static const char*" << endl
+ << "_static_type ();"
+ << endl
+ << "virtual const char*" << endl
+ << "_dynamic_type () const;";
+ }
+
+ if (tiein)
+ {
+ os << endl
+ << "// Constructor." << endl
+ << "//" << endl
+ << name << " (" << fq_base << "* tiein);"
+ << endl;
+
+ os << "// Implementation details." << endl
+ << "//" << endl;
+
+ // If our base has pure virtual functions, override them here.
+ //
+ inherits (e);
+
+ os << "protected:" << endl
+ << name << "* " << etiein (e) << ";"
+ << name << " (" << name << "*, void*);"
+ << endl;
+ }
+
+ os << "};";
+ }
+ };
+
+ //
+ //
+ struct List: Traversal::List, Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String const& name (ename (l));
+ SemanticGraph::Type& t (l.argumented ().type ());
+ String item_type (fq_name (t));
+
+ String item (unclash (name, "item"));
+ String item_next (unclash (name, "item_next"));
+
+ os << "class " << name << ": public " << simple_base
+ << "{"
+ << "public:" << endl
+ << "// Serializer callbacks. Override them in your " <<
+ "implementation." << endl
+ << "//" << endl
+ << endl;
+
+ // pre
+ //
+ String const& arg (arg_type (l));
+
+ os << "virtual void" << endl;
+
+ if (arg == L"void")
+ os << "pre ();";
+ else
+ os << "pre (" << arg << ") = 0;";
+
+ os << endl;
+
+ // item
+ //
+ os << "virtual bool" << endl
+ << item_next << " ();"
+ << endl;
+
+ String const& ret (ret_type (t));
+
+ os << "virtual " << ret << endl
+ << item << " ()" << (ret != L"void" ? " = 0" : "") << ";"
+ << endl;
+
+ // post
+ //
+ os << "// virtual void" << endl
+ << "// post ();" << endl
+ << endl;
+
+ //
+ //
+ os << "// Serializer construction API." << endl
+ << "//" << endl;
+
+ // item_serializer
+ //
+ os << "void" << endl
+ << unclash (name, "item_serializer") << " (" << item_type << "&);"
+ << endl;
+
+ // serializers
+ //
+ os << "void" << endl
+ << "serializers (" << item_type << "& /* item */);"
+ << endl;
+
+ if (reset)
+ os << "virtual void" << endl
+ << "_reset ();"
+ << endl;
+
+ // c-tor
+ //
+ os << "// Constructor." << endl
+ << "//" << endl
+ << name << " ();"
+ << endl;
+
+ if (poly_code)
+ {
+ os << "public:" << endl
+ << "static const char*" << endl
+ << "_static_type ();"
+ << endl
+ << "virtual const char*" << endl
+ << "_dynamic_type () const;"
+ << endl;
+ }
+
+ //
+ //
+ os << "// Implementation." << endl
+ << "//" << endl
+ << "public:" << endl;
+
+ os << "virtual void" << endl
+ << "_serialize_content ();"
+ << endl;
+
+ os << "protected:" << endl;
+
+ if (tiein)
+ {
+ os << name << "* " << etiein (l) << ";"
+ << name << " (" << name << "*, void*);"
+ << endl;
+ }
+
+ os << item_type << "* _xsde_" << item << "_;"
+ << "};";
+ }
+ };
+
+ struct Union: Traversal::Union, Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ String const& name (ename (u));
+
+ os << "class " << name << ": public " << simple_base
+ << "{"
+ << "public:" << endl
+ << "// Serializer callbacks. Override them in your " <<
+ "implementation." << endl
+ << "//" << endl
+ << endl;
+
+ // pre
+ //
+ String const& arg (arg_type (u));
+
+ os << "virtual void" << endl;
+
+ if (arg == L"void")
+ os << "pre ();";
+ else
+ os << "pre (" << arg << ") = 0;";
+
+ os << endl;
+
+ // serialize_content
+ //
+ os << "virtual void" << endl
+ << "_serialize_content () = 0;"
+ << endl;
+
+ // post
+ //
+ os << "// virtual void" << endl
+ << "// post ();" << endl;
+
+ if (poly_code)
+ {
+ os << endl
+ << "public:" << endl
+ << "static const char*" << endl
+ << "_static_type ();"
+ << endl
+ << "virtual const char*" << endl
+ << "_dynamic_type () const;";
+ }
+
+ if (tiein)
+ {
+ // c-tor
+ //
+ os << endl
+ << "// Constructor." << endl
+ << "//" << endl
+ << name << " ();"
+ << endl;
+
+ //
+ //
+ os << "// Implementation details." << endl
+ << "//" << endl
+ << "protected:" << endl
+ << name << "* " << etiein (u) << ";"
+ << name << " (" << name << "*, void*);"
+ << endl;
+ }
+
+ os << "};";
+ }
+ };
+
+ //
+ //
+ struct ParticleTag: Traversal::Particle, Context
+ {
+ ParticleTag (Context& c)
+ : Context (c), first_ (true)
+ {
+ }
+
+ virtual Void
+ traverse (Type& p)
+ {
+ if (first_)
+ first_ = false;
+ else
+ os << "," << endl;
+
+ os << etag (p);
+ }
+
+ private:
+ Boolean first_;
+ };
+
+ struct CompositorCallback: Traversal::All,
+ Traversal::Choice,
+ Traversal::Sequence,
+ Context
+ {
+ CompositorCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ if (!a.context ().count ("xsd-frontend-restriction-correspondence"))
+ {
+ // For the all compositor, maxOccurs=1 and minOccurs={0,1}.
+ //
+ if (a.min () == 0)
+ {
+ os << "virtual bool" << endl
+ << epresent (a) << " ();"
+ << endl;
+ }
+ }
+
+ Traversal::All::traverse (a);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ if (c.contains_begin () != c.contains_end ())
+ {
+ if (SemanticGraph::Compositor* b = correspondent (c))
+ {
+ // Add the *_present callback if this is a restriction
+ // of sequence to optional.
+ //
+ UnsignedLong cmin (c.min ()), bmax (b->max ());
+
+ if (bmax != 1 && cmin == 0)
+ {
+ os << "virtual bool" << endl
+ << epresent (c) << " ();"
+ << endl;
+ }
+ }
+ else
+ {
+ UnsignedLong min (c.min ()), max (c.max ());
+
+ if (min == 0 && max == 1)
+ {
+ os << "virtual bool" << endl
+ << epresent (c) << " ();"
+ << endl;
+ }
+ else if (max != 1)
+ {
+ os << "virtual bool" << endl
+ << enext (c) << " ()" << (min != 0 ? " = 0" : "") << ";"
+ << endl;
+ }
+
+ //
+ //
+ os << "enum " << earm_tag (c)
+ << "{";
+
+ {
+ ParticleTag particle (*this);
+ Traversal::ContainsParticle contain_particle (particle);
+ Traversal::Choice::contains (c, contain_particle);
+ }
+
+ os << "};";
+
+ os << "virtual " << earm_tag (c) << endl
+ << earm (c) << " ()" << (min != 0 ? " = 0" : "") << ";"
+ << endl;
+ }
+
+ Traversal::Choice::traverse (c);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ // Root compositor that models inheritance by extension
+ // may not have an association so we may fall through
+ // in to the 'else' case even though this is a restriction.
+ // This is ok since such a compositor always has max ==
+ // min == 1 and so nothing is generated.
+ //
+ if (SemanticGraph::Compositor* b = correspondent (s))
+ {
+ // Add the *_present callback if this is a restriction
+ // of sequence to optional.
+ //
+ UnsignedLong smin (s.min ());
+ UnsignedLong bmax (b->max ());
+
+ if (bmax != 1 && smin == 0)
+ {
+ os << "virtual bool" << endl
+ << epresent (s) << " ();"
+ << endl;
+ }
+ }
+ else
+ {
+ UnsignedLong min (s.min ()), max (s.max ());
+
+ if (min == 0 && max == 1)
+ {
+ os << "virtual bool" << endl
+ << epresent (s) << " ();"
+ << endl;
+ }
+ else if (max != 1)
+ {
+ os << "virtual bool" << endl
+ << enext (s) << " ()" << (min != 0 ? " = 0" : "") << ";"
+ << endl;
+ }
+ }
+
+ Traversal::Sequence::traverse (s);
+ }
+ };
+
+ struct ParticleCallback: Traversal::Element,
+ Traversal::Any,
+ Context
+ {
+ ParticleCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (SemanticGraph::Element* b = correspondent (e))
+ {
+ // Add the *_present callback if this is a restriction
+ // of sequence to optional.
+ //
+ if (b->max () != 1 && e.min () == 0)
+ {
+ os << "virtual bool" << endl
+ << epresent (e) << " ();"
+ << endl;
+ }
+ }
+ else
+ {
+ UnsignedLong min (e.min ()), max (e.max ());
+
+ if (min == 0 && max == 1)
+ {
+ os << "virtual bool" << endl
+ << epresent (e) << " ();"
+ << endl;
+ }
+ else if (max != 1)
+ {
+ os << "virtual bool" << endl
+ << enext (e) << " ()" << (min != 0 ? " = 0" : "") << ";"
+ << endl;
+ }
+
+ String const& ret (ret_type (e.type ()));
+
+ // Make it non-pure-virtual only if the return type is void.
+ //
+ os << "virtual " << ret << endl
+ << ename (e) << " ()" << (ret != L"void" ? " = 0;" : ";")
+ << endl;
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ if (SemanticGraph::Any* b = correspondent (a))
+ {
+ // Add the *_present callback if this is a restriction
+ // of sequence to optional.
+ //
+ if (b->max () != 1 && a.min () == 0)
+ {
+ os << "virtual bool" << endl
+ << epresent (a) << " ();"
+ << endl;
+ }
+ }
+ else
+ {
+ UnsignedLong min (a.min ()), max (a.max ());
+
+ // Generate pure virtual callbacks unless we are optional
+ // or in choice.
+ //
+ Boolean pv (
+ min != 0 &&
+ !a.contained_particle ().compositor ().is_a<
+ SemanticGraph::Choice> ());
+
+ if (min == 0 && max == 1)
+ {
+ os << "virtual bool" << endl
+ << epresent (a) << " ();"
+ << endl;
+ }
+ else if (max != 1)
+ {
+ os << "virtual bool" << endl
+ << enext (a) << " ()" << (pv ? " = 0" : "") << ";"
+ << endl;
+ }
+
+ if (stl)
+ {
+ os << "virtual void" << endl
+ << ename (a) << " (::std::string& ns, ::std::string& name)" <<
+ (pv ? " = 0;" : ";")
+ << endl;
+ }
+ else
+ {
+ os << "virtual void" << endl
+ << ename (a) << " (const char*& ns, const char*& name, " <<
+ "bool& free)" << (pv ? " = 0;" : ";")
+ << endl;
+ }
+
+ os << "virtual void" << endl
+ << eserialize (a) << " ()" << (pv ? " = 0;" : ";")
+ << endl;
+ }
+ }
+ };
+
+ struct AttributeCallback: Traversal::Attribute,
+ Traversal::AnyAttribute,
+ Context
+ {
+ AttributeCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ if (a.optional ())
+ {
+ os << "virtual bool" << endl
+ << epresent (a) << " ();"
+ << endl;
+ }
+
+ String const& ret (ret_type (a.type ()));
+
+ // Make it non-pure-virtual only if the return type is void.
+ //
+ os << "virtual " << ret << endl
+ << ename (a) << " ()" << (ret != L"void" ? " = 0;" : ";")
+ << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute& a)
+ {
+ os << "virtual bool" << endl
+ << enext (a) << " ();"
+ << endl;
+
+ if (stl)
+ {
+ os << "virtual void" << endl
+ << ename (a) << " (::std::string& ns, ::std::string& name);"
+ << endl;
+ }
+ else
+ {
+ os << "virtual void" << endl
+ << ename (a) << " (const char*& ns, const char*& name, " <<
+ "bool& free);"
+ << endl;
+ }
+
+ os << "virtual void" << endl
+ << eserialize (a) << " ();"
+ << endl;
+ }
+ };
+
+
+ //
+ //
+ struct ParticleAccessor: Traversal::Element, Context
+ {
+ ParticleAccessor (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ String const& serializer (eserializer (e));
+
+ os << "void" << endl
+ << serializer << " (" << fq_name (e.type ()) << "&);"
+ << endl;
+
+ if (poly_code && !anonymous (e.type ()))
+ {
+ os << "void" << endl
+ << eserializer (e) << " (" << serializer_map << "&);"
+ << endl;
+ }
+ }
+ };
+
+ struct AttributeAccessor: Traversal::Attribute, Context
+ {
+ AttributeAccessor (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ os << "void" << endl
+ << eserializer (a) << " (" << fq_name (a.type ()) << "&);"
+ << endl;
+ }
+ };
+
+
+ //
+ //
+ struct ParticleMember: Traversal::Element, Context
+ {
+ ParticleMember (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ String type (fq_name (e.type ()));
+
+ os << type << "* " << emember (e) << ";";
+
+ if (poly_code && !anonymous (e.type ()))
+ {
+ os << serializer_map << "* " << emember_map (e) << ";"
+ << endl;
+ }
+ }
+ };
+
+ struct AttributeMember: Traversal::Attribute, Context
+ {
+ AttributeMember (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ os << fq_name (a.type ()) << "* " << emember (a) << ";";
+ }
+ };
+
+
+ //
+ //
+ struct Complex : Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c),
+ compositor_callback_ (c),
+ particle_callback_ (c),
+ attribute_callback_ (c),
+ particle_accessor_ (c),
+ attribute_accessor_ (c),
+ particle_member_ (c),
+ attribute_member_ (c)
+ {
+ // Callback.
+ //
+ 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_;
+
+ // Accessor.
+ //
+ contains_compositor_accessor_ >> compositor_accessor_;
+ compositor_accessor_ >> contains_particle_accessor_;
+ contains_particle_accessor_ >> compositor_accessor_;
+ contains_particle_accessor_ >> particle_accessor_;
+
+ names_attribute_accessor_ >> attribute_accessor_;
+
+ // Member.
+ //
+ contains_compositor_member_ >> compositor_member_;
+ compositor_member_ >> contains_particle_member_;
+ contains_particle_member_ >> compositor_member_;
+ contains_particle_member_ >> particle_member_;
+
+ names_attribute_member_ >> attribute_member_;
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ String const& name (ename (c));
+
+ // 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));
+
+ Boolean hra (false); // Has required attribute.
+ if (ha)
+ {
+ RequiredAttributeTest test (hra);
+ Traversal::Names names_test (test);
+ names (c, names_test);
+ }
+
+ //
+ //
+ os << "class " << name << ": public ";
+
+ if (hb)
+ os << (mixin ? "virtual " : "") << fq_name (c.inherits ().base ());
+ else
+ os << complex_base;
+
+ os << "{"
+ << "public:" << endl
+ << "// Serializer callbacks. Override them in your " <<
+ "implementation." << endl
+ << "//" << endl
+ << endl;
+
+ // pre
+ //
+ String const& arg (arg_type (c));
+ Boolean same (hb && arg == arg_type (c.inherits ().base ()));
+
+ if (same)
+ {
+ os << "// virtual void" << endl;
+
+ if (arg == L"void")
+ os << "// pre ();" << endl;
+ else
+ os << "// pre (" << arg << ") = 0;" << endl;
+
+ os << endl;
+ }
+ else
+ {
+ os << "virtual void" << endl;
+
+ if (arg == L"void")
+ os << "pre ();";
+ else
+ os << "pre (" << arg << ") = 0;";
+
+ os << endl;
+ }
+
+ // Member callbacks.
+ //
+ if (!restriction)
+ {
+ if (ha || haa)
+ {
+ os << "// Attributes." << endl
+ << "//" << endl;
+
+ names (c, names_attribute_callback_);
+ }
+ }
+
+ if (he || hae)
+ {
+ if (!restriction)
+ {
+ os << "// Elements." << endl
+ << "//" << endl;
+ }
+
+ contains_compositor (c, contains_compositor_callback_);
+ }
+
+ // post
+ //
+ os << "// virtual void" << endl
+ << "// post ();" << endl
+ << endl;
+
+ //
+ //
+ if (!restriction && (he || ha))
+ {
+ os << "// Serializer construction API." << endl
+ << "//" << endl;
+
+ os << "void" << endl
+ << "serializers (";
+
+ {
+ SerializerParamDecl decl (*this, false);
+ decl.traverse (c);
+ }
+
+ os << ");"
+ << endl;
+
+ if (ha)
+ {
+ os << "// Individual attribute serializers." << endl
+ << "//" << endl;
+
+ names (c, names_attribute_accessor_);
+ }
+
+ if (he)
+ {
+ os << "// Individual element serializers." << endl
+ << "//" << endl;
+
+ contains_compositor (c, contains_compositor_accessor_);
+ }
+ }
+
+ if (!restriction && (he || ha) && reset)
+ {
+ os << "virtual void" << endl
+ << "_reset ();"
+ << endl;
+ }
+
+ // Default c-tor.
+ //
+ if (tiein || (!restriction && (he || ha)))
+ {
+ os << "// Constructor." << endl
+ << "//" << endl;
+
+ if (hb && tiein)
+ os << name << " (" << fq_name (c.inherits ().base ()) <<
+ "* tiein);"
+ << endl;
+ else
+ os << name << " ();"
+ << endl;
+ }
+
+ if (poly_code)
+ {
+ os << "public:" << endl
+ << "static const char*" << endl
+ << "_static_type ();"
+ << endl
+ << "virtual const char*" << endl
+ << "_dynamic_type () const;"
+ << endl;
+ }
+
+ // Implementation.
+ //
+ if (tiein || he || ha || hae || haa)
+ {
+ os << "// Implementation." << endl
+ << "//" << endl
+ << "public:" << endl;
+
+ // If our base has pure virtual functions, override them here.
+ //
+ if (tiein && hb)
+ inherits (c);
+
+ if (ha || haa)
+ {
+ os << "virtual void" << endl
+ << "_serialize_attributes ();"
+ << endl;
+ }
+
+ if (he || hae)
+ {
+ os << "virtual void" << endl
+ << "_serialize_content ();"
+ << endl;
+ }
+ }
+
+ if (tiein)
+ {
+ os << "protected:" << endl
+ << name << "* " << etiein (c) << ";"
+ << name << " (" << name << "*, void*);"
+ << endl;
+ }
+
+ if (!restriction && (he || ha))
+ {
+ os << "protected:" << endl;
+
+ if (ha)
+ names (c, names_attribute_member_);
+
+ if (he)
+ contains_compositor (c, contains_compositor_member_);
+ }
+
+ os << "};";
+ }
+
+ private:
+ //
+ //
+ CompositorCallback compositor_callback_;
+ ParticleCallback particle_callback_;
+ Traversal::ContainsCompositor contains_compositor_callback_;
+ Traversal::ContainsParticle contains_particle_callback_;
+
+ AttributeCallback attribute_callback_;
+ Traversal::Names names_attribute_callback_;
+
+ //
+ //
+ Traversal::Compositor compositor_accessor_;
+ ParticleAccessor particle_accessor_;
+ Traversal::ContainsCompositor contains_compositor_accessor_;
+ Traversal::ContainsParticle contains_particle_accessor_;
+
+ AttributeAccessor attribute_accessor_;
+ Traversal::Names names_attribute_accessor_;
+
+ //
+ //
+ Traversal::Compositor compositor_member_;
+ ParticleMember particle_member_;
+ Traversal::ContainsCompositor contains_compositor_member_;
+ Traversal::ContainsParticle contains_particle_member_;
+
+ AttributeMember attribute_member_;
+ Traversal::Names names_attribute_member_;
+ };
+
+ 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), xs_ns_ (xs_ns_name ())
+ {
+ impl_ns_ = "::xsde::cxx::serializer::";
+ impl_ns_ += (validation ? L"validating" : L"non_validating");
+
+ if (options.value<CLI::no_stl> ())
+ {
+ qname_type_ = L"const " + xs_ns_ + L"::qname*";
+ string_type_ = L"const char*";
+ }
+ else
+ {
+ qname_type_ = xs_ns_ + L"::qname";
+ string_type_ = L"::std::string";
+ }
+
+ string_seq_type_ = L"const " + xs_ns_ + L"::string_sequence*";
+ buffer_type_ = L"const " + xs_ns_ + L"::buffer*";
+
+ 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& t)
+ {
+ gen_typedef (t, "void");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnySimpleType& t)
+ {
+ gen_typedef (t, "void");
+ }
+
+ // Boolean.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Boolean& t)
+ {
+ gen_typedef (t, "bool");
+ }
+
+ // Integral types.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Byte& t)
+ {
+ gen_typedef (t, "signed char");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedByte& t)
+ {
+ gen_typedef (t, "unsigned char");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Short& t)
+ {
+ gen_typedef (t, "short");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedShort& t)
+ {
+ gen_typedef (t, "unsigned short");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Int& t)
+ {
+ gen_typedef (t, "int");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedInt& t)
+ {
+ gen_typedef (t, "unsigned int");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Long& t)
+ {
+ gen_typedef (t, long_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedLong& t)
+ {
+ gen_typedef (t, unsigned_long_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Integer& t)
+ {
+ gen_typedef (t, "long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NegativeInteger& t)
+ {
+ gen_typedef (t, "long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonPositiveInteger& t)
+ {
+ gen_typedef (t, "long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::PositiveInteger& t)
+ {
+ gen_typedef (t, "unsigned long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonNegativeInteger& t)
+ {
+ gen_typedef (t, "unsigned long");
+ }
+
+ // Floats.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Float& t)
+ {
+ gen_typedef (t, "float");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Double& t)
+ {
+ gen_typedef (t, "double");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Decimal& t)
+ {
+ gen_typedef (t, "double");
+ }
+
+ // Strings.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::String& t)
+ {
+ gen_typedef (t, string_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NormalizedString& t)
+ {
+ gen_typedef (t, string_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Token& t)
+ {
+ gen_typedef (t, string_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameToken& t)
+ {
+ nmtoken_ = gen_typedef (t, string_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameTokens& t)
+ {
+ // NMTOKENS uses NMTOKEN implementation to serialize individual
+ // items. As a result, we don't generate NMTOKENS if we didn't
+ // generate NMTOKEN. Here we assume NMTOKEN is handled before
+ // NMTOKENS.
+ //
+ if(nmtoken_)
+ gen_typedef (t, string_seq_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Name& t)
+ {
+ gen_typedef (t, string_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NCName& t)
+ {
+ gen_typedef (t, string_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Language& t)
+ {
+ gen_typedef (t, string_type_);
+ }
+
+ // Qualified name.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::QName& t)
+ {
+ gen_typedef (t, qname_type_);
+ }
+
+ // ID/IDREF.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Id& t)
+ {
+ gen_typedef (t, string_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRef& t)
+ {
+ idref_ = gen_typedef (t, string_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRefs& t)
+ {
+ // IDREFS uses IDREF implementation to serialize individual items.
+ // As a result, we don't generate IDREFS if we didn't generate
+ // IDREF. Here we assume IDREF is handled before IDREFS.
+ //
+ if (idref_)
+ gen_typedef (t, string_seq_type_);
+ }
+
+ // URI.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::AnyURI& t)
+ {
+ gen_typedef (t, string_type_);
+ }
+
+ // Binary.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Base64Binary& t)
+ {
+ gen_typedef (t, buffer_type_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::HexBinary& t)
+ {
+ gen_typedef (t, buffer_type_);
+ }
+
+
+ // Date/time.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Date& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::date");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::DateTime& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::date_time");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Duration& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::duration");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Day& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::gday");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Month& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::gmonth");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::MonthDay& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::gmonth_day");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Year& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::gyear");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::YearMonth& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::gyear_month");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Time& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::time");
+ }
+
+ // Entity.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entity&)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entities&)
+ {
+ }
+
+ private:
+ Boolean
+ gen_typedef (SemanticGraph::Type& t, String const& type)
+ {
+ if (ret_type (t) == type)
+ {
+ SemanticGraph::Context& c (t.context ());
+
+ String const& real_name (c.get<String> ("s:real-name"));
+ String const& name (c.get<String> ("s:name"));
+
+ os << "typedef " << real_name << " " << name << ";";
+
+ String const& real_impl (c.get<String> ("s:real-impl"));
+ String const& impl (c.get<String> ("s:impl"));
+
+ os << "typedef " << real_impl << " " << impl << ";"
+ << endl;
+
+ return true;
+ }
+
+ return false;
+ }
+
+ String xs_ns_;
+ String impl_ns_;
+ String qname_type_;
+ String string_type_;
+ String buffer_type_;
+ String string_seq_type_;
+ String long_type_;
+ String unsigned_long_type_;
+
+ Boolean idref_;
+ Boolean nmtoken_;
+ };
+
+ struct FundNamespace : Namespace, Context
+ {
+ FundNamespace (Context& c)
+ : Namespace (c), Context (c)
+ {
+ }
+
+ void
+ traverse (Type& ns)
+ {
+ pre (ns);
+
+ String impl ("::xsde::cxx::serializer::");
+ impl += (validation ? L"validating" : L"non_validating");
+
+ String const c (char_type);
+
+ os << "// Built-in XML Schema types mapping." << endl
+ << "//" << endl
+ << "using ::xsde::cxx::string_sequence;"
+ << "using ::xsde::cxx::qname;"
+ << "using ::xsde::cxx::buffer;"
+ << "using ::xsde::cxx::time_zone;"
+ << "using ::xsde::cxx::gday;"
+ << "using ::xsde::cxx::gmonth;"
+ << "using ::xsde::cxx::gyear;"
+ << "using ::xsde::cxx::gmonth_day;"
+ << "using ::xsde::cxx::gyear_month;"
+ << "using ::xsde::cxx::date;"
+ << "using ::xsde::cxx::time;"
+ << "using ::xsde::cxx::date_time;"
+ << "using ::xsde::cxx::duration;"
+ << endl;
+
+ os << "// Base serializer skeletons." << endl
+ << "//" << endl
+ << "using ::xsde::cxx::serializer::serializer_base;"
+ << "typedef " << impl << "::empty_content " <<
+ "serializer_empty_content;"
+ << "typedef " << impl << "::simple_content " <<
+ "serializer_simple_content;"
+ << "typedef " << impl << "::complex_content " <<
+ "serializer_complex_content;"
+ << endl;
+
+ if (poly_code)
+ {
+ os << "// Serializer map interface and default implementation." << endl
+ << "//" << endl
+ << "using ::xsde::cxx::serializer::serializer_map;"
+ << "using ::xsde::cxx::serializer::serializer_map_impl;"
+ << endl;
+
+ os << "// Substitution and inheritance hashmaps load querying." << endl
+ << "//" << endl
+ << "using ::xsde::cxx::serializer::serializer_smap_buckets;"
+ << "using ::xsde::cxx::serializer::serializer_smap_elements;"
+ << "using ::xsde::cxx::serializer::serializer_smap_bucket_buckets;"
+ << "using ::xsde::cxx::serializer::serializer_smap_bucket_elements;";
+
+ if (validation)
+ os << "using ::xsde::cxx::serializer::validating::serializer_imap_buckets;"
+ << "using ::xsde::cxx::serializer::validating::serializer_imap_elements;";
+
+ os << endl;
+ }
+
+ os << "// Serializer skeletons and implementations for the" << endl
+ << "// XML Schema built-in types." << endl
+ << "//" << endl;
+
+ names (ns);
+
+ os << "// Error codes." << endl
+ << "//" << endl;
+
+ if (!exceptions)
+ os << "using xsde::cxx::sys_error;";
+
+ os << "typedef xsde::cxx::serializer::genx::xml_error " <<
+ "serializer_xml_error;";
+
+ if (validation)
+ os << "typedef xsde::cxx::schema_error " <<
+ "serializer_schema_error;";
+
+ os << endl;
+
+ if (exceptions)
+ {
+ os << "// Exceptions." << endl
+ << "//" << endl
+ << "typedef xsde::cxx::serializer::exception " <<
+ "serializer_exception;"
+ << "typedef xsde::cxx::serializer::xml serializer_xml;";
+
+ if (validation)
+ os << "typedef xsde::cxx::serializer::schema " <<
+ "serializer_schema;";
+
+ os << endl;
+ }
+ else
+ os << "// Error object." << endl
+ << "//" << endl
+ << "typedef xsde::cxx::serializer::error serializer_error;"
+ << endl;
+
+ os << "// Document serializer." << endl
+ << "//" << endl
+ << "using xsde::cxx::serializer::genx::writer;"
+ << "using xsde::cxx::serializer::genx::document_simpl;"
+ << endl;
+
+ os << "// Serializer context." << endl
+ << "//" << endl
+ << "typedef xsde::cxx::serializer::context serializer_context;"
+ << endl;
+
+ post (ns);
+ }
+ };
+ }
+
+ Void
+ generate_serializer_header (Context& ctx, Boolean generate_xml_schema)
+ {
+ NarrowString extern_xml_schema;
+
+ if (!generate_xml_schema)
+ extern_xml_schema = ctx.options.value<CLI::extern_xml_schema> ();
+
+ if (extern_xml_schema)
+ {
+ String name (ctx.hxx_expr->merge (extern_xml_schema));
+
+ ctx.os << "#include " << ctx.process_include_path (name) << endl
+ << endl;
+
+ // Generate includes that came from the type map.
+ //
+ if (ctx.schema_root.context ().count ("s:includes"))
+ {
+ typedef Cult::Containers::Set<String> Includes;
+
+ Includes& is (
+ ctx.schema_root.context ().get<Includes> ("s:includes"));
+
+ for (Includes::ConstReverseIterator i (is.rbegin ());
+ i != is.rend (); ++i)
+ {
+ ctx.os << "#include " << *i << endl;
+ }
+
+ ctx.os << endl;
+ }
+ }
+ else
+ {
+ ctx.os << "#include <xsde/config.h>" << endl
+ << endl;
+
+ // std::string or xsde::cxx::string is used in wildcard API.
+ //
+ if (ctx.stl)
+ {
+ ctx.os << "#include <string>" << endl
+ << endl;
+ }
+ else
+ {
+ ctx.os << "#include <xsde/cxx/string.hxx>" << endl
+ << endl;
+ }
+
+ // Data types.
+ //
+ ctx.os << "#include <xsde/cxx/serializer/xml-schema.hxx>" << endl
+ << endl;
+
+ // Error handling.
+ //
+ if (ctx.exceptions)
+ ctx.os << "#include <xsde/cxx/serializer/exceptions.hxx>" << endl
+ << endl;
+ else
+ {
+ ctx.os << "#include <xsde/cxx/sys-error.hxx>" << endl;
+
+ if (ctx.validation)
+ ctx.os << "#include <xsde/cxx/schema-error.hxx>" << endl;
+
+ ctx.os << "#include <xsde/cxx/serializer/error.hxx>" << endl
+ << "#include <xsde/cxx/serializer/genx/xml-error.hxx>" << endl;
+
+ ctx.os << endl;
+ }
+
+ // Polymorphism support.
+ //
+ if (ctx.poly_code)
+ {
+ ctx.os << "#include <xsde/cxx/serializer/map.hxx>" << endl
+ << "#include <xsde/cxx/serializer/substitution-map-load.hxx>" << endl;
+
+ if (ctx.validation)
+ ctx.os << "#include <xsde/cxx/serializer/validating/inheritance-map-load.hxx>" << endl;
+
+ ctx.os << endl;
+ }
+
+ // Serializers.
+ //
+ if (ctx.validation)
+ ctx.os << "#include <xsde/cxx/serializer/validating/serializer.hxx>" << endl
+ << "#include <xsde/cxx/serializer/validating/xml-schema-sskel.hxx>" << endl
+ << "#include <xsde/cxx/serializer/validating/xml-schema-simpl.hxx>" << endl
+ << endl;
+ else
+ ctx.os << "#include <xsde/cxx/serializer/non-validating/serializer.hxx>" << endl
+ << "#include <xsde/cxx/serializer/non-validating/xml-schema-sskel.hxx>" << endl
+ << "#include <xsde/cxx/serializer/non-validating/xml-schema-simpl.hxx>" << endl
+ << endl;
+
+ // Document.
+ //
+ ctx.os << "#include <xsde/cxx/serializer/genx/document.hxx>" << endl
+ << endl;
+
+ // Generate includes that came from the type map.
+ //
+ if (ctx.schema_root.context ().count ("s:includes"))
+ {
+ typedef Cult::Containers::Set<String> Includes;
+
+ Includes& is (
+ ctx.schema_root.context ().get<Includes> ("s:includes"));
+
+ for (Includes::ConstReverseIterator i (is.rbegin ());
+ i != is.rend (); ++i)
+ {
+ ctx.os << "#include " << *i << endl;
+ }
+
+ ctx.os << endl;
+ }
+
+ // Generate fundamental types.
+ //
+ 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);
+ }
+ 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);
+ }
+ }
+
+ // Generate user type mapping.
+ //
+ if (!generate_xml_schema)
+ {
+ Traversal::Schema schema;
+
+ Traversal::Sources sources;
+ Includes includes (ctx, Includes::header);
+ Traversal::Names schema_names;
+
+ Namespace ns (ctx);
+ Traversal::Names names;
+
+ schema >> includes;
+ schema >> sources >> schema;
+ schema >> schema_names >> ns >> names;
+
+ List list (ctx);
+ Union union_ (ctx);
+ Complex complex (ctx);
+ Enumeration enumeration (ctx);
+
+ names >> list;
+ names >> union_;
+ names >> complex;
+ names >> enumeration;
+
+ BaseOverride base_override (ctx);
+ Traversal::Inherits inherits_override;
+
+ complex >> inherits_override;
+ enumeration >> inherits_override;
+ inherits_override >> base_override;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+ }
+}
diff --git a/xsde/cxx/serializer/serializer-header.hxx b/xsde/cxx/serializer/serializer-header.hxx
new file mode 100644
index 0000000..64c63ab
--- /dev/null
+++ b/xsde/cxx/serializer/serializer-header.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/serializer/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_SERIALIZER_SERIALIZER_HEADER_HXX
+#define CXX_SERIALIZER_SERIALIZER_HEADER_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/serializer/elements.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ Void
+ generate_serializer_header (Context&, Boolean generate_xml_schema);
+ }
+}
+
+#endif // CXX_SERIALIZER_SERIALIZER_HEADER_HXX
diff --git a/xsde/cxx/serializer/serializer-inline.cxx b/xsde/cxx/serializer/serializer-inline.cxx
new file mode 100644
index 0000000..8caa791
--- /dev/null
+++ b/xsde/cxx/serializer/serializer-inline.cxx
@@ -0,0 +1,631 @@
+// file : xsde/cxx/serializer/serializer-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/serializer/serializer-inline.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ namespace
+ {
+ struct Enumeration: Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (tiein)
+ {
+ String const& name (ename (e));
+ String const& impl (etiein (e));
+
+ // We have to use "real" (non-typedef) base name in base
+ // initializer because of some broken compilers (EVC 4.0).
+ //
+ SemanticGraph::Type& base (e.inherits ().base ());
+ String fq_base (fq_name (base));
+ String real_fq_base (real_fq_name (base));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ os << inl
+ << name << "::" << endl
+ << name << " (" << fq_base << "* tiein)" << endl
+ << ": " << real_fq_base << " (tiein, 0)," << endl
+ << " " << impl << " (0)"
+ << "{"
+ << "}";
+
+ os << inl
+ << name << "::" << endl
+ << name << " (" << name << "* impl, void*)" << endl
+ << ": " << real_fq_base << " (impl, 0)," << endl
+ << " " << impl << " (impl)"
+ << "{"
+ << "}";
+ }
+ }
+ };
+
+
+ //
+ //
+ struct List: Traversal::List, Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String const& name (ename (l));
+ SemanticGraph::Type& t (l.argumented ().type ());
+ String item_type (fq_name (t));
+
+ String item (unclash (name, "item"));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ // item_serializer
+ //
+ os << inl
+ << "void " << name << "::" << endl
+ << unclash (name, "item_serializer") << " (" <<
+ item_type << "& " << item << ")"
+ << "{"
+ << "this->_xsde_" << item << "_ = &" << item << ";"
+ << "}";
+
+ // serializers
+ //
+ os << inl
+ << "void " << name << "::" << endl
+ << "serializers (" << item_type << "& " << item << ")"
+ << "{"
+ << "this->_xsde_" << item << "_ = &" << item << ";"
+ << "}";
+
+ // c-tor
+ //
+ os << inl
+ << name << "::" << endl
+ << name << " ()" << endl
+ << ": ";
+
+ if (tiein)
+ os << etiein (l) << " (0)," << endl
+ << " ";
+
+ os << "_xsde_" << item << "_ (0)"
+ << "{"
+ << "}";
+
+ if (tiein)
+ {
+ os << inl
+ << name << "::" << endl
+ << name << " (" << name << "* impl, void*)" << endl
+ << ": " << simple_base << " (impl, 0)," << endl
+ << " " << etiein (l) << " (impl)," << endl
+ << " _xsde_" << item << "_ (0)"
+ << "{"
+ << "}";
+ }
+ }
+ };
+
+ struct Union: Traversal::Union, Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ if (tiein)
+ {
+ String const& name (ename (u));
+ String const& impl (etiein (u));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ //
+ //
+ os << inl
+ << name << "::" << endl
+ << name << " ()" << endl
+ << ": " << impl << " (0)"
+ << "{"
+ << "}";
+
+ //
+ //
+ os << inl
+ << name << "::" << endl
+ << name << " (" << name << "* impl, void*)" << endl
+ << ": " << simple_base << " (impl, 0)," << endl
+ << " " << impl << " (impl)"
+ << "{"
+ << "}";
+ }
+ }
+ };
+
+ //
+ //
+ struct ParticleAccessor: Traversal::Element, Context
+ {
+ ParticleAccessor (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ String const& scope (ename (e.scope ()));
+ String const& serializer (eserializer (e));
+
+ os << inl
+ << "void " << scope << "::" << endl
+ << serializer << " (" << fq_name (e.type ()) << "& s)"
+ << "{"
+ << "this->" << emember (e) << " = &s;"
+ << "}";
+
+ if (poly_code && !anonymous (e.type ()))
+ {
+ os << inl
+ << "void " << scope << "::" << endl
+ << serializer << " (" << serializer_map << "& m)"
+ << "{"
+ << "this->" << emember_map (e) << " = &m;"
+ << "}";
+ }
+ }
+ };
+
+ struct AttributeAccessor: Traversal::Attribute, Context
+ {
+ AttributeAccessor (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ String const& name (ename (a));
+
+ os << inl
+ << "void " << ename (a.scope ()) << "::" << endl
+ << eserializer (a) << " (" << fq_name (a.type ()) << "& " <<
+ name << ")"
+ << "{"
+ << "this->" << emember (a) << " = &" << name << ";"
+ << "}";
+ }
+ };
+
+ //
+ //
+ struct ParticleMemberSet: Traversal::Element, Context
+ {
+ ParticleMemberSet (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ os << "this->" << emember (e) << " = &" << ename (e) << ";";
+ }
+ };
+
+ struct AttributeMemberSet: Traversal::Attribute, Context
+ {
+ AttributeMemberSet (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ os << "this->" << emember (a) << " = &" << ename (a) << ";";
+ }
+ };
+
+ struct BaseMemberSet: Traversal::Complex,
+ Traversal::List,
+ Context
+ {
+ BaseMemberSet (Context& c)
+ : Context (c)
+ {
+ inherits_ >> *this;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ inherits (c, inherits_);
+
+ if (!restriction_p (c))
+ {
+ names (c);
+ contains_compositor (c);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::List& l)
+ {
+ String const& name (ename (l));
+ String item (unclash (name, "item"));
+
+ os << "this->_xsde_" << item << "_ = &" << name << "_item;";
+ }
+
+ private:
+ Traversal::Inherits inherits_;
+ };
+
+ //
+ //
+ struct ParticleMemberInit: Traversal::Element, Context
+ {
+ ParticleMemberInit (Context& c, Boolean comma)
+ : Context (c), first_ (!comma)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (first_)
+ first_ = false;
+ else
+ os << "," << endl << " ";
+
+ os << emember (e) << " (0)";
+
+ if (poly_code && !anonymous (e.type ()))
+ {
+ os << "," << endl
+ << " " << emember_map (e) << " (0)";
+ }
+ }
+
+ private:
+ Boolean first_;
+ };
+
+ struct AttributeMemberInit: Traversal::Attribute, Context
+ {
+ AttributeMemberInit (Context& c, Boolean comma)
+ : Context (c), first_ (!comma)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ if (first_)
+ first_ = false;
+ else
+ os << "," << endl << " ";
+
+ os << emember (a) << " (0)";
+ }
+
+ Boolean
+ comma () const
+ {
+ return !first_;
+ }
+
+ private:
+ Boolean first_;
+ };
+
+
+ //
+ //
+ struct Complex: Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c),
+ particle_accessor_ (c),
+ attribute_accessor_ (c),
+ base_set_ (c),
+ particle_set_ (c),
+ attribute_set_ (c)
+ {
+ // Accessor.
+ //
+ contains_compositor_accessor_ >> compositor_accessor_;
+ compositor_accessor_ >> contains_particle_accessor_;
+ contains_particle_accessor_ >> compositor_accessor_;
+ contains_particle_accessor_ >> particle_accessor_;
+
+ names_attribute_accessor_ >> attribute_accessor_;
+
+ // Member set.
+ //
+ inherits_base_set_ >> base_set_;
+ base_set_ >> contains_compositor_set_;
+ base_set_ >> names_attribute_set_;
+
+ contains_compositor_set_ >> compositor_set_;
+ compositor_set_ >> contains_particle_set_;
+ contains_particle_set_ >> compositor_set_;
+ contains_particle_set_ >> particle_set_;
+
+ names_attribute_set_ >> attribute_set_;
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ Boolean hb (c.inherits_p ());
+ Boolean he (has<Traversal::Element> (c));
+ Boolean ha (has<Traversal::Attribute> (c));
+ Boolean restriction (restriction_p (c));
+
+ if (!(tiein || (!restriction && (he || ha))))
+ return;
+
+ String const& name (ename (c));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ if (!restriction && (he || ha))
+ {
+ // <name>_serializer ()
+ //
+ if (ha)
+ names (c, names_attribute_accessor_);
+
+ if (he)
+ contains_compositor (c, contains_compositor_accessor_);
+
+ // serializer ()
+ //
+
+ os << inl
+ << "void " << name << "::" << endl
+ << "serializers (";
+
+ {
+ SerializerParamDecl decl (*this, true);
+ decl.traverse (c);
+ }
+
+ os << ")"
+ << "{";
+
+ inherits (c, inherits_base_set_);
+
+ if (ha)
+ names (c, names_attribute_set_);
+
+ if (he)
+ contains_compositor (c, contains_compositor_set_);
+
+ os << "}";
+ }
+
+ // We have to use "real" (non-typedef) base name in base
+ // initializer because of some broken compilers (EVC 4.0).
+ //
+ String real_fq_base;
+
+ if (hb && tiein)
+ real_fq_base = real_fq_name (c.inherits ().base ());
+
+ // Default c-tor.
+ //
+ os << inl
+ << name << "::" << endl;
+
+ if (hb && tiein)
+ os << name << " (" << fq_name (c.inherits ().base ()) <<
+ "* tiein)" << endl;
+ else
+ os << name << " ()" << endl;
+
+ os << ": ";
+
+ Boolean comma (false);
+
+ if (hb && tiein)
+ {
+ os << real_fq_base << " (tiein, 0)";
+ comma = true;
+ }
+
+ if (tiein)
+ {
+ if (comma)
+ os << "," << endl << " ";
+
+ os << etiein (c) << " (0)";
+ comma = true;
+ }
+
+ if (!restriction && (he || ha))
+ {
+ if (ha)
+ {
+ AttributeMemberInit attribute_init (*this, comma);
+ Traversal::Names names_attribute_init;
+
+ names_attribute_init >> attribute_init;
+
+ names (c, names_attribute_init);
+
+ comma = attribute_init.comma ();
+ }
+
+ if (he)
+ {
+ Traversal::Compositor compositor_init;
+ ParticleMemberInit particle_init (*this, comma);
+ Traversal::ContainsCompositor contains_compositor_init;
+ Traversal::ContainsParticle contains_particle_init;
+
+ contains_compositor_init >> compositor_init;
+ compositor_init >> contains_particle_init;
+ contains_particle_init >> compositor_init;
+ contains_particle_init >> particle_init;
+
+ contains_compositor (c, contains_compositor_init);
+ }
+ }
+
+ os << "{"
+ << "}";
+
+ // Tiein c-tor.
+ //
+ if (tiein)
+ {
+ os << inl
+ << name << "::" << endl
+ << name << " (" << name << "* impl, void*)" << endl
+ << ": ";
+
+ if (hb)
+ os << real_fq_base << " (impl, 0)," << endl;
+ else
+ os << complex_base << " (impl, 0)," << endl;
+
+ os << " " << etiein (c) << " (impl)";
+
+ Boolean comma (true);
+
+ if (!restriction && (he || ha))
+ {
+ if (ha)
+ {
+ AttributeMemberInit attribute_init (*this, comma);
+ Traversal::Names names_attribute_init;
+
+ names_attribute_init >> attribute_init;
+
+ names (c, names_attribute_init);
+
+ comma = attribute_init.comma ();
+ }
+
+ if (he)
+ {
+ Traversal::Compositor compositor_init;
+ ParticleMemberInit particle_init (*this, comma);
+ Traversal::ContainsCompositor contains_compositor_init;
+ Traversal::ContainsParticle contains_particle_init;
+
+ contains_compositor_init >> compositor_init;
+ compositor_init >> contains_particle_init;
+ contains_particle_init >> compositor_init;
+ contains_particle_init >> particle_init;
+
+ contains_compositor (c, contains_compositor_init);
+ }
+ }
+
+ os << "{"
+ << "}";
+ }
+ }
+
+ private:
+ //
+ //
+ Traversal::Compositor compositor_accessor_;
+ ParticleAccessor particle_accessor_;
+ Traversal::ContainsCompositor contains_compositor_accessor_;
+ Traversal::ContainsParticle contains_particle_accessor_;
+
+ AttributeAccessor attribute_accessor_;
+ Traversal::Names names_attribute_accessor_;
+
+ //
+ //
+ BaseMemberSet base_set_;
+ Traversal::Inherits inherits_base_set_;
+
+ Traversal::Compositor compositor_set_;
+ ParticleMemberSet particle_set_;
+ Traversal::ContainsCompositor contains_compositor_set_;
+ Traversal::ContainsParticle contains_particle_set_;
+
+ AttributeMemberSet attribute_set_;
+ Traversal::Names names_attribute_set_;
+ };
+ }
+
+ Void
+ generate_serializer_inline (Context& ctx)
+ {
+ // Emit "weak" header includes that are used in the file-per-type
+ // compilation model.
+ //
+ if (!ctx.options.value<CLI::generate_inline> ())
+ {
+ 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;
+
+ Enumeration enumeration (ctx);
+ List list (ctx);
+ Union union_ (ctx);
+ Complex complex (ctx);
+
+ names >> enumeration;
+ names >> list;
+ names >> union_;
+ names >> complex;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+}
diff --git a/xsde/cxx/serializer/serializer-inline.hxx b/xsde/cxx/serializer/serializer-inline.hxx
new file mode 100644
index 0000000..8cde76d
--- /dev/null
+++ b/xsde/cxx/serializer/serializer-inline.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/serializer/serializer-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_SERIALIZER_SERIALIZER_INLINE_HXX
+#define CXX_SERIALIZER_SERIALIZER_INLINE_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/serializer/elements.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ Void
+ generate_serializer_inline (Context&);
+ }
+}
+
+#endif // CXX_SERIALIZER_SERIALIZER_INLINE_HXX
diff --git a/xsde/cxx/serializer/serializer-source.cxx b/xsde/cxx/serializer/serializer-source.cxx
new file mode 100644
index 0000000..ec30add
--- /dev/null
+++ b/xsde/cxx/serializer/serializer-source.cxx
@@ -0,0 +1,2703 @@
+// file : xsde/cxx/serializer/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/serializer/serializer-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ namespace
+ {
+ // Override classes override pure virtual functions in the base.
+ // Should be in sync with definition generators below. Used in
+ // tiein implementation.
+ //
+
+ struct CompositorCallbackOverride: Traversal::Choice,
+ Traversal::Sequence,
+ Context
+ {
+ CompositorCallbackOverride (Context& c, String const& scope)
+ : Context (c), scope_ (scope)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ if (c.contains_begin () != c.contains_end ())
+ {
+ UnsignedLong min (c.min ()), max (c.max ());
+
+ if (min != 0)
+ {
+ SemanticGraph::Type& t (
+ dynamic_cast<SemanticGraph::Type&> (scope (c)));
+
+ String const& impl (etiein (t));
+
+ if (max != 1)
+ {
+ String const& next (enext (c));
+
+ os << "bool " << scope_ << "::" << endl
+ << next << " ()"
+ << "{"
+ << "assert (this->" << impl << ");"
+ << "return this->" << impl << "->" << next << " ();"
+ << "}";
+ }
+
+ String const& arm (earm (c));
+
+ os << fq_name (t) << "::" << earm_tag (c) << " " <<
+ scope_ << "::" << endl
+ << arm << " ()"
+ << "{"
+ << "assert (this->" << impl << ");"
+ << "return this->" << impl << "->" << arm << " ();"
+ << "}";
+ }
+
+ Traversal::Choice::traverse (c);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ UnsignedLong min (s.min ()), max (s.max ());
+
+ if (max != 1 && min != 0)
+ {
+ String const& impl (
+ etiein (dynamic_cast<SemanticGraph::Type&> (scope (s))));
+
+ String const& next (enext (s));
+
+ os << "bool " << scope_ << "::" << endl
+ << next << " ()"
+ << "{"
+ << "assert (this->" << impl << ");"
+ << "return this->" << impl << "->" << next << " ();"
+ << "}";
+ }
+
+ Traversal::Sequence::traverse (s);
+ }
+
+ private:
+ SemanticGraph::Scope&
+ scope (SemanticGraph::Compositor& c)
+ {
+ SemanticGraph::Compositor* root (&c);
+
+ while (root->contained_particle_p ())
+ root = &root->contained_particle ().compositor ();
+
+ return dynamic_cast<SemanticGraph::Scope&> (
+ root->contained_compositor ().container ());
+ }
+
+ private:
+ String const& scope_;
+ };
+
+ struct ParticleCallbackOverride: Traversal::Element,
+ Traversal::Any,
+ Context
+ {
+ ParticleCallbackOverride (Context& c, String const& scope)
+ : Context (c), scope_ (scope)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ UnsignedLong min (e.min ()), max (e.max ());
+
+ String const& impl (
+ etiein (dynamic_cast<SemanticGraph::Type&> (e.scope ())));
+
+ if (max != 1 && min != 0)
+ {
+ String const& next (enext (e));
+
+ os << "bool " << scope_ << "::" << endl
+ << next << " ()"
+ << "{"
+ << "assert (this->" << impl << ");"
+ << "return this->" << impl << "->" << next << " ();"
+ << "}";
+ }
+
+ String const& ret (ret_type (e.type ()));
+
+ if (ret != L"void")
+ {
+ String const& name (ename (e));
+
+ os << ret << " " << scope_ << "::" << endl
+ << name << " ()"
+ << "{"
+ << "assert (this->" << impl << ");"
+ << "return this->" << impl << "->" << name << " ();"
+ << "}";
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ UnsignedLong min (a.min ()), max (a.max ());
+
+ if (min != 0 &&
+ !a.contained_particle ().compositor ().is_a<
+ SemanticGraph::Choice> ())
+ {
+ String const& impl (
+ etiein (dynamic_cast<SemanticGraph::Type&> (a.scope ())));
+
+ if (max != 1)
+ {
+ String const& next (enext (a));
+
+ os << "bool " << scope_ << "::" << endl
+ << next << " ()"
+ << "{"
+ << "assert (this->" << impl << ");"
+ << "return this->" << impl << "->" << next << " ();"
+ << "}";
+ }
+
+ String const& name (ename (a));
+
+ if (stl)
+ {
+ os << "void " << scope_ << "::" << endl
+ << name << " (::std::string& ns, ::std::string& name)"
+ << "{"
+ << "assert (this->" << impl << ");"
+ << "this->" << impl << "->" << name << " (ns, name);"
+ << "}";
+ }
+ else
+ {
+ os << "void " << scope_ << "::" << endl
+ << name << " (const char*& ns, const char*& name, " <<
+ "bool& free)"
+ << "{"
+ << "assert (this->" << impl << ");"
+ << "this->" << impl << "->" << name << " (ns, name, free);"
+ << "}";
+ }
+
+ String const& serialize (eserialize (a));
+
+ os << "void " << scope_ << "::" << endl
+ << serialize << " ()"
+ << "{"
+ << "assert (this->" << impl << ");"
+ << "this->" << impl << "->" << serialize << " ();"
+ << "}";
+ }
+ }
+
+ private:
+ String const& scope_;
+ };
+
+ struct AttributeCallbackOverride: Traversal::Attribute, Context
+ {
+ AttributeCallbackOverride (Context& c, String const& scope)
+ : Context (c), scope_ (scope)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ String const& ret (ret_type (a.type ()));
+
+ if (ret != L"void")
+ {
+ String const& impl (
+ etiein (dynamic_cast<SemanticGraph::Type&> (a.scope ())));
+
+ String const& name (ename (a));
+
+ os << ret << " " << scope_ << "::" << endl
+ << name << " ()"
+ << "{"
+ << "assert (this->" << impl << ");"
+ << "return this->" << impl << "->" << name << " ();"
+ << "}";
+ }
+ }
+
+ private:
+ String const& scope_;
+ };
+
+ struct BaseOverride: Traversal::Type,
+ Traversal::Enumeration,
+ Traversal::List,
+ Traversal::Union,
+ Traversal::Complex,
+ Context
+ {
+ BaseOverride (Context& c, String const& scope)
+ : Context (c),
+ scope_ (scope),
+ compositor_callback_ (c, scope),
+ particle_callback_ (c, scope),
+ attribute_callback_ (c, scope)
+ {
+ 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 (SemanticGraph::Type& t)
+ {
+ // pre
+ //
+ String const& arg (arg_type (t));
+
+ if (arg != L"void")
+ {
+ String const& impl (etiein (t));
+
+ os << "void " << scope_ << "::" << endl
+ << "pre (" << arg << " x)"
+ << "{"
+ << "assert (this->" << impl << ");"
+ << "this->" << impl << "->pre (x);"
+ << "}";
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Enumeration& e)
+ {
+ SemanticGraph::Type& t (e);
+ traverse (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::List& l)
+ {
+ SemanticGraph::Type& t (l);
+ traverse (t);
+
+ // item
+ //
+ String const& ret (ret_type (l.argumented ().type ()));
+
+ if (ret != L"void")
+ {
+ String item (unclash (ename (l), "item"));
+ String const& impl (etiein (l));
+
+ os << ret << " " << scope_ << "::" << endl
+ << item << " ()"
+ << "{"
+ << "assert (this->" << impl << ");"
+ << "return this->" << impl << "->" << item << " ();"
+ << "}";
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Union& u)
+ {
+ SemanticGraph::Type& t (u);
+ traverse (t);
+
+ // serialize_content
+ //
+ String const& impl (etiein (u));
+
+ os << "void " << scope_ << "::" << endl
+ << "_serialize_content ()"
+ << "{"
+ << "assert (this->" << impl << ");"
+ << "this->" << impl << "->_serialize_content ();"
+ << "}";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ SemanticGraph::Type& t (c);
+ traverse (t);
+
+ // Member callbacks.
+ //
+ if (!restriction_p (c))
+ {
+ Traversal::Complex::names (c, names_attribute_callback_);
+ Traversal::Complex::contains_compositor (
+ c, contains_compositor_callback_);
+ }
+ }
+
+ private:
+ String const& scope_;
+
+ CompositorCallbackOverride compositor_callback_;
+ ParticleCallbackOverride particle_callback_;
+ Traversal::ContainsCompositor contains_compositor_callback_;
+ Traversal::ContainsParticle contains_particle_callback_;
+
+ AttributeCallbackOverride attribute_callback_;
+ Traversal::Names names_attribute_callback_;
+ };
+
+ //
+ //
+
+ struct Enumeration: Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ String const& name (ename (e));
+ String const& arg (arg_type (e));
+ SemanticGraph::Type& base (e.inherits ().base ());
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ if (arg != arg_type (base) && arg == L"void")
+ {
+ os << "void " << name << "::" << endl
+ << "pre ()"
+ << "{";
+
+ if (tiein)
+ {
+ String const& impl (etiein (e));
+
+ os << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->pre ();";
+ }
+
+ os << "}";
+ }
+
+ if (poly_code)
+ {
+ String id (e.name ());
+
+ if (String ns = xml_ns_name (e))
+ {
+ id += L' ';
+ id += ns;
+ }
+
+ os << "const char* " << name << "::" << endl
+ << "_static_type ()"
+ << "{"
+ << "return " << strlit (id) << ";"
+ << "}";
+
+ os << "const char* " << name << "::" << endl
+ << "_dynamic_type () const"
+ << "{"
+ << "return _static_type ();"
+ << "}";
+
+ if (validation)
+ {
+ Boolean gen (!anonymous (e));
+
+ // We normally don't need to enter anonymous types into
+ // the inheritance map. The only exception is when an
+ // anonymous types is defined inside an element that
+ // is a member of a substitution group.
+ //
+ if (!gen)
+ {
+ // The first instance that this anonymous type classifies
+ // is the prototype for others if any.
+ //
+ SemanticGraph::Instance& i (
+ e.classifies_begin ()->instance ());
+
+ if (SemanticGraph::Element* e =
+ dynamic_cast<SemanticGraph::Element*> (&i))
+ {
+ if (e->substitutes_p ())
+ gen = true;
+ }
+ }
+
+ if (gen)
+ {
+ os << "static" << endl
+ << "const ::xsde::cxx::serializer::validating::" <<
+ "inheritance_map_entry" << endl
+ << "_xsde_" << name << "_inheritance_map_entry_ (" << endl
+ << name << "::_static_type ()," << endl
+ << fq_name (base) << "::_static_type ());"
+ << endl;
+ }
+ }
+ }
+
+ if (tiein)
+ {
+ // If our base has pure virtual functions, override them here.
+ //
+ BaseOverride t (*this, name);
+ t.dispatch (base);
+ }
+ }
+ };
+
+ //
+ //
+ struct List: Traversal::List, Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String const& name (ename (l));
+ SemanticGraph::Type& t (l.argumented ().type ());
+
+ String const& ret (ret_type (t));
+ String const& arg (arg_type (t));
+
+ String item (unclash (name, "item"));
+ String item_next (unclash (name, "item_next"));
+ String inst (L"_xsde_" + item + L"_");
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ String impl;
+
+ if (tiein)
+ impl = etiein (l);
+
+ // pre
+ //
+ if (arg_type (l) == L"void")
+ {
+ os << "void " << name << "::" << endl
+ << "pre ()"
+ << "{";
+
+ if (tiein)
+ os << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->pre ();";
+
+ os << "}";
+ }
+
+ // item
+ //
+ os << "bool " << name << "::" << endl
+ << item_next << " ()"
+ << "{";
+
+ if (tiein)
+ os << "return this->" << impl << " ? this->" << impl << "->" <<
+ item_next << " () : false;";
+ else
+ os << "return false;";
+
+ os << "}";
+
+ if (ret == L"void")
+ {
+ os << ret << " " << name << "::" << endl
+ << item << " ()"
+ << "{";
+
+ if (tiein)
+ os << "if (this->" << impl << ")" << endl
+ << "return this->" << impl << "->" << item << " ();";
+
+ os << "}";
+ }
+
+ // reset
+ //
+ if (reset)
+ {
+ os << "void " << name << "::" << endl
+ << "_reset ()"
+ << "{"
+ << simple_base << "::_reset ();"
+ << endl
+ << "if (this->" << inst << ")" << endl
+ << "this->" << inst << "->_reset ();"
+ << "}";
+ }
+
+ // serialize_content
+ //
+ os << "void " << name << "::" << endl
+ << "_serialize_content ()"
+ << "{";
+
+ os << "bool first = true;"
+ << "::xsde::cxx::serializer::context& ctx = this->_context ();"
+ << endl;
+
+ if (exceptions && !validation)
+ {
+ os << "while (this->" << item_next << " ())"
+ << "{"
+ << "if (this->" << inst << ")"
+ << "{";
+
+ if (ret == L"void")
+ os << "this->" << item << " ();"
+ << "this->" << inst << "->pre ();";
+ else
+ os << arg << " r = this->" << item << " ();"
+ << "this->" << inst << "->pre (r);";
+
+ os << endl
+ << "if (!first)" << endl
+ << "this->_characters (\" \", 1);"
+ << "else" << endl
+ << "first = false;"
+ << endl;
+
+ os << "this->" << inst << "->_pre_impl (ctx);"
+ << "this->" << inst << "->_serialize_content ();"
+ << "this->" << inst << "->_post_impl ();"
+ << "this->" << inst << "->post ();";
+
+ os << "}"
+ << "}";
+ }
+ else
+ {
+ os << "while (this->" << item_next << " ())"
+ << "{"
+ << "if (this->" << inst << ")"
+ << "{";
+
+ if (ret == L"void")
+ os << "this->" << item << " ();";
+ else
+ os << arg << " r = this->" << item << " ();";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "break;"
+ << endl;
+
+ if (ret == L"void")
+ os << "this->" << inst << "->pre ();";
+ else
+ os << "this->" << inst << "->pre (r);";
+
+ if (!exceptions)
+ {
+ os << endl
+ << "if (this->" << inst << "->_error_type ())" << endl
+ << "this->" << inst << "->_copy_error (ctx);"
+ << endl;
+
+ os << "if (ctx.error_type ())" << endl
+ << "break;";
+ }
+
+ if (!exceptions)
+ os << endl
+ << "if (!first)"
+ << "{"
+ << "if (!this->_characters (\" \", 1))" << endl
+ << "break;"
+ << "}";
+ else
+ os << endl
+ << "if (!first)" << endl
+ << "this->_characters (\" \", 1);";
+
+ os << "else" << endl
+ << "first = false;"
+ << endl;
+
+ os << "this->" << inst << "->_pre_impl (ctx);";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "break;"
+ << endl;
+
+ os << "this->" << inst << "->_serialize_content ();";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "break;"
+ << endl;
+
+ os << "this->" << inst << "->_post_impl ();";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "break;"
+ << endl;
+
+ os << "this->" << inst << "->post ();";
+
+ if (!exceptions)
+ {
+ os << endl
+ << "if (this->" << inst << "->_error_type ())" << endl
+ << "this->" << inst << "->_copy_error (ctx);"
+ << endl;
+
+ os << "if (ctx.error_type ())" << endl
+ << "break;";
+ }
+
+ os << "}" // No check for error here since we return anyway.
+ << "}";
+ }
+
+ os << "}"; // _serialize_content
+
+ //
+ //
+ if (poly_code)
+ {
+ String id (l.name ());
+
+ if (String ns = xml_ns_name (l))
+ {
+ id += L' ';
+ id += ns;
+ }
+
+ os << "const char* " << name << "::" << endl
+ << "_static_type ()"
+ << "{"
+ << "return " << strlit (id) << ";"
+ << "}";
+
+ os << "const char* " << name << "::" << endl
+ << "_dynamic_type () const"
+ << "{"
+ << "return _static_type ();"
+ << "}";
+ }
+ }
+ };
+
+ //
+ //
+ struct Union: Traversal::Union, Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ String const& name (ename (u));
+ String const& arg (arg_type (u));
+
+ if (arg == L"void" || poly_code)
+ {
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+ }
+
+ if (arg == L"void")
+ {
+ os << "void " << name << "::" << endl
+ << "pre ()"
+ << "{";
+
+ if (tiein)
+ {
+ String const& impl (etiein (u));
+
+ os << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->pre ();";
+ }
+
+ os << "}";
+ }
+
+ if (poly_code)
+ {
+ String id (u.name ());
+
+ if (String ns = xml_ns_name (u))
+ {
+ id += L' ';
+ id += ns;
+ }
+
+ os << "const char* " << name << "::" << endl
+ << "_static_type ()"
+ << "{"
+ << "return " << strlit (id) << ";"
+ << "}";
+
+ os << "const char* " << name << "::" << endl
+ << "_dynamic_type () const"
+ << "{"
+ << "return _static_type ();"
+ << "}";
+ }
+ }
+ };
+
+ //
+ //
+ struct ParticleReset: Traversal::Element, Context
+ {
+ ParticleReset (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ String const& m (emember (e));
+
+ os << "if (this->" << m << ")" << endl
+ << "this->" << m << "->_reset ();"
+ << endl;
+
+ if (poly_code && !anonymous (e.type ()))
+ {
+ String const& map (emember_map (e));
+
+ os << "if (this->" << map << ")" << endl
+ << "this->" << map << "->reset ();"
+ << endl;
+ }
+ }
+ };
+
+ struct AttributeReset: Traversal::Attribute, Context
+ {
+ AttributeReset (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ String const& m (emember (a));
+
+ os << "if (this->" << m << ")" << endl
+ << "this->" << m << "->_reset ();"
+ << endl;
+ }
+ };
+
+ // Complex serialization code.
+ //
+ struct Compositor: Traversal::All,
+ Traversal::Choice,
+ Traversal::Sequence,
+ Context
+ {
+ Compositor (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ // For the all compositor, maxOccurs=1 and minOccurs={0,1}.
+ //
+ UnsignedLong min (a.min ());
+
+ if (min == 0)
+ os << "if (this->" << epresent (a) << " ())"
+ << "{";
+
+ Traversal::All::traverse (a);
+
+ if (min == 0)
+ {
+ os << "}";
+
+ if (!exceptions)
+ {
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+ }
+ }
+
+ 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 << "if (this->" << epresent (c) << " ())"
+ << "{";
+ }
+ else if (max != 1)
+ {
+ os << "while (this->" << enext (c) << " ())"
+ << "{";
+ }
+ else if (!exceptions)
+ {
+ os << "{";
+ }
+
+ if (exceptions)
+ os << "switch (this->" << earm (c) << " ())";
+ else
+ os << earm_tag (c) << " t = this->" << earm (c) << " ();"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl
+ << "switch (t)";
+
+
+ os << "{";
+
+ for (SemanticGraph::Choice::ContainsIterator
+ i (c.contains_begin ()); i != c.contains_end (); ++i)
+ {
+ os << "case " << etag (i->particle ()) << ":"
+ << "{";
+
+ edge_traverser ().dispatch (*i);
+
+ os << "break;"
+ << "}";
+ }
+
+ // In case of restriction we may not handle all enumerators
+ // in which case default will help avoid warnings.
+ //
+ os << "default:"
+ << "{"
+ << "break;"
+ << "}"
+ << "}"; // switch
+
+ if (min == 0 || max != 1)
+ {
+ os << "}";
+
+ if (!exceptions)
+ {
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+ }
+ else if (!exceptions)
+ {
+ os << "}";
+ }
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ UnsignedLong min (s.min ()), max (s.max ());
+
+ if (min == 0 && max == 1)
+ {
+ os << "if (this->" << epresent (s) << " ())"
+ << "{";
+ }
+ else if (max != 1)
+ {
+ os << "while (this->" << enext (s) << " ())"
+ << "{";
+ }
+
+ Traversal::Sequence::traverse (s);
+
+
+ if (min == 0 || max != 1)
+ {
+ os << "}";
+
+ if (!exceptions)
+ {
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+ }
+ }
+ };
+
+ struct Particle: Traversal::Element,
+ Traversal::Any,
+ Context
+ {
+ Particle (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ UnsignedLong min (e.min ()), max (e.max ());
+
+ String const& name (ename (e));
+
+ os << "// " << name << endl
+ << "//" << endl;
+
+ if (min == 0 && max == 1)
+ {
+ os << "if (this->" << epresent (e) << " ())";
+ }
+ else if (max != 1)
+ {
+ os << "while (this->" << enext (e) << " ())";
+ }
+
+ os << "{";
+
+ String const& ret (ret_type (e.type ()));
+ String const& arg (arg_type (e.type ()));
+ String fq_type (fq_name (e.type ()));
+
+ Boolean poly (poly_code && !anonymous (e.type ()));
+ String inst (poly ? String (L"s") : L"this->" + emember (e));
+
+ if (poly)
+ os << "ctx.type_id (0);";
+
+ if (ret == L"void")
+ os << "this->" << name << " ();"
+ << endl;
+ else
+ os << arg << " r = this->" << name << " ();"
+ << endl;
+
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ if (poly)
+ {
+ // In case of mixin we use virtual inheritance and only
+ // dynamic_cast can be used.
+ //
+ String cast (mixin ? L"dynamic_cast" : L"static_cast");
+
+ os << "const void* t = ctx.type_id ();"
+ << fq_type << "* " << inst << " = 0;"
+ << endl
+ << "if (t == 0 && this->" << emember (e) << " != 0)" << endl
+ << inst << " = this->" << emember (e) << ";"
+ << "else if (this->" << emember_map (e) << " != 0)" << endl
+ << inst << " = " << cast << "< " << fq_type << "* > (" << endl
+ << "this->" << emember_map (e) << "->find (t));"
+ << endl;
+ }
+
+ os << "if (" << inst << ")"
+ << "{";
+
+ if (exceptions)
+ {
+ if (ret == L"void")
+ os << inst << "->pre ();";
+ else
+ os << inst << "->pre (r);";
+
+ if (poly)
+ {
+ os << endl
+ << "const char* dt = 0;"
+ << "if (t != 0)"
+ << "{"
+ << "dt = " << inst << "->_dynamic_type ();"
+ << "if (strcmp (dt, " << fq_type <<
+ "::_static_type ()) == 0)" << endl
+ << "dt = 0;"
+ << "}";
+ }
+
+ // Only a globally-defined element can be a subst-group root.
+ //
+ if (poly && e.global ())
+ {
+ if (e.qualified () && e.namespace_ ().name ())
+ os << "const char* ns = " <<
+ strlit (e.namespace_ ().name ()) << ";";
+ else
+ os << "const char* ns = 0;";
+
+ os << "const char* n = " << strlit (e.name ()) << ";"
+ << endl;
+
+ os << "if (dt != 0 && " <<
+ "::xsde::cxx::serializer::substitution_map_instance ()" <<
+ ".check (ns, n, dt))" << endl
+ << "dt = 0;"
+ << endl;
+
+ os << "if (ns != 0)" << endl
+ << "this->_start_element (ns, n);"
+ << "else" << endl
+ << "this->_start_element (n);";
+ }
+ else
+ {
+ if (e.qualified () && e.namespace_ ().name ())
+ os << "this->_start_element (" <<
+ strlit (e.namespace_ ().name ()) << ", " <<
+ strlit (e.name ()) << ");";
+ else
+ os << "this->_start_element (" << strlit (e.name ()) << ");";
+ }
+
+ if (poly)
+ {
+ // Set xsi:type if necessary.
+ //
+ os << endl
+ << "if (dt != 0)" << endl
+ << "this->_set_type (dt);"
+ << endl;
+ }
+
+ os << inst << "->_pre_impl (ctx);"
+ << inst << "->_serialize_attributes ();"
+ << inst << "->_serialize_content ();"
+ << inst << "->_post_impl ();"
+ << "this->_end_element ();"
+ << inst << "->post ();";
+ }
+ else
+ {
+ if (ret == L"void")
+ os << inst << "->pre ();";
+ else
+ os << inst << "->pre (r);";
+
+ // Note that after pre() we need to check both the serializer
+ // and context error states because of the recursive parsing.
+ //
+ os << endl
+ << "if (" << inst << "->_error_type ())" << endl
+ << inst << "->_copy_error (ctx);"
+ << endl;
+
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ if (poly)
+ {
+ os << "const char* dt = 0;"
+ << "if (t != 0)"
+ << "{"
+ << "dt = " << inst << "->_dynamic_type ();"
+ << "if (strcmp (dt, " << fq_type <<
+ "::_static_type ()) == 0)" << endl
+ << "dt = 0;"
+ << "}";
+ }
+
+ // Only a globally-defined element can be a subst-group root.
+ //
+ if (poly && e.global ())
+ {
+ if (e.qualified () && e.namespace_ ().name ())
+ os << "const char* ns = " <<
+ strlit (e.namespace_ ().name ()) << ";";
+ else
+ os << "const char* ns = 0;";
+
+ os << "const char* n = " << strlit (e.name ()) << ";"
+ << endl;
+
+ os << "if (dt != 0 && " <<
+ "::xsde::cxx::serializer::substitution_map_instance ()" <<
+ ".check (ns, n, dt))" << endl
+ << "dt = 0;"
+ << endl;
+
+ os << "if (ns != 0)"
+ << "{"
+ << "if (!this->_start_element (ns, n))" << endl
+ << "return;"
+ << "}"
+ << "else"
+ << "{"
+ << "if (!this->_start_element (n))" << endl
+ << "return;"
+ << "}";
+ }
+ else
+ {
+ if (e.qualified () && e.namespace_ ().name ())
+ os << "if (!this->_start_element (" <<
+ strlit (e.namespace_ ().name ()) << ", " <<
+ strlit (e.name ()) << "))" << endl
+ << "return;"
+ << endl;
+ else
+ os << "if (!this->_start_element (" <<
+ strlit (e.name ()) << "))" << endl
+ << "return;"
+ << endl;
+ }
+
+ if (poly)
+ {
+ // Set xsi:type if necessary.
+ //
+ os << "if (dt != 0)"
+ << "{"
+ << "if (!this->_set_type (dt))" << endl
+ << "return;"
+ << "}";
+ }
+
+ os << inst << "->_pre_impl (ctx);";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ os << inst << "->_serialize_attributes ();";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ os << inst << "->_serialize_content ();";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ os << inst << "->_post_impl ();";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ os << "if (!this->_end_element ())" << endl
+ << "return;"
+ << endl;
+
+ os << inst << "->post ();";
+
+ // Note that after post() we need to check both the serializer
+ // and context error states because of the recursive parsing.
+ //
+ os << endl
+ << "if (" << inst << "->_error_type ())" << endl
+ << inst << "->_copy_error (ctx);"
+ << endl;
+
+ os << "if (ctx.error_type ())" << endl
+ << "return;";
+ }
+
+ os << "}" // if (inst)
+ << "}";
+
+ if ((min == 0 || max != 1) && !exceptions)
+ {
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ UnsignedLong min (a.min ()), max (a.max ());
+
+ if (min == 0 && max == 1)
+ {
+ os << "if (this->" << epresent (a) << " ())";
+
+ }
+ else if (max != 1)
+ {
+ os << "while (this->" << enext (a) << " ())";
+ }
+
+ os << "{";
+
+ if (stl)
+ {
+ os << "::std::string ns, name;";
+
+ if (exceptions)
+ {
+ os << "this->" << ename (a) << " (ns, name);"
+ << endl
+ << "if (ns.empty ())" << endl
+ << "this->_start_element (name.c_str ());"
+ << "else" << endl
+ << "this->_start_element (ns.c_str (), name.c_str ());"
+ << endl
+ << "this->" << eserialize (a) << " ();"
+ << "this->_end_element ();";
+ }
+ else
+ {
+ os << "this->" << ename (a) << " (ns, name);"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl
+ << "if (ns.empty ())"
+ << "{"
+ << "if (!this->_start_element (name.c_str ()))" << endl
+ << "return;"
+ << "}"
+ << "else"
+ << "{"
+ << "if (!this->_start_element (ns.c_str (), " <<
+ "name.c_str ()))" << endl
+ << "return;"
+ << "}"
+ << "this->" << eserialize (a) << " ();"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl
+ << "if (!this->_end_element ())" << endl
+ << "return;";
+ }
+ }
+ else
+ {
+ os << "const char* ns = 0;"
+ << "const char* name;"
+ << "bool free;";
+
+ if (exceptions)
+ {
+ os << "this->" << ename (a) << " (ns, name, free);"
+ << endl
+ << "::xsde::cxx::string auto_ns, auto_name;"
+ << "if (free)"
+ << "{"
+ << "auto_ns.attach (const_cast< char* > (ns));"
+ << "auto_name.attach (const_cast< char* > (name));"
+ << "}"
+ << "if (ns == 0 || *ns == '\\0')" << endl
+ << "this->_start_element (name);"
+ << "else" << endl
+ << "this->_start_element (ns, name);"
+ << endl
+ << "this->" << eserialize (a) << " ();"
+ << "this->_end_element ();";
+ }
+ else
+ {
+ os << "this->" << ename (a) << " (ns, name, free);"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl
+ << "bool r;"
+ << "if (ns == 0 || *ns == '\\0')" << endl
+ << "r = this->_start_element (name);"
+ << "else" << endl
+ << "r = this->_start_element (ns, name);"
+ << endl
+ << "if (free)"
+ << "{"
+ << "delete[] ns;"
+ << "delete[] name;"
+ << "}"
+ << "if (!r)" << endl
+ << "return;"
+ << endl
+ << "this->" << eserialize (a) << " ();"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl
+ << "if (!this->_end_element ())" << endl
+ << "return;";
+ }
+ }
+
+ os << "}";
+
+ if (!exceptions && (min == 0 || max != 1))
+ {
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+ }
+
+ };
+
+ struct Attribute: Traversal::Attribute,
+ Traversal::AnyAttribute,
+ Context
+ {
+ Attribute (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ String const& name (ename (a));
+
+ os << "// " << name << endl
+ << "//" << endl;
+
+ if (a.optional ())
+ {
+ os << "if (this->" << epresent (a) << " ())";
+ }
+
+ os << "{";
+
+ String const& inst (emember (a));
+ String const& ret (ret_type (a.type ()));
+ String const& arg (arg_type (a.type ()));
+
+ if (ret == L"void")
+ os << "this->" << name << " ();"
+ << endl;
+ else
+ os << arg << " r = this->" << name << " ();"
+ << endl;
+
+ if (!exceptions)
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ os << "if (this->" << inst << ")"
+ << "{";
+
+ if (exceptions)
+ {
+ if (ret == L"void")
+ os << "this->" << inst << "->pre ();";
+ else
+ os << "this->" << inst << "->pre (r);";
+
+ if (a.qualified () && a.namespace_ ().name ())
+ os << "this->_start_attribute (" <<
+ strlit (a.namespace_ ().name ()) << ", " <<
+ strlit (a.name ()) << ");";
+ else
+ os << "this->_start_attribute (" << strlit (a.name ()) << ");";
+
+ os << "this->" << inst << "->_pre_impl (ctx);"
+ << "this->" << inst << "->_serialize_content ();"
+ << "this->" << inst << "->_post_impl ();"
+ << "this->_end_attribute ();"
+ << "this->" << inst << "->post ();";
+ }
+ else
+ {
+ if (ret == L"void")
+ os << "this->" << inst << "->pre ();";
+ else
+ os << "this->" << inst << "->pre (r);";
+
+ os << endl
+ << "if (this->" << inst << "->_error_type ())" << endl
+ << "this->" << inst << "->_copy_error (ctx);"
+ << endl;
+
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ if (a.qualified () && a.namespace_ ().name ())
+ os << "if (!this->_start_attribute (" <<
+ strlit (a.namespace_ ().name ()) << ", " <<
+ strlit (a.name ()) << "))" << endl
+ << "return;"
+ << endl;
+ else
+ os << "if (!this->_start_attribute (" <<
+ strlit (a.name ()) << "))" << endl
+ << "return;"
+ << endl;
+
+ os << "this->" << inst << "->_pre_impl (ctx);";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ os << "this->" << inst << "->_serialize_content ();";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ os << "this->" << inst << "->_post_impl ();";
+
+ os << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+
+ os << "if (!this->_end_attribute ())" << endl
+ << "return;"
+ << endl;
+
+ os << "this->" << inst << "->post ();";
+
+ os << endl
+ << "if (this->" << inst << "->_error_type ())" << endl
+ << "this->" << inst << "->_copy_error (ctx);"
+ << endl;
+
+ os << "if (ctx.error_type ())" << endl
+ << "return;";
+ }
+
+ os << "}" // if (inst)
+ << "}";
+
+ if (a.optional () && !exceptions)
+ {
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute& a)
+ {
+ os << "while (this->" << enext (a) << " ())"
+ << "{";
+
+ if (stl)
+ {
+ os << "::std::string ns, name;";
+
+ if (exceptions)
+ {
+ os << "this->" << ename (a) << " (ns, name);"
+ << endl
+ << "if (ns.empty ())" << endl
+ << "this->_start_attribute (name.c_str ());"
+ << "else" << endl
+ << "this->_start_attribute (ns.c_str (), name.c_str ());"
+ << endl
+ << "this->" << eserialize (a) << " ();"
+ << "this->_end_attribute ();";
+ }
+ else
+ {
+ os << "this->" << ename (a) << " (ns, name);"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl
+ << "if (ns.empty ())"
+ << "{"
+ << "if (!this->_start_attribute (name.c_str ()))" << endl
+ << "return;"
+ << "}"
+ << "else"
+ << "{"
+ << "if (!this->_start_attribute (ns.c_str (), " <<
+ "name.c_str ()))" << endl
+ << "return;"
+ << "}"
+ << "this->" << eserialize (a) << " ();"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl
+ << "if (!this->_end_attribute ())" << endl
+ << "return;";
+ }
+ }
+ else
+ {
+ os << "const char* ns = 0;"
+ << "const char* name;"
+ << "bool free;";
+
+ if (exceptions)
+ {
+ os << "this->" << ename (a) << " (ns, name, free);"
+ << endl
+ << "::xsde::cxx::string auto_ns, auto_name;"
+ << "if (free)"
+ << "{"
+ << "auto_ns.attach (const_cast< char* > (ns));"
+ << "auto_name.attach (const_cast< char* > (name));"
+ << "}"
+ << "if (ns == 0 || *ns == '\\0')" << endl
+ << "this->_start_attribute (name);"
+ << "else" << endl
+ << "this->_start_attribute (ns, name);"
+ << endl
+ << "this->" << eserialize (a) << " ();"
+ << "this->_end_attribute ();";
+ }
+ else
+ {
+ os << "this->" << ename (a) << " (ns, name, free);"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl
+ << "bool r;"
+ << "if (ns == 0 || *ns == '\\0')" << endl
+ << "r = this->_start_attribute (name);"
+ << "else" << endl
+ << "r = this->_start_attribute (ns, name);"
+ << endl
+ << "if (free)"
+ << "{"
+ << "delete[] ns;"
+ << "delete[] name;"
+ << "}"
+ << "if (!r)" << endl
+ << "return;"
+ << endl
+ << "this->" << eserialize (a) << " ();"
+ << endl
+ << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl
+ << "if (!this->_end_attribute ())" << endl
+ << "return;";
+ }
+ }
+
+ os << "}";
+
+ if (!exceptions)
+ {
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+ }
+ };
+
+ // Callbacks.
+ //
+ struct CompositorCallback: Traversal::All,
+ Traversal::Choice,
+ Traversal::Sequence,
+ Context
+ {
+ CompositorCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ if (!a.context ().count ("xsd-frontend-restriction-correspondence"))
+ {
+ // For the all compositor, maxOccurs=1 and minOccurs={0,1}.
+ //
+ if (a.min () == 0)
+ {
+ SemanticGraph::Scope& s (scope (a));
+ String const& present (epresent (a));
+
+ os << "bool " << ename (s) << "::" << endl
+ << present << " ()"
+ << "{";
+
+ if (tiein)
+ {
+ String const& impl (
+ etiein (dynamic_cast<SemanticGraph::Type&> (s)));
+
+ os << "return this->" << impl << " ? this->" << impl <<
+ "->" << present << " () : false;";
+ }
+ else
+ os << "return false;";
+
+ os << "}";
+ }
+ }
+
+ Traversal::All::traverse (a);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ if (SemanticGraph::Compositor* b = correspondent (c))
+ {
+ UnsignedLong smin (c.min ());
+ UnsignedLong bmax (b->max ());
+
+ if (bmax != 1 && smin == 0)
+ {
+ String const& next (enext (c));
+ String const& present (epresent (c));
+
+ SemanticGraph::Scope& scope (this->scope (c));
+
+ os << "bool " << ename (scope) << "::" << endl
+ << present << " ()"
+ << "{";
+
+ if (tiein)
+ {
+ String const& impl (
+ etiein (dynamic_cast<SemanticGraph::Type&> (scope)));
+
+ os << "return this->" << impl << " ? this->" << impl <<
+ "->" << present << " () : this->" << next << " ();";
+ }
+ else
+ os << "return this->" << next << " ();";
+
+ os << "}";
+ }
+ }
+ else
+ {
+ UnsignedLong min (c.min ()), max (c.max ());
+
+ if (min == 0)
+ {
+ SemanticGraph::Scope& scope (this->scope (c));
+ String const& s (ename (scope));
+
+ String impl;
+
+ if (tiein)
+ impl = etiein (dynamic_cast<SemanticGraph::Type&> (scope));
+
+ if (max == 1)
+ {
+ String const& present (epresent (c));
+
+ os << "bool " << s << "::" << endl
+ << present << " ()"
+ << "{";
+
+ if (tiein)
+ os << "return this->" << impl << " ? this->" << impl <<
+ "->" << present << " () : false;";
+ else
+ os << "return false;";
+
+ os << "}";
+ }
+ else
+ {
+ String const& next (enext (c));
+
+ os << "bool " << s << "::" << endl
+ << next << " ()"
+ << "{";
+
+ if (tiein)
+ os << "return this->" << impl << " ? this->" << impl <<
+ "->" << next << " () : false;";
+ else
+ os << "return false;";
+
+ os << "}";
+ }
+
+ String const& arm (earm (c));
+ String const& tag (etag (c.contains_begin ()->particle ()));
+
+ os << s << "::" << earm_tag (c) << " " << s << "::" << endl
+ << arm << " ()"
+ << "{";
+
+ if (tiein)
+ os << "return this->" << impl << " ? this->" << impl <<
+ "->" << arm << " () : " << tag << ";";
+ else
+ os << "return " << tag << ";";
+
+ os << "}";
+ }
+ }
+
+ Traversal::Choice::traverse (c);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ if (SemanticGraph::Compositor* b = correspondent (s))
+ {
+ UnsignedLong smin (s.min ());
+ UnsignedLong bmax (b->max ());
+
+ if (bmax != 1 && smin == 0)
+ {
+ String const& next (enext (s));
+ String const& present (epresent (s));
+
+ SemanticGraph::Scope& scope (this->scope (s));
+
+ os << "bool " << ename (scope) << "::" << endl
+ << present << " ()"
+ << "{";
+
+ if (tiein)
+ {
+ String const& impl (
+ etiein (dynamic_cast<SemanticGraph::Type&> (scope)));
+
+ os << "return this->" << impl << " ? this->" << impl <<
+ "->" << present << " () : this->" << next << " ();";
+ }
+ else
+ os << "return this->" << next << " ();";
+
+ os << "}";
+ }
+ }
+ else
+ {
+ UnsignedLong min (s.min ()), max (s.max ());
+
+ if (min == 0)
+ {
+ SemanticGraph::Scope& scope (this->scope (s));
+
+ String impl;
+
+ if (tiein)
+ impl = etiein (dynamic_cast<SemanticGraph::Type&> (scope));
+
+ if (max == 1)
+ {
+ String const& present (epresent (s));
+
+ os << "bool " << ename (scope) << "::" << endl
+ << present << " ()"
+ << "{";
+
+ if (tiein)
+ os << "return this->" << impl << " ? this->" << impl <<
+ "->" << present << " () : false;";
+ else
+ os << "return false;";
+
+ os << "}";
+ }
+ else
+ {
+ String const& next (enext (s));
+
+ os << "bool " << ename (scope) << "::" << endl
+ << next << " ()"
+ << "{";
+
+ if (tiein)
+ os << "return this->" << impl << " ? this->" << impl <<
+ "->" << next << " () : false;";
+ else
+ os << "return false;";
+
+ os << "}";
+ }
+ }
+ }
+
+ Traversal::Sequence::traverse (s);
+ }
+
+ private:
+ SemanticGraph::Scope&
+ scope (SemanticGraph::Compositor& c)
+ {
+ SemanticGraph::Compositor* root (&c);
+
+ while (root->contained_particle_p ())
+ root = &root->contained_particle ().compositor ();
+
+ return dynamic_cast<SemanticGraph::Scope&> (
+ root->contained_compositor ().container ());
+ }
+ };
+
+ struct ParticleCallback: Traversal::Element,
+ Traversal::Any,
+ Context
+ {
+ ParticleCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (SemanticGraph::Element* b = correspondent (e))
+ {
+ if (b->max () != 1 && e.min () == 0)
+ {
+ String const& next (enext (e));
+ String const& present (epresent (e));
+
+ os << "bool " << ename (e.scope ()) << "::" << endl
+ << present << " ()"
+ << "{";
+
+ if (tiein)
+ {
+ String const& impl (
+ etiein (dynamic_cast<SemanticGraph::Type&> (e.scope ())));
+
+ os << "return this->" << impl << " ? this->" << impl <<
+ "->" << present << " () : this->" << next << " ();";
+ }
+ else
+ os << "return this->" << next << " ();";
+
+ os << "}";
+ }
+ }
+ else
+ {
+ UnsignedLong min (e.min ()), max (e.max ());
+ String const& s (ename (e.scope ()));
+
+ String impl;
+
+ if (tiein)
+ impl = etiein (dynamic_cast<SemanticGraph::Type&> (e.scope ()));
+
+ if (min == 0)
+ {
+ if (max == 1)
+ {
+ String const& present (epresent (e));
+
+ os << "bool " << s << "::" << endl
+ << present << " ()"
+ << "{";
+
+ if (tiein)
+ os << "return this->" << impl << " ? this->" << impl <<
+ "->" << present << " () : false;";
+ else
+ os << "return false;";
+
+ os << "}";
+ }
+ else
+ {
+ String const& next (enext (e));
+
+ os << "bool " << s << "::" << endl
+ << next << " ()"
+ << "{";
+
+ if (tiein)
+ os << "return this->" << impl << " ? this->" << impl <<
+ "->" << next << " () : false;";
+ else
+ os << "return false;";
+
+ os << "}";
+ }
+ }
+
+ // The callback is non-pure-virtual only if the return type
+ // is void.
+ //
+ if (ret_type (e.type ()) == L"void")
+ {
+ String const& name (ename (e));
+
+ os << "void " << s << "::" << endl
+ << name << " ()"
+ << "{";
+
+ if (tiein)
+ os << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->" << name << " ();";
+
+ os << "}";
+ }
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ if (SemanticGraph::Any* b = correspondent (a))
+ {
+ if (b->max () != 1 && a.min () == 0)
+ {
+ String const& next (enext (a));
+ String const& present (epresent (a));
+
+ os << "bool " << ename (a.scope ()) << "::" << endl
+ << present << " ()"
+ << "{";
+
+ if (tiein)
+ {
+ String const& impl (
+ etiein (dynamic_cast<SemanticGraph::Type&> (a.scope ())));
+
+ os << "return this->" << impl << " ? this->" << impl <<
+ "->" << present << " () : this->" << next << " ();";
+ }
+ else
+ os << "return this->" << next << " ();";
+
+ os << "}";
+ }
+ }
+ else
+ {
+ UnsignedLong min (a.min ()), max (a.max ());
+
+ if (min == 0 ||
+ a.contained_particle ().compositor ().is_a<
+ SemanticGraph::Choice> ())
+ {
+ String const& s (ename (a.scope ()));
+ String impl;
+
+ if (tiein)
+ impl = etiein (dynamic_cast<SemanticGraph::Type&> (a.scope ()));
+
+ if (min == 0 && max == 1)
+ {
+ String const& present (epresent (a));
+
+ os << "bool " << s << "::" << endl
+ << present << " ()"
+ << "{";
+
+ if (tiein)
+ os << "return this->" << impl << " ? this->" << impl <<
+ "->" << present << " () : false;";
+ else
+ os << "return false;";
+
+ os << "}";
+ }
+ else if (max != 1)
+ {
+ String const& next (enext (a));
+
+ os << "bool " << s << "::" << endl
+ << next << " ()"
+ << "{";
+
+ if (tiein)
+ os << "return this->" << impl << " ? this->" << impl <<
+ "->" << next << " () : false;";
+ else
+ os << "return false;";
+
+ os << "}";
+ }
+
+ String const& name (ename (a));
+
+ if (stl)
+ {
+ if (tiein)
+ os << "void " << s << "::" << endl
+ << name << " (::std::string& ns, ::std::string& n)"
+ << "{"
+ << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->" << name << " (ns, n);"
+ << "}";
+
+ else
+ os << "void " << s << "::" << endl
+ << name << " (::std::string&, ::std::string&)"
+ << "{"
+ << "}";
+ }
+ else
+ {
+ if (tiein)
+ os << "void " << s << "::" << endl
+ << name << " (const char*& ns, const char*& n, bool& f)"
+ << "{"
+ << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->" << name << " (ns, n, f);"
+ << "}";
+ else
+ os << "void " << s << "::" << endl
+ << name << " (const char*&, const char*&, bool&)"
+ << "{"
+ << "}";
+ }
+
+ String const& serialize (eserialize (a));
+
+ os << "void " << s << "::" << endl
+ << serialize << " ()"
+ << "{";
+
+ if (tiein)
+ os << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->" << serialize << " ();";
+
+ os << "}";
+ }
+ }
+
+ }
+ };
+
+ struct AttributeCallback: Traversal::Attribute,
+ Traversal::AnyAttribute,
+ Context
+ {
+ AttributeCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ String const& s (ename (a.scope ()));
+
+ String impl;
+
+ if (tiein)
+ impl = etiein (dynamic_cast<SemanticGraph::Type&> (a.scope ()));
+
+ if (a.optional ())
+ {
+ String const& present (epresent (a));
+
+ os << "bool " << s << "::" << endl
+ << present << " ()"
+ << "{";
+
+ if (tiein)
+ os << "return this->" << impl << " ? this->" << impl <<
+ "->" << present << " () : false;";
+ else
+ os << "return false;";
+
+ os << "}";
+ }
+
+ // The callback is non-pure-virtual only if the return type
+ // is void.
+ //
+ if (ret_type (a.type ()) == L"void")
+ {
+ String const& name (ename (a));
+
+ os << "void " << s << "::" << endl
+ << name << " ()"
+ << "{";
+
+ if (tiein)
+ os << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->" << name << " ();";
+
+ os << "}";
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute& a)
+ {
+ String const& s (ename (a.scope ()));
+
+ String impl;
+
+ if (tiein)
+ impl = etiein (dynamic_cast<SemanticGraph::Type&> (a.scope ()));
+
+ String const& next (enext (a));
+
+ os << "bool " << s << "::" << endl
+ << next << " ()"
+ << "{";
+
+ if (tiein)
+ os << "return this->" << impl << " ? this->" << impl <<
+ "->" << next << " () : false;";
+ else
+ os << "return false;";
+
+ os << "}";
+
+ String const& name (ename (a));
+
+ if (stl)
+ {
+ if (tiein)
+ os << "void " << s << "::" << endl
+ << name << " (::std::string& ns, ::std::string& n)"
+ << "{"
+ << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->" << name << " (ns, n);"
+ << "}";
+
+ else
+ os << "void " << s << "::" << endl
+ << name << " (::std::string&, ::std::string&)"
+ << "{"
+ << "}";
+ }
+ else
+ {
+ if (tiein)
+ os << "void " << s << "::" << endl
+ << name << " (const char*& ns, const char*& n, bool& f)"
+ << "{"
+ << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->" << name << " (ns, n, f);"
+ << "}";
+ else
+ os << "void " << s << "::" << endl
+ << name << " (const char*&, const char*&, bool&)"
+ << "{"
+ << "}";
+ }
+
+ String const& serialize (eserialize (a));
+
+ os << "void " << s << "::" << endl
+ << serialize << " ()"
+ << "{";
+
+ if (tiein)
+ os << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->" << serialize << " ();";
+
+ os << "}";
+ }
+ };
+
+ //
+ //
+ struct Complex : Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c),
+ compositor_callback_ (c),
+ particle_callback_ (c),
+ attribute_callback_ (c),
+ particle_reset_ (c),
+ attribute_reset_ (c),
+ compositor_ (c),
+ particle_ (c),
+ attribute_ (c)
+ {
+ // Callback.
+ //
+ 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_;
+
+ // Reset.
+ //
+ contains_compositor_reset_ >> compositor_reset_;
+ compositor_reset_ >> contains_particle_reset_;
+ contains_particle_reset_ >> compositor_reset_;
+ contains_particle_reset_ >> particle_reset_;
+
+ names_attribute_reset_ >> attribute_reset_;
+
+ // Serialization code.
+ //
+ contains_compositor_ >> compositor_;
+ compositor_ >> contains_particle_;
+ contains_particle_ >> compositor_;
+ contains_particle_ >> particle_;
+
+ names_attribute_ >> attribute_;
+ }
+
+ virtual Void
+ traverse (Type& 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 (arg_type (c));
+ Boolean same (hb && arg == arg_type (c.inherits ().base ()));
+
+ String const& name (ename (c));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ // pre
+ //
+ if (!same && arg == L"void")
+ {
+ os << "void " << name << "::" << endl
+ << "pre ()"
+ << "{";
+
+ if (tiein)
+ {
+ String const& impl (etiein (c));
+
+ os << "if (this->" << impl << ")" << endl
+ << "this->" << impl << "->pre ();";
+ }
+
+ os << "}";
+ }
+
+ // Member callbacks.
+ //
+ if (!restriction_p (c))
+ {
+ if (ha || haa)
+ names (c, names_attribute_callback_);
+ }
+
+ if (he || hae)
+ contains_compositor (c, contains_compositor_callback_);
+
+ // reset
+ //
+ if (!restriction_p (c) && (he || ha) && reset)
+ {
+ os << "void " << name << "::" << endl
+ << "_reset ()"
+ << "{";
+
+ // Avoid recursion in case of recursive parsing.
+ //
+ if (he)
+ os << "if (this->resetting_)" << endl
+ << "return;"
+ << endl;
+
+ // Reset the base. We cannot use the fully-qualified base name
+ // directly because of some broken compilers (EVC 4.0).
+ //
+ String base (unclash (name, "base"));
+
+ os << "typedef ";
+
+ if (hb)
+ os << fq_name (c.inherits ().base ());
+ else
+ os << complex_base;
+
+ os << " " << base << ";"
+ << base << "::_reset ();"
+ << endl;
+
+ // Reset member serializer.
+ //
+
+ if (ha)
+ names (c, names_attribute_reset_);
+
+ if (he)
+ {
+ os << "this->resetting_ = true;"
+ << endl;
+
+ contains_compositor (c, contains_compositor_reset_);
+
+ os << "this->resetting_ = false;"
+ << endl;
+ }
+
+ os << "}";
+ }
+
+ //
+ //
+ if (poly_code)
+ {
+ String id (c.name ());
+
+ if (String ns = xml_ns_name (c))
+ {
+ id += L' ';
+ id += ns;
+ }
+
+ os << "const char* " << name << "::" << endl
+ << "_static_type ()"
+ << "{"
+ << "return " << strlit (id) << ";"
+ << "}";
+
+ os << "const char* " << name << "::" << endl
+ << "_dynamic_type () const"
+ << "{"
+ << "return _static_type ();"
+ << "}";
+
+ if (hb && validation)
+ {
+ Boolean gen (!anonymous (c));
+
+ // We normally don't need to enter anonymous types into
+ // the inheritance map. The only exception is when an
+ // anonymous types is defined inside an element that
+ // is a member of a substitution group.
+ //
+ if (!gen)
+ {
+ // The first instance that this anonymous type classifies
+ // is the prototype for others if any.
+ //
+ SemanticGraph::Instance& i (
+ c.classifies_begin ()->instance ());
+
+ if (SemanticGraph::Element* e =
+ dynamic_cast<SemanticGraph::Element*> (&i))
+ {
+ if (e->substitutes_p ())
+ gen = true;
+ }
+ }
+
+ if (gen)
+ {
+ SemanticGraph::Type& base (c.inherits ().base ());
+
+ os << "static" << endl
+ << "const ::xsde::cxx::serializer::validating::" <<
+ "inheritance_map_entry" << endl
+ << "_xsde_" << name << "_inheritance_map_entry_ (" << endl
+ << name << "::_static_type ()," << endl
+ << fq_name (base) << "::_static_type ());"
+ << endl;
+ }
+ }
+ }
+
+ if (tiein && hb)
+ {
+ // If our base has pure virtual functions, override them here.
+ //
+ BaseOverride t (*this, name);
+ t.dispatch (c.inherits ().base ());
+ }
+
+ // If we are validating, the rest is generated elsewere.
+ //
+ if (validation)
+ return;
+
+ // Don't use restriction_p here since we don't want special
+ // treatment of anyType.
+ //
+ Boolean restriction (
+ hb && c.inherits ().is_a<SemanticGraph::Restricts> ());
+
+ // _serialize_attributes
+ //
+ if (ha || haa)
+ {
+ os << "void " << name << "::" << endl
+ << "_serialize_attributes ()"
+ << "{";
+
+ // We need context for wildcards only if we are using error
+ // codes.
+ //
+ if (ha || !exceptions)
+ os << "::xsde::cxx::serializer::context& ctx = this->_context ();"
+ << endl;
+
+ if (hb && !restriction)
+ {
+ // We cannot use the fully-qualified base name directly
+ // because of some broken compilers (EVC 4.0).
+ //
+ String base (unclash (name, "base"));
+
+ os << "typedef " << fq_name (c.inherits ().base ()) << " " <<
+ base << ";"
+ << base << "::_serialize_attributes ();"
+ << endl;
+
+ if (!exceptions)
+ {
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+ }
+
+ names (c, names_attribute_);
+
+ os << "}";
+ }
+
+ // _serialize_content
+ //
+ if (he || hae)
+ {
+ os << "void " << name << "::" << endl
+ << "_serialize_content ()"
+ << "{";
+
+ // We need context for wildcards only if we are using error
+ // codes.
+ //
+ if (he || !exceptions)
+ os << "::xsde::cxx::serializer::context& ctx = this->_context ();"
+ << endl;
+
+ if (hb && !restriction)
+ {
+ // We cannot use the fully-qualified base name directly
+ // because of some broken compilers (EVC 4.0).
+ //
+ String base (unclash (name, "base"));
+
+ os << "typedef " << fq_name (c.inherits ().base ()) << " " <<
+ base << ";"
+ << base << "::_serialize_content ();"
+ << endl;
+
+ if (!exceptions)
+ {
+ os << "if (ctx.error_type ())" << endl
+ << "return;"
+ << endl;
+ }
+ }
+
+ contains_compositor (c, contains_compositor_);
+
+ os << "}";
+ }
+ }
+
+ private:
+ //
+ //
+ CompositorCallback compositor_callback_;
+ ParticleCallback particle_callback_;
+ Traversal::ContainsCompositor contains_compositor_callback_;
+ Traversal::ContainsParticle contains_particle_callback_;
+
+ AttributeCallback attribute_callback_;
+ Traversal::Names names_attribute_callback_;
+
+ //
+ //
+ Traversal::Compositor compositor_reset_;
+ ParticleReset particle_reset_;
+ Traversal::ContainsCompositor contains_compositor_reset_;
+ Traversal::ContainsParticle contains_particle_reset_;
+
+ AttributeReset attribute_reset_;
+ Traversal::Names names_attribute_reset_;
+
+ //
+ //
+ Compositor compositor_;
+ Particle particle_;
+ Traversal::ContainsCompositor contains_compositor_;
+ Traversal::ContainsParticle contains_particle_;
+
+ Attribute attribute_;
+ Traversal::Names names_attribute_;
+ };
+
+
+ // Generate substitution group map entries.
+ //
+ struct GlobalElement: Traversal::Element, Context
+ {
+ GlobalElement (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (e.substitutes_p ())
+ {
+ String name (escape (e.name ()));
+ Type& r (e.substitutes ().root ());
+
+ SemanticGraph::Type& type (e.type ());
+
+ String r_id (r.name ());
+
+ if (String const& ns = r.namespace_ ().name ())
+ {
+ r_id += L' ';
+ r_id += ns;
+ }
+
+ os << "// Substitution map entry for " << comment (e.name ()) <<
+ "." << endl
+ << "//" << endl
+ << "static" << endl
+ << "const ::xsde::cxx::serializer::substitution_map_entry" << endl
+ << "_xsde_" << name << "_substitution_map_entry_ (" << endl
+ << strlit (r_id) << "," << endl;
+
+ if (String const& ns = e.namespace_ ().name ())
+ os << strlit (ns) << "," << endl;
+ else
+ os << "0," << endl;
+
+ os << strlit (e.name ()) << "," << endl
+ << fq_name (type) << "::_static_type ());"
+ << endl;
+ }
+ }
+ };
+ }
+
+ Void
+ generate_serializer_source (Context& ctx)
+ {
+ if (ctx.tiein)
+ ctx.os << "#include <assert.h>" << endl
+ << endl;
+
+ if (ctx.poly_code)
+ {
+ ctx.os << "#include <string.h>" << endl
+ << "#include <xsde/cxx/serializer/substitution-map.hxx>" << endl;
+
+ if (ctx.validation)
+ ctx.os << "#include <xsde/cxx/serializer/validating/inheritance-map.hxx>" << endl
+ << endl;
+ else
+ ctx.os << endl;
+
+ ctx.os << "static" << endl
+ << "const ::xsde::cxx::serializer::substitution_map_init" << endl
+ << "_xsde_substitution_map_init_;"
+ << endl;
+
+ if (ctx.validation)
+ {
+ ctx.os << "static" << endl
+ << "const ::xsde::cxx::serializer::validating::" <<
+ "inheritance_map_init" << endl
+ << "_xsde_inheritance_map_init_;"
+ << endl;
+ }
+ }
+
+ // Emit "weak" header includes that are used in the file-per-type
+ // compilation model.
+ //
+ if (ctx.options.value<CLI::generate_inline> ())
+ {
+ 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);
+ Enumeration enumeration (ctx);
+ GlobalElement global_element (ctx);
+
+ names >> list;
+ names >> union_;
+ names >> complex;
+ names >> enumeration;
+
+ if (ctx.poly_code)
+ names >> global_element;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+}
diff --git a/xsde/cxx/serializer/serializer-source.hxx b/xsde/cxx/serializer/serializer-source.hxx
new file mode 100644
index 0000000..6b1353e
--- /dev/null
+++ b/xsde/cxx/serializer/serializer-source.hxx
@@ -0,0 +1,22 @@
+// file : xsde/cxx/serializer/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_SERIALIZER_SERIALIZER_SOURCE_HXX
+#define CXX_SERIALIZER_SERIALIZER_SOURCE_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/serializer/elements.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ Void
+ generate_serializer_source (Context&);
+ }
+}
+
+#endif // CXX_SERIALIZER_SERIALIZER_SOURCE_HXX
diff --git a/xsde/cxx/serializer/type-processor.cxx b/xsde/cxx/serializer/type-processor.cxx
new file mode 100644
index 0000000..6854e2c
--- /dev/null
+++ b/xsde/cxx/serializer/type-processor.cxx
@@ -0,0 +1,356 @@
+// file : xsde/cxx/serializer/type-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 <cult/containers/set.hxx>
+
+#include <cxx/serializer/elements.hxx>
+#include <cxx/serializer/type-processor.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ namespace
+ {
+ //
+ //
+ struct Type: Traversal::Type
+ {
+ Type (SemanticGraph::Schema& schema,
+ TypeMap::Namespaces& type_map,
+ Boolean add_includes)
+ : schema_ (schema),
+ type_map_ (type_map),
+ add_includes_ (add_includes)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& type)
+ {
+ using TypeMap::Namespace;
+ using TypeMap::Namespaces;
+
+ SemanticGraph::Context& tc (type.context ());
+
+ // There are two situations where we may try to process the
+ // same type more than once. The first is when the type is
+ // used in several element declarations in the same schema.
+ // The second situation only occurs when we are in the file-
+ // per-type mode. In this case the type was processed as part
+ // of another root schema. In the second case, while the ret
+ // and arg types are assumed to be the same, we need to re-
+ // match the type in order to add include directives to the
+ // new root schema.
+ //
+ Boolean set (true);
+
+ if (tc.count ("s:ret-type"))
+ {
+ SemanticGraph::Schema* s (
+ tc.get<SemanticGraph::Schema*> ("s:root-schema"));
+
+ if (&schema_ == s)
+ return;
+
+ set = false;
+ }
+
+ SemanticGraph::Namespace& ns (
+ dynamic_cast<SemanticGraph::Namespace&> (type.scope ()));
+
+ String ns_name (ns.name ());
+ String t_name (type.name ());
+
+ // std::wcerr << "traversing: " << ns_name << "#" << t_name << endl;
+
+ for (Namespaces::ConstIterator n (type_map_.begin ());
+ n != type_map_.end (); ++n)
+ {
+ // Check if the namespace matches.
+ //
+ //@@ Should probably store precompiled regex somewhere
+ // instead of doing it every time.
+ //
+ boost::basic_regex<WideChar> ns_expr;
+
+ Boolean ns_match;
+
+ if (!n->xsd_name ().empty ())
+ {
+ ns_match = n->xsd_name ().match (ns_name);
+ }
+ else
+ ns_match = ns_name.empty ();
+
+ // std::wcerr << "considering ns expr: " << n->xsd_name () << endl;
+
+ if (ns_match)
+ {
+ // Namespace matched. See if there is a type that matches.
+ //
+ for (Namespace::TypesIterator t (n->types_begin ());
+ t != n->types_end (); ++t)
+ {
+ if (t->xsd_name ().match (t_name))
+ {
+ if (set)
+ {
+ // Got a match. See if the namespace has the C++
+ // namespace mapping.
+ //
+ String cxx_ns;
+
+ if (n->has_cxx_name ())
+ {
+ if (!n->xsd_name ().empty ())
+ {
+ cxx_ns = n->xsd_name ().merge (
+ n->cxx_name (), ns_name, true);
+ }
+ else
+ cxx_ns = n->cxx_name ();
+
+ cxx_ns += L"::";
+ }
+
+ // Figure out ret and arg type names.
+ //
+ String ret_type (cxx_ns);
+
+ ret_type += t->xsd_name ().merge (
+ t->cxx_ret_name (), t_name, true);
+
+ String arg_type;
+
+ if (t->cxx_arg_name ())
+ {
+ arg_type = cxx_ns;
+ arg_type += t->xsd_name ().merge (
+ t->cxx_arg_name (), t_name, true);
+ }
+ else
+ {
+ if (ret_type == L"void")
+ arg_type = ret_type;
+ else
+ {
+ WideChar last (ret_type[ret_type.size () - 1]);
+
+ // If it is already a pointer or reference then use
+ // it as is.
+ //
+ if (last == L'*' || last == L'&')
+ arg_type = ret_type;
+ else
+ arg_type = L"const " + ret_type + L"&";
+ }
+ }
+
+ tc.set ("s:ret-type", ret_type);
+ tc.set ("s:arg-type", arg_type);
+ }
+
+ tc.set ("s:root-schema", &schema_);
+
+ //std::wcerr << t_name << " -> " << ret_type << endl;
+
+ // See of we need to add any includes to the translations
+ // unit.
+ //
+ if (add_includes_)
+ {
+ if (n->includes_begin () != n->includes_end ())
+ {
+ typedef Cult::Containers::Set<String> Includes;
+
+ SemanticGraph::Context& sc (schema_.context ());
+
+ if (!sc.count ("s:includes"))
+ sc.set ("s:includes", Includes ());
+
+ Includes& is (sc.get<Includes> ("s:includes"));
+
+ for (Namespace::IncludesIterator i (n->includes_begin ());
+ i != n->includes_end (); ++i)
+ {
+ is.insert (*i);
+ }
+ }
+ }
+
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ private:
+ SemanticGraph::Schema& schema_;
+ TypeMap::Namespaces& type_map_;
+ Boolean add_includes_;
+ };
+
+ //
+ //
+ struct BaseType: Traversal::Complex
+ {
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ Complex::names (c);
+ }
+ };
+
+ //
+ //
+ struct GlobalType: Traversal::Type,
+ Traversal::List,
+ Traversal::Complex,
+ Traversal::Enumeration
+ {
+ GlobalType (SemanticGraph::Schema& schema,
+ TypeMap::Namespaces& type_map,
+ Boolean add_includes,
+ Boolean tiein)
+ : type_ (schema, type_map, add_includes)
+ {
+ inherits_ >> type_;
+ names_ >> instance_ >> belongs_ >> type_;
+ argumented_ >> type_;
+
+ if (tiein)
+ {
+ // In case of a tiein support, we also need to process base's
+ // members to assign ret/arg types.
+ //
+ inherits_base_ >> base_type_ >> names_;
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& t)
+ {
+ type_.traverse (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::List& l)
+ {
+ type_.traverse (l);
+ Traversal::List::argumented (l, argumented_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ type_.traverse (c);
+ Complex::inherits (c, inherits_);
+ Complex::inherits (c, inherits_base_);
+ Complex::names (c, names_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Enumeration& e)
+ {
+ type_.traverse (e);
+ Complex::inherits (e, inherits_);
+ }
+
+ private:
+ Serializer::Type type_;
+ BaseType base_type_;
+ Traversal::Names names_;
+ Traversal::Instance instance_;
+ Traversal::Inherits inherits_;
+ Traversal::Inherits inherits_base_;
+ Traversal::Belongs belongs_;
+ Traversal::Argumented argumented_;
+ };
+
+ Void
+ process_impl (CLI::Options const& options,
+ XSDFrontend::SemanticGraph::Schema& tu,
+ TypeMap::Namespaces& type_map)
+ {
+ Boolean tiein (!options.value<CLI::reuse_style_mixin> () &&
+ !options.value<CLI::reuse_style_none> ());
+
+ 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;
+ GlobalType global_type (tu, type_map, true, tiein);
+
+ schema >> schema_names >> ns >> ns_names >> global_type;
+
+ schema.dispatch (tu);
+ }
+ else
+ {
+ // If --extern-xml-schema is specified, then we don't want
+ // includes from the XML Schema type map.
+ //
+ Boolean extern_xml_schema (
+ options.value<CLI::extern_xml_schema> ());
+
+ // Besides types defined in this schema, also process those
+ // referenced by global elements in case we are generating
+ // something for them.
+ //
+ Traversal::Schema schema;
+ Traversal::Schema xs_schema;
+ Traversal::Sources sources;
+ Traversal::Implies implies;
+
+ schema >> sources >> schema;
+ schema >> implies >> xs_schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+ Traversal::Element global_element;
+ GlobalType global_type (tu, type_map, true, tiein);
+
+ schema >> schema_names >> ns >> ns_names;
+
+ ns_names >> global_element;
+ ns_names >> global_type;
+
+ Traversal::Belongs element_belongs;
+ global_element >> element_belongs >> global_type;
+
+ Traversal::Names xs_schema_names;
+ Traversal::Namespace xs_ns;
+ Traversal::Names xs_ns_names;
+ GlobalType xs_global_type (tu, type_map, !extern_xml_schema, tiein);
+
+ xs_schema >> xs_schema_names >> xs_ns >> xs_ns_names >>
+ xs_global_type;
+
+ schema.dispatch (tu);
+ }
+ }
+ }
+
+ Void TypeProcessor::
+ process (CLI::Options const& options,
+ XSDFrontend::SemanticGraph::Schema& s,
+ TypeMap::Namespaces& tm)
+ {
+ process_impl (options, s, tm);
+ }
+ }
+}
diff --git a/xsde/cxx/serializer/type-processor.hxx b/xsde/cxx/serializer/type-processor.hxx
new file mode 100644
index 0000000..8408a4e
--- /dev/null
+++ b/xsde/cxx/serializer/type-processor.hxx
@@ -0,0 +1,34 @@
+// file : xsde/cxx/serializer/type-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_SERIALIZER_TYPE_PROCESSOR_HXX
+#define CXX_SERIALIZER_TYPE_PROCESSOR_HXX
+
+#include <cult/types.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+
+#include <type-map/type-map.hxx>
+
+#include <cxx/serializer/cli.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ using namespace Cult::Types;
+
+ class TypeProcessor
+ {
+ public:
+ Void
+ process (CLI::Options const& options,
+ XSDFrontend::SemanticGraph::Schema&,
+ TypeMap::Namespaces&);
+ };
+ }
+}
+
+#endif // CXX_SERIALIZER_TYPE_PROCESSOR_HXX
diff --git a/xsde/cxx/serializer/validator.cxx b/xsde/cxx/serializer/validator.cxx
new file mode 100644
index 0000000..d9cc724
--- /dev/null
+++ b/xsde/cxx/serializer/validator.cxx
@@ -0,0 +1,501 @@
+// file : xsde/cxx/serializer/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/serializer/validator.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cxx/serializer/elements.hxx>
+
+#include <iostream>
+
+using std::wcerr;
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ 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 ("S001"))
+ 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 S001: 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 GlobalElement: Traversal::Element, ValidationContext
+ {
+ GlobalElement (ValidationContext& c, SemanticGraph::Element*& element)
+ : ValidationContext (c), element_ (element)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (!valid)
+ return;
+
+ if (options.value<CLI::root_element_first> ())
+ {
+ if (element_ == 0)
+ element_ = &e;
+ }
+ else if (options.value<CLI::root_element_last> ())
+ {
+ element_ = &e;
+ }
+ else if (String name = options.value<CLI::root_element> ())
+ {
+ if (e.name () == name)
+ element_ = &e;
+ }
+ else
+ {
+ if (element_ == 0)
+ element_ = &e;
+ else
+ {
+ wcerr << schema_root.file () << ": error: unable to generate "
+ << "the test driver without a unique document root"
+ << endl;
+
+ wcerr << schema_root.file () << ": info: use --root-element-* "
+ << "options to specify the document root" << endl;
+
+ valid = false;
+ }
+ }
+ }
+
+ private:
+ SemanticGraph::Element*& element_;
+ };
+ }
+
+ Boolean Validator::
+ validate (CLI::Options const& options,
+ SemanticGraph::Schema& root,
+ SemanticGraph::Path const&,
+ Boolean gen_driver,
+ const WarningSet& disabled_warnings)
+ {
+ Boolean valid (true);
+ ValidationContext ctx (root, options, disabled_warnings, valid);
+
+ //
+ //
+ {
+ Boolean ref (options.value<CLI::root_element_first> ());
+ Boolean rel (options.value<CLI::root_element_last> ());
+ Boolean re (options.value<CLI::root_element> ());
+
+ if ((ref && rel) || (ref && re) || (rel && re))
+ {
+ wcerr << "error: mutually exclusive options specified: "
+ << "--root-element-last, --root-element-first, and "
+ << "--root-element"
+ << endl;
+
+ return false;
+ }
+ }
+
+ //
+ //
+ if (options.value<CLI::reuse_style_mixin> () &&
+ options.value<CLI::reuse_style_none> ())
+ {
+ wcerr << "error: mutually exclusive options specified: "
+ << "--reuse-style-mixin and --reuse-style-none"
+ << endl;
+
+ return false;
+ }
+
+ //
+ //
+ if (options.value<CLI::reuse_style_none> () &&
+ options.value<CLI::generate_empty_impl> () &&
+ !ctx.is_disabled ("S002"))
+ {
+ wcerr << "warning S002: generating sample implementation without "
+ << "serializer reuse support: the resulting code may not "
+ << "compile"
+ << endl;
+
+ return false;
+ }
+
+ // Test for anonymout types.
+ //
+ {
+ AnonymousType traverser (ctx);
+ traverser.dispatch (root);
+ }
+
+ // Test the rest.
+ //
+ if (valid)
+ {
+ Traverser traverser (ctx);
+ traverser.dispatch (root);
+ }
+
+ // Test that the document root is unique.
+ //
+ if (valid && gen_driver)
+ {
+ SemanticGraph::Element* element (0);
+
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+
+ schema >> sources >> schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+ GlobalElement global_element (ctx, element);
+
+ schema >> schema_names >> ns >> ns_names >> global_element;
+
+ schema.dispatch (root);
+
+ if (valid && element == 0)
+ {
+ wcerr << root.file () << ": error: unable to generate the "
+ << "test driver without a global element (document root)"
+ << endl;
+
+ valid = false;
+ }
+ }
+
+ return valid;
+ }
+ }
+}
diff --git a/xsde/cxx/serializer/validator.hxx b/xsde/cxx/serializer/validator.hxx
new file mode 100644
index 0000000..03d1349
--- /dev/null
+++ b/xsde/cxx/serializer/validator.hxx
@@ -0,0 +1,36 @@
+// file : xsde/cxx/serializer/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_SERIALIZER_VALIDATOR_HXX
+#define CXX_SERIALIZER_VALIDATOR_HXX
+
+#include <cult/types.hxx>
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/serializer/cli.hxx>
+
+#include <xsde.hxx>
+
+namespace CXX
+{
+ namespace Serializer
+ {
+ using namespace Cult::Types;
+
+ class Validator
+ {
+ public:
+ Boolean
+ validate (CLI::Options const& options,
+ XSDFrontend::SemanticGraph::Schema&,
+ XSDFrontend::SemanticGraph::Path const& tu,
+ Boolean gen_driver,
+ const WarningSet& disabled_warnings);
+ };
+ }
+}
+
+#endif // CXX_SERIALIZER_VALIDATOR_HXX