From f0510d2f90467de8e8f260b47d79a9baaf9bef17 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 17 Sep 2009 07:15:29 +0200 Subject: Start tracking XSD with git --- xsd/cxx/tree/elements.cxx | 1327 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1327 insertions(+) create mode 100644 xsd/cxx/tree/elements.cxx (limited to 'xsd/cxx/tree/elements.cxx') 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 +// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +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 (), + ops.value (), + ops.value (), + ops.value (), + ops.value (), + ops.value (), + ops.value (), + ops.value (), + ops.value (), + ops.value (), + ops.value ()), + 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 ()), + 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 ()), + 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 ("container"); + flags_type = xs_name + L"::" + xsc.get ("flags"); + + if (ops.value ()) + element_type = xs_name + L"::" + xsc.get ("element-type"); + + properties_type = xs_name + L"::" + xsc.get ("properties"); + + if (!ops.value () || + ops.value ()) + { + error_handler_type = xs_name + L"::" + + xsc.get ("error-handler"); + } + + dom_auto_ptr_ = xs_name + L"::dom::auto_ptr"; + dom_node_key_ = xs_name + L"::dom::" + + xsc.get ("tree-node-key"); + + if (ops.value ()) + { + as_double_type_ = xs_name + L"::" + + xsc.get ("as-double"); + + as_decimal_type_ = xs_name + L"::" + + xsc.get ("as-decimal"); + + list_stream_type = xs_name + L"::" + + xsc.get ("list-stream"); + + namespace_infomap_type = xs_name + L"::" + + xsc.get ("namespace-infomap"); + } + + // istream and ostream are templates and for now use the same + // names regardless of the naming convention. + // + if (!ops.value ().empty ()) + istream_type = xs_name + L"::istream"; + + if (!ops.value ().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 ()) + 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 Vector; + + // Direct custom type mapping. + // + { + Vector const& v (ops.value ()); + + 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 ()); + + 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 ()) + return true; + + if (Complex* c = dynamic_cast (&t)) + { + if (c->inherits_p () && ultimate_base (*c).is_a ()) + 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 (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 () && + 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 () && + 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 ()) + 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 ()) + 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 ()) + 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 () && + ctx_.options.value () && + !ctx_.options.value ()) + return false; + + return true; + } + + Boolean GlobalElementBase:: + doc_root_p (SemanticGraph::Element& e) + { + if (!ctx_.options.value () && + !ctx_.options.value () && + !ctx_.options.value () && + !ctx_.options.value () && + ctx_.options.value ().empty ()) + return true; // By default treat them all. + + if (ctx_.options.value ()) + return false; + + if (ctx_.options.value ()) + return true; + + if (ctx_.options.value () && + e.context ().count ("first") != 0) + return true; + + if (ctx_.options.value () && + e.context ().count ("last") != 0) + return true; + + typedef Cult::Containers::Vector Names; + Names const& names (ctx_.options.value ()); + + // 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 () || + (n.is_a () && generate_p (dynamic_cast (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; + } + } +} -- cgit v1.1