summaryrefslogtreecommitdiff
path: root/xsd/cxx
diff options
context:
space:
mode:
Diffstat (limited to 'xsd/cxx')
-rw-r--r--xsd/cxx/elements.cxx1020
-rw-r--r--xsd/cxx/elements.hxx577
-rw-r--r--xsd/cxx/parser/attribute-validation-source.cxx410
-rw-r--r--xsd/cxx/parser/attribute-validation-source.hxx22
-rw-r--r--xsd/cxx/parser/characters-validation-source.cxx77
-rw-r--r--xsd/cxx/parser/characters-validation-source.hxx22
-rw-r--r--xsd/cxx/parser/cli.hxx152
-rw-r--r--xsd/cxx/parser/driver-source.cxx768
-rw-r--r--xsd/cxx/parser/driver-source.hxx22
-rw-r--r--xsd/cxx/parser/element-validation-source.cxx1587
-rw-r--r--xsd/cxx/parser/element-validation-source.hxx22
-rw-r--r--xsd/cxx/parser/elements.cxx262
-rw-r--r--xsd/cxx/parser/elements.hxx312
-rw-r--r--xsd/cxx/parser/generator.cxx1450
-rw-r--r--xsd/cxx/parser/generator.hxx55
-rw-r--r--xsd/cxx/parser/impl-header.cxx237
-rw-r--r--xsd/cxx/parser/impl-header.hxx22
-rw-r--r--xsd/cxx/parser/impl-source.cxx389
-rw-r--r--xsd/cxx/parser/impl-source.hxx22
-rw-r--r--xsd/cxx/parser/name-processor.cxx1205
-rw-r--r--xsd/cxx/parser/name-processor.hxx34
-rw-r--r--xsd/cxx/parser/parser-forward.cxx115
-rw-r--r--xsd/cxx/parser/parser-forward.hxx22
-rw-r--r--xsd/cxx/parser/parser-header.cxx1440
-rw-r--r--xsd/cxx/parser/parser-header.hxx22
-rw-r--r--xsd/cxx/parser/parser-inline.cxx407
-rw-r--r--xsd/cxx/parser/parser-inline.hxx22
-rw-r--r--xsd/cxx/parser/parser-source.cxx924
-rw-r--r--xsd/cxx/parser/parser-source.hxx22
-rw-r--r--xsd/cxx/parser/print-impl-common.hxx643
-rw-r--r--xsd/cxx/parser/state-processor.cxx318
-rw-r--r--xsd/cxx/parser/state-processor.hxx28
-rw-r--r--xsd/cxx/parser/type-processor.cxx352
-rw-r--r--xsd/cxx/parser/type-processor.hxx37
-rw-r--r--xsd/cxx/parser/validator.cxx714
-rw-r--r--xsd/cxx/parser/validator.hxx35
-rw-r--r--xsd/cxx/tree/cli.hxx220
-rw-r--r--xsd/cxx/tree/counter.cxx265
-rw-r--r--xsd/cxx/tree/counter.hxx28
-rw-r--r--xsd/cxx/tree/elements.cxx1327
-rw-r--r--xsd/cxx/tree/elements.hxx2030
-rw-r--r--xsd/cxx/tree/fundamental-header.hxx1186
-rw-r--r--xsd/cxx/tree/generator.cxx1689
-rw-r--r--xsd/cxx/tree/generator.hxx49
-rw-r--r--xsd/cxx/tree/name-processor.cxx2100
-rw-r--r--xsd/cxx/tree/name-processor.hxx34
-rw-r--r--xsd/cxx/tree/parser-header.cxx474
-rw-r--r--xsd/cxx/tree/parser-header.hxx23
-rw-r--r--xsd/cxx/tree/parser-source.cxx544
-rw-r--r--xsd/cxx/tree/parser-source.hxx24
-rw-r--r--xsd/cxx/tree/serialization-header.cxx581
-rw-r--r--xsd/cxx/tree/serialization-header.hxx22
-rw-r--r--xsd/cxx/tree/serialization-source.cxx1342
-rw-r--r--xsd/cxx/tree/serialization-source.hxx24
-rw-r--r--xsd/cxx/tree/stream-extraction-source.cxx754
-rw-r--r--xsd/cxx/tree/stream-extraction-source.hxx22
-rw-r--r--xsd/cxx/tree/stream-header.cxx183
-rw-r--r--xsd/cxx/tree/stream-header.hxx22
-rw-r--r--xsd/cxx/tree/stream-insertion-header.cxx178
-rw-r--r--xsd/cxx/tree/stream-insertion-header.hxx22
-rw-r--r--xsd/cxx/tree/stream-insertion-source.cxx532
-rw-r--r--xsd/cxx/tree/stream-insertion-source.hxx22
-rw-r--r--xsd/cxx/tree/stream-source.cxx489
-rw-r--r--xsd/cxx/tree/stream-source.hxx24
-rw-r--r--xsd/cxx/tree/tree-forward.cxx324
-rw-r--r--xsd/cxx/tree/tree-forward.hxx22
-rw-r--r--xsd/cxx/tree/tree-header.cxx3778
-rw-r--r--xsd/cxx/tree/tree-header.hxx22
-rw-r--r--xsd/cxx/tree/tree-inline.cxx1025
-rw-r--r--xsd/cxx/tree/tree-inline.hxx22
-rw-r--r--xsd/cxx/tree/tree-source.cxx3461
-rw-r--r--xsd/cxx/tree/tree-source.hxx24
-rw-r--r--xsd/cxx/tree/validator.cxx675
-rw-r--r--xsd/cxx/tree/validator.hxx33
74 files changed, 37364 insertions, 0 deletions
diff --git a/xsd/cxx/elements.cxx b/xsd/cxx/elements.cxx
new file mode 100644
index 0000000..a62ed5d
--- /dev/null
+++ b/xsd/cxx/elements.cxx
@@ -0,0 +1,1020 @@
+// file : xsd/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,
+ 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),
+ 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),
+ 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)
+ {
+ 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 ())
+ {
+ // Here we need to detect a special multi-schema compilation
+ // case where the root schemas are imported into a special
+ // schema that doesn't have a namespace.
+ //
+ SemanticGraph::Uses& u (*schema.used_begin ());
+ SemanticGraph::Schema& s (u.user ());
+
+ if (s.names_begin () != s.names_end ())
+ 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)
+ {
+ 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);
+ }
+
+ 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;
+ }
+
+ 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)
+ {
+ 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 (n, L"", ns ? false : true);
+
+ do
+ {
+ e = ns.find (L"::", b);
+
+ String name (ns, b, e == ns.npos ? e : e - b);
+
+ if (!name.empty ())
+ {
+ if (st_)
+ st_->enter (n, name, e == ns.npos);
+
+ ctx_.os << "namespace " << 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 ();
+ }
+}
diff --git a/xsd/cxx/elements.hxx b/xsd/cxx/elements.hxx
new file mode 100644
index 0000000..dba9665
--- /dev/null
+++ b/xsd/cxx/elements.hxx
@@ -0,0 +1,577 @@
+// file : xsd/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,
+ 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),
+ 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),
+ 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&);
+
+ // 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&);
+
+ // 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 = "name");
+
+ public:
+ static SemanticGraph::Type&
+ ultimate_base (SemanticGraph::Complex&);
+
+ public:
+ String
+ process_include_path (String const&) const;
+
+ public:
+ static Boolean
+ skip (SemanticGraph::Member& m)
+ {
+ // "Subsequent" local element.
+ //
+ return !m.scope ().is_a<SemanticGraph::Namespace> () &&
+ m.context ().count ("min") == 0;
+ }
+
+ static UnsignedLong
+ min (SemanticGraph::Member const& m)
+ {
+ return m.context ().get<UnsignedLong> ("min");
+ }
+
+ static UnsignedLong
+ min (SemanticGraph::Any const& a)
+ {
+ return a.context ().get<UnsignedLong> ("min");
+ }
+
+ static UnsignedLong
+ max (SemanticGraph::Member const& m)
+ {
+ return m.context ().get<UnsignedLong> ("max");
+ }
+
+ static UnsignedLong
+ max (SemanticGraph::Any const& a)
+ {
+ return a.context ().get<UnsignedLong> ("max");
+ }
+
+ public:
+ // Get escaped name.
+ //
+ static String const&
+ ename (SemanticGraph::Nameable const& n)
+ {
+ return n.context ().get<String> ("name");
+ }
+
+ public:
+ std::wostream& os;
+
+ SemanticGraph::Schema& schema_root;
+
+ 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_;
+
+ 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
+ {
+ // First scope name if always empty (global scope). The last flag
+ // signals the last scope.
+ //
+ virtual Void
+ enter (Type&, String const& name, Boolean last) = 0;
+
+ virtual Void
+ leave () = 0;
+ };
+
+
+ Namespace (Context& c)
+ : ctx_ (c), st_ (0)
+ {
+ }
+
+ 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);
+ }
+ };
+}
+
+#endif // CXX_TREE_ELEMENTS_HXX
diff --git a/xsd/cxx/parser/attribute-validation-source.cxx b/xsd/cxx/parser/attribute-validation-source.cxx
new file mode 100644
index 0000000..52c51b1
--- /dev/null
+++ b/xsd/cxx/parser/attribute-validation-source.cxx
@@ -0,0 +1,410 @@
+// file : xsd/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,
+ protected virtual 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,
+ protected virtual 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 ();"
+ << "this->" << inst << "->_pre_impl ();"
+ << "this->" << inst << "->_characters (s);"
+ << "this->" << inst << "->_post_impl ();";
+
+ if (ret == L"void")
+ os << "this->" << inst << "->" << post << " ();"
+ << "this->" << name << " ();";
+ else
+ os << arg_type (type) << " tmp (this->" << inst << "->" <<
+ post << " ());"
+ << "this->" << name << " (tmp);"
+ << endl;
+
+ 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,
+ protected virtual 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,
+ protected virtual Context
+ {
+ AttributeStateInit (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ if (!a.optional ())
+ os << "as." << ename (a) << " = false;";
+ }
+ };
+
+
+ //
+ //
+ struct AttributeStateCheck: Traversal::Attribute,
+ protected virtual 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) << ")" << endl
+ << "this->_expected_attribute (" << endl
+ << L << strlit (ns) << ", " << L << strlit (a.name ()) << ");";
+ }
+ }
+ };
+
+ //
+ //
+ struct Complex : Traversal::Complex,
+ protected virtual 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
+ << "{";
+
+ names (c, names_phase_one_);
+
+ // Nothing matched - call our base (extension) or return false
+ // if there is no base (or restriction (even from anyType)).
+ //
+ os << "return ";
+
+ if (c.inherits_p () &&
+ !c.inherits ().is_a<SemanticGraph::Restricts> ())
+ {
+ os << "this->" << fq_name (c.inherits ().base ()) <<
+ "::_attribute_impl_phase_one (ns, n, s);";
+ }
+ else
+ os << "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)).
+ //
+ os << "return ";
+
+ if (c.inherits_p () &&
+ !c.inherits ().is_a<SemanticGraph::Restricts> ())
+ {
+ os << "this->" << fq_name (c.inherits ().base ()) <<
+ "::_attribute_impl_phase_two (ns, n, s);";
+ }
+ else
+ os << "false;";
+
+ os << "}";
+ }
+
+ if (has_req_att)
+ {
+ // _pre_a_validate
+ //
+ os << "void " << name << "::" << endl
+ << "_pre_a_validate ()"
+ << "{"
+ << "this->v_state_attr_stack_.push ();"
+ << "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> ())
+ {
+ os << "this->" << fq_name (c.inherits ().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> ())
+ {
+ os << "this->" << fq_name (c.inherits ().base ()) <<
+ "::_post_a_validate ();"
+ << 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/xsd/cxx/parser/attribute-validation-source.hxx b/xsd/cxx/parser/attribute-validation-source.hxx
new file mode 100644
index 0000000..400e460
--- /dev/null
+++ b/xsd/cxx/parser/attribute-validation-source.hxx
@@ -0,0 +1,22 @@
+// file : xsd/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/xsd/cxx/parser/characters-validation-source.cxx b/xsd/cxx/parser/characters-validation-source.cxx
new file mode 100644
index 0000000..ec698f8
--- /dev/null
+++ b/xsd/cxx/parser/characters-validation-source.cxx
@@ -0,0 +1,77 @@
+// file : xsd/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,
+ protected virtual 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/xsd/cxx/parser/characters-validation-source.hxx b/xsd/cxx/parser/characters-validation-source.hxx
new file mode 100644
index 0000000..c9e9889
--- /dev/null
+++ b/xsd/cxx/parser/characters-validation-source.hxx
@@ -0,0 +1,22 @@
+// file : xsd/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/xsd/cxx/parser/cli.hxx b/xsd/cxx/parser/cli.hxx
new file mode 100644
index 0000000..504de43
--- /dev/null
+++ b/xsd/cxx/parser/cli.hxx
@@ -0,0 +1,152 @@
+// file : xsd/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 char_type;
+ extern Key output_dir;
+ extern Key xml_parser;
+ extern Key generate_inline;
+ extern Key generate_validation;
+ extern Key suppress_validation;
+ extern Key generate_polymorphic;
+ 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 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 export_symbol;
+ extern Key export_maps;
+ extern Key import_maps;
+ extern Key show_anonymous;
+ extern Key show_sloc;
+ extern Key proprietary_license;
+
+ typedef Cult::CLI::Options<
+ type_map, Cult::Containers::Vector<NarrowString>,
+ char_type, NarrowString,
+ output_dir, NarrowString,
+ xml_parser, NarrowString,
+ generate_inline, Boolean,
+ generate_validation, Boolean,
+ suppress_validation, Boolean,
+ generate_polymorphic, 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,
+ 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,
+ export_symbol, NarrowString,
+ export_maps, Boolean,
+ import_maps, Boolean,
+ show_anonymous, Boolean,
+ show_sloc, Boolean,
+ proprietary_license, Boolean
+
+ > Options;
+
+ struct OptionsSpec: Cult::CLI::OptionsSpec<Options> {};
+ }
+ }
+}
+
+#endif // CXX_PARSER_CLI_HXX
diff --git a/xsd/cxx/parser/driver-source.cxx b/xsd/cxx/parser/driver-source.cxx
new file mode 100644
index 0000000..91c4cca
--- /dev/null
+++ b/xsd/cxx/parser/driver-source.cxx
@@ -0,0 +1,768 @@
+// file : xsd/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);
+ }
+ };
+
+ 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 >> names_;
+ base_ >> names_;
+
+ names_ >> member_ >> 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, "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, "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, "impl") << " " << inst << ";";
+
+ inherits (c);
+
+ if (!restriction_p (c))
+ names (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, "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::Names names_;
+ Traversal::Member member_;
+ Traversal::Belongs belongs_;
+ };
+
+ struct ArgList : Traversal::Complex,
+ Traversal::List,
+ Traversal::Member,
+ Context
+ {
+ ArgList (Context& c, TypeInstanceMap& map)
+ : Context (c), map_ (map), first_ (true)
+ {
+ inherits_ >> *this;
+ names_ >> *this;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ inherits (c, inherits_);
+
+ if (!restriction_p (c))
+ names (c, names_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::List& l)
+ {
+ if (!first_)
+ os << "," << endl;
+ else
+ first_ = false;
+
+ os << map_[&l.argumented ().type ()];
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Member& m)
+ {
+ if (skip (m))
+ return;
+
+ if (!first_)
+ os << "," << endl;
+ else
+ first_ = false;
+
+ os << map_[&m.type ()];
+ }
+
+ private:
+ TypeInstanceMap& map_;
+
+ Traversal::Inherits inherits_;
+ Traversal::Names names_;
+
+ 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 >> names_;
+ base_ >> names_;
+
+ names_ >> member_ >> 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);
+ }
+ }
+
+ 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::Names names_;
+ Traversal::Member member_;
+ Traversal::Belongs belongs_;
+ };
+ }
+
+ 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 root_element (ctx.options, root);
+
+ schema >> schema_names >> ns >> ns_names >> root_element;
+
+ schema.dispatch (ctx.schema_root);
+ }
+
+ std::wostream& os (ctx.os);
+ String const& L (ctx.L);
+ String const& cerr (ctx.cerr_inst);
+
+ InstanceSet set;
+ TypeInstanceMap map;
+ SemanticGraph::Type& root_type (root->type ());
+
+ set.insert ("doc_p");
+
+ os << "#include <iostream>" << endl
+ << endl
+ << "int" << endl
+ << "main (int argc, char* argv[])"
+ << "{"
+ << "if (argc != 2)"
+ << "{"
+ << cerr << " << " << L << "\"usage: \" << argv[0] << " <<
+ L << "\" file.xml\" << std::endl;"
+ << "return 1;"
+ << "}"
+ << "try"
+ << "{"
+ << "// Instantiate individual parsers." << endl
+ << "//" << endl;
+
+ {
+ ParserDef def (ctx, map, set);
+ def.dispatch (root_type);
+ }
+
+ os << endl
+ << "// Connect the parsers together." << endl
+ << "//" << endl;
+
+ {
+ ParserConnect connect (ctx, map);
+ connect.dispatch (root_type);
+ }
+
+ String const& root_p (map[&root_type]);
+
+ os << "// Parse the XML document." << endl
+ << "//" << endl;
+
+ if (root->namespace_().name ())
+ os << ctx.xs_ns_name () << "::document doc_p (" << endl
+ << root_p << "," << endl
+ << L << ctx.strlit (root->namespace_().name ()) << "," << endl
+ << L << ctx.strlit (root->name ()) << ");"
+ << endl;
+ else
+ os << ctx.xs_ns_name () << "::document doc_p (" << root_p << ", " <<
+ L << ctx.strlit (root->name ()) << ");"
+ << endl;
+
+ os << root_p << ".pre ();"
+ << "doc_p.parse (argv[1]);";
+
+ String const& ret (Context::ret_type (root_type));
+ String const& post (Context::post_name (root_type));
+
+ if (ret == L"void")
+ os << root_p << "." << post << " ();";
+ else
+ {
+ os << Context::arg_type (root_type) << " v (" <<
+ root_p << "." << post << " ());"
+ << endl;
+
+ if (ctx.options.value<CLI::generate_print_impl> ())
+ {
+ PrintCall t (ctx, root->name (), "v");
+ t.dispatch (root_type);
+ }
+ else
+ os << "// TODO" << endl
+ << "//" << endl;
+ }
+
+ os << "}" // try
+ << "catch (const " << ctx.xs_ns_name () << "::exception& e)"
+ << "{"
+ << cerr << " << e << std::endl;"
+ << "return 1;"
+ << "}"
+ << "catch (const std::ios_base::failure&)"
+ << "{"
+ << cerr << " << argv[1] << " <<
+ L << "\": error: io failure\" << std::endl;"
+ << "return 1;"
+ << "}"
+ << "}";
+ }
+ }
+}
diff --git a/xsd/cxx/parser/driver-source.hxx b/xsd/cxx/parser/driver-source.hxx
new file mode 100644
index 0000000..9e0912f
--- /dev/null
+++ b/xsd/cxx/parser/driver-source.hxx
@@ -0,0 +1,22 @@
+// file : xsd/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/xsd/cxx/parser/element-validation-source.cxx b/xsd/cxx/parser/element-validation-source.cxx
new file mode 100644
index 0000000..949f491
--- /dev/null
+++ b/xsd/cxx/parser/element-validation-source.cxx
@@ -0,0 +1,1587 @@
+// file : xsd/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;
+
+
+ //
+ //
+ struct ParticleTest: Traversal::Compositor,
+ Traversal::Element,
+ Traversal::Any,
+ protected virtual Context
+ {
+ ParticleTest (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ String const& name (e.name ());
+
+ if (polymorphic && e.global ())
+ 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 (polymorphic && e.global ())
+ {
+ os << ") ||" << endl
+ << "::xsd::cxx::parser::substitution_map_instance< " <<
+ char_type << " > ().check (" << endl
+ << "ns, n, " << L << strlit (e.namespace_ ().name ()) <<
+ ", " << L << strlit (name) << ", 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> ("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,
+ protected virtual 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> ("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 (polymorphic && !anonymous (type));
+
+ String name, inst, def_parser, map;
+
+ if (e->context ().count("name"))
+ {
+ name = ename (*e);
+ inst = poly ? emember_cache (*e) : emember (*e);
+
+ if (poly)
+ {
+ def_parser = emember (*e);
+ map = emember_map (*e);
+ }
+ }
+ else
+ {
+ // This is the subsequent mentioning of this element in the
+ // content. We need to find the first one in order to get
+ // to the escaped names.
+ //
+ Complex::NamesIteratorPair ip (type_.find (e->name ()));
+ assert (ip.first != ip.second);
+ Element& fe (dynamic_cast<Element&>(ip.first->named ()));
+
+ name = ename (fe);
+ inst = poly ? emember_cache (fe) : emember (fe);
+
+ if (poly)
+ {
+ def_parser = emember (fe);
+ map = emember_map (fe);
+ }
+ }
+
+ if (poly)
+ {
+ // For pre-computing length.
+ //
+ String type_id (type.name ());
+
+ if (String type_ns = xml_ns_name (type))
+ {
+ type_id += L' ';
+ type_id += type_ns;
+ }
+
+ os << "if (t == 0 && this->" << def_parser << " != 0)" << endl
+ << "this->" << inst << " = this->" << def_parser << ";"
+ << "else"
+ << "{"
+ << string_type << " ts (" << fq_name (type) <<
+ "::_static_type (), " << type_id.size () << "UL);"
+ << endl
+ << "if (t == 0)" << endl
+ << "t = &ts;"
+ << endl
+ << "if (this->" << def_parser << " != 0 && *t == ts)" << endl
+ << "this->" << inst << " = this->" << def_parser << ";"
+ << "else"
+ << "{";
+
+ // Check that the types are related by inheritance.
+ //
+ os << "if (t != &ts &&" << endl
+ << "!::xsd::cxx::parser::validating::" <<
+ "inheritance_map_instance< " << char_type <<
+ " > ().check (" << endl
+ << "t->data (), ts))" << endl
+ << "throw ::xsd::cxx::parser::dynamic_type< " << char_type <<
+ " > (*t);"
+ << endl
+ << "if (this->" << map << " != 0)" << endl
+ << "this->" << inst << " = dynamic_cast< " <<
+ fq_name (type) << "* > (" << endl
+ << "this->" << map << "->find (*t));"
+ << "else" << endl
+ << "this->" << inst << " = 0;"
+ << "}"
+ << "}";
+ }
+
+ os << "this->" << complex_base << "::context_.top ()." <<
+ "parser_ = this->" << inst << ";"
+ << endl
+ << "if (this->" << inst << ")" << endl
+ << "this->" << inst << "->pre ();"
+ << "}"
+ << "else" // start
+ << "{"
+ << "if (this->" << inst << ")"
+ << "{";
+
+ String const& ret (ret_type (type));
+ String const& post (post_name (type));
+
+ if (ret == L"void")
+ os << "this->" << inst << "->" << post << " ();"
+ << "this->" << name << " ();";
+ else
+ os << arg_type (type) << " tmp (this->" << inst << "->" <<
+ post << " ());"
+ << "this->" << name << " (tmp);";
+
+ os << "}";
+ }
+ else
+ {
+ os << "this->_start_any_element (ns, n, t);"
+ << "this->" << complex_base << "::context_.top ().any_ = true;"
+ << "}"
+ << "else" // start
+ << "{"
+ << "this->" << complex_base << "::context_.top ().any_ = false;"
+ << "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> ("state"));
+
+ if (state != 0)
+ os << "else ";
+
+ os << "if (";
+
+ particle_test_.traverse (e);
+
+ os << ")"
+ << "{"
+ << "if (count[" << state << "UL] == 0)"
+ << "{"
+ << "if (start)"
+ << "{";
+
+ 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> ("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->_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::Compositor;
+
+ UnsignedLong max (c.max ());
+ UnsignedLong min (c.context ().get<UnsignedLong> ("effective-min"));
+ UnsignedLong n (c.context ().get<UnsignedLong> ("comp-number"));
+ UnsignedLong state (c.context ().get<UnsignedLong> ("state"));
+
+ String func (c.is_a<SemanticGraph::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> () && !c.context ().count ("comp-number"))
+ continue; // Empty compositor.
+
+ if (!p.context ().count ("prefix"))
+ break;
+
+ UnsignedLong state (p.context ().get<UnsignedLong> ("state"));
+
+ if (first)
+ first = false;
+ else
+ os << "else ";
+
+ os << "if (";
+
+ particle_test_.dispatch (p);
+
+ os << ")" << endl
+ << "s = " << state << "UL;";
+ }
+
+ // 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.
+ //
+
+ 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
+ << "this->" << func << n << " (vd.state, vd.count, ns, n, t, 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->_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)" << endl
+ << "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::Compositor;
+
+ UnsignedLong max (c.max ());
+ UnsignedLong min (c.context ().get<UnsignedLong> ("effective-min"));
+ UnsignedLong n (c.context ().get<UnsignedLong> ("comp-number"));
+
+ String func (c.is_a<SemanticGraph::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> () && !c.context ().count ("comp-number"))
+ continue; // Empty compositor.
+
+ if (!p.context ().count ("prefix"))
+ break;
+
+ UnsignedLong state (p.context ().get<UnsignedLong> ("state"));
+
+ if (first)
+ first = false;
+ else
+ os << "else ";
+
+ os << "if (";
+
+ particle_test_.dispatch (p);
+
+ os << ")" << endl
+ << "s = " << state << "UL;";
+ }
+
+ // 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.
+ //
+
+ 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
+ << "this->" << func << n << " (vd.state, vd.count, ns, n, t, true);"
+ << "break;"
+ << "}";
+
+ // Not this compositor.
+ //
+
+ 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)" << endl
+ << "this->_expected_element (" << endl;
+
+ particle_name_.dispatch (c);
+
+ os << "," << endl
+ << "ns, n);";
+ }
+
+ 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,
+ protected virtual 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 ("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
+ << "const " << string_type << "* t," << endl
+ << "bool start)"
+ << "{"
+ << "XSD_UNUSED (t);"
+ << 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> ("state"));
+
+ os << "if (count[" << state << "UL] == 0)" << endl
+ << "this->_expected_element (" << endl
+ << L << strlit (ns) << ", " <<
+ L << strlit (e.name ()) << ");"
+ << endl;
+ }
+
+ os << "state = ~0UL;"
+ << "}"
+ << "else" << endl
+ << "state = ~0UL;"
+ << "}";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ if (!c.context().count ("comp-number")) // Empty compositor.
+ return;
+
+ using SemanticGraph::Compositor;
+
+ UnsignedLong n (c.context ().get<UnsignedLong> ("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
+ << "const " << string_type << "* t," << endl
+ << "bool start)"
+ << "{"
+ << "XSD_UNUSED (count);"
+ << "XSD_UNUSED (ns);"
+ << "XSD_UNUSED (n);"
+ << "XSD_UNUSED (t);"
+ << 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 ("comp-number"))
+ continue; // Empty compositor.
+
+ ParticleInChoice t (*this, type_);
+ t.dispatch (p);
+ }
+
+ os << "}" // switch
+ << "}";
+
+ // Generate nested compositor functions.
+ //
+ Traversal::Choice::traverse (c);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ if (!s.context().count ("comp-number")) // Empty compositor.
+ return;
+
+ using SemanticGraph::Compositor;
+
+ UnsignedLong n (s.context ().get<UnsignedLong> ("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
+ << "const " << string_type << "* t," << endl
+ << "bool start)"
+ << "{"
+ << "XSD_UNUSED (t);"
+ << endl
+ << "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 ("comp-number"))
+ {
+ // Empty compositor.
+ //
+ ++ci;
+ continue;
+ }
+
+ // Find the next state.
+ //
+ do
+ ++ci;
+ while (ci != ce &&
+ ci->particle ().is_a<Compositor> () &&
+ !ci->particle ().context().count ("comp-number"));
+
+ UnsignedLong next (ci == ce ? 0 : state + 1);
+
+ ParticleInSequence t (*this, state++, next, type_);
+ t.dispatch (p);
+ }
+
+ 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,
+ protected virtual 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,
+ protected virtual 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, t, true);"
+ << endl
+ << "if (vd->state != ~0UL)" << endl
+ << "vd->count++;"
+ << "else" << endl
+ << "return false;" // Let our parent handle this.
+ << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Compositor& c) // Choice and sequence.
+ {
+ using SemanticGraph::Compositor;
+
+ UnsignedLong max (c.max ());
+ UnsignedLong min (c.context ().get<UnsignedLong> ("effective-min"));
+ UnsignedLong n (c.context ().get<UnsignedLong> ("comp-number"));
+
+ String func (c.is_a<SemanticGraph::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, t, true);"
+ << endl
+ << "vd = vs.data + (vs.size - 1);" // re-acquire
+ << endl
+ << "if (vd->state == ~0UL)" << 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> () && !c.context ().count ("comp-number"))
+ continue; // Empty compositor.
+
+ if (!p.context ().count ("prefix"))
+ break;
+
+ UnsignedLong state (p.context ().get<UnsignedLong> ("state"));
+
+ if (first)
+ first = false;
+ else
+ os << "else ";
+
+ os << "if (";
+
+ particle_test_.dispatch (p);
+
+ os << ")" << endl
+ << "s = " << state << "UL;";
+ }
+
+ 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.
+ //
+
+ os << endl
+ << "vd = vs.data + vs.size++;" // push
+ << "vd->func = &" << ename (type_) << "::" << func << n << ";"
+ << "vd->state = s;"
+ << "vd->count = 0;"
+ << endl
+ << "this->" << func << n << " (vd->state, vd->count, ns, n, t, true);"
+ << "}";
+
+ // This element is not our prefix.
+ //
+
+ os << "else"
+ << "{";
+
+ // 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->_expected_element (" << endl;
+
+ particle_name_.dispatch (c);
+
+ os << "," << endl
+ << "ns, n);";
+ }
+
+ // 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,
+ protected virtual 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, 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, 0, false);"
+ << endl
+ << "if (vd.state == ~0UL)" << endl
+ << "vs.size--;" // pop
+ << endl;
+ }
+
+ private:
+ SemanticGraph::Complex& type_;
+ };
+
+
+ //
+ //
+ struct CompositorPost: Traversal::All,
+ Traversal::Compositor,
+ protected virtual 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, 0, true);"
+ << "}";
+
+ if (a.context ().get<UnsignedLong> ("effective-min") != 0)
+ {
+ os << "else" << endl
+ << "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.
+ {
+ UnsignedLong min (c.context ().get<UnsignedLong> ("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, 0, true);"
+ << "assert (vd->state == ~0UL);"
+ << "vd = vs.data + (--vs.size - 1);" // pop
+ << "}";
+
+ // 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->_expected_element (" << endl;
+
+ particle_name_.dispatch (c);
+
+ os << ");";
+ }
+ }
+
+ private:
+ SemanticGraph::Complex& type_;
+ ParticleName particle_name_;
+ };
+
+
+ //
+ //
+ struct Complex : Traversal::Complex,
+ protected virtual 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," << endl
+ << "const " << string_type << "* t)"
+ << "{"
+ << "XSD_UNUSED (t);"
+ << 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.
+ // States 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)"
+ << "{"
+ << "if (this->";
+
+ if (c.inherits_p ())
+ os << fq_name (c.inherits ().base ());
+ else
+ os << complex_base;
+
+
+ os << "::_start_element_impl (ns, n, t))" << endl
+ << "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)"
+ << "{"
+ << "if (!";
+
+ if (c.inherits_p ())
+ os << fq_name (c.inherits ().base ());
+ else
+ os << complex_base;
+
+ os << "::_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 ()"
+ << "{"
+ << "this->v_state_stack_.push ();"
+ << "static_cast< v_state_* > (this->v_state_stack_.top ())->" <<
+ "size = 0;"
+ << endl;
+
+ {
+ 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 ())
+ {
+ os << endl
+ << fq_name (c.inherits ().base ()) << "::_pre_e_validate ();";
+ }
+ }
+
+ os << "}";
+
+
+ // _post_e_validate
+ //
+ os << "void " << name << "::" << endl
+ << "_post_e_validate ()"
+ << "{";
+
+ // 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 ())
+ {
+ os << fq_name (c.inherits ().base ()) << "::_post_e_validate ();"
+ << 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 <cassert>" << 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/xsd/cxx/parser/element-validation-source.hxx b/xsd/cxx/parser/element-validation-source.hxx
new file mode 100644
index 0000000..493c1ef
--- /dev/null
+++ b/xsd/cxx/parser/element-validation-source.hxx
@@ -0,0 +1,22 @@
+// file : xsd/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/xsd/cxx/parser/elements.cxx b/xsd/cxx/parser/elements.cxx
new file mode 100644
index 0000000..8a02ffb
--- /dev/null
+++ b/xsd/cxx/parser/elements.cxx
@@ -0,0 +1,262 @@
+// file : xsd/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
+ {
+ // Keep this symbol first to help HP-UX linker (long symbols?).
+ //
+ 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;
+ }
+
+ 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,
+ ops.value<CLI::char_type> (),
+ ops.value<CLI::include_with_brackets> (),
+ ops.value<CLI::include_prefix> (),
+ ops.value<CLI::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_),
+ cout_inst (cout_inst_),
+ cerr_inst (cerr_inst_),
+ parser_map (parser_map_),
+ std_string_type (std_string_type_),
+ validation (validation_),
+ polymorphic (polymorphic_),
+ hxx_expr (he),
+ ixx_expr (ie),
+ hxx_impl_expr (hie),
+ xml_parser_ (ops.value<CLI::xml_parser> ()),
+ validation_ ((ops.value<CLI::xml_parser> () == "expat" ||
+ ops.value<CLI::generate_validation> ()) &&
+ !ops.value<CLI::suppress_validation> ()),
+ polymorphic_ (ops.value<CLI::generate_polymorphic> ())
+ {
+ if (char_type == L"char")
+ std_string_type = L"::std::string";
+ else if (char_type == L"wchar_t")
+ std_string_type = L"::std::wstring";
+ else
+ std_string_type = L"::std::basic_string< " + char_type + L" >";
+
+ String xs_ns (xs_ns_name ());
+
+ string_type = xs_ns + L"::ro_string";
+ simple_base = xs_ns + L"::simple_content";
+ complex_base = xs_ns + L"::complex_content";
+ list_base = xs_ns + L"::list_base";
+
+ cout_inst = (char_type == L"char" ? L"std::cout" : L"std::wcout");
+ cerr_inst = (char_type == L"char" ? L"std::cerr" : L"std::wcerr");
+
+ if (polymorphic)
+ parser_map_ = xs_ns + L"::parser_map";
+ }
+
+ Context::
+ 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),
+ cout_inst (c.cout_inst),
+ cerr_inst (c.cerr_inst),
+ parser_map (c.parser_map),
+ std_string_type (c.std_string_type),
+ validation (c.validation),
+ polymorphic (c.polymorphic),
+ hxx_expr (c.hxx_expr),
+ ixx_expr (c.ixx_expr),
+ hxx_impl_expr (c.hxx_impl_expr)
+ {
+ }
+
+ Context::
+ 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),
+ cout_inst (c.cout_inst),
+ cerr_inst (c.cerr_inst),
+ parser_map (c.parser_map),
+ std_string_type (c.std_string_type),
+ validation (c.validation),
+ polymorphic (c.polymorphic),
+ hxx_expr (c.hxx_expr),
+ ixx_expr (c.ixx_expr),
+ hxx_impl_expr (c.hxx_impl_expr)
+ {
+ }
+
+ Boolean Context::
+ anonymous (SemanticGraph::Type& t)
+ {
+ return t.context ().count ("anonymous");
+ }
+
+ String const& Context::
+ ret_type (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("ret-type");
+ }
+
+ String const& Context::
+ arg_type (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("arg-type");
+ }
+
+ String const& Context::
+ post_name (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("post");
+ }
+
+ String const& Context::
+ eparser (SemanticGraph::Member& m)
+ {
+ return m.context ().get<String> ("parser");
+ }
+
+ String const& Context::
+ emember (SemanticGraph::Member& m)
+ {
+ return m.context ().get<String> ("member");
+ }
+
+ String const& Context::
+ emember_cache (SemanticGraph::Member& m)
+ {
+ return m.context ().get<String> ("member-cache");
+ }
+
+ String const& Context::
+ emember_map (SemanticGraph::Member& m)
+ {
+ return m.context ().get<String> ("member-map");
+ }
+
+ String const& Context::
+ eimpl (SemanticGraph::Type& t)
+ {
+ return t.context ().get<String> ("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/xsd/cxx/parser/elements.hxx b/xsd/cxx/parser/elements.hxx
new file mode 100644
index 0000000..cac1786
--- /dev/null
+++ b/xsd/cxx/parser/elements.hxx
@@ -0,0 +1,312 @@
+// file : xsd/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);
+ Context (Context& c, std::wostream& o);
+
+ 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 Content::Value
+ content (SemanticGraph::Complex&);
+
+ public:
+ static Boolean
+ anonymous (SemanticGraph::Type&);
+
+ public:
+ static String const&
+ ret_type (SemanticGraph::Type&);
+
+ static String const&
+ arg_type (SemanticGraph::Type&);
+
+ static String const&
+ post_name (SemanticGraph::Type&);
+
+ 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&);
+
+ 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& cout_inst;
+ String& cerr_inst;
+ String& parser_map;
+ String& std_string_type;
+ Boolean& validation;
+ Boolean& polymorphic;
+
+ 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 cout_inst_;
+ String cerr_inst_;
+ String parser_map_;
+ String std_string_type_;
+ Boolean validation_;
+ Boolean polymorphic_;
+ };
+
+ //
+ //
+ struct RequiredAttributeTest: Traversal::Attribute
+ {
+ RequiredAttributeTest (Boolean& result)
+ : result_ (result)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ if (!result_ && !a.optional ())
+ result_ = true;
+ }
+
+ private:
+ Boolean& result_;
+ };
+
+ //
+ //
+ struct ParserParamDecl : Traversal::Complex,
+ Traversal::List,
+ Traversal::Member,
+ protected virtual Context
+ {
+ ParserParamDecl (Context& c, Boolean name_arg)
+ : Context (c), first_ (true), name_arg_ (name_arg)
+ {
+ inherits_ >> *this;
+ names_ >> *this;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ inherits (c, inherits_);
+
+ if (!restriction_p (c))
+ names (c, names_);
+ }
+
+ 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 */";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Member& m)
+ {
+ if (skip (m)) return;
+
+ if (!first_)
+ os << "," << endl;
+ else
+ first_ = false;
+
+ os << fq_name (m.type ()) << "&";
+
+ if (name_arg_)
+ os << " " << ename (m);
+ else
+ os << " /* " << comment (m.name ()) << " */";
+ }
+
+ private:
+ Traversal::Inherits inherits_;
+ 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 ? "name" : "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/xsd/cxx/parser/generator.cxx b/xsd/cxx/parser/generator.cxx
new file mode 100644
index 0000000..342e3f2
--- /dev/null
+++ b/xsd/cxx/parser/generator.cxx
@@ -0,0 +1,1450 @@
+// file : xsd/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 <type-map/type-map.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-header.hxx>
+#include <cxx/parser/parser-inline.hxx>
+#include <cxx/parser/parser-source.hxx>
+#include <cxx/parser/parser-forward.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 "../../../libxsd/xsd/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, an XML Schema to\n"
+ "// C++ data binding compiler.\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"
+ "// In addition, as a special exception, Code Synthesis Tools CC gives\n"
+ "// permission to link this program with the Xerces-C++ library (or with\n"
+ "// modified versions of Xerces-C++ that use the same license as Xerces-C++),\n"
+ "// and distribute linked combinations including the two. You must obey\n"
+ "// the GNU General Public License version 2 in all respects for all of\n"
+ "// the code used other than Xerces-C++. If you modify this copy of the\n"
+ "// program, you may extend this exception to your version of the program,\n"
+ "// but you are not obligated to do so. If you do not wish to do so, delete\n"
+ "// this exception statement from your version.\n"
+ "//\n"
+ "// Furthermore, Code Synthesis Tools CC makes a special exception for\n"
+ "// the Free/Libre and Open Source Software (FLOSS) which is described\n"
+ "// in the accompanying FLOSSE file.\n"
+ "//\n\n";
+
+ Char const copyright_proprietary[] =
+ "// Copyright (C) 2005-2009 Code Synthesis Tools CC\n"
+ "//\n"
+ "// This program was generated by CodeSynthesis XSD, an XML Schema\n"
+ "// to C++ data binding compiler, in the Proprietary License mode.\n"
+ "// You should have received a proprietary license from Code Synthesis\n"
+ "// Tools CC prior to generating this code. See the license text for\n"
+ "// conditions.\n"
+ "//\n\n";
+
+ Char const copyright_impl[] =
+ "// Not copyrighted - public domain.\n"
+ "//\n"
+ "// This sample parser implementation was generated by CodeSynthesis XSD,\n"
+ "// an XML Schema to C++ data binding compiler. You may use it in your\n"
+ "// programs without any restrictions.\n"
+ "//\n\n";
+ }
+
+ namespace Parser
+ {
+ namespace CLI
+ {
+ extern Key char_type;
+ extern Key type_map = "type-map";
+ extern Key char_type = "char-type";
+ extern Key output_dir = "output-dir";
+ extern Key xml_parser = "xml-parser";
+ extern Key generate_inline = "generate-inline";
+ extern Key generate_validation = "generate-validation";
+ extern Key suppress_validation = "suppress-validation";
+ extern Key generate_polymorphic = "generate-polymorphic";
+ 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 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 export_symbol = "export-symbol";
+ extern Key export_maps = "export-maps";
+ extern Key import_maps = "import-maps";
+ 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 << "--char-type <type>" << endl
+ << " Use <type> as the base character type. Valid\n"
+ << " values are 'char' (default) and 'wchar_t'."
+ << endl;
+
+ e << "--output-dir <dir>" << endl
+ << " Write generated files to <dir> instead of current\n"
+ << " directory."
+ << endl;
+
+ e << "--xml-parser <parser>" << endl
+ << " Use <parser> as the underlying XML parser. Valid\n"
+ << " values are 'xerces' (default) and 'expat'."
+ << endl;
+
+ e << "--generate-inline" << endl
+ << " Generate certain functions inline."
+ << endl;
+
+ e << "--generate-validation" << endl
+ << " Generate validation code."
+ << 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 << "--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 << "--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 << "--export-symbol <symbol>" << endl
+ << " Export symbol for Win32 DLL export/import control."
+ << endl;
+
+ e << "--export-maps" << endl
+ << " Export polymorphism support maps from Win32 DLL."
+ << endl;
+
+ e << "--import-maps" << endl
+ << " Import polymorphism support maps from Win32 DLL."
+ << endl;
+
+ 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::char_type> ().default_value ("char");
+ spec.option<CLI::xml_parser> ().default_value ("xerces");
+
+ 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,
+ 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::xml_parser> () == "expat" ||
+ ops.value<CLI::generate_validation> ()) &&
+ !ops.value<CLI::suppress_validation> ());
+
+ // Compute state machine info.
+ //
+ if (validation)
+ {
+ StateProcessor proc;
+ proc.process (schema, file_path);
+ }
+
+ // Read-in type maps.
+ //
+ TypeMap::Namespaces type_map;
+ {
+ 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-based types.
+ //
+ String char_type (ops.value<CLI::char_type> ());
+ String string_type;
+
+ 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" >";
+
+ String xns;
+ {
+ Context ctx (std::wcerr, schema, ops, 0, 0, 0);
+ xns = ctx.xs_ns_name ();
+ }
+
+ String buffer (L"::std::auto_ptr< " + xns + L"::buffer >");
+ TypeMap::Namespace xsd ("http://www\\.w3\\.org/2001/XMLSchema");
+
+ xsd.types_push_back ("string", string_type);
+ xsd.types_push_back ("normalizedString", string_type);
+ xsd.types_push_back ("token", string_type);
+ xsd.types_push_back ("Name", string_type);
+ xsd.types_push_back ("NMTOKEN", string_type);
+ xsd.types_push_back ("NMTOKENS", xns + L"::string_sequence");
+ xsd.types_push_back ("NCName", string_type);
+
+ xsd.types_push_back ("ID", string_type);
+ xsd.types_push_back ("IDREF", string_type);
+ xsd.types_push_back ("IDREFS", xns + L"::string_sequence");
+
+ xsd.types_push_back ("language", string_type);
+ xsd.types_push_back ("anyURI", string_type);
+ xsd.types_push_back ("QName", xns + L"::qname");
+
+ 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");
+
+ // Fundamental C++ types.
+ //
+ 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");
+
+ 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", "long long");
+
+ xsd.types_push_back ("negativeInteger", "long long", "long long");
+ xsd.types_push_back ("nonPositiveInteger", "long long", "long long");
+
+ xsd.types_push_back ("positiveInteger",
+ "unsigned long long",
+ "unsigned long long");
+ xsd.types_push_back ("nonNegativeInteger",
+ "unsigned long long",
+ "unsigned long long");
+
+ xsd.types_push_back ("float", "float", "float");
+ xsd.types_push_back ("double", "double", "double");
+ xsd.types_push_back ("decimal", "double", "double");
+
+ 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, gen_driver, type_map);
+ }
+
+ //
+ //
+ Boolean inline_ (ops.value<CLI::generate_inline> () &&
+ !generate_xml_schema);
+
+ Boolean source (!generate_xml_schema);
+
+ // Generate code.
+ //
+ 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-driver" + 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 <xsd/cxx/config.hxx>" << endl
+ << endl
+ << "#if (XSD_INT_VERSION != " << XSD_INT_VERSION << "L)" << endl
+ << "#error XSD runtime version mismatch" << endl
+ << "#endif" << endl
+ << endl;
+
+ {
+ hxx << "#include <xsd/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;
+
+ hxx << "#include <xsd/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/xsd/cxx/parser/generator.hxx b/xsd/cxx/parser/generator.hxx
new file mode 100644
index 0000000..aaab3b8
--- /dev/null
+++ b/xsd/cxx/parser/generator.hxx
@@ -0,0 +1,55 @@
+// file : xsd/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 <xsd.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,
+ Boolean gen_driver,
+ const WarningSet& disabled_warnings,
+ FileList& file_list,
+ AutoUnlinks& unlinks);
+
+ private:
+ Generator ();
+ };
+ }
+}
+
+#endif // CXX_PARSER_GENERATOR_HXX
diff --git a/xsd/cxx/parser/impl-header.cxx b/xsd/cxx/parser/impl-header.cxx
new file mode 100644
index 0000000..8a52254
--- /dev/null
+++ b/xsd/cxx/parser/impl-header.cxx
@@ -0,0 +1,237 @@
+// file : xsd/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,
+ protected virtual 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 " << type_exp << name << ": " <<
+ "public virtual " << ename (e) << "," << endl
+ << " public " << fq_name (base, "impl")
+ << "{"
+ << "public:" << endl
+ << "virtual void" << endl
+ << "pre ();"
+ << endl
+ << "virtual " << ret << endl
+ << post_name (e) << " ();"
+ << "};";
+ }
+ };
+
+ //
+ //
+ struct List: Traversal::List, protected virtual 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 " << type_exp << name << ": public 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, protected virtual Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ String const& name (eimpl (u));
+ String const& ret (ret_type (u));
+
+ os << "class " << type_exp << name << ": public 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 ParserCallback: Traversal::Member,
+ protected virtual Context
+ {
+ ParserCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& m)
+ {
+ if (skip (m))
+ return;
+
+ String const& arg (arg_type (m.type ()));
+
+ os << "virtual void" << endl
+ << ename (m);
+
+ if (arg == L"void")
+ os << " ();";
+ else
+ os << " (" << arg << ");";
+
+ os << endl;
+ }
+ };
+
+ //
+ //
+ struct Complex : Traversal::Complex,
+ protected virtual Context
+ {
+ Complex (Context& c)
+ : Context (c),
+ parser_callback_ (c)
+ {
+ names_parser_callback_ >> parser_callback_;
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ String const& name (eimpl (c));
+ String const& ret (ret_type (c));
+
+ os << "class " << type_exp << name << ": public virtual " <<
+ ename (c);
+
+ if (c.inherits_p ())
+ os << "," << endl
+ << " public " << fq_name (c.inherits ().base (), "impl");
+
+ os << "{"
+ << "public:" << endl
+ << "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))
+ {
+ names (c, names_parser_callback_);
+ }
+
+ os << "virtual " << ret << endl
+ << post_name (c) << " ();"
+ << "};";
+ }
+
+ private:
+ //
+ //
+ ParserCallback parser_callback_;
+ Traversal::Names names_parser_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/xsd/cxx/parser/impl-header.hxx b/xsd/cxx/parser/impl-header.hxx
new file mode 100644
index 0000000..d69c65a
--- /dev/null
+++ b/xsd/cxx/parser/impl-header.hxx
@@ -0,0 +1,22 @@
+// file : xsd/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/xsd/cxx/parser/impl-source.cxx b/xsd/cxx/parser/impl-source.cxx
new file mode 100644
index 0000000..00b9456
--- /dev/null
+++ b/xsd/cxx/parser/impl-source.cxx
@@ -0,0 +1,389 @@
+// file : xsd/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,
+ protected virtual 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;
+
+ // 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::generate_print_impl> ())
+ {
+ PrintCall t (*this, e.name (), "v");
+ t.dispatch (base);
+ }
+ else
+ os << "// TODO" << endl
+ << "//" << endl;
+ }
+ else
+ {
+ if (base_ret == L"void")
+ os << post_name (base) << " ();";
+ else
+ os << arg_type (base) << " v (" << post_name (base) << " ());"
+ << endl
+ << "// TODO" << endl
+ << "//" << endl
+ << "// return ... ;" << endl;
+ }
+
+ os << "}";
+ }
+ };
+
+ //
+ //
+ struct List: Traversal::List, protected virtual 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;
+ }
+
+ 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, protected virtual 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> ())
+ os << cout_inst << " << " << L << 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 ParserCallback: Traversal::Member,
+ protected virtual Context
+ {
+ ParserCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& m)
+ {
+ if (skip (m))
+ return;
+
+ String const& name (ename (m));
+ String const& arg (arg_type (m.type ()));
+
+ os << "void " <<
+ eimpl (dynamic_cast<SemanticGraph::Complex&> (m.scope ())) <<
+ "::" << 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, m.name (), name);
+ t.dispatch (m.type ());
+ }
+ else
+ os << "// TODO" << endl
+ << "//" << endl;
+ }
+
+ os << "}";
+ }
+ };
+
+ //
+ //
+ struct Complex : Traversal::Complex,
+ protected virtual Context
+ {
+ Complex (Context& c)
+ : Context (c), parser_callback_ (c)
+ {
+ names_parser_callback_ >> parser_callback_;
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ String const& name (eimpl (c));
+
+ Boolean restriction (restriction_p (c));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ // pre
+ //
+ os << "void " << name << "::" << endl
+ << "pre ()"
+ << "{"
+ << "}";
+
+ // Parser callbacks.
+ //
+ if (!restriction)
+ names (c, names_parser_callback_);
+
+ // post
+ //
+ String const& ret (ret_type (c));
+
+ os << ret << " " << name << "::" << endl
+ << post_name (c) << " ()"
+ << "{";
+
+ if (c.inherits_p ())
+ {
+ 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::generate_print_impl> ())
+ {
+ PrintCall t (*this, c.name (), "v");
+ t.dispatch (base);
+ }
+ else
+ os << "// TODO" << endl
+ << "//" << endl;
+ }
+ else
+ {
+ if (base_ret == L"void")
+ os << post_name (base) << " ();";
+ else
+ os << arg_type (base) << " v (" << post_name (base) << " ());"
+ << endl
+ << "// TODO" << endl
+ << "//" << endl
+ << "// return ... ;" << endl;
+ }
+ }
+ else
+ {
+ if (ret != L"void")
+ os << "// TODO" << endl
+ << "//" << endl
+ << "// return ... ;" << endl;
+ }
+
+ os << "}";
+ }
+
+ private:
+ //
+ //
+ ParserCallback parser_callback_;
+ Traversal::Names names_parser_callback_;
+ };
+ }
+
+ Void
+ generate_impl_source (Context& ctx)
+ {
+ if (ctx.options.value<CLI::generate_print_impl> ())
+ 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/xsd/cxx/parser/impl-source.hxx b/xsd/cxx/parser/impl-source.hxx
new file mode 100644
index 0000000..68a5f5e
--- /dev/null
+++ b/xsd/cxx/parser/impl-source.hxx
@@ -0,0 +1,22 @@
+// file : xsd/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/xsd/cxx/parser/name-processor.cxx b/xsd/cxx/parser/name-processor.cxx
new file mode 100644
index 0000000..b40522b
--- /dev/null
+++ b/xsd/cxx/parser/name-processor.cxx
@@ -0,0 +1,1205 @@
+// file : xsd/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
+ {
+ NameProcessor::
+ NameProcessor ()
+ {
+ // Dummy ctor, helps with long symbols on HP-UX.
+ }
+
+ 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,
+ ops.value<CLI::char_type> (),
+ ops.value<CLI::include_with_brackets> (),
+ ops.value<CLI::include_prefix> (),
+ ops.value<CLI::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> ()),
+ skel_suffix (skel_suffix_),
+ impl_suffix (impl_suffix_),
+ global_type_names (global_type_names_),
+ polymorphic (ops.value<CLI::generate_polymorphic> ())
+ {
+ }
+
+ protected:
+ Context (Context& c)
+ : CXX::Context (c),
+ schema (c.schema),
+ schema_path (c.schema_path),
+ impl (c.impl),
+ skel_suffix (c.skel_suffix),
+ impl_suffix (c.impl_suffix),
+ global_type_names (c.global_type_names),
+ polymorphic (c.polymorphic)
+ {
+ }
+
+ public:
+ String
+ find_name (String const& n, NameSet& set)
+ {
+ String base_name (escape (n));
+ 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;
+ }
+
+ 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;
+ String const& skel_suffix;
+ String const& impl_suffix;
+
+ Cult::Containers::Map<String, NameSet>& global_type_names;
+
+ Boolean polymorphic;
+ };
+
+
+ //
+ //
+ struct PrimaryMember: Traversal::Member, Context
+ {
+ PrimaryMember (Context& c, NameSet& set)
+ : Context (c), set_ (set)
+ {
+ }
+
+ virtual Void
+ traverse (Type& m)
+ {
+ if (Parser::Context::skip (m))
+ return;
+
+ m.context ().set ("name", find_name (m.name (), set_));
+ }
+
+ private:
+ NameSet& set_;
+ };
+
+ struct DerivedMember: Traversal::Member, Context
+ {
+ DerivedMember (Context& c, NameSet& set)
+ : Context (c), set_ (set)
+ {
+ }
+
+ virtual Void
+ traverse (Type& m)
+ {
+ if (Parser::Context::skip (m))
+ return;
+
+ m.context ().set ("parser",
+ find_name (m.name () + L"_parser", set_));
+
+ String const& base (m.context ().get<String> ("name"));
+ m.context ().set ("member", find_name (base + L"_parser_", set_));
+
+ if (polymorphic &&
+ m.is_a<SemanticGraph::Element> () &&
+ !m.type ().context ().count ("anonymous"))
+ {
+ m.context ().set (
+ "member-cache", find_name (base + L"_parser_cache_", set_));
+
+ m.context ().set (
+ "member-map", find_name (base + L"_parser_map_", set_));
+
+ m.context ().set (
+ "member-map-impl",
+ find_name (base + L"_parser_map_impl_", set_));
+ }
+ }
+
+ private:
+ NameSet& set_;
+ };
+
+
+ //
+ //
+ struct MemberInRestrictionBase: Traversal::Member
+ {
+ protected:
+ MemberInRestrictionBase (NameSet& set, SemanticGraph::Complex& base)
+ : set_ (set), base_ (base)
+ {
+ }
+
+ struct NotFound {};
+
+ Type&
+ find_member (SemanticGraph::Complex& c, Type& m)
+ {
+ using SemanticGraph::Complex;
+
+ Complex::NamesIteratorPair r (c.find (m.name ()));
+
+ for (; r.first != r.second; ++r.first)
+ {
+ if (r.first->named ().is_a<Type> ())
+ {
+ Type& bm (dynamic_cast<Type&> (r.first->named ()));
+
+ if (typeid (bm) != typeid (m))
+ continue;
+
+ if (m.qualified ())
+ {
+ if (bm.qualified () &&
+ m.name () == bm.name () &&
+ m.namespace_ ().name () == bm.namespace_ ().name ())
+ return bm;
+ }
+ else
+ {
+ if (!bm.qualified () && m.name () == bm.name ())
+ return bm;
+ }
+ }
+ }
+
+ // If we didn't find anything, try our base.
+ //
+ if (c.inherits_p ())
+ {
+ SemanticGraph::Type& base (c.inherits ().base ());
+
+ if (base.is_a<Complex> ())
+ return find_member (dynamic_cast<Complex&> (base), m);
+ }
+
+ //std::wcerr << "unable to find member " << m.name () << " in "
+ // << c.name () << std::endl;
+
+ throw NotFound ();
+ }
+
+ protected:
+ NameSet& set_;
+ SemanticGraph::Complex& base_;
+ };
+
+ struct PrimaryMemberInRestriction: MemberInRestrictionBase, Context
+ {
+ PrimaryMemberInRestriction (Context& c,
+ NameSet& set,
+ SemanticGraph::Complex& base)
+ : MemberInRestrictionBase (set, base), Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& m)
+ {
+ if (Parser::Context::skip (m))
+ return;
+
+ String name;
+
+ try
+ {
+ // Try to find corresponding member in one of our bases.
+ // This may fail if we use an element that substitutes
+ // one in our base.
+ //
+ Type& bm (find_member (base_, m));
+ name = bm.context ().get<String> ("name");
+ }
+ catch (NotFound const&)
+ {
+ // Fall back to the standard name assignment.
+ //
+ name = find_name (m.name (), set_);
+ }
+
+ m.context ().set ("name", name);
+ }
+ };
+
+ struct DerivedMemberInRestriction: MemberInRestrictionBase, Context
+ {
+ DerivedMemberInRestriction (Context& c,
+ NameSet& set,
+ SemanticGraph::Complex& base)
+ : MemberInRestrictionBase (set, base), Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& m)
+ {
+ if (Parser::Context::skip (m))
+ return;
+
+ Boolean poly (polymorphic &&
+ m.is_a<SemanticGraph::Element> () &&
+ !m.type ().context ().count ("anonymous"));
+
+ String parser, member, member_cache, member_map, member_map_impl;
+
+ try
+ {
+ // Try to find corresponding member in one of our bases.
+ // This may fail if we use an element that substitutes
+ // one in our base.
+ //
+ Type& bm (find_member (base_, m));
+ parser = bm.context ().get<String> ("parser");
+ member = bm.context ().get<String> ("member");
+
+ if (poly)
+ {
+ member_cache = bm.context ().get<String> ("member-cache");
+ member_map = bm.context ().get<String> ("member-map");
+ member_map_impl = bm.context ().get<String> ("member-map-impl");
+ }
+ }
+ catch (NotFound const&)
+ {
+ // Fall back to the standard name assignment.
+ //
+ String const& base (m.context ().get<String> ("name"));
+
+ parser = find_name (m.name () + L"_parser", set_);
+ member = find_name (base + L"_parser_", set_);
+
+ if (poly)
+ {
+ member_cache = find_name (base + L"_parser_cache_", set_);
+ member_map = find_name (base + L"_parser_map_", set_);
+ member_map_impl = find_name (base + L"_parser_map_impl_", set_);
+ }
+ }
+
+ m.context ().set ("parser", parser);
+ m.context ().set ("member", member);
+
+ if (poly)
+ {
+ m.context ().set ("member-cache", member_cache);
+ m.context ().set ("member-map", member_map);
+ m.context ().set ("member-map-impl", member_map_impl);
+ }
+ }
+ };
+
+ //
+ //
+ 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> ("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> ();
+ }
+ }
+
+ if (restriction)
+ {
+ // First assign the "primary" names.
+ //
+ {
+ PrimaryMemberInRestriction member (
+ *this,
+ member_set,
+ dynamic_cast<SemanticGraph::Complex&> (
+ c.inherits ().base ()));
+
+ Traversal::Names names (member);
+
+ Complex::names (c, names);
+ }
+
+ // Assign "derived" names.
+ //
+ {
+ DerivedMemberInRestriction member (
+ *this,
+ member_set,
+ dynamic_cast<SemanticGraph::Complex&> (
+ c.inherits ().base ()));
+
+ Traversal::Names names (member);
+
+ Complex::names (c, names);
+ }
+ }
+ else
+ {
+ // First assign the "primary" names.
+ //
+ {
+ PrimaryMember member (*this, member_set);
+ Traversal::Names names (member);
+
+ Complex::names (c, names);
+ }
+
+ // Assign "derived" names.
+ //
+ {
+ DerivedMember member (*this, member_set);
+ Traversal::Names names (member);
+
+ 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 ("name", name);
+
+ // Assign the post_* name.
+ //
+ c.set ("post", find_post_name (t));
+
+ // Note that we do not add this name to the set so that it
+ // does not influence other names.
+ //
+ if (impl)
+ c.set ("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 ("post"))
+ set.insert (b->context ().get<String> ("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)
+ {
+ NameSet& type_set (global_type_names[ns.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)
+ {
+ t.context ().set ("name", make_skel_name ("any_type"));
+ t.context ().set ("impl", make_impl_name ("any_type"));
+ t.context ().set ("post", String ("post_any_type"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnySimpleType& t)
+ {
+ t.context ().set ("name", make_skel_name ("any_simple_type"));
+ t.context ().set ("impl", make_impl_name ("any_simple_type"));
+ t.context ().set ("post", String ("post_any_simple_type"));
+ }
+
+ // Boolean.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Boolean& t)
+ {
+ t.context ().set ("name", make_skel_name ("boolean"));
+ t.context ().set ("impl", make_impl_name ("boolean"));
+ t.context ().set ("post", String ("post_boolean"));
+ }
+
+ // Integral types.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Byte& t)
+ {
+ t.context ().set ("name", make_skel_name ("byte"));
+ t.context ().set ("impl", make_impl_name ("byte"));
+ t.context ().set ("post", String ("post_byte"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedByte& t)
+ {
+ t.context ().set ("name", make_skel_name ("unsigned_byte"));
+ t.context ().set ("impl", make_impl_name ("unsigned_byte"));
+ t.context ().set ("post", String ("post_unsigned_byte"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Short& t)
+ {
+ t.context ().set ("name", make_skel_name ("short"));
+ t.context ().set ("impl", make_impl_name ("short"));
+ t.context ().set ("post", String ("post_short"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedShort& t)
+ {
+ t.context ().set ("name", make_skel_name ("unsigned_short"));
+ t.context ().set ("impl", make_impl_name ("unsigned_short"));
+ t.context ().set ("post", String ("post_unsigned_short"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Int& t)
+ {
+ t.context ().set ("name", make_skel_name ("int"));
+ t.context ().set ("impl", make_impl_name ("int"));
+ t.context ().set ("post", String ("post_int"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedInt& t)
+ {
+ t.context ().set ("name", make_skel_name ("unsigned_int"));
+ t.context ().set ("impl", make_impl_name ("unsigned_int"));
+ t.context ().set ("post", String ("post_unsigned_int"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Long& t)
+ {
+ t.context ().set ("name", make_skel_name ("long"));
+ t.context ().set ("impl", make_impl_name ("long"));
+ t.context ().set ("post", String ("post_long"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedLong& t)
+ {
+ t.context ().set ("name", make_skel_name ("unsigned_long"));
+ t.context ().set ("impl", make_impl_name ("unsigned_long"));
+ t.context ().set ("post", String ("post_unsigned_long"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Integer& t)
+ {
+ t.context ().set ("name", make_skel_name ("integer"));
+ t.context ().set ("impl", make_impl_name ("integer"));
+ t.context ().set ("post", String ("post_integer"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonPositiveInteger& t)
+ {
+ t.context ().set ("name", make_skel_name ("non_positive_integer"));
+ t.context ().set ("impl", make_impl_name ("non_positive_integer"));
+ t.context ().set ("post", String ("post_non_positive_integer"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonNegativeInteger& t)
+ {
+ t.context ().set ("name", make_skel_name ("non_negative_integer"));
+ t.context ().set ("impl", make_impl_name ("non_negative_integer"));
+ t.context ().set ("post", String ("post_non_negative_integer"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::PositiveInteger& t)
+ {
+ t.context ().set ("name", make_skel_name ("positive_integer"));
+ t.context ().set ("impl", make_impl_name ("positive_integer"));
+ t.context ().set ("post", String ("post_positive_integer"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NegativeInteger& t)
+ {
+ t.context ().set ("name", make_skel_name ("negative_integer"));
+ t.context ().set ("impl", make_impl_name ("negative_integer"));
+ t.context ().set ("post", String ("post_negative_integer"));
+ }
+
+ // Floats.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Float& t)
+ {
+ t.context ().set ("name", make_skel_name ("float"));
+ t.context ().set ("impl", make_impl_name ("float"));
+ t.context ().set ("post", String ("post_float"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Double& t)
+ {
+ t.context ().set ("name", make_skel_name ("double"));
+ t.context ().set ("impl", make_impl_name ("double"));
+ t.context ().set ("post", String ("post_double"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Decimal& t)
+ {
+ t.context ().set ("name", make_skel_name ("decimal"));
+ t.context ().set ("impl", make_impl_name ("decimal"));
+ t.context ().set ("post", String ("post_decimal"));
+ }
+
+ // Strings.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::String& t)
+ {
+ t.context ().set ("name", make_skel_name ("string"));
+ t.context ().set ("impl", make_impl_name ("string"));
+ t.context ().set ("post", String ("post_string"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NormalizedString& t)
+ {
+ t.context ().set ("name", make_skel_name ("normalized_string"));
+ t.context ().set ("impl", make_impl_name ("normalized_string"));
+ t.context ().set ("post", String ("post_normalized_string"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Token& t)
+ {
+ t.context ().set ("name", make_skel_name ("token"));
+ t.context ().set ("impl", make_impl_name ("token"));
+ t.context ().set ("post", String ("post_token"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameToken& t)
+ {
+ t.context ().set ("name", make_skel_name ("nmtoken"));
+ t.context ().set ("impl", make_impl_name ("nmtoken"));
+ t.context ().set ("post", String ("post_nmtoken"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameTokens& t)
+ {
+ t.context ().set ("name", make_skel_name ("nmtokens"));
+ t.context ().set ("impl", make_impl_name ("nmtokens"));
+ t.context ().set ("post", String ("post_nmtokens"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Name& t)
+ {
+ t.context ().set ("name", make_skel_name ("name"));
+ t.context ().set ("impl", make_impl_name ("name"));
+ t.context ().set ("post", String ("post_name"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NCName& t)
+ {
+ t.context ().set ("name", make_skel_name ("ncname"));
+ t.context ().set ("impl", make_impl_name ("ncname"));
+ t.context ().set ("post", String ("post_ncname"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Language& t)
+ {
+ t.context ().set ("name", make_skel_name ("language"));
+ t.context ().set ("impl", make_impl_name ("language"));
+ t.context ().set ("post", String ("post_language"));
+ }
+
+
+ // Qualified name.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::QName& t)
+ {
+ t.context ().set ("name", make_skel_name ("qname"));
+ t.context ().set ("impl", make_impl_name ("qname"));
+ t.context ().set ("post", String ("post_qname"));
+ }
+
+
+ // ID/IDREF.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Id& t)
+ {
+ t.context ().set ("name", make_skel_name ("id"));
+ t.context ().set ("impl", make_impl_name ("id"));
+ t.context ().set ("post", String ("post_id"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRef& t)
+ {
+ t.context ().set ("name", make_skel_name ("idref"));
+ t.context ().set ("impl", make_impl_name ("idref"));
+ t.context ().set ("post", String ("post_idref"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRefs& t)
+ {
+ t.context ().set ("name", make_skel_name ("idrefs"));
+ t.context ().set ("impl", make_impl_name ("idrefs"));
+ t.context ().set ("post", String ("post_idrefs"));
+ }
+
+ // URI.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::AnyURI& t)
+ {
+ t.context ().set ("name", make_skel_name ("uri"));
+ t.context ().set ("impl", make_impl_name ("uri"));
+ t.context ().set ("post", String ("post_uri"));
+ }
+
+ // Binary.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Base64Binary& t)
+ {
+ t.context ().set ("name", make_skel_name ("base64_binary"));
+ t.context ().set ("impl", make_impl_name ("base64_binary"));
+ t.context ().set ("post", String ("post_base64_binary"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::HexBinary& t)
+ {
+ t.context ().set ("name", make_skel_name ("hex_binary"));
+ t.context ().set ("impl", make_impl_name ("hex_binary"));
+ t.context ().set ("post", String ("post_hex_binary"));
+ }
+
+
+ // Date/time.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Date& t)
+ {
+ t.context ().set ("name", make_skel_name ("date"));
+ t.context ().set ("impl", make_impl_name ("date"));
+ t.context ().set ("post", String ("post_date"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::DateTime& t)
+ {
+ t.context ().set ("name", make_skel_name ("date_time"));
+ t.context ().set ("impl", make_impl_name ("date_time"));
+ t.context ().set ("post", String ("post_date_time"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Duration& t)
+ {
+ t.context ().set ("name", make_skel_name ("duration"));
+ t.context ().set ("impl", make_impl_name ("duration"));
+ t.context ().set ("post", String ("post_duration"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Day& t)
+ {
+ t.context ().set ("name", make_skel_name ("gday"));
+ t.context ().set ("impl", make_impl_name ("gday"));
+ t.context ().set ("post", String ("post_gday"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Month& t)
+ {
+ t.context ().set ("name", make_skel_name ("gmonth"));
+ t.context ().set ("impl", make_impl_name ("gmonth"));
+ t.context ().set ("post", String ("post_gmonth"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::MonthDay& t)
+ {
+ t.context ().set ("name", make_skel_name ("gmonth_day"));
+ t.context ().set ("impl", make_impl_name ("gmonth_day"));
+ t.context ().set ("post", String ("post_gmonth_day"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Year& t)
+ {
+ t.context ().set ("name", make_skel_name ("gyear"));
+ t.context ().set ("impl", make_impl_name ("gyear"));
+ t.context ().set ("post", String ("post_gyear"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::YearMonth& t)
+ {
+ t.context ().set ("name", make_skel_name ("gyear_month"));
+ t.context ().set ("impl", make_impl_name ("gyear_month"));
+ t.context ().set ("post", String ("post_gyear_month"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Time& t)
+ {
+ t.context ().set ("name", make_skel_name ("time"));
+ t.context ().set ("impl", make_impl_name ("time"));
+ t.context ().set ("post", String ("post_time"));
+ }
+
+ // Entity.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entity& t)
+ {
+ t.context ().set ("name", make_skel_name ("entity"));
+ t.context ().set ("impl", make_impl_name ("entity"));
+ t.context ().set ("post", String ("post_entity"));
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entities& t)
+ {
+ t.context ().set ("name", make_skel_name ("entities"));
+ t.context ().set ("impl", make_impl_name ("entities"));
+ t.context ().set ("post", String ("post_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);
+ }
+ };
+
+ // 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/xsd/cxx/parser/name-processor.hxx b/xsd/cxx/parser/name-processor.hxx
new file mode 100644
index 0000000..f7849c8
--- /dev/null
+++ b/xsd/cxx/parser/name-processor.hxx
@@ -0,0 +1,34 @@
+// file : xsd/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:
+ NameProcessor (); // Dummy ctor, helps with long symbols on HP-UX.
+
+ Void
+ process (CLI::Options const& ops,
+ XSDFrontend::SemanticGraph::Schema&,
+ XSDFrontend::SemanticGraph::Path const& file);
+ };
+ }
+}
+
+#endif // CXX_PARSER_NAME_PROCESSOR_HXX
diff --git a/xsd/cxx/parser/parser-forward.cxx b/xsd/cxx/parser/parser-forward.cxx
new file mode 100644
index 0000000..4d97e23
--- /dev/null
+++ b/xsd/cxx/parser/parser-forward.cxx
@@ -0,0 +1,115 @@
+// file : xsd/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,
+ protected virtual Context
+ {
+ Enumeration (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ os << "class " << ename (e) << ";";
+ }
+ };
+
+ //
+ //
+ struct List: Traversal::List, protected virtual Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ os << "class " << ename (l) << ";";
+ }
+ };
+
+ //
+ //
+ struct Union: Traversal::Union, protected virtual Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ os << "class " << ename (u) << ";";
+ }
+ };
+
+ //
+ //
+ struct Complex : Traversal::Complex,
+ protected virtual 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/xsd/cxx/parser/parser-forward.hxx b/xsd/cxx/parser/parser-forward.hxx
new file mode 100644
index 0000000..a4c23f2
--- /dev/null
+++ b/xsd/cxx/parser/parser-forward.hxx
@@ -0,0 +1,22 @@
+// file : xsd/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/xsd/cxx/parser/parser-header.cxx b/xsd/cxx/parser/parser-header.cxx
new file mode 100644
index 0000000..f8ca090
--- /dev/null
+++ b/xsd/cxx/parser/parser-header.cxx
@@ -0,0 +1,1440 @@
+// file : xsd/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,
+ protected virtual Context
+ {
+ Enumeration (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ String const& name (ename (e));
+ SemanticGraph::Type& base (e.inherits ().base ());
+
+ os << "class " << type_exp << name << ": public virtual " <<
+ fq_name (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));
+
+ Boolean same (ret == ret_type (base));
+
+ os << "virtual " << ret << endl
+ << post_name (e) << " ()" <<
+ (same || ret == L"void" ? ";" : " = 0;");
+
+ if (polymorphic)
+ {
+ os << endl
+ << "public:" << endl
+ << "static const " << char_type << "*" << endl
+ << "_static_type ();"
+ << endl
+ << "virtual const " << char_type << "*" << endl
+ << "_dynamic_type () const;";
+ }
+
+ os << "};";
+ }
+ };
+
+ //
+ //
+ struct List: Traversal::List, protected virtual 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"));
+
+ os << "class " << type_exp << 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") << " (" << fq_name (t) << "&);"
+ << endl;
+
+ // parsers
+ //
+ os << "void" << endl
+ << "parsers (" << fq_name (t) << "& /* item */);"
+ << endl;
+
+ // c-tor
+ //
+ os << "// Constructor." << endl
+ << "//" << endl
+ << name << " ();"
+ << endl;
+
+
+ if (polymorphic)
+ {
+ os << "public:" << endl
+ << "static const " << char_type << "*" << endl
+ << "_static_type ();"
+ << endl
+ << "virtual const " << char_type << "*" << endl
+ << "_dynamic_type () const;"
+ << endl;
+ }
+
+ //
+ //
+ os << "// Implementation." << endl
+ << "//" << endl
+ << "protected:" << endl;
+
+ os << "virtual void" << endl
+ << "_xsd_parse_item (const " << string_type << "&);"
+ << endl;
+
+ os << "protected:" << endl
+ << fq_name (t) << "* _xsd_" << item << "_;"
+ << "};";
+ }
+ };
+
+ struct Union: Traversal::Union, protected virtual Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ String const& name (ename (u));
+
+ os << "class " << type_exp << 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 (polymorphic)
+ {
+ os << endl
+ << "public:" << endl
+ << "static const " << char_type << "*" << endl
+ << "_static_type ();"
+ << endl
+ << "virtual const " << char_type << "*" << endl
+ << "_dynamic_type () const;";
+ }
+
+ os << "};";
+ }
+ };
+
+
+ //
+ //
+ struct ParserCallback: Traversal::Member,
+ protected virtual Context
+ {
+ ParserCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& m)
+ {
+ if (skip (m)) return;
+
+ String const& arg (arg_type (m.type ()));
+
+ os << "virtual void" << endl
+ << ename (m);
+
+ if (arg == L"void")
+ os << " ();";
+ else
+ os << " (" << arg << ");";
+
+ os << endl;
+ }
+ };
+
+
+ //
+ //
+ struct ParserModifier: Traversal::Member,
+ protected virtual Context
+ {
+ ParserModifier (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& m)
+ {
+ if (skip (m))
+ return;
+
+ os << "void" << endl
+ << eparser (m) << " (" << fq_name (m.type ()) << "&);"
+ << endl;
+
+ if (polymorphic &&
+ m.is_a<SemanticGraph::Element> () &&
+ !anonymous (m.type ()))
+ {
+ os << "void" << endl
+ << eparser (m) << " (const " << parser_map << "&);"
+ << endl;
+ }
+ }
+ };
+
+ //
+ //
+ struct ParserMember: Traversal::Member,
+ protected virtual Context
+ {
+ ParserMember (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& m)
+ {
+ if (skip (m))
+ return;
+
+ String type (fq_name (m.type ()));
+
+ os << type << "* " << emember (m) << ";";
+
+ if (polymorphic &&
+ m.is_a<SemanticGraph::Element> () &&
+ !anonymous (m.type ()))
+ {
+ os << type << "* " << emember_cache (m) << ";"
+ << "const " << parser_map << "* " << emember_map (m) << ";"
+ << endl;
+ }
+ }
+ };
+
+ //
+ //
+ struct Particle: Traversal::All,
+ Traversal::Choice,
+ Traversal::Sequence,
+ protected virtual Context
+ {
+ Particle (Context& c)
+ : Context (c)
+ {
+ *this >> contains_particle_ >> *this;
+ }
+
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ if (!a.context().count ("comp-number"))
+ return;
+
+ UnsignedLong state_count (
+ a.context().get<UnsignedLong> ("state-count"));
+
+ os << "void" << endl
+ << "all_0 (unsigned long& state," << endl
+ << "unsigned char* count," << endl
+ << "const " << string_type << "& ns," << endl
+ << "const " << string_type << "& n," << endl
+ << "const " << string_type << "* t," << endl
+ << "bool start);"
+ << endl
+ << "unsigned char v_all_first_[" << state_count << "UL];"
+ << "::xsd::cxx::parser::validating::all_stack v_all_count_;"
+ << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Choice& c)
+ {
+ if (!c.context().count ("comp-number"))
+ return;
+
+ UnsignedLong n (c.context ().get<UnsignedLong> ("comp-number"));
+
+ os << "void" << endl
+ << "choice_" << n << " (unsigned long& state," << endl
+ << "unsigned long& count," << endl
+ << "const " << string_type << "& ns," << endl
+ << "const " << string_type << "& n," << endl
+ << "const " << string_type << "* t," << endl
+ << "bool start);"
+ << endl;
+
+ Traversal::Choice::traverse (c);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Sequence& s)
+ {
+ if (!s.context().count ("comp-number"))
+ return;
+
+ UnsignedLong n (s.context ().get<UnsignedLong> ("comp-number"));
+
+ os << "void" << endl
+ << "sequence_" << n << " (unsigned long& state," << endl
+ << "unsigned long& count," << endl
+ << "const " << string_type << "& ns," << endl
+ << "const " << string_type << "& n," << endl
+ << "const " << string_type << "* t," << endl
+ << "bool start);"
+ << endl;
+
+ Traversal::Sequence::traverse (s);
+ }
+
+ private:
+ Traversal::ContainsParticle contains_particle_;
+ };
+
+
+ //
+ //
+ struct AttributeValidationState: Traversal::Attribute,
+ protected virtual Context
+ {
+ AttributeValidationState (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ if (!a.optional ())
+ {
+ os << "bool " << ename (a) << ";";
+ }
+ }
+ };
+
+ //
+ //
+ struct Complex : Traversal::Complex,
+ protected virtual Context
+ {
+ Complex (Context& c)
+ : Context (c),
+ parser_callback_ (c),
+ parser_member_ (c),
+ parser_modifier_ (c),
+ attribute_validation_state_ (c)
+ {
+ names_parser_callback_ >> parser_callback_;
+ names_parser_member_ >> parser_member_;
+ names_parser_modifier_ >> parser_modifier_;
+ 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 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 " << type_exp << name << ": public ";
+
+ if (c.inherits_p ())
+ os << "virtual " << fq_name (c.inherits ().base ());
+ else
+ os << complex_base;
+
+ os << "{"
+ << "public:" << endl
+ << "// Parser callbacks. Override them in your " <<
+ "implementation." << endl
+ << "//" << endl;
+
+ os << "// virtual void" << endl
+ << "// pre ();" << endl
+ << endl;
+
+
+ if (!restriction && (ha || he))
+ {
+ names (c, names_parser_callback_);
+ }
+
+ String const& ret (ret_type (c));
+
+ Boolean same (c.inherits_p () &&
+ 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;
+
+ names (c, names_parser_modifier_);
+
+ os << "void" << endl
+ << "parsers (";
+
+ {
+ ParserParamDecl decl (*this, false);
+ decl.traverse (c);
+ }
+
+ os << ");"
+ << endl;
+ }
+
+ // Default c-tor.
+ //
+ if ((!restriction && (he || ha)) ||
+ (validation && (he || hae || hra)))
+ {
+ os << "// Constructor." << endl
+ << "//" << endl
+ << name << " ();"
+ << endl;
+ }
+
+ if (polymorphic)
+ {
+ os << "public:" << endl
+ << "static const " << char_type << "*" << endl
+ << "_static_type ();"
+ << endl
+ << "virtual const " << char_type << "*" << endl
+ << "_dynamic_type () const;"
+ << endl;
+ }
+
+ // Implementation.
+ //
+ if (he || ha || (validation && (hae || haa)))
+ {
+ os << "// Implementation." << endl
+ << "//" << endl
+ << "protected:" << endl;
+ }
+
+ // element
+ //
+ if (he || (validation && hae))
+ {
+ // _start_element_impl
+ //
+ os << "virtual bool" << endl
+ << "_start_element_impl (const " << string_type << "&," << endl
+ << "const " << string_type << "&," << endl
+ << "const " << string_type << "*);"
+ << endl;
+
+ // end_element
+ //
+ os << "virtual bool" << endl
+ << "_end_element_impl (const " << string_type << "&," << endl
+ << "const " << string_type << "&);"
+ << endl;
+ }
+
+ // attribute
+ //
+ if (validation)
+ {
+ 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 << "virtual bool" << endl
+ << "_attribute_impl (const " << string_type << "&," << endl
+ << "const " << string_type << "&," << endl
+ << "const " << string_type << "&);"
+ << endl;
+ }
+ }
+
+ // characters
+ //
+ if (validation && c.mixed ())
+ {
+ os << "virtual bool" << endl
+ << "_characters_impl (const " << string_type << "&);"
+ << endl;
+ }
+
+ if (!restriction && (he || ha))
+ {
+ os << "protected:" << endl;
+ names (c, names_parser_member_);
+ os << endl;
+ }
+
+ if (validation && (he || hae))
+ {
+ UnsignedLong depth (c.context ().get<UnsignedLong> ("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
+ << "const " << string_type << "*," << endl
+ << "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_;"
+ << "::xsd::cxx::parser::pod_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_;"
+ << "::xsd::cxx::parser::pod_stack v_state_attr_stack_;"
+ << endl;
+
+ os << "virtual void" << endl
+ << "_pre_a_validate ();"
+ << endl;
+
+ os << "virtual void" << endl
+ << "_post_a_validate ();"
+ << endl;
+ }
+
+ os << "};";
+ }
+
+ private:
+ //
+ //
+ ParserCallback parser_callback_;
+ Traversal::Names names_parser_callback_;
+
+ //
+ //
+ ParserMember parser_member_;
+ Traversal::Names names_parser_member_;
+
+ //
+ //
+ ParserModifier parser_modifier_;
+ Traversal::Names names_parser_modifier_;
+
+ //
+ //
+ 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_ = "::xsd::cxx::parser::";
+ impl_ns_ += (validation ? L"validating" : L"non_validating");
+
+ 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" >";
+ }
+
+ // anyType & anySimpleType.
+ //
+ virtual Void
+ traverse (SemanticGraph::AnyType& t)
+ {
+ gen_typedef (t, "void", "any_type_pskel", "any_type_pimpl");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnySimpleType& t)
+ {
+ gen_typedef (t, "void",
+ "any_simple_type_pskel", "any_simple_type_pimpl");
+ }
+
+ // Boolean.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Boolean& t)
+ {
+ gen_typedef (t, "bool", "boolean_pskel", "boolean_pimpl");
+ }
+
+ // Integral types.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Byte& t)
+ {
+ gen_typedef (t, "signed char", "byte_pskel", "byte_pimpl");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedByte& t)
+ {
+ gen_typedef (t, "unsigned char",
+ "unsigned_byte_pskel", "unsigned_byte_pimpl");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Short& t)
+ {
+ gen_typedef (t, "short", "short_pskel", "short_pimpl");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedShort& t)
+ {
+ gen_typedef (t, "unsigned short",
+ "unsigned_short_pskel", "unsigned_short_pimpl");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Int& t)
+ {
+ gen_typedef (t, "int", "int_pskel", "int_pimpl");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedInt& t)
+ {
+ gen_typedef (t, "unsigned int",
+ "unsigned_int_pskel", "unsigned_int_pimpl");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Long& t)
+ {
+ gen_typedef (t, "long long", "long_pskel", "long_pimpl");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedLong& t)
+ {
+ gen_typedef (t, "unsigned long long",
+ "unsigned_long_pskel", "unsigned_long_pimpl");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Integer& t)
+ {
+ gen_typedef (t, "long long", "integer_pskel", "integer_pimpl");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NegativeInteger& t)
+ {
+ gen_typedef (t, "long long",
+ "negative_integer_pskel", "negative_integer_pimpl");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonPositiveInteger& t)
+ {
+ gen_typedef (t, "long long",
+ "non_positive_integer_pskel",
+ "non_positive_integer_pimpl");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::PositiveInteger& t)
+ {
+ gen_typedef (t, "unsigned long long",
+ "positive_integer_pskel", "positive_integer_pimpl");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonNegativeInteger& t)
+ {
+ gen_typedef (t, "unsigned long long",
+ "non_negative_integer_pskel",
+ "non_negative_integer_pimpl");
+ }
+
+ // Floats.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Float& t)
+ {
+ gen_typedef (t, "float", "float_pskel", "float_pimpl");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Double& t)
+ {
+ gen_typedef (t, "double", "double_pskel", "double_pimpl");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Decimal& t)
+ {
+ gen_typedef (t, "double", "decimal_pskel", "decimal_pimpl");
+ }
+
+ // Strings.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::String& t)
+ {
+ gen_typedef (t, string_type_, "string_pskel", "string_pimpl");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NormalizedString& t)
+ {
+ gen_typedef (t, string_type_,
+ "normalized_string_pskel", "normalized_string_pimpl");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Token& t)
+ {
+ gen_typedef (t, string_type_, "token_pskel", "token_pimpl");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameToken& t)
+ {
+ nmtoken_ = gen_typedef (t, string_type_,
+ "nmtoken_pskel", "nmtoken_pimpl");
+ }
+
+ 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, xs_ns_ + L"::string_sequence",
+ "nmtokens_pskel", "nmtokens_pimpl");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Name& t)
+ {
+ gen_typedef (t, string_type_, "name_pskel", "name_pimpl");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NCName& t)
+ {
+ gen_typedef (t, string_type_, "ncname_pskel", "ncname_pimpl");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Language& t)
+ {
+ gen_typedef (t, string_type_, "language_pskel", "language_pimpl");
+ }
+
+ // Qualified name.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::QName& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::qname", "qname_pskel", "qname_pimpl");
+ }
+
+ // ID/IDREF.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Id& t)
+ {
+ gen_typedef (t, string_type_, "id_pskel", "id_pimpl");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRef& t)
+ {
+ idref_ = gen_typedef (t, string_type_, "idref_pskel", "idref_pimpl");
+ }
+
+ 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, xs_ns_ + L"::string_sequence",
+ "idrefs_pskel", "idrefs_pimpl");
+ }
+
+ // URI.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::AnyURI& t)
+ {
+ gen_typedef (t, string_type_, "uri_pskel", "uri_pimpl");
+ }
+
+ // Binary.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Base64Binary& t)
+ {
+ String buffer (L"::std::auto_ptr< " + xs_ns_ + L"::buffer >");
+ gen_typedef (t, buffer,
+ "base64_binary_pskel", "base64_binary_pimpl");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::HexBinary& t)
+ {
+ String buffer (L"::std::auto_ptr< " + xs_ns_ + L"::buffer >");
+ gen_typedef (t, buffer, "hex_binary_pskel", "hex_binary_pimpl");
+ }
+
+
+ // Date/time.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Date& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::date", "date_pskel", "date_pimpl");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::DateTime& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::date_time",
+ "date_time_pskel", "date_time_pimpl");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Duration& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::duration",
+ "duration_pskel", "duration_pimpl");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Day& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::gday", "gday_pskel", "gday_pimpl");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Month& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::gmonth",
+ "gmonth_pskel", "gmonth_pimpl");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::MonthDay& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::gmonth_day",
+ "gmonth_day_pskel", "gmonth_day_pimpl");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Year& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::gyear", "gyear_pskel", "gyear_pimpl");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::YearMonth& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::gyear_month",
+ "gyear_month_pskel", "gyear_month_pimpl");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Time& t)
+ {
+ gen_typedef (t, xs_ns_ + L"::time", "time_pskel", "time_pimpl");
+ }
+
+ // Entity.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entity&)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entities&)
+ {
+ }
+
+ private:
+ Boolean
+ gen_typedef (SemanticGraph::Type& t,
+ String const& type,
+ String const& pskel,
+ String const& pimpl)
+ {
+ if (ret_type (t) == type)
+ {
+ os << "typedef " << impl_ns_ << "::" << pskel << "< " <<
+ char_type << " > " << ename (t) << ";";
+
+ String const& pimpl_name (t.context ().get<String> ("impl"));
+
+ os << "typedef " << impl_ns_ << "::" << pimpl << "< " <<
+ char_type << " > " << pimpl_name << ";"
+ << endl;
+
+ return true;
+ }
+
+ return false;
+ }
+
+ String xs_ns_;
+ String impl_ns_;
+ String string_type_;
+
+ Boolean idref_;
+ Boolean nmtoken_;
+ };
+
+ struct FundNamespace : Namespace,
+ protected virtual Context
+ {
+ FundNamespace (Context& c)
+ : Context (c), Namespace (c)
+ {
+ }
+
+ void
+ traverse (Type& ns)
+ {
+ pre (ns);
+
+ String impl ("::xsd::cxx::parser::");
+ impl += (validation ? L"validating" : L"non_validating");
+
+ String const c (char_type);
+
+ os << "// Built-in XML Schema types mapping." << endl
+ << "//" << endl
+ << "typedef ::xsd::cxx::parser::string_sequence< " << c <<
+ " > string_sequence;"
+ << "typedef ::xsd::cxx::parser::qname< " << c << " > qname;"
+ << "typedef ::xsd::cxx::parser::buffer buffer;"
+ << "typedef ::xsd::cxx::parser::time_zone time_zone;"
+ << "typedef ::xsd::cxx::parser::gday gday;"
+ << "typedef ::xsd::cxx::parser::gmonth gmonth;"
+ << "typedef ::xsd::cxx::parser::gyear gyear;"
+ << "typedef ::xsd::cxx::parser::gmonth_day gmonth_day;"
+ << "typedef ::xsd::cxx::parser::gyear_month gyear_month;"
+ << "typedef ::xsd::cxx::parser::date date;"
+ << "typedef ::xsd::cxx::parser::time time;"
+ << "typedef ::xsd::cxx::parser::date_time date_time;"
+ << "typedef ::xsd::cxx::parser::duration duration;"
+ << endl;
+
+ os << "// Base parser skeletons." << endl
+ << "//" << endl
+ << "typedef ::xsd::cxx::parser::parser_base< " << c <<
+ " > parser_base;"
+ << "typedef " << impl << "::empty_content< " << c <<
+ " > empty_content;"
+ << "typedef " << impl << "::simple_content< " << c <<
+ " > simple_content;"
+ << "typedef " << impl << "::complex_content< " << c <<
+ " > complex_content;"
+ << "typedef " << impl << "::list_base< " << c << " > list_base;"
+ << endl;
+
+ if (polymorphic)
+ {
+ os << "// Parser map interface and default implementation." << endl
+ << "//" << endl
+ << "typedef ::xsd::cxx::parser::parser_map< " << c <<
+ " > parser_map;"
+ << "typedef ::xsd::cxx::parser::parser_map_impl< " << c <<
+ " > parser_map_impl;"
+ << endl;
+ }
+
+ os << "// Parser skeletons and implementations for the XML Schema" << endl
+ << "// built-in types." << endl
+ << "//" << endl;
+
+ names (ns);
+
+ os << "// Exceptions. See libxsd/xsd/cxx/parser/exceptions.hxx " <<
+ "for details." << endl
+ << "//" << endl
+ << "typedef ::xsd::cxx::parser::exception< " <<
+ char_type << " > exception;"
+ << endl
+ << "// Parsing diagnostics." << endl
+ << "//" << endl
+ << "typedef ::xsd::cxx::parser::severity severity;"
+ << "typedef ::xsd::cxx::parser::error< " << c << " > error;"
+ << "typedef ::xsd::cxx::parser::diagnostics< " << c <<
+ " > diagnostics;"
+ << "typedef ::xsd::cxx::parser::parsing< " << c << " > parsing;"
+ << endl;
+
+ os << "// Error handler. See " <<
+ "libxsd/xsd/cxx/xml/error-handler.hxx for details." << endl
+ << "//" << endl
+ << "typedef ::xsd::cxx::xml::error_handler< " << c <<
+ " > error_handler;"
+ << endl;
+
+ os << "// Read-only string." << endl
+ << "//" << endl
+ << "typedef ::xsd::cxx::ro_string< " << c << " > ro_string;"
+ << endl;
+
+ if (xml_parser == L"xerces")
+ {
+ os << "// Parsing flags. See " <<
+ "libxsd/xsd/cxx/parser/xerces/elements.hxx" << endl
+ << "// for details." << endl
+ << "//" << endl
+ << "typedef ::xsd::cxx::parser::xerces::flags flags;"
+ << endl;
+
+ os << "// Parsing properties. See " <<
+ "libxsd/xsd/cxx/parser/xerces/elements.hxx" << endl
+ << "// for details." << endl
+ << "//" << endl
+ << "typedef ::xsd::cxx::parser::xerces::properties< " << c <<
+ " > properties;"
+ << endl;
+
+ os << "// Document type. See " <<
+ "libxsd/xsd/cxx/parser/xerces/elements.hxx" << endl
+ << "// for details." << endl
+ << "//" << endl
+ << "typedef ::xsd::cxx::parser::xerces::document< " << c <<
+ " > document;"
+ << endl;
+
+ }
+ else if (xml_parser == L"expat")
+ {
+ os << "// Document type. See " <<
+ "libxsd/xsd/cxx/parser/expat/elements.hxx" << endl
+ << "// for details." << endl
+ << "//" << endl
+ << "typedef ::xsd::cxx::parser::expat::document< " << c <<
+ " > document;"
+ << endl;
+ }
+
+ post (ns);
+ }
+ };
+ }
+
+ Void
+ generate_parser_header (Context& ctx, Boolean generate_xml_schema)
+ {
+ String c (ctx.char_type);
+
+ //
+ //
+ if (c == L"char")
+ {
+ ctx.os << "#ifndef XSD_USE_CHAR" << endl
+ << "#define XSD_USE_CHAR" << endl
+ << "#endif" << endl
+ << endl;
+
+ ctx.os << "#ifndef XSD_CXX_PARSER_USE_CHAR" << endl
+ << "#define XSD_CXX_PARSER_USE_CHAR" << endl
+ << "#endif" << endl
+ << endl;
+ }
+ else if (c == L"wchar_t")
+ {
+ ctx.os << "#ifndef XSD_USE_WCHAR" << endl
+ << "#define XSD_USE_WCHAR" << endl
+ << "#endif" << endl
+ << endl;
+
+ ctx.os << "#ifndef XSD_CXX_PARSER_USE_WCHAR" << endl
+ << "#define XSD_CXX_PARSER_USE_WCHAR" << endl
+ << "#endif" << endl
+ << endl;
+ }
+
+ //
+ //
+ 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 ("includes"))
+ {
+ typedef Cult::Containers::Set<String> Includes;
+
+ Includes const& is (
+ ctx.schema_root.context ().get<Includes> ("includes"));
+
+ for (Includes::ConstReverseIterator i (is.rbegin ());
+ i != is.rend (); ++i)
+ {
+ ctx.os << "#include " << *i << endl;
+ }
+
+ ctx.os << endl;
+ }
+ }
+ else
+ {
+ ctx.os << "#include <xsd/cxx/xml/error-handler.hxx>" << endl
+ << "#include <xsd/cxx/parser/exceptions.hxx>" << endl
+ << "#include <xsd/cxx/parser/elements.hxx>" << endl
+ << "#include <xsd/cxx/parser/xml-schema.hxx>" << endl;
+
+ if (ctx.polymorphic)
+ ctx.os << "#include <xsd/cxx/parser/map.hxx>" << endl;
+
+ if (ctx.validation)
+ ctx.os << "#include <xsd/cxx/parser/validating/parser.hxx>" << endl
+ << "#include <xsd/cxx/parser/validating/exceptions.hxx>" << endl
+ << "#include <xsd/cxx/parser/validating/xml-schema-pskel.hxx>" << endl
+ << "#include <xsd/cxx/parser/validating/xml-schema-pimpl.hxx>" << endl;
+ else
+ ctx.os << "#include <xsd/cxx/parser/non-validating/parser.hxx>" << endl
+ << "#include <xsd/cxx/parser/non-validating/xml-schema-pskel.hxx>" << endl
+ << "#include <xsd/cxx/parser/non-validating/xml-schema-pimpl.hxx>" << endl;
+
+ ctx.os << "#include <xsd/cxx/parser/" << ctx.xml_parser <<
+ "/elements.hxx>" << endl
+ << endl;
+
+ // Generate includes that came from the type map.
+ //
+ if (ctx.schema_root.context ().count ("includes"))
+ {
+ typedef Cult::Containers::Set<String> Includes;
+
+ Includes const& is (
+ ctx.schema_root.context ().get<Includes> ("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/xsd/cxx/parser/parser-header.hxx b/xsd/cxx/parser/parser-header.hxx
new file mode 100644
index 0000000..348acdf
--- /dev/null
+++ b/xsd/cxx/parser/parser-header.hxx
@@ -0,0 +1,22 @@
+// file : xsd/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/xsd/cxx/parser/parser-inline.cxx b/xsd/cxx/parser/parser-inline.cxx
new file mode 100644
index 0000000..f2d3bd8
--- /dev/null
+++ b/xsd/cxx/parser/parser-inline.cxx
@@ -0,0 +1,407 @@
+// file : xsd/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 List: Traversal::List, protected virtual 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"));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ // item_parser
+ //
+ os << inl
+ << "void " << name << "::" << endl
+ << unclash (name, "item_parser") << " (" <<
+ fq_name (t) << "& " << item << ")"
+ << "{"
+ << "this->_xsd_" << item << "_ = &" << item << ";"
+ << "}";
+
+ // parsers
+ //
+ os << inl
+ << "void " << name << "::" << endl
+ << "parsers (" << fq_name (t) << "& " << item << ")"
+ << "{"
+ << "this->_xsd_" << item << "_ = &" << item << ";"
+ << "}";
+
+ // c-tor
+ //
+ os << inl
+ << name << "::" << endl
+ << name << " ()" << endl
+ << ": _xsd_" << item << "_ (0)"
+ << "{"
+ << "}";
+ }
+ };
+
+
+ //
+ //
+ struct ParserModifier: Traversal::Member,
+ protected virtual Context
+ {
+ ParserModifier (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& m)
+ {
+ if (skip (m))
+ return;
+
+ String const& scope (ename (m.scope ()));
+ String const& parser (eparser (m));
+
+ Boolean poly (polymorphic &&
+ m.is_a<SemanticGraph::Element> () &&
+ !anonymous (m.type ()));
+
+ os << inl
+ << "void " << scope << "::" << endl
+ << parser << " (" << fq_name (m.type ()) << "& p)"
+ << "{"
+ << "this->" << emember (m) << " = &p;"
+ << "}";
+
+ if (poly)
+ {
+ os << inl
+ << "void " << scope << "::" << endl
+ << parser << " (const " << parser_map << "& m)"
+ << "{"
+ << "this->" << emember_map (m) << " = &m;"
+ << "}";
+ }
+ }
+ };
+
+
+ //
+ //
+ struct ParserMemberSet: Traversal::Member,
+ protected virtual Context
+ {
+ ParserMemberSet (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& m)
+ {
+ if (skip (m)) return;
+
+ String const& name (ename (m));
+
+ os << "this->" << emember (m) << " = &" << name << ";";
+ }
+ };
+
+
+ //
+ //
+ struct ParserMemberInit: Traversal::Member,
+ protected virtual Context
+ {
+ ParserMemberInit (Context& c)
+ : Context (c), first_ (true)
+ {
+ }
+
+ virtual Void
+ traverse (Type& m)
+ {
+ if (skip (m)) return;
+
+ if (first_)
+ first_ = false;
+ else
+ os << "," << endl << " ";
+
+ os << emember (m) << " (0)";
+
+ if (polymorphic &&
+ m.is_a<SemanticGraph::Element> () &&
+ !anonymous (m.type ()))
+ {
+ os << "," << endl
+ << " " << emember_map (m) << " (0)";
+ }
+ }
+
+ Boolean
+ comma () const
+ {
+ return !first_;
+ }
+
+ private:
+ Boolean first_;
+ };
+
+ struct ParserBaseSet: Traversal::Complex,
+ Traversal::List,
+ protected virtual Context
+ {
+ ParserBaseSet (Context& c)
+ : Context (c), member_ (c)
+ {
+ inherits_ >> *this;
+ names_ >> member_;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ inherits (c, inherits_);
+
+ if (!restriction_p (c))
+ names (c, names_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::List& l)
+ {
+ String const& name (ename (l));
+ String item (unclash (name, "item"));
+
+ os << "this->_xsd_" << item << "_ = &" << name << "_item;";
+ }
+
+ private:
+ Traversal::Inherits inherits_;
+
+ ParserMemberSet member_;
+ Traversal::Names names_;
+ };
+
+ struct Particle: Traversal::All,
+ protected virtual Context
+ {
+ Particle (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::All& a)
+ {
+ if (!a.context().count ("comp-number"))
+ return;
+
+ UnsignedLong state_count (
+ a.context().get<UnsignedLong> ("state-count"));
+
+ os << "," << endl
+ << " v_all_count_ (" << state_count << "UL, v_all_first_)";
+ }
+ };
+
+ //
+ //
+ struct Complex: Traversal::Complex,
+ protected virtual Context
+ {
+ Complex (Context& c)
+ : Context (c),
+ parser_modifier_ (c),
+ parser_base_set_ (c),
+ parser_member_set_ (c),
+ particle_ (c)
+ {
+ names_parser_modifier_ >> parser_modifier_;
+ inherits_parser_base_set_ >> parser_base_set_;
+ names_parser_member_set_ >> parser_member_set_;
+ }
+
+ virtual Void
+ traverse (Type& 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);
+ }
+
+ Boolean restriction (restriction_p (c));
+
+ if (!((!restriction && (he || ha)) ||
+ (validation && (he || hae || hra))))
+ return;
+
+ String const& name (ename (c));
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ if (!restriction && (he || ha))
+ {
+ // <name>_parser ()
+ //
+ names (c, names_parser_modifier_);
+
+
+ // parsers ()
+ //
+
+ os << inl
+ << "void " << name << "::" << endl
+ << "parsers (";
+
+ {
+ ParserParamDecl decl (*this, true);
+ decl.traverse (c);
+ }
+
+ os << ")"
+ << "{";
+
+ inherits (c, inherits_parser_base_set_);
+ names (c, names_parser_member_set_);
+
+ os << "}";
+ }
+
+ // Default c-tor.
+ //
+ os << inl
+ << name << "::" << endl
+ << name << " ()" << endl
+ << ": ";
+
+ Boolean comma (false);
+
+ if (!restriction && (he || ha))
+ {
+ ParserMemberInit member_init (*this);
+ Traversal::Names names_member_init (member_init);
+
+ names (c, names_member_init);
+
+ comma = member_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:
+ //
+ //
+ ParserModifier parser_modifier_;
+ Traversal::Names names_parser_modifier_;
+
+ //
+ //
+ ParserBaseSet parser_base_set_;
+ Traversal::Inherits inherits_parser_base_set_;
+
+ //
+ //
+ ParserMemberSet parser_member_set_;
+ Traversal::Names names_parser_member_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;
+
+ List list (ctx);
+ Complex complex (ctx);
+
+ names >> list;
+ names >> complex;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+}
diff --git a/xsd/cxx/parser/parser-inline.hxx b/xsd/cxx/parser/parser-inline.hxx
new file mode 100644
index 0000000..2016828
--- /dev/null
+++ b/xsd/cxx/parser/parser-inline.hxx
@@ -0,0 +1,22 @@
+// file : xsd/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/xsd/cxx/parser/parser-source.cxx b/xsd/cxx/parser/parser-source.cxx
new file mode 100644
index 0000000..be6c8df
--- /dev/null
+++ b/xsd/cxx/parser/parser-source.cxx
@@ -0,0 +1,924 @@
+// file : xsd/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,
+ protected virtual 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 ());
+
+ Boolean same (ret == ret_type (base));
+
+ if (same || ret == L"void" || polymorphic)
+ {
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+ }
+
+ if (same || ret == L"void")
+ {
+ os << ret << " " << name << "::" << endl
+ << post_name (e) << " ()"
+ << "{";
+
+ if (same)
+ {
+ if (ret == L"void")
+ os << post_name (base) << " ();";
+ else
+ os << "return " << post_name (base) << " ();";
+ }
+
+ os << "}";
+ }
+
+ if (polymorphic)
+ {
+ String id (e.name ());
+
+ if (String ns = xml_ns_name (e))
+ {
+ id += L' ';
+ id += ns;
+ }
+
+ os << "const " << char_type << "* " << name << "::" << endl
+ << "_static_type ()"
+ << "{"
+ << "return " << L << strlit (id) << ";"
+ << "}";
+
+ os << "const " << char_type << "* " << 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 ::xsd::cxx::parser::validating::inheritance_map_entry< " <<
+ char_type << " >" << endl
+ << "_xsd_" << name << "_inheritance_map_entry_ (" << endl
+ << name << "::_static_type ()," << endl
+ << fq_name (base) << "::_static_type ());"
+ << endl;
+ }
+ }
+ }
+ }
+ };
+
+ //
+ //
+ struct List: Traversal::List, protected virtual 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"));
+
+ 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 << ")";
+
+ os << "{"
+ << "}";
+
+ // post
+ //
+ if (ret_type (l) == L"void")
+ os << "void " << name << "::" << endl
+ << post_name (l) << " ()"
+ << "{"
+ << "}";
+
+ // parse_item
+ //
+ String inst (L"_xsd_" + item + L"_");
+ String const& post (post_name (t));
+
+ os << "void " << name << "::" << endl
+ << "_xsd_parse_item (const " << string_type << "& v)"
+ << "{"
+ << "if (this->" << inst << ")"
+ << "{"
+ << "this->" << inst << "->pre ();"
+ << "this->" << inst << "->_pre_impl ();"
+ << "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 (polymorphic)
+ {
+ String id (l.name ());
+
+ if (String ns = xml_ns_name (l))
+ {
+ id += L' ';
+ id += ns;
+ }
+
+ os << "const " << char_type << "* " << name << "::" << endl
+ << "_static_type ()"
+ << "{"
+ << "return " << L << strlit (id) << ";"
+ << "}";
+
+ os << "const " << char_type << "* " << name << "::" << endl
+ << "_dynamic_type () const"
+ << "{"
+ << "return _static_type ();"
+ << "}";
+ }
+ }
+ };
+
+ //
+ //
+ struct Union: Traversal::Union, protected virtual 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" || polymorphic)
+ {
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+ }
+
+ if (ret == L"void")
+ {
+ os << "void " << name << "::" << endl
+ << post_name (u) << " ()"
+ << "{"
+ << "}";
+ }
+
+ if (polymorphic)
+ {
+ String id (u.name ());
+
+ if (String ns = xml_ns_name (u))
+ {
+ id += L' ';
+ id += ns;
+ }
+
+ os << "const " << char_type << "* " << name << "::" << endl
+ << "_static_type ()"
+ << "{"
+ << "return " << L << strlit (id) << ";"
+ << "}";
+
+ os << "const " << char_type << "* " << name << "::" << endl
+ << "_dynamic_type () const"
+ << "{"
+ << "return _static_type ();"
+ << "}";
+ }
+ }
+ };
+
+ //
+ //
+ struct StartElement : Traversal::Element,
+ protected virtual Context
+ {
+ StartElement (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (skip (e))
+ return;
+
+ Boolean poly (polymorphic && !anonymous (e.type ()));
+
+ String const& inst (poly ? emember_cache (e) : emember (e));
+
+ os << "if (";
+
+ if (poly && e.global ())
+ os << "(";
+
+ if (e.qualified () && e.namespace_ ().name ())
+ {
+ os << "n == " << L << strlit (e.name ()) << " && " <<
+ "ns == " << L << strlit (e.namespace_ ().name ());
+ }
+ else
+ {
+ os << "n == " << L << strlit (e.name ()) << " && ns.empty ()";
+ }
+
+ // Only a globally-defined element can be a subst-group root.
+ //
+ if (poly && e.global ())
+ {
+ os << ") ||" << endl
+ << "::xsd::cxx::parser::substitution_map_instance< " <<
+ char_type << " > ().check (" << endl
+ << "ns, n, " << L << strlit (e.namespace_ ().name ()) <<
+ ", " << L << strlit (e.name ()) << ", t)";
+ }
+
+ os << ")"
+ << "{";
+
+ if (poly)
+ {
+ SemanticGraph::Type& t (e.type ());
+
+ // For pre-computing length.
+ //
+ String type_id (t.name ());
+
+ if (String type_ns = xml_ns_name (t))
+ {
+ type_id += L' ';
+ type_id += type_ns;
+ }
+
+ String fq_type (fq_name (t));
+ 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"
+ << "{"
+ << string_type << " ts (" << fq_type <<
+ "::_static_type (), " << type_id.size () << "UL);"
+ << endl
+ << "if (t == 0)" << endl
+ << "t = &ts;"
+ << endl
+ << "if (this->" << member << " != 0 && *t == ts)" << endl
+ << "this->" << inst << " = this->" << member << ";"
+ << "else if (this->" << member_map << " != 0)" << endl
+ << "this->" << inst << " = dynamic_cast< " << fq_type <<
+ "* > (" << endl
+ << "this->" << member_map << "->find (*t));"
+ << "else" << endl
+ << "this->" << inst << " = 0;"
+ << "}";
+ }
+
+ os << "this->" << complex_base << "::context_.top ().parser_ = " <<
+ "this->" << inst << ";"
+ << endl
+ << "if (this->" << inst << ")" << endl
+ << "this->" << inst << "->pre ();" // _start_element calls _pre
+ << endl
+ << "return true;"
+ << "}";
+ }
+ };
+
+
+ //
+ //
+ struct EndElement : Traversal::Element,
+ protected virtual Context
+ {
+ EndElement (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (skip (e))
+ return;
+
+ Boolean poly (polymorphic && !anonymous (e.type ()));
+
+ String const& name (ename (e));
+ String const& inst (poly ? emember_cache (e) : emember (e));
+
+ os << "if (";
+
+ if (poly && e.global ())
+ os << "(";
+
+ if (e.qualified () && e.namespace_ ().name ())
+ {
+ os << "n == " << L << strlit (e.name ()) << " && " <<
+ "ns == " << L << strlit (e.namespace_ ().name ());
+ }
+ else
+ {
+ os << "n == " << L << strlit (e.name ()) << " && ns.empty ()";
+ }
+
+ // Only a globally-defined element can be a subst-group root.
+ //
+ if (poly && e.global ())
+ {
+ os << ") ||" << endl
+ << "::xsd::cxx::parser::substitution_map_instance< " <<
+ char_type << " > ().check (" << endl
+ << "ns, n, " << L << strlit (e.namespace_ ().name ()) <<
+ ", " << L << strlit (e.name ()) << ")";
+ }
+
+ os << ")"
+ << "{";
+
+ // _end_element calls post
+ //
+
+ SemanticGraph::Type& type (e.type ());
+ String const& post (post_name (type));
+
+ os << "if (this->" << inst << ")";
+
+ if (ret_type (type) == L"void")
+ os << "{"
+ << "this->" << inst << "->" << post << " ();"
+ << "this->" << name << " ();"
+ << "}";
+ else
+ os << endl
+ << "this->" << name << " (this->" << inst << "->" <<
+ post << " ());"
+ << endl;
+
+ os << "return true;"
+ << "}";
+ }
+ };
+
+ //
+ //
+ struct Attribute : Traversal::Attribute,
+ protected virtual 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 ()) << " && " <<
+ "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 << ")"
+ << "{"
+ << "this->" << inst << "->pre ();"
+ << "this->" << inst << "->_pre_impl ();"
+ << "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 << " ());";
+
+ os << "}"
+ << "return true;"
+ << "}";
+ }
+ };
+
+ //
+ //
+ struct ParserCallback: Traversal::Member,
+ protected virtual Context
+ {
+ ParserCallback (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& m)
+ {
+ if (skip (m))
+ return;
+
+ String const& arg (arg_type (m.type ()));
+
+ os << "void " << ename (m.scope ()) << "::" << endl
+ << ename (m);
+
+ if (arg == L"void")
+ os << " ()";
+ else
+ os << " (" << arg << ")";
+
+ os << "{"
+ << "}";
+ }
+ };
+
+ //
+ //
+ struct Complex : Traversal::Complex,
+ protected virtual Context
+ {
+ Complex (Context& c)
+ : Context (c),
+ parser_callback_ (c),
+ start_element_ (c),
+ end_element_ (c),
+ attribute_ (c)
+ {
+ names_parser_callback_ >> parser_callback_;
+ names_start_element_ >> start_element_;
+ names_end_element_ >> end_element_;
+ names_attribute_ >> attribute_;
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ Boolean he (has<Traversal::Element> (c));
+ Boolean ha (has<Traversal::Attribute> (c));
+
+ String const& ret (ret_type (c));
+ Boolean same (c.inherits_p () &&
+ ret == ret_type (c.inherits ().base ()));
+
+ String const& name (ename (c));
+
+ if ((he || ha || same || ret == L"void") || polymorphic)
+ {
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+ }
+
+ if (polymorphic)
+ {
+ String id (c.name ());
+
+ if (String ns = xml_ns_name (c))
+ {
+ id += L' ';
+ id += ns;
+ }
+
+ os << "const " << char_type << "* " << name << "::" << endl
+ << "_static_type ()"
+ << "{"
+ << "return " << L << strlit (id) << ";"
+ << "}";
+
+ os << "const " << char_type << "* " << name << "::" << endl
+ << "_dynamic_type () const"
+ << "{"
+ << "return _static_type ();"
+ << "}";
+
+ if (c.inherits_p () && 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 ::xsd::cxx::parser::validating::inheritance_map_entry< " <<
+ char_type << " >" << endl
+ << "_xsd_" << name << "_inheritance_map_entry_ (" << endl
+ << name << "::_static_type ()," << endl
+ << fq_name (base) << "::_static_type ());"
+ << endl;
+ }
+ }
+ }
+
+ if (!(he || ha || same || ret == L"void"))
+ return;
+
+ // Parser callbacks.
+ //
+ if (!restriction_p (c))
+ names (c, names_parser_callback_);
+
+ if (same || ret == L"void")
+ {
+ os << ret << " " << name << "::" << endl
+ << post_name (c) << " ()"
+ << "{";
+
+ if (same)
+ {
+ SemanticGraph::Type& base (c.inherits ().base ());
+
+ if (ret == L"void")
+ os << post_name (base) << " ();";
+ else
+ os << "return " << post_name (base) << " ();";
+ }
+
+ os << "}";
+ }
+
+ // The rest is parsing/validation code which is generated in
+ // *-validation-source.cxx.
+ //
+ if (validation)
+ 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> ());
+
+ // _start_element_impl & _end_element_impl
+ //
+ if (he)
+ {
+ os << "bool " << name << "::" << endl
+ << "_start_element_impl (const " << string_type << "& ns," << endl
+ << "const " << string_type << "& n," << endl
+ << "const " << string_type << "* t)"
+ << "{"
+ << "XSD_UNUSED (t);"
+ << endl;
+
+ if (!restriction)
+ {
+ os << "if (this->";
+
+ if (c.inherits_p ())
+ os << fq_name (c.inherits ().base ());
+ else
+ os << complex_base;
+
+ os << "::_start_element_impl (ns, n, t))" << endl
+ << "return true;"
+ << endl;
+ }
+
+ names (c, names_start_element_);
+
+ os << "return false;"
+ << "}";
+
+
+ // _end_element_impl
+ //
+ os << "bool " << name << "::" << endl
+ << "_end_element_impl (const " << string_type << "& ns," << endl
+ << "const " << string_type << "& n)"
+ << "{";
+
+ if (!restriction)
+ {
+ os << "if (this->";
+
+ if (c.inherits_p () && !restriction)
+ os << fq_name (c.inherits ().base ());
+ else
+ os << complex_base;
+
+ os << "::_end_element_impl (ns, n))" << endl
+ << "return true;"
+ << endl;
+ }
+
+ names (c, names_end_element_);
+
+ 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)
+ {
+ os << "if (this->";
+
+ if (c.inherits_p ())
+ os << fq_name (c.inherits ().base ());
+ else
+ os << complex_base;
+
+ os << "::_attribute_impl (ns, n, v))" << endl
+ << "return true;"
+ << endl;
+ }
+
+ names (c, names_attribute_);
+
+ os << "return false;"
+ << "}";
+ }
+ }
+
+ private:
+ //
+ //
+ ParserCallback parser_callback_;
+ Traversal::Names names_parser_callback_;
+
+ //
+ //
+ StartElement start_element_;
+ Traversal::Names names_start_element_;
+
+ //
+ //
+ EndElement end_element_;
+ Traversal::Names names_end_element_;
+
+ //
+ //
+ Attribute attribute_;
+ Traversal::Names names_attribute_;
+ };
+
+
+ // Generate substitution group map entries.
+ //
+ struct GlobalElement: Traversal::Element,
+ protected virtual 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 ());
+
+ os << "// Substitution map entry for " << comment (e.name ()) << "." << endl
+ << "//" << endl
+ << "static" << endl
+ << "const ::xsd::cxx::parser::substitution_map_entry< " <<
+ char_type << " >" << endl
+ << "_xsd_" << name << "_substitution_map_entry_ (" << endl
+ << L << strlit (e.namespace_ ().name ()) << "," << endl
+ << L << strlit (e.name ()) << "," << endl
+ << L << strlit (r.namespace_ ().name ()) << "," << endl
+ << L << strlit (r.name ()) << "," << endl
+ << fq_name (type) << "::_static_type ());"
+ << endl;
+ }
+ }
+ };
+ }
+
+ Void
+ generate_parser_source (Context& ctx)
+ {
+ if (ctx.polymorphic)
+ {
+ ctx.os << "#include <xsd/cxx/parser/substitution-map.hxx>" << endl;
+
+ if (ctx.validation)
+ ctx.os << "#include <xsd/cxx/parser/validating/inheritance-map.hxx>" << endl
+ << endl;
+ else
+ ctx.os << endl;
+
+ Boolean import_maps (ctx.options.value<CLI::import_maps> ());
+ Boolean export_maps (ctx.options.value<CLI::export_maps> ());
+
+ if (import_maps || export_maps)
+ {
+ ctx.os << "#ifdef _MSC_VER" << endl
+ << endl
+ << "namespace xsd"
+ << "{"
+ << "namespace cxx"
+ << "{"
+ << "namespace parser"
+ << "{";
+
+ if (export_maps)
+ ctx.os << "template struct __declspec (dllexport) " <<
+ "substitution_map_init< " << ctx.char_type << " >;";
+
+ if (import_maps)
+ ctx.os << "template struct __declspec (dllimport) " <<
+ "substitution_map_init< " << ctx.char_type << " >;";
+
+ if (ctx.validation && export_maps)
+ ctx.os << "template struct __declspec (dllexport) " <<
+ "inheritance_map_init< " << ctx.char_type << " >;";
+
+ if (ctx.validation && import_maps)
+ ctx.os << "template struct __declspec (dllimport) " <<
+ "inheritance_map_init< " << ctx.char_type << " >;";
+
+ ctx.os << "}" // parser
+ << "}" // cxx
+ << "}" // xsd
+ << "#endif // _MSC_VER" << endl
+ << endl;
+ }
+
+ ctx.os << "static" << endl
+ << "const ::xsd::cxx::parser::substitution_map_init< " <<
+ ctx.char_type << " >" << endl
+ << "_xsd_substitution_map_init_;"
+ << endl;
+
+ if (ctx.validation)
+ {
+ ctx.os << "static" << endl
+ << "const ::xsd::cxx::parser::validating::inheritance_map_init< " <<
+ ctx.char_type << " >" << endl
+ << "_xsd_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.polymorphic)
+ names >> global_element;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+}
diff --git a/xsd/cxx/parser/parser-source.hxx b/xsd/cxx/parser/parser-source.hxx
new file mode 100644
index 0000000..2281c24
--- /dev/null
+++ b/xsd/cxx/parser/parser-source.hxx
@@ -0,0 +1,22 @@
+// file : xsd/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/xsd/cxx/parser/print-impl-common.hxx b/xsd/cxx/parser/print-impl-common.hxx
new file mode 100644
index 0000000..9e501ac
--- /dev/null
+++ b/xsd/cxx/parser/print-impl-common.hxx
@@ -0,0 +1,643 @@
+// file : xsd/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"))
+ {
+ os << cout_inst << " << " << L << 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"))
+ {
+ os << cout_inst << " << " << L << 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"))
+ {
+ os << cout_inst << " << " << L << 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"))
+ {
+ os << cout_inst << " << " << L << strlit (tag_ + L": ") << " << " <<
+ arg_ << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedShort& t)
+ {
+ if (default_type (t, "unsigned short"))
+ {
+ os << cout_inst << " << " << L << strlit (tag_ + L": ") << " << " <<
+ arg_ << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Int& t)
+ {
+ if (default_type (t, "int"))
+ {
+ os << cout_inst << " << " << L << strlit (tag_ + L": ") << " << " <<
+ arg_ << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedInt& t)
+ {
+ if (default_type (t, "unsigned int"))
+ {
+ os << cout_inst << " << " << L << strlit (tag_ + L": ") << " << " <<
+ arg_ << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Long& t)
+ {
+ if (default_type (t, "long long"))
+ {
+ os << cout_inst << " << " << L << strlit (tag_ + L": ") << " << " <<
+ arg_ << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedLong& t)
+ {
+ if (default_type (t, "unsigned long long"))
+ {
+ os << cout_inst << " << " << L << strlit (tag_ + L": ") << " << " <<
+ arg_ << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Integer& t)
+ {
+ if (default_type (t, "long long"))
+ {
+ os << cout_inst << " << " << L << strlit (tag_ + L": ") << " << " <<
+ arg_ << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NegativeInteger& t)
+ {
+ if (default_type (t, "long long"))
+ {
+ os << cout_inst << " << " << L << strlit (tag_ + L": ") << " << " <<
+ arg_ << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonPositiveInteger& t)
+ {
+ if (default_type (t, "long long"))
+ {
+ os << cout_inst << " << " << L << strlit (tag_ + L": ") << " << " <<
+ arg_ << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::PositiveInteger& t)
+ {
+ if (default_type (t, "unsigned long long"))
+ {
+ os << cout_inst << " << " << L << strlit (tag_ + L": ") << " << " <<
+ arg_ << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonNegativeInteger& t)
+ {
+ if (default_type (t, "unsigned long long"))
+ {
+ os << cout_inst << " << " << L << strlit (tag_ + L": ") << " << " <<
+ arg_ << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ // Floats.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Float& t)
+ {
+ if (default_type (t, "float"))
+ {
+ os << cout_inst << " << " << L << strlit (tag_ + L": ") << " << " <<
+ arg_ << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Double& t)
+ {
+ if (default_type (t, "double"))
+ {
+ os << cout_inst << " << " << L << strlit (tag_ + L": ") << " << " <<
+ arg_ << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Decimal& t)
+ {
+ if (default_type (t, "double"))
+ {
+ os << cout_inst << " << " << L << 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 (default_type (t, xs_ns_name () + L"::qname"))
+ {
+ os << cout_inst << " << " << L << strlit (tag_ + L": ") << ";"
+ << endl
+ << "if (" << arg_ << ".prefix ().empty ())" << endl
+ << cout_inst << " << " << arg_ << ".name ();"
+ << "else" << endl
+ << cout_inst << " << " << arg_ << ".prefix () << " << L <<
+ "':' << " << arg_ << ".name ();"
+ << endl
+ << cout_inst << " << 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"))
+ {
+ os << cout_inst << " << " << L << 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"))
+ {
+ os << cout_inst << " << " << L << 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"))
+ {
+ os << cout_inst << " << " << L << strlit (tag_ + L": ") << ";"
+ << endl
+ << "if (" << arg_ << ".negative ())" << endl
+ << cout_inst << " << '-';"
+ << endl
+ << cout_inst << " << 'P'" << endl
+ << " << " << arg_ << ".years () << 'Y'" << endl
+ << " << " << arg_ << ".months () << 'M'" << endl
+ << " << " << arg_ << ".days () << " << L << "\"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"))
+ {
+ os << cout_inst << " << " << L << 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"))
+ {
+ os << cout_inst << " << " << L << 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"))
+ {
+ os << cout_inst << " << " << L << 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"))
+ {
+ os << cout_inst << " << " << L << 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"))
+ {
+ os << cout_inst << " << " << L << 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"))
+ {
+ os << cout_inst << " << " << L << 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 ((char_type == L"char" && default_type (t, "::std::string")) ||
+ (char_type == L"wchar_t" && default_type (t, "::std::wstring")))
+ {
+ os << cout_inst << " << " << L << 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))
+ {
+ os << cout_inst << " << " << L << strlit (tag_ + L": ") << ";"
+ << endl;
+
+ os << "for (" << type << "::const_iterator i (" << arg_ <<
+ ".begin ()), e (" << arg_ << ".end ());" << endl
+ << "i != e;)"
+ << "{"
+ << cout_inst << " << *i++;"
+ << "if (i != e)" << endl
+ << cout_inst << " << ' ';"
+ << "}"
+ << cout_inst << " << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ void
+ gen_buffer (SemanticGraph::Type& t)
+ {
+ String type (L"::std::auto_ptr< " + xs_ns_name () + L"::buffer >");
+
+ if (default_type (t, type))
+ {
+ os << cout_inst << " << " << L << strlit (tag_ + L": ") << " << "
+ << arg_ << "->size () << " << L << "\" bytes\" << std::endl;";
+ }
+ else
+ gen_user_type ();
+ }
+
+ void
+ gen_time_zone ()
+ {
+ os << endl
+ << "if (" << arg_ << ".zone_present ())"
+ << "{"
+ << "if (" << arg_ << ".zone_hours () < 0)" << endl
+ << cout_inst << " << " << arg_ << ".zone_hours () << ':' << -" <<
+ arg_ << ".zone_minutes ();"
+ << "else" << endl
+ << cout_inst << " << '+' << " << arg_ << ".zone_hours () << " <<
+ "':' << " << arg_ << ".zone_minutes ();";
+
+ os << "}"
+ << cout_inst << " << std::endl;";
+ }
+
+ private:
+ String tag_;
+ String arg_;
+ };
+ }
+}
+
+#endif // CXX_PARSER_PRINT_IMPL_COMMON_HXX
diff --git a/xsd/cxx/parser/state-processor.cxx b/xsd/cxx/parser/state-processor.cxx
new file mode 100644
index 0000000..141ab05
--- /dev/null
+++ b/xsd/cxx/parser/state-processor.cxx
@@ -0,0 +1,318 @@
+// file : xsd/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 ("prefix", true);
+ p.context ().set ("state", state++);
+ }
+
+ if (!prefixes_.empty ())
+ {
+ a.context ().set ("comp-number", choice_++);
+ a.context ().set ("prefixes", prefixes_);
+ a.context ().set ("state-count", UnsignedLong (prefixes_.size ()));
+
+ // effective-min = min * actual-min
+ //
+ if (min == 1)
+ min = a.min ();
+
+ a.context ().set ("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> ("effective-min") == 0)
+ min = 0;
+ }
+
+ p.context ().set ("prefix", true);
+ p.context ().set ("state", state++);
+ }
+
+ if (!prefixes_.empty ())
+ {
+ c.context ().set ("comp-number", choice_++);
+ c.context ().set ("prefixes", prefixes_);
+
+ // effective-min = min * actual-min
+ //
+ if (min == 1)
+ min = c.min ();
+
+ c.context ().set ("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> ("effective-min") != 0)
+ min = 1;
+ }
+ }
+
+ p.context ().set ("state", state++);
+
+ if (prefix)
+ p.context ().set ("prefix", true);
+
+ if (prefix && min != 0)
+ prefix = false;
+ }
+
+ if (!prefixes_.empty ())
+ {
+ s.context ().set ("comp-number", sequence_++);
+ s.context ().set ("prefixes", prefixes_);
+
+ // effective-min = min * actual-min
+ //
+ if (min == 1)
+ min = s.min ();
+
+ s.context ().set ("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 ("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/xsd/cxx/parser/state-processor.hxx b/xsd/cxx/parser/state-processor.hxx
new file mode 100644
index 0000000..681959c
--- /dev/null
+++ b/xsd/cxx/parser/state-processor.hxx
@@ -0,0 +1,28 @@
+// file : xsd/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/xsd/cxx/parser/type-processor.cxx b/xsd/cxx/parser/type-processor.cxx
new file mode 100644
index 0000000..3d24208
--- /dev/null
+++ b/xsd/cxx/parser/type-processor.cxx
@@ -0,0 +1,352 @@
+// file : xsd/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
+ {
+ TypeProcessor::
+ TypeProcessor ()
+ {
+ // Dummy ctor, helps with long symbols on HP-UX.
+ }
+
+ 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 ("ret-type"))
+ {
+ SemanticGraph::Schema* s (
+ tc.get<SemanticGraph::Schema*> ("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.
+ //
+ 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 ("ret-type", ret_type);
+ tc.set ("arg-type", arg_type);
+ }
+
+ tc.set ("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;
+
+ if (!schema_.context ().count ("includes"))
+ schema_.context ().set ("includes", Includes ());
+
+ Includes& is (
+ schema_.context ().get<Includes> ("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 GlobalType: Traversal::Type,
+ Traversal::List,
+ Traversal::Complex,
+ Traversal::Enumeration
+ {
+ GlobalType (SemanticGraph::Schema& schema,
+ TypeMap::Namespaces& type_map,
+ Boolean add_includes)
+ : type_ (schema, type_map, add_includes)
+ {
+ inherits_ >> type_;
+ names_ >> instance_ >> belongs_ >> type_;
+ argumented_ >> 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::names (c, names_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Enumeration& e)
+ {
+ type_.traverse (e);
+ Complex::inherits (e, inherits_);
+ }
+
+ private:
+ Parser::Type type_;
+ Traversal::Names names_;
+ Traversal::Instance instance_;
+ Traversal::Inherits inherits_;
+ Traversal::Belongs belongs_;
+ Traversal::Argumented argumented_;
+ };
+
+ Void
+ process_impl (CLI::Options const& options,
+ XSDFrontend::SemanticGraph::Schema& tu,
+ Boolean gen_driver,
+ TypeMap::Namespaces& type_map)
+ {
+ 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);
+
+ 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> ());
+
+ //
+ //
+ 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;
+ GlobalType global_type (tu, type_map, true);
+
+ schema >> schema_names >> ns >> ns_names >> 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);
+
+ xs_schema >> xs_schema_names >> xs_ns >> xs_ns_names >>
+ xs_global_type;
+
+ schema.dispatch (tu);
+
+ // If we are generating the test driver, make sure the root
+ // element type is processed.
+ //
+ if (gen_driver && options.value<CLI::generate_test_driver> ())
+ {
+ // 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 root_element (options, root);
+
+ schema >> schema_names >> ns >> ns_names >> root_element;
+
+ schema.dispatch (tu);
+ }
+
+ global_type.dispatch (root->type ());
+ }
+ }
+ }
+ }
+
+ Void TypeProcessor::
+ process (CLI::Options const& options,
+ XSDFrontend::SemanticGraph::Schema& s,
+ Boolean gen_driver,
+ TypeMap::Namespaces& tm)
+ {
+ process_impl (options, s, gen_driver, tm);
+ }
+ }
+}
diff --git a/xsd/cxx/parser/type-processor.hxx b/xsd/cxx/parser/type-processor.hxx
new file mode 100644
index 0000000..045b331
--- /dev/null
+++ b/xsd/cxx/parser/type-processor.hxx
@@ -0,0 +1,37 @@
+// file : xsd/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:
+ TypeProcessor (); // Dummy ctor, helps with long symbols on HP-UX.
+
+ Void
+ process (CLI::Options const& options,
+ XSDFrontend::SemanticGraph::Schema&,
+ Boolean gen_driver,
+ TypeMap::Namespaces&);
+ };
+ }
+}
+
+#endif // CXX_PARSER_TYPE_PROCESSOR_HXX
diff --git a/xsd/cxx/parser/validator.cxx b/xsd/cxx/parser/validator.cxx
new file mode 100644
index 0000000..8d6b968
--- /dev/null
+++ b/xsd/cxx/parser/validator.cxx
@@ -0,0 +1,714 @@
+// file : xsd/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, protected virtual ValidationContext
+ {
+ Any (ValidationContext& c)
+ : ValidationContext (c)
+ {
+ }
+
+ struct Element: Traversal::Element,
+ protected virtual ValidationContext
+ {
+ Element (ValidationContext& c, SemanticGraph::Any& any)
+ : ValidationContext (c),
+ any_ (any),
+ ns_ (any.definition_namespace ().name ())
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (skip (e)) return;
+
+ 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::Names names;
+ Element element (*this, a);
+
+ complex >> names >> element;
+
+ complex.dispatch (type);
+ }
+ };
+
+
+ //
+ //
+ struct Traverser : Traversal::Schema,
+ Traversal::Complex,
+ Traversal::Type,
+ Traversal::Element,
+ protected virtual 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 AnonymousType : Traversal::Schema,
+ Traversal::Complex,
+ Traversal::Element,
+ Traversal::Attribute,
+ protected virtual ValidationContext
+ {
+ AnonymousType (ValidationContext& c)
+ : ValidationContext (c),
+ anonymous_error_issued_ (false)
+ {
+ *this >> sources_ >> *this;
+ *this >> schema_names_ >> ns_ >> names_ >> *this;
+ *this >> names_;
+ }
+
+ 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 (!anonymous_error_issued_)
+ {
+ valid = false;
+ anonymous_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;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (skip (e)) return;
+
+ 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);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& 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);
+ }
+
+ private:
+ Boolean anonymous_error_issued_;
+
+ Containers::Set<String> types_;
+
+ Traversal::Sources sources_;
+
+ Traversal::Names schema_names_;
+ Traversal::Namespace ns_;
+
+ Traversal::Names names_;
+ };
+
+ 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_;
+ };
+
+ }
+
+ Validator::
+ Validator ()
+ {
+ // Dummy ctor, helps with long symbols on HP-UX.
+ }
+
+ 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::char_type> () != "char" &&
+ options.value<CLI::char_type> () != "wchar_t" &&
+ !ctx.is_disabled ("P003"))
+ {
+ wcerr << "warning P003: unknown base character type '" <<
+ options.value<CLI::char_type> ().c_str () << "'" << endl;
+ }
+
+ //
+ //
+ if (options.value<CLI::xml_parser> () != "xerces" &&
+ options.value<CLI::xml_parser> () != "expat" &&
+ !ctx.is_disabled ("P004"))
+ {
+ wcerr << "warning P004: unknown underlying XML parser '" <<
+ options.value<CLI::xml_parser> ().c_str () << "'" << endl;
+ }
+
+ //
+ //
+ if (options.value<CLI::xml_parser> () == "expat" &&
+ options.value<CLI::char_type> () == "wchar_t")
+ {
+ wcerr << "error: using expat with wchar_t is not yet supported"
+ << endl;
+
+ return false;
+ }
+
+ //
+ //
+ if (options.value<CLI::generate_validation> () &&
+ options.value<CLI::suppress_validation> ())
+ {
+ wcerr << "error: mutually exclusive options specified: "
+ << "--generate-validation and --suppress-validation"
+ << endl;
+
+ return false;
+ }
+
+ //
+ //
+ 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;
+ }
+ }
+
+ //
+ //
+ Boolean import_maps (options.value<CLI::import_maps> ());
+ Boolean export_maps (options.value<CLI::export_maps> ());
+
+ if (import_maps && export_maps)
+ {
+ wcerr << "error: --import-maps and --export-maps are "
+ << "mutually exclusive" << endl;
+
+ return false;
+ }
+
+ if (import_maps && !ctx.polymorphic)
+ {
+ wcerr << "error: --import-maps can only be specified together with "
+ << "--generate-polymorphic" << endl;
+
+ return false;
+ }
+
+ if (export_maps && !ctx.polymorphic)
+ {
+ wcerr << "error: --export-maps can only be specified together with "
+ << "--generate-polymorphic" << 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/xsd/cxx/parser/validator.hxx b/xsd/cxx/parser/validator.hxx
new file mode 100644
index 0000000..3f10073
--- /dev/null
+++ b/xsd/cxx/parser/validator.hxx
@@ -0,0 +1,35 @@
+// file : xsd/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 <cxx/parser/elements.hxx>
+#include <cxx/parser/cli.hxx>
+
+#include <xsd.hxx>
+
+namespace CXX
+{
+ namespace Parser
+ {
+ using namespace Cult::Types;
+
+ class Validator
+ {
+ public:
+ Validator (); // Dummy ctor, helps with long symbols on HP-UX.
+
+ Boolean
+ validate (CLI::Options const& options,
+ SemanticGraph::Schema&,
+ SemanticGraph::Path const& tu,
+ Boolean gen_driver,
+ const WarningSet& disabled_warnings);
+ };
+ }
+}
+
+#endif // CXX_PARSER_VALIDATOR_HXX
diff --git a/xsd/cxx/tree/cli.hxx b/xsd/cxx/tree/cli.hxx
new file mode 100644
index 0000000..9ccf405
--- /dev/null
+++ b/xsd/cxx/tree/cli.hxx
@@ -0,0 +1,220 @@
+// file : xsd/cxx/tree/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_TREE_CLI_HXX
+#define CXX_TREE_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 Tree
+ {
+ namespace CLI
+ {
+ using namespace Cult::Types;
+
+ typedef Char const Key[];
+
+ extern Key char_type;
+ extern Key output_dir;
+ extern Key generate_polymorphic;
+ extern Key generate_serialization;
+ extern Key generate_inline;
+ extern Key generate_ostream;
+ extern Key generate_doxygen;
+ extern Key generate_comparison;
+ extern Key generate_default_ctor;
+ extern Key generate_from_base_ctor;
+ extern Key generate_wildcard;
+ extern Key generate_insertion;
+ extern Key generate_extraction;
+ extern Key generate_forward;
+ extern Key generate_xml_schema;
+ extern Key extern_xml_schema;
+ extern Key suppress_parsing;
+ extern Key generate_element_type;
+ extern Key generate_element_map;
+ extern Key generate_intellisense;
+ extern Key omit_default_attributes;
+ extern Key namespace_map;
+ extern Key namespace_regex;
+ extern Key namespace_regex_trace;
+ extern Key reserved_name;
+ extern Key type_naming;
+ extern Key function_naming;
+ extern Key type_regex;
+ extern Key accessor_regex;
+ extern Key one_accessor_regex;
+ extern Key opt_accessor_regex;
+ extern Key seq_accessor_regex;
+ extern Key modifier_regex;
+ extern Key one_modifier_regex;
+ extern Key opt_modifier_regex;
+ extern Key seq_modifier_regex;
+ extern Key parser_regex;
+ extern Key serializer_regex;
+ extern Key enumerator_regex;
+ extern Key element_type_regex;
+ extern Key name_regex_trace;
+ extern Key include_with_brackets;
+ extern Key include_prefix;
+ extern Key include_regex;
+ extern Key include_regex_trace;
+ extern Key guard_prefix;
+ 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 custom_type;
+ extern Key custom_type_regex;
+ 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 parts;
+ extern Key parts_suffix;
+ extern Key export_symbol;
+ extern Key export_xml_schema;
+ extern Key export_maps;
+ extern Key import_maps;
+ extern Key show_anonymous;
+ extern Key show_sloc;
+ extern Key proprietary_license;
+ extern Key disable_multi_import; // Undocumented.
+
+
+ typedef Cult::CLI::Options<
+
+ char_type, NarrowString,
+ output_dir, NarrowString,
+ generate_polymorphic, Boolean,
+ generate_serialization, Boolean,
+ generate_inline, Boolean,
+ generate_ostream, Boolean,
+ generate_doxygen, Boolean,
+ generate_comparison, Boolean,
+ generate_default_ctor, Boolean,
+ generate_from_base_ctor, Boolean,
+ generate_wildcard, Boolean,
+ generate_insertion, Cult::Containers::Vector<NarrowString>,
+ generate_extraction, Cult::Containers::Vector<NarrowString>,
+ generate_forward, Boolean,
+ generate_xml_schema, Boolean,
+ extern_xml_schema, NarrowString,
+ suppress_parsing, Boolean,
+ generate_element_type, Boolean,
+ generate_element_map, Boolean,
+ generate_intellisense, Boolean,
+ omit_default_attributes, Boolean,
+ namespace_map, Cult::Containers::Vector<NarrowString>,
+ namespace_regex, Cult::Containers::Vector<NarrowString>,
+ namespace_regex_trace, Boolean,
+ reserved_name, Cult::Containers::Vector<NarrowString>,
+ type_naming, NarrowString,
+ function_naming, NarrowString,
+ type_regex, Cult::Containers::Vector<NarrowString>,
+ accessor_regex, Cult::Containers::Vector<NarrowString>,
+ one_accessor_regex, Cult::Containers::Vector<NarrowString>,
+ opt_accessor_regex, Cult::Containers::Vector<NarrowString>,
+ seq_accessor_regex, Cult::Containers::Vector<NarrowString>,
+ modifier_regex, Cult::Containers::Vector<NarrowString>,
+ one_modifier_regex, Cult::Containers::Vector<NarrowString>,
+ opt_modifier_regex, Cult::Containers::Vector<NarrowString>,
+ seq_modifier_regex, Cult::Containers::Vector<NarrowString>,
+ parser_regex, Cult::Containers::Vector<NarrowString>,
+ serializer_regex, Cult::Containers::Vector<NarrowString>,
+ enumerator_regex, Cult::Containers::Vector<NarrowString>,
+ element_type_regex, Cult::Containers::Vector<NarrowString>,
+ name_regex_trace, Boolean,
+ include_with_brackets, Boolean,
+ include_prefix, NarrowString,
+ include_regex, Cult::Containers::Vector<NarrowString>,
+ include_regex_trace, Boolean,
+ guard_prefix, NarrowString,
+ root_element_first, Boolean,
+ root_element_last, Boolean,
+ root_element_all, Boolean,
+ root_element_none, Boolean,
+ root_element, Cult::Containers::Vector<NarrowString>,
+ custom_type, Cult::Containers::Vector<NarrowString>,
+ custom_type_regex, Cult::Containers::Vector<NarrowString>,
+ hxx_suffix, NarrowString,
+ ixx_suffix, NarrowString,
+ cxx_suffix, NarrowString,
+ fwd_suffix, NarrowString,
+ hxx_regex, NarrowString,
+ ixx_regex, NarrowString,
+ cxx_regex, 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, NarrowString,
+ ixx_prologue_file, NarrowString,
+ cxx_prologue_file, NarrowString,
+ fwd_prologue_file, NarrowString,
+ prologue_file, NarrowString,
+ hxx_epilogue_file, NarrowString,
+ ixx_epilogue_file, NarrowString,
+ cxx_epilogue_file, NarrowString,
+ fwd_epilogue_file, NarrowString,
+ epilogue_file, NarrowString,
+ parts, UnsignedLong,
+ parts_suffix, NarrowString,
+ export_symbol, NarrowString,
+ export_xml_schema, Boolean,
+ export_maps, Boolean,
+ import_maps, Boolean,
+ show_anonymous, Boolean,
+ show_sloc, Boolean,
+ proprietary_license, Boolean,
+ disable_multi_import, Boolean
+
+ > Options;
+
+ struct OptionsSpec: Cult::CLI::OptionsSpec<Options> {};
+ }
+ }
+}
+
+#endif // CXX_TREE_CLI_HXX
diff --git a/xsd/cxx/tree/counter.cxx b/xsd/cxx/tree/counter.cxx
new file mode 100644
index 0000000..d8223bb
--- /dev/null
+++ b/xsd/cxx/tree/counter.cxx
@@ -0,0 +1,265 @@
+// file : xsd/cxx/tree/counter.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/tree/counter.hxx>
+
+#include <iostream>
+
+namespace CXX
+{
+ namespace Tree
+ {
+ namespace
+ {
+ struct Member: Traversal::Member
+ {
+ Member (UnsignedLong& complexity)
+ : complexity_ (complexity)
+ {
+ }
+
+ virtual Void
+ traverse (Type&)
+ {
+ complexity_++;
+ }
+
+ UnsignedLong& complexity_;
+ };
+
+ struct Any: Traversal::Any, Traversal::AnyAttribute
+ {
+ Any (UnsignedLong& complexity)
+ : complexity_ (complexity)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any&)
+ {
+ complexity_++;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute&)
+ {
+ complexity_++;
+ }
+
+ UnsignedLong& complexity_;
+ };
+
+ struct TypeBase: Traversal::List,
+ Traversal::Union,
+ Traversal::Enumeration,
+ Traversal::Complex,
+ Context
+ {
+ TypeBase (Context& c, UnsignedLong& complexity)
+ : Context (c), complexity_ (complexity)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::List&)
+ {
+ complexity_++;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Union&)
+ {
+ complexity_++;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Enumeration& e)
+ {
+ Boolean string_based (false);
+ {
+ IsStringBasedType t (string_based);
+ t.dispatch (e);
+ }
+
+ complexity_ += (string_based ? 1 : 2);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ complexity_++; // One for the type itself.
+
+ // Plus some for each member.
+ //
+ Any any (complexity_);
+ Member member (complexity_);
+ Traversal::Names names;
+
+ names >> member;
+
+ if (options.value<CLI::generate_wildcard> ())
+ names >> any;
+
+ Complex::names (c, names);
+ }
+
+ private:
+ UnsignedLong& complexity_;
+ };
+
+
+ //
+ //
+ struct GlobalType: Traversal::Type, Context
+
+ {
+ GlobalType (Context& c, Counts& counts)
+ : Context (c), counts_ (counts)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& t)
+ {
+ counts_.global_types++;
+
+ UnsignedLong complexity (0);
+ TypeBase type (*this, complexity);
+ type.dispatch (t);
+
+ counts_.complexity_total += complexity;
+ counts_.complexity.push_back (complexity);
+ }
+
+ private:
+ Counts& counts_;
+ };
+
+ //
+ //
+ struct GlobalElement: Traversal::Element,
+ GlobalElementBase,
+ Context
+ {
+ GlobalElement (Context& c, Counts& counts)
+ : GlobalElementBase (c),
+ Context (c),
+ counts_ (counts),
+ last_ (0)
+ {
+ }
+
+ ~GlobalElement ()
+ {
+ if (last_ != 0)
+ {
+ last_->context ().set ("last", true);
+ count_last ();
+ }
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ // Check if the previous element we saw needs to be generated.
+ //
+ if (last_ != 0)
+ count_last ();
+
+ last_ = &e;
+
+ if (counts_.global_elements == 0)
+ e.context ().set ("first", true);
+
+ counts_.global_elements++;
+ }
+
+ private:
+ Void
+ count_last ()
+ {
+ if (generate_p (*last_))
+ {
+ counts_.generated_global_elements++;
+
+ UnsignedLong complexity (0);
+
+ if (doc_root_p (*last_))
+ {
+ if (options.value<CLI::generate_element_type> ())
+ {
+ complexity += 1; // For c-tors and d-tor.
+
+ if (!options.value<CLI::suppress_parsing> ())
+ complexity += 1;
+
+ if (options.value<CLI::generate_serialization> ())
+ complexity += 1;
+ }
+ else
+ {
+ if (!options.value<CLI::suppress_parsing> ())
+ complexity += 6; // 13 parsing functions.
+
+ if (options.value<CLI::generate_serialization> ())
+ complexity += 4; // 8 serialization functions.
+ }
+ }
+
+ if (complexity == 0)
+ {
+ // This element must be a substitution group members. For
+ // such elements we are only generating an entry in a map.
+ // We will assign it a complexity of 1 so that we don't
+ // end up with the total complexity that is less than the
+ // number of elements and types.
+ //
+ complexity = 1;
+ }
+
+ counts_.complexity_total += complexity;
+ counts_.complexity.push_back (complexity);
+ }
+ }
+
+ private:
+ Counts& counts_;
+ SemanticGraph::Element* last_;
+ };
+ }
+
+ Counter::
+ Counter ()
+ {
+ }
+
+ Counts Counter::
+ count (CLI::Options const& options, SemanticGraph::Schema& tu)
+ {
+ Counts counts;
+ Context ctx (std::wcerr, tu, options, counts, false, 0, 0, 0);
+
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+
+ schema >> sources >> schema;
+
+ Traversal::Names schema_names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+ GlobalType global_type (ctx, counts);
+ GlobalElement global_element (ctx, counts);
+
+ schema >> schema_names >> ns >> ns_names;
+
+ ns_names >> global_element;
+ ns_names >> global_type;
+
+ schema.dispatch (tu);
+
+ return counts;
+ }
+ }
+}
diff --git a/xsd/cxx/tree/counter.hxx b/xsd/cxx/tree/counter.hxx
new file mode 100644
index 0000000..f4186ba
--- /dev/null
+++ b/xsd/cxx/tree/counter.hxx
@@ -0,0 +1,28 @@
+// file : xsd/cxx/tree/counter.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_TREE_COUNTER_HXX
+#define CXX_TREE_COUNTER_HXX
+
+#include <cxx/tree/elements.hxx>
+#include <cxx/tree/cli.hxx>
+
+namespace CXX
+{
+ namespace Tree
+ {
+ class Counter
+ {
+ public:
+ Counter (); // Dummy ctor, helps with long symbols on HP-UX.
+
+ Counts
+ count (CLI::Options const& options,
+ SemanticGraph::Schema&);
+ };
+ }
+}
+
+#endif // CXX_TREE_COUNTER_HXX
diff --git a/xsd/cxx/tree/elements.cxx b/xsd/cxx/tree/elements.cxx
new file mode 100644
index 0000000..5e85087
--- /dev/null
+++ b/xsd/cxx/tree/elements.cxx
@@ -0,0 +1,1327 @@
+// file : xsd/cxx/tree/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/tree/elements.hxx>
+
+namespace CXX
+{
+ namespace Tree
+ {
+ // Context
+ //
+ Void Context::
+ update_ns_scope () // Keeping this function first helps HP-UX
+ { // (long symbols).
+ ns_scope.clear ();
+
+ Boolean first (true);
+
+ for (NamespaceStack::Iterator i (ns_scope_stack.begin ());
+ i != ns_scope_stack.end ();
+ ++i)
+ {
+ // We only qualify names until the namespace level.
+ //
+ if (first)
+ first = false;
+ else
+ ns_scope += L"::";
+
+ ns_scope += *i;
+ }
+ }
+
+ Context::
+ Context (std::wostream& o,
+ SemanticGraph::Schema& root,
+ CLI::Options const& ops,
+ Counts const& counts_,
+ Boolean generate_xml_schema__,
+ Regex const* fe,
+ Regex const* he,
+ Regex const* ie)
+ : CXX::Context (o,
+ root,
+ ops.value<CLI::char_type> (),
+ ops.value<CLI::include_with_brackets> (),
+ ops.value<CLI::include_prefix> (),
+ ops.value<CLI::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),
+ counts (counts_),
+ any_type (any_type_),
+ any_simple_type (any_simple_type_),
+ element_type (element_type_),
+ container (container_),
+ flags_type (flags_type_),
+ qname_type (qname_type_),
+ xs_string_type (xs_string_type_),
+ properties_type (properties_type_),
+ error_handler_type (error_handler_type_),
+ list_stream_type (list_stream_type_),
+ namespace_infomap_type (namespace_infomap_type_),
+ parser_type (parser_type_),
+ std_ostream_type (std_ostream_type_),
+ ostream_type (ostream_type_),
+ istream_type (istream_type_),
+ xerces_ns (xerces_ns_),
+ dom_auto_ptr (dom_auto_ptr_),
+ dom_node_key (dom_node_key_),
+ as_double_type (as_double_type_),
+ as_decimal_type (as_decimal_type_),
+ generate_xml_schema (generate_xml_schema_),
+ doxygen (doxygen_),
+ polymorphic (ops.value<CLI::generate_polymorphic> ()),
+ fwd_expr (fe),
+ hxx_expr (he),
+ ixx_expr (ie),
+ ns_scope (ns_scope_),
+ regex_custom_type_map (regex_custom_type_map_),
+ direct_custom_type_map (direct_custom_type_map_),
+ qname_type_ (L"::xsd::cxx::xml::qualified_name< " + char_type + L" >"),
+ parser_type_ (L"::xsd::cxx::xml::dom::parser< " + char_type + L" >"),
+ generate_xml_schema_ (generate_xml_schema__),
+ doxygen_ (ops.value<CLI::generate_doxygen> ()),
+ ns_scope_stack (ns_scope_stack_),
+ cxx_uq_id_expr_ (L"^[a-zA-Z_]\\w*$"),
+ cxx_uq_id_expr (cxx_uq_id_expr_)
+ {
+ SemanticGraph::Namespace& xs (xs_ns ());
+ SemanticGraph::Context& xsc (xs.context ());
+
+ // Cache some often-used names from the XML Schema namespace
+ // if names have already been processed.
+ //
+ if (xsc.count ("container"))
+ {
+ String xs_name (ns_name (xs));
+
+ any_type = fq_name (xs.find ("anyType").first->named ());
+ any_simple_type = fq_name (xs.find ("anySimpleType").first->named ());
+ xs_string_type = fq_name (xs.find ("string").first->named ());
+
+ container = xs_name + L"::" + xsc.get<String> ("container");
+ flags_type = xs_name + L"::" + xsc.get<String> ("flags");
+
+ if (ops.value<CLI::generate_element_type> ())
+ element_type = xs_name + L"::" + xsc.get<String> ("element-type");
+
+ properties_type = xs_name + L"::" + xsc.get<String> ("properties");
+
+ if (!ops.value<CLI::suppress_parsing> () ||
+ ops.value<CLI::generate_serialization> ())
+ {
+ error_handler_type = xs_name + L"::" +
+ xsc.get<String> ("error-handler");
+ }
+
+ dom_auto_ptr_ = xs_name + L"::dom::auto_ptr";
+ dom_node_key_ = xs_name + L"::dom::" +
+ xsc.get<String> ("tree-node-key");
+
+ if (ops.value<CLI::generate_serialization> ())
+ {
+ as_double_type_ = xs_name + L"::" +
+ xsc.get<String> ("as-double");
+
+ as_decimal_type_ = xs_name + L"::" +
+ xsc.get<String> ("as-decimal");
+
+ list_stream_type = xs_name + L"::" +
+ xsc.get<String> ("list-stream");
+
+ namespace_infomap_type = xs_name + L"::" +
+ xsc.get<String> ("namespace-infomap");
+ }
+
+ // istream and ostream are templates and for now use the same
+ // names regardless of the naming convention.
+ //
+ if (!ops.value<CLI::generate_extraction> ().empty ())
+ istream_type = xs_name + L"::istream";
+
+ if (!ops.value<CLI::generate_insertion> ().empty ())
+ ostream_type = xs_name + L"::ostream";
+ }
+
+ // Xerces-C++ namespace. IntelliSense for some reason does not like
+ // it fully-qualified (maybe because it's a namespace alias).
+ //
+ if (ops.value<CLI::generate_intellisense> ())
+ xerces_ns = "xercesc";
+ else
+ xerces_ns = "::xercesc";
+
+ //
+ //
+ if (char_type == L"char")
+ std_ostream_type_ = L"::std::ostream";
+ else if (char_type == L"wchar_t")
+ std_ostream_type_ = L"::std::wostream";
+ else
+ std_ostream_type_ = L"::std::basic_ostream< " + char_type + L" >";
+
+ // Custom type mapping.
+ //
+ typedef Containers::Vector<NarrowString> Vector;
+
+ // Direct custom type mapping.
+ //
+ {
+ Vector const& v (ops.value<CLI::custom_type> ());
+
+ for (Vector::ConstIterator i (v.begin ()), e (v.end ()); i != e; ++i)
+ {
+ String s (*i);
+
+ if (s.empty ())
+ throw InvalidCustomTypeMapping (s, "mapping string is empty");
+
+ // Split the string in two parts at the last '='.
+ //
+ Size pos (s.rfind ('='));
+
+ // If no delimiter found then both type and base are empty.
+ //
+ if (pos == String::npos)
+ {
+ direct_custom_type_map[s].type.clear ();
+ direct_custom_type_map[s].base.clear ();
+ continue;
+ }
+
+ String name (s, 0, pos);
+ String rest (s, pos + 1);
+
+ // See if we've got the base part after '/'.
+ //
+ pos = rest.rfind ('/');
+
+ String type, base;
+
+ if (pos != String::npos)
+ {
+ type.assign (rest, 0, pos);
+ base.assign (rest, pos + 1, String::npos);
+ }
+ else
+ type = rest;
+
+ // type can be a potentially-qualified template-id. base is
+ // an unqualified C++ name.
+ //
+
+ if (!base.empty () && !cxx_uq_id_expr.match (base))
+ throw InvalidCustomTypeMapping (s, "invalid C++ identifier");
+
+ direct_custom_type_map[name].type = type;
+ direct_custom_type_map[name].base = base;
+ }
+ }
+
+ // Regex custom type mapping.
+ //
+ {
+ Vector const& v (ops.value<CLI::custom_type_regex> ());
+
+ for (Vector::ConstIterator i (v.begin ()), e (v.end ()); i != e; ++i)
+ {
+ String s (*i);
+
+ if (s.empty ())
+ throw InvalidCustomTypeMapping (s, "mapping string is empty");
+
+ WideChar delimiter (s[0]);
+
+ // First get pattern.
+ //
+ Size pos (s.find (delimiter, 1));
+
+ if (pos == String::npos)
+ throw InvalidCustomTypeMapping (
+ s, "missing pattern-substitution separator");
+
+ String pat (s, 1, pos - 1);
+ String rest (s, pos + 1);
+
+ String type, base;
+
+ // See if we've got type and base.
+ //
+ if (!rest.empty ())
+ {
+ pos = rest.find (delimiter);
+
+ if (pos == String::npos)
+ throw InvalidCustomTypeMapping (
+ s, "missing pattern-substitution separator");
+
+ type.assign (rest, 0, pos);
+ rest = String (rest, pos + 1);
+
+ if (!rest.empty ())
+ {
+ pos = rest.find (delimiter);
+
+ if (pos == String::npos)
+ throw InvalidCustomTypeMapping (
+ s, "missing pattern-substitution separator");
+
+ base.assign (rest, 0, pos);
+ rest = String (rest, pos + 1);
+
+ if (!rest.empty ())
+ throw InvalidCustomTypeMapping (s, "invalid format");
+ }
+ }
+
+ regex_custom_type_map.push_back (
+ RegexCustomTypeMapInfo (pat, type, base));
+ }
+ }
+ }
+
+ Context::
+ Context (Context& c)
+ : CXX::Context (c),
+ options (c.options),
+ counts (c.counts),
+ any_type (c.any_type),
+ any_simple_type (c.any_simple_type),
+ element_type (c.element_type),
+ container (c.container),
+ flags_type (c.flags_type),
+ qname_type (c.qname_type),
+ xs_string_type (c.xs_string_type),
+ properties_type (c.properties_type),
+ error_handler_type (c.error_handler_type),
+ list_stream_type (c.list_stream_type),
+ namespace_infomap_type (c.namespace_infomap_type),
+ parser_type (c.parser_type),
+ std_ostream_type (c.std_ostream_type),
+ ostream_type (c.ostream_type),
+ istream_type (c.istream_type),
+ xerces_ns (c.xerces_ns),
+ dom_auto_ptr (c.dom_auto_ptr),
+ dom_node_key (c.dom_node_key),
+ as_double_type (c.as_double_type),
+ as_decimal_type (c.as_decimal_type),
+ generate_xml_schema (c.generate_xml_schema),
+ doxygen (c.doxygen),
+ polymorphic (c.polymorphic),
+ fwd_expr (c.fwd_expr),
+ hxx_expr (c.hxx_expr),
+ ixx_expr (c.ixx_expr),
+ ns_scope (c.ns_scope),
+ regex_custom_type_map (c.regex_custom_type_map),
+ direct_custom_type_map (c.direct_custom_type_map),
+ ns_scope_stack (c.ns_scope_stack),
+ cxx_uq_id_expr (c.cxx_uq_id_expr)
+ {
+ }
+
+ Context::
+ Context (Context& c, std::wostream& o)
+ : CXX::Context (c, o),
+ options (c.options),
+ counts (c.counts),
+ any_type (c.any_type),
+ any_simple_type (c.any_simple_type),
+ element_type (c.element_type),
+ container (c.container),
+ flags_type (c.flags_type),
+ qname_type (c.qname_type),
+ xs_string_type (c.xs_string_type),
+ properties_type (c.properties_type),
+ error_handler_type (c.error_handler_type),
+ list_stream_type (c.list_stream_type),
+ namespace_infomap_type (c.namespace_infomap_type),
+ parser_type (c.parser_type),
+ std_ostream_type (c.std_ostream_type),
+ ostream_type (c.ostream_type),
+ istream_type (c.istream_type),
+ xerces_ns (c.xerces_ns),
+ dom_auto_ptr (c.dom_auto_ptr),
+ dom_node_key (c.dom_node_key),
+ as_double_type (c.as_double_type),
+ as_decimal_type (c.as_decimal_type),
+ generate_xml_schema (c.generate_xml_schema),
+ doxygen (c.doxygen),
+ polymorphic (c.polymorphic),
+ fwd_expr (c.fwd_expr),
+ hxx_expr (c.hxx_expr),
+ ixx_expr (c.ixx_expr),
+ ns_scope (c.ns_scope),
+ regex_custom_type_map (c.regex_custom_type_map),
+ direct_custom_type_map (c.direct_custom_type_map),
+ ns_scope_stack (c.ns_scope_stack),
+ cxx_uq_id_expr (c.cxx_uq_id_expr)
+ {
+ }
+
+ Boolean Context::
+ custom_type (SemanticGraph::Type const& t, String& r) const
+ {
+ String const& name (t.name ());
+
+ // First search the direct mapping.
+ //
+ {
+ DirectCustomTypeMap::ConstIterator i (
+ direct_custom_type_map.find (name));
+
+ if (i != direct_custom_type_map.end ())
+ {
+ r = i->second.type;
+ return true;
+ }
+ }
+
+
+ // Second search the regex mapping.
+ //
+ for (RegexCustomTypeMap::ConstIterator
+ i (regex_custom_type_map.begin ()),
+ e (regex_custom_type_map.end ());
+ i != e; ++i)
+ {
+ if (i->pat.match (name))
+ {
+ // Empty type sub tells us to use the original name.
+ //
+ if (i->type_sub.empty ())
+ {
+ r.clear ();
+ return true;
+ }
+
+ r = i->pat.merge (name, i->type_sub);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ String Context::
+ custom_type (SemanticGraph::Type const& t) const
+ {
+ String r;
+ if (custom_type (t, r))
+ {
+ // Empty type name tells us to use the original name.
+ //
+ if (r.empty ())
+ r = ename (t);
+ }
+
+ return r;
+ }
+
+ Boolean Context::
+ renamed_type (SemanticGraph::Type const& t, String& r) const
+ {
+ String const& name (t.name ());
+
+ // First search the direct mapping.
+ //
+ {
+ DirectCustomTypeMap::ConstIterator i (
+ direct_custom_type_map.find (name));
+
+ if (i != direct_custom_type_map.end ())
+ {
+ r = i->second.base;
+ return true;
+ }
+ }
+
+
+ // Second search the regex mapping.
+ //
+ for (RegexCustomTypeMap::ConstIterator
+ i (regex_custom_type_map.begin ()),
+ e (regex_custom_type_map.end ());
+ i != e; ++i)
+ {
+ if (i->pat.match (name))
+ {
+ if (!i->base_sub.empty ())
+ {
+ r = i->pat.merge (name, i->base_sub);
+ }
+ else
+ r.clear ();
+
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ Boolean Context::
+ is_qname (SemanticGraph::Type& t)
+ {
+ using SemanticGraph::Complex;
+ using SemanticGraph::Fundamental::QName;
+
+ if (t.is_a<QName> ())
+ return true;
+
+ if (Complex* c = dynamic_cast<Complex*> (&t))
+ {
+ if (c->inherits_p () && ultimate_base (*c).is_a<QName> ())
+ return true;
+ }
+
+ return false;
+ }
+
+
+ Void Context::
+ write_annotation (SemanticGraph::Annotation& a)
+ {
+ String const& doc (a.documentation ());
+ WideChar const* s (doc.c_str ());
+ Size size (doc.size ());
+
+ // Remove leading and trailing whitespaces.
+ //
+ while (*s == WideChar (0x20) || *s == WideChar (0x0A) ||
+ *s == WideChar (0x0D) || *s == WideChar (0x09))
+ {
+ s++;
+ size--;
+ }
+
+ if (size != 0)
+ {
+ WideChar const* e (s + size - 1);
+
+ while (e > s &&
+ (*e == WideChar (0x20) || *e == WideChar (0x0A) ||
+ *e == WideChar (0x0D) || *e == WideChar (0x09)))
+ --e;
+
+ size = s <= e ? e - s + 1 : 0;
+ }
+
+ if (size != 0)
+ {
+ os << " * ";
+
+ // Go over the data, forcing newline after 80 chars and adding
+ // ' * ' after each new line.
+ //
+ WideChar const* last_space (0);
+ WideChar const* b (s);
+ WideChar const* e (s);
+ Boolean after_newline (false);
+ Boolean rogue (false);
+
+ for (; e < s + size; ++e)
+ {
+ UnsignedLong u (unicode_char (e)); // May advance e.
+
+ // We are going to treat \v and \f as rogue here even though
+ // they can be present in C++ source code.
+ //
+ if (u > 127 || (u < 32 && u != '\t' && u != '\n'))
+ rogue = true;
+
+ if (u == ' ' || u == '\t')
+ {
+ if (after_newline)
+ {
+ if (e == b)
+ b++; // Skip leading spaces after newline.
+
+ continue;
+ }
+ else
+ last_space = e;
+ }
+ else if (after_newline)
+ {
+ os << " * ";
+ after_newline = false;
+ }
+
+ if (u == '\n')
+ {
+ write_rogue_text (b, e - b + 1, rogue);
+
+ b = e + 1;
+ last_space = 0;
+ after_newline = true;
+ rogue = false;
+ continue;
+ }
+
+ if (e - b >= 70 && last_space != 0)
+ {
+ write_rogue_text (b, last_space - b, rogue);
+ os << endl;
+
+ b = last_space + 1;
+ last_space = 0;
+ after_newline = true;
+ // Cannot reset rogue since we don't output the whole string.
+ }
+ }
+
+ if (e != b)
+ write_rogue_text (b, e - b, rogue);
+
+ if (!after_newline)
+ os << endl;
+ }
+ }
+
+ Void Context::
+ write_rogue_text (WideChar const* s, Size size, Boolean rogue)
+ {
+ if (!rogue)
+ os.write (s, size);
+ else
+ {
+ for (WideChar const* p (s); p < s + size; ++p)
+ {
+ UnsignedLong u (unicode_char (p)); // May advance p.
+
+ // We are going to treat \v and \f as rogue here even though
+ // they can be present in C++ source code.
+ //
+ if (u > 127 || (u < 32 && u != '\t' && u != '\n'))
+ os.put ('?');
+ else
+ os.put (static_cast<WideChar> (u));
+ }
+ }
+ }
+
+ // GenerateDefautCtor
+ //
+ GenerateDefaultCtor::
+ GenerateDefaultCtor (Context& c, Boolean& generate, Boolean no_base)
+ : Context (c), generate_ (generate), no_base_ (no_base)
+ {
+ *this >> inherits_ >> *this;
+ *this >> names_ >> *this;
+ }
+
+ Void GenerateDefaultCtor::
+ traverse (SemanticGraph::Complex& c)
+ {
+ // Make sure we figure out if we have any required members before
+ // we base our decision on the base type.
+ //
+ Complex::names (c, names_);
+
+ if (!generate_)
+ Complex::inherits (c, inherits_);
+ }
+
+ Void GenerateDefaultCtor::
+ traverse (SemanticGraph::Type&)
+ {
+ if (!no_base_)
+ generate_ = true;
+ }
+
+ Void GenerateDefaultCtor::
+ traverse (SemanticGraph::Enumeration&)
+ {
+ if (!no_base_)
+ generate_ = true;
+ }
+
+ Void GenerateDefaultCtor::
+ traverse (SemanticGraph::Element& e)
+ {
+ if (!skip (e) && min (e) == 1 && max (e) == 1)
+ generate_ = true;
+ }
+
+ Void GenerateDefaultCtor::
+ traverse (SemanticGraph::Attribute& a)
+ {
+ if (min (a) == 1 && !(a.fixed () && !is_qname (a.type ())))
+ generate_ = true;
+ }
+
+ Void GenerateDefaultCtor::
+ traverse (SemanticGraph::Any& a)
+ {
+ if (options.value<CLI::generate_wildcard> () &&
+ min (a) == 1 && max (a) == 1)
+ generate_ = true;
+ }
+
+
+ // GenerateFromBaseCtor
+ //
+ GenerateFromBaseCtor::
+ GenerateFromBaseCtor (Context& c, Boolean& generate)
+ : traverser_ (c, generate)
+ {
+ inherits_ >> traverser_;
+ }
+
+ Void GenerateFromBaseCtor::
+ traverse (SemanticGraph::Complex& c)
+ {
+ inherits (c, inherits_);
+ }
+
+ GenerateFromBaseCtor::Traverser::
+ Traverser (Context& c, Boolean& generate)
+ : Context (c), generate_ (generate)
+ {
+ *this >> inherits_ >> *this;
+ *this >> names_ >> *this;
+ }
+
+ Void GenerateFromBaseCtor::Traverser::
+ traverse (SemanticGraph::Complex& c)
+ {
+ names (c, names_);
+
+ if (!generate_)
+ inherits (c, inherits_);
+ }
+
+ Void GenerateFromBaseCtor::Traverser::
+ traverse (SemanticGraph::Element& e)
+ {
+ if (!skip (e) && min (e) == 1 && max (e) == 1)
+ generate_ = true;
+ }
+
+ Void GenerateFromBaseCtor::Traverser::
+ traverse (SemanticGraph::Attribute& a)
+ {
+ if (min (a) == 1 && !(a.fixed () && !is_qname (a.type ())))
+ generate_ = true;
+ }
+
+ Void GenerateFromBaseCtor::Traverser::
+ traverse (SemanticGraph::Any& a)
+ {
+ if (options.value<CLI::generate_wildcard> () &&
+ min (a) == 1 && max (a) == 1)
+ generate_ = true;
+ }
+
+ // HasComplexNonOptArgs
+ //
+ HasComplexNonFundNonOptArgs::
+ HasComplexNonFundNonOptArgs (Context& c,
+ Boolean base,
+ Boolean& complex,
+ Boolean& non_fund,
+ Boolean& clash)
+ : Context (c),
+ complex_ (complex),
+ non_fund_ (non_fund),
+ clash_ (clash)
+ {
+ if (base)
+ *this >> inherits_ >> *this;
+
+ *this >> names_ >> *this;
+ }
+
+ Void HasComplexNonFundNonOptArgs::
+ traverse (SemanticGraph::Complex& c)
+ {
+ // No optimizations: need to check every arg for clashes.
+ //
+ inherits (c, inherits_);
+ names (c, names_);
+ }
+
+ Void HasComplexNonFundNonOptArgs::
+ traverse (SemanticGraph::Element& e)
+ {
+ if (!skip (e) && min (e) == 1 && max (e) == 1)
+ {
+ Boolean fund (false);
+ IsFundamentalType t (fund);
+ t.dispatch (e.type ());
+
+ if (!fund)
+ {
+ non_fund_ = true;
+
+ Boolean simple (true);
+ IsSimpleType t (simple);
+ t.dispatch (e.type ());
+
+ if (!simple)
+ complex_ = true;
+ else
+ clash_ = false;
+ }
+ }
+ }
+
+ // FromBaseCtorArg
+ //
+ FromBaseCtorArg::
+ FromBaseCtorArg (Context& c, ArgType at, Boolean arg)
+ : Context (c), arg_type_ (at), arg_ (arg)
+ {
+ }
+
+ Void FromBaseCtorArg::
+ traverse (SemanticGraph::Any& a)
+ {
+ if (!options.value<CLI::generate_wildcard> ())
+ return;
+
+ if (min (a) == 1 && max (a) == 1)
+ {
+ String const& name (ename (a));
+
+ os << "," << endl
+ << "const " << xerces_ns << "::DOMElement&";
+
+ if (arg_)
+ os << " " << name;
+ }
+ }
+
+ Void FromBaseCtorArg::
+ traverse (SemanticGraph::Element& e)
+ {
+ if (skip (e))
+ return;
+
+ if (min (e) == 1 && max (e) == 1)
+ {
+ String const& name (ename (e));
+
+ os << "," << endl;
+
+ Boolean auto_ptr (false);
+
+ switch (arg_type_)
+ {
+ case arg_complex_auto_ptr:
+ {
+ Boolean simple (true);
+ IsSimpleType t (simple);
+ t.dispatch (e.type ());
+ auto_ptr = !simple;
+ break;
+ }
+ case arg_non_fund_auto_ptr:
+ {
+ Boolean fund (false);
+ IsFundamentalType t (fund);
+ t.dispatch (e.type ());
+ auto_ptr = !fund;
+ break;
+ }
+ case arg_type:
+ break;
+ }
+
+ if (auto_ptr)
+ os << "::std::auto_ptr< " << etype (e) << " >&";
+ else
+ os << "const " << etype (e) << "&";
+
+ if (arg_)
+ os << " " << name;
+ }
+ }
+
+ Void FromBaseCtorArg::
+ traverse (SemanticGraph::Attribute& a)
+ {
+ // Note that we are not going to include attributes with
+ // default or required fixed values here. Instead we are
+ // going to default-initialize them.
+ //
+ if (min (a) == 1 && !(a.fixed () && !is_qname (a.type ())))
+ {
+ String const& name (ename (a));
+
+ os << "," << endl
+ << "const " << etype (a) << "&";
+
+ if (arg_)
+ os << " " << name;
+ }
+ }
+
+ // CtorArgs
+ //
+ CtorArgs::
+ CtorArgs (Context& c, ArgType at)
+ : Context (c),
+ arg_type_ (at),
+ base_arg_ (0),
+ first_ (true),
+ member_name_ (c)
+ {
+ *this >> inherits_ >> *this;
+ *this >> names_ >> *this;
+ }
+
+ CtorArgs::
+ CtorArgs (Context& c, ArgType at, String& base_arg)
+ : Context (c),
+ arg_type_ (at),
+ base_arg_ (&base_arg),
+ first_ (true),
+ member_name_ (c)
+ {
+ *this >> inherits_ >> *this;
+ *this >> names_ >> *this;
+ }
+
+ Void CtorArgs::
+ traverse (SemanticGraph::Type& t)
+ {
+ os << comma () << "const ";
+
+ member_name_.dispatch (t);
+
+ os << "&";
+
+ if (base_arg_ != 0)
+ {
+ *base_arg_ = L"_xsd_" + ename (t) + L"_base";
+
+ os << " " << *base_arg_;
+ }
+ }
+
+ Void CtorArgs::
+ traverse (SemanticGraph::Enumeration& e)
+ {
+ os << comma () << "const ";
+
+ member_name_.traverse (e);
+
+ os << "&";
+
+ if (base_arg_ != 0)
+ {
+ *base_arg_ = L"_xsd_" + ename (e) + L"_base";
+
+ os << " " << *base_arg_;
+ }
+ }
+
+ Void CtorArgs::
+ traverse (SemanticGraph::Any& a)
+ {
+ if (!options.value<CLI::generate_wildcard> ())
+ return;
+
+ if (min (a) == 1 && max (a) == 1)
+ {
+ os << comma () << "const " << xerces_ns << "::DOMElement&";
+
+ if (base_arg_ != 0)
+ os << " " << ename (a);
+ }
+ }
+
+ Void CtorArgs::
+ traverse (SemanticGraph::Element& e)
+ {
+ if (skip (e))
+ return;
+
+ if (min (e) == 1 && max (e) == 1)
+ {
+ Boolean auto_ptr (false);
+
+ switch (arg_type_)
+ {
+ case arg_complex_auto_ptr:
+ {
+ Boolean simple (true);
+ IsSimpleType t (simple);
+ t.dispatch (e.type ());
+ auto_ptr = !simple;
+ break;
+ }
+ case arg_non_fund_auto_ptr:
+ {
+ Boolean fund (false);
+ IsFundamentalType t (fund);
+ t.dispatch (e.type ());
+ auto_ptr = !fund;
+ break;
+ }
+ case arg_type:
+ break;
+ }
+
+ if (auto_ptr)
+ os << comma () << "::std::auto_ptr< " << etype (e) << " >&";
+ else
+ os << comma () << "const " << etype (e) << "&";
+
+ if (base_arg_ != 0)
+ os << " " << ename (e);
+ }
+ }
+
+ Void CtorArgs::
+ traverse (SemanticGraph::Attribute& a)
+ {
+ // Note that we are not going to include attributes with
+ // default or required fixed values here. Instead we are
+ // going to default-initialize them.
+ //
+ if (min (a) == 1 && !(a.fixed () && !is_qname (a.type ())))
+ {
+ os << comma () << "const " << etype (a) << "&";
+
+ if (base_arg_ != 0)
+ os << " " << ename (a);
+ }
+ }
+
+ String CtorArgs::
+ comma ()
+ {
+ Boolean tmp (first_);
+ first_ = false;
+ return tmp ? "" : ",\n";
+ }
+
+
+ // CtorArgsWithoutBase
+ //
+ CtorArgsWithoutBase::
+ CtorArgsWithoutBase (Context& c, ArgType at, Boolean arg, Boolean first)
+ : Context (c), arg_type_ (at), arg_ (arg), first_ (first)
+ {
+ *this >> inherits_ >> *this;
+ *this >> names_ >> *this;
+ }
+
+ Void CtorArgsWithoutBase::
+ traverse (SemanticGraph::Any& a)
+ {
+ if (!options.value<CLI::generate_wildcard> ())
+ return;
+
+ if (min (a) == 1 && max (a) == 1)
+ {
+ os << comma () << "const " << xerces_ns << "::DOMElement&";
+
+ if (arg_)
+ os << " " << ename (a);
+ }
+ }
+
+ Void CtorArgsWithoutBase::
+ traverse (SemanticGraph::Element& e)
+ {
+ if (skip (e))
+ return;
+
+ if (min (e) == 1 && max (e) == 1)
+ {
+ Boolean auto_ptr (false);
+
+ switch (arg_type_)
+ {
+ case arg_complex_auto_ptr:
+ {
+ Boolean simple (true);
+ IsSimpleType t (simple);
+ t.dispatch (e.type ());
+ auto_ptr = !simple;
+ break;
+ }
+ case arg_non_fund_auto_ptr:
+ {
+ Boolean fund (false);
+ IsFundamentalType t (fund);
+ t.dispatch (e.type ());
+ auto_ptr = !fund;
+ break;
+ }
+ case arg_type:
+ break;
+ }
+
+ if (auto_ptr)
+ os << comma () << "::std::auto_ptr< " << etype (e) << " >&";
+ else
+ os << comma () << "const " << etype (e) << "&";
+
+ if (arg_)
+ os << " " << ename (e);
+ }
+ }
+
+ Void CtorArgsWithoutBase::
+ traverse (SemanticGraph::Attribute& a)
+ {
+ // Note that we are not going to include attributes with
+ // default or required fixed values here. Instead we are
+ // going to default-initialize them.
+ //
+ if (min (a) == 1 && !(a.fixed () && !is_qname (a.type ())))
+ {
+ os << comma () << "const " << etype (a) << "&";
+
+ if (arg_)
+ os << " " << ename (a);
+ }
+ }
+
+ String CtorArgsWithoutBase::
+ comma ()
+ {
+ Boolean tmp (first_);
+ first_ = false;
+ return tmp ? "" : ",\n";
+ }
+
+ // GlobalElementBase
+ //
+ Boolean GlobalElementBase::
+ generate_p (SemanticGraph::Element& e)
+ {
+ if (e.substitutes_p () && ctx_.polymorphic)
+ return true;
+
+ if (!doc_root_p (e))
+ return false;
+
+ // If we are not generating element types nor parsing/serialization
+ // code then we won't generate anything from it.
+ //
+ if (!ctx_.options.value<CLI::generate_element_type> () &&
+ ctx_.options.value<CLI::suppress_parsing> () &&
+ !ctx_.options.value<CLI::generate_serialization> ())
+ return false;
+
+ return true;
+ }
+
+ Boolean GlobalElementBase::
+ doc_root_p (SemanticGraph::Element& e)
+ {
+ if (!ctx_.options.value<CLI::root_element_first> () &&
+ !ctx_.options.value<CLI::root_element_last> () &&
+ !ctx_.options.value<CLI::root_element_all> () &&
+ !ctx_.options.value<CLI::root_element_none> () &&
+ ctx_.options.value<CLI::root_element> ().empty ())
+ return true; // By default treat them all.
+
+ if (ctx_.options.value<CLI::root_element_none> ())
+ return false;
+
+ if (ctx_.options.value<CLI::root_element_all> ())
+ return true;
+
+ if (ctx_.options.value<CLI::root_element_first> () &&
+ e.context ().count ("first") != 0)
+ return true;
+
+ if (ctx_.options.value<CLI::root_element_last> () &&
+ e.context ().count ("last") != 0)
+ return true;
+
+ typedef Cult::Containers::Vector<NarrowString> Names;
+ Names const& names (ctx_.options.value<CLI::root_element> ());
+
+ // Hopefully nobody will specify more than a handful of names ;-).
+ //
+ for (Names::ConstIterator i (names.begin ()); i != names.end (); ++i)
+ {
+ String name (*i);
+
+ if (e.name () == name)
+ return true;
+ }
+
+ return false;
+ }
+
+ // Namespace
+ //
+ Namespace::
+ Namespace (Context& c,
+ UnsignedLong first,
+ UnsignedLong last)
+ : CXX::Namespace (c, *this),
+ GlobalElementBase (c),
+ ctx_ (c),
+ first_ (first),
+ last_ (last),
+ count_ (0)
+ {
+ }
+
+ Void Namespace::
+ traverse (Type& ns)
+ {
+ using SemanticGraph::Element;
+
+ if (first_ > last_)
+ CXX::Namespace::traverse (ns);
+ else
+ {
+ Boolean opened (false);
+
+ for (Type::NamesIterator i (ns.names_begin ());
+ i != ns.names_end (); ++i)
+ {
+ SemanticGraph::Nameable& n (i->named ());
+
+ if (n.is_a<SemanticGraph::Type> () ||
+ (n.is_a<Element> () && generate_p (dynamic_cast<Element&> (n))))
+ {
+ if (count_ >= first_ && count_ <= last_)
+ {
+ if (!opened)
+ {
+ opened = true;
+ pre (ns);
+ }
+
+ edge_traverser ().dispatch (*i);
+ }
+
+ ++count_;
+ }
+ }
+
+ if (opened)
+ post (ns);
+ }
+ }
+
+ Void Namespace::
+ enter (Type&, String const& name, Boolean)
+ {
+ ctx_.enter_ns_scope (name);
+ }
+
+ Void Namespace::
+ leave ()
+ {
+ ctx_.leave_ns_scope ();
+ }
+
+ // Includes
+ //
+ Void TypeForward::
+ traverse (SemanticGraph::Type& t)
+ {
+ String const& name (ename (t));
+
+ if (String custom = custom_type (t))
+ {
+ String new_name;
+ renamed_type (t, new_name);
+
+ if (new_name)
+ os << "class " << new_name << ";";
+
+ if (custom == name)
+ os << "class " << name << ";";
+ else
+ os << "typedef " << custom << " " << name << ";";
+ }
+ else
+ os << "class " << name << ";";
+ }
+
+ 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)
+ {
+ // Generate forward declarations.
+ //
+ 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 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/xsd/cxx/tree/elements.hxx b/xsd/cxx/tree/elements.hxx
new file mode 100644
index 0000000..3d70aab
--- /dev/null
+++ b/xsd/cxx/tree/elements.hxx
@@ -0,0 +1,2030 @@
+// file : xsd/cxx/tree/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_TREE_ELEMENTS_HXX
+#define CXX_TREE_ELEMENTS_HXX
+
+#include <sstream>
+
+#include <cult/containers/map.hxx>
+#include <cult/containers/deque.hxx>
+#include <cult/containers/vector.hxx>
+
+#include <backend-elements/regex.hxx>
+
+#include <cxx/elements.hxx>
+
+#include <cxx/tree/cli.hxx>
+
+
+namespace CXX
+{
+ namespace Tree
+ {
+ struct Counts
+ {
+ Counts ()
+ : global_types (0),
+ global_elements (0),
+ generated_global_elements (0),
+ complexity_total (0)
+ {
+ }
+
+ UnsignedLong global_types;
+ UnsignedLong global_elements;
+ UnsignedLong generated_global_elements;
+
+ // Complexity value for each global type and generated global
+ // element, in order.
+ //
+ Cult::Containers::Vector<UnsignedLong> complexity;
+ UnsignedLong complexity_total;
+ };
+
+ struct InvalidCustomTypeMapping
+ {
+ InvalidCustomTypeMapping (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 CXX::Context
+ {
+ public:
+ typedef BackendElements::Regex::Expression<Char> Regex;
+ typedef BackendElements::Regex::Pattern<WideChar> WideRegexPat;
+
+ struct DirectCustomTypeMapInfo
+ {
+ DirectCustomTypeMapInfo (String const& t = L"",
+ String const& b = L"")
+ : type (t), base (b)
+ {
+ }
+
+ String type;
+ String base;
+ };
+
+ struct RegexCustomTypeMapInfo
+ {
+ RegexCustomTypeMapInfo (WideRegexPat const& p,
+ String const& t,
+ String const& b)
+ : pat (p), type_sub (t), base_sub (b)
+ {
+ }
+
+ WideRegexPat pat;
+ String type_sub;
+ String base_sub;
+ };
+
+ typedef
+ Cult::Containers::Vector<RegexCustomTypeMapInfo>
+ RegexCustomTypeMap;
+
+ typedef
+ Cult::Containers::Map<String, DirectCustomTypeMapInfo>
+ DirectCustomTypeMap;
+
+ public:
+ Context (std::wostream& o,
+ SemanticGraph::Schema& root,
+ CLI::Options const& ops,
+ Counts const& counts_,
+ Boolean generate_xml_schema,
+ Regex const* fwd_expr,
+ Regex const* hxx_expr,
+ Regex const* ixx_expr);
+
+ protected:
+ Context (Context& c);
+ Context (Context& c, std::wostream& o);
+
+ // Custom type mapping.
+ //
+ public:
+ // Returns empty string if custom mapping is not required.
+ //
+ String
+ custom_type (SemanticGraph::Type const&) const;
+
+ // Returns true if custom mapping is required. name is
+ // populated with the custom type name or empty if the
+ // original name should be used.
+ //
+ Boolean
+ custom_type (SemanticGraph::Type const&, String& name) const;
+
+ // Returns true if this type has been renamed as part of the
+ // customization process. If the function returns true, the
+ // name string is populated with the new name or empty if
+ // the type should not be generated at all.
+ //
+ Boolean
+ renamed_type (SemanticGraph::Type const&, String& name) const;
+
+ public:
+ // Return true if this type is-a QName.
+ //
+ Boolean
+ is_qname (SemanticGraph::Type&);
+
+ public:
+ // Performs a number of processing steps, including forcing a new
+ // line after 80 characters as well as "commentizing" the text by
+ // adding '* ' after each newline.
+ //
+ Void
+ write_annotation (SemanticGraph::Annotation&);
+
+ // Escaped names.
+ //
+ public:
+ // Accessor name.
+ //
+ static String const&
+ eaname (SemanticGraph::Member const& m)
+ {
+ return m.context ().get<String> ("aname");
+ }
+
+ static String const&
+ eaname (SemanticGraph::Any const& a)
+ {
+ return a.context ().get<String> ("aname");
+ }
+
+ static String const&
+ eaname (SemanticGraph::AnyAttribute const& a)
+ {
+ return a.context ().get<String> ("aname");
+ }
+
+ // Modifier name.
+ //
+ static String const&
+ emname (SemanticGraph::Member const& m)
+ {
+ return m.context ().get<String> ("mname");
+ }
+
+ static String const&
+ emname (SemanticGraph::Any const& a)
+ {
+ return a.context ().get<String> ("mname");
+ }
+
+ static String const&
+ emname (SemanticGraph::AnyAttribute const& a)
+ {
+ return a.context ().get<String> ("mname");
+ }
+
+ //
+ //
+ static String const&
+ etype (SemanticGraph::Member const& m)
+ {
+ return m.context ().get<String> ("type");
+ }
+
+ static String const&
+ etraits (SemanticGraph::Member const& m)
+ {
+ return m.context ().get<String> ("traits");
+ }
+
+ static String const&
+ econtainer (SemanticGraph::Member const& m)
+ {
+ return m.context ().get<String> ("container");
+ }
+
+ static String const&
+ econtainer (SemanticGraph::Any const& a)
+ {
+ return a.context ().get<String> ("container");
+ }
+
+ static String const&
+ econtainer (SemanticGraph::AnyAttribute const& a)
+ {
+ return a.context ().get<String> ("container");
+ }
+
+ static String const&
+ eiterator (SemanticGraph::Member const& m)
+ {
+ return m.context ().get<String> ("iterator");
+ }
+
+ static String const&
+ eiterator (SemanticGraph::Any const& a)
+ {
+ return a.context ().get<String> ("iterator");
+ }
+
+ static String const&
+ eiterator (SemanticGraph::AnyAttribute const& a)
+ {
+ return a.context ().get<String> ("iterator");
+ }
+
+ static String const&
+ econst_iterator (SemanticGraph::Member const& m)
+ {
+ return m.context ().get<String> ("const-iterator");
+ }
+
+ static String const&
+ econst_iterator (SemanticGraph::Any const& a)
+ {
+ return a.context ().get<String> ("const-iterator");
+ }
+
+ static String const&
+ econst_iterator (SemanticGraph::AnyAttribute const& a)
+ {
+ return a.context ().get<String> ("const-iterator");
+ }
+
+ static String const&
+ emember (SemanticGraph::Member const& m)
+ {
+ return m.context ().get<String> ("member");
+ }
+
+ static String const&
+ emember (SemanticGraph::Any const& a)
+ {
+ return a.context ().get<String> ("member");
+ }
+
+ static String const&
+ emember (SemanticGraph::AnyAttribute const& a)
+ {
+ return a.context ().get<String> ("member");
+ }
+
+ static String const&
+ edefault_value (SemanticGraph::Member const& m)
+ {
+ return m.context ().get<String> ("default-value");
+ }
+
+ static String const&
+ edefault_value_member (SemanticGraph::Member const& m)
+ {
+ return m.context ().get<String> ("default-value-member");
+ }
+
+ // Underlying enum value type.
+ //
+ static String const&
+ evalue (SemanticGraph::Enumeration const& e)
+ {
+ return e.context ().get<String> ("value");
+ }
+
+ // dom_document
+ //
+ static Boolean
+ edom_document_p (SemanticGraph::Complex const& c)
+ {
+ return c.context ().count ("dom-document");
+ }
+
+ static String const&
+ edom_document (SemanticGraph::Complex const& c)
+ {
+ return c.context ().get<String> ("dom-document");
+ }
+
+ static Boolean
+ edom_document_member_p (SemanticGraph::Complex const& c)
+ {
+ return c.context ().count ("dom-document-member");
+ }
+
+ static String const&
+ edom_document_member (SemanticGraph::Complex const& c)
+ {
+ return c.context ().get<String> ("dom-document-member");
+ }
+
+ // Parsing and serialization function names.
+ //
+ static String const&
+ eparser (SemanticGraph::Element const& e)
+ {
+ return e.context ().get<String> ("parser");
+ }
+
+ static String const&
+ eserializer (SemanticGraph::Element const& e)
+ {
+ return e.context ().get<String> ("serializer");
+ }
+
+ public:
+ Void
+ enter_ns_scope (String const& name)
+ {
+ ns_scope_stack.push_back (name);
+ update_ns_scope ();
+ }
+
+ Void
+ leave_ns_scope ()
+ {
+ ns_scope_stack.pop_back ();
+ update_ns_scope ();
+ }
+
+ private:
+ Void
+ update_ns_scope ();
+
+ private:
+ // Write text that may contain characters that we will have
+ // to escape (indicated by the rogue flag).
+ //
+ Void
+ write_rogue_text (WideChar const* s, Size size, Boolean rogue);
+
+ public:
+ CLI::Options const& options;
+ Counts const& counts;
+ String& any_type;
+ String& any_simple_type;
+ String& element_type;
+ String& container;
+ String& flags_type;
+ String& qname_type;
+ String& xs_string_type;
+ String& properties_type;
+ String& error_handler_type;
+ String& list_stream_type;
+ String& namespace_infomap_type;
+ String& parser_type;
+ String& std_ostream_type;
+ String& ostream_type;
+ String& istream_type;
+ String& xerces_ns;
+ String& dom_auto_ptr;
+ String& dom_node_key;
+ String& as_double_type;
+ String& as_decimal_type;
+
+ Boolean& generate_xml_schema;
+ Boolean& doxygen;
+ Boolean polymorphic;
+
+ Regex const* fwd_expr;
+ Regex const* hxx_expr;
+ Regex const* ixx_expr;
+
+ String& ns_scope;
+
+ RegexCustomTypeMap& regex_custom_type_map;
+ DirectCustomTypeMap& direct_custom_type_map;
+
+ private:
+ String any_type_;
+ String any_simple_type_;
+ String element_type_;
+ String container_;
+ String flags_type_;
+ String qname_type_;
+ String xs_string_type_;
+ String properties_type_;
+ String error_handler_type_;
+ String list_stream_type_;
+ String namespace_infomap_type_;
+ String parser_type_;
+ String std_ostream_type_;
+ String ostream_type_;
+ String istream_type_;
+ String xerces_ns_;
+ String dom_auto_ptr_;
+ String dom_node_key_;
+ String as_double_type_;
+ String as_decimal_type_;
+
+ Boolean generate_xml_schema_;
+ Boolean doxygen_;
+
+ typedef
+ Cult::Containers::Deque<String>
+ NamespaceStack;
+
+ typedef
+ Cult::Containers::Deque<String>
+ ScopeStack;
+
+ String ns_scope_;
+
+ NamespaceStack& ns_scope_stack;
+ NamespaceStack ns_scope_stack_;
+
+ RegexCustomTypeMap regex_custom_type_map_;
+ DirectCustomTypeMap direct_custom_type_map_;
+
+ private:
+ WideRegexPat const cxx_uq_id_expr_;
+ WideRegexPat const& cxx_uq_id_expr;
+ };
+
+ // Check whether this Schema type maps to a fundamental C++ type.
+ //
+ struct IsFundamentalType : 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
+
+ {
+ IsFundamentalType (Boolean& r)
+ : r_ (r)
+ {
+ }
+
+ // 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_;
+ };
+
+ // Check whether this is a string-based type.
+ //
+ struct IsStringBasedType : Traversal::Complex,
+ Traversal::Union,
+ Traversal::Fundamental::String,
+ Traversal::Fundamental::NormalizedString,
+ Traversal::Fundamental::Token,
+ Traversal::Fundamental::Name,
+ Traversal::Fundamental::NameToken,
+ Traversal::Fundamental::NCName,
+ Traversal::Fundamental::Language
+ {
+ IsStringBasedType (Boolean& r)
+ : r_ (r)
+ {
+ *this >> inherits_ >> *this;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ inherits (c, inherits_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Union&)
+ {
+ // Current mapping of union is string-based.
+ //
+ r_ = true;
+ }
+
+ // Strings.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::String&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NormalizedString&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Token&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameToken&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Name&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NCName&)
+ {
+ r_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Language&)
+ {
+ r_ = true;
+ }
+
+ private:
+ Boolean& r_;
+ Traversal::Inherits inherits_;
+ };
+
+
+ // Check whether this is a enumeration-based type.
+ //
+ struct IsEnumBasedType : Traversal::Complex
+ {
+ IsEnumBasedType (SemanticGraph::Enumeration*& e)
+ : enum_ (e)
+ {
+ *this >> inherits_;
+
+ inherits_ >> *this;
+ inherits_ >> enum_;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ inherits (c, inherits_);
+ }
+
+ private:
+ struct Enumeration: Traversal::Enumeration
+ {
+ Enumeration (SemanticGraph::Enumeration*& e)
+ : e_ (e)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (e_ == 0)
+ e_ = &e;
+ }
+
+ private:
+ SemanticGraph::Enumeration*& e_;
+ };
+
+
+ private:
+ Enumeration enum_;
+ Traversal::Inherits inherits_;
+ };
+
+
+ //
+ //
+ struct MemberTypeName : protected Context,
+ Traversal::Type,
+ 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::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
+
+ {
+ MemberTypeName (Context& c)
+ : Context (c)
+ {
+ }
+
+ MemberTypeName (Context& c, std::wostream& o)
+ : Context (c, o)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type&)
+ {
+ abort ();
+ }
+
+ virtual Void
+ traverse (SemanticGraph::List& l)
+ {
+ os << fq_name (l);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Union& u)
+ {
+ os << fq_name (u);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ os << fq_name (c);
+ }
+
+ // anyType & anySimpleType.
+ //
+ virtual Void
+ traverse (SemanticGraph::AnyType& t)
+ {
+ os << fq_name (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnySimpleType& t)
+ {
+ os << fq_name (t);
+ }
+
+ // Integral types.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Byte& t)
+ {
+ os << fq_name (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedByte& t)
+ {
+ os << fq_name (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Short& t)
+ {
+ os << fq_name (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedShort& t)
+ {
+ os << fq_name (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Int& t)
+ {
+ os << fq_name (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedInt& t)
+ {
+ os << fq_name (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Long& t)
+ {
+ os << fq_name (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedLong& t)
+ {
+ os << fq_name (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Integer& t)
+ {
+ os << fq_name (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonPositiveInteger& t)
+ {
+ os << fq_name (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonNegativeInteger& t)
+ {
+ os << fq_name (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::PositiveInteger& t)
+ {
+ os << fq_name (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NegativeInteger& t)
+ {
+ os << fq_name (t);
+ }
+
+ // Boolean.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Boolean& t)
+ {
+ os << fq_name (t);
+ }
+
+ // Floats.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Float& t)
+ {
+ os << fq_name (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Double& t)
+ {
+ os << fq_name (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Decimal& t)
+ {
+ os << fq_name (t);
+ }
+
+ // Strings.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::String& t)
+ {
+ os << fq_name (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NormalizedString& t)
+ {
+ os << fq_name (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Token& t)
+ {
+ os << fq_name (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameToken& t)
+ {
+ os << fq_name (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameTokens& t)
+ {
+ os << fq_name (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Name& t)
+ {
+ os << fq_name (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NCName& t)
+ {
+ os << fq_name (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Language& t)
+ {
+ os << fq_name (t);
+ }
+
+
+ // Qualified name.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::QName& t)
+ {
+ os << fq_name (t);
+ }
+
+
+ // ID/IDREF.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Id& t)
+ {
+ os << fq_name (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRef& t)
+ {
+ if (t.named ())
+ {
+ // IDREF<anyType>
+ //
+ os << fq_name (t);
+ }
+ else
+ {
+ SemanticGraph::Nameable& ncname (
+ xs_ns ().find ("NCName").first->named ());
+
+ os << "::xsd::cxx::tree::idref< " <<
+ type_name (t.argumented ().type ()) << ", " <<
+ char_type << ", " << fq_name (ncname) << " >";
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRefs& t)
+ {
+ if (t.named ())
+ {
+ // IDREFS<anyType>
+ //
+ os << fq_name (t);
+ }
+ else
+ {
+ SemanticGraph::Nameable& ncname (
+ xs_ns ().find ("NCName").first->named ());
+
+ os << "::xsd::cxx::tree::idrefs< " << char_type << ", " <<
+ any_simple_type << ", ::xsd::cxx::tree::idref< " <<
+ type_name (t.argumented ().type ()) << ", " << char_type <<
+ ", " << fq_name (ncname) << " > >";
+ }
+ }
+
+ // URI.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::AnyURI& t)
+ {
+ os << fq_name (t);
+ }
+
+ // Binary.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Base64Binary& t)
+ {
+ os << fq_name (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::HexBinary& t)
+ {
+ os << fq_name (t);
+ }
+
+
+ // Date/time.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Date& t)
+ {
+ os << fq_name (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::DateTime& t)
+ {
+ os << fq_name (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Duration& t)
+ {
+ os << fq_name (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Day& t)
+ {
+ os << fq_name (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Month& t)
+ {
+ os << fq_name (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::MonthDay& t)
+ {
+ os << fq_name (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Year& t)
+ {
+ os << fq_name (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::YearMonth& t)
+ {
+ os << fq_name (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Time& t)
+ {
+ os << fq_name (t);
+ }
+
+ // Entity.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entity& t)
+ {
+ os << fq_name (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entities& t)
+ {
+ os << fq_name (t);
+ }
+
+ private:
+ // For idref/idrefs
+ //
+ String
+ type_name (SemanticGraph::Type& t)
+ {
+ // This type is always named.
+ //
+ std::wostringstream o;
+
+ MemberTypeName type (*this, o);
+ type.dispatch (t);
+
+ return o.str ();
+ }
+ };
+
+
+ //
+ //
+ struct BaseTypeName : MemberTypeName
+ {
+ BaseTypeName (Context& c)
+ : MemberTypeName (c)
+ {
+ }
+
+ BaseTypeName (Context& c, std::wostream& o)
+ : MemberTypeName (c, o)
+ {
+ }
+
+ virtual Void
+ fundamental_base (SemanticGraph::Type& t)
+ {
+ os << "::xsd::cxx::tree::fundamental_base< " <<
+ fq_name (t) << ", " << char_type << ", " <<
+ any_simple_type << " >";
+ }
+
+ // Integrals.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Byte& t)
+ {
+ fundamental_base (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedByte& t)
+ {
+ fundamental_base (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Short& t)
+ {
+ fundamental_base (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedShort& t)
+ {
+ fundamental_base (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Int& t)
+ {
+ fundamental_base (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedInt& t)
+ {
+ fundamental_base (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Long& t)
+ {
+ fundamental_base (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedLong& t)
+ {
+ fundamental_base (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Integer& t)
+ {
+ fundamental_base (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonPositiveInteger& t)
+ {
+ fundamental_base (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonNegativeInteger& t)
+ {
+ fundamental_base (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::PositiveInteger& t)
+ {
+ fundamental_base (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NegativeInteger& t)
+ {
+ fundamental_base (t);
+ }
+
+ // Boolean.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Boolean& t)
+ {
+ fundamental_base (t);
+ }
+
+ // Floats.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Float& t)
+ {
+ fundamental_base (t);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Double& t)
+ {
+ os << "::xsd::cxx::tree::fundamental_base< " <<
+ fq_name (t) << ", " << char_type << ", " <<
+ any_simple_type << ", " <<
+ "::xsd::cxx::tree::schema_type::double_ >";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Decimal& t)
+ {
+ os << "::xsd::cxx::tree::fundamental_base< " <<
+ fq_name (t) << ", " << char_type << ", " <<
+ any_simple_type << ", " <<
+ "::xsd::cxx::tree::schema_type::decimal >";
+ }
+ };
+
+ // Initial value should be true.
+ //
+ struct IsSimpleType : Traversal::Complex,
+ Traversal::Member,
+ Traversal::Any,
+ Traversal::AnyAttribute
+ {
+ IsSimpleType (Boolean& v)
+ : v_ (v)
+ {
+ *this >> names_ >> *this;
+ *this >> inherits_ >> *this;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ names (c, names_);
+
+ if (v_)
+ inherits (c, inherits_);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Member&)
+ {
+ v_ = false;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any&)
+ {
+ v_ = false;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute&)
+ {
+ v_ = false;
+ }
+
+ private:
+ Boolean& v_;
+ Traversal::Names names_;
+ Traversal::Inherits inherits_;
+ };
+
+ // Test whether we need to generate default c-tor. Note that we are not
+ // interested in anyAttribute since it is always mapped to a sequence.
+ //
+ struct GenerateDefaultCtor: Traversal::Complex,
+ Traversal::Enumeration,
+ Traversal::Type,
+ Traversal::Element,
+ Traversal::Attribute,
+ Traversal::Any,
+ protected virtual Context
+ {
+ // generate should initially be false.
+ //
+ GenerateDefaultCtor (Context&, Boolean& generate, Boolean no_base);
+
+ virtual Void
+ traverse (SemanticGraph::Complex&);
+
+ virtual Void
+ traverse (SemanticGraph::Type&);
+
+ virtual Void
+ traverse (SemanticGraph::Enumeration&);
+
+ virtual Void
+ traverse (SemanticGraph::Element&);
+
+ virtual Void
+ traverse (SemanticGraph::Attribute&);
+
+ virtual Void
+ traverse (SemanticGraph::Any&);
+
+ private:
+ Boolean& generate_;
+ Boolean no_base_;
+
+ private:
+ Traversal::Inherits inherits_;
+ Traversal::Names names_;
+ };
+
+ // Test whether we need to generate from-base c-tor.
+ //
+ struct GenerateFromBaseCtor: Traversal::Complex
+ {
+ // generate should initially be false.
+ //
+ GenerateFromBaseCtor (Context& c, Boolean& generate);
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c);
+
+ private:
+ // Note that we are not interested in anyAttribute since it is always
+ // mapped to a sequence.
+ //
+ struct Traverser: Traversal::Complex,
+ Traversal::Element,
+ Traversal::Attribute,
+ Traversal::Any,
+ protected virtual Context
+ {
+ Traverser (Context& c, Boolean& generate);
+
+ virtual Void
+ traverse (SemanticGraph::Complex&);
+
+ virtual Void
+ traverse (SemanticGraph::Attribute&);
+
+ virtual Void
+ traverse (SemanticGraph::Element&);
+
+ virtual Void
+ traverse (SemanticGraph::Any&);
+
+ private:
+ Boolean& generate_;
+
+ private:
+ Traversal::Inherits inherits_;
+ Traversal::Names names_;
+ } traverser_;
+
+ Traversal::Inherits inherits_;
+ };
+
+ // Test whether the type has any non-optional element of complex
+ // (has attributes/elements) and non-fundamental types.
+ //
+ struct HasComplexNonFundNonOptArgs: Traversal::Complex,
+ Traversal::Element,
+ protected virtual Context
+ {
+ // complex and non_fund should initially be false. clash
+ // should initially be true.
+ //
+ HasComplexNonFundNonOptArgs (Context& c,
+ Boolean including_base,
+ Boolean& complex,
+ Boolean& non_fund,
+ Boolean& clash);
+
+ virtual Void
+ traverse (SemanticGraph::Complex&);
+
+ virtual Void
+ traverse (SemanticGraph::Element&);
+
+ private:
+ Boolean& complex_;
+ Boolean& non_fund_;
+ Boolean& clash_;
+
+ Traversal::Inherits inherits_;
+ Traversal::Names names_;
+ };
+
+ // Immediate non-optional member. Note that AnyAttribute is always
+ // mapped to a sequence.
+ //
+ struct FromBaseCtorArg : Traversal::Any,
+ Traversal::Element,
+ Traversal::Attribute,
+ protected virtual Context
+ {
+ enum ArgType
+ {
+ arg_type,
+ arg_complex_auto_ptr,
+ arg_non_fund_auto_ptr
+ };
+
+ FromBaseCtorArg (Context& c, ArgType, Boolean arg);
+
+ virtual Void
+ traverse (SemanticGraph::Any&);
+
+ virtual Void
+ traverse (SemanticGraph::Attribute&);
+
+ virtual Void
+ traverse (SemanticGraph::Element&);
+
+ private:
+ ArgType arg_type_;
+ Boolean arg_;
+ };
+
+ // List of all non-optional members and a simple base. Note that
+ // AnyAttribute is always mapped to a sequence.
+ //
+ struct CtorArgs : Traversal::Complex,
+ Traversal::Enumeration,
+ Traversal::Type,
+ Traversal::Any,
+ Traversal::Element,
+ Traversal::Attribute,
+ protected virtual Context
+ {
+ enum ArgType
+ {
+ arg_type,
+ arg_complex_auto_ptr,
+ arg_non_fund_auto_ptr
+ };
+
+ // The second version outputs the argument name and stores
+ // in in the base_arg string.
+ //
+ CtorArgs (Context&, ArgType);
+ CtorArgs (Context&, ArgType, String& base_arg);
+
+ virtual Void
+ traverse (SemanticGraph::Type&);
+
+ virtual Void
+ traverse (SemanticGraph::Enumeration&);
+
+ virtual Void
+ traverse (SemanticGraph::Any&);
+
+ virtual Void
+ traverse (SemanticGraph::Attribute&);
+
+ virtual Void
+ traverse (SemanticGraph::Element&);
+
+ private:
+ String
+ comma ();
+
+ private:
+ ArgType arg_type_;
+ String base_;
+ String* base_arg_;
+ Boolean first_;
+
+ private:
+ Traversal::Inherits inherits_;
+ Traversal::Names names_;
+
+ MemberTypeName member_name_;
+ };
+
+
+ // Check whether we need to generate c-tor without the base argument.
+ //
+ struct GenerateWithoutBaseCtor: Traversal::List,
+ Traversal::Union,
+ Traversal::Complex,
+ Traversal::Enumeration,
+
+ Traversal::AnyType,
+ Traversal::AnySimpleType,
+
+ Traversal::Fundamental::String,
+ Traversal::Fundamental::NormalizedString,
+ Traversal::Fundamental::Token,
+
+ Traversal::Fundamental::NameTokens,
+ Traversal::Fundamental::IdRefs,
+
+ Traversal::Fundamental::Base64Binary,
+ Traversal::Fundamental::HexBinary
+ {
+ // generate should initially be false.
+ //
+ GenerateWithoutBaseCtor (Boolean& generate)
+ : generate_ (generate)
+ {
+ *this >> inherits_ >> *this;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::List&)
+ {
+ generate_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Union&)
+ {
+ // No default initialization.
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ Complex::inherits (c);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Enumeration&)
+ {
+ // No default initialization.
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyType&)
+ {
+ generate_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnySimpleType&)
+ {
+ generate_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::String&)
+ {
+ generate_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NormalizedString&)
+ {
+ generate_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Token&)
+ {
+ generate_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameTokens&)
+ {
+ generate_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRefs&)
+ {
+ generate_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Base64Binary&)
+ {
+ generate_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::HexBinary&)
+ {
+ generate_ = true;
+ }
+
+ private:
+ Boolean& generate_;
+ Traversal::Inherits inherits_;
+ };
+
+
+ // List of all non-optional members sans simple base. Note that
+ // AnyAttribute is always mapped to a sequence.
+ //
+ struct CtorArgsWithoutBase: Traversal::Complex,
+ Traversal::Any,
+ Traversal::Element,
+ Traversal::Attribute,
+ protected virtual Context
+ {
+ enum ArgType
+ {
+ arg_type,
+ arg_complex_auto_ptr,
+ arg_non_fund_auto_ptr
+ };
+
+ CtorArgsWithoutBase (Context& c, ArgType, Boolean arg, Boolean first);
+
+ virtual Void
+ traverse (SemanticGraph::Any&);
+
+ virtual Void
+ traverse (SemanticGraph::Element&);
+
+ virtual Void
+ traverse (SemanticGraph::Attribute&);
+
+ private:
+ String
+ comma ();
+
+ private:
+ ArgType arg_type_;
+ Boolean arg_;
+ Boolean first_;
+
+ private:
+ Traversal::Inherits inherits_;
+ Traversal::Names names_;
+ };
+
+ //
+ //
+ struct GlobalElementBase
+ {
+ GlobalElementBase (Context& c)
+ : ctx_ (c)
+ {
+ }
+
+ Boolean
+ generate_p (SemanticGraph::Element&);
+
+ Boolean
+ doc_root_p (SemanticGraph::Element&);
+
+ private:
+ Context& ctx_;
+ };
+
+
+ //
+ //
+ struct Namespace: CXX::Namespace,
+ GlobalElementBase,
+ CXX::Namespace::ScopeTracker
+ {
+ Namespace (Context&,
+ UnsignedLong first = 1,
+ UnsignedLong last = 0);
+
+ virtual Void
+ traverse (Type&);
+
+ protected:
+ virtual Void
+ enter (Type&, String const& name, Boolean last);
+
+ virtual Void
+ leave ();
+
+ protected:
+ Context& ctx_;
+
+ private:
+ UnsignedLong first_;
+ UnsignedLong last_;
+ UnsignedLong count_;
+ };
+
+ //
+ //
+ struct DocumentedNamespace: Namespace
+ {
+ DocumentedNamespace (Context& c)
+ : Namespace (c)
+ {
+ }
+
+ virtual Void
+ enter (Type& ns, String const& name, Boolean last)
+ {
+ Namespace::enter (ns, name, last);
+
+ // Only add documentation to the innermost namespace.
+ //
+ if (ctx_.doxygen && name && last)
+ {
+ ctx_.os << "/**" << endl
+ << " * @brief C++ namespace for the %" <<
+ ctx_.comment (ns.name ()) << endl
+ << " * schema namespace." << endl
+ << " */" << endl;
+ }
+ }
+ };
+
+ //
+ //
+ 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,
+ 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_;
+ };
+
+ //
+ //
+ struct FundIncludes : 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,
+ Context
+
+ {
+ FundIncludes (Context& c, String const& prefix)
+ : Context (c), prefix_ (prefix),
+ long_ (false), unsigned_long_ (false)
+ {
+ }
+
+ // Integral types.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Byte& t)
+ {
+ gen_include (t, "byte.hxx");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedByte& t)
+ {
+ gen_include (t, "unsigned-byte.hxx");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Short& t)
+ {
+ gen_include (t, "short.hxx");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedShort& t)
+ {
+ gen_include (t, "unsigned-short.hxx");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Int& t)
+ {
+ gen_include (t, "int.hxx");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedInt& t)
+ {
+ gen_include (t, "unsigned-int.hxx");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Long& t)
+ {
+ if (!long_)
+ long_ = gen_include (t, "long.hxx");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedLong& t)
+ {
+ if (!unsigned_long_)
+ unsigned_long_ = gen_include (t, "unsigned-long.hxx");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Integer& t)
+ {
+ if (!long_)
+ long_ = gen_include (t, "long.hxx");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonPositiveInteger& t)
+ {
+ if (!long_)
+ long_ = gen_include (t, "long.hxx");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonNegativeInteger& t)
+ {
+ if (!unsigned_long_)
+ unsigned_long_ = gen_include (t, "unsigned-long.hxx");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::PositiveInteger& t)
+ {
+ if (!unsigned_long_)
+ unsigned_long_ = gen_include (t, "unsigned-long.hxx");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NegativeInteger& t)
+ {
+ if (!long_)
+ long_ = gen_include (t, "long.hxx");
+ }
+
+ // Boolean.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Boolean& t)
+ {
+ gen_include (t, "boolean.hxx");
+ }
+
+ // Floats.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Float& t)
+ {
+ gen_include (t, "float.hxx");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Double& t)
+ {
+ gen_include (t, "double.hxx");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Decimal& t)
+ {
+ gen_include (t, "decimal.hxx");
+ }
+
+ private:
+ Boolean
+ gen_include (SemanticGraph::Type& t, String const& file)
+ {
+ String custom;
+
+ // XML Schema built-in type customization is only possible when
+ // we are generating separate header.
+ //
+ if (generate_xml_schema && custom_type (t, custom))
+ {
+ String new_name;
+ renamed_type (t, new_name);
+
+ if (!new_name)
+ return false;
+ }
+
+ os << "#include <xsd/cxx/tree/" << prefix_ << "/" << file << ">"
+ << endl;
+
+ return true;
+ }
+
+ private:
+ String prefix_;
+ Boolean long_;
+ Boolean unsigned_long_;
+ };
+ }
+}
+
+#endif // CXX_TREE_ELEMENTS_HXX
diff --git a/xsd/cxx/tree/fundamental-header.hxx b/xsd/cxx/tree/fundamental-header.hxx
new file mode 100644
index 0000000..5ea3596
--- /dev/null
+++ b/xsd/cxx/tree/fundamental-header.hxx
@@ -0,0 +1,1186 @@
+// file : xsd/cxx/tree/fundamental-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_TREE_FUNDAMENTAL_HEADER_HXX
+#define CXX_TREE_FUNDAMENTAL_HEADER_HXX
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cxx/tree/elements.hxx>
+
+namespace CXX
+{
+ namespace Tree
+ {
+ struct FundamentalNamespace : DocumentedNamespace,
+
+ 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::Id,
+ Traversal::Fundamental::IdRef,
+ Traversal::Fundamental::IdRefs,
+
+ Traversal::Fundamental::AnyURI,
+
+ Traversal::Fundamental::QName,
+
+ 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,
+ protected virtual Context
+ {
+ FundamentalNamespace (Context& c)
+ : Context (c),
+ DocumentedNamespace (c),
+ export_ (c.options.value<CLI::export_xml_schema> () && type_exp)
+ {
+ *this >> names_ >> *this;
+ }
+
+ Void
+ gen_typedef (String const& type, String const& name)
+ {
+ os << "typedef " << type << " " << name << ";";
+
+ if (export_ && type.find (L'<') != String::npos)
+ os << "template class " << type_exp << type << ";";
+ }
+
+ String
+ built_in_type (SemanticGraph::Type& t, String const& type)
+ {
+ String custom;
+
+ String name (ename (t));
+
+ // XML Schema built-in type customization is only possible when
+ // we are generating separate header.
+ //
+ if (generate_xml_schema && custom_type (t, custom))
+ {
+ if (custom.empty ())
+ custom = name;
+
+ String new_name;
+ renamed_type (t, new_name);
+
+ if (new_name)
+ {
+ gen_typedef (type, new_name);
+
+ if (doxygen)
+ os << endl;
+ }
+
+ if (doxygen)
+ os << "/**" << endl
+ << " * @brief C++ type corresponding to the " <<
+ comment (t.name ()) << " XML Schema" << endl
+ << " * built-in type." << endl
+ << " */" << endl;
+
+ if (custom == name)
+ os << "class " << name << ";";
+ else
+ os << "typedef " << custom << " " << name << ";";
+
+ if (doxygen)
+ os << endl;
+ }
+ else
+ {
+ // Otherwise generate simple typedef.
+ //
+
+ if (doxygen)
+ os << "/**" << endl
+ << " * @brief C++ type corresponding to the " <<
+ comment (t.name ()) << " XML Schema" << endl
+ << " * built-in type." << endl
+ << " */" << endl;
+
+ gen_typedef (type, name);
+
+ if (doxygen)
+ os << endl;
+ }
+
+ return name;
+ }
+
+ // anyType and anySimpleType
+ //
+ virtual Void
+ traverse (SemanticGraph::AnyType& t)
+ {
+ os << "// anyType and anySimpleType." << endl
+ << "//" << endl;
+
+ if (doxygen)
+ os << endl;
+
+ type_ = built_in_type (t, "::xsd::cxx::tree::type");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnySimpleType& t)
+ {
+ simple_type_ = built_in_type (
+ t, L"::xsd::cxx::tree::simple_type< " + type_ + L" >");
+
+ if (doxygen)
+ os << "/**" << endl
+ << " * @brief Alias for the anyType type." << endl
+ << " */" << endl;
+
+ gen_typedef ("::xsd::cxx::tree::type",
+ xs_ns ().context().get<String> ("container"));
+
+ os << endl;
+
+ if (doxygen)
+ os << endl;
+ }
+
+ // Integrals.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Byte& t)
+ {
+ os << "// 8-bit" << endl
+ << "//" << endl;
+
+ if (doxygen)
+ os << endl;
+
+ built_in_type (t, "signed char");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedByte& t)
+ {
+ built_in_type (t, "unsigned char");
+ os << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Short& t)
+ {
+ os << "// 16-bit" << endl
+ << "//" << endl;
+
+ if (doxygen)
+ os << endl;
+
+ built_in_type (t, "short");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedShort& t)
+ {
+ built_in_type (t, "unsigned short");
+ os << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Int& t)
+ {
+ os << "// 32-bit" << endl
+ << "//" << endl;
+
+ if (doxygen)
+ os << endl;
+
+ built_in_type (t, "int");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedInt& t)
+ {
+ built_in_type (t, "unsigned int");
+ os << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Long& t)
+ {
+ os << "// 64-bit" << endl
+ << "//" <<endl;
+
+ if (doxygen)
+ os << endl;
+
+ built_in_type (t, "long long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedLong& t)
+ {
+ built_in_type (t, "unsigned long long");
+ os << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Integer& t)
+ {
+ os << "// Supposed to be arbitrary-length integral types." << endl
+ << "//" << endl;
+
+ if (doxygen)
+ os << endl;
+
+ built_in_type (t, "long long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonPositiveInteger& t)
+ {
+ built_in_type (t, "long long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonNegativeInteger& t)
+ {
+ built_in_type (t, "unsigned long long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::PositiveInteger& t)
+ {
+ built_in_type (t, "unsigned long long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NegativeInteger& t)
+ {
+ built_in_type (t, "long long");
+ os << endl;
+ }
+
+ // Boolean.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Boolean& t)
+ {
+ os << "// Boolean." << endl
+ << "//" << endl;
+
+ if (doxygen)
+ os << endl;
+
+ built_in_type (t, "bool");
+
+ os << endl;
+ }
+
+ // Floats.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Float& t)
+ {
+ os << "// Floating-point types." << endl
+ << "//" << endl;
+
+ if (doxygen)
+ os << endl;
+
+ built_in_type (t, "float");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Double& t)
+ {
+ double_ = built_in_type (t, "double");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Decimal& t)
+ {
+ decimal_ = built_in_type (t, "double");
+ os << endl;
+ }
+
+
+ // Strings.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::String& t)
+ {
+ os << "// String types." << endl
+ << "//" << endl;
+
+ if (doxygen)
+ os << endl;
+
+ string_ = built_in_type (
+ t,
+ L"::xsd::cxx::tree::string< " + char_type + L", " +
+ simple_type_ + L" >");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NormalizedString& t)
+ {
+ norm_string_ = built_in_type (
+ t,
+ L"::xsd::cxx::tree::normalized_string< " + char_type +
+ L", " + string_ + L" >");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Token& t)
+ {
+ token_ = built_in_type (
+ t,
+ L"::xsd::cxx::tree::token< " + char_type + L", " +
+ norm_string_ + L" >");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameToken& t)
+ {
+ nmtoken_ = built_in_type (
+ t,
+ L"::xsd::cxx::tree::nmtoken< " + char_type + L", " +
+ token_ + L" >");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameTokens& t)
+ {
+ built_in_type (
+ t,
+ L"::xsd::cxx::tree::nmtokens< " + char_type +
+ L", " + simple_type_ + L", " + nmtoken_ + L" >");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Name& t)
+ {
+ name_ = built_in_type (
+ t,
+ L"::xsd::cxx::tree::name< " + char_type + L", " + token_ + L" >");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NCName& t)
+ {
+ ncname_ = built_in_type (
+ t,
+ L"::xsd::cxx::tree::ncname< " + char_type + L", " + name_ + L" >");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Language& t)
+ {
+ built_in_type (
+ t,
+ L"::xsd::cxx::tree::language< " + char_type + L", " +
+ token_ + L" >");
+
+ os << endl;
+ }
+
+ // ID/IDREF.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Id& t)
+ {
+ os << "// ID/IDREF." << endl
+ << "//" << endl;
+
+ if (doxygen)
+ os << endl;
+
+ built_in_type (
+ t,
+ L"::xsd::cxx::tree::id< " + char_type + L", " + ncname_ + L" >");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRef& t)
+ {
+ idref_ = built_in_type (
+ t,
+ L"::xsd::cxx::tree::idref< " + type_ + L", " + char_type + L", " +
+ ncname_ + L" >");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRefs& t)
+ {
+ built_in_type (
+ t,
+ L"::xsd::cxx::tree::idrefs< " + char_type +
+ L", " + simple_type_ + L", " + idref_ + L" >");
+
+ os << endl;
+ }
+
+
+ // URI.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::AnyURI& t)
+ {
+ os << "// URI." << endl
+ << "//" << endl;
+
+ if (doxygen)
+ os << endl;
+
+ uri_ = built_in_type (
+ t,
+ L"::xsd::cxx::tree::uri< " + char_type + L", " +
+ simple_type_ + L" >");
+
+ os << endl;
+ }
+
+ // Qualified name.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::QName& t)
+ {
+ os << "// Qualified name." << endl
+ << "//" << endl;
+
+ if (doxygen)
+ os << endl;
+
+ built_in_type (
+ t,
+ L"::xsd::cxx::tree::qname< " + char_type +
+ L", " + simple_type_ + L", " + uri_ + L", " + ncname_ + L" >");
+
+ os << endl;
+ }
+
+ // Binary.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Base64Binary& t)
+ {
+ os << "// Binary." << endl
+ << "//" << endl;
+
+ if (doxygen)
+ os << endl
+ << "/**" << endl
+ << " * @brief Binary buffer type." << endl
+ << " */" << endl;
+
+ gen_typedef (L"::xsd::cxx::tree::buffer< " + char_type + L" >",
+ xs_ns ().context().get<String> ("buffer"));
+
+ if (doxygen)
+ os << endl;
+
+ built_in_type (
+ t,
+ L"::xsd::cxx::tree::base64_binary< " + char_type +
+ L", " + simple_type_ + L" >");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::HexBinary& t)
+ {
+ built_in_type (
+ t,
+ L"::xsd::cxx::tree::hex_binary< " + char_type +
+ L", " + simple_type_ + L" >");
+
+ os << endl;
+ }
+
+
+ // Date/time.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Date& t)
+ {
+ os << "// Date/time." << endl
+ << "//" << endl;
+
+ if (doxygen)
+ os << endl
+ << "/**" << endl
+ << " * @brief Time zone type." << endl
+ << " */" << endl;
+
+ gen_typedef ("::xsd::cxx::tree::time_zone",
+ xs_ns ().context().get<String> ("time-zone"));
+
+ if (doxygen)
+ os << endl;
+
+ built_in_type (
+ t,
+ L"::xsd::cxx::tree::date< " + char_type + L", " +
+ simple_type_ + L" >");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::DateTime& t)
+ {
+ built_in_type (
+ t,
+ L"::xsd::cxx::tree::date_time< " + char_type + L", " +
+ simple_type_ + L" >");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Duration& t)
+ {
+ built_in_type (
+ t,
+ L"::xsd::cxx::tree::duration< " + char_type + L", " +
+ simple_type_ + L" >");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Day& t)
+ {
+ built_in_type (
+ t,
+ L"::xsd::cxx::tree::gday< " + char_type + L", " +
+ simple_type_ + L" >");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Month& t)
+ {
+ built_in_type (
+ t,
+ L"::xsd::cxx::tree::gmonth< " + char_type + L", " +
+ simple_type_ + L" >");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::MonthDay& t)
+ {
+ built_in_type (
+ t,
+ L"::xsd::cxx::tree::gmonth_day< " + char_type + L", " +
+ simple_type_ + L" >");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Year& t)
+ {
+ built_in_type (
+ t,
+ L"::xsd::cxx::tree::gyear< " + char_type + L", " +
+ simple_type_ + L" >");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::YearMonth& t)
+ {
+ built_in_type (
+ t,
+ L"::xsd::cxx::tree::gyear_month< " + char_type + L", " +
+ simple_type_ + L" >");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Time& t)
+ {
+ built_in_type (
+ t,
+ L"::xsd::cxx::tree::time< " + char_type + L", " +
+ simple_type_ + L" >");
+
+ os << endl;
+ }
+
+ // Entity.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entity& t)
+ {
+ os << "// Entity." << endl
+ << "//" << endl;
+
+ if (doxygen)
+ os << endl;
+
+ entity_ = built_in_type (
+ t,
+ L"::xsd::cxx::tree::entity< " + char_type + L", " +
+ ncname_ + L" >");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entities& t)
+ {
+ built_in_type (
+ t,
+ L"::xsd::cxx::tree::entities< " + char_type +
+ L", " + simple_type_ + L", " + entity_ + L" >");
+
+ os << endl;
+ }
+
+ virtual Void
+ post (SemanticGraph::Namespace& n)
+ {
+ SemanticGraph::Context& c (xs_ns ().context());
+
+ Boolean parsing (!options.value<CLI::suppress_parsing> ());
+ Boolean serialization (options.value<CLI::generate_serialization> ());
+ Boolean element_map (options.value<CLI::generate_element_map> ());
+
+ if (options.value<CLI::generate_element_type> ())
+ {
+ if (doxygen)
+ os << "/**" << endl
+ << " * @brief Base class for element types." << endl
+ << " */" << endl;
+ else
+ os << "// Base class for element types." << endl
+ << "//" << endl;
+
+ gen_typedef (L"::xsd::cxx::tree::element_type < " +
+ char_type + L", " + type_ + L" >",
+ c.get<String> ("element-type"));
+ os << endl;
+ }
+
+ if (element_map)
+ {
+ if (doxygen)
+ os << "/**" << endl
+ << " * @brief Root element map." << endl
+ << " */" << endl;
+ else
+ os << "// Root element map." << endl
+ << "//" << endl;
+
+ gen_typedef (L"::xsd::cxx::tree::element_map < " +
+ char_type + L", " + type_ + L" >",
+ c.get<String> ("element-map"));
+ os << endl;
+ }
+
+ if (serialization)
+ {
+ os << "// Namespace information and list stream. Used in" << endl
+ << "// serialization functions." << endl
+ << "//" << endl;
+
+ if (doxygen)
+ os << "/**" << endl
+ << " * @brief Namespace serialization information." << endl
+ << " */" << endl;
+
+ gen_typedef (
+ L"::xsd::cxx::xml::dom::namespace_info < " + char_type + L" >",
+ c.get<String> ("namespace-info"));
+
+ if (doxygen)
+ os << endl
+ << "/**" << endl
+ << " * @brief Namespace serialization information map." << endl
+ << " */" << endl;
+
+ gen_typedef (L"::xsd::cxx::xml::dom::namespace_infomap < " +
+ char_type + L" >",
+ c.get<String> ("namespace-infomap"));
+
+ if (doxygen)
+ os << endl
+ << "/**" << endl
+ << " * @brief List serialization stream." << endl
+ << " */" << endl;
+
+ gen_typedef (
+ L"::xsd::cxx::tree::list_stream < " + char_type + L" >",
+ c.get<String> ("list-stream"));
+
+ if (doxygen)
+ os << endl
+ << "/**" << endl
+ << " * @brief Serialization wrapper for the %double type." << endl
+ << " */" << endl;
+
+ gen_typedef (L"::xsd::cxx::tree::as_double < " + double_ + L" >",
+ c.get<String> ("as-double"));
+
+ if (doxygen)
+ os << endl
+ << "/**" << endl
+ << " * @brief Serialization wrapper for the %decimal type." << endl
+ << " */" << endl;
+
+ gen_typedef (L"::xsd::cxx::tree::as_decimal < " + decimal_ + L" >",
+ c.get<String> ("as-decimal"));
+
+ if (doxygen)
+ os << endl
+ << "/**" << endl
+ << " * @brief Simple type facet." << endl
+ << " */" << endl;
+
+ gen_typedef ("::xsd::cxx::tree::facet", c.get<String> ("facet"));
+
+ os << endl;
+ }
+
+ //@@ Can't change names of ostream/istream since they are
+ // templates.
+ //
+ if (!options.value<CLI::generate_insertion> ().empty ())
+ {
+ if (doxygen)
+ os << "/**" << endl
+ << " * @brief Data representation output stream template." << endl
+ << " */" << endl;
+ else
+ os << "// Data representation output stream template." << endl
+ << "//" << endl;
+
+ os << "using ::xsd::cxx::tree::ostream;"
+ << endl;
+ }
+
+ if (!options.value<CLI::generate_extraction> ().empty ())
+ {
+ if (doxygen)
+ os << "/**" << endl
+ << " * @brief Data representation input stream template." << endl
+ << " */" << endl;
+ else
+ os << "// Data representation input stream template." << endl
+ << "//" << endl;
+
+ os << "using ::xsd::cxx::tree::istream;"
+ << endl;
+ }
+
+ os << "// Flags and properties." << endl
+ << "//" << endl;
+
+ if (doxygen)
+ os << endl
+ << "/**" << endl
+ << " * @brief Parsing and serialization flags." << endl
+ << " */" << endl;
+
+ gen_typedef ("::xsd::cxx::tree::flags", c.get<String> ("flags"));
+
+ if (doxygen)
+ os << endl
+ << "/**" << endl
+ << " * @brief Parsing properties." << endl
+ << " */" << endl;
+
+ gen_typedef (L"::xsd::cxx::tree::properties< " + char_type + L" >",
+ c.get<String> ("properties"));
+ os << endl;
+
+
+ //
+ //
+ os << "// Exceptions." << endl
+ << "//" << endl;
+
+ if (doxygen)
+ os << endl
+ << "/**" << endl
+ << " * @brief Root of the C++/Tree %exception hierarchy." << endl
+ << " */" << endl;
+
+ gen_typedef (L"::xsd::cxx::tree::exception< " + char_type + L" >",
+ c.get<String> ("exception"));
+
+ if (doxygen)
+ os << endl
+ << "/**" << endl
+ << " * @brief Exception indicating that the size argument exceeds" <<
+ endl
+ << " * the capacity argument." << endl
+ << " */" << endl;
+
+ gen_typedef (L"::xsd::cxx::tree::bounds< " + char_type + L" >",
+ c.get<String> ("bounds"));
+
+ if (doxygen)
+ os << endl
+ << "/**" << endl
+ << " * @brief Exception indicating that a duplicate ID value" <<
+ endl
+ << " * was encountered in the object model." << endl
+ << " */" << endl;
+
+ gen_typedef (L"::xsd::cxx::tree::duplicate_id< " + char_type + L" >",
+ c.get<String> ("duplicate-id"));
+
+ if (parsing)
+ {
+ if (doxygen)
+ os << endl
+ << "/**" << endl
+ << " * @brief Exception indicating a parsing failure." << endl
+ << " */" << endl;
+
+ gen_typedef (L"::xsd::cxx::tree::parsing< " + char_type + L" >",
+ c.get<String> ("parsing"));
+
+ if (doxygen)
+ os << endl
+ << "/**" << endl
+ << " * @brief Exception indicating that an expected element" <<
+ endl
+ << " * was not encountered." << endl
+ << " */" << endl;
+
+ gen_typedef (
+ L"::xsd::cxx::tree::expected_element< " + char_type + L" >",
+ c.get<String> ("expected-element"));
+ }
+
+ if (parsing || serialization)
+ {
+ if (doxygen)
+ os << endl
+ << "/**" << endl
+ << " * @brief Exception indicating that an unexpected " <<
+ "element" << endl
+ << " * was encountered." << endl
+ << " */" << endl;
+
+ gen_typedef (
+ L"::xsd::cxx::tree::unexpected_element< " + char_type + L" >",
+ c.get<String> ("unexpected-element"));
+ }
+
+ if (parsing)
+ {
+ if (doxygen)
+ os << endl
+ << "/**" << endl
+ << " * @brief Exception indicating that an expected " <<
+ "attribute" << endl
+ << " * was not encountered." << endl
+ << " */" << endl;
+
+ gen_typedef (
+ L"::xsd::cxx::tree::expected_attribute< " + char_type + L" >",
+ c.get<String> ("expected-attribute"));
+
+ if (doxygen)
+ os << endl
+ << "/**" << endl
+ << " * @brief Exception indicating that an unexpected " <<
+ "enumerator" << endl
+ << " * was encountered." << endl
+ << " */" << endl;
+
+ gen_typedef (
+ L"::xsd::cxx::tree::unexpected_enumerator< " + char_type + L" >",
+ c.get<String> ("unexpected-enumerator"));
+
+ if (doxygen)
+ os << endl
+ << "/**" << endl
+ << " * @brief Exception indicating that the text content " <<
+ "was" << endl
+ << " * expected for an element." << endl
+ << " */" << endl;
+
+ gen_typedef (
+ L"::xsd::cxx::tree::expected_text_content< " + char_type + L" >",
+ c.get<String> ("expected-text-content"));
+
+ if (doxygen)
+ os << endl
+ << "/**" << endl
+ << " * @brief Exception indicating that a prefix-namespace" <<
+ endl
+ << " * mapping was not provided." << endl
+ << " */" << endl;
+
+ gen_typedef (
+ L"::xsd::cxx::tree::no_prefix_mapping< " + char_type + L" >",
+ c.get<String> ("no-prefix-mapping"));
+ }
+
+ if (options.value<CLI::generate_polymorphic> ())
+ {
+ if (parsing || serialization)
+ {
+ if (doxygen)
+ os << endl
+ << "/**" << endl
+ << " * @brief Exception indicating that the type " <<
+ "information" << endl
+ << " * is not available for a type." << endl
+ << " */" << endl;
+
+ gen_typedef (
+ L"::xsd::cxx::tree::no_type_info< " + char_type + L" >",
+ c.get<String> ("no-type-info"));
+ }
+
+ if (parsing)
+ {
+ if (doxygen)
+ os << endl
+ << "/**" << endl
+ << " * @brief Exception indicating that the types are not" <<
+ endl
+ << " * related by inheritance." << endl
+ << " */" << endl;
+
+ gen_typedef (
+ L"::xsd::cxx::tree::not_derived< " + char_type + L" >",
+ c.get<String> ("not-derived"));
+ }
+ }
+
+ if (element_map)
+ {
+ if (doxygen)
+ os << endl
+ << "/**" << endl
+ << " * @brief Exception indicating that parsing or " <<
+ "serialization" << endl
+ << " * information is not available for an element." << endl
+ << " */" << endl;
+
+ gen_typedef (
+ L"::xsd::cxx::tree::no_element_info< " + char_type + L" >",
+ c.get<String> ("no-element-info"));
+ }
+
+ if (serialization)
+ {
+ if (doxygen)
+ os << endl
+ << "/**" << endl
+ << " * @brief Exception indicating a serialization " <<
+ "failure." << endl
+ << " */" << endl;
+
+ gen_typedef (
+ L"::xsd::cxx::tree::serialization< " + char_type + L" >",
+ c.get<String> ("serialization"));
+ }
+
+ os << endl;
+
+ //
+ //
+ if (parsing || serialization)
+ {
+ os << "// Parsing/serialization diagnostics." << endl
+ << "//" << endl;
+
+ if (doxygen)
+ os << endl
+ << "/**" << endl
+ << " * @brief Error severity." << endl
+ << " */" << endl;
+
+ gen_typedef ("::xsd::cxx::tree::severity",
+ c.get<String> ("severity"));
+
+ if (doxygen)
+ os << endl
+ << "/**" << endl
+ << " * @brief Error condition." << endl
+ << " */" << endl;
+
+ gen_typedef (L"::xsd::cxx::tree::error< " + char_type + L" >",
+ c.get<String> ("error"));
+
+ if (doxygen)
+ os << endl
+ << "/**" << endl
+ << " * @brief List of %error conditions." << endl
+ << " */" << endl;
+
+ gen_typedef (L"::xsd::cxx::tree::diagnostics< " + char_type + L" >",
+ c.get<String> ("diagnostics"));
+ os << endl;
+ }
+
+ if (parsing || serialization)
+ {
+ if (doxygen)
+ os << "/**" << endl
+ << " * @brief Error handler callback interface." << endl
+ << " */" << endl;
+ else
+ os << "// Error handler callback interface." << endl
+ << "//" << endl;
+
+ gen_typedef (
+ L"::xsd::cxx::xml::error_handler< " + char_type + L" >",
+ c.get<String> ("error-handler"));
+
+ os << endl;
+ }
+
+ if (parsing || serialization)
+ {
+ if (doxygen)
+ os << "/**" << endl
+ << " * @brief DOM interaction." << endl
+ << " */" << endl;
+ else
+ os << "// DOM interaction." << endl
+ << "//" << endl;
+
+ os << "namespace dom"
+ << "{";
+
+ // @@ Disregarding current naming convention by using the
+ // fixed name (no template typedef).
+ //
+ if (doxygen)
+ os << "/**" << endl
+ << " * @brief Automatic pointer for DOMDocument." << endl
+ << " */" << endl;
+ else
+ os << "// Automatic pointer for DOMDocument." << endl
+ << "//" << endl;
+
+ os << "using ::xsd::cxx::xml::dom::auto_ptr;"
+ << endl;
+
+ if (parsing)
+ {
+ if (!generate_xml_schema)
+ {
+ String g (L"XSD_CXX_TREE_TREE_NODE_KEY" + ns_name (n));
+
+ std::transform (g.begin (), g.end(), g.begin (), upcase);
+ g = escape (g); // Make it a C++ id.
+
+ os << "#ifndef " << g << endl
+ << "#define " << g << endl;
+ }
+
+ if (doxygen)
+ os << "/**" << endl
+ << " * @brief DOM user data key for back pointers to " <<
+ "tree nodes." << endl
+ << " */" << endl;
+ else
+ os << "// DOM user data key for back pointers to tree nodes." << endl
+ << "//" << endl;
+
+ os << "const XMLCh* const " << c.get<String> ("tree-node-key") <<
+ " = ::xsd::cxx::tree::user_data_keys::node;";
+
+ if (!generate_xml_schema)
+ os << "#endif" << endl;
+ }
+
+ os << "}"; // namespace dom
+ }
+
+ if (element_map)
+ {
+ if (doxygen)
+ os << "//@cond" << endl
+ << endl;
+
+ if (!generate_xml_schema)
+ {
+ String g (L"XSD_CXX_TREE_ELEMENT_MAP_INIT" + ns_name (n));
+
+ std::transform (g.begin (), g.end(), g.begin (), upcase);
+ g = escape (g); // Make it a C++ id.
+
+ os << "#ifndef " << g << endl
+ << "#define " << g << endl;
+ }
+
+ os << "static" << endl
+ << "const ::xsd::cxx::tree::element_map_init < " <<
+ char_type << ", " << type_ << " >" << endl
+ << "_xsd_element_map_init;";
+
+ if (!generate_xml_schema)
+ os << "#endif" << endl;
+
+ if (doxygen)
+ os << endl
+ << "//@endcond" << endl;
+ }
+
+ Namespace::post (n);
+ }
+
+ private:
+ Boolean export_;
+
+ Traversal::Names names_;
+
+ String type_;
+ String simple_type_;
+ String string_;
+ String norm_string_;
+ String token_;
+ String nmtoken_;
+ String name_;
+ String ncname_;
+ String idref_;
+ String uri_;
+ String entity_;
+
+ String double_;
+ String decimal_;
+ };
+ }
+}
+
+#endif // CXX_TREE_FUNDAMENTAL_HEADER_HXX
diff --git a/xsd/cxx/tree/generator.cxx b/xsd/cxx/tree/generator.cxx
new file mode 100644
index 0000000..f9b055e
--- /dev/null
+++ b/xsd/cxx/tree/generator.cxx
@@ -0,0 +1,1689 @@
+// file : xsd/cxx/tree/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/tree/generator.hxx>
+
+#include <cxx/tree/elements.hxx>
+
+#include <cxx/tree/counter.hxx>
+#include <cxx/tree/validator.hxx>
+#include <cxx/tree/name-processor.hxx>
+
+#include <cxx/tree/tree-forward.hxx>
+#include <cxx/tree/tree-header.hxx>
+#include <cxx/tree/tree-inline.hxx>
+#include <cxx/tree/tree-source.hxx>
+
+#include <cxx/tree/parser-header.hxx>
+#include <cxx/tree/parser-source.hxx>
+
+#include <cxx/tree/stream-header.hxx>
+#include <cxx/tree/stream-source.hxx>
+
+#include <cxx/tree/serialization-header.hxx>
+#include <cxx/tree/serialization-source.hxx>
+
+#include <cxx/tree/stream-insertion-header.hxx>
+#include <cxx/tree/stream-insertion-source.hxx>
+#include <cxx/tree/stream-extraction-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 "../../../libxsd/xsd/cxx/version.hxx"
+
+using std::endl;
+using std::wcerr;
+
+using namespace XSDFrontend::SemanticGraph;
+
+//
+//
+typedef
+boost::filesystem::wifstream
+WideInputFileStream;
+
+typedef
+boost::filesystem::wofstream
+WideOutputFileStream;
+
+namespace CXX
+{
+ namespace
+ {
+ Char const copyright_gpl[] =
+ "// Copyright (C) 2005-2009 Code Synthesis Tools CC\n"
+ "//\n"
+ "// This program was generated by CodeSynthesis XSD, an XML Schema to\n"
+ "// C++ data binding compiler.\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"
+ "// In addition, as a special exception, Code Synthesis Tools CC gives\n"
+ "// permission to link this program with the Xerces-C++ library (or with\n"
+ "// modified versions of Xerces-C++ that use the same license as Xerces-C++),\n"
+ "// and distribute linked combinations including the two. You must obey\n"
+ "// the GNU General Public License version 2 in all respects for all of\n"
+ "// the code used other than Xerces-C++. If you modify this copy of the\n"
+ "// program, you may extend this exception to your version of the program,\n"
+ "// but you are not obligated to do so. If you do not wish to do so, delete\n"
+ "// this exception statement from your version.\n"
+ "//\n"
+ "// Furthermore, Code Synthesis Tools CC makes a special exception for\n"
+ "// the Free/Libre and Open Source Software (FLOSS) which is described\n"
+ "// in the accompanying FLOSSE file.\n"
+ "//\n\n";
+
+ Char const copyright_proprietary[] =
+ "// Copyright (C) 2005-2009 Code Synthesis Tools CC\n"
+ "//\n"
+ "// This program was generated by CodeSynthesis XSD, an XML Schema\n"
+ "// to C++ data binding compiler, in the Proprietary License mode.\n"
+ "// You should have received a proprietary license from Code Synthesis\n"
+ "// Tools CC prior to generating this code. See the license text for\n"
+ "// conditions.\n"
+ "//\n\n";
+ }
+
+ namespace Tree
+ {
+ namespace CLI
+ {
+ extern Key char_type = "char-type";
+ extern Key output_dir = "output-dir";
+ extern Key generate_polymorphic = "generate-polymorphic";
+ extern Key generate_serialization = "generate-serialization";
+ extern Key generate_inline = "generate-inline";
+ extern Key generate_ostream = "generate-ostream";
+ extern Key generate_doxygen = "generate-doxygen";
+ extern Key generate_comparison = "generate-comparison";
+ extern Key generate_default_ctor = "generate-default-ctor";
+ extern Key generate_from_base_ctor = "generate-from-base-ctor";
+ extern Key generate_wildcard = "generate-wildcard";
+ extern Key generate_insertion = "generate-insertion";
+ extern Key generate_extraction = "generate-extraction";
+ 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_parsing = "suppress-parsing";
+ extern Key generate_element_type = "generate-element-type";
+ extern Key generate_element_map = "generate-element-map";
+ extern Key generate_intellisense = "generate-intellisense";
+ extern Key omit_default_attributes = "omit-default-attributes";
+ 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 type_naming = "type-naming";
+ extern Key function_naming = "function-naming";
+ extern Key type_regex = "type-regex";
+ extern Key accessor_regex = "accessor-regex";
+ extern Key one_accessor_regex = "one-accessor-regex";
+ extern Key opt_accessor_regex = "opt-accessor-regex";
+ extern Key seq_accessor_regex = "seq-accessor-regex";
+ extern Key modifier_regex = "modifier-regex";
+ extern Key one_modifier_regex = "one-modifier-regex";
+ extern Key opt_modifier_regex = "opt-modifier-regex";
+ extern Key seq_modifier_regex = "seq-modifier-regex";
+ extern Key parser_regex = "parser-regex";
+ extern Key serializer_regex = "serializer-regex";
+ extern Key enumerator_regex = "enumerator-regex";
+ extern Key element_type_regex = "element-type-regex";
+ extern Key name_regex_trace = "name-regex-trace";
+ 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 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 custom_type = "custom-type";
+ extern Key custom_type_regex = "custom-type-regex";
+ 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 parts = "parts";
+ extern Key parts_suffix = "parts-suffix";
+ extern Key export_symbol = "export-symbol";
+ extern Key export_xml_schema = "export-xml-schema";
+ extern Key export_maps = "export-maps";
+ extern Key import_maps = "import-maps";
+ extern Key show_anonymous = "show-anonymous";
+ extern Key show_sloc = "show-sloc";
+ extern Key proprietary_license = "proprietary-license";
+ extern Key disable_multi_import = "disable-multi-import";
+ }
+ }
+
+ Void Tree::Generator::
+ usage ()
+ {
+ std::wostream& e (wcerr);
+ ::CLI::Indent::Clip< ::CLI::OptionsUsage, WideChar> clip (e);
+
+ e << "--char-type <type>" << endl
+ << " Use <type> as the base character type. Valid\n"
+ << " values are 'char' (default) and 'wchar_t'."
+ << endl;
+
+ e << "--output-dir <dir>" << endl
+ << " Write generated files to <dir> instead of current\n"
+ << " directory."
+ << endl;
+
+
+ e << "--generate-polymorphic" << endl
+ << " Generate polymorphism-aware code. Specify this\n"
+ << " option if you use substitution groups or xsi:type."
+ << endl;
+
+ e << "--generate-serialization" << endl
+ << " Generate serialization functions. They convert an\n"
+ << " in-memory representation back to XML."
+ << endl;
+
+ e << "--generate-inline" << endl
+ << " Generate certain functions inline."
+ << endl;
+
+ e << "--generate-ostream" << endl
+ << " Generate ostream insertion operators."
+ << endl;
+
+ e << "--generate-doxygen" << endl
+ << " Generate documentation comments in the Doxygen\n"
+ << " format."
+ << endl;
+
+ e << "--generate-comparison" << endl
+ << " Generate comparison operators."
+ << endl;
+
+ e << "--generate-default-ctor" << endl
+ << " Generate default constructors even for types that\n"
+ << " have required members."
+ << endl;
+
+ e << "--generate-from-base-ctor" << endl
+ << " Generate from-base constructors."
+ << endl;
+
+ e << "--generate-wildcard" << endl
+ << " Generate accessors/modifiers as well as parsing\n"
+ << " and serialization code for XML Schema wildcards."
+ << endl;
+
+ e << "--generate-insertion <os>" << endl
+ << " Generate data representation stream insertion\n"
+ << " operators for the <os> output stream type."
+ << endl;
+
+ e << "--generate-extraction <is>" << endl
+ << " Generate data representation stream extraction\n"
+ << " constructors for the <is> input stream type."
+ << endl;
+
+ e << "--generate-forward" << endl
+ << " Generate forward declaration file."
+ << 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 << "--suppress-parsing" << endl
+ << " Suppress the generation of parsing functions."
+ << endl;
+
+ e << "--generate-element-type" << endl
+ << " Generate types instead of parsing/serialization\n"
+ << " functions for root elements."
+ << endl;
+
+ e << "--generate-element-map" << endl
+ << " Generate a root element map that allows uniform\n"
+ << " parsing/serialization of multiple root elements.\n"
+ << endl;
+
+ e << "--generate-intellisense" << endl
+ << " Generate workarounds for IntelliSense bugs in\n"
+ << " Visual Studio 2005 (8.0)."
+ << endl;
+
+ e << "--omit-default-attributes" << endl
+ << " Omit attributes with default and fixed values\n"
+ << " from serialized XML documents."
+ << 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 << "--type-naming <style>" << endl
+ << " Specify the type naming convention that should be\n"
+ << " used in the generated code. Valid styles are 'knr'\n"
+ << " (default), 'ucc', and 'java'."
+ << endl;
+
+ e << "--function-naming <style>" << endl
+ << " Specify the function naming convention that should\n"
+ << " be used in the generated code. Valid styles are\n"
+ << " 'knr' (default), 'lcc', and 'java'."
+ << endl;
+
+ e << "--type-regex <expr>" << endl
+ << " Add <expr> to the list of regular expressions\n"
+ << " used to translate XML Schema type names to C++\n"
+ << " type names."
+ << endl;
+
+ e << "--accessor-regex <expr>" << endl
+ << " Add <expr> to the list of regular expressions\n"
+ << " used to translate XML Schema names of elements and\n"
+ << " attributes to C++ accessor function names."
+ << endl;
+
+ e << "--one-accessor-regex <expr>" << endl
+ << " Add <expr> to the list of regular expressions\n"
+ << " used to translate XML Schema names of elements\n"
+ << " and attributes with cardinality one to C++\n"
+ << " accessor function names."
+ << endl;
+
+ e << "--opt-accessor-regex <expr>" << endl
+ << " Add <expr> to the list of regular expressions\n"
+ << " used to translate XML Schema names of elements\n"
+ << " and attributes with cardinality optional to C++\n"
+ << " accessor function names."
+ << endl;
+
+ e << "--seq-accessor-regex <expr>" << endl
+ << " Add <expr> to the list of regular expressions\n"
+ << " used to translate XML Schema names of elements\n"
+ << " and attributes with cardinality sequence to C++\n"
+ << " accessor function names."
+ << endl;
+
+ e << "--modifier-regex <expr>" << endl
+ << " Add <expr> to the list of regular expressions\n"
+ << " used to translate XML Schema names of elements and\n"
+ << " attributes to C++ modifier function names."
+ << endl;
+
+ e << "--one-modifier-regex <expr>" << endl
+ << " Add <expr> to the list of regular expressions\n"
+ << " used to translate XML Schema names of elements\n"
+ << " and attributes with cardinality one to C++\n"
+ << " modifier function names."
+ << endl;
+
+ e << "--opt-modifier-regex <expr>" << endl
+ << " Add <expr> to the list of regular expressions\n"
+ << " used to translate XML Schema names of elements\n"
+ << " and attributes with cardinality optional to C++\n"
+ << " modifier function names."
+ << endl;
+
+ e << "--seq-modifier-regex <expr>" << endl
+ << " Add <expr> to the list of regular expressions\n"
+ << " used to translate XML Schema names of elements\n"
+ << " and attributes with cardinality sequence to C++\n"
+ << " modifier function names."
+ << endl;
+
+ e << "--parser-regex <expr>" << endl
+ << " Add <expr> to the list of regular expressions\n"
+ << " used to translate XML Schema element names to\n"
+ << " C++ parsing function names."
+ << endl;
+
+ e << "--serializer-regex <expr>" << endl
+ << " Add <expr> to the list of regular expressions\n"
+ << " used to translate XML Schema element names to\n"
+ << " C++ serialization function names."
+ << endl;
+
+ e << "--enumerator-regex <expr>" << endl
+ << " Add <expr> to the list of regular expressions\n"
+ << " used to translate XML Schema enumeration values\n"
+ << " to C++ enumerator names."
+ << endl;
+
+ e << "--element-type-regex <expr>" << endl
+ << " Add <expr> to the list of regular expressions\n"
+ << " used to translate XML Schema element names to\n"
+ << " C++ element type names."
+ << endl;
+
+ e << "--name-regex-trace" << endl
+ << " Trace the process of applying regular expressions\n"
+ << " specified with the name transformation options."
+ << 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 << "--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 << "--custom-type <map>" << endl
+ << " Use a custom C++ type instead of the generated\n"
+ << " class. The <map> argument is in the form\n"
+ << " name[=type[/base]], where <name> is a type name as\n"
+ << " defined in XML Schema, <type> is a C++ type name\n"
+ << " that should be used instead, and optional <base>\n"
+ << " is a C++ name that should be given to the C++\n"
+ << " class generated from the XML Schema definition\n"
+ << " which is normally used as a base for the custom\n"
+ << " type."
+ << endl;
+
+ e << "--custom-type-regex <regex>" << endl
+ << " Use custom C++ types instead of the generated\n"
+ << " classes. The <regex> argument is in the form\n"
+ << " /name/[type/[base/]], where <name> is a regex\n"
+ << " pattern that will be matched against type names\n"
+ << " as defined in XML Schema, <type> is a C++ type\n"
+ << " name that should be used instead, and optional\n"
+ << " <base> is a C++ name that should be given to\n"
+ << " the C++ class generated from the XML Schema\n"
+ << " definition."
+ << 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 << "--fwd-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '-fwd.hxx'\n"
+ << " to construct the name of the forward declaration\n"
+ << " 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;
+
+ 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 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 << "--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 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 << "--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 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 << "--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 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 << "--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 << "--parts <num>" << endl
+ << " Split generated source code into <num> parts."
+ << endl;
+
+ e << "--parts-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '-' to\n"
+ << " separate the file name from the part number."
+ << endl;
+
+ e << "--export-symbol <symbol>" << endl
+ << " Export symbol for Win32 DLL export/import control."
+ << endl;
+
+ e << "--export-xml-schema" << endl
+ << " Export/import types in the XML Schema namespace."
+ << endl;
+
+ e << "--export-maps" << endl
+ << " Export polymorphism support maps from Win32 DLL."
+ << endl;
+
+ e << "--import-maps" << endl
+ << " Import polymorphism support maps from Win32 DLL."
+ << endl;
+
+ 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;
+ }
+
+ Tree::CLI::OptionsSpec Tree::Generator::
+ options_spec ()
+ {
+ CLI::OptionsSpec spec;
+
+ spec.option<CLI::char_type> ().default_value ("char");
+
+ 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");
+
+ spec.option<CLI::type_naming> ().default_value ("knr");
+ spec.option<CLI::function_naming> ().default_value ("knr");
+
+ spec.option<CLI::parts> ().default_value (1);
+ spec.option<CLI::parts_suffix> ().default_value ("-");
+
+ return spec;
+ }
+
+
+ namespace
+ {
+ Void
+ open (WideInputFileStream& 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 Tree::Generator::Failed ();
+ }
+ }
+ catch (InvalidPath const&)
+ {
+ wcerr << "error: '" << path.c_str () << "' is not a valid "
+ << "filesystem path" << endl;
+
+ throw Tree::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 Tree::Generator::
+ generate (Tree::CLI::Options const& ops,
+ Schema& schema,
+ Path const& file_path,
+ const WarningSet& disabled_warnings,
+ FileList& file_list,
+ AutoUnlinks& unlinks)
+ {
+ using std::ios_base;
+ namespace Indentation = BackendElements::Indentation;
+
+ typedef BackendElements::Regex::Expression<Char> Regex;
+
+ using Cult::Containers::Vector;
+
+ typedef Vector<Path> Paths;
+ typedef Vector<Evptr<WideOutputFileStream> > WideOutputFileStreams;
+
+ try
+ {
+ // Do option validation.
+ //
+ if (ops.value<CLI::parts> () < 1)
+ {
+ wcerr << "error: invalid value for option --parts: " <<
+ ops.value<CLI::parts> () << endl;
+ throw Failed ();
+ }
+
+ // Get counts.
+ //
+ Counts counts;
+ {
+ Counter counter;
+ counts = counter.count (ops, schema);
+
+ /*
+ wcerr << "global type count: " << counts.global_types << endl;
+ wcerr << "global element count: " << counts.global_elements << endl;
+ wcerr << "generated global element count: " <<
+ counts.generated_global_elements << endl;
+
+ wcerr << "total complexity: " << counts.complexity_total << endl;
+ wcerr << "complexity vector size: " << counts.complexity.size ()
+ << endl;
+ */
+ }
+
+ // Evaluate the graph for possibility of generating something useful.
+ //
+ {
+ Validator validator;
+ if (!validator.validate (
+ ops, schema, file_path, disabled_warnings, counts))
+ throw Failed ();
+ }
+
+ // Process names.
+ //
+ {
+ NameProcessor proc;
+ if (!proc.process (ops, schema, file_path))
+ throw Failed ();
+ }
+
+ // Parts.
+ //
+ UnsignedLong parts (ops.value<CLI::parts> ());
+ UnsignedLong units (
+ counts.global_types + counts.generated_global_elements);
+
+ UnsignedLong units_per_part (units / parts);
+
+ if (parts != 1 && units_per_part < 1)
+ {
+ wcerr << "error: too many parts specified: " << parts << endl;
+ throw Failed ();
+ }
+
+ UnsignedLong complexity_per_part (counts.complexity_total / parts);
+
+
+ NarrowString parts_suffix (ops.value<CLI::parts_suffix> ());
+
+ //
+ //
+ 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 inline_ (ops.value<CLI::generate_inline> () &&
+ !generate_xml_schema);
+
+ Boolean forward (ops.value<CLI::generate_forward> () &&
+ !generate_xml_schema);
+
+ Boolean source (!generate_xml_schema);
+
+ // Generate code.
+ //
+ 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> ());
+
+ Regex hxx_expr (ops.value <CLI::hxx_regex> ().empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + hxx_suffix + "#"
+ : ops.value <CLI::hxx_regex> ());
+
+ Regex ixx_expr (ops.value <CLI::ixx_regex> ().empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + ixx_suffix + "#"
+ : ops.value <CLI::ixx_regex> ());
+
+ Regex cxx_expr (ops.value <CLI::cxx_regex> ().empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + cxx_suffix + "#"
+ : ops.value <CLI::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 && parts == 1 && !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 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 fwd_path (fwd_name, boost::filesystem::native);
+ Paths cxx_paths;
+
+ if (source)
+ {
+ if (parts > 1)
+ {
+ for (UnsignedLong i (0); i < parts; ++i)
+ {
+ std::ostringstream os;
+ os << i;
+
+ Regex expr (
+ "#^(.+?)(\\.[^./\\\\]+)?$#$1" + parts_suffix + os.str () + "$2#");
+
+ NarrowString part_name (expr.merge (name));
+
+ if (!cxx_expr.match (part_name))
+ {
+ wcerr << "error: source expression '" <<
+ cxx_expr.pattern () << "' does not match '" <<
+ part_name.c_str () << "'" << endl;
+ throw Failed ();
+ }
+
+ cxx_paths.push_back (
+ Path (cxx_expr.merge (part_name), boost::filesystem::native));
+ }
+ }
+ else
+ cxx_paths.push_back (
+ Path (cxx_expr.merge (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;
+ fwd_path = path / fwd_path;
+
+ for (Paths::Iterator i (cxx_paths.begin ());
+ i != cxx_paths.end (); ++i)
+ *i = path / *i;
+ }
+ catch (InvalidPath const&)
+ {
+ wcerr << dir.c_str () << ": error: invalid path" << endl;
+ throw Failed ();
+ }
+ }
+
+ //
+ //
+ WideOutputFileStream hxx (hxx_path, ios_base::out);
+ WideOutputFileStream ixx;
+ WideOutputFileStream fwd;
+ WideOutputFileStreams cxx;
+
+
+ // 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 ());
+ }
+
+
+ // HXX
+ //
+ 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 ());
+
+
+ // IXX
+ //
+ 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 ());
+ }
+
+
+ // CXX
+ //
+ if (source)
+ {
+ for (Paths::Iterator i (cxx_paths.begin ());
+ i != cxx_paths.end (); ++i)
+ {
+ Evptr<WideOutputFileStream> s (
+ new WideOutputFileStream (*i, ios_base::out));
+
+ if (!s->is_open ())
+ {
+ wcerr << *i << ": error: unable to open in write mode" << endl;
+ throw Failed ();
+ }
+
+ unlinks.add (*i);
+ file_list.push_back (i->native_file_string ());
+ cxx.push_back (s);
+ }
+ }
+
+
+ // Print copyright and license.
+ //
+ Char const* copyright (
+ ops.value<CLI::proprietary_license> ()
+ ? copyright_proprietary
+ : copyright_gpl);
+
+ if (forward)
+ fwd << copyright;
+
+ hxx << copyright;
+
+ if (ops.value<CLI::generate_doxygen> ())
+ {
+ // Use native path format.
+ //
+ hxx << "/**" << endl
+ << " * @file" << endl
+ << " * @brief Generated from " << name.c_str () << "." << endl
+ << " */" << endl
+ << endl;
+
+ }
+
+ if (inline_)
+ ixx << copyright;
+
+ if (source)
+ {
+ for (WideOutputFileStreams::Iterator i (cxx.begin ());
+ i != cxx.end (); ++i)
+ **i << copyright;
+ }
+
+
+ // 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 += '_';
+
+ // FWD
+ //
+ if (forward)
+ {
+ Context ctx (fwd, schema, ops, counts, generate_xml_schema,
+ &fwd_expr, &hxx_expr, &ixx_expr);
+
+ Indentation::Clip<Indentation::SLOC, WideChar> fwd_sloc (fwd);
+
+ // Guard
+ //
+ String guard (guard_expr.merge (guard_prefix + fwd_name));
+ guard = ctx.escape (guard); // make 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> ());
+ append (fwd, ops.value<CLI::fwd_prologue_file> (), prologue);
+
+ fwd << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ // Version check.
+ //
+ fwd << "#include <xsd/cxx/version.hxx>" << endl
+ << endl
+ << "#if (XSD_INT_VERSION != " << XSD_INT_VERSION << "L)" << endl
+ << "#error XSD runtime version mismatch" << endl
+ << "#endif" << endl
+
+ << endl;
+ {
+ fwd << "#include <xsd/cxx/pre.hxx>" << endl
+ << endl;
+
+ if (ctx.char_type == L"char")
+ {
+ fwd << "#ifndef XSD_USE_CHAR" << endl
+ << "#define XSD_USE_CHAR" << endl
+ << "#endif" << endl
+ << endl;
+
+ fwd << "#ifndef XSD_CXX_TREE_USE_CHAR" << endl
+ << "#define XSD_CXX_TREE_USE_CHAR" << endl
+ << "#endif" << endl
+ << endl;
+ }
+ else if (ctx.char_type == L"wchar_t")
+ {
+ fwd << "#ifndef XSD_USE_WCHAR" << endl
+ << "#define XSD_USE_WCHAR" << endl
+ << "#endif" << endl
+ << endl;
+
+ fwd << "#ifndef XSD_CXX_TREE_USE_WCHAR" << endl
+ << "#define XSD_CXX_TREE_USE_WCHAR" << endl
+ << "#endif" << endl
+ << endl;
+ }
+
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> fwd_clip (fwd);
+
+
+ // Generate.
+ //
+ generate_forward (ctx);
+
+ fwd << "#include <xsd/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> ());
+
+ 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, counts, generate_xml_schema,
+ &fwd_expr, &hxx_expr, &ixx_expr);
+
+ Indentation::Clip<Indentation::SLOC, WideChar> hxx_sloc (hxx);
+
+ // Guard
+ //
+ String guard (guard_expr.merge (guard_prefix + hxx_name));
+ guard = ctx.escape (guard); // make 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 <xsd/cxx/config.hxx>" << endl
+ << endl
+ << "#if (XSD_INT_VERSION != " << XSD_INT_VERSION << "L)" << endl
+ << "#error XSD runtime version mismatch" << endl
+ << "#endif" << endl
+ << endl;
+
+ {
+ hxx << "#include <xsd/cxx/pre.hxx>" << endl
+ << endl;
+
+ // Generate character selection defines.
+ //
+ if (!forward)
+ {
+ if (ctx.char_type == L"char")
+ {
+ hxx << "#ifndef XSD_USE_CHAR" << endl
+ << "#define XSD_USE_CHAR" << endl
+ << "#endif" << endl
+ << endl;
+
+ hxx << "#ifndef XSD_CXX_TREE_USE_CHAR" << endl
+ << "#define XSD_CXX_TREE_USE_CHAR" << endl
+ << "#endif" << endl
+ << endl;
+ }
+ else if (ctx.char_type == L"wchar_t")
+ {
+ hxx << "#ifndef XSD_USE_WCHAR" << endl
+ << "#define XSD_USE_WCHAR" << endl
+ << "#endif" << endl
+ << endl;
+
+ hxx << "#ifndef XSD_CXX_TREE_USE_WCHAR" << endl
+ << "#define XSD_CXX_TREE_USE_WCHAR" << endl
+ << "#endif" << 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_forward (ctx);
+ }
+
+ generate_tree_header (ctx);
+
+ if (!generate_xml_schema)
+ {
+
+ if (ops.value<CLI::generate_ostream> ())
+ generate_stream_header (ctx);
+
+ if (!ops.value<CLI::generate_element_type> () &&
+ !ops.value<CLI::suppress_parsing> ())
+ generate_parser_header (ctx);
+
+ if (ops.value<CLI::generate_serialization> ())
+ generate_serialization_header (ctx);
+
+ if (!ops.value<CLI::generate_insertion> ().empty ())
+ generate_stream_insertion_header (ctx);
+ }
+
+ if (inline_)
+ {
+ hxx << "#ifndef XSD_DONT_INCLUDE_INLINE" << endl
+ << "#include " << ctx.process_include_path (ixx_name) << endl
+ << "#endif // XSD_DONT_INCLUDE_INLINE" << endl
+ << endl;
+ }
+
+ hxx << "#include <xsd/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, counts, generate_xml_schema,
+ &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, 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, 1, 0);
+ }
+
+ // 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;
+
+ 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)
+ {
+ UnsignedLong first_unit (0); // First unit in the current part.
+
+ for (UnsignedLong part (0); part < parts; ++part)
+ {
+ // Figure out the range of units for this part.
+ //
+ UnsignedLong last_unit (first_unit);
+
+ if (units != 0)
+ {
+ UnsignedLong complexity (counts.complexity[last_unit]);
+
+ while (complexity < complexity_per_part)
+ {
+ // Make sure there will be at least one unit for each part left.
+ //
+ if ((last_unit + 1) >= units ||
+ (units - (last_unit + 1) - 1) < (parts - part - 1))
+ break;
+
+ // Check if the increase in complexity should be kept in this
+ // part or moved to the next.
+ //
+ UnsignedLong new_complexity (
+ complexity + counts.complexity[last_unit + 1]);
+
+ if (new_complexity > complexity_per_part)
+ {
+ if ((new_complexity - complexity_per_part) >
+ (counts.complexity[last_unit + 1] / 2))
+ break;
+ }
+
+ last_unit++;
+ complexity = new_complexity;
+ }
+
+ if (part + 1 == parts)
+ {
+ // Last part.
+ //
+ last_unit = units - 1;
+ }
+ }
+
+ //
+ //
+ UnsignedLong first (first_unit);
+ UnsignedLong last (last_unit);
+
+ first_unit = last_unit + 1;
+
+ //wcerr << "[" << first << ", " << last << "]: " << complexity
+ // << endl;
+
+ WideOutputFileStream& os (*cxx[part]);
+
+ Context ctx (os, schema, ops, counts, generate_xml_schema,
+ &fwd_expr, &hxx_expr, &ixx_expr);
+
+ Indentation::Clip<Indentation::SLOC, WideChar> cxx_sloc (os);
+
+ // Copy prologue.
+ //
+ os << "// Begin prologue." << endl
+ << "//" << endl;
+
+ append (os,
+ ops.value<CLI::cxx_prologue> (),
+ ops.value<CLI::prologue> ());
+ append (os, ops.value<CLI::cxx_prologue_file> (), prologue);
+
+ os << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ os << "#include <xsd/cxx/pre.hxx>" << endl
+ << endl;
+
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> cxx_clip (os);
+
+
+ // Generate.
+ //
+ os << "#include " << ctx.process_include_path (hxx_name) << endl
+ << endl;
+
+ if (!inline_)
+ generate_tree_inline (ctx, first, last);
+
+ generate_tree_source (ctx, first, last);
+
+ if (ops.value<CLI::generate_ostream> ())
+ generate_stream_source (ctx, first, last);
+
+ if (!ops.value<CLI::generate_element_type> () &&
+ !ops.value<CLI::suppress_parsing> ())
+ generate_parser_source (ctx, first, last);
+
+ if (ops.value<CLI::generate_serialization> ())
+ generate_serialization_source (ctx, first, last);
+
+ if (!ops.value<CLI::generate_extraction> ().empty ())
+ generate_stream_extraction_source (ctx);
+
+ if (!ops.value<CLI::generate_insertion> ().empty ())
+ generate_stream_insertion_source (ctx);
+
+ os << "#include <xsd/cxx/post.hxx>" << endl
+ << endl;
+ }
+
+ // Copy epilogue.
+ //
+ os << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (os, ops.value<CLI::cxx_epilogue_file> (), epilogue);
+ append (os,
+ ops.value<CLI::cxx_epilogue> (),
+ ops.value<CLI::epilogue> ());
+
+ os << "//" << endl
+ << "// End epilogue." << endl
+ << endl;
+
+ if (show_sloc)
+ {
+ wcerr << cxx_paths[part] << ": "
+ << 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 (InvalidCustomTypeMapping const& e)
+ {
+ wcerr << "error: invalid custom type 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/xsd/cxx/tree/generator.hxx b/xsd/cxx/tree/generator.hxx
new file mode 100644
index 0000000..1aa3c60
--- /dev/null
+++ b/xsd/cxx/tree/generator.hxx
@@ -0,0 +1,49 @@
+// file : xsd/cxx/tree/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_TREE_GENERATOR_HXX
+#define CXX_TREE_GENERATOR_HXX
+
+#include <cult/types.hxx>
+
+#include <xsd-frontend/semantic-graph/elements.hxx> // Path
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <xsd.hxx>
+
+#include <cxx/tree/cli.hxx>
+
+namespace CXX
+{
+ namespace Tree
+ {
+ 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,
+ const WarningSet& disabled_warnings,
+ FileList& file_list,
+ AutoUnlinks& unlinks);
+
+ private:
+ Generator ();
+ };
+ }
+}
+
+#endif // CXX_TREE_GENERATOR_HXX
diff --git a/xsd/cxx/tree/name-processor.cxx b/xsd/cxx/tree/name-processor.cxx
new file mode 100644
index 0000000..456095f
--- /dev/null
+++ b/xsd/cxx/tree/name-processor.cxx
@@ -0,0 +1,2100 @@
+// file : xsd/cxx/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/tree/name-processor.hxx>
+#include <cxx/tree/elements.hxx>
+
+#include <backend-elements/regex.hxx>
+
+#include <cult/containers/set.hxx>
+#include <cult/containers/map.hxx>
+#include <cult/containers/vector.hxx>
+
+#include <sstream>
+#include <iostream>
+
+namespace CXX
+{
+ namespace Tree
+ {
+ NameProcessor::
+ NameProcessor ()
+ {
+ // Dummy ctor, helps with long symbols on HP-UX.
+ }
+
+ namespace
+ {
+ //
+ //
+ typedef Cult::Containers::Set<String> NameSet;
+
+
+
+
+ class Context: public Tree::Context
+ {
+ public:
+ struct Failed {};
+
+ Context (CLI::Options const& options,
+ Counts const& counts,
+ Boolean generate_xml_schema,
+ SemanticGraph::Schema& root,
+ SemanticGraph::Path const& file)
+ : Tree::Context (std::wcerr,
+ root,
+ options,
+ counts,
+ generate_xml_schema,
+ 0,
+ 0,
+ 0),
+ schema_path_ (file),
+ schema_path (schema_path_),
+ global_type_names (global_type_names_),
+ global_element_names (global_element_names_),
+ type_regex (type_regex_),
+ accessor_regex (accessor_regex_),
+ one_accessor_regex (one_accessor_regex_),
+ opt_accessor_regex (opt_accessor_regex_),
+ seq_accessor_regex (seq_accessor_regex_),
+ modifier_regex (modifier_regex_),
+ one_modifier_regex (one_modifier_regex_),
+ opt_modifier_regex (opt_modifier_regex_),
+ seq_modifier_regex (seq_modifier_regex_),
+ parser_regex (parser_regex_),
+ serializer_regex (serializer_regex_),
+ enumerator_regex (enumerator_regex_),
+ element_type_regex (element_type_regex_)
+ {
+ typedef Containers::Vector<NarrowString> Vector;
+
+ NarrowString tn (options.value<CLI::type_naming> ());
+ NarrowString fn (options.value<CLI::function_naming> ());
+
+
+ // Type name regex.
+ //
+ {
+ // Predefined rules. The most frequently used come last: global
+ // names, two components (<name>,type), three components
+ // (<name>,const,iterator), and one component (value in enum).
+ //
+ if (tn == "knr")
+ {
+ type_regex.push_back ("/(?:[^ ]* )?([^,]+),([^,]+),([^,]+),([^,]+)/$1_$2_$3_$4/");
+ type_regex.push_back ("/(?:[^ ]* )?([^,]+),([^,]+),([^,]+)/$1_$2_$3/");
+ type_regex.push_back ("/(?:[^ ]* )?([^,]+),([^,]+)/$1_$2/");
+ type_regex.push_back ("/(?:[^ ]* )?([^,]+)/$1/");
+
+ /*
+ type_regex.push_back ("/([^,]+)/$1/");
+ type_regex.push_back ("/([^,]+),([^,]+),([^,]+),([^,]+)/$1_$2_$3_$4/");
+ type_regex.push_back ("/([^,]+),([^,]+),([^,]+)/$1_$2_$3/");
+ type_regex.push_back ("/([^,]+),([^,]+)/$1_$2/");
+ type_regex.push_back ("/[^ ]* (.+)/$1/");
+ */
+ }
+ else
+ {
+ // Upper camel case or Java.
+ //
+ type_regex.push_back ("/(?:[^ ]* )?([^,]+),([^,]+),([^,]+),([^,]+)/\\u$1\\u$2\\u$3\\u$4/");
+ type_regex.push_back ("/(?:[^ ]* )?([^,]+),([^,]+),([^,]+)/\\u$1\\u$2\\u$3/");
+ type_regex.push_back ("/(?:[^ ]* )?([^,]+),([^,]+)/\\u$1\\u$2/");
+ type_regex.push_back ("/(?:[^ ]* )?([^,]+)/\\u$1/");
+
+ /*
+ type_regex.push_back ("/([^,]+)/\\u$1/");
+ type_regex.push_back ("/([^,]+),([^,]+),([^,]+),([^,]+)/\\u$1\\u$2\\u$3\\u$4/");
+ type_regex.push_back ("/([^,]+),([^,]+),([^,]+)/\\u$1\\u$2\\u$3/");
+ type_regex.push_back ("/([^,]+),([^,]+)/\\u$1\\u$2/");
+ type_regex.push_back ("/[^ ]* (.+)/\\u$1/");
+ */
+
+ }
+
+ compile_regex (options.value<CLI::type_regex> (),
+ type_regex,
+ "type");
+ }
+
+ // Accessor name regex.
+ //
+ {
+ // Predefined rules. The most frequently used come last: one
+ // component, three components (<name>,default,value) and two
+ // component (dom,document).
+ //
+ if (fn == "knr")
+ {
+ accessor_regex.push_back ("/([^,]+),([^,]+)/$1_$2/");
+ accessor_regex.push_back ("/([^,]+),([^,]+),([^,]+)/$1_$2_$3/");
+ accessor_regex.push_back ("/([^,]+)/$1/");
+ }
+ else if (fn == "lcc")
+ {
+ accessor_regex.push_back ("/([^,]+),([^,]+)/\\l$1\\u$2/");
+ accessor_regex.push_back ("/([^,]+),([^,]+),([^,]+)/\\l$1\\u$2\\u$3/");
+ accessor_regex.push_back ("/([^,]+)/\\l$1/");
+ }
+ else
+ {
+ // Java: add get.
+ //
+ accessor_regex.push_back ("/([^,]+),([^,]+)/get\\u$1\\u$2/");
+ accessor_regex.push_back ("/([^,]+),([^,]+),([^,]+)/get\\u$1\\u$2\\u$3/");
+ accessor_regex.push_back ("/([^,]+)/get\\u$1/");
+ }
+
+ compile_regex (options.value<CLI::accessor_regex> (),
+ accessor_regex,
+ "accessor");
+
+ compile_regex (options.value<CLI::one_accessor_regex> (),
+ one_accessor_regex,
+ "one accessor");
+
+ compile_regex (options.value<CLI::opt_accessor_regex> (),
+ opt_accessor_regex,
+ "optional accessor");
+
+ compile_regex (options.value<CLI::seq_accessor_regex> (),
+ seq_accessor_regex,
+ "sequence accessor");
+ }
+
+
+ // Modifier name regex.
+ //
+ {
+ if (fn == "knr")
+ {
+ // any,attribute
+ //
+ modifier_regex.push_back ("/([^,]+),([^,]+)/$1_$2/");
+ }
+ else if (fn == "lcc")
+ {
+ modifier_regex.push_back ("/([^,]+),([^,]+)/\\l$1\\u$2/");
+ modifier_regex.push_back ("/([^,]+)/\\l$1/");
+ }
+ else
+ {
+ // Java: add set.
+ //
+ modifier_regex.push_back ("/([^,]+),([^,]+)/set\\u$1\\u$2/");
+ modifier_regex.push_back ("/([^,]+)/set\\u$1/");
+ }
+
+ compile_regex (options.value<CLI::modifier_regex> (),
+ modifier_regex,
+ "modifier");
+
+ compile_regex (options.value<CLI::one_modifier_regex> (),
+ one_modifier_regex,
+ "one modifier");
+
+ compile_regex (options.value<CLI::opt_modifier_regex> (),
+ opt_modifier_regex,
+ "optional modifier");
+
+ compile_regex (options.value<CLI::seq_modifier_regex> (),
+ seq_modifier_regex,
+ "sequence modifier");
+ }
+
+
+ // Parser name regex.
+ //
+ {
+ if (fn == "lcc")
+ {
+ parser_regex.push_back ("/(.+)/\\l$1/");
+ }
+ else if (fn == "java")
+ {
+ // Java: add parse.
+ //
+ parser_regex.push_back ("/(.+)/parse\\u$1/");
+ }
+
+ compile_regex (options.value<CLI::parser_regex> (),
+ parser_regex,
+ "parser");
+ }
+
+ // Serializer name regex.
+ //
+ {
+ if (fn == "lcc")
+ {
+ serializer_regex.push_back ("/(.+)/\\l$1/");
+ }
+ else if (fn == "java")
+ {
+ // Java: add serialize.
+ //
+ serializer_regex.push_back ("/(.+)/serialize\\u$1/");
+ }
+
+ compile_regex (options.value<CLI::serializer_regex> (),
+ serializer_regex,
+ "serializer");
+ }
+
+ // Enumerator name regex.
+ //
+ {
+ compile_regex (options.value<CLI::enumerator_regex> (),
+ enumerator_regex,
+ "enumerator");
+ }
+
+ // Element type regex.
+ //
+ compile_regex (options.value<CLI::element_type_regex> (),
+ element_type_regex,
+ "element_type");
+ }
+
+ protected:
+ Context (Context& c)
+ : Tree::Context (c),
+ schema_path (c.schema_path),
+ global_type_names (c.global_type_names),
+ global_element_names (c.global_element_names),
+ type_regex (c.type_regex),
+ accessor_regex (c.accessor_regex),
+ one_accessor_regex (c.one_accessor_regex),
+ opt_accessor_regex (c.opt_accessor_regex),
+ seq_accessor_regex (c.seq_accessor_regex),
+ modifier_regex (c.modifier_regex),
+ one_modifier_regex (c.one_modifier_regex),
+ opt_modifier_regex (c.opt_modifier_regex),
+ seq_modifier_regex (c.seq_modifier_regex),
+ parser_regex (c.parser_regex),
+ serializer_regex (c.serializer_regex),
+ enumerator_regex (c.enumerator_regex),
+ element_type_regex (c.element_type_regex)
+ {
+ }
+
+ public:
+ typedef BackendElements::Regex::Expression<WideChar> Regex;
+ typedef BackendElements::Regex::Format<WideChar> RegexFormat;
+ typedef Cult::Containers::Vector<Regex> RegexVector;
+
+ String
+ process_regex (String const& name,
+ RegexVector const& rv,
+ String const& id)
+ {
+ Boolean trace (options.value<CLI::name_regex_trace> ());
+
+ if (trace)
+ os << id << " name: '" << name << "'" << endl;
+
+ for (RegexVector::ConstReverseIterator i (rv.rbegin ());
+ i != rv.rend (); ++i)
+ {
+ if (trace)
+ os << "try: '" << i->pattern () << "' : ";
+
+ if (i->match (name))
+ {
+ String r (i->merge (name));
+
+ if (trace)
+ os << "'" << r << "' : +" << endl;
+
+ return r;
+ }
+
+ if (trace)
+ os << '-' << endl;
+ }
+
+ return name;
+ }
+
+ String
+ process_regex (String const& name,
+ RegexVector const& primary,
+ RegexVector const& backup,
+ String const& id)
+ {
+ Boolean trace (options.value<CLI::name_regex_trace> ());
+
+ if (trace)
+ os << id << " name: '" << name << "'" << endl;
+
+ for (RegexVector::ConstReverseIterator i (primary.rbegin ());
+ i != primary.rend (); ++i)
+ {
+ if (trace)
+ os << "try: '" << i->pattern () << "' : ";
+
+ if (i->match (name))
+ {
+ String r (i->merge (name));
+
+ if (trace)
+ os << "'" << r << "' : +" << endl;
+
+ return r;
+ }
+
+ if (trace)
+ os << '-' << endl;
+ }
+
+ for (RegexVector::ConstReverseIterator i (backup.rbegin ());
+ i != backup.rend (); ++i)
+ {
+ if (trace)
+ os << "try: '" << i->pattern () << "' : ";
+
+ if (i->match (name))
+ {
+ String r (i->merge (name));
+
+ if (trace)
+ os << "'" << r << "' : +" << endl;
+
+ return r;
+ }
+
+ if (trace)
+ os << '-' << endl;
+ }
+
+ return name;
+ }
+
+ String
+ process_regex (String const& ns,
+ String const& name,
+ RegexVector const& rv,
+ String const& id)
+ {
+ String s (ns + L' ' + name);
+ Boolean trace (options.value<CLI::name_regex_trace> ());
+
+ if (trace)
+ os << id << " name: '" << s << "'" << endl;
+
+ for (RegexVector::ConstReverseIterator i (rv.rbegin ());
+ i != rv.rend (); ++i)
+ {
+ if (trace)
+ os << "try: '" << i->pattern () << "' : ";
+
+ if (i->match (s))
+ {
+ String r (i->merge (s));
+
+ if (trace)
+ os << "'" << r << "' : +" << endl;
+
+ return r;
+ }
+
+ if (trace)
+ os << '-' << endl;
+ }
+
+ return name;
+ }
+
+ String
+ process_regex (String const& ns,
+ String const& name,
+ RegexVector const& primary,
+ RegexVector const& backup,
+ String const& id)
+ {
+ String s (ns + L' ' + name);
+ Boolean trace (options.value<CLI::name_regex_trace> ());
+
+ if (trace)
+ os << id << " name: '" << s << "'" << endl;
+
+ for (RegexVector::ConstReverseIterator i (primary.rbegin ());
+ i != primary.rend (); ++i)
+ {
+ if (trace)
+ os << "try: '" << i->pattern () << "' : ";
+
+ if (i->match (s))
+ {
+ String r (i->merge (s));
+
+ if (trace)
+ os << "'" << r << "' : +" << endl;
+
+ return r;
+ }
+
+ if (trace)
+ os << '-' << endl;
+ }
+
+ for (RegexVector::ConstReverseIterator i (backup.rbegin ());
+ i != backup.rend (); ++i)
+ {
+ if (trace)
+ os << "try: '" << i->pattern () << "' : ";
+
+ if (i->match (s))
+ {
+ String r (i->merge (s));
+
+ if (trace)
+ os << "'" << r << "' : +" << endl;
+
+ return r;
+ }
+
+ if (trace)
+ os << '-' << endl;
+ }
+
+ return name;
+ }
+
+ public:
+ String
+ find_name (String const& base_name,
+ NameSet& set,
+ Boolean insert = true)
+ {
+ String name (base_name);
+
+ for (UnsignedLong i (1); set.find (name) != set.end (); ++i)
+ {
+ std::wostringstream os;
+ os << i;
+ name = base_name + os.str ();
+ }
+
+ if (insert)
+ set.insert (name);
+
+ return name;
+ }
+
+ private:
+ Void
+ compile_regex (Containers::Vector<NarrowString> const& sv,
+ RegexVector& rv,
+ String const& id)
+ {
+ typedef Containers::Vector<NarrowString> Vector;
+
+ for (Vector::ConstIterator i (sv.begin ()); i != sv.end (); ++i)
+ {
+ try
+ {
+ rv.push_back (Regex (*i));
+ }
+ catch (RegexFormat const& e)
+ {
+ os << "error: invalid " << id << " name regex: '" <<
+ e.expression () << "': " << e.description () << endl;
+
+ throw Failed ();
+ }
+ }
+ }
+
+ private:
+ SemanticGraph::Path const schema_path_;
+
+ Cult::Containers::Map<String, NameSet> global_type_names_;
+ Cult::Containers::Map<String, NameSet> global_element_names_;
+
+ RegexVector type_regex_;
+ RegexVector accessor_regex_;
+ RegexVector one_accessor_regex_;
+ RegexVector opt_accessor_regex_;
+ RegexVector seq_accessor_regex_;
+ RegexVector modifier_regex_;
+ RegexVector one_modifier_regex_;
+ RegexVector opt_modifier_regex_;
+ RegexVector seq_modifier_regex_;
+ RegexVector parser_regex_;
+ RegexVector serializer_regex_;
+ RegexVector enumerator_regex_;
+ RegexVector element_type_regex_;
+
+ public:
+ SemanticGraph::Path const& schema_path;
+
+ Cult::Containers::Map<String, NameSet>& global_type_names;
+ Cult::Containers::Map<String, NameSet>& global_element_names;
+
+ RegexVector& type_regex;
+ RegexVector& accessor_regex;
+ RegexVector& one_accessor_regex;
+ RegexVector& opt_accessor_regex;
+ RegexVector& seq_accessor_regex;
+ RegexVector& modifier_regex;
+ RegexVector& one_modifier_regex;
+ RegexVector& opt_modifier_regex;
+ RegexVector& seq_modifier_regex;
+ RegexVector& parser_regex;
+ RegexVector& serializer_regex;
+ RegexVector& enumerator_regex;
+ RegexVector& element_type_regex;
+ };
+
+ //
+ //
+ struct Enumerator: Traversal::Enumerator, Context
+ {
+ Enumerator (Context& c, NameSet& set)
+ : Context (c), set_ (set)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ // Process the name with enumerator name regex.
+ //
+ String name (
+ process_regex (e.name (), enumerator_regex, L"enumerator"));
+
+ // Escape and unclash.
+ //
+ name = find_name (escape (name), set_);
+ e.context ().set ("name", name);
+ }
+
+ private:
+ NameSet& set_;
+ };
+
+ //
+ //
+ struct Enumeration: Traversal::Enumeration, Context
+ {
+ Enumeration (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ // Use processed name.
+ //
+ String name (e.context ().get<String> ("name"));
+
+ // If renamed name is empty then we are not generating
+ // anything for this type and name processing is not
+ // required.
+ //
+ if (renamed_type (e, name) && !name)
+ return;
+
+ NameSet enum_set;
+ enum_set.insert (name);
+
+ Enumerator enumerator (*this, enum_set);
+ Traversal::Names names (enumerator);
+
+ Traversal::Enumeration::names (e, names);
+
+ // Assign name to the value type. First process the name
+ // with type name regex.
+ //
+ String value_name (
+ escape (process_regex ("value", type_regex, L"type")));
+ e.context ().set ("value", find_name (value_name, enum_set));
+ }
+ };
+
+ //
+ //
+ struct PrimaryMember: Traversal::Member, Context
+ {
+ PrimaryMember (Context& c, NameSet& name_set, NameSet& stem_set)
+ : Context (c), name_set_ (name_set), stem_set_ (stem_set)
+ {
+ }
+
+ virtual Void
+ traverse (Type& m)
+ {
+ if (Tree::Context::skip (m))
+ return;
+
+ String stem (find_name (m.name (), stem_set_));
+
+ m.context ().set ("stem", stem);
+ m.context ().set ("name",
+ find_name (escape (stem), name_set_, false));
+ }
+
+ private:
+ NameSet& name_set_;
+ NameSet& stem_set_;
+ };
+
+ //
+ //
+ struct DerivedMember: Traversal::Member, Context
+ {
+ DerivedMember (Context& c, NameSet& name_set)
+ : Context (c), name_set_ (name_set)
+ {
+ }
+
+ virtual Void
+ traverse (Type& m)
+ {
+ if (Tree::Context::skip (m))
+ return;
+
+ UnsignedLong max (Tree::Context::max (m));
+ UnsignedLong min (Tree::Context::min (m));
+
+ String const& s (m.context ().get<String> ("stem"));
+ String const& b (m.context ().get<String> ("name"));
+
+ Boolean def_attr (m.default_ () &&
+ m.is_a<SemanticGraph::Attribute> () &&
+ !Tree::Context::is_qname (m.type ()));
+
+ // Accessors/modifiers. Note that we postpone inserting the
+ // names into the name_set to avoid over-escaping.
+ //
+ String an, mn;
+
+ if (max != 1)
+ {
+ an = find_name (
+ escape (process_regex (s,
+ seq_accessor_regex,
+ accessor_regex,
+ L"sequence accessor")),
+ name_set_,
+ false);
+
+ mn = find_name (
+ escape (process_regex (s,
+ seq_modifier_regex,
+ modifier_regex,
+ L"sequence modifier")),
+ name_set_,
+ false);
+ }
+ else if (min == 0 && !def_attr)
+ {
+ an = find_name (
+ escape (process_regex (s,
+ opt_accessor_regex,
+ accessor_regex,
+ L"optional accessor")),
+ name_set_,
+ false);
+
+ mn = find_name (
+ escape (process_regex (s,
+ opt_modifier_regex,
+ modifier_regex,
+ L"optional modifier")),
+ name_set_,
+ false);
+ }
+ else
+ {
+ an = find_name (
+ escape (process_regex (s,
+ one_accessor_regex,
+ accessor_regex,
+ L"one accessor")),
+ name_set_,
+ false);
+
+ mn = find_name (
+ escape (process_regex (s,
+ one_modifier_regex,
+ modifier_regex,
+ L"one modifier")),
+ name_set_,
+ false);
+ }
+
+ m.context ().set ("aname", an);
+ m.context ().set ("mname", mn);
+
+ name_set_.insert (b);
+
+ if (an != b)
+ name_set_.insert (an);
+
+ if (mn != b && mn != an)
+ name_set_.insert (mn);
+
+
+ // Types.
+ //
+ m.context ().set (
+ "type",
+ find_name (
+ escape (process_regex (s + L",type", type_regex, L"type")),
+ name_set_));
+
+ m.context ().set (
+ "traits",
+ find_name (
+ escape (process_regex (s + L",traits", type_regex, L"type")),
+ name_set_));
+
+ if (max != 1)
+ {
+ m.context ().set (
+ "container",
+ find_name (
+ escape (process_regex (s + L",sequence", type_regex, L"type")),
+ name_set_));
+
+ m.context ().set (
+ "iterator",
+ find_name (
+ escape (process_regex (s + L",iterator", type_regex, L"type")),
+ name_set_));
+
+ m.context ().set (
+ "const-iterator",
+ find_name (
+ escape (
+ process_regex (s + L",const,iterator", type_regex, L"type")),
+ name_set_));
+ }
+ else if (min == 0 && !def_attr)
+ {
+ m.context ().set (
+ "container",
+ find_name (
+ escape (process_regex (s + L",optional", type_regex, L"type")),
+ name_set_));
+ }
+
+ // Data member.
+ //
+ m.context ().set ("member", find_name (b + L"_", name_set_));
+
+ // Default value.
+ //
+ if (m.default_ () && !Tree::Context::is_qname (m.type ()))
+ {
+ Boolean simple (true);
+
+ if (m.is_a<SemanticGraph::Element> ())
+ {
+ IsSimpleType test (simple);
+ test.dispatch (m.type ());
+ }
+
+ if (simple)
+ {
+ String an (
+ escape (
+ process_regex (
+ s + L",default,value", accessor_regex, L"accessor")));
+
+ m.context ().set ( "default-value", find_name (an, name_set_));
+
+ m.context ().set (
+ "default-value-member",
+ find_name (b + L"_default_value_", name_set_));
+ }
+ }
+ }
+
+ private:
+ NameSet& name_set_;
+ };
+
+
+ //
+ //
+ struct Any: Traversal::Any, Traversal::AnyAttribute, Context
+ {
+ Any (Context& c,
+ NameSet& name_set,
+ NameSet& stem_set,
+ Boolean& has_wildcard)
+ : Context (c),
+ name_set_ (name_set),
+ stem_set_ (stem_set),
+ has_wildcard_ (has_wildcard)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ UnsignedLong max (Tree::Context::max (a));
+ UnsignedLong min (Tree::Context::min (a));
+
+ String s (find_name (L"any", stem_set_));
+
+ String b (find_name (escape (s), name_set_, false));
+ a.context ().set ("name", b);
+
+ // Accessors/modifiers. Note that we postpone inserting the
+ // names into the name_set to avoid over-escaping.
+ //
+ String an, mn;
+
+ if (max != 1)
+ {
+ an = find_name (
+ escape (process_regex (s,
+ seq_accessor_regex,
+ accessor_regex,
+ L"sequence accessor")),
+ name_set_,
+ false);
+
+ mn = find_name (
+ escape (process_regex (s,
+ seq_modifier_regex,
+ modifier_regex,
+ L"sequence modifier")),
+ name_set_,
+ false);
+ }
+ else if (min == 0)
+ {
+ an = find_name (
+ escape (process_regex (s,
+ opt_accessor_regex,
+ accessor_regex,
+ L"optional accessor")),
+ name_set_,
+ false);
+
+ mn = find_name (
+ escape (process_regex (s,
+ opt_modifier_regex,
+ modifier_regex,
+ L"optional modifier")),
+ name_set_,
+ false);
+ }
+ else
+ {
+ an = find_name (
+ escape (process_regex (s,
+ one_accessor_regex,
+ accessor_regex,
+ L"one accessor")),
+ name_set_,
+ false);
+
+ mn = find_name (
+ escape (process_regex (s,
+ one_modifier_regex,
+ modifier_regex,
+ L"one modifier")),
+ name_set_,
+ false);
+ }
+
+ a.context ().set ("aname", an);
+ a.context ().set ("mname", mn);
+
+ name_set_.insert (b);
+
+ if (an != b)
+ name_set_.insert (an);
+
+ if (mn != b && mn != an)
+ name_set_.insert (mn);
+
+ // Types
+ //
+ if (max != 1)
+ {
+ a.context ().set (
+ "container",
+ find_name (
+ escape (process_regex (s + L",sequence", type_regex, L"type")),
+ name_set_));
+
+ a.context ().set (
+ "iterator",
+ find_name (
+ escape (process_regex (s + L",iterator", type_regex, L"type")),
+ name_set_));
+
+ a.context ().set (
+ "const-iterator",
+ find_name (
+ escape (
+ process_regex (s + L",const,iterator", type_regex, L"type")),
+ name_set_));
+ }
+ else if (min == 0)
+ {
+ a.context ().set (
+ "container",
+ find_name (
+ escape (process_regex (s + L",optional", type_regex, L"type")),
+ name_set_));
+ }
+
+ // Data member.
+ //
+ a.context ().set ("member", find_name (b + L"_", name_set_));
+
+ if (!has_wildcard_)
+ has_wildcard_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute& a)
+ {
+ String s (find_name (L"any,attribute", stem_set_));
+
+ String b (find_name (escape (s), name_set_, false));
+ a.context ().set ("name", b);
+
+ // Accessors/modifiers. Note that we postpone inserting the
+ // names into the name_set to avoid over-escaping.
+ //
+ String an (
+ find_name (
+ escape (process_regex (s, accessor_regex, L"accessor")),
+ name_set_,
+ false));
+
+ String mn (
+ find_name (
+ escape (process_regex (s, modifier_regex, L"modifier")),
+ name_set_,
+ false));
+
+ a.context ().set ("aname", an);
+ a.context ().set ("mname", mn);
+
+ name_set_.insert (b);
+
+ if (an != b)
+ name_set_.insert (an);
+
+ if (mn != b && mn != an)
+ name_set_.insert (mn);
+
+ // Types
+ //
+ a.context ().set (
+ "container",
+ find_name (
+ escape (process_regex (s + L",set", type_regex, L"type")),
+ name_set_));
+
+ a.context ().set (
+ "iterator",
+ find_name (
+ escape (process_regex (s + L",iterator", type_regex, L"type")),
+ name_set_));
+
+ a.context ().set (
+ "const-iterator",
+ find_name (
+ escape (
+ process_regex (s + L",const,iterator", type_regex, L"type")),
+ name_set_));
+
+ // Data member.
+ //
+ a.context ().set ("member", find_name (b + L"_", name_set_));
+
+ if (!has_wildcard_)
+ has_wildcard_ = true;
+ }
+
+ private:
+ NameSet& name_set_;
+ NameSet& stem_set_;
+ Boolean& has_wildcard_;
+ };
+
+ //
+ //
+ struct Complex: Traversal::Complex, Context
+ {
+ Complex (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ SemanticGraph::Context& cc (c.context ());
+
+ // Use processed name.
+ //
+ String name (cc.get<String> ("name"));
+
+ // If renamed name is empty then we are not generating
+ // anything for this type and name processing is not
+ // required.
+ //
+ if (renamed_type (c, name) && !name)
+ return;
+
+ // We leave this set around to allow other mappings to use
+ // this information.
+ //
+ cc.set ("cxx-tree-name-processor-stem-set", NameSet ());
+ cc.set ("cxx-tree-name-processor-member-set", NameSet ());
+
+ NameSet& stem_set (
+ cc.get<NameSet> ("cxx-tree-name-processor-stem-set"));
+
+ NameSet& member_set (
+ cc.get<NameSet> ("cxx-tree-name-processor-member-set"));
+
+ stem_set.insert (c.name ());
+ member_set.insert (name);
+
+ // Add our base's stems and members to the initial list.
+ //
+ 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-tree-name-processor-member-set"))
+ {
+ dispatch (base);
+ }
+
+ NameSet const& base_stem_set (
+ base.context ().get<NameSet> (
+ "cxx-tree-name-processor-stem-set"));
+
+ stem_set.insert (base_stem_set.begin (), base_stem_set.end ());
+
+ NameSet const& base_member_set (
+ base.context ().get<NameSet> (
+ "cxx-tree-name-processor-member-set"));
+
+ member_set.insert (base_member_set.begin (),
+ base_member_set.end ());
+ }
+ }
+
+ // First assign the "primary" names.
+ //
+ {
+ PrimaryMember member (*this, member_set, stem_set);
+ Traversal::Names names (member);
+
+ Complex::names (c, names);
+ }
+
+ // Derived names for members.
+ //
+ {
+ DerivedMember member (*this, member_set);
+ Traversal::Names names (member);
+
+ Complex::names (c, names);
+ }
+
+ // Names for wildcards.
+ //
+ if (options.value<CLI::generate_wildcard> ())
+ {
+ Boolean has_wildcard (false);
+ Any any (*this, member_set, stem_set, has_wildcard);
+ Traversal::Names names (any);
+ Complex::names (c, names);
+
+ // Assign names for dom_document.
+ //
+ if (has_wildcard)
+ {
+ // Check if we already have dom_document down inheritance
+ // hierarchy.
+ //
+ for (SemanticGraph::Complex* p (&c); p->inherits_p ();)
+ {
+ if (SemanticGraph::Complex* base =
+ dynamic_cast<SemanticGraph::Complex*> (
+ &p->inherits ().base ()))
+ {
+ if (base->context ().count ("dom-document"))
+ {
+ c.context ().set (
+ "dom-document",
+ base->context ().get<String> ("dom-document"));
+ break;
+ }
+
+ p = base;
+ }
+ else
+ break;
+ }
+
+ // If not, set up the names.
+ //
+ if (!c.context ().count ("dom-document"))
+ {
+ String stem (find_name (L"dom,document", stem_set));
+
+ String an (
+ escape (
+ process_regex (stem, accessor_regex, L"accessor")));
+
+ c.context ().set ("dom-document", find_name (an, member_set));
+
+ c.context ().set (
+ "dom-document-member",
+ find_name (escape (stem + L"_"), member_set));
+ }
+ }
+ }
+ }
+ };
+
+
+ //
+ //
+ struct GlobalType: Traversal::Type, Context
+ {
+ GlobalType (Context& c, NameSet& set)
+ : Context (c), set_ (set)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& t)
+ {
+ // Process the name with type name regex.
+ //
+ String name (process_regex (
+ namespace_ (t).name (),
+ t.name (),
+ type_regex,
+ L"type"));
+
+ // Escape and unclash.
+ //
+ name = find_name (escape (name), set_);
+ t.context ().set ("name", name);
+
+ // Also add renamed name if any.
+ //
+ if (renamed_type (t, name) && name)
+ set_.insert (name);
+ }
+
+ private:
+ NameSet& set_;
+ };
+
+
+ //
+ //
+ struct GlobalElement: Traversal::Element,
+ GlobalElementBase,
+ Context
+ {
+ GlobalElement (Context& c,
+ NameSet const& type_set,
+ NameSet& element_set)
+ : GlobalElementBase (c),
+ Context (c),
+ type_set_ (type_set),
+ element_set_ (element_set)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ // First we need to figure out if we need to process this
+ // global element.
+ //
+ if (!generate_p (e))
+ return;
+
+ if (options.value<CLI::generate_element_type> ())
+ {
+ SemanticGraph::Context& ec (e.context ());
+
+ String name;
+
+ if (doc_root_p (e))
+ {
+ name = find_name (
+ escape (
+ process_regex (
+ namespace_ (e).name (),
+ e.name (),
+ element_type_regex,
+ type_regex,
+ L"element type")));
+
+ // Assign inner names.
+ //
+ NameSet set;
+ set.insert (name);
+
+ ec.set (
+ "type",
+ Context::find_name (
+ escape (process_regex (L"value,type", type_regex, L"type")),
+ set));
+
+ ec.set (
+ "traits",
+ Context::find_name (
+ escape (process_regex (L"value,traits", type_regex, L"type")),
+ set));
+
+ String an = Context::find_name (
+ escape (process_regex ("value",
+ one_accessor_regex,
+ accessor_regex,
+ L"one accessor")),
+ set,
+ false);
+
+ String mn = Context::find_name (
+ escape (process_regex ("value",
+ one_modifier_regex,
+ modifier_regex,
+ L"one modifier")),
+ set,
+ false);
+
+ ec.set ("aname", an);
+ ec.set ("mname", mn);
+
+ set.insert (an);
+
+ if (an != mn)
+ set.insert (mn);
+
+ // Assign name() and namespace_() names.
+ //
+ ec.set (
+ "element-name",
+ Context::find_name (
+ escape (
+ process_regex ("name", accessor_regex, L"modifier")),
+ set));
+
+ ec.set (
+ "element-ns",
+ Context::find_name (
+ escape (
+ process_regex ("namespace", accessor_regex, L"modifier")),
+ set));
+
+ // Data members.
+ //
+ ec.set ("member", Context::find_name ("value_", set));
+ ec.set ("element-name-member",
+ Context::find_name ("name_", set));
+ ec.set ("element-ns-member",
+ Context::find_name ("namespace__", set));
+ }
+ else
+ name = find_name (escape (e.name ()));
+
+ ec.set ("name", name);
+ element_set_.insert (name);
+ }
+ else
+ {
+ // Make sure the name is unique among global elements and
+ // does not collide with a global type name.
+ //
+ String base (find_name (escape (e.name ())));
+ e.context ().set ("name", base);
+
+ String n (e.name ());
+
+ // Assign the parsing function name.
+ //
+ String p;
+
+ if (!options.value<CLI::suppress_parsing> () && doc_root_p (e))
+ {
+ p = find_name (
+ escape (
+ process_regex (n, parser_regex, L"parsing function")));
+
+ e.context ().set ("parser", p);
+ }
+
+ // Assign the serialization function name.
+ //
+ String s;
+
+ if (options.value<CLI::generate_serialization> () &&
+ doc_root_p (e))
+ {
+ s = find_name (
+ escape (
+ process_regex (
+ n, serializer_regex, L"serialization function")));
+
+ e.context ().set ("serializer", s);
+ }
+
+ // Add the names to the set only after processing parsing and
+ // serialization function names so that we do not over-escape
+ // them.
+ //
+ element_set_.insert (base);
+
+ if (p && p != base)
+ element_set_.insert (p);
+
+ if (s && s != base && s != p)
+ element_set_.insert (s);
+ }
+ }
+
+ private:
+ String
+ find_name (String const& name)
+ {
+ String r (name);
+
+ // If we are conflicting with a type name let's first try to
+ // simply append an underscore and only resort to ugly names
+ // like name1, etc., if this fails.
+ //
+ if (type_set_.find (r) != type_set_.end ())
+ r += L"_";
+
+ for (UnsignedLong i (1);
+ element_set_.find (r) != element_set_.end () ||
+ type_set_.find (r) != type_set_.end (); ++i)
+ {
+ std::wostringstream os;
+ os << i;
+ r = name + os.str ();
+ }
+
+ return r;
+ }
+
+ private:
+ NameSet const& type_set_;
+ NameSet& element_set_;
+ };
+
+ struct NamespacePassOne: Traversal::Namespace, Context
+ {
+ NamespacePassOne (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& ns)
+ {
+ NameSet& type_set (global_type_names[ns.name ()]);
+
+ GlobalType type (*this, type_set);
+ Traversal::Names names (type);
+
+ Traversal::Namespace::names (ns, names);
+ Traversal::Namespace::names (ns);
+ }
+ };
+
+
+ struct NamespacePassThree: Traversal::Namespace, Context
+ {
+ NamespacePassThree (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& ns)
+ {
+ String const& name (ns.name ());
+
+ NameSet const& type_set (global_type_names[name]);
+ NameSet& element_set (global_element_names[name]);
+
+ GlobalElement element (*this, type_set, element_set);
+ Traversal::Names names (element);
+
+ Traversal::Namespace::names (ns, names);
+ }
+ };
+
+
+ struct FundamentalNamespace : Traversal::Namespace,
+
+ 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::Id,
+ Traversal::Fundamental::IdRef,
+ Traversal::Fundamental::IdRefs,
+
+ Traversal::Fundamental::AnyURI,
+
+ Traversal::Fundamental::QName,
+
+ 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
+ {
+ FundamentalNamespace (Context& c)
+ : Context (c)
+ {
+ *this >> names_ >> *this;
+ }
+
+ Void
+ process_name (SemanticGraph::Type& t, String const& name)
+ {
+ String r (
+ process_regex (
+ namespace_ (t).name (), name, type_regex, L"type"));
+
+ t.context ().set ("name", escape (r));
+ }
+
+ Void
+ process_name (SemanticGraph::Namespace& n,
+ String const& name,
+ Char const* key)
+ {
+ String r (process_regex (name, type_regex, L"type"));
+ n.context ().set (key, escape (r));
+ }
+
+ // anyType and anySimpleType
+ //
+ virtual Void
+ traverse (SemanticGraph::AnyType& t)
+ {
+ process_name (t, "type");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnySimpleType& t)
+ {
+ process_name (t, "simple,type");
+ }
+
+ // Integrals.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Byte& t)
+ {
+ process_name (t, "byte");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedByte& t)
+ {
+ process_name (t, "unsigned,byte");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Short& t)
+ {
+ process_name (t, "short");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedShort& t)
+ {
+ process_name (t, "unsigned,short");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Int& t)
+ {
+ process_name (t, "int");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedInt& t)
+ {
+ process_name (t, "unsigned,int");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Long& t)
+ {
+ process_name (t, "long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::UnsignedLong& t)
+ {
+ process_name (t, "unsigned,long");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Integer& t)
+ {
+ process_name (t, "integer");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonPositiveInteger& t)
+ {
+ process_name (t, "non,positive,integer");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NonNegativeInteger& t)
+ {
+ process_name (t, "non,negative,integer");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::PositiveInteger& t)
+ {
+ process_name (t, "positive,integer");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NegativeInteger& t)
+ {
+ process_name (t, "negative,integer");
+ }
+
+ // Boolean.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Boolean& t)
+ {
+ process_name (t, "boolean");
+ }
+
+ // Floats.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Float& t)
+ {
+ process_name (t, "float");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Double& t)
+ {
+ process_name (t, "double");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Decimal& t)
+ {
+ process_name (t, "decimal");
+ }
+
+ // Strings.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::String& t)
+ {
+ process_name (t, "string");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NormalizedString& t)
+ {
+ process_name (t, "normalized,string");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Token& t)
+ {
+ process_name (t, "token");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameToken& t)
+ {
+ process_name (t, "nmtoken");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NameTokens& t)
+ {
+ process_name (t, "nmtokens");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Name& t)
+ {
+ process_name (t, "name");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::NCName& t)
+ {
+ process_name (t, "ncname");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Language& t)
+ {
+ process_name (t, "language");
+ }
+
+ // ID/IDREF.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Id& t)
+ {
+ process_name (t, "id");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRef& t)
+ {
+ process_name (t, "idref");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::IdRefs& t)
+ {
+ process_name (t, "idrefs");
+ }
+
+
+ // URI.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::AnyURI& t)
+ {
+ process_name (t, "uri");
+ }
+
+ // Qualified name.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::QName& t)
+ {
+ process_name (t, "qname");
+ }
+
+ // Binary.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Base64Binary& t)
+ {
+ process_name (t, "base64,binary");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::HexBinary& t)
+ {
+ process_name (t, "hex,binary");
+ }
+
+
+ // Date/time.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Date& t)
+ {
+ process_name (t, "date");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::DateTime& t)
+ {
+ process_name (t, "date,time");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Duration& t)
+ {
+ process_name (t, "duration");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Day& t)
+ {
+ process_name (t, "gday");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Month& t)
+ {
+ process_name (t, "gmonth");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::MonthDay& t)
+ {
+ process_name (t, "gmonth,day");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Year& t)
+ {
+ process_name (t, "gyear");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::YearMonth& t)
+ {
+ process_name (t, "gyear,month");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Time& t)
+ {
+ process_name (t, "time");
+ }
+
+ // Entity.
+ //
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entity& t)
+ {
+ process_name (t, "entity");
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Entities& t)
+ {
+ process_name (t, "entities");
+ }
+
+ virtual Void
+ post (SemanticGraph::Namespace& n)
+ {
+ // Assign names to extra stuff in the XML Schema namespace.
+ //
+ process_name (n, "container", "container");
+ process_name (n, "buffer", "buffer");
+ process_name (n, "time,zone", "time-zone");
+
+ if (options.value<CLI::generate_element_type> ())
+ process_name (n, "element,type", "element-type");
+
+ if (options.value<CLI::generate_element_map> ())
+ process_name (n, "element,map", "element-map");
+
+ if (options.value<CLI::generate_serialization> ())
+ {
+ process_name (n, "namespace,info", "namespace-info");
+ process_name (n, "namespace,infomap", "namespace-infomap");
+ process_name (n, "list,stream", "list-stream");
+ process_name (n, "as,double", "as-double");
+ process_name (n, "as,decimal", "as-decimal");
+ process_name (n, "facet", "facet");
+ }
+
+ if (!options.value<CLI::generate_insertion> ().empty ())
+ {
+ process_name (n, "ostream", "ostream");
+ }
+
+ if (!options.value<CLI::generate_extraction> ().empty ())
+ {
+ process_name (n, "istream", "istream");
+ }
+
+ process_name (n, "flags", "flags");
+ process_name (n, "properties", "properties");
+
+ NarrowString fn (options.value<CLI::function_naming> ());
+
+ if (fn == "knr")
+ n.context ().set ("tree-node-key", String ("tree_node_key"));
+ else
+ n.context ().set ("tree-node-key", String ("treeNodeKey"));
+
+ process_name (n, "exception", "exception");
+ process_name (n, "parsing", "parsing");
+ process_name (n, "expected,element", "expected-element");
+ process_name (n, "unexpected,element", "unexpected-element");
+ process_name (n, "expected,attribute", "expected-attribute");
+ process_name (n, "unexpected,enumerator", "unexpected-enumerator");
+ process_name (n, "expected,text,content", "expected-text-content");
+ process_name (n, "no,type,info", "no-type-info");
+ process_name (n, "no,element,info", "no-element-info");
+ process_name (n, "not,derived", "not-derived");
+ process_name (n, "duplicate,id", "duplicate-id");
+ process_name (n, "serialization", "serialization");
+ process_name (n, "no,namespace,mapping", "no-namespace-mapping");
+ process_name (n, "no,prefix,mapping", "no-prefix-mapping");
+ process_name (n, "xsi,already,in,use", "xsi-already-in-use");
+ process_name (n, "bounds", "bounds");
+
+ process_name (n, "severity", "severity");
+ process_name (n, "error", "error");
+ process_name (n, "diagnostics", "diagnostics");
+
+ if (!options.value<CLI::suppress_parsing> () ||
+ options.value<CLI::generate_serialization> ())
+ {
+ process_name (n, "error,handler", "error-handler");
+ }
+
+ Namespace::post (n);
+ }
+
+ private:
+ Traversal::Names names_;
+ };
+
+
+ // Go into sourced/included/imported schemas while making sure
+ // we don't process the same stuff more than once.
+ //
+ struct UsesPassOne: Traversal::Uses
+ {
+ virtual Void
+ traverse (Type& u)
+ {
+ SemanticGraph::Schema& s (u.schema ());
+
+ if (!s.context ().count ("cxx-tree-name-processor-pass-1"))
+ {
+ s.context ().set ("cxx-tree-name-processor-pass-1", true);
+ Traversal::Uses::traverse (u);
+ }
+ }
+ };
+
+ struct UsesPassThree: Traversal::Uses
+ {
+ virtual Void
+ traverse (Type& u)
+ {
+ SemanticGraph::Schema& s (u.schema ());
+
+ if (!s.context ().count ("cxx-tree-name-processor-pass-3"))
+ {
+ s.context ().set ("cxx-tree-name-processor-pass-3", true);
+ Traversal::Uses::traverse (u);
+ }
+ }
+ };
+
+ // 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-tree-name-processor-seen"))
+ {
+ s.context ().set ("cxx-tree-name-processor-seen", true);
+ Traversal::Implies::traverse (i);
+ }
+ }
+ };
+
+ Boolean
+ process_impl (CLI::Options const& ops,
+ SemanticGraph::Schema& tu,
+ SemanticGraph::Path const& file)
+ {
+ try
+ {
+ Counts counts;
+ Context ctx (ops, counts, false, tu, file);
+
+ if (tu.names_begin ()->named ().name () ==
+ L"http://www.w3.org/2001/XMLSchema")
+ {
+ // XML Schema namespace.
+ //
+ Traversal::Schema xs_schema;
+ Traversal::Names xs_schema_names;
+ FundamentalNamespace xs_ns (ctx);
+
+ xs_schema >> xs_schema_names >> xs_ns;
+
+ xs_schema.dispatch (tu);
+ }
+ else
+ {
+
+ // 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 ("cxx-tree-name-processor-pass-1"))
+ {
+ Traversal::Schema schema;
+ Traversal::Schema xs_schema;
+ UsesPassOne uses;
+ Implies implies;
+
+ schema >> uses >> schema;
+ schema >> implies >> xs_schema;
+
+ Traversal::Names schema_names;
+ Traversal::Names xs_schema_names;
+ NamespacePassOne ns (ctx);
+ FundamentalNamespace xs_ns (ctx);
+
+ schema >> schema_names >> ns;
+ xs_schema >> xs_schema_names >> xs_ns;
+
+ // Some twisted schemas do recusive self-inclusion.
+ //
+ tu.context ().set ("cxx-tree-name-processor-pass-1", 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;
+
+ Complex complex (ctx);
+ Traversal::Enumeration enumeration; // Avoid fallback on complex.
+
+ ns_names >> complex;
+ ns_names >> enumeration;
+
+ schema.dispatch (tu);
+ }
+
+ // Pass three - assign names to global elements as well as
+ // inside enums. 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-tree-name-processor-pass-3"))
+ {
+ Traversal::Schema schema;
+ UsesPassThree uses;
+
+ schema >> uses >> schema;
+
+ Traversal::Names schema_names;
+ NamespacePassThree ns (ctx);
+ Traversal::Namespace ns_enum;
+
+ schema >> schema_names;
+
+ schema_names >> ns;
+ schema_names >> ns_enum;
+
+ Traversal::Names ns_names;
+ Enumeration enumeration (ctx);
+
+ ns_enum >> ns_names >> enumeration;
+
+ // Some twisted schemas do recusive self-inclusion.
+ //
+ tu.context ().set ("cxx-tree-name-processor-pass-3", true);
+
+ schema.dispatch (tu);
+ }
+ }
+ }
+ catch (Context::Failed const&)
+ {
+ // Diagnostics has already been issued.
+ //
+ return false;
+ }
+
+ return true;
+ }
+ }
+
+ Boolean NameProcessor::
+ process (CLI::Options const& ops,
+ SemanticGraph::Schema& tu,
+ SemanticGraph::Path const& file)
+ {
+ return process_impl (ops, tu, file);
+ }
+ }
+}
diff --git a/xsd/cxx/tree/name-processor.hxx b/xsd/cxx/tree/name-processor.hxx
new file mode 100644
index 0000000..9b8eac9
--- /dev/null
+++ b/xsd/cxx/tree/name-processor.hxx
@@ -0,0 +1,34 @@
+// file : xsd/cxx/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_TREE_NAME_PROCESSOR_HXX
+#define CXX_TREE_NAME_PROCESSOR_HXX
+
+#include <cult/types.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+
+#include <cxx/tree/cli.hxx>
+
+namespace CXX
+{
+ namespace Tree
+ {
+ using namespace Cult::Types;
+
+ class NameProcessor
+ {
+ public:
+ NameProcessor (); // Dummy ctor, helps with long symbols on HP-UX.
+
+ Boolean
+ process (CLI::Options const&,
+ XSDFrontend::SemanticGraph::Schema&,
+ XSDFrontend::SemanticGraph::Path const& file);
+ };
+ }
+}
+
+#endif // CXX_TREE_NAME_PROCESSOR_HXX
diff --git a/xsd/cxx/tree/parser-header.cxx b/xsd/cxx/tree/parser-header.cxx
new file mode 100644
index 0000000..bf49821
--- /dev/null
+++ b/xsd/cxx/tree/parser-header.cxx
@@ -0,0 +1,474 @@
+// file : xsd/cxx/tree/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/tree/parser-header.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Tree
+ {
+ namespace
+ {
+ struct ElementFunction : Traversal::Element,
+ GlobalElementBase,
+ protected virtual Context
+ {
+ ElementFunction (Context& c)
+ : Context (c), GlobalElementBase (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (!doc_root_p (e))
+ return;
+
+ String const& name (eparser (e));
+ String const& error_handler (error_handler_type);
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @name Parsing functions for the %" <<
+ comment (e.name ()) << " document root." << endl;
+
+ if (e.annotated ())
+ {
+ os << " *" << endl;
+ write_annotation (e.annotation ());
+ }
+
+ os << " */" << endl
+ << "//@{" << endl
+ << endl;
+ }
+
+ if (!doxygen)
+ {
+ os << "// Parse a URI or a local file." << endl
+ << "//" << endl
+ << endl;
+ }
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Parse a URI or a local file." << endl
+ << " *" << endl
+ << " * @param uri A URI or a local file name." << endl
+ << " * @param f Parsing flags." << endl
+ << " * @param p Parsing properties. " << endl
+ << " * @return A pointer to the root of the object model." << endl
+ << " *" << endl
+ << " * This function uses exceptions to report parsing errors." << endl
+ << " */" << endl;
+ }
+
+ os << inst_exp
+ << "::std::auto_ptr< " << type_name (e) << " >" << endl
+ << name << " (const " << string_type << "& uri," << endl
+ << flags_type << " f = 0," << endl
+ << "const " << properties_type << "& p = " << properties_type << " ());"
+ << endl;
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Parse a URI or a local file with an error handler." << endl
+ << " *" << endl
+ << " * @param uri A URI or a local file name." << endl
+ << " * @param eh An error handler." << endl
+ << " * @param f Parsing flags." << endl
+ << " * @param p Parsing properties. " << endl
+ << " * @return A pointer to the root of the object model." << endl
+ << " *" << endl
+ << " * This function reports parsing errors by calling the " <<
+ "error handler." << endl
+ << " */" << endl;
+ }
+
+ os << inst_exp
+ << "::std::auto_ptr< " << type_name (e) << " >" << endl
+ << name << " (const " << string_type << "& uri," << endl
+ << error_handler << "& eh," << endl
+ << flags_type << " f = 0," << endl
+ << "const " << properties_type << "& p = " << properties_type << " ());"
+ << endl;
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Parse a URI or a local file with a Xerces-C++ " <<
+ "DOM error" << endl
+ << " * handler." << endl
+ << " *" << endl
+ << " * @param uri A URI or a local file name." << endl
+ << " * @param eh A Xerces-C++ DOM error handler." << endl
+ << " * @param f Parsing flags." << endl
+ << " * @param p Parsing properties. " << endl
+ << " * @return A pointer to the root of the object model." << endl
+ << " *" << endl
+ << " * This function reports parsing errors by calling the " <<
+ "error handler." << endl
+ << " */" << endl;
+ }
+
+ os << inst_exp
+ << "::std::auto_ptr< " << type_name (e) << " >" << endl
+ << name << " (const " << string_type << "& uri," << endl
+ << xerces_ns << "::DOMErrorHandler& eh," << endl
+ << flags_type << " f = 0," << endl
+ << "const " << properties_type << "& p = " << properties_type << " ());"
+ << endl;
+
+ if (!doxygen)
+ {
+ os << "// Parse std::istream." << endl
+ << "//" << endl
+ << endl;
+ }
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Parse a standard input stream." << endl
+ << " *" << endl
+ << " * @param is A standrad input stream." << endl
+ << " * @param f Parsing flags." << endl
+ << " * @param p Parsing properties. " << endl
+ << " * @return A pointer to the root of the object model." << endl
+ << " *" << endl
+ << " * This function uses exceptions to report parsing errors." << endl
+ << " */" << endl;
+ }
+
+ os << inst_exp
+ << "::std::auto_ptr< " << type_name (e) << " >" << endl
+ << name << " (::std::istream& is," << endl
+ << flags_type << " f = 0," << endl
+ << "const " << properties_type << "& p = " << properties_type << " ());"
+ << endl;
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Parse a standard input stream with an error handler." << endl
+ << " *" << endl
+ << " * @param is A standrad input stream." << endl
+ << " * @param eh An error handler." << endl
+ << " * @param f Parsing flags." << endl
+ << " * @param p Parsing properties. " << endl
+ << " * @return A pointer to the root of the object model." << endl
+ << " *" << endl
+ << " * This function reports parsing errors by calling the " <<
+ "error handler." << endl
+ << " */" << endl;
+ }
+
+ os << inst_exp
+ << "::std::auto_ptr< " << type_name (e) << " >" << endl
+ << name << " (::std::istream& is," << endl
+ << error_handler << "& eh," << endl
+ << flags_type << " f = 0," << endl
+ << "const " << properties_type << "& p = " << properties_type << " ());"
+ << endl;
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Parse a standard input stream with a " <<
+ "Xerces-C++ DOM error" << endl
+ << " * handler." << endl
+ << " *" << endl
+ << " * @param is A standrad input stream." << endl
+ << " * @param eh A Xerces-C++ DOM error handler." << endl
+ << " * @param f Parsing flags." << endl
+ << " * @param p Parsing properties. " << endl
+ << " * @return A pointer to the root of the object model." << endl
+ << " *" << endl
+ << " * This function reports parsing errors by calling the " <<
+ "error handler." << endl
+ << " */" << endl;
+ }
+
+ os << inst_exp
+ << "::std::auto_ptr< " << type_name (e) << " >" << endl
+ << name << " (::std::istream& is," << endl
+ << xerces_ns << "::DOMErrorHandler& eh," << endl
+ << flags_type << " f = 0," << endl
+ << "const " << properties_type << "& p = " << properties_type << " ());"
+ << endl;
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Parse a standard input stream with a resource id." << endl
+ << " *" << endl
+ << " * @param is A standrad input stream." << endl
+ << " * @param id A resource id." << endl
+ << " * @param f Parsing flags." << endl
+ << " * @param p Parsing properties. " << endl
+ << " * @return A pointer to the root of the object model." << endl
+ << " *" << endl
+ << " * The resource id is used to identify the document " <<
+ "being parsed in" << endl
+ << " * diagnostics as well as to resolve relative paths." << endl
+ << " *" << endl
+ << " * This function uses exceptions to report parsing errors." << endl
+ << " */" << endl;
+ }
+
+ os << inst_exp
+ << "::std::auto_ptr< " << type_name (e) << " >" << endl
+ << name << " (::std::istream& is," << endl
+ << "const " << string_type << "& id," << endl
+ << flags_type << " f = 0," << endl
+ << "const " << properties_type << "& p = " << properties_type << " ());"
+ << endl;
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Parse a standard input stream with a resource " <<
+ "id and an" << endl
+ << " * error handler." << endl
+ << " *" << endl
+ << " * @param is A standrad input stream." << endl
+ << " * @param id A resource id." << endl
+ << " * @param eh An error handler." << endl
+ << " * @param f Parsing flags." << endl
+ << " * @param p Parsing properties. " << endl
+ << " * @return A pointer to the root of the object model." << endl
+ << " *" << endl
+ << " * The resource id is used to identify the document " <<
+ "being parsed in" << endl
+ << " * diagnostics as well as to resolve relative paths." << endl
+ << " *" << endl
+ << " * This function reports parsing errors by calling the " <<
+ "error handler." << endl
+ << " */" << endl;
+ }
+
+ os << inst_exp
+ << "::std::auto_ptr< " << type_name (e) << " >" << endl
+ << name << " (::std::istream& is," << endl
+ << "const " << string_type << "& id," << endl
+ << error_handler << "& eh," << endl
+ << flags_type << " f = 0," << endl
+ << "const " << properties_type << "& p = " << properties_type << " ());"
+ << endl;
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Parse a standard input stream with a resource " <<
+ "id and a" << endl
+ << " * Xerces-C++ DOM error handler." << endl
+ << " *" << endl
+ << " * @param is A standrad input stream." << endl
+ << " * @param id A resource id." << endl
+ << " * @param eh A Xerces-C++ DOM error handler." << endl
+ << " * @param f Parsing flags." << endl
+ << " * @param p Parsing properties. " << endl
+ << " * @return A pointer to the root of the object model." << endl
+ << " *" << endl
+ << " * The resource id is used to identify the document " <<
+ "being parsed in" << endl
+ << " * diagnostics as well as to resolve relative paths." << endl
+ << " *" << endl
+ << " * This function reports parsing errors by calling the " <<
+ "error handler." << endl
+ << " */" << endl;
+ }
+
+ os << inst_exp
+ << "::std::auto_ptr< " << type_name (e) << " >" << endl
+ << name << " (::std::istream& is," << endl
+ << "const " << string_type << "& id," << endl
+ << xerces_ns << "::DOMErrorHandler& eh," << endl
+ << flags_type << " f = 0," << endl
+ << "const " << properties_type << "& p = " << properties_type << " ());"
+ << endl;
+
+ if (!doxygen)
+ {
+ os << "// Parse xercesc::InputSource." << endl
+ << "//" << endl
+ << endl;
+ }
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Parse a Xerces-C++ input source." << endl
+ << " *" << endl
+ << " * @param is A Xerces-C++ input source." << endl
+ << " * @param f Parsing flags." << endl
+ << " * @param p Parsing properties. " << endl
+ << " * @return A pointer to the root of the object model." << endl
+ << " *" << endl
+ << " * This function uses exceptions to report parsing errors." << endl
+ << " */" << endl;
+ }
+
+ os << inst_exp
+ << "::std::auto_ptr< " << type_name (e) << " >" << endl
+ << name << " (" << xerces_ns << "::InputSource& is," << endl
+ << flags_type << " f = 0," << endl
+ << "const " << properties_type << "& p = " << properties_type << " ());"
+ << endl;
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Parse a Xerces-C++ input source with an " <<
+ "error handler." << endl
+ << " *" << endl
+ << " * @param is A Xerces-C++ input source." << endl
+ << " * @param eh An error handler." << endl
+ << " * @param f Parsing flags." << endl
+ << " * @param p Parsing properties. " << endl
+ << " * @return A pointer to the root of the object model." << endl
+ << " *" << endl
+ << " * This function reports parsing errors by calling the " <<
+ "error handler." << endl
+ << " */" << endl;
+ }
+
+ os << inst_exp
+ << "::std::auto_ptr< " << type_name (e) << " >" << endl
+ << name << " (" << xerces_ns << "::InputSource& is," << endl
+ << error_handler << "& eh," << endl
+ << flags_type << " f = 0," << endl
+ << "const " << properties_type << "& p = " << properties_type << " ());"
+ << endl;
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Parse a Xerces-C++ input source with a " <<
+ "Xerces-C++ DOM" << endl
+ << " * error handler." << endl
+ << " *" << endl
+ << " * @param is A Xerces-C++ input source." << endl
+ << " * @param eh A Xerces-C++ DOM error handler." << endl
+ << " * @param f Parsing flags." << endl
+ << " * @param p Parsing properties. " << endl
+ << " * @return A pointer to the root of the object model." << endl
+ << " *" << endl
+ << " * This function reports parsing errors by calling the " <<
+ "error handler." << endl
+ << " */" << endl;
+ }
+
+ os << inst_exp
+ << "::std::auto_ptr< " << type_name (e) << " >" << endl
+ << name << " (" << xerces_ns << "::InputSource& is," << endl
+ << xerces_ns << "::DOMErrorHandler& eh," << endl
+ << flags_type << " f = 0," << endl
+ << "const " << properties_type << "& p = " << properties_type << " ());"
+ << endl;
+
+ if (!doxygen)
+ {
+ os << "// Parse xercesc::DOMDocument." << endl
+ << "//" << endl
+ << endl;
+ }
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Parse a Xerces-C++ DOM document." << endl
+ << " *" << endl
+ << " * @param d A Xerces-C++ DOM document." << endl
+ << " * @param f Parsing flags." << endl
+ << " * @param p Parsing properties. " << endl
+ << " * @return A pointer to the root of the object model." << endl
+ << " */" << endl;
+ }
+
+ os << inst_exp
+ << "::std::auto_ptr< " << type_name (e) << " >" << endl
+ << name << " (const " << xerces_ns << "::DOMDocument& d," << endl
+ << flags_type << " f = 0," << endl
+ << "const " << properties_type << "& p = " << properties_type << " ());"
+ << endl;
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Parse a Xerces-C++ DOM document." << endl
+ << " *" << endl
+ << " * @param d A pointer to the Xerces-C++ DOM document." << endl
+ << " * @param f Parsing flags." << endl
+ << " * @param p Parsing properties. " << endl
+ << " * @return A pointer to the root of the object model." << endl
+ << " *" << endl
+ << " * This function is normally used together with the " <<
+ "keep_dom and" << endl
+ << " * own_dom parsing flags to assign ownership of the DOM " <<
+ "document" << endl
+ << " * to the object model." << endl
+ << " */" << endl;
+ }
+
+ os << inst_exp
+ << "::std::auto_ptr< " << type_name (e) << " >" << endl
+ << name << " (" << dom_auto_ptr << "< " << xerces_ns <<
+ "::DOMDocument >& d," << endl
+ << flags_type << " f = 0," << endl
+ << "const " << properties_type << "& p = " << properties_type << " ());"
+ << endl;
+
+ if (doxygen)
+ {
+ os << "//@}" << endl
+ << endl;
+ }
+ }
+
+ private:
+ String
+ type_name (Type& e)
+ {
+ std::wostringstream o;
+
+ MemberTypeName type (*this, o);
+ type.dispatch (e.type ());
+
+ return o.str ();
+ }
+ };
+ }
+
+
+ Void
+ generate_parser_header (Context& ctx)
+ {
+ ctx.os << "#include <iosfwd>" << endl
+ << endl
+ << "#include <xercesc/sax/InputSource.hpp>" << endl
+ << "#include <xercesc/dom/DOMDocument.hpp>" << endl
+ << "#include <xercesc/dom/DOMErrorHandler.hpp>" << endl
+ << endl;
+
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+ Traversal::Names names_ns, names;
+ Namespace ns (ctx);
+ ElementFunction element (ctx);
+
+ schema >> sources >> schema;
+ schema >> names_ns >> ns >> names >> element;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+}
diff --git a/xsd/cxx/tree/parser-header.hxx b/xsd/cxx/tree/parser-header.hxx
new file mode 100644
index 0000000..ff43926
--- /dev/null
+++ b/xsd/cxx/tree/parser-header.hxx
@@ -0,0 +1,23 @@
+// file : xsd/cxx/tree/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_TREE_PARSER_HEADER_HXX
+#define CXX_TREE_PARSER_HEADER_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/tree/elements.hxx>
+
+
+namespace CXX
+{
+ namespace Tree
+ {
+ Void
+ generate_parser_header (Context&);
+ }
+}
+
+#endif // CXX_TREE_PARSER_HEADER_HXX
diff --git a/xsd/cxx/tree/parser-source.cxx b/xsd/cxx/tree/parser-source.cxx
new file mode 100644
index 0000000..5c121f2
--- /dev/null
+++ b/xsd/cxx/tree/parser-source.cxx
@@ -0,0 +1,544 @@
+// file : xsd/cxx/tree/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/tree/parser-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Tree
+ {
+ namespace
+ {
+ struct ElementFunction: Traversal::Element,
+ GlobalElementBase,
+ protected virtual Context
+ {
+ ElementFunction (Context& c)
+ : Context (c), GlobalElementBase (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (!doc_root_p (e))
+ return;
+
+ String const& name (eparser (e));
+ SemanticGraph::Type& t (e.type ());
+ String type (type_name (e));
+ String const& error_handler (error_handler_type);
+
+ // Note that I am using fq-name in function calls because g++ gets
+ // confused if the name is 'type'. (see tests/schema/anonymous)
+ //
+
+ // URI.
+ //
+ os << "::std::auto_ptr< " << type << " >" << endl
+ << name << " (const " << string_type << "& u," << endl
+ << flags_type << " f," << endl
+ << "const " << properties_type << "& p)"
+ << "{"
+ << "::xsd::cxx::xml::auto_initializer i (" << endl
+ << "(f & " << flags_type << "::dont_initialize) == 0," << endl
+ << "(f & " << flags_type << "::keep_dom) == 0);"
+ << endl
+ << "::xsd::cxx::tree::error_handler< " << char_type << " > h;"
+ << endl
+ << dom_auto_ptr << "< " << xerces_ns <<
+ "::DOMDocument > d (" << endl
+ << "::xsd::cxx::xml::dom::parse< " << char_type << " > (" << endl
+ << "u, h, p, f";
+
+ if (options.value<CLI::disable_multi_import> ())
+ os << " | ::xsd::cxx::xml::dom::no_muliple_imports";
+
+ os << "));"
+ << endl
+ << "h.throw_if_failed< ::xsd::cxx::tree::parsing< " <<
+ char_type << " > > ();"
+ << endl
+ << "::std::auto_ptr< " << type << " > r (" << endl
+ << fq_name (e, "parser") << " (" << endl
+ << "d, f | " << flags_type << "::own_dom, p));"
+ << endl
+ << "return r;"
+ << "}";
+
+ os << "::std::auto_ptr< " << type << " >" << endl
+ << name << " (const " << string_type << "& u," << endl
+ << error_handler << "& h," << endl
+ << flags_type << " f," << endl
+ << "const " << properties_type << "& p)"
+ << "{"
+ << "::xsd::cxx::xml::auto_initializer i (" << endl
+ << "(f & " << flags_type << "::dont_initialize) == 0," << endl
+ << "(f & " << flags_type << "::keep_dom) == 0);"
+ << endl
+ << dom_auto_ptr << "< " << xerces_ns <<
+ "::DOMDocument > d (" << endl
+ << "::xsd::cxx::xml::dom::parse< " << char_type << " > (" << endl
+ << "u, h, p, f";
+
+ if (options.value<CLI::disable_multi_import> ())
+ os << " | ::xsd::cxx::xml::dom::no_muliple_imports";
+
+ os << "));"
+ << endl
+ << "if (!d.get ())" << endl
+ << "throw ::xsd::cxx::tree::parsing< " << char_type << " > ();"
+ << endl
+ << "::std::auto_ptr< " << type << " > r (" << endl
+ << fq_name (e, "parser") << " (" << endl
+ << "d, f | " << flags_type << "::own_dom, p));"
+ << endl
+ << "return r;"
+ << "}";
+
+ os << "::std::auto_ptr< " << type << " >" << endl
+ << name << " (const " << string_type << "& u," << endl
+ << xerces_ns << "::DOMErrorHandler& h," << endl
+ << flags_type << " f," << endl
+ << "const " << properties_type << "& p)"
+ << "{"
+ << dom_auto_ptr << "< " << xerces_ns <<
+ "::DOMDocument > d (" << endl
+ << "::xsd::cxx::xml::dom::parse< " << char_type << " > (" << endl
+ << "u, h, p, f";
+
+ if (options.value<CLI::disable_multi_import> ())
+ os << " | ::xsd::cxx::xml::dom::no_muliple_imports";
+
+ os << "));"
+ << endl
+ << "if (!d.get ())" << endl
+ << "throw ::xsd::cxx::tree::parsing< " << char_type << " > ();"
+ << endl
+ << "::std::auto_ptr< " << type << " > r (" << endl
+ << fq_name (e, "parser") << " (" << endl
+ << "d, f | " << flags_type << "::own_dom, p));"
+ << endl
+ << "return r;"
+ << "}";
+
+
+ // istream
+ //
+ os << "::std::auto_ptr< " << type << " >" << endl
+ << name << " (::std::istream& is," << endl
+ << flags_type << " f," << endl
+ << "const " << properties_type << "& p)"
+ << "{"
+ << "::xsd::cxx::xml::auto_initializer i (" << endl
+ << "(f & " << flags_type << "::dont_initialize) == 0," << endl
+ << "(f & " << flags_type << "::keep_dom) == 0);"
+ << endl
+ << "::xsd::cxx::xml::sax::std_input_source isrc (is);"
+ << "return " << fq_name (e, "parser") << " (isrc, f, p);"
+ << "}";
+
+ os << "::std::auto_ptr< " << type << " >" << endl
+ << name << " (::std::istream& is," << endl
+ << error_handler << "& h," << endl
+ << flags_type << " f," << endl
+ << "const " << properties_type << "& p)"
+ << "{"
+ << "::xsd::cxx::xml::auto_initializer i (" << endl
+ << "(f & " << flags_type << "::dont_initialize) == 0," << endl
+ << "(f & " << flags_type << "::keep_dom) == 0);"
+ << endl
+ << "::xsd::cxx::xml::sax::std_input_source isrc (is);"
+ << "return " << fq_name (e, "parser") << " (isrc, h, f, p);"
+ << "}";
+
+ os << "::std::auto_ptr< " << type << " >" << endl
+ << name << " (::std::istream& is," << endl
+ << xerces_ns << "::DOMErrorHandler& h," << endl
+ << flags_type << " f," << endl
+ << "const " << properties_type << "& p)"
+ << "{"
+ << "::xsd::cxx::xml::sax::std_input_source isrc (is);"
+ << "return " << fq_name (e, "parser") << " (isrc, h, f, p);"
+ << "}";
+
+ os << "::std::auto_ptr< " << type << " >" << endl
+ << name << " (::std::istream& is," << endl
+ << "const " << string_type << "& sid," << endl
+ << flags_type << " f," << endl
+ << "const " << properties_type << "& p)"
+ << "{"
+ << "::xsd::cxx::xml::auto_initializer i (" << endl
+ << "(f & " << flags_type << "::dont_initialize) == 0," << endl
+ << "(f & " << flags_type << "::keep_dom) == 0);"
+ << endl
+ << "::xsd::cxx::xml::sax::std_input_source isrc (is, sid);"
+ << "return " << fq_name (e, "parser") << " (isrc, f, p);"
+ << "}";
+
+ os << "::std::auto_ptr< " << type << " >" << endl
+ << name << " (::std::istream& is," << endl
+ << "const " << string_type << "& sid," << endl
+ << error_handler << "& h," << endl
+ << flags_type << " f," << endl
+ << "const " << properties_type << "& p)"
+ << "{"
+ << "::xsd::cxx::xml::auto_initializer i (" << endl
+ << "(f & " << flags_type << "::dont_initialize) == 0," << endl
+ << "(f & " << flags_type << "::keep_dom) == 0);"
+ << endl
+ << "::xsd::cxx::xml::sax::std_input_source isrc (is, sid);"
+ << "return " << fq_name (e, "parser") << " (isrc, h, f, p);"
+ << "}";
+
+ os << "::std::auto_ptr< " << type << " >" << endl
+ << name << " (::std::istream& is," << endl
+ << "const " << string_type << "& sid," << endl
+ << xerces_ns << "::DOMErrorHandler& h," << endl
+ << flags_type << " f," << endl
+ << "const " << properties_type << "& p)"
+ << "{"
+ << "::xsd::cxx::xml::sax::std_input_source isrc (is, sid);"
+ << "return " << fq_name (e, "parser") << " (isrc, h, f, p);"
+ << "}";
+
+
+ // InputSource.
+ //
+ os << "::std::auto_ptr< " << type << " >" << endl
+ << name << " (" << xerces_ns << "::InputSource& i," << endl
+ << flags_type << " f," << endl
+ << "const " << properties_type << "& p)"
+ << "{"
+ << "::xsd::cxx::tree::error_handler< " << char_type << " > h;"
+ << endl
+ << dom_auto_ptr << "< " << xerces_ns <<
+ "::DOMDocument > d (" << endl
+ << "::xsd::cxx::xml::dom::parse< " << char_type << " > (" << endl
+ << "i, h, p, f";
+
+ if (options.value<CLI::disable_multi_import> ())
+ os << " | ::xsd::cxx::xml::dom::no_muliple_imports";
+
+ os << "));"
+ << endl
+ << "h.throw_if_failed< ::xsd::cxx::tree::parsing< " <<
+ char_type << " > > ();"
+ << endl
+ << "::std::auto_ptr< " << type << " > r (" << endl
+ << fq_name (e, "parser") << " (" << endl
+ << "d, f | " << flags_type << "::own_dom, p));"
+ << endl
+ << "return r;"
+ << "}";
+
+ os << "::std::auto_ptr< " << type << " >" << endl
+ << name << " (" << xerces_ns << "::InputSource& i," << endl
+ << error_handler << "& h," << endl
+ << flags_type << " f," << endl
+ << "const " << properties_type << "& p)"
+ << "{"
+ << dom_auto_ptr << "< " << xerces_ns <<
+ "::DOMDocument > d (" << endl
+ << "::xsd::cxx::xml::dom::parse< " << char_type << " > (" << endl
+ << "i, h, p, f";
+
+ if (options.value<CLI::disable_multi_import> ())
+ os << " | ::xsd::cxx::xml::dom::no_muliple_imports";
+
+ os << "));"
+ << endl
+ << "if (!d.get ())" << endl
+ << "throw ::xsd::cxx::tree::parsing< " << char_type << " > ();"
+ << endl
+ << "::std::auto_ptr< " << type << " > r (" << endl
+ << fq_name (e, "parser") << " (" << endl
+ << "d, f | " << flags_type << "::own_dom, p));"
+ << endl
+ << "return r;"
+ << "}";
+
+
+ os << "::std::auto_ptr< " << type << " >" << endl
+ << name << " (" << xerces_ns << "::InputSource& i," << endl
+ << xerces_ns << "::DOMErrorHandler& h," << endl
+ << flags_type << " f," << endl
+ << "const " << properties_type << "& p)"
+ << "{"
+ << dom_auto_ptr << "< " << xerces_ns <<
+ "::DOMDocument > d (" << endl
+ << "::xsd::cxx::xml::dom::parse< " << char_type << " > (" << endl
+ << "i, h, p, f";
+
+ if (options.value<CLI::disable_multi_import> ())
+ os << " | ::xsd::cxx::xml::dom::no_muliple_imports";
+
+ os << "));"
+ << endl
+ << "if (!d.get ())" << endl
+ << "throw ::xsd::cxx::tree::parsing< " << char_type << " > ();"
+ << endl
+ << "::std::auto_ptr< " << type << " > r (" << endl
+ << fq_name (e, "parser") << " (" << endl
+ << "d, f | " << flags_type << "::own_dom, p));"
+ << endl
+ << "return r;"
+ << "}";
+
+
+ // DOM.
+ //
+
+ Boolean fund (false);
+
+ {
+ IsFundamentalType test (fund);
+ test.dispatch (t);
+ }
+
+ // Check if we need to handle xsi:type and substitution groups.
+ // If this element's type is anonymous or mapped to a fundamental
+ // C++ type then we don't need to do anything.
+ //
+ Boolean poly (!fund && polymorphic &&
+ !t.context ().count ("anonymous"));
+
+ // const DOMDocument&
+ //
+ os << "::std::auto_ptr< " << type << " >" << endl
+ << name << " (const " << xerces_ns << "::DOMDocument& d," << endl
+ << flags_type << " f," << endl
+ << "const " << properties_type << "& p)"
+ << "{"
+ << "if (f & " << flags_type << "::keep_dom)"
+ << "{"
+ << dom_auto_ptr << "< " << xerces_ns <<
+ "::DOMDocument > c (" << endl
+ << "static_cast< " << xerces_ns <<
+ "::DOMDocument* > (d.cloneNode (true)));"
+ << endl
+ << "::std::auto_ptr< " << type << " > r (" << endl
+ << fq_name (e, "parser") << " (" << endl
+ << "c, f | " << flags_type << "::own_dom, p));"
+ << endl
+ << "return r;"
+ << "}"
+ << "const " << xerces_ns << "::DOMElement& e (*d.getDocumentElement ());"
+ << "const " << qname_type << " n (" << endl
+ << "::xsd::cxx::xml::dom::name< " << char_type << " > (e));"
+ << endl;
+
+ if (poly)
+ {
+ // aCC cannot handle an inline call to type_factory_map_instance.
+ //
+ os << "::xsd::cxx::tree::type_factory_map< " << char_type <<
+ " >& tfm (" << endl
+ << "::xsd::cxx::tree::type_factory_map_instance< 0, " <<
+ char_type << " > ());"
+ << endl
+ << "::std::auto_ptr< ::xsd::cxx::tree::type > tmp (" << endl
+ << "tfm.create (" << endl
+ << L << strlit (e.name ()) << "," << endl
+ << L << strlit (e.namespace_().name ()) << "," << endl
+ << "&::xsd::cxx::tree::factory_impl< " << type << " >," << endl
+ << "true, true, e, n, f, 0));"
+ << endl
+ << "if (tmp.get () != 0)"
+ << "{"
+ << "::std::auto_ptr< " << type << " > r (" << endl
+ << "dynamic_cast< " << type << "* > (tmp.get ()));"
+ << endl
+ << "if (r.get ())" << endl
+ << "tmp.release ();"
+ << "else" << endl
+ << "throw ::xsd::cxx::tree::not_derived< " << char_type <<
+ " > ();"
+ << endl;
+ }
+ else
+ {
+ os << "if (n.name () == " << L << strlit (e.name ()) << " &&" << endl
+ << "n.namespace_ () == " << L << strlit (e.namespace_().name ()) << ")"
+ << "{";
+
+ if (fund)
+ {
+ os << "::std::auto_ptr< " << type << " > r (" << endl
+ << "new " << type << " (" << endl
+ << "::xsd::cxx::tree::traits< " << type << ", " <<
+ char_type;
+
+ if (t.is_a<SemanticGraph::Fundamental::Double> ())
+ os << ", ::xsd::cxx::tree::schema_type::double_";
+ else if (t.is_a<SemanticGraph::Fundamental::Decimal> ())
+ os << ", ::xsd::cxx::tree::schema_type::decimal";
+
+ os << " >::create (" << endl
+ << "e, f, 0)));";
+ }
+ else
+ {
+ os << "::std::auto_ptr< " << type << " > r (" << endl
+ << "::xsd::cxx::tree::traits< " << type << ", " <<
+ char_type << " >::create (" << endl
+ << "e, f, 0));";
+ }
+ }
+
+ os << "return r;"
+ << "}"
+ << "throw ::xsd::cxx::tree::unexpected_element < " <<
+ char_type << " > (" << endl
+ << "n.name ()," << endl
+ << "n.namespace_ ()," << endl
+ << L << strlit (e.name ()) << "," << endl
+ << L << strlit (e.namespace_().name ()) << ");"
+ << "}";
+
+
+ // dom::auto_ptr<DOMDocument>
+ //
+ os << "::std::auto_ptr< " << type << " >" << endl
+ << name << " (" << dom_auto_ptr << "< " << xerces_ns <<
+ "::DOMDocument >& d," << endl
+ << flags_type << " f," << endl
+ << "const " << properties_type << "&)"
+ << "{"
+ << dom_auto_ptr << "< " << xerces_ns <<
+ "::DOMDocument > c (" << endl
+ << "((f & " << flags_type << "::keep_dom) &&" << endl
+ << "!(f & " << flags_type << "::own_dom))" << endl
+ << "? static_cast< " << xerces_ns << "::DOMDocument* > (" <<
+ "d->cloneNode (true))" << endl
+ << ": 0);"
+ << endl
+ << xerces_ns << "::DOMDocument& doc (c.get () ? *c : *d);"
+ << "const " << xerces_ns << "::DOMElement& e (" <<
+ "*doc.getDocumentElement ());"
+ << endl
+ << "const " << qname_type << " n (" << endl
+ << "::xsd::cxx::xml::dom::name< " << char_type << " > (e));"
+ << endl
+ << "if (f & " << flags_type << "::keep_dom)" << endl
+ << "doc.setUserData (" << dom_node_key << "," << endl
+ << "(c.get () ? &c : &d)," << endl
+ << "0);"
+ << endl;
+
+ if (poly)
+ {
+ // aCC cannot handle an inline call to type_factory_map_instance.
+ //
+ os << "::xsd::cxx::tree::type_factory_map< " << char_type <<
+ " >& tfm (" << endl
+ << "::xsd::cxx::tree::type_factory_map_instance< 0, " <<
+ char_type << " > ());"
+ << endl
+ << "::std::auto_ptr< ::xsd::cxx::tree::type > tmp (" << endl
+ << "tfm.create (" << endl
+ << L << strlit (e.name ()) << "," << endl
+ << L << strlit (e.namespace_().name ()) << "," << endl
+ << "&::xsd::cxx::tree::factory_impl< " << type << " >," << endl
+ << "true, true, e, n, f, 0));"
+ << endl
+ << "if (tmp.get () != 0)"
+ << "{";
+ }
+ else
+ {
+ os << "if (n.name () == " << L << strlit (e.name ()) << " &&" << endl
+ << "n.namespace_ () == " << L << strlit (e.namespace_().name ()) << ")"
+ << "{";
+
+ if (fund)
+ {
+ os << "::std::auto_ptr< " << type << " > r (" << endl
+ << "new " << type << " (" << endl
+ << "::xsd::cxx::tree::traits< " << type << ", " <<
+ char_type;
+
+ if (t.is_a<SemanticGraph::Fundamental::Double> ())
+ os << ", ::xsd::cxx::tree::schema_type::double_";
+ else if (t.is_a<SemanticGraph::Fundamental::Decimal> ())
+ os << ", ::xsd::cxx::tree::schema_type::decimal";
+
+ os << " >::create (" << endl
+ << "e, f, 0)));";
+ }
+ else
+ {
+ os << "::std::auto_ptr< " << type << " > r (" << endl
+ << "::xsd::cxx::tree::traits< " << type << ", " <<
+ char_type << " >::create (" << endl
+ << "e, f, 0));";
+ }
+ }
+
+ if (poly)
+ {
+ os << endl
+ << "::std::auto_ptr< " << type << " > r (" << endl
+ << "dynamic_cast< " << type << "* > (tmp.get ()));"
+ << endl
+ << "if (r.get ())" << endl
+ << "tmp.release ();"
+ << "else" << endl
+ << "throw ::xsd::cxx::tree::not_derived< " << char_type <<
+ " > ();"
+ << endl;
+ }
+
+ os << "return r;"
+ << "}"
+ << "throw ::xsd::cxx::tree::unexpected_element < " <<
+ char_type << " > (" << endl
+ << "n.name ()," << endl
+ << "n.namespace_ ()," << endl
+ << L << strlit (e.name ()) << "," << endl
+ << L << strlit (e.namespace_().name ()) << ");"
+ << "}";
+ }
+
+ private:
+ String
+ type_name (Type& e)
+ {
+ std::wostringstream o;
+
+ MemberTypeName type (*this, o);
+ type.dispatch (e.type ());
+
+ return o.str ();
+ }
+ };
+ }
+
+ Void
+ generate_parser_source (Context& ctx,
+ UnsignedLong first,
+ UnsignedLong last)
+ {
+ ctx.os << "#include <istream>" << endl
+ << "#include <xsd/cxx/xml/sax/std-input-source.hxx>" << endl
+ << "#include <xsd/cxx/tree/error-handler.hxx>" << endl
+ << endl;
+
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+ Traversal::Names names_ns, names;
+ Namespace ns (ctx, first, last);
+ ElementFunction element (ctx);
+
+ schema >> sources >> schema;
+ schema >> names_ns >> ns >> names >> element;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+}
diff --git a/xsd/cxx/tree/parser-source.hxx b/xsd/cxx/tree/parser-source.hxx
new file mode 100644
index 0000000..9b0875d
--- /dev/null
+++ b/xsd/cxx/tree/parser-source.hxx
@@ -0,0 +1,24 @@
+// file : xsd/cxx/tree/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_TREE_PARSER_SOURCE_HXX
+#define CXX_TREE_PARSER_SOURCE_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/tree/elements.hxx>
+
+namespace CXX
+{
+ namespace Tree
+ {
+ Void
+ generate_parser_source (Context&,
+ UnsignedLong first,
+ UnsignedLong last);
+ }
+}
+
+#endif // CXX_TREE_PARSER_SOURCE_HXX
diff --git a/xsd/cxx/tree/serialization-header.cxx b/xsd/cxx/tree/serialization-header.cxx
new file mode 100644
index 0000000..090f0f5
--- /dev/null
+++ b/xsd/cxx/tree/serialization-header.cxx
@@ -0,0 +1,581 @@
+// file : xsd/cxx/tree/serialization-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/tree/serialization-header.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Tree
+ {
+ namespace
+ {
+ struct List: Traversal::List, protected virtual Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String name (ename (l));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (l, name) && !name)
+ return;
+
+ // operator<< (xercesc::DOMElement)
+ //
+ os << inst_exp
+ << "void" << endl
+ << "operator<< (" << xerces_ns << "::DOMElement&, " <<
+ "const " << name << "&);"
+ << endl;
+
+ // operator<< (xercesc::DOMAttr)
+ //
+ os << inst_exp
+ << "void" << endl
+ << "operator<< (" << xerces_ns << "::DOMAttr&, " <<
+ "const " << name << "&);"
+ << endl;
+
+ // operator<< (list_stream)
+ //
+ os << inst_exp
+ << "void" << endl
+ << "operator<< (" << list_stream_type << "&," << endl
+ << "const " << name << "&);"
+ << endl;
+
+ }
+ };
+
+
+ struct Union: Traversal::Union, protected virtual Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ String name (ename (u));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (u, name) && !name)
+ return;
+
+ // operator<< (xercesc::DOMElement)
+ //
+ os << inst_exp
+ << "void" << endl
+ << "operator<< (" << xerces_ns << "::DOMElement&, " <<
+ "const " << name << "&);"
+ << endl;
+
+ // operator<< (xercesc::DOMAttr)
+ //
+ os << inst_exp
+ << "void" << endl
+ << "operator<< (" << xerces_ns << "::DOMAttr&, " <<
+ "const " << name << "&);"
+ << endl;
+
+ // operator<< (list_stream)
+ //
+ os << inst_exp
+ << "void" << endl
+ << "operator<< (" << list_stream_type << "&," << endl
+ << "const " << name << "&);"
+ << endl;
+ }
+ };
+
+
+ struct Enumeration: Traversal::Enumeration, protected virtual Context
+ {
+ Enumeration (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ String name (ename (e));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (e, name) && !name)
+ return;
+
+ // operator<< (xercesc::DOMElement)
+ //
+ os << inst_exp
+ << "void" << endl
+ << "operator<< (" << xerces_ns << "::DOMElement&, " <<
+ "const " << name << "&);"
+ << endl;
+
+ // operator<< (xercesc::DOMAttr)
+ //
+ os << inst_exp
+ << "void" << endl
+ << "operator<< (" << xerces_ns << "::DOMAttr&, " <<
+ "const " << name << "&);"
+ << endl;
+
+ // operator<< (list_stream)
+ //
+ os << inst_exp
+ << "void" << endl
+ << "operator<< (" << list_stream_type << "&," << endl
+ << "const " << name << "&);"
+ << endl;
+ }
+ };
+
+ struct Complex : Traversal::Complex, protected virtual Context
+ {
+ Complex (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ String name (ename (c));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (c, name) && !name)
+ return;
+
+ // operator<< (xercesc::DOMElement)
+ //
+ os << inst_exp
+ << "void" << endl
+ << "operator<< (" << xerces_ns << "::DOMElement&, " <<
+ "const " << name << "&);"
+ << endl;
+
+ Boolean simple (true);
+ {
+ IsSimpleType t (simple);
+ t.dispatch (c);
+ }
+
+ if (simple)
+ {
+ // operator<< (xercesc::DOMAttr)
+ //
+ os << inst_exp
+ << "void" << endl
+ << "operator<< (" << xerces_ns << "::DOMAttr&, " <<
+ "const " << name << "&);"
+ << endl;
+
+ // operator<< (list_stream)
+ //
+ os << inst_exp
+ << "void" << endl
+ << "operator<< (" << list_stream_type << "&," << endl
+ << "const " << name << "&);"
+ << endl;
+ }
+ }
+ };
+
+ struct ElementType: Traversal::Element,
+ GlobalElementBase,
+ protected virtual Context
+ {
+ ElementType (Context& c)
+ : Context (c), GlobalElementBase (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (doc_root_p (e))
+ {
+ // operator<< (xercesc::DOMElement)
+ //
+ os << inst_exp
+ << "void" << endl
+ << "operator<< (" << xerces_ns << "::DOMElement&, " <<
+ "const " << ename (e) << "&);"
+ << endl;
+ }
+ }
+ };
+
+ struct ElementFunction: Traversal::Element,
+ GlobalElementBase,
+ protected virtual Context
+ {
+ ElementFunction (Context& c)
+ : Context (c), GlobalElementBase (c)
+ {
+ }
+
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (!doc_root_p (e))
+ return;
+
+ String const& name (eserializer (e));
+ String const& error_handler (error_handler_type);
+ String const& namespace_infomap (namespace_infomap_type);
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @name Serialization functions for the %" <<
+ comment (e.name ()) << " document root." << endl;
+
+ if (e.annotated ())
+ {
+ os << " *" << endl;
+ write_annotation (e.annotation ());
+ }
+
+ os << " */" << endl
+ << "//@{" << endl
+ << endl;
+ }
+
+ if (!doxygen)
+ {
+ os << "// Serialize to std::ostream." << endl
+ << "//" << endl
+ << endl;
+ }
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Serialize to a standard output stream." << endl
+ << " *" << endl
+ << " * @param os A standrad output stream." << endl
+ << " * @param x An object model to serialize." << endl
+ << " * @param m A namespace information map." << endl
+ << " * @param e A character encoding to produce XML in." << endl
+ << " * @param f Serialization flags." << endl
+ << " *" << endl
+ << " * This function uses exceptions to report " <<
+ "serialization errors." << endl
+ << " */" << endl;
+ }
+
+ os << inst_exp
+ << "void" << endl
+ << name << " (::std::ostream& os," << endl
+ << "const " << type_name (e) << "& x, " << endl
+ << "const " << namespace_infomap << "& m = " <<
+ namespace_infomap << " ()," << endl
+ << "const " << string_type << "& e = " << L << "\"UTF-8\"," << endl
+ << flags_type << " f = 0);"
+ << endl;
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Serialize to a standard output stream with an " <<
+ "error handler." << endl
+ << " *" << endl
+ << " * @param os A standrad output stream." << endl
+ << " * @param x An object model to serialize." << endl
+ << " * @param eh An error handler." << endl
+ << " * @param m A namespace information map." << endl
+ << " * @param e A character encoding to produce XML in." << endl
+ << " * @param f Serialization flags." << endl
+ << " *" << endl
+ << " * This function reports serialization errors by " <<
+ "calling the error" << endl
+ << " * handler." << endl
+ << " */" << endl;
+ }
+
+ os << inst_exp
+ << "void" << endl
+ << name << " (::std::ostream& os," << endl
+ << "const " << type_name (e) << "& x, " << endl
+ << error_handler << "& eh," << endl
+ << "const " << namespace_infomap << "& m = " <<
+ namespace_infomap << " ()," << endl
+ << "const " << string_type << "& e = " << L << "\"UTF-8\"," << endl
+ << flags_type << " f = 0);"
+ << endl;
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Serialize to a standard output stream with a " <<
+ "Xerces-C++ DOM" << endl
+ << " * error handler." << endl
+ << " *" << endl
+ << " * @param os A standrad output stream." << endl
+ << " * @param x An object model to serialize." << endl
+ << " * @param eh A Xerces-C++ DOM error handler." << endl
+ << " * @param m A namespace information map." << endl
+ << " * @param e A character encoding to produce XML in." << endl
+ << " * @param f Serialization flags." << endl
+ << " *" << endl
+ << " * This function reports serialization errors by " <<
+ "calling the error" << endl
+ << " * handler." << endl
+ << " */" << endl;
+ }
+
+ os << inst_exp
+ << "void" << endl
+ << name << " (::std::ostream& os," << endl
+ << "const " << type_name (e) << "& x, " << endl
+ << xerces_ns << "::DOMErrorHandler& eh," << endl
+ << "const " << namespace_infomap << "& m = " <<
+ namespace_infomap << " ()," << endl
+ << "const " << string_type << "& e = " << L << "\"UTF-8\"," << endl
+ << flags_type << " f = 0);"
+ << endl;
+
+ if (!doxygen)
+ {
+ os << "// Serialize to xercesc::XMLFormatTarget." << endl
+ << "//" << endl
+ << endl;
+ }
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Serialize to a Xerces-C++ XML format target." << endl
+ << " *" << endl
+ << " * @param ft A Xerces-C++ XML format target." << endl
+ << " * @param x An object model to serialize." << endl
+ << " * @param m A namespace information map." << endl
+ << " * @param e A character encoding to produce XML in." << endl
+ << " * @param f Serialization flags." << endl
+ << " *" << endl
+ << " * This function uses exceptions to report " <<
+ "serialization errors." << endl
+ << " */" << endl;
+ }
+
+ os << inst_exp
+ << "void" << endl
+ << name << " (" << xerces_ns << "::XMLFormatTarget& ft," << endl
+ << "const " << type_name (e) << "& x, " << endl
+ << "const " << namespace_infomap << "& m = " <<
+ namespace_infomap << " ()," << endl
+ << "const " << string_type << "& e = " << L << "\"UTF-8\"," << endl
+ << flags_type << " f = 0);"
+ << endl;
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Serialize to a Xerces-C++ XML format target " <<
+ "with an error" << endl
+ << " * handler." << endl
+ << " *" << endl
+ << " * @param ft A Xerces-C++ XML format target." << endl
+ << " * @param x An object model to serialize." << endl
+ << " * @param eh An error handler." << endl
+ << " * @param m A namespace information map." << endl
+ << " * @param e A character encoding to produce XML in." << endl
+ << " * @param f Serialization flags." << endl
+ << " *" << endl
+ << " * This function reports serialization errors by " <<
+ "calling the error" << endl
+ << " * handler." << endl
+ << " */" << endl;
+ }
+
+ os << inst_exp
+ << "void" << endl
+ << name << " (" << xerces_ns << "::XMLFormatTarget& ft," << endl
+ << "const " << type_name (e) << "& x, " << endl
+ << error_handler << "& eh," << endl
+ << "const " << namespace_infomap << "& m = " <<
+ namespace_infomap << " ()," << endl
+ << "const " << string_type << "& e = " << L << "\"UTF-8\"," << endl
+ << flags_type << " f = 0);"
+ << endl;
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Serialize to a Xerces-C++ XML format target " <<
+ "with a" << endl
+ << " * Xerces-C++ DOM error handler." << endl
+ << " *" << endl
+ << " * @param ft A Xerces-C++ XML format target." << endl
+ << " * @param x An object model to serialize." << endl
+ << " * @param eh A Xerces-C++ DOM error handler." << endl
+ << " * @param m A namespace information map." << endl
+ << " * @param e A character encoding to produce XML in." << endl
+ << " * @param f Serialization flags." << endl
+ << " *" << endl
+ << " * This function reports serialization errors by " <<
+ "calling the error" << endl
+ << " * handler." << endl
+ << " */" << endl;
+ }
+
+ os << inst_exp
+ << "void" << endl
+ << name << " (" << xerces_ns << "::XMLFormatTarget& ft," << endl
+ << "const " << type_name (e) << "& x, " << endl
+ << xerces_ns << "::DOMErrorHandler& eh," << endl
+ << "const " << namespace_infomap << "& m = " <<
+ namespace_infomap << " ()," << endl
+ << "const " << string_type << "& e = " << L << "\"UTF-8\"," << endl
+ << flags_type << " f = 0);"
+ << endl;
+
+ if (!doxygen)
+ {
+ os << "// Serialize to an existing xercesc::DOMDocument." << endl
+ << "//" << endl
+ << endl;
+ }
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Serialize to an existing Xerces-C++ DOM document." << endl
+ << " *" << endl
+ << " * @param d A Xerces-C++ DOM document." << endl
+ << " * @param x An object model to serialize." << endl
+ << " * @param f Serialization flags." << endl
+ << " *" << endl
+ << " * Note that it is your responsibility to create the " <<
+ "DOM document" << endl
+ << " * with the correct root element as well as set the " <<
+ "necessary" << endl
+ << " * namespace mapping attributes." << endl
+ << " */" << endl;
+ }
+ os << inst_exp
+ << "void" << endl
+ << name << " (" << xerces_ns << "::DOMDocument& d," << endl
+ << "const " << type_name (e) << "& x," << endl
+ << flags_type << " f = 0);"
+ << endl;
+
+ if (!doxygen)
+ {
+ os << "// Serialize to a new xercesc::DOMDocument." << endl
+ << "//" << endl
+ << endl;
+ }
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Serialize to a new Xerces-C++ DOM document." << endl
+ << " *" << endl
+ << " * @param x An object model to serialize." << endl
+ << " * @param m A namespace information map." << endl
+ << " * @param f Serialization flags." << endl
+ << " * @return A pointer to the new Xerces-C++ DOM document." << endl
+ << " */" << endl;
+ }
+
+ os << inst_exp
+ << dom_auto_ptr << "< " << xerces_ns <<
+ "::DOMDocument >" << endl
+ << name << " (const " << type_name (e) << "& x, " << endl
+ << "const " << namespace_infomap << "& m = " <<
+ namespace_infomap << " ()," << endl
+ << flags_type << " f = 0);"
+ << endl;
+
+ if (doxygen)
+ {
+ os << "//@}" << endl
+ << endl;
+ }
+ }
+
+ private:
+ String
+ type_name (Type& e)
+ {
+ std::wostringstream o;
+
+ MemberTypeName type (*this, o);
+ type.dispatch (e.type ());
+
+ return o.str ();
+ }
+ };
+
+ }
+
+ Void
+ generate_serialization_header (Context& ctx)
+ {
+ Boolean elemen_type (ctx.options.value<CLI::generate_element_type> ());
+
+ if (!elemen_type)
+ ctx.os << "#include <iosfwd>" << endl
+ << endl
+ << "#include <xercesc/dom/DOMDocument.hpp>" << endl
+ << "#include <xercesc/dom/DOMErrorHandler.hpp>" << endl
+ << "#include <xercesc/framework/XMLFormatter.hpp>" << endl
+ << endl
+ << "#include <xsd/cxx/xml/dom/auto-ptr.hxx>" << 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);
+ ElementType element_type (ctx);
+ ElementFunction element_function (ctx);
+
+ schema >> sources >> schema;
+ schema >> names_ns >> ns >> names;
+
+ names >> list;
+ names >> union_;
+ names >> complex;
+ names >> enumeration;
+
+ if (elemen_type)
+ names >> element_type;
+ else
+ names >> element_function;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+}
diff --git a/xsd/cxx/tree/serialization-header.hxx b/xsd/cxx/tree/serialization-header.hxx
new file mode 100644
index 0000000..c6909c8
--- /dev/null
+++ b/xsd/cxx/tree/serialization-header.hxx
@@ -0,0 +1,22 @@
+// file : xsd/cxx/tree/serialization-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_TREE_SERIALIZATION_HEADER_HXX
+#define CXX_TREE_SERIALIZATION_HEADER_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/tree/elements.hxx>
+
+namespace CXX
+{
+ namespace Tree
+ {
+ Void
+ generate_serialization_header (Context&);
+ }
+}
+
+#endif // CXX_TREE_SERIALIZATION_HEADER_HXX
diff --git a/xsd/cxx/tree/serialization-source.cxx b/xsd/cxx/tree/serialization-source.cxx
new file mode 100644
index 0000000..1d96883
--- /dev/null
+++ b/xsd/cxx/tree/serialization-source.cxx
@@ -0,0 +1,1342 @@
+// file : xsd/cxx/tree/serialization-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/tree/serialization-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Tree
+ {
+ namespace
+ {
+ enum schema_type
+ {
+ st_other,
+ st_double,
+ st_decimal
+ };
+
+ enum schema_type
+ schema_type (SemanticGraph::Type& t)
+ {
+ if (t.is_a<SemanticGraph::Fundamental::Double> ())
+ return st_double;
+ else if (t.is_a<SemanticGraph::Fundamental::Decimal> ())
+ return st_decimal;
+ else
+ return st_other;
+ }
+
+
+ //
+ //
+ struct List : Traversal::List, protected virtual Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String name (ename (l));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (l, name) && !name)
+ return;
+
+ SemanticGraph::Type& item_type (l.argumented ().type ());
+ String base (L"::xsd::cxx::tree::list< " +
+ item_type_name (item_type) + L", " + char_type);
+
+ if (item_type.is_a<SemanticGraph::Fundamental::Double> ())
+ base += L", ::xsd::cxx::tree::schema_type::double_";
+ else if (item_type.is_a<SemanticGraph::Fundamental::Decimal> ())
+ base += L", ::xsd::cxx::tree::schema_type::decimal";
+
+ base += L" >";
+
+ // operator<< (xercesc::DOMElement)
+ //
+ os << "void" << endl
+ << "operator<< (" << xerces_ns << "::DOMElement& e, " <<
+ "const " << name << "& i)"
+ << "{"
+ << "e << static_cast< const " << base << "& > (i);"
+ << "}";
+
+ // operator<< (xercesc::DOMAttr)
+ //
+ os << "void" << endl
+ << "operator<< (" << xerces_ns << "::DOMAttr& a, " <<
+ "const " << name << "& i)"
+ << "{"
+ << "a << static_cast< const " << base << "& > (i);"
+ << "}";
+
+ // operator<< (list_stream)
+ //
+ os << "void" << endl
+ << "operator<< (" << list_stream_type << "& l," << endl
+ << "const " << name << "& i)"
+ << "{"
+ << "l << static_cast< const " << base << "& > (i);"
+ << "}";
+
+ // Register with type factory map.
+ //
+ if (polymorphic && !l.context ().count ("anonymous"))
+ {
+ // Note that we are using the original type name.
+ //
+ String const& name (ename (l));
+
+ os << "static" << endl
+ << "const ::xsd::cxx::tree::type_serializer_initializer< 0, " <<
+ char_type << ", " << name << " >" << endl
+ << "_xsd_" << name << "_type_serializer_init (" << endl
+ << L << strlit (l.name ()) << "," << endl
+ << L << strlit (xml_ns_name (l)) << ");"
+ << endl
+ << endl;
+ }
+ }
+
+ private:
+ String
+ item_type_name (SemanticGraph::Type& t)
+ {
+ std::wostringstream o;
+
+ MemberTypeName type (*this, o);
+ type.dispatch (t);
+
+ return o.str ();
+ }
+ };
+
+
+ struct Union : Traversal::Union, protected virtual Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ String name (ename (u));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (u, name) && !name)
+ return;
+
+ String const& base (xs_string_type);
+
+ // operator<< (xercesc::DOMElement)
+ //
+ os << "void" << endl
+ << "operator<< (" << xerces_ns << "::DOMElement& e, " <<
+ "const " << name << "& i)"
+ << "{"
+ << "e << static_cast< const " << base << "& > (i);"
+ << "}";
+
+ // operator<< (xercesc::DOMAttr)
+ //
+ os << "void" << endl
+ << "operator<< (" << xerces_ns << "::DOMAttr& a, " <<
+ "const " << name << "& i)"
+ << "{"
+ << "a << static_cast< const " << base << "& > (i);"
+ << "}";
+
+ // operator<< (list_stream)
+ //
+ os << "void" << endl
+ << "operator<< (" << list_stream_type << "& l," << endl
+ << "const " << name << "& i)"
+ << "{"
+ << "l << static_cast< const " << base << "& > (i);"
+ << "}";
+
+ // Register with type factory map.
+ //
+ if (polymorphic && !u.context ().count ("anonymous"))
+ {
+ // Note that we are using the original type name.
+ //
+ String const& name (ename (u));
+
+ os << "static" << endl
+ << "const ::xsd::cxx::tree::type_serializer_initializer< 0, " <<
+ char_type << ", " << name << " >" << endl
+ << "_xsd_" << name << "_type_serializer_init (" << endl
+ << L << strlit (u.name ()) << "," << endl
+ << L << strlit (xml_ns_name (u)) << ");"
+ << endl
+ << endl;
+ }
+ }
+ };
+
+
+ struct Enumeration : Traversal::Enumeration, protected virtual Context
+ {
+ Enumeration (Context& c)
+ : Context (c), base_ (c)
+ {
+ inherits_base_ >> base_;
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ String name (ename (e));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (e, name) && !name)
+ return;
+
+ // operator<< (xercesc::DOMElement)
+ //
+ os << "void" << endl
+ << "operator<< (" << xerces_ns << "::DOMElement& e, " <<
+ "const " << name << "& i)"
+ << "{"
+ << "e << static_cast< const ";
+
+ inherits (e, inherits_base_);
+
+ os << "& > (i);"
+ << "}";
+
+
+ // operator<< (xercesc::DOMAttr)
+ //
+ os << "void" << endl
+ << "operator<< (" << xerces_ns << "::DOMAttr& a, " <<
+ "const " << name << "& i)"
+ << "{"
+ << "a << static_cast< const ";
+
+ inherits (e, inherits_base_);
+
+ os << "& > (i);"
+ << "}";
+
+
+ // operator<< (list_stream)
+ //
+ os << "void" << endl
+ << "operator<< (" << list_stream_type << "& l," << endl
+ << "const " << name << "& i)"
+ << "{"
+ << "l << static_cast< const ";
+
+ inherits (e, inherits_base_);
+
+ os << "& > (i);"
+ << "}";
+
+
+ // Register with type factory map.
+ //
+ if (polymorphic && !e.context ().count ("anonymous"))
+ {
+ // Note that we are using the original type name.
+ //
+ String const& name (ename (e));
+
+ os << "static" << endl
+ << "const ::xsd::cxx::tree::type_serializer_initializer< 0, " <<
+ char_type << ", " << name << " >" << endl
+ << "_xsd_" << name << "_type_serializer_init (" << endl
+ << L << strlit (e.name ()) << "," << endl
+ << L << strlit (xml_ns_name (e)) << ");"
+ << endl
+ << endl;
+ }
+ }
+
+ private:
+ Traversal::Inherits inherits_base_;
+ BaseTypeName base_;
+ };
+
+ struct Element : Traversal::Element, protected virtual Context
+ {
+ Element (Context& c, String const& scope_)
+ : Context (c), scope (scope_)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (skip (e))
+ return;
+
+ String const& aname (eaname (e));
+ String ns (e.qualified () ? e.namespace_ ().name () : "");
+ String type (scope + L"::" + etype (e));
+
+ // Check if we need to handle xsi:type and substitution groups.
+ // If this element's type is anonymous or mapped to a fundamental
+ // C++ type then we don't need to do anything. Note that if the
+ // type is anonymous then it can't be derived from which makes it
+ // impossible to substitute or dynamically-type with xsi:type.
+ //
+ SemanticGraph::Type& t (e.type ());
+ Boolean poly (polymorphic && !t.context ().count ("anonymous"));
+
+ if (poly)
+ {
+ Boolean fund (false);
+ IsFundamentalType traverser (fund);
+ traverser.dispatch (t);
+ poly = !fund;
+ }
+
+ os << "// " << comment (e.name ()) << endl
+ << "//" << endl;
+
+ // aCC cannot handle an inline call to type_serializer_map_instance.
+ //
+ if (poly)
+ {
+ os << "{"
+ << "::xsd::cxx::tree::type_serializer_map< " << char_type
+ << " >& tsm (" << endl
+ << "::xsd::cxx::tree::type_serializer_map_instance< 0, " <<
+ char_type << " > ());"
+ << endl;
+ }
+
+ if (max (e) != 1)
+ {
+ // sequence
+ //
+ os << "for (" << scope << "::" << econst_iterator (e) << endl
+ << "b (i." << aname << " ().begin ()), " <<
+ "n (i." << aname << " ().end ());" << endl
+ << "b != n; ++b)"
+ << "{";
+
+ if (poly)
+ {
+ os << "if (typeid (" << type << ") == typeid (*b))"
+ << "{"
+ << xerces_ns << "::DOMElement& s (" << endl
+ << "::xsd::cxx::xml::dom::create_element (" << endl
+ << L << strlit (e.name ()) << "," << endl
+ << (ns ? L + strlit (ns) + L",\n" : L"")
+ << "e));"
+ << endl
+ << "s << *b;"
+ << "}"
+ << "else" << endl
+ << "tsm.serialize (" << endl
+ << L << strlit (e.name ()) << "," << endl
+ << L << strlit (ns) << "," << endl
+ << (e.global () ? "true" : "false") << ", " <<
+ (e.qualified () ? "true" : "false") << ", e, *b);";
+ }
+ else
+ {
+ os << xerces_ns << "::DOMElement& s (" << endl
+ << "::xsd::cxx::xml::dom::create_element (" << endl
+ << L << strlit (e.name ()) << "," << endl
+ << (ns ? L + strlit (ns) + L",\n" : L"")
+ << "e));"
+ << endl;
+
+ switch (schema_type (t))
+ {
+ case st_other:
+ {
+ os << "s << *b;";
+ break;
+ }
+ case st_double:
+ {
+ os << "s << " << as_double_type << " (*b);";
+ break;
+ }
+ case st_decimal:
+ {
+ os << "s << " << as_decimal_type << " (*b);";
+ break;
+ }
+ }
+ }
+
+ os << "}";
+ }
+ else if (min (e) == 0)
+ {
+ // optional
+ //
+ os << "if (i." << aname << " ())"
+ << "{";
+
+ if (poly)
+ {
+ os << "const " << type << "& x (*i." << aname << " ());"
+ << "if (typeid (" << type << ") == typeid (x))"
+ << "{"
+ << xerces_ns << "::DOMElement& s (" << endl
+ << "::xsd::cxx::xml::dom::create_element (" << endl
+ << L << strlit (e.name ()) << "," << endl
+ << (ns ? L + strlit (ns) + L",\n" : L"")
+ << "e));"
+ << endl
+ << "s << x;"
+ << "}"
+ << "else" << endl
+ << "tsm.serialize (" << endl
+ << L << strlit (e.name ()) << "," << endl
+ << L << strlit (ns) << "," << endl
+ << (e.global () ? "true" : "false") << ", " <<
+ (e.qualified () ? "true" : "false") << ", e, x);";
+ }
+ else
+ {
+ os << xerces_ns << "::DOMElement& s (" << endl
+ << "::xsd::cxx::xml::dom::create_element (" << endl
+ << L << strlit (e.name ()) << "," << endl
+ << (ns ? L + strlit (ns) + L",\n" : L"")
+ << "e));"
+ << endl;
+
+ switch (schema_type (t))
+ {
+ case st_other:
+ {
+ os << "s << *i." << aname << " ();";
+ break;
+ }
+ case st_double:
+ {
+ os << "s << " << as_double_type << "(*i." << aname << " ());";
+ break;
+ }
+ case st_decimal:
+ {
+ os << "s << " << as_decimal_type << "(*i." << aname << " ());";
+ break;
+ }
+ }
+ }
+
+ os << "}";
+ }
+ else
+ {
+ // one
+ //
+ if (poly)
+ {
+ os << "const " << type << "& x (i." << aname << " ());"
+ << "if (typeid (" << type << ") == typeid (x))"
+ << "{"
+ << xerces_ns << "::DOMElement& s (" << endl
+ << "::xsd::cxx::xml::dom::create_element (" << endl
+ << L << strlit (e.name ()) << "," << endl
+ << (ns ? L + strlit (ns) + L",\n" : L"")
+ << "e));"
+ << endl
+ << "s << x;"
+ << "}"
+ << "else" << endl
+ << "tsm.serialize (" << endl
+ << L << strlit (e.name ()) << "," << endl
+ << L << strlit (ns) << "," << endl
+ << (e.global () ? "true" : "false") << ", " <<
+ (e.qualified () ? "true" : "false") << ", e, x);";
+ }
+ else
+ {
+ os << "{"
+ << xerces_ns << "::DOMElement& s (" << endl
+ << "::xsd::cxx::xml::dom::create_element (" << endl
+ << L << strlit (e.name ()) << "," << endl
+ << (ns ? L + strlit (ns) + L",\n" : L"")
+ << "e));"
+ << endl;
+
+ switch (schema_type (t))
+ {
+ case st_other:
+ {
+ os << "s << i." << aname << " ();";
+ break;
+ }
+ case st_double:
+ {
+ os << "s << " << as_double_type << "(i." << aname << " ());";
+ break;
+ }
+ case st_decimal:
+ {
+ os << "s << " << as_decimal_type << "(i." << aname << " ());";
+ break;
+ }
+ }
+
+ os << "}";
+ }
+ }
+
+ if (poly)
+ os << "}";
+ }
+
+ private:
+ String scope;
+ };
+
+ struct Any : Traversal::Any, protected virtual Context
+ {
+ Any (Context& c, String const& scope_)
+ : Context (c), scope (scope_)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ String const& aname (eaname (a));
+
+ os << "// " << ename (a) << endl
+ << "//" << endl;
+
+ if (max (a) != 1)
+ {
+ // sequence
+ //
+ os << "for (" << scope << "::" << econst_iterator (a) << endl
+ << "b (i." << aname << " ().begin ()), " <<
+ "n (i." << aname << " ().end ());" << endl
+ << "b != n; ++b)"
+ << "{"
+ << "e.appendChild (" << endl
+ << "e.getOwnerDocument ()->importNode (" << endl
+ << "const_cast< " << xerces_ns <<
+ "::DOMElement* > (&(*b)), true));"
+ << "}";
+ }
+ else if (min (a) == 0)
+ {
+ // optional
+ //
+ os << "if (i." << aname << " ())"
+ << "{"
+ << "e.appendChild (" << endl
+ << "e.getOwnerDocument ()->importNode (" << endl
+ << "const_cast< " << xerces_ns << "::DOMElement* > (&(*i." <<
+ aname << " ())), true));"
+ << "}";
+ }
+ else
+ {
+ // one
+ //
+ os << "e.appendChild (" << endl
+ << "e.getOwnerDocument ()->importNode (" << endl
+ << "const_cast< " << xerces_ns << "::DOMElement* > (&(i." <<
+ aname << " ())), true));"
+ << endl;
+ }
+ }
+
+ private:
+ String scope;
+ };
+
+ struct Attribute : Traversal::Attribute, protected virtual Context
+ {
+ Attribute (Context& c, String const& scope_)
+ : Context (c), scope (scope_)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ String const& aname (eaname (a));
+ String ns (a.qualified () ? a.namespace_ ().name () : "");
+
+ os << "// " << comment (a.name ()) << endl
+ << "//" << endl;
+
+ Boolean def (a.default_ () && !is_qname (a.type ()));
+
+ if (a.optional () && !def)
+ {
+ os << "if (i." << aname << " ())"
+ << "{"
+ << xerces_ns << "::DOMAttr& a (" << endl
+ << "::xsd::cxx::xml::dom::create_attribute (" << endl
+ << L << strlit (a.name ()) << "," << endl
+ << (ns ? L + strlit (ns) + L",\n" : L"")
+ << "e));"
+ << endl;
+
+ switch (schema_type (a.type ()))
+ {
+ case st_other:
+ {
+ os << "a << *i." << aname << " ();";
+ break;
+ }
+ case st_double:
+ {
+ os << "a << " << as_double_type << "(*i." << aname << " ());";
+ break;
+ }
+ case st_decimal:
+ {
+ os << "a << " << as_decimal_type << "(*i." << aname << " ());";
+ break;
+ }
+ }
+
+ os << "}";
+ }
+ else
+ {
+ // Make sure we serialize required fixed attributes.
+ //
+ if (a.optional () &&
+ options.value<CLI::omit_default_attributes> ())
+ {
+ os << "if (i." << aname << " () != " << scope <<
+ "::" << edefault_value (a) << " ())";
+ }
+
+ os << "{"
+ << xerces_ns << "::DOMAttr& a (" << endl
+ << "::xsd::cxx::xml::dom::create_attribute (" << endl
+ << L << strlit (a.name ()) << "," << endl
+ << (ns ? L + strlit (ns) + L",\n" : L"")
+ << "e));"
+ << endl;
+
+ switch (schema_type (a.type ()))
+ {
+ case st_other:
+ {
+ os << "a << i." << aname << " ();";
+ break;
+ }
+ case st_double:
+ {
+ os << "a << " << as_double_type << "(i." << aname << " ());";
+ break;
+ }
+ case st_decimal:
+ {
+ os << "a << " << as_decimal_type << "(i." << aname << " ());";
+ break;
+ }
+ }
+
+ os << "}";
+ }
+ }
+
+ private:
+ String scope;
+ };
+
+ struct AnyAttribute : Traversal::AnyAttribute,
+ protected virtual Context
+ {
+ AnyAttribute (Context& c, String const& scope_)
+ : Context (c), scope (scope_)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ String const& aname (eaname (a));
+
+ os << "// " << ename (a) << endl
+ << "//" << endl;
+
+ os << "for (" << scope << "::" << econst_iterator (a) << endl
+ << "b (i." << aname << " ().begin ()), " <<
+ "n (i." << aname << " ().end ());" << endl
+ << "b != n; ++b)"
+ << "{"
+ << xerces_ns << "::DOMAttr* a (" << endl
+ << "static_cast< " << xerces_ns << "::DOMAttr* > (" << endl
+ << "e.getOwnerDocument ()->importNode (" << endl
+ << "const_cast< " << xerces_ns << "::DOMAttr* > (&(*b)), true)));"
+ << endl
+ << "if (a->getLocalName () == 0)" << endl
+ << "e.setAttributeNode (a);"
+ << "else" << endl
+ << "e.setAttributeNodeNS (a);"
+ << "}";
+ }
+
+ private:
+ String scope;
+ };
+
+ struct Complex : Traversal::Complex, protected virtual Context
+ {
+ Complex (Context& c)
+ : Context (c), base_ (c)
+ {
+ inherits_ >> base_;
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ String name (ename (c));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (c, name) && !name)
+ return;
+
+ // operator<< (xercesc::DOMElement)
+ //
+ os << "void" << endl
+ << "operator<< (" << xerces_ns << "::DOMElement& e, " <<
+ "const " << name << "& i)"
+ << "{";
+
+ if (c.inherits_p ())
+ {
+ os << "e << static_cast< const ";
+ inherits (c, inherits_);
+ os << "& > (i);"
+ << endl;
+ }
+ else
+ os << "e << static_cast< const " << any_type << "& > (i);"
+ << endl;
+
+ // Serialize anyAttribute content first so that is gets
+ // overriden by schema-defined attributes.
+ //
+ if (options.value<CLI::generate_wildcard> ())
+ {
+ AnyAttribute any_attribute (*this, name);
+ Traversal::Names names (any_attribute);
+
+ Complex::names (c, names);
+ }
+
+ {
+ Traversal::Names names;
+ Any any (*this, name);
+ Element element (*this, name);
+ Attribute attribute (*this, name);
+
+ names >> element;
+ names >> attribute;
+
+ if (options.value<CLI::generate_wildcard> ())
+ names >> any;
+
+ Complex::names (c, names);
+ }
+
+ os << "}";
+
+
+ Boolean simple (true);
+ {
+ IsSimpleType t (simple);
+ t.dispatch (c);
+ }
+
+ if (simple)
+ {
+ Boolean hb (c.inherits_p ());
+
+ // operator<< (xercesc::DOMAttr)
+ //
+ os << "void" << endl
+ << "operator<< (" << xerces_ns << "::DOMAttr&" <<
+ (hb ? " a" : "") << ", " <<
+ "const " << name << "&" << (hb ? " i" : "") << ")"
+ << "{";
+
+ if (hb)
+ {
+ os << "a << static_cast< const ";
+
+ inherits (c, inherits_);
+
+ os << "& > (i);";
+ }
+
+ os << "}";
+
+
+ // operator<< (list_stream)
+ //
+ os << "void" << endl
+ << "operator<< (" << list_stream_type << "&" <<
+ (hb ? " l" : "") << "," << endl
+ << "const " << name << "&" << (hb ? " i" : "") << ")"
+ << "{";
+
+ if (hb)
+ {
+ os << "l << static_cast< const ";
+
+ inherits (c, inherits_);
+
+ os << "& > (i);";
+ }
+
+ os << "}";
+ }
+
+ // Register with type factory map.
+ //
+ if (polymorphic && !c.context ().count ("anonymous"))
+ {
+ // Note that we are using the original type name.
+ //
+ String const& name (ename (c));
+
+ os << "static" << endl
+ << "const ::xsd::cxx::tree::type_serializer_initializer< 0, " <<
+ char_type << ", " << name << " >" << endl
+ << "_xsd_" << name << "_type_serializer_init (" << endl
+ << L << strlit (c.name ()) << "," << endl
+ << L << strlit (xml_ns_name (c)) << ");"
+ << endl
+ << endl;
+ }
+ }
+
+ private:
+ Traversal::Inherits inherits_;
+ BaseTypeName base_;
+ };
+
+
+ // Generate substitution group map entry.
+ //
+ struct GlobalElement : Traversal::Element,
+ GlobalElementBase,
+ protected virtual Context
+ {
+ GlobalElement (Context& c)
+ : Context (c), GlobalElementBase (c), type_name_ (c)
+ {
+ belongs_ >> type_name_;
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (polymorphic && e.substitutes_p ())
+ {
+ Type& r (e.substitutes ().root ());
+
+ String const& name (ename (e));
+
+ os << "static" << endl
+ << "const ::xsd::cxx::tree::type_serializer_initializer< 0, " <<
+ char_type << ", ";
+
+ belongs (e, belongs_);
+
+ os << " >" << endl
+ << "_xsd_" << name << "_element_name_init (" << endl
+ << L << strlit (r.name ()) << "," << endl
+ << L << strlit (r.namespace_ ().name ()) << "," << endl
+ << L << strlit (e.name ()) << "," << endl
+ << L << strlit (e.namespace_ ().name ()) << ");"
+ << endl
+ << endl;
+ }
+ }
+
+ private:
+ Traversal::Belongs belongs_;
+ MemberTypeName type_name_;
+
+ };
+
+ struct ElementType: Traversal::Element,
+ GlobalElementBase,
+ protected virtual Context
+ {
+ ElementType (Context& c)
+ : Context (c),
+ GlobalElementBase (c),
+ element_map_ (c.options.value<CLI::generate_element_map> ())
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (doc_root_p (e))
+ {
+ String const& name (ename (e));
+
+ // operator<< (xercesc::DOMElement)
+ //
+ os << "void" << endl
+ << "operator<< (" << xerces_ns << "::DOMElement& e, " <<
+ "const " << name << "& i)"
+ << "{"
+ << "e << i." << eaname (e) << " ();"
+ << "}";
+
+ // Element map registration.
+ //
+ if (element_map_)
+ {
+ SemanticGraph::Context& ec (e.context ());
+ String const& aname (ec.get<String> ("element-name"));
+ String const& ans (ec.get<String> ("element-ns"));
+
+ os << "static " << endl
+ << "const ::xsd::cxx::tree::serializer_init< " <<
+ name << ", " << char_type << ", " << any_type << " >" << endl
+ << "_xsd_" << name << "_serializer_init (" <<
+ name << "::" << aname << " (), " <<
+ name << "::" << ans << " ());"
+ << endl;
+ }
+ }
+ }
+
+ private:
+ Boolean element_map_;
+ };
+
+ struct ElementFunction: Traversal::Element,
+ GlobalElementBase,
+ protected virtual Context
+ {
+ ElementFunction (Context& c)
+ : Context (c), GlobalElementBase (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (!doc_root_p (e))
+ return;
+
+ String const& name (eserializer (e));
+ String ns (e.namespace_ ().name ());
+ String const& error_handler (error_handler_type);
+ String const& namespace_infomap (namespace_infomap_type);
+
+ SemanticGraph::Type& type (e.type ());
+
+ // Note that I am using fq-name in function calls because g++ gets
+ // confused if the name is 'type'. (see tests/schema/anonymous)
+ //
+
+ Boolean fund (false);
+ {
+ IsFundamentalType t (fund);
+ t.dispatch (type);
+ }
+
+ // Check if we need to handle xsi:type and substitution groups.
+ // If this element's type is anonymous or mapped to a fundamental
+ // C++ type then we don't need to do anything.
+ //
+ Boolean poly (!fund && polymorphic &&
+ !type.context ().count ("anonymous"));
+
+ // To std::ostream.
+ //
+ os << "void" << endl
+ << name << " (::std::ostream& o," << endl
+ << "const " << type_name (e) << "& s," << endl
+ << "const " << namespace_infomap << "& m," << endl
+ << "const " << string_type << "& e," << endl
+ << flags_type << " f)"
+ << "{"
+ << "::xsd::cxx::xml::auto_initializer i (" << endl
+ << "(f & " << flags_type << "::dont_initialize) == 0);"
+ << endl
+ << dom_auto_ptr << "< " << xerces_ns <<
+ "::DOMDocument > d (" << endl
+ << fq_name (e, "serializer") << " (s, m, f));"
+ << endl
+ << "::xsd::cxx::tree::error_handler< " << char_type << " > h;"
+ << endl
+ << "::xsd::cxx::xml::dom::ostream_format_target t (o);"
+ << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))"
+ << "{"
+ << "h.throw_if_failed< ::xsd::cxx::tree::serialization< " <<
+ char_type << " > > ();"
+ << "}"
+ << "}";
+
+ os << "void" << endl
+ << name << " (::std::ostream& o," << endl
+ << "const " << type_name (e) << "& s," << endl
+ << error_handler << "& h," << endl
+ << "const " << namespace_infomap << "& m," << endl
+ << "const " << string_type << "& e," << endl
+ << flags_type << " f)"
+ << "{"
+ << "::xsd::cxx::xml::auto_initializer i (" << endl
+ << "(f & " << flags_type << "::dont_initialize) == 0);"
+ << endl
+ << dom_auto_ptr << "< " << xerces_ns <<
+ "::DOMDocument > d (" << endl
+ << fq_name (e, "serializer") << " (s, m, f));"
+ << "::xsd::cxx::xml::dom::ostream_format_target t (o);"
+ << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))"
+ << "{"
+ << "throw ::xsd::cxx::tree::serialization< " <<
+ char_type << " > ();"
+ << "}"
+ << "}";
+
+ os << "void" << endl
+ << name << " (::std::ostream& o," << endl
+ << "const " << type_name (e) << "& s," << endl
+ << xerces_ns << "::DOMErrorHandler& h," << endl
+ << "const " << namespace_infomap << "& m," << endl
+ << "const " << string_type << "& e," << endl
+ << flags_type << " f)"
+ << "{"
+ << dom_auto_ptr << "< " << xerces_ns <<
+ "::DOMDocument > d (" << endl
+ << fq_name (e, "serializer") << " (s, m, f));"
+ << "::xsd::cxx::xml::dom::ostream_format_target t (o);"
+ << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))"
+ << "{"
+ << "throw ::xsd::cxx::tree::serialization< " <<
+ char_type << " > ();"
+ << "}"
+ << "}";
+
+ // To XMLFormatTarget.
+ //
+ os << "void" << endl
+ << name << " (" << xerces_ns << "::XMLFormatTarget& t," << endl
+ << "const " << type_name (e) << "& s," << endl
+ << "const " << namespace_infomap << "& m," << endl
+ << "const " << string_type << "& e," << endl
+ << flags_type << " f)"
+ << "{"
+ << dom_auto_ptr << "< " << xerces_ns <<
+ "::DOMDocument > d (" << endl
+ << fq_name (e, "serializer") << " (s, m, f));"
+ << endl
+ << "::xsd::cxx::tree::error_handler< " << char_type << " > h;"
+ << endl
+ << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))"
+ << "{"
+ << "h.throw_if_failed< ::xsd::cxx::tree::serialization< " <<
+ char_type << " > > ();"
+ << "}"
+ << "}";
+
+ os << "void" << endl
+ << name << " (" << xerces_ns << "::XMLFormatTarget& t," << endl
+ << "const " << type_name (e) << "& s," << endl
+ << error_handler << "& h," << endl
+ << "const " << namespace_infomap << "& m," << endl
+ << "const " << string_type << "& e," << endl
+ << flags_type << " f)"
+ << "{"
+ << dom_auto_ptr << "< " << xerces_ns <<
+ "::DOMDocument > d (" << endl
+ << fq_name (e, "serializer") << " (s, m, f));"
+ << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))"
+ << "{"
+ << "throw ::xsd::cxx::tree::serialization< " <<
+ char_type << " > ();"
+ << "}"
+ << "}";
+
+ os << "void" << endl
+ << name << " (" << xerces_ns << "::XMLFormatTarget& t," << endl
+ << "const " << type_name (e) << "& s," << endl
+ << xerces_ns << "::DOMErrorHandler& h," << endl
+ << "const " << namespace_infomap << "& m," << endl
+ << "const " << string_type << "& e," << endl
+ << flags_type << " f)"
+ << "{"
+ << dom_auto_ptr << "< " << xerces_ns <<
+ "::DOMDocument > d (" << endl
+ << fq_name (e, "serializer") << " (s, m, f));"
+ << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))"
+ << "{"
+ << "throw ::xsd::cxx::tree::serialization< " <<
+ char_type << " > ();"
+ << "}"
+ << "}";
+
+ // To an existing DOM instance.
+ //
+ os << "void" << endl
+ << name << " (" << xerces_ns << "::DOMDocument& d," << endl
+ << "const " << type_name (e) << "& s," << endl
+ << flags_type << ")"
+ << "{"
+ << xerces_ns << "::DOMElement& e (*d.getDocumentElement ());"
+ << "const " << qname_type << " n (" << endl
+ << "::xsd::cxx::xml::dom::name< " << char_type << " > (e));"
+ << endl;
+
+ if (poly)
+ {
+ os << "if (typeid (" << type_name (e) << ") == typeid (s))"
+ << "{";
+ }
+
+ os << "if (n.name () == " << L << strlit (e.name ()) << " &&" << endl
+ << "n.namespace_ () == " << L << strlit (ns) << ")"
+ << "{";
+
+ switch (schema_type (type))
+ {
+ case st_other:
+ {
+ os << "e << s;";
+ break;
+ }
+ case st_double:
+ {
+ os << "e << " << as_double_type << "(s);";
+ break;
+ }
+ case st_decimal:
+ {
+ os << "e << " << as_decimal_type << "(s);";
+ break;
+ }
+ }
+
+ os << "}"
+ << "else"
+ << "{"
+ << "throw ::xsd::cxx::tree::unexpected_element < " <<
+ char_type << " > (" << endl
+ << "n.name ()," << endl
+ << "n.namespace_ ()," << endl
+ << L << strlit (e.name ()) << "," << endl
+ << L << strlit (ns) << ");"
+ << "}";
+
+ if (poly)
+ {
+ // aCC cannot handle an inline call to
+ // type_serializer_map_instance.
+ //
+ os << "}"
+ << "else"
+ << "{"
+ << "::xsd::cxx::tree::type_serializer_map< " << char_type
+ << " >& tsm (" << endl
+ << "::xsd::cxx::tree::type_serializer_map_instance< 0, " <<
+ char_type << " > ());"
+ << endl
+ << "tsm.serialize (" << endl
+ << L << strlit (e.name ()) << "," << endl
+ << L << strlit (e.namespace_().name ()) << "," << endl
+ << "e, n, s);"
+ << "}";
+ }
+
+ os << "}";
+
+
+ // To a new DOM instance.
+ //
+ os << dom_auto_ptr << "< " << xerces_ns << "::DOMDocument >" << endl
+ << name << " (const " << type_name (e) << "& s," << endl
+ << "const " << namespace_infomap << "& m," << endl
+ << flags_type << " f)"
+ << "{";
+
+ if (poly)
+ {
+ // aCC cannot handle an inline call to
+ // type_serializer_map_instance as well as the direct
+ // auto_ptr assignment.
+ //
+ os << dom_auto_ptr << "< " << xerces_ns << "::DOMDocument > d;"
+ << endl
+ << "if (typeid (" << type_name (e) << ") == typeid (s))"
+ << "{"
+ << dom_auto_ptr << "< " << xerces_ns <<
+ "::DOMDocument > r (" << endl
+ << "::xsd::cxx::xml::dom::serialize< " <<
+ char_type << " > (" << endl
+ << L << strlit (e.name ()) << "," << endl
+ << L << strlit (ns) << "," << endl
+ << "m, f));"
+ << "d = r;"
+ << "}"
+ << "else"
+ << "{"
+ << "::xsd::cxx::tree::type_serializer_map< " << char_type
+ << " >& tsm (" << endl
+ << "::xsd::cxx::tree::type_serializer_map_instance< 0, " <<
+ char_type << " > ());"
+ << endl
+ << dom_auto_ptr << "< " << xerces_ns <<
+ "::DOMDocument > r (" << endl
+ << "tsm.serialize (" << endl
+ << L << strlit (e.name ()) << "," << endl
+ << L << strlit (e.namespace_().name ()) << "," << endl
+ << "m, s, f));"
+ << "d = r;"
+ << "}";
+ }
+ else
+ {
+ os << dom_auto_ptr << "< " << xerces_ns <<
+ "::DOMDocument > d (" << endl
+ << "::xsd::cxx::xml::dom::serialize< " <<
+ char_type << " > (" << endl
+ << L << strlit (e.name ()) << "," << endl
+ << L << strlit (ns) << "," << endl
+ << "m, f));"
+ << endl;
+ }
+
+ os << fq_name (e, "serializer") << " (*d, s, f);"
+ << "return d;"
+ << "}";
+
+ }
+
+ private:
+ String
+ type_name (Type& e)
+ {
+ std::wostringstream o;
+
+ MemberTypeName type (*this, o);
+ type.dispatch (e.type ());
+
+ return o.str ();
+ }
+ };
+ }
+
+ Void
+ generate_serialization_source (Context& ctx,
+ UnsignedLong first,
+ UnsignedLong last)
+ {
+ Boolean elemen_type (ctx.options.value<CLI::generate_element_type> ());
+
+ if (!elemen_type)
+ ctx.os << "#include <ostream>" << endl
+ << "#include <xsd/cxx/tree/error-handler.hxx>" << endl;
+
+ ctx.os << "#include <xsd/cxx/xml/dom/serialization-source.hxx>" << endl
+ << endl;
+
+ if (ctx.polymorphic)
+ {
+ ctx.os << "#include <xsd/cxx/tree/type-serializer-map.hxx>" << endl
+ << endl;
+
+ Boolean import_maps (ctx.options.value<CLI::import_maps> ());
+ Boolean export_maps (ctx.options.value<CLI::export_maps> ());
+
+ if (import_maps || export_maps)
+ {
+ ctx.os << "#ifdef _MSC_VER" << endl
+ << endl
+ << "namespace xsd"
+ << "{"
+ << "namespace cxx"
+ << "{"
+ << "namespace tree"
+ << "{";
+
+ if (export_maps)
+ ctx.os << "template struct __declspec (dllexport) " <<
+ "type_serializer_plate< 0, " << ctx.char_type << " >;";
+
+ if (import_maps)
+ ctx.os << "template struct __declspec (dllimport) " <<
+ "type_serializer_plate< 0, " << ctx.char_type << " >;";
+
+ ctx.os << "}" // tree
+ << "}" // cxx
+ << "}" // xsd
+ << "#endif // _MSC_VER" << endl
+ << endl;
+ }
+
+ ctx.os << "namespace _xsd"
+ << "{"
+ << "static" << endl
+ << "const ::xsd::cxx::tree::type_serializer_plate< 0, " <<
+ ctx.char_type << " >" << endl
+ << "type_serializer_plate_init;"
+ << "}";
+ }
+
+ Traversal::Schema schema;
+
+ Traversal::Sources sources;
+ Traversal::Names names_ns, names;
+
+ Namespace ns (ctx, first, last);
+
+ List list (ctx);
+ Union union_ (ctx);
+ Complex complex (ctx);
+ Enumeration enumeration (ctx);
+ GlobalElement element (ctx);
+ ElementType element_type (ctx);
+ ElementFunction element_function (ctx);
+
+
+ schema >> sources >> schema;
+ schema >> names_ns >> ns >> names;
+
+ names >> list;
+ names >> union_;
+ names >> complex;
+ names >> enumeration;
+ names >> element;
+
+ if (elemen_type)
+ names >> element_type;
+ else
+ names >> element_function;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+}
diff --git a/xsd/cxx/tree/serialization-source.hxx b/xsd/cxx/tree/serialization-source.hxx
new file mode 100644
index 0000000..3ea85b4
--- /dev/null
+++ b/xsd/cxx/tree/serialization-source.hxx
@@ -0,0 +1,24 @@
+// file : xsd/cxx/tree/serialization-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_TREE_SERIALIZATION_SOURCE_HXX
+#define CXX_TREE_SERIALIZATION_SOURCE_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/tree/elements.hxx>
+
+namespace CXX
+{
+ namespace Tree
+ {
+ Void
+ generate_serialization_source (Context&,
+ UnsignedLong first,
+ UnsignedLong last);
+ }
+}
+
+#endif // CXX_TREE_SERIALIZATION_SOURCE_HXX
diff --git a/xsd/cxx/tree/stream-extraction-source.cxx b/xsd/cxx/tree/stream-extraction-source.cxx
new file mode 100644
index 0000000..8b92040
--- /dev/null
+++ b/xsd/cxx/tree/stream-extraction-source.cxx
@@ -0,0 +1,754 @@
+// file : xsd/cxx/tree/stream-extraction-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/tree/stream-extraction-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Tree
+ {
+ namespace
+ {
+ typedef Containers::Vector<NarrowString> Streams;
+
+ struct List : Traversal::List, protected virtual Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String name (ename (l));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (l, name) && !name)
+ return;
+
+ SemanticGraph::Type& item_type (l.argumented ().type ());
+ String base (L"::xsd::cxx::tree::list< " +
+ item_type_name (item_type) + L", " + char_type);
+
+ if (item_type.is_a<SemanticGraph::Fundamental::Double> ())
+ base += L", ::xsd::cxx::tree::schema_type::double_";
+ else if (item_type.is_a<SemanticGraph::Fundamental::Decimal> ())
+ base += L", ::xsd::cxx::tree::schema_type::decimal";
+
+ base += L" >";
+
+ UnsignedLong n (0);
+ Streams const& st (options.value<CLI::generate_extraction> ());
+ for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i)
+ {
+ os << name << "::" << endl
+ << name << " (" << istream_type << "< " <<
+ i->c_str () << " >& s," << endl
+ << flags_type << " f," << endl
+ << container << "* c)" << endl
+ << ": " << any_simple_type << " (s, f, c)," << endl
+ << " " << base << " (s, f, c)"
+ << "{"
+ << "}";
+
+ // Register with type map.
+ //
+ if (polymorphic && !l.context ().count ("anonymous"))
+ {
+ // Note that we are using the original type name.
+ //
+ String const& name (ename (l));
+
+ os << "static" << endl
+ << "const ::xsd::cxx::tree::stream_extraction_initializer< " <<
+ "0, " << i->c_str () << ", " <<
+ char_type << ", " << name << " >" << endl
+ << "_xsd_" << name << "_stream_extraction_init_" <<
+ n++ << " (" << endl
+ << L << strlit (l.name ()) << "," << endl
+ << L << strlit (xml_ns_name (l)) << ");"
+ << endl;
+ }
+ }
+ }
+
+ private:
+ String
+ item_type_name (SemanticGraph::Type& t)
+ {
+ std::wostringstream o;
+
+ MemberTypeName type (*this, o);
+ type.dispatch (t);
+
+ return o.str ();
+ }
+ };
+
+
+ struct Union : Traversal::Union, protected virtual Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ String name (ename (u));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (u, name) && !name)
+ return;
+
+ String const& base (xs_string_type);
+
+ UnsignedLong n (0);
+ Streams const& st (options.value<CLI::generate_extraction> ());
+ for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i)
+ {
+ os << name << "::" << endl
+ << name << " (" << istream_type << "< " <<
+ i->c_str () << " >& s," << endl
+ << flags_type << " f," << endl
+ << container << "* c)" << endl
+ << ": " << base << " (s, f, c)"
+ << "{"
+ << "}";
+
+ // Register with type map.
+ //
+ if (polymorphic && !u.context ().count ("anonymous"))
+ {
+ // Note that we are using the original type name.
+ //
+ String const& name (ename (u));
+
+ os << "static" << endl
+ << "const ::xsd::cxx::tree::stream_extraction_initializer< " <<
+ "0, " << i->c_str () << ", " <<
+ char_type << ", " << name << " >" << endl
+ << "_xsd_" << name << "_stream_extraction_init_" <<
+ n++ << " (" << endl
+ << L << strlit (u.name ()) << "," << endl
+ << L << strlit (xml_ns_name (u)) << ");"
+ << endl;
+ }
+ }
+ }
+ };
+
+
+ struct Enumeration : Traversal::Enumeration, protected virtual Context
+ {
+ Enumeration (Context& c)
+ : Context (c), base_ (c)
+ {
+ inherits_base_ >> base_;
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ String name (ename (e));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (e, name) && !name)
+ return;
+
+ Boolean string_based (false);
+ {
+ IsStringBasedType t (string_based);
+ t.dispatch (e);
+ }
+
+ UnsignedLong n (0);
+ Streams const& st (options.value<CLI::generate_extraction> ());
+ for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i)
+ {
+ os << name << "::" << endl
+ << name << " (" << istream_type << "< " <<
+ i->c_str () << " >& s," << endl
+ << flags_type << " f," << endl
+ << container << "* c)" << endl
+ << ": ";
+
+ inherits (e, inherits_base_);
+
+ os << " (s, f, c)"
+ << "{";
+
+ if (string_based)
+ os << "_xsd_" << name << "_convert ();";
+
+ os << "}";
+
+ // Register with type map.
+ //
+ if (polymorphic && !e.context ().count ("anonymous"))
+ {
+ // Note that we are using the original type name.
+ //
+ String const& name (ename (e));
+
+ os << "static" << endl
+ << "const ::xsd::cxx::tree::stream_extraction_initializer< " <<
+ "0, " << i->c_str () << ", " <<
+ char_type << ", " << name << " >" << endl
+ << "_xsd_" << name << "_stream_extraction_init_" <<
+ n++ << " (" << endl
+ << L << strlit (e.name ()) << "," << endl
+ << L << strlit (xml_ns_name (e)) << ");"
+ << endl;
+ }
+ }
+ }
+
+ private:
+ Traversal::Inherits inherits_base_;
+ BaseTypeName base_;
+ };
+
+ struct CtorMember : Traversal::Member,
+ protected virtual Context
+ {
+ CtorMember (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Member& m)
+ {
+ if (skip (m))
+ return;
+
+ os << "," << endl
+ << " " << emember (m) << " (f, this)";
+ }
+ };
+
+ struct CtorAny : Traversal::Any,
+ Traversal::AnyAttribute,
+ protected virtual Context
+ {
+ CtorAny (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ String const& member (emember (a));
+ String const& dom_doc (
+ edom_document (
+ dynamic_cast<SemanticGraph::Complex&> (a.scope ())));
+
+ os << "," << endl
+ << " " << member << " (this->" << dom_doc << " ())";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute& a)
+ {
+ String const& member (emember (a));
+ String const& dom_doc (
+ edom_document (
+ dynamic_cast<SemanticGraph::Complex&> (a.scope ())));
+
+ os << "," << endl
+ << " " << member << " (this->" << dom_doc << " ())";
+ }
+ };
+
+ struct Element : Traversal::Element, protected virtual Context
+ {
+ Element (Context& c, String const& stream_)
+ : Context (c), stream (stream_)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (skip (e))
+ return;
+
+ String const& member (emember (e));
+
+ SemanticGraph::Type& t (e.type ());
+ String type (etype (e));
+
+ Boolean fund (false);
+ {
+ IsFundamentalType traverser (fund);
+ traverser.dispatch (t);
+ }
+
+ // Figure out if we need to generate polymorphic code. If this
+ // elemen's type is anonymous or mapped to a fundamental C++
+ // type then we don't need to do anything. Note that if the type
+ // is anonymous then it can't be derived from which makes it
+ // impossible to substitute or dynamically-type with xsi:type.
+ //
+ Boolean poly (!fund && polymorphic &&
+ !t.context ().count ("anonymous"));
+
+ if (max (e) != 1)
+ {
+ // sequence
+ //
+ String container (econtainer (e));
+
+ os << "{"
+ << "::std::size_t n;"
+ << "::xsd::cxx::tree::istream_common::as_size< " <<
+ "::std::size_t > as (n);"
+ << "s >> as;"
+ << "if (n > 0)"
+ << "{"
+ << container << "& c (this->" << member << ");"
+ << "c.reserve (n);"
+ << "while (n--)"
+ << "{";
+
+ if (poly)
+ {
+ os << "bool d;"
+ << "::std::auto_ptr< " << type << " > r;"
+ << "s >> d;"
+ << endl
+ << "if (!d)" << endl
+ << "r.reset (new " << type << " (s, f, this));"
+ << "else"
+ << "{"
+ << "::std::auto_ptr< ::xsd::cxx::tree::type > tmp (" << endl
+ << "::xsd::cxx::tree::stream_extraction_map_instance< 0, " <<
+ stream << ", " << char_type << " > ().extract (" << endl
+ << "s, f, this));"
+ << "r.reset (dynamic_cast< " << type << "* > (tmp.get ()));"
+ << "if (r.get ())" << endl
+ << "tmp.release ();"
+ << "else" << endl
+ << "throw ::xsd::cxx::tree::not_derived< " << char_type <<
+ " > ();"
+ << "}";
+ }
+ else if (fund)
+ {
+ os << type << " r;"
+ << "s >> r;";
+ }
+ else
+ {
+ os << "::std::auto_ptr< " << type << " > r (new " << type <<
+ " (s, f, this));";
+ }
+
+ os << "c.push_back (r);"
+ << "}" // while
+ << "}" // if
+ << "}";
+ }
+ else if (min (e) == 0)
+ {
+ // optional
+ //
+ os << "{"
+ << "bool p;"
+ << "s >> p;"
+ << "if (p)"
+ << "{";
+
+ if (poly)
+ {
+ os << "bool d;"
+ << "::std::auto_ptr< " << type << " > r;"
+ << "s >> d;"
+ << endl
+ << "if (!d)" << endl
+ << "r.reset (new " << type << " (s, f, this));"
+ << "else"
+ << "{"
+ << "::std::auto_ptr< ::xsd::cxx::tree::type > tmp (" << endl
+ << "::xsd::cxx::tree::stream_extraction_map_instance< 0, " <<
+ stream << ", " << char_type << " > ().extract (" << endl
+ << "s, f, this));"
+ << "r.reset (dynamic_cast< " << type << "* > (tmp.get ()));"
+ << "if (r.get ())" << endl
+ << "tmp.release ();"
+ << "else" << endl
+ << "throw ::xsd::cxx::tree::not_derived< " << char_type <<
+ " > ();"
+ << "}";
+ }
+ else if (fund)
+ {
+ os << type << " r;"
+ << "s >> r;";
+ }
+ else
+ {
+ os << "::std::auto_ptr< " << type << " > r (new " << type <<
+ " (s, f, this));";
+ }
+
+ os << "this->" << member << ".set (r);"
+ << "}" // if (p)
+ << "}";
+ }
+ else
+ {
+ // one
+ //
+ os << "{";
+
+ if (poly)
+ {
+ os << "bool d;"
+ << "::std::auto_ptr< " << type << " > r;"
+ << "s >> d;"
+ << endl
+ << "if (!d)" << endl
+ << "r.reset (new " << type << " (s, f, this));"
+ << "else"
+ << "{"
+ << "::std::auto_ptr< ::xsd::cxx::tree::type > tmp (" << endl
+ << "::xsd::cxx::tree::stream_extraction_map_instance< 0, " <<
+ stream << ", " << char_type << " > ().extract (" << endl
+ << "s, f, this));"
+ << "r.reset (dynamic_cast< " << type << "* > (tmp.get ()));"
+ << "if (r.get ())" << endl
+ << "tmp.release ();"
+ << "else" << endl
+ << "throw ::xsd::cxx::tree::not_derived< " << char_type <<
+ " > ();"
+ << "}";
+ }
+ else if (fund)
+ {
+ os << type << " r;"
+ << "s >> r;";
+ }
+ else
+ {
+ os << "::std::auto_ptr< " << type << " > r (new " << type <<
+ " (s, f, this));";
+ }
+
+ os << "this->" << member << ".set (r);"
+ << "}";
+ }
+ }
+
+ private:
+ String stream;
+ };
+
+ struct Attribute : Traversal::Attribute, protected virtual Context
+ {
+ Attribute (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ String const& member (emember (a));
+ String type (etype (a));
+
+ Boolean fund (false);
+ {
+ IsFundamentalType traverser (fund);
+ traverser.dispatch (a.type ());
+ }
+
+ Boolean def (a.default_ () && !is_qname (a.type ()));
+
+ if (a.optional () && !def)
+ {
+ os << "{"
+ << "bool p;"
+ << "s >> p;"
+ << "if (p)"
+ << "{";
+
+ if (fund)
+ {
+ os << type << " r;"
+ << "s >> r;"
+ << "this->" << member << ".set (r);";
+ }
+ else
+ {
+ os << "::std::auto_ptr< " << type << " > r (new " << type <<
+ " (s, f, this));"
+ << "this->" << member << ".set (r);";
+ }
+
+ os << "}" // if (p)
+ << "}";
+ }
+ else
+ {
+ os << "{";
+
+ if (fund)
+ {
+ os << type << " r;"
+ << "s >> r;"
+ << "this->" << member << ".set (r);";
+ }
+ else
+ {
+ os << "::std::auto_ptr< " << type << " > r (new " << type <<
+ " (s, f, this));"
+ << "this->" << member << ".set (r);";
+ }
+
+ os << "}";
+ }
+ }
+ };
+
+ struct Complex : Traversal::Complex, protected virtual Context
+ {
+ Complex (Context& c)
+ : Context (c), base_ (c), ctor_any_ (c), ctor_member_ (c)
+ {
+ inherits_ >> base_;
+ names_ctor_member_ >> ctor_member_;
+
+ if (options.value<CLI::generate_wildcard> ())
+ names_ctor_member_ >> ctor_any_;
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ String name (ename (c));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (c, name) && !name)
+ return;
+
+ Boolean has_members (has<Traversal::Member> (c));
+
+ Boolean facets (false);
+ if (c.inherits_p ())
+ {
+ // See if we have any facets that we need to handle.
+ //
+ using SemanticGraph::Restricts;
+ using SemanticGraph::Fundamental::Decimal;
+
+ if (Restricts* r = dynamic_cast<Restricts*> (&c.inherits ()))
+ {
+ if (!r->facet_empty () &&
+ (r->facet_find ("fractionDigits") != r->facet_end () ||
+ r->facet_find ("totalDigits") != r->facet_end ()) &&
+ ultimate_base (c).is_a<Decimal> ())
+ facets = true;
+ }
+ }
+
+ UnsignedLong n (0);
+ Streams const& st (options.value<CLI::generate_extraction> ());
+ for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i)
+ {
+
+ os << name << "::" << endl
+ << name << " (" << istream_type << "< " <<
+ i->c_str () << " >& s," << endl
+ << flags_type << " f," << endl
+ << container << "* c)" << endl
+ << ": ";
+
+ if (c.inherits_p ())
+ inherits (c, inherits_);
+ else
+ os << any_type;
+
+ os << " (s, f, c)";
+
+ if (edom_document_member_p (c))
+ {
+ os << "," << endl
+ << " " << edom_document_member (c) << " (" <<
+ "::xsd::cxx::xml::dom::create_document< " << char_type <<
+ " > ())";
+ }
+
+ names (c, names_ctor_member_);
+
+ os << "{";
+
+ if (facets)
+ os << "this->_facet_table (_xsd_" << name << "_facet_table);"
+ << endl;
+
+ if (has_members)
+ os << "this->" << unclash (name, "parse") << " (s, f);";
+
+ os << "}";
+
+ // Parse
+ //
+ if (has_members)
+ {
+ os << "void " << name << "::" << endl
+ << unclash (name, "parse") << " (" <<
+ istream_type << "< " << i->c_str () << " >& s," << endl
+ << flags_type << " f)"
+ << "{";
+ {
+ Element element (*this, *i);
+ Attribute attribute (*this);
+ Traversal::Names names_;
+
+ names_ >> element;
+ names_ >> attribute;
+
+ names (c, names_);
+ }
+
+ os << "}";
+ }
+
+
+ // Register with type map.
+ //
+ if (polymorphic && !c.context ().count ("anonymous"))
+ {
+ // Note that we are using the original type name.
+ //
+ String const& name (ename (c));
+
+ os << "static" << endl
+ << "const ::xsd::cxx::tree::stream_extraction_initializer< " <<
+ "0, " << i->c_str () << ", " <<
+ char_type << ", " << name << " >" << endl
+ << "_xsd_" << name << "_stream_extraction_init_" <<
+ n++ << " (" << endl
+ << L << strlit (c.name ()) << "," << endl
+ << L << strlit (xml_ns_name (c)) << ");"
+ << endl;
+ }
+ }
+ }
+
+ private:
+ Traversal::Inherits inherits_;
+ BaseTypeName base_;
+
+ CtorAny ctor_any_;
+ CtorMember ctor_member_;
+
+ Traversal::Names names_ctor_member_;
+ };
+ }
+
+ Void
+ generate_stream_extraction_source (Context& ctx)
+ {
+ if (ctx.polymorphic)
+ {
+ Streams const& st (ctx.options.value<CLI::generate_extraction> ());
+
+ ctx.os << "#include <xsd/cxx/tree/stream-extraction-map.hxx>" << endl
+ << endl;
+
+ Boolean import_maps (ctx.options.value<CLI::import_maps> ());
+ Boolean export_maps (ctx.options.value<CLI::export_maps> ());
+
+ if (import_maps || export_maps)
+ {
+ ctx.os << "#ifdef _MSC_VER" << endl
+ << endl
+ << "namespace xsd"
+ << "{"
+ << "namespace cxx"
+ << "{"
+ << "namespace tree"
+ << "{";
+
+ for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i)
+ {
+ String stream (*i);
+
+ if (export_maps)
+ ctx.os << "template struct __declspec (dllexport) " <<
+ "stream_extraction_plate< 0, " << stream << ", " <<
+ ctx.char_type << " >;";
+
+ if (import_maps)
+ ctx.os << "template struct __declspec (dllimport) " <<
+ "stream_extraction_plate< 0, " << stream << ", " <<
+ ctx.char_type << " >;";
+ }
+
+ ctx.os << "}" // tree
+ << "}" // cxx
+ << "}" // xsd
+ << "#endif // _MSC_VER" << endl
+ << endl;
+ }
+
+ ctx.os << "namespace _xsd"
+ << "{";
+
+ UnsignedLong n (0);
+ for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i)
+ {
+ String stream (*i);
+
+ ctx.os << "static" << endl
+ << "const ::xsd::cxx::tree::stream_extraction_plate< 0, " <<
+ stream << ", " << ctx.char_type << " >" << endl
+ << "stream_extraction_plate_init_" << n++ << ";";
+ }
+
+ ctx.os << "}";
+ }
+
+ 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/xsd/cxx/tree/stream-extraction-source.hxx b/xsd/cxx/tree/stream-extraction-source.hxx
new file mode 100644
index 0000000..c6524f7
--- /dev/null
+++ b/xsd/cxx/tree/stream-extraction-source.hxx
@@ -0,0 +1,22 @@
+// file : xsd/cxx/tree/stream-extraction-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_TREE_EXTRACTION_SOURCE_HXX
+#define CXX_TREE_EXTRACTION_SOURCE_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/tree/elements.hxx>
+
+namespace CXX
+{
+ namespace Tree
+ {
+ Void
+ generate_stream_extraction_source (Context&);
+ }
+}
+
+#endif // CXX_TREE_EXTRACTION_SOURCE_HXX
diff --git a/xsd/cxx/tree/stream-header.cxx b/xsd/cxx/tree/stream-header.cxx
new file mode 100644
index 0000000..64964a3
--- /dev/null
+++ b/xsd/cxx/tree/stream-header.cxx
@@ -0,0 +1,183 @@
+// file : xsd/cxx/tree/stream-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/tree/stream-header.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Tree
+ {
+ namespace
+ {
+ struct List: Traversal::List, protected virtual Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String name (ename (l));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (l, name) && !name)
+ return;
+
+ os << inst_exp
+ << std_ostream_type << "&" << endl
+ << "operator<< (" << std_ostream_type << "&, const " <<
+ name << "&);"
+ << endl;
+ }
+ };
+
+
+ struct Union: Traversal::Union, protected virtual Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ String name (ename (u));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (u, name) && !name)
+ return;
+
+ os << inst_exp
+ << std_ostream_type << "&" << endl
+ << "operator<< (" << std_ostream_type << "&, const " <<
+ name << "&);"
+ << endl;
+ }
+ };
+
+
+ struct Enumeration: Traversal::Enumeration, protected virtual Context
+ {
+ Enumeration (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ String name (ename (e));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (e, name) && !name)
+ return;
+
+ Boolean string_based (false);
+ {
+ IsStringBasedType t (string_based);
+ t.dispatch (e);
+ }
+
+ Boolean enum_based (false);
+ if (string_based)
+ {
+ SemanticGraph::Enumeration* be (0);
+ IsEnumBasedType t (be);
+ t.dispatch (e);
+
+ enum_based = (be != 0);
+ }
+
+ // If we are based on an enum then the value type is just an
+ // alias and we don't need to generate this operator again.
+ //
+ if (string_based && !enum_based)
+ {
+ os << inst_exp
+ << std_ostream_type << "&" << endl
+ << "operator<< (" << std_ostream_type << "&, " <<
+ name << "::" << evalue (e) << ");"
+ << endl;
+ }
+
+ os << inst_exp
+ << std_ostream_type << "&" << endl
+ << "operator<< (" << std_ostream_type << "&, const " <<
+ name << "&);"
+ << endl;
+ }
+ };
+
+ struct Complex : Traversal::Complex, protected virtual Context
+ {
+ Complex (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ String name (ename (c));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (c, name) && !name)
+ return;
+
+ os << inst_exp
+ << std_ostream_type << "&" << endl
+ << "operator<< (" << std_ostream_type << "&, const " <<
+ name << "&);"
+ << endl;
+ }
+ };
+ }
+
+ Void
+ generate_stream_header (Context& ctx)
+ {
+ String c (ctx.char_type);
+
+ ctx.os << "#include <iosfwd>" << 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);
+ }
+ }
+}
diff --git a/xsd/cxx/tree/stream-header.hxx b/xsd/cxx/tree/stream-header.hxx
new file mode 100644
index 0000000..c34c763
--- /dev/null
+++ b/xsd/cxx/tree/stream-header.hxx
@@ -0,0 +1,22 @@
+// file : xsd/cxx/tree/stream-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_TREE_STREAM_HEADER_HXX
+#define CXX_TREE_STREAM_HEADER_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/tree/elements.hxx>
+
+namespace CXX
+{
+ namespace Tree
+ {
+ Void
+ generate_stream_header (Context&);
+ }
+}
+
+#endif // CXX_TREE_STREAM_HEADER_HXX
diff --git a/xsd/cxx/tree/stream-insertion-header.cxx b/xsd/cxx/tree/stream-insertion-header.cxx
new file mode 100644
index 0000000..32cb402
--- /dev/null
+++ b/xsd/cxx/tree/stream-insertion-header.cxx
@@ -0,0 +1,178 @@
+// file : xsd/cxx/tree/stream-insertion-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/tree/stream-insertion-header.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Tree
+ {
+ namespace
+ {
+ typedef Containers::Vector<NarrowString> Streams;
+
+ struct List: Traversal::List, protected virtual Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String name (ename (l));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (l, name) && !name)
+ return;
+
+ Streams const& st (options.value<CLI::generate_insertion> ());
+ for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i)
+ {
+ String stream_type (ostream_type + L"< " + String (*i) + L" >");
+
+ os << inst_exp
+ << stream_type << "&" << endl
+ << "operator<< (" << stream_type << "&," << endl
+ << "const " << name << "&);"
+ << endl;
+ }
+ }
+ };
+
+
+ struct Union: Traversal::Union, protected virtual Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ String name (ename (u));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (u, name) && !name)
+ return;
+
+ Streams const& st (options.value<CLI::generate_insertion> ());
+ for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i)
+ {
+ String stream_type (ostream_type + L"< " + String (*i) + L" >");
+
+ os << inst_exp
+ << stream_type << "&" << endl
+ << "operator<< (" << stream_type << "&," << endl
+ << "const " << name << "&);"
+ << endl;
+ }
+ }
+ };
+
+
+ struct Enumeration: Traversal::Enumeration, protected virtual Context
+ {
+ Enumeration (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ String name (ename (e));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (e, name) && !name)
+ return;
+
+ Streams const& st (options.value<CLI::generate_insertion> ());
+ for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i)
+ {
+ String stream_type (ostream_type + L"< " + String (*i) + L" >");
+
+ os << inst_exp
+ << stream_type << "&" << endl
+ << "operator<< (" << stream_type << "&," << endl
+ << "const " << name << "&);"
+ << endl;
+ }
+ }
+ };
+
+ struct Complex : Traversal::Complex, protected virtual Context
+ {
+ Complex (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ String name (ename (c));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (c, name) && !name)
+ return;
+
+ Streams const& st (options.value<CLI::generate_insertion> ());
+ for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i)
+ {
+ String stream_type (ostream_type + L"< " + String (*i) + L" >");
+
+ os << inst_exp
+ << stream_type << "&" << endl
+ << "operator<< (" << stream_type << "&," << endl
+ << "const " << name << "&);"
+ << endl;
+ }
+ }
+ };
+ }
+
+ Void
+ generate_stream_insertion_header (Context& ctx)
+ {
+ String c (ctx.char_type);
+
+ 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/xsd/cxx/tree/stream-insertion-header.hxx b/xsd/cxx/tree/stream-insertion-header.hxx
new file mode 100644
index 0000000..95bfc2c
--- /dev/null
+++ b/xsd/cxx/tree/stream-insertion-header.hxx
@@ -0,0 +1,22 @@
+// file : xsd/cxx/tree/stream-insertion-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_TREE_STREAM_INSERTION_HEADER_HXX
+#define CXX_TREE_STREAM_INSERTION_HEADER_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/tree/elements.hxx>
+
+namespace CXX
+{
+ namespace Tree
+ {
+ Void
+ generate_stream_insertion_header (Context&);
+ }
+}
+
+#endif // CXX_TREE_STREAM_INSERTION_HEADER_HXX
diff --git a/xsd/cxx/tree/stream-insertion-source.cxx b/xsd/cxx/tree/stream-insertion-source.cxx
new file mode 100644
index 0000000..87c7caa
--- /dev/null
+++ b/xsd/cxx/tree/stream-insertion-source.cxx
@@ -0,0 +1,532 @@
+// file : xsd/cxx/tree/stream-insertion-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/tree/stream-insertion-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Tree
+ {
+ namespace
+ {
+ typedef Containers::Vector<NarrowString> Streams;
+
+ struct List : Traversal::List, protected virtual Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String name (ename (l));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (l, name) && !name)
+ return;
+
+ SemanticGraph::Type& item_type (l.argumented ().type ());
+ String base (L"::xsd::cxx::tree::list< " +
+ item_type_name (item_type) + L", " + char_type);
+
+ if (item_type.is_a<SemanticGraph::Fundamental::Double> ())
+ base += L", ::xsd::cxx::tree::schema_type::double_";
+ else if (item_type.is_a<SemanticGraph::Fundamental::Decimal> ())
+ base += L", ::xsd::cxx::tree::schema_type::decimal";
+
+ base += L" >";
+
+ UnsignedLong n (0);
+ Streams const& st (options.value<CLI::generate_insertion> ());
+ for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i)
+ {
+ String stream_type ("::xsd::cxx::tree::ostream< " + *i + " >");
+
+ os << stream_type << "&" << endl
+ << "operator<< (" << stream_type << "& s," << endl
+ << "const " << name << "& x)"
+ << "{"
+ << "return s << static_cast< const " << base << "& > (x);"
+ << "}";
+
+ // Register with type map.
+ //
+ if (polymorphic && !l.context ().count ("anonymous"))
+ {
+ // Note that we are using the original type name.
+ //
+ String const& name (ename (l));
+
+ os << "static" << endl
+ << "const ::xsd::cxx::tree::stream_insertion_initializer< " <<
+ "0, " << i->c_str () << ", " <<
+ char_type << ", " << name << " >" << endl
+ << "_xsd_" << name << "_stream_insertion_init_" <<
+ n++ << " (" << endl
+ << L << strlit (l.name ()) << "," << endl
+ << L << strlit (xml_ns_name (l)) << ");"
+ << endl;
+ }
+ }
+ }
+
+ private:
+ String
+ item_type_name (SemanticGraph::Type& t)
+ {
+ std::wostringstream o;
+
+ MemberTypeName type (*this, o);
+ type.dispatch (t);
+
+ return o.str ();
+ }
+ };
+
+
+ struct Union : Traversal::Union, protected virtual Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ String name (ename (u));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (u, name) && !name)
+ return;
+
+ String const& base (xs_string_type);
+
+ UnsignedLong n (0);
+ Streams const& st (options.value<CLI::generate_insertion> ());
+ for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i)
+ {
+ String stream_type ("::xsd::cxx::tree::ostream< " + *i + " >");
+
+ os << stream_type << "&" << endl
+ << "operator<< (" << stream_type << "& s," << endl
+ << "const " << name << "& x)"
+ << "{"
+ << "return s << static_cast< const " << base << "& > (x);"
+ << "}";
+
+ // Register with type map.
+ //
+ if (polymorphic && !u.context ().count ("anonymous"))
+ {
+ // Note that we are using the original type name.
+ //
+ String const& name (ename (u));
+
+ os << "static" << endl
+ << "const ::xsd::cxx::tree::stream_insertion_initializer< " <<
+ "0, " << i->c_str () << ", " <<
+ char_type << ", " << name << " >" << endl
+ << "_xsd_" << name << "_stream_insertion_init_" <<
+ n++ << " (" << endl
+ << L << strlit (u.name ()) << "," << endl
+ << L << strlit (xml_ns_name (u)) << ");"
+ << endl;
+ }
+ }
+ }
+ };
+
+
+ struct Enumeration : Traversal::Enumeration, protected virtual Context
+ {
+ Enumeration (Context& c)
+ : Context (c), base_ (c)
+ {
+ inherits_base_ >> base_;
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ String name (ename (e));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (e, name) && !name)
+ return;
+
+ UnsignedLong n (0);
+ Streams const& st (options.value<CLI::generate_insertion> ());
+ for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i)
+ {
+ String stream_type ("::xsd::cxx::tree::ostream< " + *i + " >");
+
+ os << stream_type << "&" << endl
+ << "operator<< (" << stream_type << "& s," << endl
+ << "const " << name << "& x)"
+ << "{"
+ << "return s << static_cast< const ";
+
+ inherits (e, inherits_base_);
+
+ os << "& > (x);"
+ << "}";
+
+ // Register with type map.
+ //
+ if (polymorphic && !e.context ().count ("anonymous"))
+ {
+ // Note that we are using the original type name.
+ //
+ String const& name (ename (e));
+
+ os << "static" << endl
+ << "const ::xsd::cxx::tree::stream_insertion_initializer< " <<
+ "0, " << i->c_str () << ", " <<
+ char_type << ", " << name << " >" << endl
+ << "_xsd_" << name << "_stream_insertion_init_" <<
+ n++ << " (" << endl
+ << L << strlit (e.name ()) << "," << endl
+ << L << strlit (xml_ns_name (e)) << ");"
+ << endl;
+ }
+ }
+ }
+
+ private:
+ Traversal::Inherits inherits_base_;
+ BaseTypeName base_;
+ };
+
+ struct Element : Traversal::Element, protected virtual Context
+ {
+ Element (Context& c, String const& scope_, String const& stream_)
+ : Context (c), scope (scope_), stream (stream_)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (skip (e)) return;
+
+ String const& aname (eaname (e));
+ SemanticGraph::Type& t (e.type ());
+ String type (scope + L"::" + etype (e));
+
+ // Figure out if we need to generate polymorphic code. If this
+ // elemen's type is anonymous or mapped to a fundamental C++
+ // type then we don't need to do anything. Note that if the type
+ // is anonymous then it can't be derived from which makes it
+ // impossible to substitute or dynamically-type with xsi:type.
+ //
+ Boolean poly (polymorphic && !t.context ().count ("anonymous"));
+
+ if (poly)
+ {
+ Boolean fund (false);
+ IsFundamentalType traverser (fund);
+ traverser.dispatch (t);
+ poly = !fund;
+ }
+
+ if (max (e) != 1)
+ {
+ // sequence
+ //
+ os << "{"
+ << "const " << scope << "::" << econtainer (e) << "& c (" <<
+ "x." << aname << " ());"
+ << "s << ::xsd::cxx::tree::ostream_common::as_size< " <<
+ "::std::size_t > (c.size ());";
+
+ os << "for (" << scope << "::" << econst_iterator (e) << endl
+ << "i (c.begin ()), e (c.end ());" << endl
+ << "i != e; ++i)"
+ << "{";
+
+ if (poly)
+ {
+ os << "bool d (typeid (" << type << ") != typeid (*i));"
+ << "s << d;"
+ << "if (!d)" << endl
+ << "s << *i;"
+ << "else" << endl
+ << "::xsd::cxx::tree::stream_insertion_map_instance< 0, " <<
+ stream << ", " << char_type << " > ().insert (s, *i);";
+ }
+ else
+ os << "s << *i;";
+
+ os << "}" // for
+ << "}";
+ }
+ else if (min (e) == 0)
+ {
+ // optional
+ //
+ os << "{"
+ << "bool p (x." << aname << " ());"
+ << "s << p;"
+ << "if (p)";
+
+ if (poly)
+ {
+ os << "{"
+ << "const " << type << "& i (*x." << aname << " ());"
+ << "bool d (typeid (" << type << ") != typeid (i));"
+ << "s << d;"
+ << "if (!d)" << endl
+ << "s << i;"
+ << "else" << endl
+ << "::xsd::cxx::tree::stream_insertion_map_instance< 0, " <<
+ stream << ", " << char_type << " > ().insert (s, i);"
+ << "}";
+ }
+ else
+ os << endl
+ << "s << *x." << aname << " ();";
+
+ os << "}";
+ }
+ else
+ {
+ // one
+ //
+ if (poly)
+ {
+ os << "{"
+ << "const " << type << "& i (x." << aname << " ());"
+ << "bool d (typeid (" << type << ") != typeid (i));"
+ << "s << d;"
+ << "if (!d)" << endl
+ << "s << i;"
+ << "else" << endl
+ << "::xsd::cxx::tree::stream_insertion_map_instance< 0, " <<
+ stream << ", " << char_type << " > ().insert (s, i);"
+ << "}";
+ }
+ else
+ os << "s << x." << aname << " ();";
+ }
+ }
+
+ private:
+ String scope;
+ String stream;
+ };
+
+ struct Attribute : Traversal::Attribute, protected virtual Context
+ {
+ Attribute (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ String const& aname (eaname (a));
+
+ Boolean def (a.default_ () && !is_qname (a.type ()));
+
+ if (a.optional () && !def)
+ {
+ os << "{"
+ << "bool p (x." << aname << " ());"
+ << "s << p;"
+ << "if (p)" << endl
+ << "s << *x." << aname << " ();"
+ << "}";
+ }
+ else
+ {
+ os << "s << x." << aname << " ();";
+ }
+ }
+ };
+
+
+ struct Complex : Traversal::Complex, protected virtual Context
+ {
+ Complex (Context& c)
+ : Context (c), base_ (c)
+ {
+ inherits_ >> base_;
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ String name (ename (c));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (c, name) && !name)
+ return;
+
+ Boolean has_body (has<Traversal::Member> (c) || c.inherits_p ());
+
+ UnsignedLong n (0);
+ Streams const& st (options.value<CLI::generate_insertion> ());
+ for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i)
+ {
+ String stream_type ("::xsd::cxx::tree::ostream< " + *i + " >");
+
+ os << stream_type << "&" << endl
+ << "operator<< (" << stream_type << "& s," << endl
+ << "const " << name << "&" << (has_body ? " x" : "") << ")"
+ << "{";
+
+ if (c.inherits_p ())
+ {
+ os << "s << static_cast< const ";
+
+ inherits (c, inherits_);
+
+ os << "& > (x);";
+ }
+
+ {
+ Traversal::Names names_member;
+ Element element (*this, name, *i);
+ Attribute attribute (*this);
+
+ names_member >> element;
+ names_member >> attribute;
+
+ names (c, names_member);
+ }
+
+ os << "return s;"
+ << "}";
+
+
+ // Register with type map.
+ //
+ if (polymorphic && !c.context ().count ("anonymous"))
+ {
+ // Note that we are using the original type name.
+ //
+ String const& name (ename (c));
+
+ os << "static" << endl
+ << "const ::xsd::cxx::tree::stream_insertion_initializer< " <<
+ "0, " << i->c_str () << ", " <<
+ char_type << ", " << name << " >" << endl
+ << "_xsd_" << name << "_stream_insertion_init_" <<
+ n++ << " (" << endl
+ << L << strlit (c.name ()) << "," << endl
+ << L << strlit (xml_ns_name (c)) << ");"
+ << endl;
+ }
+ }
+ }
+
+ private:
+ Traversal::Inherits inherits_;
+ BaseTypeName base_;
+ };
+ }
+
+ Void
+ generate_stream_insertion_source (Context& ctx)
+ {
+ if (ctx.polymorphic)
+ {
+ Streams const& st (ctx.options.value<CLI::generate_insertion> ());
+
+ ctx.os << "#include <xsd/cxx/tree/stream-insertion-map.hxx>" << endl
+ << endl;
+
+ Boolean import_maps (ctx.options.value<CLI::import_maps> ());
+ Boolean export_maps (ctx.options.value<CLI::export_maps> ());
+
+ if (import_maps || export_maps)
+ {
+ ctx.os << "#ifdef _MSC_VER" << endl
+ << endl
+ << "namespace xsd"
+ << "{"
+ << "namespace cxx"
+ << "{"
+ << "namespace tree"
+ << "{";
+
+ for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i)
+ {
+ String stream (*i);
+
+ if (export_maps)
+ ctx.os << "template struct __declspec (dllexport) " <<
+ "stream_insertion_plate< 0, " << stream << ", " <<
+ ctx.char_type << " >;";
+
+ if (import_maps)
+ ctx.os << "template struct __declspec (dllimport) " <<
+ "stream_insertion_plate< 0, " << stream << ", " <<
+ ctx.char_type << " >;";
+ }
+
+ ctx.os << "}" // tree
+ << "}" // cxx
+ << "}" // xsd
+ << "#endif // _MSC_VER" << endl
+ << endl;
+ }
+
+ ctx.os << "namespace _xsd"
+ << "{";
+
+ UnsignedLong n (0);
+ for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i)
+ {
+ String stream (*i);
+
+ ctx.os << "static" << endl
+ << "const ::xsd::cxx::tree::stream_insertion_plate< 0, " <<
+ stream << ", " << ctx.char_type << " >" << endl
+ << "stream_insertion_plate_init_" << n++ << ";";
+ }
+
+ ctx.os << "}";
+ }
+
+ 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/xsd/cxx/tree/stream-insertion-source.hxx b/xsd/cxx/tree/stream-insertion-source.hxx
new file mode 100644
index 0000000..d5d4256
--- /dev/null
+++ b/xsd/cxx/tree/stream-insertion-source.hxx
@@ -0,0 +1,22 @@
+// file : xsd/cxx/tree/stream-insertion-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_TREE_INSERTION_SOURCE_HXX
+#define CXX_TREE_INSERTION_SOURCE_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/tree/elements.hxx>
+
+namespace CXX
+{
+ namespace Tree
+ {
+ Void
+ generate_stream_insertion_source (Context&);
+ }
+}
+
+#endif // CXX_TREE_INSERTION_SOURCE_HXX
diff --git a/xsd/cxx/tree/stream-source.cxx b/xsd/cxx/tree/stream-source.cxx
new file mode 100644
index 0000000..e30a4ab
--- /dev/null
+++ b/xsd/cxx/tree/stream-source.cxx
@@ -0,0 +1,489 @@
+// file : xsd/cxx/tree/stream-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/tree/stream-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Tree
+ {
+ namespace
+ {
+ struct List : Traversal::List, protected virtual Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String name (ename (l));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (l, name) && !name)
+ return;
+
+ SemanticGraph::Type& item_type (l.argumented ().type ());
+ String base (L"::xsd::cxx::tree::list< " +
+ item_type_name (item_type) + L", " + char_type);
+
+ if (item_type.is_a<SemanticGraph::Fundamental::Double> ())
+ base += L", ::xsd::cxx::tree::schema_type::double_";
+ else if (item_type.is_a<SemanticGraph::Fundamental::Decimal> ())
+ base += L", ::xsd::cxx::tree::schema_type::decimal";
+
+ base += L" >";
+
+ os << std_ostream_type << "&" << endl
+ << "operator<< (" << std_ostream_type << "& o, " <<
+ "const " << name << "& i)"
+ << "{"
+ << "return o << static_cast< const " << base << "& > (i);"
+ << "}";
+
+ // Register with ostream map.
+ //
+ if (polymorphic && !l.context ().count ("anonymous"))
+ {
+ // Note that we are using the original type name.
+ //
+ String const& name (ename (l));
+
+ os << "static" << endl
+ << "const ::xsd::cxx::tree::std_ostream_initializer< 0, " <<
+ char_type << ", " << name << " >" << endl
+ << "_xsd_" << name << "_std_ostream_init;"
+ << endl;
+ }
+ }
+
+ private:
+ String
+ item_type_name (SemanticGraph::Type& t)
+ {
+ std::wostringstream o;
+
+ MemberTypeName type (*this, o);
+ type.dispatch (t);
+
+ return o.str ();
+ }
+ };
+
+
+ struct Union : Traversal::Union, protected virtual Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ String name (ename (u));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (u, name) && !name)
+ return;
+
+ os << std_ostream_type << "&" << endl
+ << "operator<< (" << std_ostream_type << "& o, " <<
+ "const " << name << "& i)"
+ << "{"
+ << "return o << static_cast< const " << xs_string_type << "& > (i);"
+ << "}";
+
+ // Register with ostream map.
+ //
+ if (polymorphic && !u.context ().count ("anonymous"))
+ {
+ // Note that we are using the original type name.
+ //
+ String const& name (ename (u));
+
+ os << "static" << endl
+ << "const ::xsd::cxx::tree::std_ostream_initializer< 0, " <<
+ char_type << ", " << name << " >" << endl
+ << "_xsd_" << name << "_std_ostream_init;"
+ << endl;
+ }
+ }
+ };
+
+
+ struct Enumeration : Traversal::Enumeration, protected virtual Context
+ {
+ Enumeration (Context& c)
+ : Context (c), base_ (c)
+ {
+ inherits_base_ >> base_;
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ String name (ename (e));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (e, name) && !name)
+ return;
+
+ Boolean string_based (false);
+ {
+ IsStringBasedType t (string_based);
+ t.dispatch (e);
+ }
+
+ Boolean enum_based (false);
+ if (string_based)
+ {
+ SemanticGraph::Enumeration* be (0);
+ IsEnumBasedType t (be);
+ t.dispatch (e);
+
+ enum_based = (be != 0);
+ }
+
+ // If we are based on an enum then the value type is just an
+ // alias and we don't need to generate this operator again.
+ //
+ if (string_based && !enum_based)
+ {
+ os << std_ostream_type << "&" << endl
+ << "operator<< (" << std_ostream_type << "& o, " <<
+ name << "::" << evalue (e) << " i)"
+ << "{"
+ << "return o << " << name << "::_xsd_" << name <<
+ "_literals_[i];"
+ << "}";
+ }
+
+ os << std_ostream_type << "&" << endl
+ << "operator<< (" << std_ostream_type << "& o, " <<
+ "const " << name << "& i)"
+ << "{"
+ << "return o << static_cast< const ";
+
+ inherits (e, inherits_base_);
+
+ os << "& > (i);"
+ << "}";
+
+ // Register with ostream map.
+ //
+ if (polymorphic && !e.context ().count ("anonymous"))
+ {
+ // Note that we are using the original type name.
+ //
+ String const& name (ename (e));
+
+ os << "static" << endl
+ << "const ::xsd::cxx::tree::std_ostream_initializer< 0, " <<
+ char_type << ", " << name << " >" << endl
+ << "_xsd_" << name << "_std_ostream_init;"
+ << endl;
+ }
+ }
+
+ private:
+ Traversal::Inherits inherits_base_;
+ BaseTypeName base_;
+ };
+
+ struct Element : Traversal::Element, protected virtual Context
+ {
+ Element (Context& c, String const& scope_)
+ : Context (c), scope (scope_)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (skip (e))
+ return;
+
+ String const& aname (eaname (e));
+
+ // Check if we need to handle xsi:type and substitution groups.
+ // If this element's type is anonymous or mapped to a fundamental
+ // C++ type then we don't need to do anything. Note that if the
+ // type is anonymous then it can't be derived from which makes it
+ // impossible to substitute or dynamically-type with xsi:type.
+ //
+ SemanticGraph::Type& t (e.type ());
+ Boolean poly (polymorphic && !t.context ().count ("anonymous"));
+
+ if (poly)
+ {
+ Boolean fund (false);
+ IsFundamentalType traverser (fund);
+ traverser.dispatch (t);
+ poly = !fund;
+ }
+
+ // aCC cannot handle an inline call to std_ostream_map_instance.
+ //
+ if (poly)
+ {
+ os << "{"
+ << "::xsd::cxx::tree::std_ostream_map< " << char_type
+ << " >& om (" << endl
+ << "::xsd::cxx::tree::std_ostream_map_instance< 0, " <<
+ char_type << " > ());"
+ << endl;
+ }
+
+ if (max (e) != 1)
+ {
+ // sequence
+ //
+ os << "for (" << scope << "::" << econst_iterator (e) << endl
+ << "b (i." << aname << " ().begin ()), " <<
+ "e (i." << aname << " ().end ());" << endl
+ << "b != e; ++b)"
+ << "{"
+ << "o << ::std::endl << " << L << strlit (e.name () + L": ");
+
+ if (!poly)
+ os << " << *b;";
+ else
+ os << ";"
+ << "om.insert (o, *b);";
+
+ os << "}";
+ }
+ else if (min (e) == 0)
+ {
+ // optional
+ //
+
+ os << "if (i." << aname << " ())"
+ << "{"
+ << "o << ::std::endl << " << L << strlit (e.name () + L": ");
+
+ if (!poly)
+ os << " << *i." << aname << " ();";
+ else
+ os << ";"
+ << "om.insert (o, *i." << aname << " ());";
+
+ os << "}";
+ }
+ else
+ {
+ // one
+ //
+ os << "o << ::std::endl << " << L << strlit (e.name () + L": ");
+
+ if (!poly)
+ os << " << i." << aname << " ();";
+ else
+ os << ";"
+ << "om.insert (o, i." << aname << " ());";
+ }
+
+ if (poly)
+ os << "}";
+ }
+
+ private:
+ String scope;
+ };
+
+ struct Attribute : Traversal::Attribute, protected virtual Context
+ {
+ Attribute (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ String const& aname (eaname (a));
+
+ Boolean def (a.default_ () && !is_qname (a.type ()));
+
+ if (a.optional () && !def)
+ {
+ os << "if (i." << aname << " ())"
+ << "{"
+ << "o << ::std::endl << " << L << strlit (a.name () + L": ") <<
+ " << *i." << aname << " ();"
+ << "}";
+ }
+ else
+ {
+ os << "o << ::std::endl << " << L << strlit (a.name () + L": ") <<
+ " << i." << aname << " ();";
+ }
+ }
+ };
+
+
+ struct Complex : Traversal::Complex, protected virtual Context
+ {
+ Complex (Context& c)
+ : Context (c), base_ (c)
+ {
+ inherits_ >> base_;
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ String name (ename (c));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (c, name) && !name)
+ return;
+
+ //
+ //
+ Boolean has_body (has<Traversal::Member> (c) || c.inherits_p ());
+
+ os << std_ostream_type << "&" << endl
+ << "operator<< (" << std_ostream_type << "& o, " <<
+ "const " << name << "&" << (has_body ? " i" : "") << ")"
+ << "{";
+
+ if (c.inherits_p ())
+ {
+ os << "o << static_cast< const ";
+
+ inherits (c, inherits_);
+
+ os << "& > (i);"
+ << endl;
+ }
+
+ {
+ Traversal::Names names_member;
+ Element element (*this, name);
+ Attribute attribute (*this);
+
+ names_member >> element;
+ names_member >> attribute;
+
+ names (c, names_member);
+ }
+
+ os << "return o;"
+ << "}";
+
+ // Register with ostream map.
+ //
+ if (polymorphic && !c.context ().count ("anonymous"))
+ {
+ // Note that we are using the original type name.
+ //
+ String const& name (ename (c));
+
+ os << "static" << endl
+ << "const ::xsd::cxx::tree::std_ostream_initializer< 0, " <<
+ char_type << ", " << name << " >" << endl
+ << "_xsd_" << name << "_std_ostream_init;"
+ << endl;
+ }
+ }
+
+ private:
+ Traversal::Inherits inherits_;
+ BaseTypeName base_;
+ };
+ }
+
+ Void
+ generate_stream_source (Context& ctx,
+ UnsignedLong first,
+ UnsignedLong last)
+ {
+ String c (ctx.char_type);
+
+ ctx.os << "#include <ostream>" << endl
+ << endl;
+
+ if (ctx.polymorphic)
+ {
+ ctx.os << "#include <xsd/cxx/tree/std-ostream-map.hxx>" << endl
+ << endl;
+
+ Boolean import_maps (ctx.options.value<CLI::import_maps> ());
+ Boolean export_maps (ctx.options.value<CLI::export_maps> ());
+
+ if (import_maps || export_maps)
+ {
+ ctx.os << "#ifdef _MSC_VER" << endl
+ << endl
+ << "namespace xsd"
+ << "{"
+ << "namespace cxx"
+ << "{"
+ << "namespace tree"
+ << "{";
+
+ if (export_maps)
+ ctx.os << "template struct __declspec (dllexport) " <<
+ "std_ostream_plate< 0, " << ctx.char_type << " >;";
+
+ if (import_maps)
+ ctx.os << "template struct __declspec (dllimport) " <<
+ "std_ostream_plate< 0, " << ctx.char_type << " >;";
+
+ ctx.os << "}" // tree
+ << "}" // cxx
+ << "}" // xsd
+ << "#endif // _MSC_VER" << endl
+ << endl;
+ }
+
+ ctx.os << "namespace _xsd"
+ << "{"
+ << "static" << endl
+ << "const ::xsd::cxx::tree::std_ostream_plate< 0, " <<
+ ctx.char_type << " >" << endl
+ << "std_ostream_plate_init;"
+ << "}";
+ }
+
+ Traversal::Schema schema;
+
+ Traversal::Sources sources;
+ Traversal::Names names_ns, names;
+
+ Namespace ns (ctx, first, last);
+
+ 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/xsd/cxx/tree/stream-source.hxx b/xsd/cxx/tree/stream-source.hxx
new file mode 100644
index 0000000..2b2e436
--- /dev/null
+++ b/xsd/cxx/tree/stream-source.hxx
@@ -0,0 +1,24 @@
+// file : xsd/cxx/tree/stream-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_TREE_STREAM_SOURCE_HXX
+#define CXX_TREE_STREAM_SOURCE_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/tree/elements.hxx>
+
+namespace CXX
+{
+ namespace Tree
+ {
+ Void
+ generate_stream_source (Context&,
+ UnsignedLong first,
+ UnsignedLong last);
+ }
+}
+
+#endif // CXX_TREE_STREAM_SOURCE_HXX
diff --git a/xsd/cxx/tree/tree-forward.cxx b/xsd/cxx/tree/tree-forward.cxx
new file mode 100644
index 0000000..8ba8bc1
--- /dev/null
+++ b/xsd/cxx/tree/tree-forward.cxx
@@ -0,0 +1,324 @@
+// file : xsd/cxx/tree/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/tree/tree-forward.hxx>
+#include <cxx/tree/fundamental-header.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Tree
+ {
+ namespace
+ {
+ struct List : Traversal::List,
+ protected virtual Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String const& name (ename (l));
+
+ if (String custom = custom_type (l))
+ {
+ String new_name;
+ renamed_type (l, new_name);
+
+ if (new_name)
+ os << "class " << new_name << ";";
+
+ if (custom == name)
+ os << "class " << name << ";";
+ else
+ os << "typedef " << custom << " " << name << ";";
+ }
+ else
+ os << "class " << name << ";";
+ }
+ };
+
+ struct Union : Traversal::Union,
+ protected virtual Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ String const& name (ename (u));
+
+ if (String custom = custom_type (u))
+ {
+ String new_name;
+ renamed_type (u, new_name);
+
+ if (new_name)
+ os << "class " << new_name << ";";
+
+ if (custom == name)
+ os << "class " << name << ";";
+ else
+ os << "typedef " << custom << " " << name << ";";
+ }
+ else
+ os << "class " << name << ";";
+ }
+ };
+
+ struct Enumeration : Traversal::Enumeration,
+ protected virtual Context
+ {
+ Enumeration (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ String const& name (ename (e));
+
+ if (String custom = custom_type (e))
+ {
+ String new_name;
+ renamed_type (e, new_name);
+
+ if (new_name)
+ os << "class " << new_name << ";";
+
+ if (custom == name)
+ os << "class " << name << ";";
+ else
+ os << "typedef " << custom << " " << name << ";";
+ }
+ else
+ os << "class " << name << ";";
+ }
+ };
+
+ struct Complex : Traversal::Complex,
+ protected virtual Context
+ {
+ Complex (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ String const& name (ename (c));
+
+ if (String custom = custom_type (c))
+ {
+ String new_name;
+ renamed_type (c, new_name);
+
+ if (new_name)
+ os << "class " << new_name << ";";
+
+ if (custom == name)
+ os << "class " << name << ";";
+ else
+ os << "typedef " << custom << " " << name << ";";
+ }
+ else
+ os << "class " << name << ";";
+ }
+ };
+ }
+
+ Void
+ generate_forward (Context& ctx)
+ {
+ NarrowString xml_schema (ctx.options.value<CLI::extern_xml_schema> ());
+
+ // Inlcude or Emit fundamental types.
+ //
+ if (xml_schema)
+ {
+ String name (ctx.hxx_expr->merge (xml_schema));
+
+ ctx.os << "#include " << ctx.process_include_path (name) << endl
+ << endl;
+ }
+ else
+ {
+ ctx.os << "#include <xsd/cxx/tree/exceptions.hxx>" << endl
+ << "#include <xsd/cxx/tree/elements.hxx>" << endl
+ << "#include <xsd/cxx/tree/types.hxx>" << endl
+ << endl;
+
+ if (!ctx.options.value<CLI::suppress_parsing> () ||
+ ctx.options.value<CLI::generate_serialization> ())
+ {
+ ctx.os << "#include <xsd/cxx/xml/error-handler.hxx>" << endl
+ << endl;
+ }
+
+ if (!ctx.options.value<CLI::suppress_parsing> () ||
+ ctx.options.value<CLI::generate_serialization> ())
+ {
+ ctx.os << "#include <xsd/cxx/xml/dom/auto-ptr.hxx>" << endl
+ << endl;
+ }
+
+ Boolean element_map (ctx.options.value<CLI::generate_element_map> ());
+
+ if (element_map)
+ ctx.os << "#include <xsd/cxx/tree/element-map.hxx>" << endl
+ << endl;
+
+ // I need to include all the "optional" headers here (instead of
+ // later in the individual generators for each feature because
+ // those headers provide implementation for the fundamental types.
+ //
+ if (!ctx.options.value<CLI::suppress_parsing> ())
+ {
+ ctx.os << "#include <xsd/cxx/tree/parsing.hxx>" << endl;
+
+ Traversal::Schema schema, xsd;
+ Traversal::Implies implies;
+ Traversal::Names names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+ FundIncludes type (ctx, "parsing");
+
+ schema >> implies >> xsd >> names >> ns >> ns_names >> type;
+
+ schema.dispatch (ctx.schema_root);
+
+ if (element_map)
+ ctx.os << "#include <xsd/cxx/tree/parsing/element-map.txx>" <<
+ endl;
+
+ ctx.os << endl;
+ }
+
+ if (ctx.options.value<CLI::generate_serialization> ())
+ {
+ ctx.os << "#include <xsd/cxx/xml/dom/serialization-header.hxx>" << endl
+ << "#include <xsd/cxx/tree/serialization.hxx>" << endl;
+
+ Traversal::Schema schema, xsd;
+ Traversal::Implies implies;
+ Traversal::Names names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+ FundIncludes type (ctx, "serialization");
+
+ schema >> implies >> xsd >> names >> ns >> ns_names >> type;
+
+ schema.dispatch (ctx.schema_root);
+
+ if (element_map)
+ ctx.os << "#include <xsd/cxx/tree/serialization/element-map.txx>" <<
+ endl;
+
+ ctx.os << endl;
+ }
+
+ if (ctx.options.value<CLI::generate_ostream> ())
+ {
+ ctx.os << "#include <xsd/cxx/tree/std-ostream-operators.hxx>" << endl
+ << endl;
+ }
+
+ typedef Containers::Vector<NarrowString> Streams;
+
+ Streams const& ist (ctx.options.value<CLI::generate_insertion> ());
+ if (!ist.empty ())
+ {
+ for (Streams::ConstIterator i (ist.begin ()); i != ist.end (); ++i)
+ {
+ if (*i == "ACE_OutputCDR")
+ ctx.os << "#include <xsd/cxx/tree/ace-cdr-stream-insertion.hxx>"
+ << endl;
+ else if (*i == "XDR")
+ ctx.os << "#include <xsd/cxx/tree/xdr-stream-insertion.hxx>"
+ << endl;
+ }
+
+ ctx.os << "#include <xsd/cxx/tree/stream-insertion.hxx>" << endl
+ << endl;
+ }
+
+ Streams const& est (ctx.options.value<CLI::generate_extraction> ());
+ if (!est.empty ())
+ {
+ for (Streams::ConstIterator i (est.begin ()); i != est.end (); ++i)
+ {
+ if (*i == "ACE_InputCDR")
+ ctx.os << "#include <xsd/cxx/tree/ace-cdr-stream-extraction.hxx>"
+ << endl;
+ else if (*i == "XDR")
+ ctx.os << "#include <xsd/cxx/tree/xdr-stream-extraction.hxx>"
+ << endl;
+ }
+
+ ctx.os << "#include <xsd/cxx/tree/stream-extraction.hxx>" << endl
+ << endl;
+ }
+
+
+ Traversal::Schema schema, xsd;
+ Traversal::Implies implies;
+ Traversal::Names names;
+ FundamentalNamespace ns (ctx);
+
+ schema >> implies >> xsd >> names >> ns;
+
+ schema.dispatch (ctx.schema_root);
+ }
+
+ // First emit header includes.
+ //
+ if (ctx.options.value<CLI::generate_forward> ())
+ {
+ Traversal::Schema schema;
+ Includes includes (ctx, Includes::forward);
+
+ schema >> includes;
+
+ schema.dispatch (ctx.schema_root);
+ }
+
+ ctx.os << "// Forward declarations." << 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);
+
+ ctx.os << endl;
+ }
+ }
+}
diff --git a/xsd/cxx/tree/tree-forward.hxx b/xsd/cxx/tree/tree-forward.hxx
new file mode 100644
index 0000000..140f8ee
--- /dev/null
+++ b/xsd/cxx/tree/tree-forward.hxx
@@ -0,0 +1,22 @@
+// file : xsd/cxx/tree/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_TREE_TREE_FORWARD_HXX
+#define CXX_TREE_TREE_FORWARD_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/tree/elements.hxx>
+
+namespace CXX
+{
+ namespace Tree
+ {
+ Void
+ generate_forward (Context&);
+ }
+}
+
+#endif // CXX_TREE_TREE_FORWARD_HXX
diff --git a/xsd/cxx/tree/tree-header.cxx b/xsd/cxx/tree/tree-header.cxx
new file mode 100644
index 0000000..6b1490c
--- /dev/null
+++ b/xsd/cxx/tree/tree-header.cxx
@@ -0,0 +1,3778 @@
+// file : xsd/cxx/tree/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/tree/tree-header.hxx>
+#include <cxx/tree/fundamental-header.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Tree
+ {
+ namespace
+ {
+ typedef Containers::Vector<NarrowString> Streams;
+
+ // List mapping.
+ //
+ struct List: Traversal::List, protected virtual Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String name (ename (l));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (l, name) && !name)
+ return;
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief List class corresponding to the %" <<
+ comment (l.name ()) << endl
+ << " * schema type." << endl
+ << " *" << endl
+ << " * This class has an interface of a standard C++ " <<
+ "sequence (e.g.," << endl
+ << " * std::vector)." << endl;
+
+ if (l.annotated ())
+ {
+ os << " *" << endl;
+ write_annotation (l.annotation ());
+ }
+
+ os << " */" << endl;
+ }
+
+ SemanticGraph::Type& item_type (l.argumented ().type ());
+ String item_name (item_type_name (item_type));
+ String base_type (L"::xsd::cxx::tree::list< " + item_name + L", " +
+ char_type);
+
+ if (item_type.is_a<SemanticGraph::Fundamental::Double> ())
+ base_type += L", ::xsd::cxx::tree::schema_type::double_";
+ else if (item_type.is_a<SemanticGraph::Fundamental::Decimal> ())
+ base_type += L", ::xsd::cxx::tree::schema_type::decimal";
+
+ base_type += L" >";
+
+ os << "class " << type_exp << name <<
+ ": public " << any_simple_type << "," << endl
+ << " public " << base_type
+ << "{"
+ << "public:" << endl;
+
+ // c-tor ()
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Default constructor." << endl
+ << " *" << endl
+ << " * Creates an empty list." << endl
+ << " */" << endl;
+ }
+ os << name << " ();"
+ << endl;
+
+ // c-tor (size_type, const X& x)
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create a list with copies of the specified " <<
+ "element." << endl
+ << " *" << endl
+ << " * @param n A number of elements to copy." << endl
+ << " * @param x An element to copy." << endl
+ << " *" << endl
+ << " * This constructor creates a list with @a n copies " <<
+ "of @a x." << endl
+ << " */" << endl;
+ }
+
+ String size_type (name != L"size_type"
+ ? String (L"size_type")
+ : base_type + L"::size_type");
+
+ os << name << " (" << size_type << " n, const " << item_name <<
+ "& x);"
+ << endl;
+
+ // c-tor (const I& begin, const I& end)
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create a list from an iterator range." << endl
+ << " *" << endl
+ << " * @param begin An iterator pointing to the first " <<
+ "element." << endl
+ << " * @param end An iterator pointing to the one past " <<
+ "the last element." << endl
+ << " *" << endl
+ << " * This constructor creates a list consisting of " <<
+ "copies of the" << endl
+ << " * elements in the range [begin,end)." << endl
+ << " */" << endl;
+ }
+
+ String iter_type (unclash (name, "I"));
+
+ os << "template < typename " << iter_type << " >" << endl
+ << name << " (const " << iter_type << "& begin, const " <<
+ iter_type << "& end)" << endl
+ << ": " << base_type << " (begin, end)"
+ << "{"
+ << "}";
+
+ // c-tor (istream&)
+ //
+ Streams const& st (options.value<CLI::generate_extraction> ());
+ for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i)
+ {
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from a data " <<
+ "representation" << endl
+ << " * stream." << endl
+ << " *" << endl
+ << " * @param s A stream to extract the data from." << endl
+ << " * @param f Flags to create the new instance with." << endl
+ << " * @param c A pointer to the object that will " <<
+ "contain the new" << endl
+ << " * instance." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (" << istream_type << "< " << i->c_str () <<
+ " >& s," << endl
+ << flags_type << " f = 0," << endl
+ << container << "* c = 0);"
+ << endl;
+ }
+
+ if (!options.value<CLI::suppress_parsing> ())
+ {
+ // c-tor (xercesc::DOMElement)
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from a DOM element." << endl
+ << " *" << endl
+ << " * @param e A DOM element to extract the data from." << endl
+ << " * @param f Flags to create the new instance with." << endl
+ << " * @param c A pointer to the object that will " <<
+ "contain the new" << endl
+ << " * instance." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (const " << xerces_ns << "::DOMElement& e," << endl
+ << flags_type << " f = 0," << endl
+ << container << "* c = 0);"
+ << endl;
+
+ // c-tor (xercesc::DOMAttr)
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from a DOM attribute." << endl
+ << " *" << endl
+ << " * @param a A DOM attribute to extract the data from." << endl
+ << " * @param f Flags to create the new instance with." << endl
+ << " * @param c A pointer to the object that will " <<
+ "contain the new" << endl
+ << " * instance." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (const " << xerces_ns << "::DOMAttr& a," << endl
+ << flags_type << " f = 0," << endl
+ << container << "* c = 0);"
+ << endl;
+
+ // c-tor (std::basic_string const&, xercesc::DOMElement)
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from a string fragment." << endl
+ << " *" << endl
+ << " * @param s A string fragment to extract the data from." << endl
+ << " * @param e A pointer to DOM element containing the " <<
+ "string fragment." << endl
+ << " * @param f Flags to create the new instance with." << endl
+ << " * @param c A pointer to the object that will " <<
+ "contain the new" << endl
+ << " * instance." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (const " << string_type << "& s," << endl
+ << "const " << xerces_ns << "::DOMElement* e," << endl
+ << flags_type << " f = 0," << endl
+ << container << "* c = 0);"
+ << endl;
+ }
+
+ // copy c-tor ()
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Copy constructor." << endl
+ << " *" << endl
+ << " * @param x An instance to make a copy of." << endl
+ << " * @param f Flags to create the copy with." << endl
+ << " * @param c A pointer to the object that will contain " <<
+ "the copy." << endl
+ << " *" << endl
+ << " * For polymorphic object models use the @c _clone " <<
+ "function instead." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (const " << name << "& x," << endl
+ << flags_type << " f = 0," << endl
+ << container << "* c = 0);"
+ << endl;
+
+ // clone
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Copy the instance polymorphically." << endl
+ << " *" << endl
+ << " * @param f Flags to create the copy with." << endl
+ << " * @param c A pointer to the object that will contain " <<
+ "the copy." << endl
+ << " * @return A pointer to the dynamically allocated copy." << endl
+ << " *" << endl
+ << " * This function ensures that the dynamic type of the " <<
+ "instance is" << endl
+ << " * used for copying and should be used for polymorphic " <<
+ "object" << endl
+ << " * models instead of the copy constructor." << endl
+ << " */" << endl;
+ }
+
+ os << "virtual " << name << "*" << endl
+ << "_clone (" << flags_type << " f = 0," << endl
+ << container << "* c = 0) const;"
+ << endl;
+
+ // d-tor
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Destructor." << endl
+ << " */" << endl;
+ }
+
+ os << "virtual " << endl
+ << "~" << name << " ();";
+
+ os << "};";
+ }
+
+ private:
+ String
+ item_type_name (SemanticGraph::Type& t)
+ {
+ std::wostringstream o;
+
+ MemberTypeName type (*this, o);
+ type.dispatch (t);
+
+ return o.str ();
+ }
+ };
+
+
+ // Union mapping.
+ //
+ struct Union: Traversal::Union, protected virtual Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ String name (ename (u));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (u, name) && !name)
+ return;
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Union class corresponding to the %" <<
+ comment (u.name ()) << endl
+ << " * schema type." << endl
+ << " *" << endl
+ << " * The mapping represents unions as strings." << endl;
+
+ if (u.annotated ())
+ {
+ os << " *" << endl;
+ write_annotation (u.annotation ());
+ }
+
+ os << " */" << endl;
+ }
+
+ os << "class " << type_exp << name <<
+ ": public " << xs_string_type
+ << "{"
+ << "public:" << endl
+ << endl;
+
+ if (options.value<CLI::generate_default_ctor> ())
+ {
+ // c-tor ()
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Default constructor." << endl
+ << " *" << endl
+ << " * Note that this constructor may leave the " <<
+ "instance in an" << endl
+ << " * invalid state." << endl
+ << " */" << endl;
+ }
+
+ os << name << " ();"
+ << endl;
+ }
+
+ // c-tor (const char*)
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from a C string." << endl
+ << " *" << endl
+ << " * @param v A string value." << endl
+ << " */" << endl;
+ }
+ os << name << " (const " << char_type << "* v);"
+ << endl;
+
+ // c-tor (string const&)
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from a string." << endl
+ << " *" << endl
+ << " * @param v A string value." << endl
+ << " */" << endl;
+ }
+ os << name << " (const " << string_type << "& v);"
+ << endl;
+
+ // c-tor (istream&)
+ //
+ Streams const& st (options.value<CLI::generate_extraction> ());
+ for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i)
+ {
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from a data " <<
+ "representation" << endl
+ << " * stream." << endl
+ << " *" << endl
+ << " * @param s A stream to extract the data from." << endl
+ << " * @param f Flags to create the new instance with." << endl
+ << " * @param c A pointer to the object that will " <<
+ "contain the new" << endl
+ << " * instance." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (" << istream_type << "< " << i->c_str () <<
+ " >& s," << endl
+ << flags_type << " f = 0," << endl
+ << container << "* c = 0);"
+ << endl;
+ }
+
+ if (!options.value<CLI::suppress_parsing> ())
+ {
+ // c-tor (xercesc::DOMElement)
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from a DOM element." << endl
+ << " *" << endl
+ << " * @param e A DOM element to extract the data from." << endl
+ << " * @param f Flags to create the new instance with." << endl
+ << " * @param c A pointer to the object that will " <<
+ "contain the new" << endl
+ << " * instance." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (const " << xerces_ns << "::DOMElement& e," << endl
+ << flags_type << " f = 0," << endl
+ << container << "* c = 0);"
+ << endl;
+
+ // c-tor (xercesc::DOMAttr)
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from a DOM attribute." << endl
+ << " *" << endl
+ << " * @param a A DOM attribute to extract the data from." << endl
+ << " * @param f Flags to create the new instance with." << endl
+ << " * @param c A pointer to the object that will " <<
+ "contain the new" << endl
+ << " * instance." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (const " << xerces_ns << "::DOMAttr& a," << endl
+ << flags_type << " f = 0," << endl
+ << container << "* c = 0);"
+ << endl;
+
+ // c-tor (std::basic_string const&, xercesc::DOMElement)
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from a string fragment." << endl
+ << " *" << endl
+ << " * @param s A string fragment to extract the data from." << endl
+ << " * @param e A pointer to DOM element containing the " <<
+ "string fragment." << endl
+ << " * @param f Flags to create the new instance with." << endl
+ << " * @param c A pointer to the object that will " <<
+ "contain the new" << endl
+ << " * instance." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (const " << string_type << "& s," << endl
+ << "const " << xerces_ns << "::DOMElement* e," << endl
+ << flags_type << " f = 0," << endl
+ << container << "* c = 0);"
+ << endl;
+ }
+
+ // copy c-tor ()
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Copy constructor." << endl
+ << " *" << endl
+ << " * @param x An instance to make a copy of." << endl
+ << " * @param f Flags to create the copy with." << endl
+ << " * @param c A pointer to the object that will contain " <<
+ "the copy." << endl
+ << " *" << endl
+ << " * For polymorphic object models use the @c _clone " <<
+ "function instead." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (const " << name << "& x," << endl
+ << flags_type << " f = 0," << endl
+ << container << "* c = 0);"
+ << endl;
+
+ // clone
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Copy the instance polymorphically." << endl
+ << " *" << endl
+ << " * @param f Flags to create the copy with." << endl
+ << " * @param c A pointer to the object that will contain " <<
+ "the copy." << endl
+ << " * @return A pointer to the dynamically allocated copy." << endl
+ << " *" << endl
+ << " * This function ensures that the dynamic type of the " <<
+ "instance is" << endl
+ << " * used for copying and should be used for polymorphic " <<
+ "object" << endl
+ << " * models instead of the copy constructor." << endl
+ << " */" << endl;
+ }
+
+ os << "virtual " << name << "*" << endl
+ << "_clone (" << flags_type << " f = 0," << endl
+ << container << "* c = 0) const;"
+ << endl;
+
+ os << "};";
+ }
+ };
+
+ // Enum mapping.
+ //
+ struct Enumerator: Traversal::Enumerator, protected virtual Context
+ {
+ Enumerator (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (doxygen && e.annotated ())
+ {
+ os << "/**" << endl;
+ write_annotation (e.annotation ());
+ os << " */" << endl;
+ }
+
+ os << ename (e);
+ }
+ };
+
+ struct Enumeration: Traversal::Enumeration, protected virtual Context
+ {
+ Enumeration (Context& c)
+ : Context (c),
+ base_ (c),
+ member_ (c),
+ enumerator_ (c)
+ {
+ inherits_base_ >> base_;
+ inherits_member_ >> member_;
+
+ names_ >> enumerator_;
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ String name (ename (e));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (e, name) && !name)
+ return;
+
+ Boolean string_based (false);
+ {
+ IsStringBasedType t (string_based);
+ t.dispatch (e);
+ }
+
+ Boolean enum_based (false);
+ SemanticGraph::Enumeration* base_enum (0);
+
+ if (string_based)
+ {
+ IsEnumBasedType t (base_enum);
+ t.dispatch (e);
+
+ if (base_enum != 0)
+ enum_based = true;
+ }
+
+ String value;
+ if (string_based)
+ value = evalue (e);
+
+ // Get to the ultimate base and see if is a fundamental type.
+ //
+ Boolean fund_based (false);
+ SemanticGraph::Type& ult_base (ultimate_base (e));
+ {
+ IsFundamentalType t (fund_based);
+ t.dispatch (ult_base);
+ }
+
+ // Count enumerators.
+ //
+ UnsignedLong enum_count (0);
+
+ for (Type::NamesIterator i (e.names_begin ()), end (e.names_end ());
+ i != end; ++i)
+ ++enum_count;
+
+ //
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Enumeration class corresponding to the %" <<
+ comment (e.name ()) << endl
+ << " * schema type." << endl;
+
+ if (e.annotated ())
+ {
+ os << " *" << endl;
+ write_annotation (e.annotation ());
+ }
+
+ os << " */" << endl;
+ }
+
+ os << "class " << type_exp << name << ": public ";
+
+ // Enumeration always has a base.
+ //
+ inherits (e, inherits_base_);
+
+ os << "{"
+ << "public:" << endl;
+
+ if (string_based)
+ {
+ if (doxygen)
+ {
+ os << endl
+ << "/**" << endl
+ << " * @brief Underlying enum type." << endl
+ << " */" << endl;
+ }
+
+ if (enum_based)
+ {
+ os << "typedef ";
+
+ inherits (e, inherits_base_);
+
+ os << "::" << evalue (*base_enum) << " " << value << ";"
+ << endl;
+ }
+ else
+ {
+ os << "enum " << value
+ << "{";
+
+ names<Enumeration> (e, names_, 0, 0, 0, &Enumeration::comma);
+
+ os << "};";
+ }
+ }
+
+ // default c-tor
+ //
+ if (options.value<CLI::generate_default_ctor> ())
+ {
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Default constructor." << endl
+ << " *" << endl
+ << " * Note that this constructor may leave the " <<
+ "instance in an" << endl
+ << " * invalid state." << endl
+ << " */" << endl;
+ }
+
+ os << name << " ();"
+ << endl;
+ }
+
+ // c-tor (value)
+ //
+ if (string_based)
+ {
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from the " <<
+ "underlying enum value." << endl
+ << " *" << endl
+ << " * @param v A enum value." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (" << value << " v);"
+ << endl;
+ }
+
+ // c-tor (const char*)
+ //
+ if (string_based)
+ {
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from a C string." << endl
+ << " *" << endl
+ << " * @param v A string value." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (const " << char_type << "* v);"
+ << endl;
+ }
+
+ // c-tor (const std::string&)
+ //
+ if (string_based)
+ {
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from a string." << endl
+ << " *" << endl
+ << " * @param v A string value." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (const " << string_type << "& v);"
+ << endl;
+ }
+
+ // c-tor (fundamental)
+ //
+ if (fund_based)
+ {
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from a fundamental " <<
+ "type value." << endl
+ << " *" << endl
+ << " * @param v A fundamental type value." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (";
+
+ member_.dispatch (ult_base);
+
+ os << " v);"
+ << endl;
+ }
+
+ // c-tor (base)
+ //
+ // If the ultimate is also our immediate base and it is a
+ // fundamental type then this c-tor clashes with c-tor
+ // (fundamental) above.
+ //
+ if (!fund_based || &ult_base != &e.inherits ().base ())
+ {
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from the " <<
+ "base value." << endl
+ << " *" << endl
+ << " * @param v A base value." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (const ";
+
+ inherits (e, inherits_member_);
+
+ os << "& v);"
+ << endl;
+ }
+
+
+ // c-tor (istream&)
+ //
+ Streams const& st (options.value<CLI::generate_extraction> ());
+ for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i)
+ {
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from a data " <<
+ "representation" << endl
+ << " * stream." << endl
+ << " *" << endl
+ << " * @param s A stream to extract the data from." << endl
+ << " * @param f Flags to create the new instance with." << endl
+ << " * @param c A pointer to the object that will " <<
+ "contain the new" << endl
+ << " * instance." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (" << istream_type << "< " << i->c_str () <<
+ " >& s," << endl
+ << flags_type << " f = 0," << endl
+ << container << "* c = 0);"
+ << endl;
+ }
+
+ if (!options.value<CLI::suppress_parsing> ())
+ {
+ // c-tor (xercesc::DOMElement)
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from a DOM element." << endl
+ << " *" << endl
+ << " * @param e A DOM element to extract the data from." << endl
+ << " * @param f Flags to create the new instance with." << endl
+ << " * @param c A pointer to the object that will " <<
+ "contain the new" << endl
+ << " * instance." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (const " << xerces_ns << "::DOMElement& e," << endl
+ << flags_type << " f = 0," << endl
+ << container << "* c = 0);"
+ << endl;
+
+ // c-tor (xercesc::DOMAttr)
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from a DOM attribute." << endl
+ << " *" << endl
+ << " * @param a A DOM attribute to extract the data from." << endl
+ << " * @param f Flags to create the new instance with." << endl
+ << " * @param c A pointer to the object that will " <<
+ "contain the new" << endl
+ << " * instance." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (const " << xerces_ns << "::DOMAttr& a," << endl
+ << flags_type << " f = 0," << endl
+ << container << "* c = 0);"
+ << endl;
+
+ // c-tor (std::basic_string const&, xercesc::DOMElement)
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from a string fragment." << endl
+ << " *" << endl
+ << " * @param s A string fragment to extract the data from." << endl
+ << " * @param e A pointer to DOM element containing the " <<
+ "string fragment." << endl
+ << " * @param f Flags to create the new instance with." << endl
+ << " * @param c A pointer to the object that will " <<
+ "contain the new" << endl
+ << " * instance." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (const " << string_type << "& s," << endl
+ << "const " << xerces_ns << "::DOMElement* e," << endl
+ << flags_type << " f = 0," << endl
+ << container << "* c = 0);"
+ << endl;
+ }
+
+ // copy c-tor
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Copy constructor." << endl
+ << " *" << endl
+ << " * @param x An instance to make a copy of." << endl
+ << " * @param f Flags to create the copy with." << endl
+ << " * @param c A pointer to the object that will contain " <<
+ "the copy." << endl
+ << " *" << endl
+ << " * For polymorphic object models use the @c _clone " <<
+ "function instead." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (const " << name << "& x," << endl
+ << flags_type << " f = 0," << endl
+ << container << "* c = 0);"
+ << endl;
+
+ // clone
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Copy the instance polymorphically." << endl
+ << " *" << endl
+ << " * @param f Flags to create the copy with." << endl
+ << " * @param c A pointer to the object that will contain " <<
+ "the copy." << endl
+ << " * @return A pointer to the dynamically allocated copy." << endl
+ << " *" << endl
+ << " * This function ensures that the dynamic type of the " <<
+ "instance is" << endl
+ << " * used for copying and should be used for polymorphic " <<
+ "object" << endl
+ << " * models instead of the copy constructor." << endl
+ << " */" << endl;
+ }
+
+ os << "virtual " << name << "*" << endl
+ << "_clone (" << flags_type << " f = 0," << endl
+ << container << "* c = 0) const;"
+ << endl;
+
+ // operator= (value)
+ //
+ if (string_based)
+ {
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Assign the underlying enum value." << endl
+ << " *" << endl
+ << " * @param v A enum value." << endl
+ << " * @return A refernce to the instance." << endl
+ << " */" << endl;
+ }
+
+ os << name << "&" << endl
+ << "operator= (" << value << " v);"
+ << endl;
+ }
+
+ // operator value ()
+ //
+ // Name lookup differences in various compilers make generation
+ // of this operator outside of the class a really hard task. So
+ // we are going to make it "always inline".
+ //
+ if (string_based)
+ {
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Implicit conversion operator to the " <<
+ "underlying" << endl
+ << " * enum value." << endl
+ << " *" << endl
+ << " * @return A enum value." << endl
+ << " */" << endl;
+ }
+
+ os << "virtual" << endl
+ << "operator " << value << " () const"
+ << "{"
+ << "return _xsd_" << name << "_convert ();"
+ << "}";
+ }
+
+ //
+ //
+ if (string_based)
+ {
+ if (doxygen)
+ os << "//@cond" << endl
+ << endl;
+
+ os << "protected:" << endl
+ << value << endl
+ << "_xsd_" << name << "_convert () const;"
+ << endl;
+
+ os << "public:" << endl;
+
+ if (enum_based)
+ {
+ // We are going to reuse our base's literals.
+ //
+ os << "static const " << char_type << "* const* " <<
+ "_xsd_" << name << "_literals_;";
+ }
+ else
+ {
+ os << "static const " << char_type << "* const " <<
+ "_xsd_" << name << "_literals_[" << enum_count << "];";
+ }
+
+ os << "static const " << value <<
+ " _xsd_" << name << "_indexes_[" << enum_count << "];";
+
+ if (doxygen)
+ os << endl
+ << "//@endcond" << endl
+ << endl;
+ }
+
+ os << "};";
+ }
+
+ virtual Void
+ comma (Type&)
+ {
+ os << "," << endl;
+ }
+
+ private:
+ Traversal::Inherits inherits_base_;
+ BaseTypeName base_;
+
+ Traversal::Inherits inherits_member_;
+ MemberTypeName member_;
+
+ Traversal::Names names_;
+ Enumerator enumerator_;
+ };
+
+
+ //
+ //
+ struct MemberFunction: Traversal::Member, protected virtual Context
+ {
+ MemberFunction (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& m)
+ {
+ if (skip (m))
+ return;
+
+ String const& aname (eaname (m));
+ String const& mname (emname (m));
+ String kind (m.is_a<SemanticGraph::Element> ()
+ ? "element" : "attribute");
+
+ Boolean fund (false);
+ {
+ IsFundamentalType t (fund);
+ t.dispatch (m.type ());
+ }
+
+ Boolean def_attr (m.default_ () &&
+ m.is_a<SemanticGraph::Attribute> () &&
+ !is_qname (m.type ()));
+
+ if (max (m) != 1)
+ {
+ // sequence
+ //
+ String container (econtainer (m));
+
+ // container const&
+ // name () const;
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Return a read-only (constant) reference " <<
+ "to the element" << endl
+ << " * sequence." << endl
+ << " *" << endl
+ << " * @return A constant reference to the sequence " <<
+ "container." << endl
+ << " */" << endl;
+ }
+
+ os << "const " << container << "&" << endl
+ << aname << " () const;"
+ << endl;
+
+ // container&
+ // name ();
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Return a read-write reference to the " <<
+ "element sequence." << endl
+ << " *" << endl
+ << " * @return A reference to the sequence container." << endl
+ << " */" << endl;
+ }
+
+ os << container << "&" << endl
+ << aname << " ();"
+ << endl;
+
+ // void
+ // name (container const&);
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Copy elements from a given sequence." << endl
+ << " *" << endl
+ << " * @param s A sequence to copy elements from." << endl
+ << " *" << endl
+ << " * For each element in @a s this function " <<
+ "makes a copy and adds it " << endl
+ << " * to the sequence. Note that this operation " <<
+ "completely changes the " << endl
+ << " * sequence and all old elements will be lost." << endl
+ << " */" << endl;
+ }
+
+ os << "void" << endl
+ << mname << " (const " << container << "& s);"
+ << endl;
+ }
+ else if (min (m) == 0 && !def_attr)
+ {
+ // optional
+ //
+ String const& type (etype (m));
+ String container (econtainer (m));
+
+ // container const&
+ // name () const;
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Return a read-only (constant) reference " <<
+ "to the " << kind << endl
+ << " * container." << endl
+ << " *" << endl
+ << " * @return A constant reference to the optional " <<
+ "container." << endl
+ << " */" << endl;
+ }
+
+ os << "const " << container << "&" << endl
+ << aname << " () const;"
+ << endl;
+
+ // container&
+ // name ();
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Return a read-write reference to the " <<
+ kind << " container." << endl
+ << " *" << endl
+ << " * @return A reference to the optional container." << endl
+ << " */" << endl;
+ }
+
+ os << container << "&" << endl
+ << aname << " ();"
+ << endl;
+
+ // void
+ // name (type const&);
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Set the " << kind << " value." << endl
+ << " *" << endl
+ << " * @param x A new value to set." << endl
+ << " *" << endl
+ << " * This function makes a copy of its argument " <<
+ "and sets it as" << endl
+ << " * the new value of the " << kind << "." << endl
+ << " */" << endl;
+ }
+
+ os << "void" << endl
+ << mname << " (const " << type << "& x);"
+ << endl;
+
+ // void
+ // name (container const&);
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Set the " << kind << " value." << endl
+ << " *" << endl
+ << " * @param x An optional container with the new value " <<
+ "to set." << endl
+ << " *" << endl
+ << " * If the value is present in @a x then this function " <<
+ "makes a copy " << endl
+ << " * of this value and sets it as the new value of the " <<
+ kind << "." << endl
+ << " * Otherwise the " << kind << " container is set " <<
+ "the 'not present' state." << endl
+ << " */" << endl;
+ }
+
+ os << "void" << endl
+ << mname << " (const " << container << "& x);"
+ << endl;
+
+ // void
+ // name (auto_ptr<type>);
+ //
+ if (!fund)
+ {
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Set the " << kind << " value without " <<
+ "copying." << endl
+ << " *" << endl
+ << " * @param p A new value to use." << endl
+ << " *" << endl
+ << " * This function will try to use the passed value " <<
+ "directly instead" << endl
+ << " * of making a copy." << endl
+ << " */" << endl;
+ }
+
+ os << "void" << endl
+ << mname << " (::std::auto_ptr< " << type << " > p);"
+ << endl;
+ }
+ }
+ else
+ {
+ // one
+ //
+ String const& type (etype (m));
+
+ // type const&
+ // name () const;
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Return a read-only (constant) reference " <<
+ "to the " << kind << "." << endl
+ << " *" << endl
+ << " * @return A constant reference to the " << kind <<
+ "." << endl
+ << " */" << endl;
+ }
+
+ os << "const " << type << "&" << endl
+ << aname << " () const;"
+ << endl;
+
+ // Do not generate modifiers for fixed attributes.
+ //
+ if (!(def_attr && m.fixed ()))
+ {
+ // type&
+ // name ();
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Return a read-write reference to the " <<
+ kind << "." << endl
+ << " *" << endl
+ << " * @return A reference to the " << kind << "." << endl
+ << " */" << endl;
+ }
+
+ os << type << "&" << endl
+ << aname << " ();"
+ << endl;
+
+ // void
+ // name (type const&);
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Set the " << kind << " value." << endl
+ << " *" << endl
+ << " * @param x A new value to set." << endl
+ << " *" << endl
+ << " * This function makes a copy of its argument " <<
+ "and sets it as" << endl
+ << " * the new value of the " << kind << "." << endl
+ << " */" << endl;
+ }
+
+ os << "void" << endl
+ << mname << " (const " << type << "& x);"
+ << endl;
+
+ // void
+ // name (auto_ptr<type>);
+ //
+ if (!fund)
+ {
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Set the " << kind << " value without " <<
+ "copying." << endl
+ << " *" << endl
+ << " * @param p A new value to use." << endl
+ << " *" << endl
+ << " * This function will try to use the passed value " <<
+ "directly instead" << endl
+ << " * of making a copy." << endl
+ << " */" << endl;
+ }
+
+ os << "void" << endl
+ << mname << " (::std::auto_ptr< " << type << " > p);"
+ << endl;
+ }
+ }
+ }
+
+ // default_value
+ //
+ if (m.default_ () && !is_qname (m.type ()))
+ {
+ Boolean simple (true);
+
+ if (m.is_a<SemanticGraph::Element> ())
+ {
+ IsSimpleType test (simple);
+ test.dispatch (m.type ());
+ }
+
+ if (simple)
+ {
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Return the default value for the " <<
+ kind << "." << endl
+ << " *" << endl
+ << " * @return A read-only (constant) reference to the "
+ << kind << "'s" << endl
+ << " * default value." << endl
+ << " */" << endl;
+ }
+
+ os << "static const " << etype (m) << "&" << endl
+ << edefault_value (m) << " ();"
+ << endl;
+ }
+ }
+ }
+ };
+
+ struct AnyFunction: Traversal::Any, protected virtual Context
+ {
+ AnyFunction (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ String const& aname (eaname (a));
+ String const& mname (emname (a));
+
+ SemanticGraph::Complex& c (
+ dynamic_cast<SemanticGraph::Complex&> (a.scope ()));
+
+ if (max (a) != 1)
+ {
+ // sequence
+ //
+ String container (econtainer (a));
+
+ // container const&
+ // name () const;
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Return a read-only (constant) reference " <<
+ "to the wildcard" << endl
+ << " * element sequence." << endl
+ << " *" << endl
+ << " * @return A constant reference to the sequence " <<
+ "container." << endl
+ << " */" << endl;
+ }
+
+ os << "const " << container << "&" << endl
+ << aname << " () const;"
+ << endl;
+
+ // container&
+ // name ();
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Return a read-write reference to the " <<
+ "wildcard element" << endl
+ << " * sequence." << endl
+ << " *" << endl
+ << " * @return A reference to the sequence container." << endl
+ << " */" << endl;
+ }
+
+ os << container << "&" << endl
+ << aname << " ();"
+ << endl;
+
+ // void
+ // name (container const&);
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Copy elements from a given sequence." << endl
+ << " *" << endl
+ << " * @param s A sequence to copy elements from." << endl
+ << " *" << endl
+ << " * For each element in @a s this function " <<
+ "makes a copy and adds" << endl
+ << " * it to the wildcard element sequence. Note that " <<
+ "this operation" << endl
+ << " * completely changes the sequence and all old " <<
+ "elements will be" << endl
+ << " * lost." << endl
+ << " */" << endl;
+ }
+
+ os << "void" << endl
+ << mname << " (const " << container << "& s);"
+ << endl;
+ }
+ else if (min (a) == 0)
+ {
+ // optional
+ //
+ String container (econtainer (a));
+
+ // container const&
+ // name () const;
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Return a read-only (constant) reference " <<
+ "to the wildcard" << endl
+ << " * element container." << endl
+ << " *" << endl
+ << " * @return A constant reference to the optional " <<
+ "container." << endl
+ << " */" << endl;
+ }
+
+ os << "const " << container << "&" << endl
+ << aname << " () const;"
+ << endl;
+
+ // container&
+ // name ();
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Return a read-write reference to the " <<
+ "wildcard element" << endl
+ << " * container." << endl
+ << " *" << endl
+ << " * @return A reference to the optional container." << endl
+ << " */" << endl;
+ }
+
+ os << container << "&" << endl
+ << aname << " ();"
+ << endl;
+
+ // void
+ // name (type const&);
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Set the wildcard content." << endl
+ << " *" << endl
+ << " * @param e A new element to set." << endl
+ << " *" << endl
+ << " * This function makes a copy of its argument " <<
+ "and sets it as" << endl
+ << " * the new wildcard content." << endl
+ << " */" << endl;
+ }
+
+ os << "void" << endl
+ << mname << " (const " << xerces_ns << "::DOMElement& e);"
+ << endl;
+
+ // void
+ // name (type*);
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Set the wildcard content without copying." << endl
+ << " *" << endl
+ << " * @param p A new element to use." << endl
+ << " *" << endl
+ << " * This function will use the passed element " <<
+ "directly instead" << endl
+ << " * of making a copy. For this to work the element " <<
+ "should belong" << endl
+ << " * to the DOM document associated with this instance." << endl
+ << " *" << endl
+ << " * @see " << edom_document (c) << endl
+ << " */" << endl;
+ }
+
+ os << "void" << endl
+ << mname << " (" << xerces_ns << "::DOMElement* p);"
+ << endl;
+
+ // void
+ // name (container const&);
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Set the wildcard content." << endl
+ << " *" << endl
+ << " * @param x An optional container with the new " <<
+ "element to set." << endl
+ << " *" << endl
+ << " * If the element is present in @a x then this function " <<
+ "makes a " << endl
+ << " * copy of this element and sets it as the new wildcard " <<
+ "content." << endl
+ << " * Otherwise the element container is set the 'not " <<
+ "present' state." << endl
+ << " */" << endl;
+ }
+
+ os << "void" << endl
+ << mname << " (const " << container << "& x);"
+ << endl;
+ }
+ else
+ {
+ // one
+ //
+
+ // type const&
+ // name () const;
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Return a read-only (constant) reference " <<
+ "to the wildcard" << endl
+ << " * element." << endl
+ << " *" << endl
+ << " * @return A constant reference to the DOM element." << endl
+ << " */" << endl;
+ }
+
+ os << "const " << xerces_ns << "::DOMElement&" << endl
+ << aname << " () const;"
+ << endl;
+
+ // type&
+ // name ();
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Return a read-write reference to the " <<
+ "wildcard element." << endl
+ << " *" << endl
+ << " * @return A reference to the DOM element." << endl
+ << " */" << endl;
+ }
+
+ os << xerces_ns << "::DOMElement&" << endl
+ << aname << " ();"
+ << endl;
+
+ // void
+ // name (type const&);
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Set the wildcard content." << endl
+ << " *" << endl
+ << " * @param e A new element to set." << endl
+ << " *" << endl
+ << " * This function makes a copy of its argument " <<
+ "and sets it as" << endl
+ << " * the new wildcard content." << endl
+ << " */" << endl;
+ }
+
+ os << "void" << endl
+ << mname << " (const " << xerces_ns << "::DOMElement& e);"
+ << endl;
+
+ // void
+ // name (const*);
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Set the wildcard content without copying." << endl
+ << " *" << endl
+ << " * @param p A new element to use." << endl
+ << " *" << endl
+ << " * This function will use the passed element " <<
+ "directly instead" << endl
+ << " * of making a copy. For this to work the element " <<
+ "should belong" << endl
+ << " * to the DOM document associated with this instance." << endl
+ << " *" << endl
+ << " * @see " << edom_document (c) << endl
+ << " */" << endl;
+ }
+
+ os << "void" << endl
+ << mname << " (" << xerces_ns << "::DOMElement* p);"
+ << endl;
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute& a)
+ {
+ String const& aname (eaname (a));
+ String const& mname (emname (a));
+
+ String container (econtainer (a));
+
+ // container const&
+ // name () const;
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Return a read-only (constant) reference " <<
+ "to the" << endl
+ << " * attribute set." << endl
+ << " *" << endl
+ << " * @return A constant reference to the set " <<
+ "container." << endl
+ << " */" << endl;
+ }
+
+ os << "const " << container << "&" << endl
+ << aname << " () const;"
+ << endl;
+
+ // container&
+ // name ();
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Return a read-write reference to the " <<
+ "attribute set." << endl
+ << " *" << endl
+ << " * @return A reference to the set container." << endl
+ << " */" << endl;
+ }
+
+ os << container << "&" << endl
+ << aname << " ();"
+ << endl;
+
+ // void
+ // name (container const&);
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Copy attributes from a given set." << endl
+ << " *" << endl
+ << " * @param s A set to copy elements from." << endl
+ << " *" << endl
+ << " * For each attribute in @a s this function " <<
+ "makes a copy and adds" << endl
+ << " * it to the set. Note that this operation " <<
+ "completely changes the " << endl
+ << " * set and all old attributes will be lost." << endl
+ << " */" << endl;
+ }
+
+ os << "void" << endl
+ << mname << " (const " << container << "& s);"
+ << endl;
+ }
+ };
+
+ //
+ //
+ struct Member: Traversal::Member, protected virtual Context
+ {
+ Member (Context& c)
+ : Context (c),
+ type_name_ (c),
+ member_function_ (c)
+ {
+ belongs_ >> type_name_;
+ }
+
+ virtual Void
+ traverse (Type& m)
+ {
+ if (skip (m))
+ return;
+
+ String const& type (etype (m));
+ Boolean el (m.is_a<SemanticGraph::Element> ());
+
+ Boolean def_attr (m.default_ () && !el && !is_qname (m.type ()));
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @name " << comment (m.name ()) << endl
+ << " *" << endl
+ << " * @brief Accessor and modifier functions for the %" <<
+ comment (m.name ()) << endl
+ << " * ";
+
+ if (max (m) != 1)
+ {
+ os << "sequence element." << endl;
+ }
+ else if (min (m) == 0)
+ {
+ if (def_attr)
+ os << "optional attribute with a default value." << endl;
+ else
+ os << "optional " << (el ? "element." : "attribute.") << endl;
+ }
+ else
+ {
+ os << "required " << (el ? "element." : "attribute.") << endl;
+ }
+
+ if (m.annotated ())
+ {
+ os << " *" << endl;
+ write_annotation (m.annotation ());
+ }
+
+ os << " */" << endl
+ << "//@{" << endl;
+ }
+ else
+ {
+ os << "// " << comment (m.name ()) << endl
+ << "// " << endl;
+ }
+
+ // Typedefs.
+ //
+ if (doxygen)
+ {
+ os << endl
+ << "/**" << endl
+ << " * @brief " << (el ? "Element" : "Attribute") <<
+ " type." << endl
+ << " */" << endl;
+ }
+
+ os << "typedef ";
+
+ belongs (m, belongs_);
+
+ os << " " << type << ";";
+
+ if (max (m) != 1)
+ {
+ String const& container (econtainer (m));
+ Boolean isense (options.value<CLI::generate_intellisense> ());
+
+ // sequence
+ //
+ if (doxygen)
+ {
+ os << endl
+ << "/**" << endl
+ << " * @brief Element sequence container type." << endl
+ << " */" << endl;
+ }
+
+ os << "typedef ::xsd::cxx::tree::sequence< " << type << " > " <<
+ container << ";";
+
+ if (doxygen)
+ {
+ os << endl
+ << "/**" << endl
+ << " * @brief Element iterator type." << endl
+ << " */" << endl;
+ }
+
+ // IntelliSense does not not like aliases and fully-qualified
+ // names here.
+ //
+ if (!isense)
+ os << "typedef " << container << "::iterator " <<
+ eiterator (m) << ";";
+ else
+ os << "typedef xsd::cxx::tree::sequence< " << type <<
+ " >::iterator " << eiterator (m) << ";";
+
+ if (doxygen)
+ {
+ os << endl
+ << "/**" << endl
+ << " * @brief Element constant iterator type." << endl
+ << " */" << endl;
+ }
+
+ if (!isense)
+ os << "typedef " << container << "::const_iterator " <<
+ econst_iterator (m) << ";";
+ else
+ os << "typedef xsd::cxx::tree::sequence< " << type <<
+ " >::const_iterator " << econst_iterator (m) << ";";
+
+ }
+ else if (min (m) == 0 && !def_attr)
+ {
+ // optional
+ //
+ if (doxygen)
+ {
+ os << endl
+ << "/**" << endl
+ << " * @brief " << (el ? "Element" : "Attribute") <<
+ " optional container type." << endl
+ << " */" << endl;
+ }
+
+ os << "typedef ::xsd::cxx::tree::optional< " << type << " > " <<
+ econtainer (m) << ";";
+ }
+ else
+ {
+ // one
+ //
+ }
+
+ if (doxygen)
+ {
+ os << endl
+ << "/**" << endl
+ << " * @brief " << (el ? "Element" : "Attribute") <<
+ " traits type." << endl
+ << " */" << endl;
+ }
+ os << "typedef ::xsd::cxx::tree::traits< " << type << ", " <<
+ char_type;
+
+ SemanticGraph::Type& t (m.type ());
+
+ if (t.is_a<SemanticGraph::Fundamental::Double> ())
+ os << ", ::xsd::cxx::tree::schema_type::double_";
+ else if (t.is_a<SemanticGraph::Fundamental::Decimal> ())
+ os << ", ::xsd::cxx::tree::schema_type::decimal";
+
+ os << " > " << etraits (m) << ";"
+ << endl;
+
+ member_function_.traverse (m);
+
+ if (doxygen)
+ {
+ os << "//@}" << endl
+ << endl;
+ }
+ }
+
+ private:
+ MemberTypeName type_name_;
+ Traversal::Belongs belongs_;
+
+ MemberFunction member_function_;
+ };
+
+
+ struct Any: Traversal::Any,
+ Traversal::AnyAttribute,
+ protected virtual Context
+ {
+ Any (Context& c)
+ : Context (c), any_function_ (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @name " << ename (a) << endl
+ << " *" << endl
+ << " * @brief Accessor and modifier functions for the " <<
+ "any wildcard." << endl;
+
+ if (a.annotated ())
+ {
+ os << " *" << endl;
+ write_annotation (a.annotation ());
+ }
+
+ os << " */" << endl
+ << "//@{" << endl;
+ }
+ else
+ {
+ os << "// " << ename (a) << endl
+ << "// " << endl;
+ }
+
+ // Typedefs.
+ //
+ if (max (a) != 1)
+ {
+ String const& container (econtainer (a));
+
+ // sequence
+ //
+ if (doxygen)
+ {
+ os << endl
+ << "/**" << endl
+ << " * @brief DOM element sequence container type." << endl
+ << " */" << endl;
+ }
+
+ os << "typedef ::xsd::cxx::tree::element_sequence " <<
+ container << ";";
+
+ if (doxygen)
+ {
+ os << endl
+ << "/**" << endl
+ << " * @brief DOM element iterator type." << endl
+ << " */" << endl;
+ }
+
+ os << "typedef " << container << "::iterator " <<
+ eiterator (a) << ";";
+
+ if (doxygen)
+ {
+ os << endl
+ << "/**" << endl
+ << " * @brief DOM element constant iterator type." << endl
+ << " */" << endl;
+ }
+
+ os << "typedef " << container << "::const_iterator " <<
+ econst_iterator (a) << ";"
+ << endl;
+
+ }
+ else if (min (a) == 0)
+ {
+ // optional
+ //
+ if (doxygen)
+ {
+ os << endl
+ << "/**" << endl
+ << " * @brief DOM element optional container type." << endl
+ << " */" << endl;
+ }
+
+ os << "typedef ::xsd::cxx::tree::element_optional " <<
+ econtainer (a) << ";"
+ << endl;
+ }
+ else
+ {
+ // one
+ //
+ if (doxygen)
+ os << endl;
+ }
+
+ any_function_.traverse (a);
+
+ if (doxygen)
+ {
+ os << "//@}" << endl
+ << endl;
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute& a)
+ {
+ String const& container (econtainer (a));
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @name " << ename (a) << endl
+ << " *" << endl
+ << " * @brief Accessor and modifier functions for the " <<
+ "anyAttribute" << endl
+ << " * wildcard." << endl;
+
+ if (a.annotated ())
+ {
+ os << " *" << endl;
+ write_annotation (a.annotation ());
+ }
+
+ os << " */" << endl
+ << "//@{" << endl;
+ }
+ else
+ {
+ os << "// " << ename (a) << endl
+ << "// " << endl;
+ }
+
+ if (doxygen)
+ {
+ os << endl
+ << "/**" << endl
+ << " * @brief DOM attribute set container type." << endl
+ << " */" << endl;
+ }
+
+ os << "typedef ::xsd::cxx::tree::attribute_set< " << char_type <<
+ " > " << container << ";";
+
+ if (doxygen)
+ {
+ os << endl
+ << "/**" << endl
+ << " * @brief DOM attribute iterator type." << endl
+ << " */" << endl;
+ }
+
+ os << "typedef " << container << "::iterator " <<
+ eiterator (a) << ";";
+
+ if (doxygen)
+ {
+ os << endl
+ << "/**" << endl
+ << " * @brief DOM attribute constant iterator type." << endl
+ << " */" << endl;
+ }
+
+ os << "typedef " << container << "::const_iterator " <<
+ econst_iterator (a) << ";"
+ << endl;
+
+ any_function_.traverse (a);
+
+ if (doxygen)
+ {
+ os << "//@}" << endl
+ << endl;
+ }
+ }
+
+ private:
+ AnyFunction any_function_;
+ };
+
+ struct DataMember: Traversal::Member, protected virtual Context
+ {
+ DataMember (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& m)
+ {
+ if (skip (m)) return;
+
+ String const& member (emember (m));
+
+ Boolean def_attr (m.default_ () &&
+ m.is_a<SemanticGraph::Attribute> () &&
+ !is_qname (m.type ()));
+
+ if (max (m) != 1)
+ {
+ // sequence
+ //
+ os << econtainer (m) << " " << member << ";";
+ }
+ else if (min (m) == 0 && !def_attr)
+ {
+ // optional
+ //
+ os << econtainer (m) << " " << member << ";";
+ }
+ else
+ {
+ // one
+ //
+ os << "::xsd::cxx::tree::one< " << etype (m) << " > " <<
+ member << ";";
+ }
+
+ // default_value
+ //
+ if (m.default_ () && !is_qname (m.type ()))
+ {
+ Boolean simple (true);
+
+ if (m.is_a<SemanticGraph::Element> ())
+ {
+ IsSimpleType test (simple);
+ test.dispatch (m.type ());
+ }
+
+ if (simple)
+ {
+ os << "static const " << etype (m) << " " <<
+ edefault_value_member (m) << ";";
+ }
+ }
+ }
+ };
+
+ struct DataAny: Traversal::Any,
+ Traversal::AnyAttribute,
+ protected virtual Context
+ {
+ DataAny (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ String const& member (emember (a));
+
+ if (max (a) != 1)
+ {
+ // sequence
+ //
+ os << econtainer (a) << " " << member << ";";
+ }
+ else if (min (a) == 0)
+ {
+ // optional
+ //
+ os << econtainer (a) << " " << member << ";";
+ }
+ else
+ {
+ // one
+ //
+ os << "::xsd::cxx::tree::element_one " << member << ";";
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute& a)
+ {
+ os << econtainer (a) << " " << emember (a) << ";";
+ }
+ };
+
+
+ struct Complex : Traversal::Complex, protected virtual Context
+ {
+ Complex (Context& c)
+ : Context (c),
+ base_name_ (c),
+ member_name_ (c),
+ any_ (c),
+ member_ (c),
+ data_any_ (c),
+ data_member_ (c)
+ {
+ inherits_base_ >> base_name_;
+ inherits_member_ >> member_name_;
+
+ names_ >> member_;
+ if (options.value<CLI::generate_wildcard> ())
+ names_ >> any_;
+
+ names_data_ >> data_member_;
+ if (options.value<CLI::generate_wildcard> ())
+ names_data_ >> data_any_;
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ String name (ename (c));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (c, name) && !name)
+ return;
+
+ Boolean has_members (has<Traversal::Member> (c));
+
+ Boolean hae (has<Traversal::Any> (c));
+ Boolean haa (has<Traversal::AnyAttribute> (c));
+
+ Boolean gen_wildcard (options.value<CLI::generate_wildcard> ());
+
+ Boolean simple (true);
+ {
+ IsSimpleType t (simple);
+ t.dispatch (c);
+ }
+
+ Boolean string_based (false);
+ {
+ IsStringBasedType t (string_based);
+ t.dispatch (c);
+ }
+
+ SemanticGraph::Enumeration* enum_base (0);
+ {
+ IsEnumBasedType t (enum_base);
+ t.dispatch (c);
+ }
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Class corresponding to the %" <<
+ comment (c.name ()) << " schema type." << endl;
+
+ if (c.annotated ())
+ {
+ os << " *" << endl;
+ write_annotation (c.annotation ());
+ }
+
+ os << " *" << endl
+ << " * @nosubgrouping" << endl
+ << " */" << endl;
+ }
+
+ os << "class " << type_exp << name << ": public ";
+
+ if (c.inherits_p ())
+ inherits (c, inherits_base_);
+ else
+ os << any_type;
+
+ os << "{"
+ << "public:" << endl;
+
+ // Members.
+ //
+ names (c, names_);
+
+ // dom_document accessors.
+ //
+ if (edom_document_member_p (c))
+ {
+
+ if (!doxygen)
+ {
+ os << "// DOMDocument for wildcard content." << endl
+ << "//" << endl;
+ }
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Return a read-only (constant) reference " <<
+ "to the DOM" << endl
+ << " * document associated with this instance." << endl
+ << " *" << endl
+ << " * @return A constant reference to the DOM document." << endl
+ << " *" << endl
+ << " * The DOM document returned by this function is " <<
+ "used to store" << endl
+ << " * the raw XML content corresponding to wildcards." << endl
+ << " */" << endl;
+ }
+
+ os << "const " << xerces_ns << "::DOMDocument&" << endl
+ << edom_document (c) << " () const;"
+ << endl;
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Return a read-write reference to the DOM " <<
+ "document" << endl
+ << " * associated with this instance." << endl
+ << " *" << endl
+ << " * @return A reference to the DOM document." << endl
+ << " *" << endl
+ << " * The DOM document returned by this function is " <<
+ "used to store" << endl
+ << " * the raw XML content corresponding to wildcards." << endl
+ << " */" << endl;
+ }
+ os << xerces_ns << "::DOMDocument&" << endl
+ << edom_document (c) << " ();"
+ << endl;
+ }
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @name Constructors" << endl
+ << " */" << endl
+ << "//@{" << endl
+ << endl;
+ }
+ else
+ {
+ os << "// Constructors." << endl
+ << "//" << endl;
+ }
+
+ Boolean generate_no_base_ctor (false);
+ {
+ GenerateWithoutBaseCtor t (generate_no_base_ctor);
+ t.traverse (c);
+ }
+
+ Boolean has_complex_non_op_args (false);
+ Boolean has_non_fund_non_op_args (false);
+ Boolean complex_non_fund_args_clash (true);
+ {
+ HasComplexNonFundNonOptArgs t (*this, true,
+ has_complex_non_op_args,
+ has_non_fund_non_op_args,
+ complex_non_fund_args_clash);
+ t.traverse (c);
+ }
+
+ // default c-tor
+ //
+ if (options.value<CLI::generate_default_ctor> ())
+ {
+ // c-tor (ultimate-base all-non-optional-members) will become
+ // default c-tor if our inheritance hierarchy has no required
+ // members and no simple base. We can also collide with
+ // c-tor (all-non-optional-members) if we have no required
+ // members.
+ //
+ Boolean generate (false);
+ {
+ GenerateDefaultCtor t (*this, generate, generate_no_base_ctor);
+ t.traverse (c);
+ }
+
+ if (generate)
+ {
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Default constructor." << endl
+ << " *" << endl
+ << " * Note that this constructor leaves required " <<
+ "elements and" << endl
+ << " * attributes uninitialized." << endl
+ << " */" << endl;
+ }
+
+ os << name << " ();"
+ << endl;
+ }
+ }
+
+ // c-tor (base, all-non-optional-members)
+ //
+ if (options.value<CLI::generate_from_base_ctor> ())
+ {
+ // c-tor (ultimate-base, all-non-optional-members) will become
+ // c-tor (base, all-non-optional-members) unless our immediate
+ // base's hierarchy has some non-optional members.
+ //
+ Boolean generate (false);
+ {
+ GenerateFromBaseCtor t (*this, generate);
+ t.traverse (c);
+ }
+
+ if (generate)
+ {
+ Boolean has_complex_non_op_args (false);
+ Boolean has_non_fund_non_op_args (false);
+ Boolean complex_non_fund_args_clash (true);
+ {
+ HasComplexNonFundNonOptArgs t (*this, false,
+ has_complex_non_op_args,
+ has_non_fund_non_op_args,
+ complex_non_fund_args_clash);
+ t.traverse (c);
+ }
+
+ //
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from the immediate "
+ "base and" << endl
+ << " * initializers for required elements and "
+ << "attributes." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (const ";
+ inherits (c, inherits_member_);
+ os << "&";
+ {
+ FromBaseCtorArg args (*this, FromBaseCtorArg::arg_type, false);
+ Traversal::Names args_names (args);
+ names (c, args_names);
+ }
+ os << ");"
+ << endl;
+
+ // If we have any complex arguments in the previous c-tor
+ // then also generate the auto_ptr version.
+ //
+ if (has_complex_non_op_args)
+ {
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from the immediate "
+ "base and" << endl
+ << " * initializers for required elements and "
+ << "attributes" << endl
+ << " * (auto_ptr version)." << endl
+ << " *" << endl
+ << " * This constructor will try to use the passed " <<
+ "values directly" << endl
+ << " * instead of making copies." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (const ";
+ inherits (c, inherits_member_);
+ os << "&";
+ {
+ FromBaseCtorArg args (
+ *this, FromBaseCtorArg::arg_complex_auto_ptr, false);
+ Traversal::Names args_names (args);
+ names (c, args_names);
+ }
+ os << ");"
+ << endl;
+ }
+
+ // If we are generating polymorphic code then we also need to
+ // provide auto_ptr version for every non-fundamental type.
+ //
+ if (polymorphic &&
+ has_non_fund_non_op_args && !complex_non_fund_args_clash)
+ {
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from the immediate "
+ "base and" << endl
+ << " * initializers for required elements and "
+ << "attributes" << endl
+ << " * (auto_ptr version)." << endl
+ << " *" << endl
+ << " * This constructor will try to use the passed " <<
+ "values directly" << endl
+ << " * instead of making copies." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (const ";
+ inherits (c, inherits_member_);
+ os << "&";
+ {
+ FromBaseCtorArg args (
+ *this, FromBaseCtorArg::arg_non_fund_auto_ptr, false);
+ Traversal::Names args_names (args);
+ names (c, args_names);
+ }
+ os << ");"
+ << endl;
+ }
+ }
+ }
+
+ // c-tor (all-non-optional-members)
+ //
+ if (generate_no_base_ctor)
+ {
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from initializers " <<
+ "for required " << endl
+ << " * elements and attributes." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (";
+ {
+ CtorArgsWithoutBase ctor_args (
+ *this, CtorArgsWithoutBase::arg_type, false, true);
+ ctor_args.dispatch (c);
+ }
+ os << ");"
+ << endl;
+
+
+ // If we have any complex arguments in the previous c-tor
+ // then also generate the auto_ptr version. One case where
+ // this c-tor will be generated is restriction of anyType.
+ //
+ if (has_complex_non_op_args)
+ {
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from initializers " <<
+ "for required " << endl
+ << " * elements and attributes (auto_ptr version)." << endl
+ << " *" << endl
+ << " * This constructor will try to use the passed " <<
+ "values directly" << endl
+ << " * instead of making copies." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (";
+ {
+ CtorArgsWithoutBase ctor_args (
+ *this, CtorArgsWithoutBase::arg_complex_auto_ptr, false, true);
+ ctor_args.dispatch (c);
+ }
+ os << ");"
+ << endl;
+ }
+
+ // If we are generating polymorphic code then we also need to
+ // provide auto_ptr version for every non-fundamental type.
+ //
+ if (polymorphic &&
+ has_non_fund_non_op_args && !complex_non_fund_args_clash)
+ {
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from initializers " <<
+ "for required " << endl
+ << " * elements and attributes (auto_ptr version)." << endl
+ << " *" << endl
+ << " * This constructor will try to use the passed " <<
+ "values directly" << endl
+ << " * instead of making copies." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (";
+ {
+ CtorArgsWithoutBase ctor_args (
+ *this, CtorArgsWithoutBase::arg_non_fund_auto_ptr, false, true);
+ ctor_args.dispatch (c);
+ }
+ os << ");"
+ << endl;
+ }
+ }
+
+ if (string_based)
+ {
+ if (enum_base != 0)
+ {
+ // c-tor (enum-value, all-non-optional-members)
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from the " <<
+ "underlying enum value" << endl
+ << " * and initializers for required elements and " <<
+ "attributes." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (" << fq_name (*enum_base) << "::" <<
+ evalue (*enum_base);
+
+ {
+ CtorArgsWithoutBase ctor_args (
+ *this, CtorArgsWithoutBase::arg_type, false, false);
+ ctor_args.dispatch (c);
+ }
+
+ os << ");"
+ << endl;
+ }
+
+ // c-tor (const char*, all-non-optional-members)
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from a C string and " <<
+ "initializers" << endl
+ << " * for required elements and attributes." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (const " << char_type << "*";
+
+ {
+ CtorArgsWithoutBase ctor_args (
+ *this, CtorArgsWithoutBase::arg_type, false, false);
+ ctor_args.dispatch (c);
+ }
+
+ os << ");"
+ << endl;
+
+ // c-tor (const std::string&, all-non-optional-members)
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from a string and" <<
+ "initializers" << endl
+ << " * for required elements and attributes." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (const " << string_type << "&";
+
+ {
+ CtorArgsWithoutBase ctor_args (
+ *this, CtorArgsWithoutBase::arg_type, false, false);
+ ctor_args.dispatch (c);
+ }
+
+ os << ");"
+ << endl;
+ }
+
+ // c-tor (ultimate-base, all-non-optional-members)
+ //
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from the ultimate "
+ "base and" << endl
+ << " * initializers for required elements and " <<
+ "attributes." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (";
+
+ {
+ CtorArgs ctor_args (*this, CtorArgs::arg_type);
+ ctor_args.dispatch (c);
+ }
+
+ os << ");"
+ << endl;
+
+ // If we have any complex arguments in the previous c-tor
+ // then also generate the auto_ptr version.
+ //
+ if (has_complex_non_op_args)
+ {
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from the ultimate "
+ "base and" << endl
+ << " * initializers for required elements and " <<
+ "attributes" << endl
+ << " * (auto_ptr version)." << endl
+ << " *" << endl
+ << " * This constructor will try to use the passed " <<
+ "values directly" << endl
+ << " * instead of making copies." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (";
+
+ {
+ CtorArgs ctor_args (*this, CtorArgs::arg_complex_auto_ptr);
+ ctor_args.dispatch (c);
+ }
+
+ os << ");"
+ << endl;
+ }
+
+ // If we are generating polymorphic code then we also need to
+ // provide auto_ptr version for every non-fundamental type.
+ //
+ if (polymorphic &&
+ has_non_fund_non_op_args && !complex_non_fund_args_clash)
+ {
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from the ultimate "
+ "base and" << endl
+ << " * initializers for required elements and " <<
+ "attributes" << endl
+ << " * (auto_ptr version)." << endl
+ << " *" << endl
+ << " * This constructor will try to use the passed " <<
+ "values directly" << endl
+ << " * instead of making copies." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (";
+
+ {
+ CtorArgs ctor_args (*this, CtorArgs::arg_non_fund_auto_ptr);
+ ctor_args.dispatch (c);
+ }
+
+ os << ");"
+ << endl;
+ }
+
+ // c-tor (istream&)
+ //
+ Streams const& st (options.value<CLI::generate_extraction> ());
+ for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i)
+ {
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from a data " <<
+ "representation" << endl
+ << " * stream." << endl
+ << " *" << endl
+ << " * @param s A stream to extract the data from." << endl
+ << " * @param f Flags to create the new instance with." << endl
+ << " * @param c A pointer to the object that will " <<
+ "contain the new" << endl
+ << " * instance." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (" << istream_type << "< " << i->c_str () <<
+ " >& s," << endl
+ << flags_type << " f = 0," << endl
+ << container << "* c = 0);"
+ << endl;
+ }
+
+
+ if (!options.value<CLI::suppress_parsing> ())
+ {
+ // c-tor (xercesc::DOMElement)
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from a DOM element." << endl
+ << " *" << endl
+ << " * @param e A DOM element to extract the data from." << endl
+ << " * @param f Flags to create the new instance with." << endl
+ << " * @param c A pointer to the object that will " <<
+ "contain the new" << endl
+ << " * instance." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (const " << xerces_ns << "::DOMElement& e," << endl
+ << flags_type << " f = 0," << endl
+ << container << "* c = 0);"
+ << endl;
+
+
+ if (simple)
+ {
+ // c-tor (xercesc::DOMAttr)
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from a DOM attribute." << endl
+ << " *" << endl
+ << " * @param a A DOM attribute to extract the data from." << endl
+ << " * @param f Flags to create the new instance with." << endl
+ << " * @param c A pointer to the object that will " <<
+ "contain the new" << endl
+ << " * instance." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (const " << xerces_ns << "::DOMAttr& a," << endl
+ << flags_type << " f = 0," << endl
+ << container << "* c = 0);"
+ << endl;
+
+ // c-tor (std::basic_string const&, xercesc::DOMElement)
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from a string fragment." << endl
+ << " *" << endl
+ << " * @param s A string fragment to extract the data from." << endl
+ << " * @param e A pointer to DOM element containing the " <<
+ "string fragment." << endl
+ << " * @param f Flags to create the new instance with." << endl
+ << " * @param c A pointer to the object that will " <<
+ "contain the new" << endl
+ << " * instance." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (const " << string_type << "& s," << endl
+ << "const " << xerces_ns << "::DOMElement* e," << endl
+ << flags_type << " f = 0," << endl
+ << container << "* c = 0);"
+ << endl;
+ }
+ }
+
+ // copy c-tor
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Copy constructor." << endl
+ << " *" << endl
+ << " * @param x An instance to make a copy of." << endl
+ << " * @param f Flags to create the copy with." << endl
+ << " * @param c A pointer to the object that will contain " <<
+ "the copy." << endl
+ << " *" << endl
+ << " * For polymorphic object models use the @c _clone " <<
+ "function instead." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (const " << name << "& x," << endl
+ << flags_type << " f = 0," << endl
+ << container << "* c = 0);"
+ << endl;
+
+ // clone
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Copy the instance polymorphically." << endl
+ << " *" << endl
+ << " * @param f Flags to create the copy with." << endl
+ << " * @param c A pointer to the object that will contain " <<
+ "the copy." << endl
+ << " * @return A pointer to the dynamically allocated copy." << endl
+ << " *" << endl
+ << " * This function ensures that the dynamic type of the " <<
+ "instance is" << endl
+ << " * used for copying and should be used for polymorphic " <<
+ "object" << endl
+ << " * models instead of the copy constructor." << endl
+ << " */" << endl;
+ }
+
+ os << "virtual " << name << "*" << endl
+ << "_clone (" << flags_type << " f = 0," << endl
+ << container << "* c = 0) const;"
+ << endl;
+
+ if (doxygen)
+ {
+ os << "//@}" << endl
+ << endl;
+ }
+
+ // d-tor
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Destructor." << endl
+ << " */" << endl;
+ }
+
+ os << "virtual " << endl
+ << "~" << name << " ();"
+ << endl;
+
+ // Data members and implementation functions.
+ //
+ if (has_members || hae || (haa && gen_wildcard))
+ {
+ os << "// Implementation." << endl
+ << "//" << endl;
+
+ if (doxygen)
+ os << endl
+ << "//@cond" << endl
+ << endl;
+
+ if (!options.value<CLI::suppress_parsing> ())
+ {
+ // parse (xercesc::DOMElement)
+ //
+ os << "protected:" << endl
+ << "void" << endl
+ << unclash (name, "parse") << " (" <<
+ parser_type << "&," << endl
+ << flags_type << ");"
+ << endl;
+ }
+
+ os << "protected:"
+ << endl;
+
+ // parse (istream)
+ //
+ if (has_members)
+ {
+ for (Streams::ConstIterator i (st.begin ()); i != st.end (); ++i)
+ {
+ os << "void" << endl
+ << unclash (name, "parse") << " (" <<
+ istream_type << "< " << i->c_str () << " >&," << endl
+ << flags_type << ");"
+ << endl;
+ }
+ }
+
+ //
+ //
+ if (edom_document_member_p (c))
+ {
+ os << dom_auto_ptr << "< " << xerces_ns <<
+ "::DOMDocument > " << edom_document_member (c) << ";"
+ << endl;
+ }
+
+ //
+ //
+ names (c, names_data_);
+
+ if (doxygen)
+ os << endl
+ << "//@endcond" << endl;
+ }
+
+ os << "};";
+
+ // Comparison operators.
+ //
+ if (options.value<CLI::generate_comparison> () &&
+ (has_members || !c.inherits_p () ||
+ ((hae || haa) && gen_wildcard)))
+ {
+ os << inst_exp
+ << "bool" << endl
+ << "operator== (const " << name << "&, const " << name << "&);"
+ << endl;
+
+ os << inst_exp
+ << "bool" << endl
+ << "operator!= (const " << name << "&, const " << name << "&);"
+ << endl
+ << endl;
+ }
+ }
+
+ private:
+ Traversal::Inherits inherits_base_;
+ BaseTypeName base_name_;
+
+ Traversal::Inherits inherits_member_;
+ MemberTypeName member_name_;
+
+ Traversal::Names names_;
+ Any any_;
+ Member member_;
+
+ Traversal::Names names_data_;
+ DataAny data_any_;
+ DataMember data_member_;
+ };
+
+
+ struct GlobalElement : Traversal::Element,
+ GlobalElementBase,
+ protected virtual Context
+ {
+ GlobalElement (Context& c)
+ : Context (c), GlobalElementBase (c), type_name_ (c)
+ {
+ belongs_ >> type_name_;
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (!doc_root_p (e))
+ return;
+
+ SemanticGraph::Type& t (e.type ());
+
+ Boolean fund (false);
+ {
+ IsFundamentalType test (fund);
+ test.dispatch (t);
+ }
+
+ Boolean simple (true);
+ if (!fund)
+ {
+ IsSimpleType test (simple);
+ test.dispatch (t);
+ }
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Class corresponding to the %" <<
+ comment (e.name ()) << " root element." << endl;
+
+ if (e.annotated ())
+ {
+ os << " *" << endl;
+ write_annotation (e.annotation ());
+ }
+
+ os << " *" << endl
+ << " * @nosubgrouping" << endl
+ << " */" << endl;
+ }
+
+ String const& name (ename (e));
+
+ os << "class " << type_exp << name << ": public " << element_type
+ << "{"
+ << "public:" << endl
+ << endl;
+
+ String const& type (etype (e));
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @name Element value" << endl
+ << " *" << endl
+ << " * @brief Accessor and modifier functions for the " <<
+ "element value." << endl
+ << " */" << endl
+ << "//@{" << endl
+ << endl;
+ }
+ else
+ {
+ os << "// Element value." << endl
+ << "//" << endl;
+ }
+
+ // Typedefs.
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Element value type." << endl
+ << " */" << endl;
+ }
+
+ os << "typedef ";
+
+ belongs (e, belongs_);
+
+ os << " " << type << ";";
+
+ if (doxygen)
+ {
+ os << endl
+ << "/**" << endl
+ << " * @brief Element value traits type." << endl
+ << " */" << endl;
+ }
+
+ os << "typedef ::xsd::cxx::tree::traits< " << type << ", " <<
+ char_type;
+
+ if (t.is_a<SemanticGraph::Fundamental::Double> ())
+ os << ", ::xsd::cxx::tree::schema_type::double_";
+ else if (t.is_a<SemanticGraph::Fundamental::Decimal> ())
+ os << ", ::xsd::cxx::tree::schema_type::decimal";
+
+ os << " > " << etraits (e) << ";"
+ << endl;
+
+ // Accessors/modifiers.
+ //
+ String const& aname (eaname (e));
+ String const& mname (emname (e));
+
+ // type const&
+ // name () const;
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Return a read-only (constant) reference " <<
+ "to the element" << endl
+ << " * value." << endl
+ << " *" << endl
+ << " * @return A constant reference to the element value." <<
+ endl
+ << " */" << endl;
+ }
+
+ os << "const " << type << "&" << endl
+ << aname << " () const;"
+ << endl;
+
+ // type&
+ // name ();
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Return a read-write reference to the " <<
+ "element value." << endl
+ << " *" << endl
+ << " * @return A reference to the element value." << endl
+ << " */" << endl;
+ }
+
+ os << type << "&" << endl
+ << aname << " ();"
+ << endl;
+
+ // void
+ // name (type const&);
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Set the element value." << endl
+ << " *" << endl
+ << " * @param x A new value to set." << endl
+ << " *" << endl
+ << " * This function makes a copy of its argument " <<
+ "and sets it as" << endl
+ << " * the new value of the element." << endl
+ << " */" << endl;
+ }
+
+ os << "void" << endl
+ << mname << " (const " << type << "& x);"
+ << endl;
+
+ // void
+ // name (auto_ptr<type>);
+ //
+ if (!fund)
+ {
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Set the element value without " <<
+ "copying." << endl
+ << " *" << endl
+ << " * @param p A new value to use." << endl
+ << " *" << endl
+ << " * This function will try to use the passed value " <<
+ "directly" << endl
+ << " * instead of making a copy." << endl
+ << " */" << endl;
+ }
+
+ os << "void" << endl
+ << mname << " (::std::auto_ptr< " << type << " > p);"
+ << endl;
+ }
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Return a read-only (constant) pointer " <<
+ "to the element" << endl
+ << " * value." << endl
+ << " *" << endl
+ << " * @return A constant pointer to the element value " <<
+ "or 0 if this" << endl
+ << " * element is of a fundamental type." << endl
+ << " */" << endl;
+ }
+
+ os << "virtual const " << any_type << "*" << endl
+ << "_value () const;"
+ << endl;
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Return a pointer to the element value." << endl
+ << " *" << endl
+ << " * @return A pointer to the element value or 0 if this " <<
+ "element is" << endl
+ << " * of a fundamental type." << endl
+ << " */" << endl;
+ }
+ os << "virtual " << any_type << "*" << endl
+ << "_value ();"
+ << endl;
+
+ if (doxygen)
+ {
+ os << "//@}" << endl
+ << endl;
+ }
+
+ // Constructor.
+ //
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @name Constructors" << endl
+ << " */" << endl
+ << "//@{" << endl
+ << endl;
+ }
+ else
+ {
+ os << "// Constructors." << endl
+ << "//" << endl;
+ }
+
+ // default c-tor
+ //
+ if (options.value<CLI::generate_default_ctor> ())
+ {
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Default constructor." << endl
+ << " *" << endl
+ << " * Note that this constructor leaves the element " <<
+ "value" << endl
+ << " * uninitialized." << endl
+ << " */" << endl;
+ }
+
+ os << name << " ();"
+ << endl;
+ }
+
+ // c-tor (value)
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from an initializer " <<
+ "for the element" << endl
+ << " * value." << endl
+ << " *" << endl
+ << " * @param x Element value." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (const " << type << "& x);"
+ << endl;
+
+
+ // If the element value is a complex type (has elements,
+ // attributes, or wildcards) then also generate the auto_ptr
+ // version. If we are generating polymorphic code then we
+ // also need to provide auto_ptr version for simple, non-
+ // fundamental values.
+ //
+ //
+ if (!simple || (polymorphic && !fund))
+ {
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from an initializer " <<
+ "for" << endl
+ << " * the element value (auto_ptr version)." << endl
+ << " *" << endl
+ << " * @param p Element value to use." << endl
+ << " *" << endl
+ << " * This constructor will try to use the passed " <<
+ "value directly" << endl
+ << " * instead of making a copy." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (::std::auto_ptr< " << type << " > p);"
+ << endl;
+ }
+
+ if (!options.value<CLI::suppress_parsing> ())
+ {
+ // c-tor (xercesc::DOMElement)
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Create an instance from a DOM element." << endl
+ << " *" << endl
+ << " * @param e A DOM element to extract the data from." << endl
+ << " * @param f Flags to create the new instance with." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (const " << xerces_ns << "::DOMElement& e, " <<
+ flags_type << " f = 0);"
+ << endl;
+ }
+
+ // copy c-tor
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Copy constructor." << endl
+ << " *" << endl
+ << " * @param x An instance to make a copy of." << endl
+ << " * @param f Flags to create the copy with." << endl
+ << " *" << endl
+ << " * For polymorphic object models use the @c _clone " <<
+ "function instead." << endl
+ << " */" << endl;
+ }
+
+ os << name << " (const " << name << "& x, " <<
+ flags_type << " f = 0);"
+ << endl;
+
+ // _clone
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Copy the instance polymorphically." << endl
+ << " *" << endl
+ << " * @param f Flags to create the copy with." << endl
+ << " * @return A pointer to the dynamically allocated copy." << endl
+ << " *" << endl
+ << " * This function ensures that the dynamic type of the " <<
+ "instance is" << endl
+ << " * used for copying and should be used for polymorphic " <<
+ "object" << endl
+ << " * models instead of the copy constructor." << endl
+ << " */" << endl;
+ }
+
+ os << "virtual " << name << "*" << endl
+ << "_clone (" << flags_type << " f = 0) const;"
+ << endl;
+
+ if (doxygen)
+ {
+ os << "//@}" << endl
+ << endl;
+ }
+
+ // Element name and namespace accessors.
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @name Element name and namespace" << endl
+ << " *" << endl
+ << " * @brief Accessor functions for the element name " <<
+ "and namespace." << endl
+ << " */" << endl
+ << "//@{" << endl
+ << endl;
+ }
+ else
+ {
+ os << "// Element name and namespace." << endl
+ << "//" << endl;
+ }
+
+ SemanticGraph::Context& ec (e.context ());
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Return the element name (static function)." << endl
+ << " *" << endl
+ << " * @return A read-only string reference containing " <<
+ "the element" << endl
+ << " * name." << endl
+ << " */" << endl;
+ }
+ os << "static const " << string_type << "&" << endl
+ << ec.get<String> ("element-name") << " ();"
+ << endl;
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Return the element namespace (static " <<
+ "function)." << endl
+ << " *" << endl
+ << " * @return A read-only string reference containing " <<
+ "the element" << endl
+ << " * namespace." << endl
+ << " */" << endl;
+ }
+ os << "static const " << string_type << "&" << endl
+ << ec.get<String> ("element-ns") << " ();"
+ << endl;
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Return the element name." << endl
+ << " *" << endl
+ << " * @return A read-only string reference containing " <<
+ "the element" << endl
+ << " * name." << endl
+ << " */" << endl;
+ }
+ os << "virtual const " << string_type << "&" << endl
+ << "_name () const;"
+ << endl;
+
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Return the element namespace." << endl
+ << " *" << endl
+ << " * @return A read-only string reference containing " <<
+ "the element" << endl
+ << " * namespace." << endl
+ << " */" << endl;
+ }
+ os << "virtual const " << string_type << "&" << endl
+ << "_namespace () const;"
+ << endl;
+
+ if (doxygen)
+ {
+ os << "//@}" << endl
+ << endl;
+ }
+
+ // d-tor
+ //
+ if (doxygen)
+ {
+ os << "/**" << endl
+ << " * @brief Destructor." << endl
+ << " */" << endl;
+ }
+
+ os << "virtual " << endl
+ << "~" << name << " ();"
+ << endl;
+
+ // Data member.
+ //
+
+ if (doxygen)
+ os << "//@cond" << endl
+ << endl;
+
+ os << "protected:" << endl
+ << "::xsd::cxx::tree::one< " << type << " > " <<
+ emember (e) << ";"
+ << "static const " << string_type << " " <<
+ ec.get<String> ("element-name-member") << ";"
+ << "static const " << string_type << " " <<
+ ec.get<String> ("element-ns-member") << ";";
+
+ if (doxygen)
+ os << endl
+ << "//@endcond" << endl;
+
+ os << "};";
+ }
+
+ private:
+ Traversal::Belongs belongs_;
+ MemberTypeName type_name_;
+ };
+ }
+
+ Void
+ generate_tree_header (Context& ctx)
+ {
+ if (ctx.generate_xml_schema)
+ {
+ ctx.os << "#include <xsd/cxx/tree/exceptions.hxx>" << endl
+ << "#include <xsd/cxx/tree/elements.hxx>" << endl
+ << "#include <xsd/cxx/tree/types.hxx>" << endl
+ << endl;
+
+ if (!ctx.options.value<CLI::suppress_parsing> () ||
+ ctx.options.value<CLI::generate_serialization> ())
+ {
+ ctx.os << "#include <xsd/cxx/xml/error-handler.hxx>" << endl
+ << endl;
+ }
+
+ if (!ctx.options.value<CLI::suppress_parsing> () ||
+ ctx.options.value<CLI::generate_serialization> ())
+ {
+ ctx.os << "#include <xsd/cxx/xml/dom/auto-ptr.hxx>" << endl
+ << endl;
+ }
+
+ Boolean element_map (ctx.options.value<CLI::generate_element_map> ());
+
+ if (element_map)
+ ctx.os << "#include <xsd/cxx/tree/element-map.hxx>" << endl
+ << endl;
+
+ // I need to include all the "optional" headers here (instead of
+ // later in the individual generators for each feature because
+ // those headers provide implementation for the fundamental types.
+ //
+ if (!ctx.options.value<CLI::suppress_parsing> ())
+ {
+ ctx.os << "#include <xsd/cxx/tree/parsing.hxx>" << endl;
+
+ Traversal::Schema schema;
+ Traversal::Names names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+ FundIncludes type (ctx, "parsing");
+
+ schema >> names >> ns >> ns_names >> type;
+
+ schema.dispatch (ctx.schema_root);
+
+ if (element_map)
+ ctx.os << "#include <xsd/cxx/tree/parsing/element-map.txx>" <<
+ endl;
+
+ ctx.os << endl;
+ }
+
+ if (ctx.options.value<CLI::generate_serialization> ())
+ {
+ ctx.os << "#include <xsd/cxx/xml/dom/serialization-header.hxx>" << endl
+ << "#include <xsd/cxx/tree/serialization.hxx>" << endl;
+
+ Traversal::Schema schema;
+ Traversal::Names names;
+ Traversal::Namespace ns;
+ Traversal::Names ns_names;
+ FundIncludes type (ctx, "serialization");
+
+ schema >> names >> ns >> ns_names >> type;
+
+ schema.dispatch (ctx.schema_root);
+
+ if (element_map)
+ ctx.os << "#include <xsd/cxx/tree/serialization/element-map.txx>" <<
+ endl;
+
+ ctx.os << endl;
+ }
+
+ if (ctx.options.value<CLI::generate_ostream> ())
+ {
+ ctx.os << "#include <xsd/cxx/tree/std-ostream-operators.hxx>" << endl
+ << endl;
+ }
+
+ Streams const& ist (ctx.options.value<CLI::generate_insertion> ());
+ if (!ist.empty ())
+ {
+ for (Streams::ConstIterator i (ist.begin ()); i != ist.end (); ++i)
+ {
+ if (*i == "ACE_OutputCDR")
+ ctx.os << "#include <xsd/cxx/tree/ace-cdr-stream-insertion.hxx>"
+ << endl;
+ else if (*i == "XDR")
+ ctx.os << "#include <xsd/cxx/tree/xdr-stream-insertion.hxx>"
+ << endl;
+ }
+
+ ctx.os << "#include <xsd/cxx/tree/stream-insertion.hxx>" << endl
+ << endl;
+ }
+
+ Streams const& est (ctx.options.value<CLI::generate_extraction> ());
+ if (!est.empty ())
+ {
+ for (Streams::ConstIterator i (est.begin ()); i != est.end (); ++i)
+ {
+ if (*i == "ACE_InputCDR")
+ ctx.os << "#include <xsd/cxx/tree/ace-cdr-stream-extraction.hxx>"
+ << endl;
+ else if (*i == "XDR")
+ ctx.os << "#include <xsd/cxx/tree/xdr-stream-extraction.hxx>"
+ << endl;
+ }
+
+ ctx.os << "#include <xsd/cxx/tree/stream-extraction.hxx>" << endl
+ << endl;
+ }
+
+ // Emit fundamental types.
+ //
+ {
+ Traversal::Schema schema;
+ Traversal::Names names;
+ FundamentalNamespace ns (ctx);
+
+ schema >> names >> ns;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+ else
+ {
+ Boolean inline_ (ctx.options.value<CLI::generate_inline> ());
+
+ ctx.os << "#include <memory> // std::auto_ptr" << endl
+ << "#include <algorithm> // std::binary_search" << endl
+ << endl;
+
+ ctx.os << "#include <xsd/cxx/tree/exceptions.hxx>" << endl
+ << "#include <xsd/cxx/tree/elements.hxx>" << endl
+ << "#include <xsd/cxx/tree/containers.hxx>" << endl
+ << "#include <xsd/cxx/tree/list.hxx>" << endl
+ << endl;
+
+ if (!ctx.options.value<CLI::suppress_parsing> ())
+ {
+ ctx.os << "#include <xsd/cxx/xml/dom/parsing-header.hxx>" << endl
+ << endl;
+ }
+
+ if (ctx.options.value<CLI::generate_wildcard> ())
+ {
+ if (ctx.options.value<CLI::suppress_parsing> () ||
+ !ctx.options.value<CLI::generate_serialization> ())
+ ctx.os << "#include <xsd/cxx/xml/dom/auto-ptr.hxx>" << endl;
+
+ ctx.os << "#include <xsd/cxx/tree/containers-wildcard.hxx>" << endl
+ << endl;
+ }
+
+ if (!ctx.options.value<CLI::generate_extraction> ().empty ())
+ ctx.os << "#include <xsd/cxx/tree/istream-fwd.hxx>" << endl
+ << endl;
+
+ // Emit header includes.
+ //
+ {
+ if (inline_)
+ {
+ ctx.os << "#ifndef XSD_DONT_INCLUDE_INLINE" << endl
+ << "#define XSD_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 XSD_DONT_INCLUDE_INLINE" << endl
+ << "#else" << endl
+ << endl;
+
+ schema.dispatch (ctx.schema_root);
+
+ ctx.os << "#endif // XSD_DONT_INCLUDE_INLINE" << endl
+ << endl;
+ }
+ }
+
+
+ {
+ Traversal::Schema schema;
+
+ Traversal::Sources sources;
+ Traversal::Names names_ns, names;
+
+ DocumentedNamespace ns (ctx);
+
+ List list (ctx);
+ Union union_ (ctx);
+ Complex complex (ctx);
+ Enumeration enumeration (ctx);
+ GlobalElement element (ctx);
+
+ schema >> sources >> schema;
+ schema >> names_ns >> ns >> names;
+
+ names >> list;
+ names >> union_;
+ names >> complex;
+ names >> enumeration;
+
+ if (ctx.options.value<CLI::generate_element_type> ())
+ names >> element;
+
+ schema.dispatch (ctx.schema_root);
+ }
+
+ // Emit inline includes.
+ //
+ if (inline_)
+ {
+ ctx.os << "#ifndef XSD_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 // XSD_DONT_INCLUDE_INLINE" << endl
+ << endl;
+ }
+ }
+ }
+ }
+}
diff --git a/xsd/cxx/tree/tree-header.hxx b/xsd/cxx/tree/tree-header.hxx
new file mode 100644
index 0000000..0aadeaf
--- /dev/null
+++ b/xsd/cxx/tree/tree-header.hxx
@@ -0,0 +1,22 @@
+// file : xsd/cxx/tree/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_TREE_TREE_HEADER_HXX
+#define CXX_TREE_TREE_HEADER_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/tree/elements.hxx>
+
+namespace CXX
+{
+ namespace Tree
+ {
+ Void
+ generate_tree_header (Context&);
+ }
+}
+
+#endif // CXX_TREE_TREE_HEADER_HXX
diff --git a/xsd/cxx/tree/tree-inline.cxx b/xsd/cxx/tree/tree-inline.cxx
new file mode 100644
index 0000000..5bec713
--- /dev/null
+++ b/xsd/cxx/tree/tree-inline.cxx
@@ -0,0 +1,1025 @@
+// file : xsd/cxx/tree/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/tree/tree-inline.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+namespace CXX
+{
+ namespace Tree
+ {
+ namespace
+ {
+ struct List : Traversal::List, protected virtual Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String name (ename (l));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (l, name) && !name)
+ return;
+
+ SemanticGraph::Type& item_type (l.argumented ().type ());
+ String item_name (item_type_name (item_type));
+ String base_type (L"::xsd::cxx::tree::list< " + item_name +
+ L", " + char_type);
+
+ if (item_type.is_a<SemanticGraph::Fundamental::Double> ())
+ base_type += L", ::xsd::cxx::tree::schema_type::double_";
+ else if (item_type.is_a<SemanticGraph::Fundamental::Decimal> ())
+ base_type += L", ::xsd::cxx::tree::schema_type::decimal";
+
+ base_type += L" >";
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ // c-tor ()
+ //
+ os << inl
+ << name << "::" << endl
+ << name << " ()"
+ << "{"
+ << "}";
+
+ // c-tor (size_type, const X& x)
+ //
+ String size_type (name != L"size_type"
+ ? String (L"size_type")
+ : base_type + L"::size_type");
+
+ os << inl
+ << name << "::" << endl
+ << name << " (" << size_type << " n, const " << item_name <<
+ "& x)" << endl
+ << ": " << base_type << " (n, x)"
+ << "{"
+ << "}";
+
+ // copy c-tor ()
+ //
+ os << inl
+ << name << "::" << endl
+ << name << " (const " << name << "& o," << endl
+ << flags_type << " f," << endl
+ << container << "* c)" << endl
+ << ": " << any_simple_type << " (o, f, c)," << endl
+ << " " << base_type << " (o, f, c)"
+ << "{"
+ << "}";
+ }
+
+ private:
+ String
+ item_type_name (SemanticGraph::Type& t)
+ {
+ std::wostringstream o;
+
+ MemberTypeName type (*this, o);
+ type.dispatch (t);
+
+ return o.str ();
+ }
+ };
+
+
+ struct Union : Traversal::Union, protected virtual Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ String name (ename (u));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (u, name) && !name)
+ return;
+
+ String const& base (xs_string_type);
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ if (options.value<CLI::generate_default_ctor> ())
+ {
+ // c-tor ()
+ //
+ os << inl
+ << name << "::" << endl
+ << name << " ()" << endl
+ << ": " << base << " ()"
+ << "{"
+ << "}";
+ }
+
+ // c-tor (const char*)
+ //
+ os << inl
+ << name << "::" << endl
+ << name << " (const " << char_type << "* s)" << endl
+ << ": " << base << " (s)"
+ << "{"
+ << "}";
+
+ // c-tor (string const&)
+ //
+ os << inl
+ << name << "::" << endl
+ << name << " (const " << string_type << "& s)" << endl
+ << ": " << base << " (s)"
+ << "{"
+ << "}";
+
+ // copy c-tor ()
+ //
+ os << inl
+ << name << "::" << endl
+ << name << " (const " << name << "& o," << endl
+ << flags_type << " f," << endl
+ << container << "* c)" << endl
+ << ": " << base << " (o, f, c)"
+ << "{"
+ << "}";
+ }
+ };
+
+ // Enumeration
+ //
+
+ // Generate a sequence of explicit c-tor calls until we reach
+ // one of the fundamental string types that can be constructed
+ // from char literals.
+ //
+ struct CtorCallSequence: Traversal::Complex,
+ Traversal::Fundamental::Type,
+ protected virtual Context
+ {
+ CtorCallSequence (Context& c, String const& arg)
+ : Context (c), arg_ (arg), base_type_name_ (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ // This type should be ultimately string based.
+ //
+ assert (c.inherits_p ());
+
+ os << ename (c) << " (" << endl;
+
+ dispatch (c.inherits ().base ());
+
+ os << ")";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Type& t)
+ {
+ base_type_name_.dispatch (t);
+
+ os << " (" << arg_ << ")";
+ }
+
+ private:
+ String arg_;
+ BaseTypeName base_type_name_;
+ };
+
+ struct Enumeration : Traversal::Enumeration,
+ protected virtual Context
+ {
+ Enumeration (Context& c)
+ : Context (c), member_ (c)
+ {
+ inherits_member_ >> member_;
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ String name (ename (e));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (e, name) && !name)
+ return;
+
+ Boolean string_based (false);
+ {
+ IsStringBasedType t (string_based);
+ t.dispatch (e);
+ }
+
+ Boolean enum_based (false);
+ if (string_based)
+ {
+ SemanticGraph::Enumeration* be (0);
+ IsEnumBasedType t (be);
+ t.dispatch (e);
+
+ enum_based = (be != 0);
+ }
+
+ String value;
+ if (string_based)
+ value = evalue (e);
+
+ // Get to the ultimate base and see if is a fundamental type.
+ //
+ Boolean fund_based (false);
+ SemanticGraph::Type& ult_base (ultimate_base (e));
+ {
+ IsFundamentalType t (fund_based);
+ t.dispatch (ult_base);
+ }
+
+ //
+ //
+ String base; // base type name
+ {
+ std::wostringstream o;
+
+ BaseTypeName base_type (*this, o);
+ Traversal::Inherits inherits_type (base_type);
+
+ inherits (e, inherits_type);
+ base = o.str ();
+ }
+
+ os << "// " << name << endl
+ << "// " << endl
+ << endl;
+
+ // default c-tor
+ //
+ if (options.value<CLI::generate_default_ctor> ())
+ {
+ os << inl
+ << name << "::" << endl
+ << name << " ()" << endl
+ << ": " << base << " ()"
+ << "{"
+ << "}";
+ }
+
+ // c-tor (value)
+ //
+ if (string_based)
+ {
+ os << inl
+ << name << "::" << endl
+ << name << " (" << value << " v)" << endl
+ << ": ";
+
+ // If we are enum-based then we can just use the corresponding
+ // base c-tor directly. Otherwise we will use the from-string
+ // c-tor.
+ //
+ if (enum_based)
+ os << base << " (v)";
+ else
+ {
+ CtorCallSequence t (*this, L"_xsd_" + name + L"_literals_[v]");
+ t.dispatch (e.inherits ().base ());
+ }
+
+ os << "{"
+ << "}";
+ }
+
+ // c-tor (const char*)
+ //
+ if (string_based)
+ {
+ os << inl
+ << name << "::" << endl
+ << name << " (const " << char_type << "* v)" << endl
+ << ": " << base << " (v)"
+ << "{"
+ << "}";
+ }
+
+ // c-tor (const std::string&)
+ //
+ if (string_based)
+ {
+ os << inl
+ << name << "::" << endl
+ << name << " (const " << string_type << "& v)" << endl
+ << ": " << base << " (v)"
+ << "{"
+ << "}";
+ }
+
+ // c-tor (fundamental)
+ //
+ if (fund_based)
+ {
+ os << inl
+ << name << "::" << endl
+ << name << " (";
+
+ member_.dispatch (ult_base);
+
+ os << " v)"
+ << ": " << base << " (v)"
+ << "{"
+ << "}";
+ }
+
+ // c-tor (base)
+ //
+ // If the ultimate is also our immediate base and it is a
+ // fundamental type then this c-tor clashes with c-tor
+ // (fundamental) above.
+ //
+ if (!fund_based || &ult_base != &e.inherits ().base ())
+ {
+ os << inl
+ << name << "::" << endl
+ << name << " (const ";
+
+ inherits (e, inherits_member_);
+
+ os << "& v)" << endl
+ << ": " << base << " (v)"
+ << "{"
+ << "}";
+ }
+
+ // copy c-tor
+ //
+ os << inl
+ << name << "::" << endl
+ << name << " (const " << name << "& v," << endl
+ << flags_type << " f," << endl
+ << container << "* c)" << endl
+ << ": " << base << " (v, f, c)"
+ << "{"
+ << "}";
+
+ // operato= (value)
+ //
+ if (string_based)
+ {
+ os << inl
+ << name << "& " << name << "::" << endl
+ << "operator= (" << value << " v)"
+ << "{"
+ << "static_cast< " << base << "& > (*this) = ";
+
+ // If we are enum-based then we can just use the corresponding
+ // base assignment directly. Otherwise we will use the from-
+ // base assignment and a from-string base c-tor.
+ //
+ if (enum_based)
+ os << "v";
+ else
+ {
+ os << endl;
+
+ CtorCallSequence t (*this, L"_xsd_" + name + L"_literals_[v]");
+ t.dispatch (e.inherits ().base ());
+ }
+
+ os << ";"
+ << endl
+ << "return *this;"
+ << "}";
+ }
+
+ os << endl;
+ }
+
+ private:
+ Traversal::Inherits inherits_member_;
+ MemberTypeName member_;
+ };
+
+ struct Member: Traversal::Member, protected virtual Context
+ {
+ Member (Context& c, String const& scope)
+ : Context (c), scope_ (scope)
+ {
+ }
+
+ virtual Void
+ traverse (Type& m)
+ {
+ if (skip (m))
+ return;
+
+ String const& aname (eaname (m));
+ String const& mname (emname (m));
+ String const& member (emember (m));
+
+ Boolean fund (false);
+ {
+ IsFundamentalType t (fund);
+ t.dispatch (m.type ());
+ }
+
+ Boolean def_attr (m.default_ () &&
+ m.is_a<SemanticGraph::Attribute> () &&
+ !is_qname (m.type ()));
+
+ if (max (m) != 1)
+ {
+ // sequence
+ //
+ String container (econtainer (m));
+ String q_container (scope_ + L"::" + container);
+
+ // container const&
+ // name () const;
+ //
+ os << inl
+ << "const " << q_container << "& " << scope_ << "::" << endl
+ << aname << " () const"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+
+ // container&
+ // name ();
+ //
+ os << inl
+ << q_container << "& " << scope_ << "::" << endl
+ << aname << " ()"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+
+ // void
+ // name (container const&);
+ //
+ os << inl
+ << "void " << scope_ << "::" << endl
+ << mname << " (const " << container << "& s)"
+ << "{"
+ << "this->" << member << " = s;"
+ << "}";
+ }
+ else if (min (m) == 0 && !def_attr)
+ {
+ // optional
+ //
+ String type (etype (m));
+ String container (econtainer (m));
+ String q_container (scope_ + L"::" + container);
+
+ // container const&
+ // name () const;
+ //
+ os << inl
+ << "const " << q_container << "& " << scope_ << "::" << endl
+ << aname << " () const"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+
+ // container&
+ // name ();
+ //
+ os << inl
+ << q_container << "& " << scope_ << "::" << endl
+ << aname << " ()"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+
+ // void
+ // name (type const&);
+ //
+ os << inl
+ << "void " << scope_ << "::" << endl
+ << mname << " (const " << type << "& x)"
+ << "{"
+ << "this->" << member << ".set (x);"
+ << "}";
+
+ // void
+ // name (container const&);
+ //
+ os << inl
+ << "void " << scope_ << "::" << endl
+ << mname << " (const " << container << "& x)"
+ << "{"
+ << "this->" << member << " = x;"
+ << "}";
+
+ // void
+ // name (auto_ptr<type>);
+ //
+ if (!fund)
+ os << inl
+ << "void " << scope_ << "::" << endl
+ << mname << " (::std::auto_ptr< " << type << " > x)"
+ << "{"
+ << "this->" << member << ".set (x);"
+ << "}";
+ }
+ else
+ {
+ // one
+ //
+ String type (etype (m));
+ String q_type (scope_ + L"::" + type);
+
+ // type const&
+ // name () const;
+ //
+ os << inl
+ << "const " << q_type << "& " << scope_ << "::" << endl
+ << aname << " () const"
+ << "{"
+ << "return this->" << member << ".get ();"
+ << "}";
+
+ // Do not generate modifiers for fixed attributes.
+ //
+ if (!(def_attr && m.fixed ()))
+ {
+ // type&
+ // name ();
+ //
+ os << inl
+ << q_type << "& " << scope_ << "::" << endl
+ << aname << " ()"
+ << "{"
+ << "return this->" << member << ".get ();"
+ << "}";
+
+ // void
+ // name (type const&);
+ //
+ os << inl
+ << "void " << scope_ << "::" << endl
+ << mname << " (const " << type << "& x)"
+ << "{"
+ << "this->" << member << ".set (x);"
+ << "}";
+
+ // void
+ // name (auto_ptr<type>);
+ //
+ if (!fund)
+ os << inl
+ << "void " << scope_ << "::" << endl
+ << mname << " (::std::auto_ptr< " << type << " > x)"
+ << "{"
+ << "this->" << member << ".set (x);"
+ << "}";
+ }
+ }
+
+
+ // default_value
+ //
+ if (m.default_ () && !is_qname (m.type ()))
+ {
+ Boolean simple (true);
+
+ if (m.is_a<SemanticGraph::Element> ())
+ {
+ IsSimpleType test (simple);
+ test.dispatch (m.type ());
+ }
+
+ if (simple)
+ {
+ os << inl
+ << "const " << scope_ << "::" << etype (m) << "& " <<
+ scope_ << "::" << endl
+ << edefault_value (m) << " ()"
+ << "{"
+ << "return " << edefault_value_member (m) << ";"
+ << "}";
+ }
+ }
+ }
+
+ private:
+ String scope_;
+ };
+
+ struct Any: Traversal::Any,
+ Traversal::AnyAttribute,
+ protected virtual Context
+ {
+ Any (Context& c, String const& scope)
+ : Context (c), scope_ (scope)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ String const& aname (eaname (a));
+ String const& mname (emname (a));
+
+ String const& member (emember (a));
+
+ if (max (a) != 1)
+ {
+ // sequence
+ //
+ String container (econtainer (a));
+ String q_container (scope_ + L"::" + container);
+
+ // container const&
+ // name () const;
+ //
+ os << inl
+ << "const " << q_container << "& " << scope_ << "::" << endl
+ << aname << " () const"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+
+ // container&
+ // name ();
+ //
+ os << inl
+ << q_container << "& " << scope_ << "::" << endl
+ << aname << " ()"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+
+ // void
+ // name (container const&);
+ //
+ os << inl
+ << "void " << scope_ << "::" << endl
+ << mname << " (const " << container << "& s)"
+ << "{"
+ << "this->" << member << " = s;"
+ << "}";
+ }
+ else if (min (a) == 0)
+ {
+ // optional
+ //
+ String container (econtainer (a));
+ String q_container (scope_ + L"::" + container);
+
+ // container const&
+ // name () const;
+ //
+ os << inl
+ << "const " << q_container << "& " << scope_ << "::" << endl
+ << aname << " () const"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+
+ // container&
+ // name ();
+ //
+ os << inl
+ << q_container << "& " << scope_ << "::" << endl
+ << aname << " ()"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+
+ // void
+ // name (type const&);
+ //
+ os << inl
+ << "void " << scope_ << "::" << endl
+ << mname << " (const " << xerces_ns << "::DOMElement& e)"
+ << "{"
+ << "this->" << member << ".set (e);"
+ << "}";
+
+ // void
+ // name (type*);
+ //
+ os << inl
+ << "void " << scope_ << "::" << endl
+ << mname << " (" << xerces_ns << "::DOMElement* e)"
+ << "{"
+ << "this->" << member << ".set (e);"
+ << "}";
+
+ // void
+ // name (container const&);
+ //
+ os << inl
+ << "void " << scope_ << "::" << endl
+ << mname << " (const " << container << "& x)"
+ << "{"
+ << "this->" << member << " = x;"
+ << "}";
+ }
+ else
+ {
+ // one
+ //
+
+ // type const&
+ // name () const;
+ //
+ os << inl
+ << "const " << xerces_ns << "::DOMElement& " <<
+ scope_ << "::" << endl
+ << aname << " () const"
+ << "{"
+ << "return this->" << member << ".get ();"
+ << "}";
+
+ // type&
+ // name ();
+ //
+ os << inl
+ << xerces_ns << "::DOMElement& " << scope_ << "::" << endl
+ << aname << " ()"
+ << "{"
+ << "return this->" << member << ".get ();"
+ << "}";
+
+ // void
+ // name (type const&);
+ //
+ os << inl
+ << "void " << scope_ << "::" << endl
+ << mname << " (const " << xerces_ns << "::DOMElement& e)"
+ << "{"
+ << "this->" << member << ".set (e);"
+ << "}";
+
+ // void
+ // name (type*);
+ //
+ os << inl
+ << "void " << scope_ << "::" << endl
+ << mname << " (" << xerces_ns << "::DOMElement* e)"
+ << "{"
+ << "this->" << member << ".set (e);"
+ << "}";
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute& a)
+ {
+ String const& aname (eaname (a));
+ String const& mname (emname (a));
+
+ String const& member (emember (a));
+ String container (econtainer (a));
+ String q_container (scope_ + L"::" + container);
+
+ // container const&
+ // name () const;
+ //
+ os << inl
+ << "const " << q_container << "& " << scope_ << "::" << endl
+ << aname << " () const"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+
+ // container&
+ // name ();
+ //
+ os << inl
+ << q_container << "& " << scope_ << "::" << endl
+ << aname << " ()"
+ << "{"
+ << "return this->" << member << ";"
+ << "}";
+
+ // void
+ // name (container const&);
+ //
+ os << inl
+ << "void " << scope_ << "::" << endl
+ << mname << " (const " << container << "& s)"
+ << "{"
+ << "this->" << member << " = s;"
+ << "}";
+ }
+
+ private:
+ String scope_;
+ };
+
+ struct Complex : Traversal::Complex, protected virtual Context
+ {
+ Complex (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ String name (ename (c));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (c, name) && !name)
+ return;
+
+ os << "// " << name << endl
+ << "// " << endl
+ << endl;
+
+ // Generate accessors and modifiers.
+ //
+ Any any (*this, name);
+ Member member (*this, name);
+ Traversal::Names names;
+
+ if (options.value<CLI::generate_wildcard> ())
+ names >> any;
+
+ names >> member;
+
+ Complex::names (c, names);
+
+ // dom_document accessors.
+ //
+ if (edom_document_member_p (c))
+ {
+ os << inl
+ << "const " << xerces_ns << "::DOMDocument& " <<
+ name << "::" << endl
+ << edom_document (c) << " () const"
+ << "{"
+ << "return *" << edom_document_member (c) << ";"
+ << "}";
+
+ os << inl
+ << xerces_ns << "::DOMDocument& " << name << "::" << endl
+ << edom_document (c) << " ()"
+ << "{"
+ << "return *" << edom_document_member (c) << ";"
+ << "}";
+ }
+
+ os << endl;
+ }
+ };
+
+
+ struct GlobalElement : Traversal::Element,
+ GlobalElementBase,
+ protected virtual Context
+ {
+ GlobalElement (Context& c)
+ : Context (c), GlobalElementBase (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (!doc_root_p (e))
+ return;
+
+ Boolean fund (false);
+ {
+ IsFundamentalType test (fund);
+ test.dispatch (e.type ());
+ }
+
+ String const& name (ename (e));
+
+ os << "// " << name << endl
+ << "// " << endl
+ << endl;
+
+ // Accessors/modifiers.
+ //
+ String const& type (etype (e));
+ String const& aname (eaname (e));
+ String const& mname (emname (e));
+ String const& member (emember (e));
+
+ // type const&
+ // name () const;
+ //
+ os << inl
+ << "const " << name << "::" << type << "& " << name << "::" << endl
+ << aname << " () const"
+ << "{"
+ << "return this->" << member << ".get ();"
+ << "}";
+
+ // type&
+ // name ();
+ //
+ os << inl
+ << name << "::" << type << "& " << name << "::" << endl
+ << aname << " ()"
+ << "{"
+ << "return this->" << member << ".get ();"
+ << "}";
+
+ // void
+ // name (type const&);
+ //
+ os << inl
+ << "void " << name << "::" << endl
+ << mname << " (const " << type << "& x)"
+ << "{"
+ << "return this->" << member << ".set (x);"
+ << "}";
+
+ // void
+ // name (auto_ptr<type>);
+ //
+ if (!fund)
+ {
+ os << inl
+ << "void " << name << "::" << endl
+ << mname << " (::std::auto_ptr< " << type << " > p)"
+ << "{"
+ << "return this->" << member << ".set (p);"
+ << "}";
+ }
+ }
+ };
+ }
+
+ Void
+ generate_tree_inline (Context& ctx, UnsignedLong first, UnsignedLong last)
+ {
+ // 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, first, last);
+
+ List list (ctx);
+ Union union_ (ctx);
+ Complex complex (ctx);
+ Enumeration enumeration (ctx);
+ GlobalElement element (ctx);
+
+ schema >> sources >> schema;
+ schema >> names_ns >> ns >> names;
+
+ names >> list;
+ names >> union_;
+ names >> complex;
+ names >> enumeration;
+
+ if (ctx.options.value<CLI::generate_element_type> ())
+ names >> element;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+}
diff --git a/xsd/cxx/tree/tree-inline.hxx b/xsd/cxx/tree/tree-inline.hxx
new file mode 100644
index 0000000..14cb11c
--- /dev/null
+++ b/xsd/cxx/tree/tree-inline.hxx
@@ -0,0 +1,22 @@
+// file : xsd/cxx/tree/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_TREE_TREE_INLINE_HXX
+#define CXX_TREE_TREE_INLINE_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/tree/elements.hxx>
+
+namespace CXX
+{
+ namespace Tree
+ {
+ Void
+ generate_tree_inline (Context&, UnsignedLong first, UnsignedLong last);
+ }
+}
+
+#endif // CXX_TREE_TREE_INLINE_HXX
diff --git a/xsd/cxx/tree/tree-source.cxx b/xsd/cxx/tree/tree-source.cxx
new file mode 100644
index 0000000..7952e38
--- /dev/null
+++ b/xsd/cxx/tree/tree-source.cxx
@@ -0,0 +1,3461 @@
+// file : xsd/cxx/tree/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/tree/tree-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cult/containers/list.hxx>
+
+#include <iostream>
+
+using std::wcerr;
+
+namespace CXX
+{
+ namespace Tree
+ {
+ namespace
+ {
+ struct List: Traversal::List, protected virtual Context
+ {
+ List (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& l)
+ {
+ String name (ename (l));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (l, name) && !name)
+ return;
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ if (!options.value<CLI::suppress_parsing> ())
+ {
+ SemanticGraph::Type& item_type (l.argumented ().type ());
+ String base (L"::xsd::cxx::tree::list< " +
+ item_type_name (item_type) + L", " + char_type);
+
+ if (item_type.is_a<SemanticGraph::Fundamental::Double> ())
+ base += L", ::xsd::cxx::tree::schema_type::double_";
+ else if (item_type.is_a<SemanticGraph::Fundamental::Decimal> ())
+ base += L", ::xsd::cxx::tree::schema_type::decimal";
+
+ base += L" >";
+
+ // c-tor (xercesc::DOMElement)
+ //
+ os << name << "::" << endl
+ << name << " (const " << xerces_ns << "::DOMElement& e," << endl
+ << flags_type << " f," << endl
+ << container << "* c)" << endl
+ << ": " << any_simple_type << " (e, f, c)," << endl
+ << " " << base << " (e, f, c)"
+ << "{"
+ << "}";
+
+ // c-tor (xercesc::DOMAttr)
+ //
+ os << name << "::" << endl
+ << name << " (const " << xerces_ns << "::DOMAttr& a," << endl
+ << flags_type << " f," << endl
+ << container << "* c)" << endl
+ << ": " << any_simple_type << " (a, f, c)," << endl
+ << " " << base << " (a, f, c)"
+ << "{"
+ << "}";
+
+ // c-tor (string const&, xercesc::DOMElement)
+ //
+ os << name << "::" << endl
+ << name << " (const " << string_type << "& s," << endl
+ << "const " << xerces_ns << "::DOMElement* e," << endl
+ << flags_type << " f," << endl
+ << container << "* c)" << endl
+ << ": " << any_simple_type << " (s, e, f, c)," << endl
+ << " " << base << " (s, e, f, c)"
+ << "{"
+ << "}";
+ }
+
+ // _clone
+ //
+ os << name << "* " << name << "::" << endl
+ << "_clone (" << flags_type << " f," << endl
+ << container << "* c) const"
+ << "{"
+ << "return new class " << name << " (*this, f, c);"
+ << "}";
+
+ // d-tor
+ //
+ os << name << "::" << endl
+ << "~" << name << " ()"
+ << "{"
+ << "}";
+
+ // Register with type factory map.
+ //
+ if (polymorphic && !l.context ().count ("anonymous"))
+ {
+ // Note that we are using the original type name.
+ //
+ String const& name (ename (l));
+
+ if (!options.value<CLI::suppress_parsing> ())
+ os << "static" << endl
+ << "const ::xsd::cxx::tree::type_factory_initializer< 0, " <<
+ char_type << ", " << name << " >" << endl
+ << "_xsd_" << name << "_type_factory_init (" << endl
+ << L << strlit (l.name ()) << "," << endl
+ << L << strlit (xml_ns_name (l)) << ");"
+ << endl;
+
+ if (options.value<CLI::generate_comparison> ())
+ os << "static" << endl
+ << "const ::xsd::cxx::tree::comparison_initializer< 0, " <<
+ char_type << ", " << name << " >" << endl
+ << "_xsd_" << name << "_comparison_init;"
+ << endl;
+ }
+ }
+
+ private:
+ String
+ item_type_name (SemanticGraph::Type& t)
+ {
+ std::wostringstream o;
+
+ MemberTypeName type (*this, o);
+ type.dispatch (t);
+
+ return o.str ();
+ }
+ };
+
+
+ struct Union: Traversal::Union, protected virtual Context
+ {
+ Union (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& u)
+ {
+ String name (ename (u));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (u, name) && !name)
+ return;
+
+ String const& base (xs_string_type);
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ if (!options.value<CLI::suppress_parsing> ())
+ {
+ // c-tor (xercesc::DOMElement)
+ //
+ os << name << "::" << endl
+ << name << " (const " << xerces_ns << "::DOMElement& e," << endl
+ << flags_type << " f," << endl
+ << container << "* c)" << endl
+ << ": " << base << " (e, f, c)"
+ << "{"
+ << "}";
+
+ // c-tor (xercesc::DOMAttr)
+ //
+ os << name << "::" << endl
+ << name << " (const " << xerces_ns << "::DOMAttr& a," << endl
+ << flags_type << " f," << endl
+ << container << "* c)" << endl
+ << ": " << base << " (a, f, c)"
+ << "{"
+ << "}";
+
+ // c-tor (string const&, xercesc::DOMElement)
+ //
+ os << name << "::" << endl
+ << name << " (const " << string_type << "& s," << endl
+ << "const " << xerces_ns << "::DOMElement* e," << endl
+ << flags_type << " f," << endl
+ << container << "* c)" << endl
+ << ": " << base << " (s, e, f, c)"
+ << "{"
+ << "}";
+ }
+
+ // _clone
+ //
+ os << name << "* " << name << "::" << endl
+ << "_clone (" << flags_type << " f," << endl
+ << container << "* c) const"
+ << "{"
+ << "return new class " << name << " (*this, f, c);"
+ << "}";
+
+ // Register with type factory map.
+ //
+ if (polymorphic && !u.context ().count ("anonymous"))
+ {
+ // Note that we are using the original type name.
+ //
+ String const& name (ename (u));
+
+ if (!options.value<CLI::suppress_parsing> ())
+ os << "static" << endl
+ << "const ::xsd::cxx::tree::type_factory_initializer< 0, " <<
+ char_type << ", " << name << " >" << endl
+ << "_xsd_" << name << "_type_factory_init (" << endl
+ << L << strlit (u.name ()) << "," << endl
+ << L << strlit (xml_ns_name (u)) << ");"
+ << endl;
+
+ if (options.value<CLI::generate_comparison> ())
+ os << "static" << endl
+ << "const ::xsd::cxx::tree::comparison_initializer< 0, " <<
+ char_type << ", " << name << " >" << endl
+ << "_xsd_" << name << "_comparison_init;"
+ << endl;
+ }
+ }
+ };
+
+
+ // Enumeration mapping.
+ //
+
+ struct EnumeratorLiteral: Traversal::Enumerator,
+ protected virtual Context
+ {
+ EnumeratorLiteral (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ os << L << strlit (e.name ());
+ }
+ };
+
+
+ //
+ //
+ struct LiteralInfo
+ {
+ LiteralInfo (String const& value, String const& name)
+ : value_ (value), name_ (name)
+ {
+ }
+
+ String value_;
+ String name_;
+ };
+
+ Boolean
+ operator< (LiteralInfo const& x, LiteralInfo const& y)
+ {
+ return x.value_ < y.value_;
+ }
+
+ typedef Cult::Containers::List<LiteralInfo> LiteralInfoList;
+
+
+ // Populate LiteralInfoList
+ //
+ struct EnumeratorLiteralInfo: Traversal::Enumerator,
+ protected virtual Context
+
+ {
+ EnumeratorLiteralInfo (Context& c, LiteralInfoList& list)
+ : Context (c), list_ (list)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ list_.push_back (LiteralInfo (e.name (), ename (e)));
+ }
+
+ private:
+ LiteralInfoList& list_;
+ };
+
+
+ struct Enumeration: Traversal::Enumeration, protected virtual Context
+ {
+ Enumeration (Context& c)
+ : Context (c), enumerator_literal_ (c)
+ {
+ names_enumerator_literal_ >> enumerator_literal_;
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ String name (ename (e));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (e, name) && !name)
+ return;
+
+ Boolean string_based (false);
+ {
+ IsStringBasedType t (string_based);
+ t.dispatch (e);
+ }
+
+ SemanticGraph::Enumeration* be (0);
+ Boolean enum_based (false);
+ if (string_based)
+ {
+ IsEnumBasedType t (be);
+ t.dispatch (e);
+
+ enum_based = (be != 0);
+ }
+
+ String value;
+ if (string_based)
+ value = evalue (e);
+
+ UnsignedLong enum_count (0);
+
+ for (Type::NamesIterator i (e.names_begin ()), end (e.names_end ());
+ i != end; ++i)
+ ++enum_count;
+
+ String base; // base type name
+ {
+ std::wostringstream o;
+
+ BaseTypeName base_type (*this, o);
+ Traversal::Inherits inherits_type (base_type);
+
+ inherits (e, inherits_type);
+ base = o.str ();
+ }
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ if (!options.value<CLI::suppress_parsing> ())
+ {
+ // c-tor (xercesc::DOMElement)
+ //
+ os << name << "::" << endl
+ << name << " (const " << xerces_ns << "::DOMElement& e," << endl
+ << flags_type << " f," << endl
+ << container << "* c)" << endl
+ << ": " << base << " (e, f, c)"
+ << "{";
+
+ if (string_based)
+ os << "_xsd_" << name << "_convert ();";
+
+ os << "}";
+
+
+ // c-tor (xercesc::DOMAttr)
+ //
+ os << name << "::" << endl
+ << name << " (const " << xerces_ns << "::DOMAttr& a," << endl
+ << flags_type << " f," << endl
+ << container << "* c)" << endl
+ << ": " << base << " (a, f, c)"
+ << "{";
+
+ if (string_based)
+ {
+ os << "_xsd_" << name << "_convert ();";
+ }
+
+ os << "}";
+
+
+ // c-tor (string const&, xercesc::DOMElement)
+ //
+ os << name << "::" << endl
+ << name << " (const " << string_type << "& s," << endl
+ << "const " << xerces_ns << "::DOMElement* e," << endl
+ << flags_type << " f," << endl
+ << container << "* c)" << endl
+ << ": " << base << " (s, e, f, c)"
+ << "{";
+
+ if (string_based)
+ {
+ os << "_xsd_" << name << "_convert ();";
+ }
+
+ os << "}";
+ }
+
+ // _clone
+ //
+ os << name << "* " << name << "::" << endl
+ << "_clone (" << flags_type << " f," << endl
+ << container << "* c) const"
+ << "{"
+ << "return new class " << name << " (*this, f, c);"
+ << "}";
+
+ // convert
+ //
+ // @@ TODO: expected list
+ //
+ if (string_based)
+ {
+ String i_name (L"_xsd_" + name + L"_indexes_");
+
+ os << name << "::" << value << " " <<
+ name << "::" << endl
+ << "_xsd_" << name << "_convert () const"
+ << "{"
+ << "::xsd::cxx::tree::enum_comparator< " << char_type <<
+ " > c (_xsd_" << name << "_literals_);"
+ << "const " << value << "* i (::std::lower_bound (" << endl
+ << i_name << "," << endl
+ << i_name << " + " << enum_count << "," << endl
+ << "*this," << endl
+ << "c));"
+ << endl
+ << "if (i == " << i_name << " + " << enum_count << " || " <<
+ "_xsd_" << name << "_literals_[*i] != *this)"
+ << "{"
+ << "throw ::xsd::cxx::tree::unexpected_enumerator < " <<
+ char_type << " > (*this);"
+ << "}"
+ << "return *i;"
+ << "}";
+ }
+
+ // literals and indexes
+ //
+ if (string_based)
+ {
+ if (enum_based)
+ {
+ os << "const " << char_type << "* const* " << name << "::" << endl
+ << "_xsd_" << name << "_literals_ = " <<
+ fq_name (*be) << "::_xsd_" << ename (*be) << "_literals_;"
+ << endl;
+ }
+ else
+ {
+ os << "const " << char_type << "* const " << name << "::" << endl
+ << "_xsd_" << name << "_literals_[" << enum_count << "] ="
+ << "{";
+
+ names<Enumeration> (
+ e, names_enumerator_literal_, 0, 0, 0, &Enumeration::comma);
+
+ os << "};";
+ }
+
+
+ LiteralInfoList l;
+ {
+ EnumeratorLiteralInfo enumerator (*this, l);
+ Traversal::Names names_enumerator (enumerator);
+ names (e, names_enumerator);
+ }
+
+ l.sort ();
+
+ os << "const " << name << "::" << value << " " <<
+ name << "::" << endl
+ << "_xsd_" << name << "_indexes_[" << enum_count << "] ="
+ << "{";
+
+ String fq_name (ns_scope + L"::" + name);
+
+ for (LiteralInfoList::Iterator
+ b (l.begin ()), i (b), end (l.end ()); i != end; ++i)
+ {
+ if (i != b)
+ os << "," << endl;
+
+ os << fq_name << "::" << i->name_;
+ }
+
+ os << "};";
+ }
+
+ // Register with type factory map.
+ //
+ if (polymorphic && !e.context ().count ("anonymous"))
+ {
+ // Note that we are using the original type name.
+ //
+ String const& name (ename (e));
+
+ if (!options.value<CLI::suppress_parsing> ())
+ os << "static" << endl
+ << "const ::xsd::cxx::tree::type_factory_initializer< 0, " <<
+ char_type << ", " << name << " >" << endl
+ << "_xsd_" << name << "_type_factory_init (" << endl
+ << L << strlit (e.name ()) << "," << endl
+ << L << strlit (xml_ns_name (e)) << ");"
+ << endl;
+
+ if (options.value<CLI::generate_comparison> ())
+ os << "static" << endl
+ << "const ::xsd::cxx::tree::comparison_initializer< 0, " <<
+ char_type << ", " << name << " >" << endl
+ << "_xsd_" << name << "_comparison_init;"
+ << endl;
+ }
+ }
+
+ virtual Void
+ comma (Type&)
+ {
+ os << "," << endl;
+ }
+
+ private:
+ Traversal::Names names_enumerator_literal_;
+ EnumeratorLiteral enumerator_literal_;
+
+ };
+
+ //
+ //
+ struct Member: Traversal::Member, protected virtual Context
+ {
+ Member (Context& c, String const& scope)
+ : Context (c), scope_ (scope)
+ {
+ }
+
+ virtual Void
+ traverse (Type& m)
+ {
+ if (skip (m))
+ return;
+
+ // default_value
+ //
+ if (m.default_ () && !is_qname (m.type ()))
+ {
+ SemanticGraph::Type& t (m.type ());
+ Boolean simple (true);
+
+ if (m.is_a<SemanticGraph::Element> ())
+ {
+ IsSimpleType test (simple);
+ test.dispatch (t);
+ }
+
+ if (simple)
+ {
+ Boolean fund (false);
+ {
+ IsFundamentalType test (fund);
+ test.dispatch (t);
+ }
+
+ String type (etype (m));
+ String q_type (scope_ + L"::" + type);
+
+ if (fund)
+ {
+ String ftype;
+ {
+ std::wostringstream o;
+ MemberTypeName test (*this, o);
+ test.dispatch (t);
+ ftype = o.str ();
+ }
+
+ os << "const " << q_type << " " << scope_ << "::" <<
+ edefault_value_member (m) << " (" << endl
+ << "::xsd::cxx::tree::traits< " << ftype << ", " <<
+ char_type;
+
+ if (t.is_a<SemanticGraph::Fundamental::Double> ())
+ os << ", ::xsd::cxx::tree::schema_type::double_";
+ else if (t.is_a<SemanticGraph::Fundamental::Decimal> ())
+ os << ", ::xsd::cxx::tree::schema_type::decimal";
+
+ os << " >::create (" << endl
+ << string_type << " (" << L << strlit (m.value ()) <<
+ "), 0, 0, 0));"
+ << endl;
+ }
+ else
+ {
+ os << "const " << q_type << " " << scope_ << "::" <<
+ edefault_value_member (m) << " (" << endl
+ << string_type << " (" << L << strlit (m.value ()) <<
+ "), 0, 0, 0);"
+ << endl;
+ }
+ }
+ }
+ }
+
+ private:
+ String scope_;
+ };
+
+
+ struct Element: Traversal::Element, protected virtual Context
+ {
+ Element (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (skip (e))
+ return;
+
+ String const& member (emember (e));
+
+ String tr (etraits (e)); // traits type name
+ String type (etype (e));
+
+ // Check if we need to handle xsi:type and substitution groups.
+ // If this element's type is anonymous or mapped to a fundamental
+ // C++ type then we don't need to do anything. Note that if the
+ // type is anonymous then it can't be derived from which makes it
+ // impossible to substitute or dynamically-type with xsi:type.
+ //
+ SemanticGraph::Type& t (e.type ());
+
+
+ Boolean fund (false);
+ {
+ IsFundamentalType traverser (fund);
+ traverser.dispatch (t);
+ }
+
+ Boolean poly (
+ !fund && polymorphic && !t.context ().count ("anonymous"));
+
+ os << "// " << comment (e.name ()) << endl
+ << "//" << endl;
+
+ if (poly)
+ {
+ // aCC cannot handle an inline call to type_factory_map_instance.
+ //
+ os << "{"
+ << "::xsd::cxx::tree::type_factory_map< " << char_type <<
+ " >& tfm (" << endl
+ << "::xsd::cxx::tree::type_factory_map_instance< 0, " <<
+ char_type << " > ());"
+ << endl
+ << "::std::auto_ptr< ::xsd::cxx::tree::type > tmp (" << endl
+ << "tfm.create (" << endl
+ << L << strlit (e.name ()) << "," << endl
+ << L << (
+ e.qualified ()
+ ? strlit (e.namespace_ ().name ())
+ : String ("\"\"")) <<
+ "," << endl
+ << "&::xsd::cxx::tree::factory_impl< " << type << " >," << endl
+ << (e.global () ? "true" : "false") << ", " <<
+ (e.qualified () ? "true" : "false") << ", " <<
+ "i, n, f, this));"
+ << endl
+ << "if (tmp.get () != 0)"
+ << "{";
+ }
+ else
+ {
+ if (e.qualified () && e.namespace_ ().name ())
+ {
+ os << "if (n.name () == " << L << strlit (e.name ()) << " && " <<
+ "n.namespace_ () == " << L <<
+ strlit (e.namespace_ ().name ()) << ")"
+ << "{";
+ }
+ else
+ {
+ os << "if (n.name () == " << L << strlit (e.name ()) << " && " <<
+ "n.namespace_ ().empty ())"
+ << "{";
+ }
+
+ if (!fund)
+ {
+ os << "::std::auto_ptr< " << type << " > r (" << endl
+ << tr << "::create (i, f, this));"
+ << endl;
+ }
+ }
+
+
+ // Checks. Disabled at the moment since they make it impossible to
+ // parse valid instances where the same element is used in both
+ // base and derived types. See the cxx/tree/name-clash/inheritance
+ // test for details.
+ //
+ //
+ if (max (e) != 1)
+ {
+ // sequence
+ //
+ }
+ else if (min (e) == 0)
+ {
+ // optional
+ //
+ os << "if (!this->" << member << ")"
+ << "{";
+ }
+ else
+ {
+ // one
+ //
+ os << "if (!" << member << ".present ())"
+ << "{";
+ }
+
+
+ if (poly || !fund)
+ {
+ if (poly)
+ {
+ // Cast to static type.
+ //
+ os << "::std::auto_ptr< " << type << " > r (" << endl
+ << "dynamic_cast< " << type << "* > (tmp.get ()));"
+ << endl
+ << "if (r.get ())" << endl
+ << "tmp.release ();"
+ << "else" << endl
+ << "throw ::xsd::cxx::tree::not_derived< " << char_type <<
+ " > ();"
+ << endl;
+ }
+
+ if (max (e) != 1)
+ {
+ // sequence
+ //
+ os << "this->" << member << ".push_back (r);";
+ }
+ else if (min (e) == 0)
+ {
+ // optional
+ //
+ os << "this->" << member << ".set (r);";
+ }
+ else
+ {
+ // one
+ //
+ os << "this->" << member << ".set (r);";
+ }
+ }
+ else
+ {
+ if (max (e) != 1)
+ {
+ // sequence
+ //
+ os << "this->" << member << ".push_back (" << tr <<
+ "::create (i, f, this));";
+ }
+ else if (min (e) == 0)
+ {
+ // optional
+ //
+ os << "this->" << member << ".set (" << tr <<
+ "::create (i, f, this));";
+ }
+ else
+ {
+ // one
+ //
+ os << "this->" << member << ".set (" << tr <<
+ "::create (i, f, this));";
+ }
+ }
+
+ os << "continue;";
+
+ // End of check block.
+ //
+ if (max (e) != 1)
+ {
+ // sequence
+ //
+ }
+ else if (min (e) == 0)
+ {
+ // optional
+ //
+ os << "}";
+ }
+ else
+ {
+ // one
+ //
+ os << "}";
+ }
+
+ os << "}"; // if block
+
+ if (poly)
+ os << "}";
+ }
+ };
+
+ struct ElementTest : Traversal::Element, protected virtual Context
+ {
+ ElementTest (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (skip (e))
+ return;
+
+ if (max (e) == 1 && min (e) == 1)
+ {
+ // one
+ //
+ os << "if (!" << emember (e) << ".present ())"
+ << "{"
+ << "throw ::xsd::cxx::tree::expected_element< " <<
+ char_type << " > (" << endl
+ << L << strlit (e.name ()) << "," << endl
+ << L << (e.qualified ()
+ ? strlit (e.namespace_ ().name ())
+ : String ("\"\"")) << ");"
+ << "}";
+ }
+ }
+ };
+
+ struct Any: Traversal::Any, protected virtual Context
+ {
+ Any (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ String const& member (emember (a));
+
+ String const& ns (a.definition_namespace ().name ());
+ String const& dom_doc (
+ edom_document (
+ dynamic_cast<SemanticGraph::Complex&> (a.scope ())));
+
+ os << "// " << ename (a) << endl
+ << "//" << endl
+ << "if (";
+
+ for (SemanticGraph::Any::NamespaceIterator i (a.namespace_begin ()),
+ e (a.namespace_end ()); i != e;)
+ {
+ if (*i == L"##any")
+ {
+ os << "true";
+ }
+ 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 << "(!n.namespace_ ().empty () && " <<
+ "n.namespace_ () != " << L << strlit (ns) << ")";
+ }
+ else
+ os << "!n.namespace_ ().empty ()";
+ }
+ else if (*i == L"##local")
+ {
+ os << "n.namespace_ ().empty ()";
+ }
+ else if (*i == L"##targetNamespace")
+ {
+ os << "n.namespace_ () == " << L << strlit (ns);
+ }
+ else
+ {
+ os << "n.namespace_ () == " << L << strlit (*i);
+ }
+
+ if (++i != e)
+ os << " ||" << endl;
+ }
+
+ os << ")"
+ << "{";
+
+
+ // Checks.
+ //
+ //
+ if (max (a) != 1)
+ {
+ // sequence
+ //
+ }
+ else if (min (a) == 0)
+ {
+ // optional
+ //
+ os << "if (!this->" << member << ")"
+ << "{";
+ }
+ else
+ {
+ // one
+ //
+ os << "if (!" << member << ".present ())"
+ << "{";
+ }
+
+ os << xerces_ns << "::DOMElement* r (" << endl
+ << "static_cast< " << xerces_ns << "::DOMElement* > (" << endl
+ << "this->" << dom_doc << " ().importNode (" << endl
+ << "const_cast< " << xerces_ns << "::DOMElement* > (&i), true)));";
+
+ if (max (a) != 1)
+ {
+ // sequence
+ //
+ os << "this->" << member << " .push_back (r);";
+ }
+ else if (min (a) == 0)
+ {
+ // optional
+ //
+ os << "this->" << member << ".set (r);";
+ }
+ else
+ {
+ // one
+ //
+ os << "this->" << member << ".set (r);";
+ }
+
+ os << "continue;";
+
+ // End of check block.
+ //
+ if (max (a) != 1)
+ {
+ // sequence
+ //
+ }
+ else if (min (a) == 0)
+ {
+ // optional
+ //
+ os << "}";
+ }
+ else
+ {
+ // one
+ //
+ os << "}";
+ }
+
+ os << "}"; // if block
+ }
+ };
+
+ struct AnyTest : Traversal::Any, protected virtual Context
+ {
+ AnyTest (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ if (max (a) == 1 && min (a) == 1)
+ {
+ // one
+ //
+ os << "if (!" << emember (a) << ".present ())"
+ << "{"
+ << "throw ::xsd::cxx::tree::expected_element< " <<
+ char_type << " > (" << endl
+ << L << "\"*\"," << endl
+ << L << strlit (*a.namespace_begin ()) << ");"
+ << "}";
+ }
+ }
+ };
+
+ struct Attribute : Traversal::Attribute, protected virtual Context
+ {
+ Attribute (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ String const& member (emember (a));
+
+ String const& tr (etraits (a)); // traits type name
+
+ if (a.qualified () && a.namespace_ ().name ())
+ {
+ os << "if (n.name () == " << L << strlit (a.name ()) << " && " <<
+ "n.namespace_ () == " << L <<
+ strlit (a.namespace_ ().name ()) << ")"
+ << "{";
+ }
+ else
+ {
+ os << "if (n.name () == " << L << strlit (a.name ()) << " && " <<
+ "n.namespace_ ().empty ())"
+ << "{";
+ }
+
+ Boolean fund (false);
+ {
+ IsFundamentalType traverser (fund);
+ traverser.dispatch (a.type ());
+ }
+
+ if (fund)
+ {
+ os << "this->" << member << ".set (" << tr <<
+ "::create (i, f, this));";
+ }
+ else
+ {
+ String type (etype (a));
+
+ os << "::std::auto_ptr< " << type << " > r (" << endl
+ << tr << "::create (i, f, this));"
+ << endl
+ << "this->" << member << ".set (r);";
+ }
+
+ os << "continue;"
+ << "}";
+
+ }
+ };
+
+ struct AnyAttribute: Traversal::AnyAttribute, protected virtual Context
+ {
+ AnyAttribute (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ String const& member (emember (a));
+
+ String const& ns (a.definition_namespace ().name ());
+ String const& dom_doc (
+ edom_document (
+ dynamic_cast<SemanticGraph::Complex&> (a.scope ())));
+
+ os << "// " << ename (a) << endl
+ << "//" << endl
+ << "if (";
+
+ // Note that we need to filter out namespaces for xmlns and
+ // xsi.
+ //
+ for (SemanticGraph::Any::NamespaceIterator i (a.namespace_begin ()),
+ e (a.namespace_end ()); i != e;)
+ {
+ if (*i == L"##any")
+ {
+ os << "(n.namespace_ () != " <<
+ "::xsd::cxx::xml::bits::xmlns_namespace< " << char_type <<
+ " > () &&" << endl
+ << "n.namespace_ () != " <<
+ "::xsd::cxx::xml::bits::xsi_namespace< " << char_type <<
+ " > ())";
+ }
+ 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 << "(!n.namespace_ ().empty () &&" << endl
+ << "n.namespace_ () != " << L << strlit (ns) << " &&" <<endl
+ << "n.namespace_ () != " <<
+ "::xsd::cxx::xml::bits::xmlns_namespace< " << char_type <<
+ " > () &&" << endl
+ << "n.namespace_ () != " <<
+ "::xsd::cxx::xml::bits::xsi_namespace< " << char_type <<
+ " > ())";
+ }
+ else
+ os << "(!n.namespace_ ().empty () &&" << endl
+ << "n.namespace_ () != " <<
+ "::xsd::cxx::xml::bits::xmlns_namespace< " << char_type <<
+ " > () &&" << endl
+ << "n.namespace_ () != " <<
+ "::xsd::cxx::xml::bits::xsi_namespace< " << char_type <<
+ " > ())";
+ }
+ else if (*i == L"##local")
+ {
+ os << "n.namespace_ ().empty ()";
+ }
+ else if (*i == L"##targetNamespace")
+ {
+ os << "n.namespace_ () == " << L << strlit (ns);
+ }
+ else
+ {
+ os << "n.namespace_ () == " << L << strlit (*i);
+ }
+
+ if (++i != e)
+ os << " ||" << endl;
+ }
+
+ os << ")"
+ << "{"
+ << xerces_ns << "::DOMAttr* r (" << endl
+ << "static_cast< " << xerces_ns << "::DOMAttr* > (" << endl
+ << "this->" << dom_doc << " ().importNode (" << endl
+ << "const_cast< " << xerces_ns << "::DOMAttr* > (&i), true)));"
+ << "this->" << member << " .insert (r);"
+ << "continue;"
+ << "}";
+ }
+ };
+
+
+ struct AttributeTest : Traversal::Attribute, protected virtual Context
+ {
+ AttributeTest (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& a)
+ {
+ String const& member (emember (a));
+
+ if (!a.optional () || a.default_ ())
+ {
+ os << "if (!" << member << ".present ())"
+ << "{";
+
+ if (a.default_ ())
+ {
+ Boolean fund (false);
+ {
+ IsFundamentalType traverser (fund);
+ traverser.dispatch (a.type ());
+ }
+
+ String const& tr (etraits (a)); // traits type name
+
+ if (fund || !is_qname (a.type ()))
+ {
+ os << "this->" << member << ".set (" <<
+ edefault_value (a) << " ());";
+ }
+ else
+ {
+ // Parse the default value in the context of the element.
+ //
+ os << "::std::auto_ptr< " << etype (a) << " > r (" << endl
+ << tr << "::create (" << endl
+ << string_type << " (" << L << strlit (a.value ()) <<
+ ")," << endl
+ << "&p.element (), f, this));"
+ << endl
+ << "this->" << member << ".set (r);";
+ }
+ }
+ else
+ os << "throw ::xsd::cxx::tree::expected_attribute< " <<
+ char_type << " > (" << endl
+ << L << strlit (a.name ()) << "," << endl
+ << L <<(a.qualified ()
+ ? strlit (a.namespace_ ().name ())
+ : String ("\"\"")) << ");";
+
+ os << "}";
+ }
+ }
+ };
+
+
+ //
+ //
+ struct CtorBase : Traversal::Complex,
+ Traversal::Enumeration,
+ Traversal::Type,
+ protected virtual Context
+ {
+ // If base_arg is empty then no base argument is
+ // generated.
+ //
+ CtorBase (Context& c, String const& base_arg)
+ : Context (c), base_arg_ (base_arg)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type&)
+ {
+ if (base_arg_)
+ os << base_arg_;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Enumeration&)
+ {
+ if (base_arg_)
+ os << base_arg_;
+ }
+
+ Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ Args args (*this, base_arg_);
+ args.traverse (c);
+ }
+
+ private:
+ // No need to traverse AnyAttribute since it is always mapped
+ // to a sequence.
+ //
+ struct Args : Traversal::Complex,
+ Traversal::Enumeration,
+ Traversal::Type,
+ Traversal::Any,
+ Traversal::Element,
+ Traversal::Attribute,
+ protected virtual Context
+ {
+ Args (Context& c, String const& base_arg)
+ : Context (c), base_arg_ (base_arg), first_ (true)
+ {
+ *this >> inherits_ >> *this;
+ *this >> names_ >> *this;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type&)
+ {
+ if (base_arg_)
+ os << comma () << base_arg_;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Enumeration&)
+ {
+ if (base_arg_)
+ os << comma () << base_arg_;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ if (!options.value<CLI::generate_wildcard> ())
+ return;
+
+ if (min (a) == 1 && max (a) == 1)
+ {
+ // one
+ //
+ os << comma () << ename (a);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (!skip (e) && min (e) == 1 && max (e) == 1)
+ {
+ // one
+ //
+ os << comma () << ename (e);
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ // Note that we are not including attributes with default
+ // or required fixed values here.
+ //
+ if (min (a) == 1 && !(a.fixed () && !is_qname (a.type ())))
+ {
+ // one
+ //
+ os << comma () << ename (a);
+ }
+ }
+
+ using Complex::traverse;
+
+ private:
+ String
+ comma ()
+ {
+ Boolean tmp (first_);
+ first_ = false;
+ return tmp ? "" : ",\n";
+ }
+
+ private:
+ String base_arg_;
+ Boolean first_;
+
+ Traversal::Inherits inherits_;
+ Traversal::Names names_;
+ };
+
+ String base_arg_;
+ };
+
+
+ struct CtorMember : Traversal::Element,
+ Traversal::Attribute,
+ protected virtual Context
+ {
+ CtorMember (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (skip (e))
+ return;
+
+ String const& member (emember (e));
+
+ if (max (e) != 1)
+ {
+ // sequence
+ //
+ os << "," << endl
+ << " " << member << " (" << flags_type << " (), this)";
+ }
+ else if (min (e) == 0)
+ {
+ // optional
+ //
+ os << "," << endl
+ << " " << member << " (" << flags_type << " (), this)";
+ }
+ else
+ {
+ // one
+ //
+ os << "," << endl
+ << " " << member << " (" << ename (e) << ", " <<
+ flags_type << " (), this)";
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ String const& member (emember (a));
+
+ Boolean def (a.default_ () && !is_qname (a.type ()));
+
+ if (min (a) == 0 && !def)
+ {
+ // optional
+ //
+ os << "," << endl
+ << " " << member << " (" << flags_type << " (), this)";
+ }
+ else
+ {
+ // one
+ //
+
+ if (def)
+ {
+ // This is an attribute with default or fixed value. We are
+ // going to initialize it to its default value.
+ //
+ os << "," << endl
+ << " " << member << " (" <<
+ edefault_value (a) << " (), " << flags_type << " (), this)";
+ }
+ else
+ {
+ os << "," << endl
+ << " " << member << " (" << ename (a) << ", " <<
+ flags_type << " (), this)";
+ }
+ }
+ }
+ };
+
+ struct CtorAny : Traversal::Any,
+ Traversal::AnyAttribute,
+ protected virtual Context
+ {
+ CtorAny (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ String const& member (emember (a));
+ String const& dom_doc (
+ edom_document (
+ dynamic_cast<SemanticGraph::Complex&> (a.scope ())));
+
+ if (max (a) != 1)
+ {
+ // sequence
+ //
+ os << "," << endl
+ << " " << member << " (this->" << dom_doc << " ())";
+ }
+ else if (min (a) == 0)
+ {
+ // optional
+ //
+ os << "," << endl
+ << " " << member << " (this->" << dom_doc << " ())";
+ }
+ else
+ {
+ // one
+ //
+ os << "," << endl
+ << " " << member << " (" << ename (a) << ", this->" <<
+ dom_doc << " ())";
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute& a)
+ {
+ String const& dom_doc (
+ edom_document (
+ dynamic_cast<SemanticGraph::Complex&> (a.scope ())));
+
+ os << "," << endl
+ << " " << emember (a) << " (this->" << dom_doc << " ())";
+ }
+ };
+
+
+ struct CopyMember : Traversal::Member,
+ protected virtual Context
+
+ {
+ CopyMember (Context& c, String const& arg_name_)
+ : Context (c), arg_name (arg_name_)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Member& m)
+ {
+ if (skip (m))
+ return;
+
+ String const& member (emember (m));
+
+ os << "," << endl
+ << " " << member << " (" <<
+ arg_name << "." << member << ", f, this)";
+ }
+
+ private:
+ String arg_name;
+ };
+
+ struct CopyAny : Traversal::Any,
+ Traversal::AnyAttribute,
+ protected virtual Context
+
+ {
+ CopyAny (Context& c, String const& arg_name_)
+ : Context (c), arg_name (arg_name_)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ String const& member (emember (a));
+ String const& dom_doc (
+ edom_document (
+ dynamic_cast<SemanticGraph::Complex&> (a.scope ())));
+
+ os << "," << endl
+ << " " << member << " (" <<
+ arg_name << "." << member << ", this->" << dom_doc << " ())";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute& a)
+ {
+ String const& member (emember (a));
+ String const& dom_doc (
+ edom_document (
+ dynamic_cast<SemanticGraph::Complex&> (a.scope ())));
+
+ os << "," << endl
+ << " " << member << " (" <<
+ arg_name << "." << member << ", this->" << dom_doc << " ())";
+ }
+
+ private:
+ String arg_name;
+ };
+
+
+ // Element parsing c-tor initializers.
+ //
+ struct ElementCtorMember : Traversal::Member,
+ protected virtual Context
+ {
+ ElementCtorMember (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& m)
+ {
+ if (skip (m))
+ return;
+
+ String const& member (emember (m));
+
+ os << "," << endl
+ << " " << member << " (f, this)";
+ }
+ };
+
+ struct ElementCtorAny : Traversal::Any,
+ Traversal::AnyAttribute,
+ protected virtual Context
+ {
+ ElementCtorAny (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ String const& member (emember (a));
+ String const& dom_doc (
+ edom_document (
+ dynamic_cast<SemanticGraph::Complex&> (a.scope ())));
+
+ os << "," << endl
+ << " " << member << " (this->" << dom_doc << " ())";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute& a)
+ {
+ String const& member (emember (a));
+ String const& dom_doc (
+ edom_document (
+ dynamic_cast<SemanticGraph::Complex&> (a.scope ())));
+
+ os << "," << endl
+ << " " << member << " (this->" << dom_doc << " ())";
+ }
+ };
+
+
+ // Default c-tor member initializer.
+ //
+ struct DefaultCtorMemberInit : Traversal::Element,
+ Traversal::Attribute,
+ protected virtual Context
+ {
+ DefaultCtorMemberInit (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (skip (e))
+ return;
+
+ String const& member (emember (e));
+
+ os << "," << endl
+ << " " << member << " (" << flags_type << " (), this)";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ String const& member (emember (a));
+
+ if (a.default_ () && !is_qname (a.type ()))
+ {
+ // This is an attribute with default or fixed value. We are
+ // going to initialize it to its default value.
+ //
+ os << "," << endl
+ << " " << member << " (" <<
+ edefault_value (a) << " (), " << flags_type << " (), this)";
+ }
+ else
+ os << "," << endl
+ << " " << member << " (" << flags_type << " (), this)";
+ }
+ };
+
+ struct DefaultCtorAnyInit : Traversal::Any,
+ Traversal::AnyAttribute,
+ protected virtual Context
+ {
+ DefaultCtorAnyInit (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ String const& member (emember (a));
+ String const& dom_doc (
+ edom_document (
+ dynamic_cast<SemanticGraph::Complex&> (a.scope ())));
+
+ os << "," << endl
+ << " " << member << " (this->" << dom_doc << " ())";
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute& a)
+ {
+ String const& member (emember (a));
+ String const& dom_doc (
+ edom_document (
+ dynamic_cast<SemanticGraph::Complex&> (a.scope ())));
+
+ os << "," << endl
+ << " " << member << " (this->" << dom_doc << " ())";
+ }
+ };
+
+ // Test whether the base has comparison operators.
+ //
+ struct HasComparisonOperator: Traversal::Fundamental::Type,
+ Traversal::List,
+ Traversal::Union,
+ Traversal::Complex,
+ Traversal::Enumeration,
+ Traversal::Member,
+ Traversal::Any,
+ Traversal::AnyAttribute,
+ protected virtual Context
+ {
+ // generate should initially be false.
+ //
+ HasComparisonOperator (Context& c, Boolean& generate)
+ : Context (c), generate_ (generate)
+ {
+ *this >> inherits_ >> *this;
+ *this >> names_ >> *this;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Fundamental::Type&)
+ {
+ // All built-in types are comparable.
+ generate_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::List&)
+ {
+ generate_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Union&)
+ {
+ generate_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Enumeration& e)
+ {
+ Traversal::Enumeration::inherits (e);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ Complex::names (c);
+
+ if (!generate_)
+ Complex::inherits (c);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Member& m)
+ {
+ if (!skip (m))
+ generate_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any&)
+ {
+ if (options.value<CLI::generate_wildcard> ())
+ generate_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute&)
+ {
+ if (options.value<CLI::generate_wildcard> ())
+ generate_ = true;
+ }
+
+ private:
+ Boolean& generate_;
+
+ Traversal::Inherits inherits_;
+ Traversal::Names names_;
+ };
+
+ //
+ //
+ struct MemberComparison : Traversal::Element,
+ Traversal::Attribute,
+ protected virtual Context
+ {
+ MemberComparison (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (skip (e))
+ return;
+
+ String const& aname (eaname (e));
+
+ // Check if we need to handle xsi:type and substitution groups.
+ // If this element's type is anonymous or mapped to a fundamental
+ // C++ type then we don't need to do anything. Note that if the
+ // type is anonymous then it can't be derived from which makes it
+ // impossible to substitute or dynamically-type with xsi:type.
+ //
+ SemanticGraph::Type& t (e.type ());
+ Boolean poly (polymorphic && !t.context ().count ("anonymous"));
+
+ if (poly)
+ {
+ Boolean fund (false);
+ IsFundamentalType traverser (fund);
+ traverser.dispatch (t);
+ poly = !fund;
+ }
+
+ if (!poly)
+ {
+ os << "if (!(x." << aname << " () == y." << aname << " ()))" << endl
+ << "return false;"
+ << endl;
+ }
+ else
+ {
+ // aCC cannot handle an inline call to comparison_map_instance.
+ //
+ os << "{"
+ << "::xsd::cxx::tree::comparison_map< " << char_type
+ << " >& cm (" << endl
+ << "::xsd::cxx::tree::comparison_map_instance< 0, " <<
+ char_type << " > ());"
+ << endl;
+
+ if (max (e) != 1)
+ {
+ // sequence
+ //
+ String const& scope (ename (e.scope ()));
+
+ os << scope << "::" << econtainer (e) <<
+ " a (x." << aname << " ()), b (y." << aname << " ());"
+ << endl;
+
+ os << "if (a.size () != b.size ())" << endl
+ << "return false;"
+ << endl;
+
+ os << "for (" << scope << "::" << econst_iterator (e) << endl
+ << "ai (a.begin ()), bi (b.begin ()), " <<
+ "ae (a.end ()), be (b.end ());" << endl
+ << "ai != ae; ++ai, ++bi)"
+ << "{"
+ << "if (!cm.compare (*ai, *bi))" << endl
+ << "return false;"
+ << "}";
+ }
+ else if (min (e) == 0)
+ {
+ // optional
+ //
+ String const& scope (ename (e.scope ()));
+
+ os << scope << "::" << econtainer (e) <<
+ " a (x." << aname << " ()), b (y." << aname << " ());"
+ << endl;
+
+ os << "if (!a || !b)"
+ << "{"
+ << "if (a.present () != b.present ())" << endl
+ << "return false;"
+ << "}"
+ << "else"
+ << "{"
+ << "if (!cm.compare (*a, *b))" << endl
+ << "return false;"
+ << "}";
+ }
+ else
+ {
+ // one
+ //
+ os << "if (!cm.compare (x." << aname << " (), y." <<
+ aname << " ()))" << endl
+ << "return false;";
+ }
+
+ os << "}";
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& a)
+ {
+ String const& aname (eaname (a));
+
+ os << "if (!(x." << aname << " () == y." << aname << " ()))" << endl
+ << "return false;"
+ << endl;
+ }
+ };
+
+ struct AnyComparison : Traversal::Any,
+ Traversal::AnyAttribute,
+ protected virtual Context
+ {
+ AnyComparison (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any& a)
+ {
+ String const& aname (eaname (a));
+
+ if (max (a) == 1 && min (a) == 1)
+ os << "if (!x." << aname << " ().isEqualNode (&y." <<
+ aname << " ()))";
+ else
+ os << "if (!(x." << aname << " () == y." << aname << " ()))";
+
+ os << endl
+ << "return false;"
+ << endl;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute& a)
+ {
+ String const& aname (eaname (a));
+
+ os << "if (!(x." << aname << " () == y." << aname << " ()))" << endl
+ << "return false;"
+ << endl;
+ }
+ };
+
+ // Check whether a type has a parse() function (i.e., has any
+ // members, recursively).
+ //
+ struct HasParseFunction: Traversal::Complex,
+ Traversal::Element,
+ Traversal::Any,
+ Traversal::Attribute,
+ Traversal::AnyAttribute,
+ protected virtual Context
+ {
+ HasParseFunction (Context& c, Boolean& has_el, Boolean& has_at)
+ : Context (c), has_el_ (has_el), has_at_ (has_at)
+ {
+ *this >> names_ >> *this;
+ *this >> inherits_ >> *this;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Complex& c)
+ {
+ names (c);
+
+ if (!(has_el_ && has_at_))
+ inherits (c);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element&)
+ {
+ has_el_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Any&)
+ {
+ has_el_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute&)
+ {
+ has_at_ = true;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::AnyAttribute&)
+ {
+ if (options.value<CLI::generate_wildcard> ())
+ has_at_ = true;
+ }
+
+ private:
+ Boolean& has_el_;
+ Boolean& has_at_;
+
+ Traversal::Names names_;
+ Traversal::Inherits inherits_;
+ };
+
+ //
+ //
+ struct FacetArray: Traversal::Complex, protected virtual Context
+ {
+ FacetArray (Context& c)
+ : Context (c)
+ {
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ Facets f;
+ FacetCollector col (f);
+ col.traverse (c);
+
+ for (Facets::ConstIterator i (f.begin ()); i != f.end (); ++i)
+ {
+ if (i->first == L"fractionDigits")
+ os << "{::xsd::cxx::tree::facet::fraction_digits, " <<
+ i->second << "UL}," << endl;
+ else if (i->first == L"totalDigits")
+ os << "{::xsd::cxx::tree::facet::total_digits, " <<
+ i->second << "UL}," << endl;
+ }
+ }
+
+ private:
+ typedef Cult::Containers::Map<String, String> Facets;
+
+ struct FacetCollector: Traversal::Complex
+ {
+ FacetCollector (Facets& facets)
+ : facets_ (facets)
+ {
+ *this >> inherits_ >> *this;
+ }
+
+ virtual Void
+ traverse (Type& c)
+ {
+ if (c.inherits_p ())
+ {
+ // First collect our base so that we can override its
+ // facets.
+ //
+ inherits (c);
+
+ using SemanticGraph::Restricts;
+
+ if (Restricts* r = dynamic_cast<Restricts*> (&c.inherits ()))
+ {
+ if (!r->facet_empty ())
+ {
+ Restricts::FacetIterator i (r->facet_find ("totalDigits"));
+
+ if (i != r->facet_end ())
+ facets_[i->first] = i->second;
+
+ i = r->facet_find ("fractionDigits");
+
+ if (i != r->facet_end ())
+ facets_[i->first] = i->second;
+ }
+ }
+ }
+ }
+
+ private:
+ Traversal::Inherits inherits_;
+ Facets& facets_;
+ };
+ };
+
+ //
+ //
+ struct Complex: Traversal::Complex, protected virtual Context
+ {
+ Complex (Context& c)
+ : Context (c),
+ member_name_ (c),
+ any_ (c),
+ element_ (c),
+ any_test_ (c),
+ element_test_ (c),
+ attribute_ (c),
+ attribute_test_ (c),
+ any_attribute_ (c),
+ default_ctor_any_init_ (c),
+ default_ctor_member_init_ (c),
+ ctor_any_ (c),
+ ctor_member_ (c),
+ element_ctor_any_ (c),
+ element_ctor_member_ (c),
+ comparison_any_ (c),
+ comparison_member_ (c),
+ facet_array_ (c)
+ {
+ inherits_member_ >> member_name_;
+
+ names_element_ >> element_;
+ if (options.value<CLI::generate_wildcard> ())
+ names_element_ >> any_;
+
+ names_element_test_ >> element_test_;
+ if (options.value<CLI::generate_wildcard> ())
+ names_element_test_ >> any_test_;
+
+ names_attribute_ >> attribute_;
+ names_attribute_test_ >> attribute_test_;
+ names_any_attribute_ >> any_attribute_;
+
+ default_ctor_init_names_ >> default_ctor_member_init_;
+ if (options.value<CLI::generate_wildcard> ())
+ default_ctor_init_names_ >> default_ctor_any_init_;
+
+ ctor_names_ >> ctor_member_;
+ if (options.value<CLI::generate_wildcard> ())
+ ctor_names_ >> ctor_any_;
+
+ element_ctor_names_ >> element_ctor_member_;
+ if (options.value<CLI::generate_wildcard> ())
+ element_ctor_names_ >> element_ctor_any_;
+
+ comparison_names_ >> comparison_member_;
+ if (options.value<CLI::generate_wildcard> ())
+ comparison_names_ >> comparison_any_;
+ }
+
+
+ virtual Void
+ traverse (Type& c)
+ {
+ String name (ename (c));
+
+ // If renamed name is empty then we do not need to generate
+ // anything for this type.
+ //
+ if (renamed_type (c, name) && !name)
+ return;
+
+ Boolean string_based (false);
+ {
+ IsStringBasedType t (string_based);
+ t.dispatch (c);
+ }
+
+ SemanticGraph::Enumeration* enum_base (0);
+ {
+ IsEnumBasedType t (enum_base);
+ t.dispatch (c);
+ }
+
+ Boolean facets (false);
+ String base; // base type name
+ if (c.inherits_p ())
+ {
+ // Get base name.
+ //
+ std::wostringstream o;
+
+ BaseTypeName base_type (*this, o);
+ Traversal::Inherits inherits_type (base_type);
+
+ // Cannot use inherits_none here because need the
+ // result in a string.
+ //
+ inherits (c, inherits_type);
+
+ base = o.str ();
+
+ // See if we have any facets that we need to handle.
+ //
+ using SemanticGraph::Restricts;
+ using SemanticGraph::Fundamental::Decimal;
+
+ if (Restricts* r = dynamic_cast<Restricts*> (&c.inherits ()))
+ {
+ if (!r->facet_empty () &&
+ (r->facet_find ("fractionDigits") != r->facet_end () ||
+ r->facet_find ("totalDigits") != r->facet_end ()) &&
+ ultimate_base (c).is_a<Decimal> ())
+ facets = true;
+ }
+ }
+ else
+ base = any_type;
+
+ os << "// " << name << endl
+ << "//" << endl
+ << endl;
+
+ //
+ //
+ {
+ Member member (*this, name);
+ Traversal::Names names_member (member);
+ names (c, names_member);
+ }
+
+ // facets
+ //
+ if (facets)
+ {
+ os << "static const ::xsd::cxx::tree::facet _xsd_" << name <<
+ "_facet_table[] = "
+ << "{";
+
+ facet_array_.traverse (c);
+
+ os << "{::xsd::cxx::tree::facet::none, 0UL}"
+ << "};";
+ }
+
+ // c-tors
+ //
+ Boolean generate_no_base_ctor (false);
+ {
+ GenerateWithoutBaseCtor t (generate_no_base_ctor);
+ t.traverse (c);
+ }
+
+ Boolean has_complex_non_op_args (false);
+ Boolean has_non_fund_non_op_args (false);
+ Boolean complex_non_fund_args_clash (true);
+ {
+ HasComplexNonFundNonOptArgs t (*this, true,
+ has_complex_non_op_args,
+ has_non_fund_non_op_args,
+ complex_non_fund_args_clash);
+ t.traverse (c);
+ }
+
+ // default c-tor
+ //
+ if (options.value<CLI::generate_default_ctor> ())
+ {
+ Boolean generate (false);
+ {
+ GenerateDefaultCtor t (*this, generate, generate_no_base_ctor);
+ t.traverse (c);
+ }
+
+ if (generate)
+ {
+ os << name << "::" << endl
+ << name << " ()" << endl
+ << ": " << base << " ()";
+
+ if (edom_document_member_p (c))
+ {
+ os << "," << endl
+ << " " << edom_document_member (c) << " (" <<
+ "::xsd::cxx::xml::dom::create_document< " << char_type <<
+ " > ())";
+ }
+
+ names (c, default_ctor_init_names_);
+
+ os << "{";
+ if (facets)
+ os << "this->_facet_table (_xsd_" << name << "_facet_table);";
+ os << "}";
+ }
+ }
+
+ // c-tor (base, all-non-optional-members)
+ //
+ if (options.value<CLI::generate_from_base_ctor> ())
+ {
+ Boolean generate (false);
+ {
+ GenerateFromBaseCtor t (*this, generate);
+ t.traverse (c);
+ }
+
+ if (generate)
+ {
+ Boolean has_complex_non_op_args (false);
+ Boolean has_non_fund_non_op_args (false);
+ Boolean complex_non_fund_args_clash (true);
+ {
+ HasComplexNonFundNonOptArgs t (*this, false,
+ has_complex_non_op_args,
+ has_non_fund_non_op_args,
+ complex_non_fund_args_clash);
+ t.traverse (c);
+ }
+
+ String base_arg (
+ L"_xsd_" + ename (c.inherits ().base ()) + L"_base");
+
+ os << name << "::" << endl
+ << name << " (const ";
+ inherits (c, inherits_member_);
+ os << "& " << base_arg;
+ {
+ FromBaseCtorArg args (*this, FromBaseCtorArg::arg_type, true);
+ Traversal::Names args_names (args);
+ names (c, args_names);
+ }
+ os << ")" << endl
+ << ": " << base << " (" << base_arg << ")";
+
+ if (edom_document_member_p (c))
+ {
+ os << "," << endl
+ << " " << edom_document_member (c) << " (" <<
+ "::xsd::cxx::xml::dom::create_document< " << char_type <<
+ " > ())";
+ }
+
+ names (c, ctor_names_);
+
+ os << "{";
+ if (facets)
+ os << "this->_facet_table (_xsd_" << name << "_facet_table);";
+ os << "}";
+
+ // If we have any complex arguments in the previous c-tor
+ // then also generate the auto_ptr version.
+ //
+ if (has_complex_non_op_args)
+ {
+ os << name << "::" << endl
+ << name << " (const ";
+ inherits (c, inherits_member_);
+ os << "& " << base_arg;
+ {
+ FromBaseCtorArg args (
+ *this, FromBaseCtorArg::arg_complex_auto_ptr, true);
+ Traversal::Names args_names (args);
+ names (c, args_names);
+ }
+ os << ")" << endl
+ << ": " << base << " (" << base_arg << ")";
+
+ if (edom_document_member_p (c))
+ {
+ os << "," << endl
+ << " " << edom_document_member (c) << " (" <<
+ "::xsd::cxx::xml::dom::create_document< " << char_type <<
+ " > ())";
+ }
+
+ names (c, ctor_names_);
+
+ os << "{";
+ if (facets)
+ os << "this->_facet_table (_xsd_" << name << "_facet_table);";
+ os << "}";
+ }
+
+ // If we are generating polymorphic code then we also need to
+ // provide auto_ptr version for every non-fundamental type.
+ //
+ if (has_non_fund_non_op_args &&
+ !complex_non_fund_args_clash &&
+ polymorphic)
+ {
+ os << name << "::" << endl
+ << name << " (const ";
+ inherits (c, inherits_member_);
+ os << "& " << base_arg;
+ {
+ FromBaseCtorArg args (
+ *this, FromBaseCtorArg::arg_non_fund_auto_ptr, true);
+ Traversal::Names args_names (args);
+ names (c, args_names);
+ }
+ os << ")" << endl
+ << ": " << base << " (" << base_arg << ")";
+
+ if (edom_document_member_p (c))
+ {
+ os << "," << endl
+ << " " << edom_document_member (c) << " (" <<
+ "::xsd::cxx::xml::dom::create_document< " << char_type <<
+ " > ())";
+ }
+
+ names (c, ctor_names_);
+
+ os << "{";
+ if (facets)
+ os << "this->_facet_table (_xsd_" << name << "_facet_table);";
+ os << "}";
+ }
+ }
+ }
+
+ // c-tor (all-non-optional-members)
+ //
+ if (generate_no_base_ctor)
+ {
+ os << name << "::" << endl
+ << name << " (";
+ {
+ CtorArgsWithoutBase ctor_args (
+ *this, CtorArgsWithoutBase::arg_type, true, true);
+ ctor_args.dispatch (c);
+ }
+ os << ")" << endl
+ << ": " << base << " (";
+ {
+ CtorBase base (*this, "");
+ Traversal::Inherits inherits_base (base);
+
+ inherits (c, inherits_base);
+ }
+ os << ")";
+
+ if (edom_document_member_p (c))
+ {
+ os << "," << endl
+ << " " << edom_document_member (c) << " (" <<
+ "::xsd::cxx::xml::dom::create_document< " << char_type <<
+ " > ())";
+ }
+
+ names (c, ctor_names_);
+
+ os << "{";
+ if (facets)
+ os << "this->_facet_table (_xsd_" << name << "_facet_table);";
+ os << "}";
+
+ // If we have any complex arguments in the previous c-tor
+ // then also generate the auto_ptr version. One case where
+ // this c-tor will be generated is restriction of anyType.
+ //
+ if (has_complex_non_op_args)
+ {
+ os << name << "::" << endl
+ << name << " (";
+ {
+ CtorArgsWithoutBase ctor_args (
+ *this, CtorArgsWithoutBase::arg_complex_auto_ptr, true, true);
+ ctor_args.dispatch (c);
+ }
+ os << ")" << endl
+ << ": " << base << " (";
+ {
+ CtorBase base (*this, "");
+ Traversal::Inherits inherits_base (base);
+
+ inherits (c, inherits_base);
+ }
+ os << ")";
+
+ if (edom_document_member_p (c))
+ {
+ os << "," << endl
+ << " " << edom_document_member (c) << " (" <<
+ "::xsd::cxx::xml::dom::create_document< " << char_type <<
+ " > ())";
+ }
+
+ names (c, ctor_names_);
+
+ os << "{";
+ if (facets)
+ os << "this->_facet_table (_xsd_" << name << "_facet_table);";
+ os << "}";
+ }
+
+ // If we are generating polymorphic code then we also need to
+ // provide auto_ptr version for every non-fundamental type.
+ //
+ if (has_non_fund_non_op_args &&
+ !complex_non_fund_args_clash &&
+ polymorphic)
+ {
+ os << name << "::" << endl
+ << name << " (";
+ {
+ CtorArgsWithoutBase ctor_args (
+ *this, CtorArgsWithoutBase::arg_non_fund_auto_ptr, true, true);
+ ctor_args.dispatch (c);
+ }
+ os << ")" << endl
+ << ": " << base << " (";
+ {
+ CtorBase base (*this, "");
+ Traversal::Inherits inherits_base (base);
+
+ inherits (c, inherits_base);
+ }
+ os << ")";
+
+ if (edom_document_member_p (c))
+ {
+ os << "," << endl
+ << " " << edom_document_member (c) << " (" <<
+ "::xsd::cxx::xml::dom::create_document< " << char_type <<
+ " > ())";
+ }
+
+ names (c, ctor_names_);
+
+ os << "{";
+ if (facets)
+ os << "this->_facet_table (_xsd_" << name << "_facet_table);";
+ os << "}";
+ }
+ }
+
+ if (string_based)
+ {
+ if (enum_base != 0)
+ {
+ // c-tor (enum-value, all-non-optional-members)
+ //
+ String base_arg (L"_xsd_" + ename (*enum_base) + L"_base");
+
+ os << name << "::" << endl
+ << name << " (" << fq_name (*enum_base) << "::" <<
+ evalue (*enum_base) << " " << base_arg;
+
+ {
+ CtorArgsWithoutBase ctor_args (
+ *this, CtorArgsWithoutBase::arg_type, true, false);
+ ctor_args.dispatch (c);
+ }
+
+ os << ")" << endl
+ << ": " << base << " (";
+
+ {
+ CtorBase base (*this, base_arg);
+ Traversal::Inherits inherits_base (base);
+
+ inherits (c, inherits_base);
+ }
+
+ os << ")";
+
+ if (edom_document_member_p (c))
+ {
+ os << "," << endl
+ << " " << edom_document_member (c) << " (" <<
+ "::xsd::cxx::xml::dom::create_document< " << char_type <<
+ " > ())";
+ }
+
+ names (c, ctor_names_);
+
+ os << "{";
+ if (facets)
+ os << "this->_facet_table (_xsd_" << name << "_facet_table);";
+ os << "}";
+ }
+
+ String base_arg (L"_xsd_" + ename (ultimate_base (c)) + L"_base");
+
+ // c-tor (const char*, all-non-optional-members)
+ //
+ os << name << "::" << endl
+ << name << " (const " << char_type << "* " << base_arg;
+
+ {
+ CtorArgsWithoutBase ctor_args (
+ *this, CtorArgsWithoutBase::arg_type, true, false);
+ ctor_args.dispatch (c);
+ }
+
+ os << ")" << endl
+ << ": " << base << " (";
+
+ {
+ CtorBase base (*this, base_arg);
+ Traversal::Inherits inherits_base (base);
+
+ inherits (c, inherits_base);
+ }
+
+ os << ")";
+
+ if (edom_document_member_p (c))
+ {
+ os << "," << endl
+ << " " << edom_document_member (c) << " (" <<
+ "::xsd::cxx::xml::dom::create_document< " << char_type <<
+ " > ())";
+ }
+
+ names (c, ctor_names_);
+
+ os << "{";
+ if (facets)
+ os << "this->_facet_table (_xsd_" << name << "_facet_table);";
+ os << "}";
+
+
+ // c-tor (const std::string&, all-non-optional-members)
+ //
+ os << name << "::" << endl
+ << name << " (const " << string_type << "& " << base_arg;
+
+ {
+ CtorArgsWithoutBase ctor_args (
+ *this, CtorArgsWithoutBase::arg_type, true, false);
+ ctor_args.dispatch (c);
+ }
+
+ os << ")" << endl
+ << ": " << base << " (";
+
+ {
+ CtorBase base (*this, base_arg);
+ Traversal::Inherits inherits_base (base);
+
+ inherits (c, inherits_base);
+ }
+
+ os << ")";
+
+ if (edom_document_member_p (c))
+ {
+ os << "," << endl
+ << " " << edom_document_member (c) << " (" <<
+ "::xsd::cxx::xml::dom::create_document< " << char_type <<
+ " > ())";
+ }
+
+ names (c, ctor_names_);
+
+ os << "{";
+ if (facets)
+ os << "this->_facet_table (_xsd_" << name << "_facet_table);";
+ os << "}";
+ }
+
+ // c-tor (ultimate-base, all-non-optional-members)
+ //
+
+ os << name << "::" << endl
+ << name << " (";
+
+ String base_arg;
+
+ {
+ CtorArgs ctor_args (*this, CtorArgs::arg_type, base_arg);
+ ctor_args.dispatch (c);
+ }
+
+ os << ")" << endl
+ << ": " << base << " (";
+
+ {
+ CtorBase base (*this, base_arg);
+ Traversal::Inherits inherits_base (base);
+
+ inherits (c, inherits_base);
+ }
+
+ os << ")";
+
+ if (edom_document_member_p (c))
+ {
+ os << "," << endl
+ << " " << edom_document_member (c) << " (" <<
+ "::xsd::cxx::xml::dom::create_document< " << char_type <<
+ " > ())";
+ }
+
+ names (c, ctor_names_);
+
+ os << "{";
+ if (facets)
+ os << "this->_facet_table (_xsd_" << name << "_facet_table);";
+ os << "}";
+
+ // If we have any complex arguments in the previous c-tor
+ // then also generate the auto_ptr version.
+ //
+ if (has_complex_non_op_args)
+ {
+ os << name << "::" << endl
+ << name << " (";
+
+ String base_arg;
+
+ {
+ CtorArgs ctor_args (
+ *this, CtorArgs::arg_complex_auto_ptr, base_arg);
+ ctor_args.dispatch (c);
+ }
+
+ os << ")" << endl
+ << ": " << base << " (";
+
+ {
+ CtorBase base (*this, base_arg);
+ Traversal::Inherits inherits_base (base);
+
+ inherits (c, inherits_base);
+ }
+
+ os << ")";
+
+ if (edom_document_member_p (c))
+ {
+ os << "," << endl
+ << " " << edom_document_member (c) << " (" <<
+ "::xsd::cxx::xml::dom::create_document< " << char_type <<
+ " > ())";
+ }
+
+ names (c, ctor_names_);
+
+ os << "{";
+ if (facets)
+ os << "this->_facet_table (_xsd_" << name << "_facet_table);";
+ os << "}";
+ }
+
+ // If we are generating polymorphic code then we also need to
+ // provide auto_ptr version for every non-fundamental type.
+ //
+ if (has_non_fund_non_op_args &&
+ !complex_non_fund_args_clash &&
+ polymorphic)
+ {
+ os << name << "::" << endl
+ << name << " (";
+
+ String base_arg;
+
+ {
+ CtorArgs ctor_args (
+ *this, CtorArgs::arg_non_fund_auto_ptr, base_arg);
+ ctor_args.dispatch (c);
+ }
+
+ os << ")" << endl
+ << ": " << base << " (";
+
+ {
+ CtorBase base (*this, base_arg);
+ Traversal::Inherits inherits_base (base);
+
+ inherits (c, inherits_base);
+ }
+
+ os << ")";
+
+ if (edom_document_member_p (c))
+ {
+ os << "," << endl
+ << " " << edom_document_member (c) << " (" <<
+ "::xsd::cxx::xml::dom::create_document< " << char_type <<
+ " > ())";
+ }
+
+ names (c, ctor_names_);
+
+ os << "{";
+ if (facets)
+ os << "this->_facet_table (_xsd_" << name << "_facet_table);";
+ os << "}";
+ }
+
+
+ // copy c-tor
+ //
+
+ os << name << "::" << endl
+ << name << " (const " << name << "& x," << endl
+ << flags_type << " f," << endl
+ << container << "* c)" << endl
+ << ": " << base << " (x, f, c)";
+
+ if (edom_document_member_p (c))
+ {
+ os << "," << endl
+ << " " << edom_document_member (c) << " (" <<
+ "::xsd::cxx::xml::dom::create_document< " << char_type <<
+ " > ())";
+ }
+
+ {
+ CopyAny copy_any (*this, "x");
+ CopyMember copy_member (*this, "x");
+ Traversal::Names names;
+
+ names >> copy_member;
+
+ if (options.value<CLI::generate_wildcard> ())
+ names >> copy_any;
+
+ Complex::names (c, names);
+ }
+
+ os << "{";
+ if (facets)
+ os << "this->_facet_table (_xsd_" << name << "_facet_table);";
+ os << "}";
+
+ //
+ //
+ Boolean he (has<Traversal::Element> (c));
+ Boolean hae (has<Traversal::Any> (c));
+
+ Boolean ha (has<Traversal::Attribute> (c));
+ Boolean haa (has<Traversal::AnyAttribute> (c));
+
+ Boolean gen_wildcard (options.value<CLI::generate_wildcard> ());
+
+ //
+ //
+ if (!options.value<CLI::suppress_parsing> ())
+ {
+ // c-tor (xercesc::DOMElement)
+ //
+ os << name << "::" << endl
+ << name << " (const " << xerces_ns << "::DOMElement& e," << endl
+ << flags_type << " f," << endl
+ << container << "* c)" << endl
+ << ": " << base << " (e, f";
+
+ if (he || ha || hae || (haa && gen_wildcard))
+ os << " | " << flags_type << "::base";
+
+ os << ", c)";
+
+ if (edom_document_member_p (c))
+ {
+ os << "," << endl
+ << " " << edom_document_member (c) << " (" <<
+ "::xsd::cxx::xml::dom::create_document< " << char_type <<
+ " > ())";
+ }
+
+ names (c, element_ctor_names_);
+
+ os << "{";
+
+ if (facets)
+ os << "this->_facet_table (_xsd_" << name << "_facet_table);"
+ << endl;
+
+ Boolean base_has_el (false), base_has_at (false);
+
+ // We are only interested in this information if we are
+ // generating out own parse().
+ //
+ if (he || ha || hae || (haa && gen_wildcard))
+ {
+ if (c.inherits_p ())
+ {
+ HasParseFunction test (*this, base_has_el, base_has_at);
+ test.dispatch (c.inherits ().base ());
+ }
+ }
+
+ //@@ throw if p is no exhausted at the end.
+ //
+ if (he || ha || hae || (haa && gen_wildcard))
+ os << "if ((f & " << flags_type << "::base) == 0)"
+ << "{"
+ << parser_type << " p (e, " <<
+ (he || hae || base_has_el ? "true, " : "false, ") <<
+ (ha || (haa && gen_wildcard) || base_has_at ? "true" : "false")
+ << ");"
+ << "this->" << unclash (name, "parse") << " (p, f);"
+ << "}";
+
+ os << "}";
+
+ Boolean simple (true);
+ {
+ IsSimpleType t (simple);
+ t.dispatch (c);
+ }
+
+ if (simple)
+ {
+ // c-tor (xercesc::DOMAttr)
+ //
+ os << name << "::" << endl
+ << name << " (const " << xerces_ns << "::DOMAttr& a," << endl
+ << flags_type << " f," << endl
+ << container << "* c)" << endl
+ << ": " << base << " (a, f, c)"
+ << "{";
+
+ if (facets)
+ os << "this->_facet_table (_xsd_" << name << "_facet_table);";
+
+ os << "}";
+
+ // c-tor (string const&, xercesc::DOMElement)
+ //
+ os << name << "::" << endl
+ << name << " (const " << string_type << "& s," << endl
+ << "const " << xerces_ns << "::DOMElement* e," << endl
+ << flags_type << " f," << endl
+ << container << "* c)" << endl
+ << ": " << base << " (s, e, f, c)"
+ << "{";
+
+ if (facets)
+ os << "this->_facet_table (_xsd_" << name << "_facet_table);";
+
+ os << "}";
+ }
+
+ if (he || ha || hae || (haa && gen_wildcard))
+ {
+ os << "void " << name << "::" << endl
+ << unclash (name, "parse") << " (" <<
+ parser_type << "& p," << endl
+ << flags_type <<
+ (he || ha || base_has_el || base_has_at ? " f" : "") << ")"
+ << "{";
+
+ // Allow the base to parse its part.
+ //
+ if (base_has_el || base_has_at)
+ os << "this->" << base << "::parse (p, f);"
+ << endl;
+
+ if (he || hae)
+ {
+ os << "for (; p.more_elements (); p.next_element ())"
+ << "{"
+ << "const " << xerces_ns << "::DOMElement& i (" <<
+ "p.cur_element ());"
+ << "const " << qname_type << " n (" << endl
+ << "::xsd::cxx::xml::dom::name< " << char_type << " > (i));"
+ << endl;
+
+ names (c, names_element_);
+
+ os << "break;"
+ << "}";
+
+ // Make sure all non-optional elements are set.
+ //
+ names (c, names_element_test_);
+ }
+
+ if (ha || (haa && gen_wildcard))
+ {
+ if (base_has_at)
+ os << "p.reset_attributes ();"
+ << endl;
+
+ os << "while (p.more_attributes ())"
+ << "{"
+ << "const " << xerces_ns << "::DOMAttr& i (" <<
+ "p.next_attribute ());"
+ << "const " << qname_type << " n (" << endl
+ << "::xsd::cxx::xml::dom::name< " << char_type << " > (i));"
+ << endl;
+
+ names (c, names_attribute_);
+
+ // Generate anyAttribute code after all the attributes.
+ //
+ if (gen_wildcard)
+ names (c, names_any_attribute_);
+
+
+ // os << "{" // else block
+ // @@
+ // This doesn't play well with inheritance because we
+ // don't expect base's attributes. Also there are other
+ // "special" attributes such as xmlns, etc.
+ //
+ // << "throw ::xsd::cxx::tree::unexpected_attribute ... "
+ // << "}";
+
+ os << "}"; // while loop
+
+ // Make sure all non-optional attributes are set.
+ //
+ names (c, names_attribute_test_);
+ }
+
+ os << "}";
+ }
+ }
+
+ // _clone
+ //
+ os << name << "* " << name << "::" << endl
+ << "_clone (" << flags_type << " f," << endl
+ << container << "* c) const"
+ << "{"
+ << "return new class " << name << " (*this, f, c);"
+ << "}";
+
+ // d-tor
+ //
+ os << name << "::" << endl
+ << "~" << name << " ()"
+ << "{"
+ << "}";
+
+ // Register with type factory map.
+ //
+ if (polymorphic && !c.context ().count ("anonymous"))
+ {
+ // Note that we are using the original type name.
+ //
+ String const& name (ename (c));
+
+ if (!options.value<CLI::suppress_parsing> ())
+ os << "static" << endl
+ << "const ::xsd::cxx::tree::type_factory_initializer< 0, " <<
+ char_type << ", " << name << " >" << endl
+ << "_xsd_" << name << "_type_factory_init (" << endl
+ << L << strlit (c.name ()) << "," << endl
+ << L << strlit (xml_ns_name (c)) << ");"
+ << endl;
+
+ if (options.value<CLI::generate_comparison> ())
+ os << "static" << endl
+ << "const ::xsd::cxx::tree::comparison_initializer< 0, " <<
+ char_type << ", " << name << " >" << endl
+ << "_xsd_" << name << "_comparison_init;"
+ << endl;
+ }
+
+ // Comparison operators.
+ //
+ if (options.value<CLI::generate_comparison> () &&
+ (he || ha || !c.inherits_p () ||
+ ((hae || haa) && gen_wildcard)))
+ {
+ Boolean base_comp (false);
+
+ if (c.inherits_p ())
+ {
+ HasComparisonOperator test (*this, base_comp);
+ test.dispatch (c.inherits ().base ());
+ }
+
+ Boolean has_body (he || ha || base_comp ||
+ ((hae || haa) && gen_wildcard));
+
+ os << "bool" << endl
+ << "operator== (const " << name << "&" <<
+ (has_body ? " x" : "") << ", " <<
+ "const " << name << "&" << (has_body ? " y" : "") << ")"
+ << "{";
+
+ if (base_comp)
+ os << "if (!(static_cast< const " << base << "& > (x) ==" << endl
+ << "static_cast< const " << base << "& > (y)))" << endl
+ << "return false;"
+ << endl;
+
+ {
+ Complex::names (c, comparison_names_);
+ }
+
+ os << "return true;"
+ << "}";
+
+ os << "bool" << endl
+ << "operator!= (const " << name << "& x, " <<
+ "const " << name << "& y)"
+ << "{"
+ << "return !(x == y);"
+ << "}";
+ }
+ }
+
+ private:
+ Traversal::Inherits inherits_member_;
+ MemberTypeName member_name_;
+
+ Traversal::Names names_element_;
+ Traversal::Names names_element_test_;
+
+ Traversal::Names names_attribute_;
+ Traversal::Names names_any_attribute_;
+ Traversal::Names names_attribute_test_;
+
+ Any any_;
+ Element element_;
+
+ AnyTest any_test_;
+ ElementTest element_test_;
+
+ Attribute attribute_;
+ AttributeTest attribute_test_;
+
+ AnyAttribute any_attribute_;
+
+ DefaultCtorAnyInit default_ctor_any_init_;
+ DefaultCtorMemberInit default_ctor_member_init_;
+ Traversal::Names default_ctor_init_names_;
+
+ CtorAny ctor_any_;
+ CtorMember ctor_member_;
+ Traversal::Names ctor_names_;
+
+ ElementCtorAny element_ctor_any_;
+ ElementCtorMember element_ctor_member_;
+ Traversal::Names element_ctor_names_;
+
+ AnyComparison comparison_any_;
+ MemberComparison comparison_member_;
+ Traversal::Names comparison_names_;
+
+ FacetArray facet_array_;
+ };
+
+
+ // Generate element types and substitution group map entries.
+ //
+ struct GlobalElement : Traversal::Element,
+ GlobalElementBase,
+ protected virtual Context
+ {
+ GlobalElement (Context& c)
+ : Context (c),
+ GlobalElementBase (c),
+ element_type_ (c.options.value<CLI::generate_element_type> ()),
+ element_map_ (c.options.value<CLI::generate_element_map> ()),
+ type_name_ (c)
+ {
+ belongs_ >> type_name_;
+ }
+
+ virtual Void
+ traverse (Type& e)
+ {
+ if (element_type_ && doc_root_p (e))
+ {
+ SemanticGraph::Type& t (e.type ());
+
+ Boolean fund (false);
+ {
+ IsFundamentalType test (fund);
+ test.dispatch (t);
+ }
+
+ Boolean simple (true);
+ if (!fund)
+ {
+ IsSimpleType test (simple);
+ test.dispatch (t);
+ }
+
+ String const& name (ename (e));
+ String const& type (etype (e));
+ String const& member (emember (e));
+
+ os << "// " << name << endl
+ << "// " << endl
+ << endl;
+
+ // Virtual accessors.
+ //
+ os << "const " << any_type << "* " << name << "::" << endl
+ << "_value () const"
+ << "{";
+
+ if (fund)
+ os << "return 0;";
+ else
+ os << "return &this->" << member << ".get ();";
+
+ os << "}";
+
+ os << any_type << "* " << name << "::" << endl
+ << "_value ()"
+ << "{";
+
+ if (fund)
+ os << "return 0;";
+ else
+ os << "return &this->" << member << ".get ();";
+
+ os << "}";
+
+ // default c-tor
+ //
+ if (options.value<CLI::generate_default_ctor> ())
+ {
+ os << name << "::" << endl
+ << name << " ()" << endl
+ << ": " << member << " (0, 0)"
+ << "{"
+ << "}";
+ }
+
+ // c-tor (value)
+ //
+ os << name << "::" << endl
+ << name << " (const " << type << "& x)" << endl
+ << ": " << member << " (x, 0, 0)"
+ << "{"
+ << "}";
+
+
+ // c-tor (auto_ptr<value>)
+ //
+ if (!simple || (polymorphic && !fund))
+ {
+ os << name << "::" << endl
+ << name << " (::std::auto_ptr< " << type << " > p)" << endl
+ << ": " << member << " (p, 0, 0)"
+ << "{"
+ << "}";
+ }
+
+ // c-tor (xercesc::DOMElement)
+ //
+ SemanticGraph::Context& ec (e.context ());
+ String const& name_member (ec.get<String> ("element-name-member"));
+ String const& ns_member (ec.get<String> ("element-ns-member"));
+
+ Boolean parsing (!options.value<CLI::suppress_parsing> ());
+ if (parsing)
+ {
+ String const& tr (etraits (e));
+
+ os << name << "::" << endl
+ << name << " (const " << xerces_ns << "::DOMElement& e, " <<
+ flags_type << " f)" << endl
+ << ": " << member << " (f, 0)"
+ << "{"
+ << "const " << qname_type << " n (" << endl
+ << "::xsd::cxx::xml::dom::name< " << char_type << " > (e));"
+ << endl
+ << "if (n.name () == " << name_member << " && " <<
+ "n.namespace_ () == " << ns_member << ")" << endl
+ << "this->" << member << ".set (" << tr <<
+ "::create (e, f, 0));"
+ << "else" << endl
+ << "throw ::xsd::cxx::tree::unexpected_element < " <<
+ char_type << " > (" << endl
+ << "n.name (), n.namespace_ ()," << endl
+ << name_member << ", " << ns_member << ");"
+ << "}";
+ }
+
+ // copy c-tor
+ //
+ os << name << "::" << endl
+ << name << " (const " << name << "& x, " <<
+ flags_type << " f)" << endl
+ << ": " << element_type << " ()," << endl
+ << " " << member << " (x." << member << ", f, 0)"
+ << "{"
+ << "}";
+
+ // _clone
+ //
+ os << name << "* " << name << "::" << endl
+ << "_clone (" << flags_type << " f) const"
+ << "{"
+ << "return new class " << name << " (*this, f);"
+ << "}";
+
+ // Element name and namespace accessors.
+ //
+ String const& aname (ec.get<String> ("element-name"));
+ String const& ans (ec.get<String> ("element-ns"));
+
+ os << "const " << string_type << "& " << name << "::" << endl
+ << aname << " ()"
+ << "{"
+ << "return " << name_member << ";"
+ << "}";
+
+ os << "const " << string_type << "& " << name << "::" << endl
+ << ans << " ()"
+ << "{"
+ << "return " << ns_member << ";"
+ << "}";
+
+ os << "const " << string_type << "& " << name << "::" << endl
+ << "_name () const"
+ << "{"
+ << "return " << name_member << ";"
+ << "}";
+
+ os << "const " << string_type << "& " << name << "::" << endl
+ << "_namespace () const"
+ << "{"
+ << "return " << ns_member << ";"
+ << "}";
+
+ os << "const " << string_type << " " << name << "::" << endl
+ << name_member << " (" << L << strlit (e.name ()) << ");"
+ << endl
+ << "const " << string_type << " " << name << "::" << endl
+ << ns_member << " (" << L <<
+ strlit (e.namespace_ ().name ()) << ");"
+ << endl;
+
+ // d-tor
+ //
+ os << name << "::" << endl
+ << "~" << name << " ()"
+ << "{"
+ << "}";
+
+ // Element map registration.
+ //
+ if (element_map_ && parsing)
+ {
+ os << "static " << endl
+ << "const ::xsd::cxx::tree::parser_init< " << name << ", " <<
+ char_type << ", " << any_type << " >" << endl
+ << "_xsd_" << name << "_parser_init (" <<
+ name << "::" << aname << " (), " <<
+ name << "::" << ans << " ());"
+ << endl;
+ }
+ }
+
+ if (polymorphic && e.substitutes_p () &&
+ !options.value<CLI::suppress_parsing> ())
+ {
+ String const& name (ename (e));
+ Type& r (e.substitutes ().root ());
+
+ os << "static" << endl
+ << "const ::xsd::cxx::tree::type_factory_initializer< 0, " <<
+ char_type << ", ";
+
+ belongs (e, belongs_);
+
+ os << " >" << endl
+ << "_xsd_" << name << "_element_factory_init (" << endl
+ << L << strlit (r.name ()) << "," << endl
+ << L << strlit (r.namespace_ ().name ()) << "," << endl
+ << L << strlit (e.name ()) << "," << endl
+ << L << strlit (e.namespace_ ().name ()) << ");"
+ << endl
+ << endl;
+ }
+ }
+
+ private:
+ Boolean element_type_;
+ Boolean element_map_;
+ Traversal::Belongs belongs_;
+ MemberTypeName type_name_;
+ };
+ }
+
+ Void
+ generate_tree_source (Context& ctx,
+ UnsignedLong first,
+ UnsignedLong last)
+ {
+ if (ctx.options.value<CLI::generate_wildcard> ())
+ {
+ ctx.os << "#include <xsd/cxx/xml/dom/wildcard-source.hxx>" << endl
+ << endl;
+ }
+
+ if (!ctx.options.value<CLI::suppress_parsing> ())
+ ctx.os << "#include <xsd/cxx/xml/dom/parsing-source.hxx>" << endl
+ << endl;
+
+ if (ctx.polymorphic)
+ {
+ Boolean parsing (!ctx.options.value<CLI::suppress_parsing> ());
+ Boolean comparison (ctx.options.value<CLI::generate_comparison> ());
+
+ if (parsing)
+ ctx.os << "#include <xsd/cxx/tree/type-factory-map.hxx>" << endl
+ << endl;
+
+ if (comparison)
+ ctx.os << "#include <xsd/cxx/tree/comparison-map.hxx>" << endl
+ << endl;
+
+ if (parsing || comparison)
+ {
+ Boolean import_maps (ctx.options.value<CLI::import_maps> ());
+ Boolean export_maps (ctx.options.value<CLI::export_maps> ());
+
+ if (import_maps || export_maps)
+ {
+ ctx.os << "#ifdef _MSC_VER" << endl
+ << endl
+ << "namespace xsd"
+ << "{"
+ << "namespace cxx"
+ << "{"
+ << "namespace tree"
+ << "{";
+
+ if (parsing && export_maps)
+ ctx.os << "template struct __declspec (dllexport) " <<
+ "type_factory_plate< 0, " << ctx.char_type << " >;";
+
+ if (parsing && import_maps)
+ ctx.os << "template struct __declspec (dllimport) " <<
+ "type_factory_plate< 0, " << ctx.char_type << " >;";
+
+ if (comparison && export_maps)
+ ctx.os << "template struct __declspec (dllexport) " <<
+ "comparison_plate< 0, " << ctx.char_type << " >;";
+
+ if (comparison && import_maps)
+ ctx.os << "template struct __declspec (dllimport) " <<
+ "comparison_plate< 0, " << ctx.char_type << " >;";
+
+ ctx.os << "}" // tree
+ << "}" // cxx
+ << "}" // xsd
+ << "#endif // _MSC_VER" << endl
+ << endl;
+ }
+
+ ctx.os << "namespace _xsd"
+ << "{";
+
+ if (parsing)
+ ctx.os << "static" << endl
+ << "const ::xsd::cxx::tree::type_factory_plate< 0, " <<
+ ctx.char_type << " >" << endl
+ << "type_factory_plate_init;"
+ << endl;
+
+ if (comparison)
+ ctx.os << "static" << endl
+ << "const ::xsd::cxx::tree::comparison_plate< 0, " <<
+ ctx.char_type << " >" << endl
+ << "comparison_plate_init;"
+ << endl;
+
+ ctx.os << "}";
+ }
+ }
+
+ Traversal::Schema schema;
+ Traversal::Sources sources;
+ Traversal::Names names_ns, names;
+ Namespace ns (ctx, first, last);
+
+ List list (ctx);
+ Union union_ (ctx);
+ Complex complex (ctx);
+ Enumeration enumeration (ctx);
+ GlobalElement element (ctx);
+
+ schema >> sources >> schema;
+ schema >> names_ns >> ns >> names;
+
+ names >> list;
+ names >> union_;
+ names >> complex;
+ names >> enumeration;
+ names >> element;
+
+ schema.dispatch (ctx.schema_root);
+ }
+ }
+}
diff --git a/xsd/cxx/tree/tree-source.hxx b/xsd/cxx/tree/tree-source.hxx
new file mode 100644
index 0000000..a9a0521
--- /dev/null
+++ b/xsd/cxx/tree/tree-source.hxx
@@ -0,0 +1,24 @@
+// file : xsd/cxx/tree/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_TREE_TREE_SOURCE_HXX
+#define CXX_TREE_TREE_SOURCE_HXX
+
+#include <xsd-frontend/semantic-graph/schema.hxx>
+
+#include <cxx/tree/elements.hxx>
+
+namespace CXX
+{
+ namespace Tree
+ {
+ Void
+ generate_tree_source (Context&,
+ UnsignedLong first,
+ UnsignedLong last);
+ }
+}
+
+#endif // CXX_TREE_TREE_SOURCE_HXX
diff --git a/xsd/cxx/tree/validator.cxx b/xsd/cxx/tree/validator.cxx
new file mode 100644
index 0000000..8027df7
--- /dev/null
+++ b/xsd/cxx/tree/validator.cxx
@@ -0,0 +1,675 @@
+// file : xsd/cxx/tree/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/tree/validator.hxx>
+
+#include <cult/containers/set.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+#include <xsd-frontend/traversal.hxx>
+
+#include <cxx/tree/elements.hxx>
+
+#include <iostream>
+
+using std::wcerr;
+
+namespace CXX
+{
+ namespace Tree
+ {
+ namespace
+ {
+ class ValidationContext: public Context
+ {
+ public:
+ ValidationContext (SemanticGraph::Schema& root,
+ CLI::Options const& options,
+ const WarningSet& disabled_warnings,
+ Counts const& counts,
+ Boolean generate_xml_schema,
+ Boolean& valid_)
+ : Context (std::wcerr,
+ root,
+ options,
+ counts,
+ generate_xml_schema,
+ 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)
+ {
+ if (disabled_warnings_.find ("all") != disabled_warnings_.end ())
+ disabled_warnings_all_ = true;
+ }
+
+ 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.
+
+ if (n.named ())
+ {
+ SemanticGraph::Scope& scope (n.scope ());
+
+ if (scope.is_a<SemanticGraph::Namespace> ())
+ return n.name ();
+
+ return xpath (scope) + L"/" + n.name ();
+ }
+ else
+ {
+ return L"(anonymous type for " +
+ n.context ().get<String> ("instance-name") + L")";
+ }
+ }
+
+ 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, protected virtual ValidationContext
+ {
+ Any (ValidationContext& c)
+ : ValidationContext (c)
+ {
+ }
+
+ struct Element: Traversal::Element,
+ protected virtual ValidationContext
+ {
+ Element (ValidationContext& c, SemanticGraph::Any& any)
+ : ValidationContext (c),
+ any_ (any),
+ ns_ (any.definition_namespace ().name ())
+ {
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (skip (e))
+ return;
+
+ 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 T001: namespace '" << *i << "' allows for "
+ << "element '" << e.name () << "'" << endl;
+
+ os << a.file () << ":" << a.line () << ":" << a.column ()
+ << ": warning T001: 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;
+ }
+ }
+ }
+
+ 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::Names names;
+ Element element (*this, a);
+
+ complex >> names >> element;
+
+ complex.dispatch (type);
+ }
+ };
+
+
+ //
+ //
+ struct Traverser : Traversal::Schema,
+ Traversal::Complex,
+ Traversal::Type,
+ Traversal::Element,
+ protected virtual ValidationContext
+ {
+ Traverser (ValidationContext& c)
+ : ValidationContext (c), any_ (c)
+ {
+ *this >> sources_ >> *this;
+ *this >> schema_names_ >> ns_ >> names_;
+
+ names_ >> *this >> names_;
+
+ // Any
+ //
+ if (!is_disabled ("T001"))
+ {
+ *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;
+
+ os << c.file () << ":" << c.line () << ":" << c.column ()
+ << ": error: type '" << xpath (c) << "' inherits from "
+ << "yet undefined type '" << xpath (t) << "'" << endl;
+
+ os << t.file () << ":" << t.line () << ":" << t.column ()
+ << ": info: '" << xpath (t) << "' is defined here"
+ << endl;
+
+ os << c.file () << ":" << c.line () << ":" << c.column ()
+ << ": info: inheritance from a yet-undefined type is "
+ << "not supported" << endl;
+
+ os << c.file () << ":" << c.line () << ":" << c.column ()
+ << ": info: re-arrange your schema and try again"
+ << endl;
+ }
+ }
+ }
+
+ Complex::traverse (c);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Type& t)
+ {
+ // This is also used to traverse Complex.
+ //
+ if (t.named ())
+ {
+ types_.insert (t.scope ().name () + L"#" + t.name ());
+ }
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (is_disabled ("T002"))
+ return;
+
+ // Note that there is no test for generate_p since we want
+ // to catch cases when things are not being generated but
+ // most likely should have been.
+ //
+ if (e.substitutes_p () && !polymorphic &&
+ !subst_group_warning_issued)
+ {
+ subst_group_warning_issued = true;
+
+ os << e.file () << ":" << e.line () << ":" << e.column ()
+ << ": warning T002: 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 handle "
+ << "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 AnonymousType : Traversal::Schema,
+ Traversal::Complex,
+ Traversal::Element,
+ Traversal::Attribute,
+ protected virtual ValidationContext
+ {
+ AnonymousType (ValidationContext& c)
+ : ValidationContext (c),
+ anonymous_error_issued_ (false)
+ {
+ *this >> sources_ >> *this;
+ *this >> schema_names_ >> ns_ >> names_ >> *this;
+ *this >> names_;
+ }
+
+ 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 (!anonymous_error_issued_)
+ {
+ valid = false;
+ anonymous_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;
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Element& e)
+ {
+ if (skip (e)) return;
+
+ 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);
+ }
+
+ virtual Void
+ traverse (SemanticGraph::Attribute& 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);
+ }
+
+ private:
+ Boolean anonymous_error_issued_;
+
+ Containers::Set<String> types_;
+
+ Traversal::Sources sources_;
+
+ Traversal::Names schema_names_;
+ Traversal::Namespace ns_;
+
+ Traversal::Names names_;
+ };
+ }
+
+ Validator::
+ Validator ()
+ {
+ // Dummy ctor, helps with long symbols on HP-UX.
+ }
+
+ Boolean Validator::
+ validate (CLI::Options const& options,
+ SemanticGraph::Schema& schema,
+ SemanticGraph::Path const&,
+ const WarningSet& disabled_warnings,
+ Counts const& counts)
+ {
+ Boolean valid (true);
+ ValidationContext ctx (
+ schema, options, disabled_warnings, counts, false, valid);
+
+ //
+ //
+ Boolean import_maps (options.value<CLI::import_maps> ());
+ Boolean export_maps (options.value<CLI::export_maps> ());
+
+ if (import_maps && export_maps)
+ {
+ wcerr << "error: --import-maps and --export-maps are "
+ << "mutually exclusive" << endl;
+
+ return false;
+ }
+
+ if (import_maps && !ctx.polymorphic)
+ {
+ wcerr << "error: --import-maps can only be specified together with "
+ << "--generate-polymorphic" << endl;
+
+ return false;
+ }
+
+ if (export_maps && !ctx.polymorphic)
+ {
+ wcerr << "error: --export-maps can only be specified together " <<
+ "with --generate-polymorphic" << endl;
+
+ return false;
+ }
+
+ //
+ //
+ if (options.value<CLI::char_type> () != "char" &&
+ options.value<CLI::char_type> () != "wchar_t" &&
+ !ctx.is_disabled ("T003"))
+ {
+ wcerr << "warning T003: unknown base character type '" <<
+ options.value<CLI::char_type> ().c_str () << "'" << endl;
+ }
+
+ //
+ //
+ NarrowString tn (options.value<CLI::type_naming> ());
+
+ if (tn != "knr" && tn != "ucc" && tn != "java")
+ {
+ wcerr << "error: unknown type naming style specified: '" <<
+ tn.c_str () << "'" << endl;
+
+ return false;
+ }
+
+ NarrowString fn (options.value<CLI::function_naming> ());
+
+ if (fn != "knr" && fn != "lcc" && fn != "java")
+ {
+ wcerr << "error: unknown function naming style specified: '" <<
+ fn.c_str () << "'" << endl;
+
+ return false;
+ }
+
+ //
+ //
+ Boolean element_type (options.value<CLI::generate_element_type> ());
+ Boolean par (!options.value<CLI::suppress_parsing> ());
+ Boolean ser (options.value<CLI::generate_serialization> ());
+
+ if (options.value<CLI::generate_element_map> ())
+ {
+ if (!element_type)
+ {
+ wcerr << "error: --generate-element-map can only be specified " <<
+ "together with --generate-element-type" << endl;
+
+ return false;
+ }
+
+ if (!(par || ser))
+ {
+ wcerr << "error: --generate-element-map is specified but " <<
+ "neither parsing nor serialization code is generated" << endl;
+
+ return false;
+ }
+ }
+
+ // Issue a warning if there are more than one global element
+ // and we are generating parsing/serialization functions or
+ // element types for all of them by default.
+ //
+
+ if (counts.global_elements > 1 &&
+ (element_type || par || ser) &&
+ !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 ("T004"))
+ {
+ wcerr << schema.file () << ": warning T004: generating ";
+
+ if (element_type)
+ wcerr << "element types";
+ else
+ {
+ wcerr << (par ? "parsing " : "") <<
+ (ser ? (par ? "and serialization " : "serialization ") : "") <<
+ "functions";
+ }
+ wcerr << " for " << counts.global_elements << " global elements" <<
+ endl;
+
+ wcerr << schema.file () << ": info: use --root-element-* options "
+ << "to specify document root(s)" << endl;
+ }
+
+
+ // Test for anonymout types.
+ //
+ {
+ AnonymousType traverser (ctx);
+ traverser.dispatch (schema);
+ }
+
+ // Test the rest.
+ //
+ if (valid)
+ {
+ Traverser traverser (ctx);
+ traverser.dispatch (schema);
+ }
+
+ return valid;
+ }
+ }
+}
diff --git a/xsd/cxx/tree/validator.hxx b/xsd/cxx/tree/validator.hxx
new file mode 100644
index 0000000..f7fdc34
--- /dev/null
+++ b/xsd/cxx/tree/validator.hxx
@@ -0,0 +1,33 @@
+// file : xsd/cxx/tree/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_TREE_VALIDATOR_HXX
+#define CXX_TREE_VALIDATOR_HXX
+
+#include <cxx/tree/elements.hxx>
+#include <cxx/tree/cli.hxx>
+
+#include <xsd.hxx>
+
+namespace CXX
+{
+ namespace Tree
+ {
+ class Validator
+ {
+ public:
+ Validator (); // Dummy ctor, helps with long symbols on HP-UX.
+
+ Boolean
+ validate (CLI::Options const& options,
+ SemanticGraph::Schema&,
+ SemanticGraph::Path const& tu,
+ const WarningSet& disabled_warnings,
+ Counts const& counts);
+ };
+ }
+}
+
+#endif // CXX_TREE_VALIDATOR_HXX