From bce9d5a76072ec697ef69021818aa68709036da5 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 16 Mar 2009 08:16:43 +0200 Subject: Add support for type customization in C++/Hybrid examples/cxx/hybrid/custom/wildcard/: new example --- xsde/cxx/hybrid/cli.hxx | 2 + xsde/cxx/hybrid/elements.cxx | 36 +- xsde/cxx/hybrid/elements.hxx | 11 + xsde/cxx/hybrid/extraction-header.cxx | 49 ++- xsde/cxx/hybrid/extraction-source.cxx | 27 +- xsde/cxx/hybrid/generator.cxx | 31 +- xsde/cxx/hybrid/insertion-header.cxx | 49 ++- xsde/cxx/hybrid/insertion-source.cxx | 27 +- xsde/cxx/hybrid/parser-name-processor.cxx | 15 +- xsde/cxx/hybrid/parser-source.cxx | 2 +- xsde/cxx/hybrid/serializer-name-processor.cxx | 14 +- xsde/cxx/hybrid/tree-forward.cxx | 60 ++- xsde/cxx/hybrid/tree-header.cxx | 540 ++++++++++++++------------ xsde/cxx/hybrid/tree-inline.cxx | 33 +- xsde/cxx/hybrid/tree-name-processor.cxx | 194 ++++++++- xsde/cxx/hybrid/tree-size-processor.cxx | 164 +++++++- xsde/cxx/hybrid/tree-size-processor.hxx | 2 +- xsde/cxx/hybrid/tree-source.cxx | 10 +- xsde/xsde.cxx | 22 +- 19 files changed, 928 insertions(+), 360 deletions(-) (limited to 'xsde') diff --git a/xsde/cxx/hybrid/cli.hxx b/xsde/cxx/hybrid/cli.hxx index 343e53b..0d1ec70 100644 --- a/xsde/cxx/hybrid/cli.hxx +++ b/xsde/cxx/hybrid/cli.hxx @@ -43,6 +43,7 @@ namespace CXX extern Key suppress_reset; extern Key reuse_style_mixin; extern Key custom_data; + extern Key custom_type; extern Key custom_parser; extern Key custom_serializer; extern Key root_element_first; @@ -124,6 +125,7 @@ namespace CXX suppress_reset, Boolean, reuse_style_mixin, Boolean, custom_data, Cult::Containers::Vector, + custom_type, Cult::Containers::Vector, custom_parser, Cult::Containers::Vector, custom_serializer, Cult::Containers::Vector, root_element_first, Boolean, diff --git a/xsde/cxx/hybrid/elements.cxx b/xsde/cxx/hybrid/elements.cxx index 68bc0c2..a28dfc1 100644 --- a/xsde/cxx/hybrid/elements.cxx +++ b/xsde/cxx/hybrid/elements.cxx @@ -375,12 +375,19 @@ namespace CXX p->contained_compositor ().container ())); if (!r) - r = fq ? fq_name (t) : ename (t); + r = fq ? fq_name (t) : ename_custom (t); else { String tmp; tmp.swap (r); - r = fq ? fq_name (t) : ename (t); + + if (fq) + { + r += fq_name (t.scope ()); + r += L"::"; + } + + r = ename_custom (t); r += L"::"; r += tmp; } @@ -405,7 +412,10 @@ namespace CXX using SemanticGraph::Complex; Complex& t (dynamic_cast (a.scope ())); - return fq ? fq_name (t) : ename (t); + + return fq + ? fq_name (t.scope ()) + L"::" + ename_custom (t) + : ename_custom (t); } Void Context:: @@ -474,7 +484,25 @@ namespace CXX Void TypeForward:: traverse (SemanticGraph::Type& t) { - os << "class " << ename (t) << ";"; + SemanticGraph::Context& ctx (t.context ()); + + // Forward-declare the base. + // + if (ctx.count ("name-base")) + { + if (String base = ctx.get ("name-base")) + os << "class " << base << ";"; + } + + // Typedef or forward-declare the type. + // + if (ctx.count ("name-typedef")) + { + os << "typedef " << ctx.get ("name-typedef") << " " << + ename (t) << ";"; + } + else + os << "class " << ename (t) << ";"; } Void Includes:: diff --git a/xsde/cxx/hybrid/elements.hxx b/xsde/cxx/hybrid/elements.hxx index cd1a40f..d324b04 100644 --- a/xsde/cxx/hybrid/elements.hxx +++ b/xsde/cxx/hybrid/elements.hxx @@ -94,6 +94,17 @@ namespace CXX } static String const& + ename_custom (SemanticGraph::Type& t) + { + SemanticGraph::Context& c (t.context ()); + + if (!c.count ("name-base")) + return c.get ("name"); + else + return c.get ("name-base"); + } + + static String const& etype (SemanticGraph::Compositor& c) { return c.context ().get ("type"); diff --git a/xsde/cxx/hybrid/extraction-header.cxx b/xsde/cxx/hybrid/extraction-header.cxx index 8b7490f..dc729f6 100644 --- a/xsde/cxx/hybrid/extraction-header.cxx +++ b/xsde/cxx/hybrid/extraction-header.cxx @@ -24,7 +24,13 @@ namespace CXX virtual Void traverse (Type& l) { - String name (ename (l)); + String const& name (ename_custom (l)); + + // We may not need to generate the class if this type is + // being customized. + // + if (!name) + return; for (Streams::ConstIterator i (istreams.begin ()); i != istreams.end (); ++i) @@ -47,7 +53,13 @@ namespace CXX virtual Void traverse (Type& u) { - String name (ename (u)); + String const& name (ename_custom (u)); + + // We may not need to generate the class if this type is + // being customized. + // + if (!name) + return; for (Streams::ConstIterator i (istreams.begin ()); i != istreams.end (); ++i) @@ -195,24 +207,27 @@ namespace CXX virtual Void traverse (Type& c) { - if (!restriction_p (c)) - { - String name (ename (c)); + String const& name (ename_custom (c)); - for (Streams::ConstIterator i (istreams.begin ()); - i != istreams.end (); ++i) - { - os << (exceptions ? "void" : "bool") << endl - << "operator>> (" << istream (*i) << "&," << endl - << name << "&);" - << endl; - } + // We may not need to generate the class if this type is + // being customized. + // + if (!name) + return; - // Operators for nested classes. - // - if (c.contains_compositor_p ()) - Complex::contains_compositor (c, contains_compositor_); + for (Streams::ConstIterator i (istreams.begin ()); + i != istreams.end (); ++i) + { + os << (exceptions ? "void" : "bool") << endl + << "operator>> (" << istream (*i) << "&," << endl + << name << "&);" + << endl; } + + // Operators for nested classes. + // + if (!restriction_p (c) && c.contains_compositor_p ()) + Complex::contains_compositor (c, contains_compositor_); } private: diff --git a/xsde/cxx/hybrid/extraction-source.cxx b/xsde/cxx/hybrid/extraction-source.cxx index 44af7e0..5945ce3 100644 --- a/xsde/cxx/hybrid/extraction-source.cxx +++ b/xsde/cxx/hybrid/extraction-source.cxx @@ -24,7 +24,13 @@ namespace CXX virtual Void traverse (Type& l) { - String name (ename (l)); + String const& name (ename_custom (l)); + + // We may not need to generate the class if this type is + // being customized. + // + if (!name) + return; for (Streams::ConstIterator i (istreams.begin ()); i != istreams.end (); ++i) @@ -56,7 +62,14 @@ namespace CXX virtual Void traverse (Type& u) { - String name (ename (u)); + String const& name (ename_custom (u)); + + // We may not need to generate the class if this type is + // being customized. + // + if (!name) + return; + String const& value (u.context ().get ("value")); for (Streams::ConstIterator i (istreams.begin ()); @@ -930,9 +943,15 @@ namespace CXX virtual Void traverse (Type& c) { - Boolean restriction (restriction_p (c)); + String const& name (ename_custom (c)); + + // We may not need to generate the class if this type is + // being customized. + // + if (!name) + return; - String name (ename (c)); + Boolean restriction (restriction_p (c)); for (Streams::ConstIterator i (istreams.begin ()); i != istreams.end (); ++i) diff --git a/xsde/cxx/hybrid/generator.cxx b/xsde/cxx/hybrid/generator.cxx index 28d851b..14afad6 100644 --- a/xsde/cxx/hybrid/generator.cxx +++ b/xsde/cxx/hybrid/generator.cxx @@ -131,6 +131,7 @@ namespace CXX extern Key suppress_reset = "suppress-reset"; extern Key reuse_style_mixin = "reuse-style-mixin"; extern Key custom_data = "custom-data"; + extern Key custom_type = "custom-type"; extern Key custom_parser = "custom-parser"; extern Key custom_serializer = "custom-serializer"; extern Key root_element_first = "root-element-first"; @@ -294,20 +295,34 @@ namespace CXX << " XML Schema type ." << endl; + e << "--custom-type " << endl + << " Use a custom type implementation instead of the\n" + << " generated version. The argument is in the\n" + << " form name[=[flags][/[type][/[base][/include]]]],\n" + << " where is an XML Schema type name,\n" + << " optional specify whether the custom type\n" + << " is fixed or variable-length, optional is\n" + << " a C++ type name that should be used instead,\n" + << " optional is a C++ name that should be\n" + << " given to the generated version, and optional\n" + << " is the header file that defines the\n" + << " custom implementation." + << endl; + e << "--custom-parser " << endl << " Use a custom parser implementation instead of the\n" << " generated version. The argument is in the\n" - << " form type[=base[/include]], where is an XML\n" - << " Schema type name, optional is a C++ name\n" - << " that should be given to the generated version,\n" - << " and optional is the header file that\n" - << " defines the custom implementation." + << " form name[=[base][/include]], where is an\n" + << " XML Schema type name, optional is a C++\n" + << " name that should be given to the generated\n" + << " version, and optional is the header\n" + << " file that defines the custom implementation." << endl; e << "--custom-serializer " << endl << " Use a custom serializer implementation instead of\n" << " the generated version. The argument is in\n" - << " the form type[=base[/include]], where is\n" + << " the form name[=[base][/include]], where is\n" << " an XML Schema type name, optional is a C++\n" << " name that should be given to the generated\n" << " version, and optional is the header\n" @@ -914,7 +929,9 @@ namespace CXX // Determine which types are fixed/variable-sized. // TreeSizeProcessor proc; - proc.process (ops, schema, file); + + if (!proc.process (ops, schema, file)) + throw Failed (); } namespace diff --git a/xsde/cxx/hybrid/insertion-header.cxx b/xsde/cxx/hybrid/insertion-header.cxx index 050b58f..4898c02 100644 --- a/xsde/cxx/hybrid/insertion-header.cxx +++ b/xsde/cxx/hybrid/insertion-header.cxx @@ -24,7 +24,13 @@ namespace CXX virtual Void traverse (Type& l) { - String name (ename (l)); + String const& name (ename_custom (l)); + + // We may not need to generate the class if this type is + // being customized. + // + if (!name) + return; for (Streams::ConstIterator i (ostreams.begin ()); i != ostreams.end (); ++i) @@ -47,7 +53,13 @@ namespace CXX virtual Void traverse (Type& u) { - String name (ename (u)); + String const& name (ename_custom (u)); + + // We may not need to generate the class if this type is + // being customized. + // + if (!name) + return; for (Streams::ConstIterator i (ostreams.begin ()); i != ostreams.end (); ++i) @@ -195,24 +207,27 @@ namespace CXX virtual Void traverse (Type& c) { - if (!restriction_p (c)) - { - String name (ename (c)); + String const& name (ename_custom (c)); - for (Streams::ConstIterator i (ostreams.begin ()); - i != ostreams.end (); ++i) - { - os << (exceptions ? "void" : "bool") << endl - << "operator<< (" << ostream (*i) << "&," << endl - << "const " << name << "&);" - << endl; - } + // We may not need to generate the class if this type is + // being customized. + // + if (!name) + return; - // Operators for nested classes. - // - if (c.contains_compositor_p ()) - Complex::contains_compositor (c, contains_compositor_); + for (Streams::ConstIterator i (ostreams.begin ()); + i != ostreams.end (); ++i) + { + os << (exceptions ? "void" : "bool") << endl + << "operator<< (" << ostream (*i) << "&," << endl + << "const " << name << "&);" + << endl; } + + // Operators for nested classes. + // + if (!restriction_p (c) && c.contains_compositor_p ()) + Complex::contains_compositor (c, contains_compositor_); } private: diff --git a/xsde/cxx/hybrid/insertion-source.cxx b/xsde/cxx/hybrid/insertion-source.cxx index 58fe9f5..b0b89c9 100644 --- a/xsde/cxx/hybrid/insertion-source.cxx +++ b/xsde/cxx/hybrid/insertion-source.cxx @@ -24,7 +24,13 @@ namespace CXX virtual Void traverse (Type& l) { - String name (ename (l)); + String const& name (ename_custom (l)); + + // We may not need to generate the class if this type is + // being customized. + // + if (!name) + return; for (Streams::ConstIterator i (ostreams.begin ()); i != ostreams.end (); ++i) @@ -57,7 +63,14 @@ namespace CXX virtual Void traverse (Type& u) { - String name (ename (u)); + String const& name (ename_custom (u)); + + // We may not need to generate the class if this type is + // being customized. + // + if (!name) + return; + String const& value (u.context ().get ("value")); for (Streams::ConstIterator i (ostreams.begin ()); @@ -590,9 +603,15 @@ namespace CXX virtual Void traverse (Type& c) { - Boolean restriction (restriction_p (c)); + String const& name (ename_custom (c)); + + // We may not need to generate the class if this type is + // being customized. + // + if (!name) + return; - String name (ename (c)); + Boolean restriction (restriction_p (c)); for (Streams::ConstIterator i (ostreams.begin ()); i != ostreams.end (); ++i) diff --git a/xsde/cxx/hybrid/parser-name-processor.cxx b/xsde/cxx/hybrid/parser-name-processor.cxx index c913766..740cf36 100644 --- a/xsde/cxx/hybrid/parser-name-processor.cxx +++ b/xsde/cxx/hybrid/parser-name-processor.cxx @@ -357,12 +357,6 @@ namespace CXX virtual Void traverse (Type& c) { - Boolean restriction (false); - - if (c.inherits_p ()) - restriction = c.inherits ().is_a () && - !c.inherits ().base ().is_a (); - SemanticGraph::Context& cc (c.context ()); // In case of customization use p:impl-base instead of p:impl. @@ -371,10 +365,17 @@ namespace CXX String const& base (cc.count ("p:impl-base") ? cc.get ("p:impl-base") : cc.get ("p:impl")); - if (!base) return; + // + // + Boolean restriction (false); + + if (c.inherits_p ()) + restriction = c.inherits ().is_a () && + !c.inherits ().base ().is_a (); + // Use skeleton's name set to make sure we don't clash // with callbacks which we are overriding. // diff --git a/xsde/cxx/hybrid/parser-source.cxx b/xsde/cxx/hybrid/parser-source.cxx index f9c1855..4c4237c 100644 --- a/xsde/cxx/hybrid/parser-source.cxx +++ b/xsde/cxx/hybrid/parser-source.cxx @@ -904,7 +904,7 @@ namespace CXX // // - struct Complex : Traversal::Complex, Context + struct Complex: Traversal::Complex, Context { Complex (Context& c) : Context (c), diff --git a/xsde/cxx/hybrid/serializer-name-processor.cxx b/xsde/cxx/hybrid/serializer-name-processor.cxx index b6ab09b..ba4a268 100644 --- a/xsde/cxx/hybrid/serializer-name-processor.cxx +++ b/xsde/cxx/hybrid/serializer-name-processor.cxx @@ -371,12 +371,6 @@ namespace CXX virtual Void traverse (Type& c) { - Boolean restriction (false); - - if (c.inherits_p ()) - restriction = c.inherits ().is_a () && - !c.inherits ().base ().is_a (); - SemanticGraph::Context& cc (c.context ()); // In case of customization use s:impl-base instead of s:impl. @@ -388,6 +382,14 @@ namespace CXX if (!base) return; + // + // + Boolean restriction (false); + + if (c.inherits_p ()) + restriction = c.inherits ().is_a () && + !c.inherits ().base ().is_a (); + // Use skeleton's name set to make sure we don't clash // with callbacks which we are overriding. // diff --git a/xsde/cxx/hybrid/tree-forward.cxx b/xsde/cxx/hybrid/tree-forward.cxx index 32f1180..451f129 100644 --- a/xsde/cxx/hybrid/tree-forward.cxx +++ b/xsde/cxx/hybrid/tree-forward.cxx @@ -24,7 +24,25 @@ namespace CXX virtual Void traverse (Type& l) { - os << "class " << ename (l) << ";"; + SemanticGraph::Context& ctx (l.context ()); + + // Forward-declare the base. + // + if (ctx.count ("name-base")) + { + if (String base = ctx.get ("name-base")) + os << "class " << base << ";"; + } + + // Typedef or forward-declare the type. + // + if (ctx.count ("name-typedef")) + { + os << "typedef " << ctx.get ("name-typedef") << " " << + ename (l) << ";"; + } + else + os << "class " << ename (l) << ";"; } }; @@ -38,7 +56,25 @@ namespace CXX virtual Void traverse (Type& u) { - os << "class " << ename (u) << ";"; + SemanticGraph::Context& ctx (u.context ()); + + // Forward-declare the base. + // + if (ctx.count ("name-base")) + { + if (String base = ctx.get ("name-base")) + os << "class " << base << ";"; + } + + // Typedef or forward-declare the type. + // + if (ctx.count ("name-typedef")) + { + os << "typedef " << ctx.get ("name-typedef") << " " << + ename (u) << ";"; + } + else + os << "class " << ename (u) << ";"; } }; @@ -52,7 +88,25 @@ namespace CXX virtual Void traverse (Type& c) { - os << "class " << ename (c) << ";"; + SemanticGraph::Context& ctx (c.context ()); + + // Forward-declare the base. + // + if (ctx.count ("name-base")) + { + if (String base = ctx.get ("name-base")) + os << "class " << base << ";"; + } + + // Typedef or forward-declare the type. + // + if (ctx.count ("name-typedef")) + { + os << "typedef " << ctx.get ("name-typedef") << " " << + ename (c) << ";"; + } + else + os << "class " << ename (c) << ";"; } }; diff --git a/xsde/cxx/hybrid/tree-header.cxx b/xsde/cxx/hybrid/tree-header.cxx index dc378fe..207b35f 100644 --- a/xsde/cxx/hybrid/tree-header.cxx +++ b/xsde/cxx/hybrid/tree-header.cxx @@ -24,66 +24,86 @@ namespace CXX virtual Void traverse (Type& l) { - String name (ename (l)); + SemanticGraph::Context& lc (l.context ()); + String const& name (ename_custom (l)); - os << "// " << comment (l.name ()) << " (variable-length)" << endl - << "//" << endl; - - os << "class " << name << ": public "; - - base_name_.dispatch (l.argumented ().type ()); - - os << "{" - << "private:" << endl - << name << " (const " << name << "&);" - << name << "& operator= (const " << name << "&);" - << endl; - - // c-tor + // We may not need to generate the class if this type is + // being customized. // - os << "public:" << endl - << name << " ();"; - - // Custom data. - // - if (l.context ().count ("cd-name")) + if (name) { - String const& name (ecd_name (l)); - String const& sequence (ecd_sequence (l)); - String const& iterator (ecd_iterator (l)); - String const& const_iterator (ecd_const_iterator (l)); - - os << endl - << "// Custom data." << endl + os << "// " << comment (l.name ()) << " (variable-length)" << endl << "//" << endl; - // sequence & iterators - // - os << "typedef ::xsde::cxx::hybrid::data_seq " << sequence << ";" - << "typedef " << sequence << "::iterator " << iterator << ";" - << "typedef " << sequence << "::const_iterator " << - const_iterator << ";" + os << "class " << name << ": public "; + + base_name_.dispatch (l.argumented ().type ()); + + os << "{" + << "private:" << endl + << name << " (const " << name << "&);" + << name << "& operator= (const " << name << "&);" << endl; - // const seq& - // name () const + // c-tor // - os << "const " << sequence << "&" << endl - << name << " () const;" - << endl; + os << "public:" << endl + << name << " ();"; - // seq& - // name () + // Custom data. // - os << sequence << "&" << endl - << name << " ();" - << endl; + if (lc.count ("cd-name")) + { + String const& name (ecd_name (l)); + String const& sequence (ecd_sequence (l)); + String const& iterator (ecd_iterator (l)); + String const& const_iterator (ecd_const_iterator (l)); - os << "private:" << endl - << sequence << " " << ecd_member (l) << ";"; + os << endl + << "// Custom data." << endl + << "//" << endl; + + // sequence & iterators + // + os << "typedef ::xsde::cxx::hybrid::data_seq " << sequence << ";" + << "typedef " << sequence << "::iterator " << iterator << ";" + << "typedef " << sequence << "::const_iterator " << + const_iterator << ";" + << endl; + + // const seq& + // name () const + // + os << "const " << sequence << "&" << endl + << name << " () const;" + << endl; + + // seq& + // name () + // + os << sequence << "&" << endl + << name << " ();" + << endl; + + os << "private:" << endl + << sequence << " " << ecd_member (l) << ";"; + } + + os << "};"; } - os << "};"; + // Generate include for custom type. + // + if (lc.count ("name-include")) + { + close_ns (); + + os << "#include " << process_include_path ( + lc.get ("name-include")) << endl + << endl; + + open_ns (); + } } private: @@ -101,147 +121,166 @@ namespace CXX traverse (Type& u) { SemanticGraph::Context& uc (u.context ()); + String const& name (ename_custom (u)); - String name (ename (u)); - Boolean cd (uc.count ("cd-name")); + // We may not need to generate the class if this type is + // being customized. + // + if (name) + { + Boolean cd (uc.count ("cd-name")); - os << "// " << comment (u.name ()) << " (variable-length)" << endl - << "//" << endl; + os << "// " << comment (u.name ()) << " (variable-length)" << endl + << "//" << endl; - os << "class " << name - << "{"; + os << "class " << name + << "{"; - if (!fixed_length (u)) - os << "private:" << endl - << name << " (const " << name << "&);" - << name << "& operator= (const " << name << "&);" - << endl; + if (!fixed_length (u)) + os << "private:" << endl + << name << " (const " << name << "&);" + << name << "& operator= (const " << name << "&);" + << endl; - os << "public:" << endl; + os << "public:" << endl; - // c-tor - // - os << name << " ();"; + // c-tor + // + os << name << " ();"; - String const& value (uc.get ("value")); - String const& member (uc.get ("value-member")); + String const& value (uc.get ("value")); + String const& member (uc.get ("value-member")); - if (stl) - { - os << endl; + if (stl) + { + os << endl; - // const std::string& - // name () const - // - os << "const ::std::string&" << endl - << value << " () const;" - << endl; + // const std::string& + // name () const + // + os << "const ::std::string&" << endl + << value << " () const;" + << endl; - // std::string& - // name () - // - os << "::std::string&" << endl - << value << " ();" - << endl; + // std::string& + // name () + // + os << "::std::string&" << endl + << value << " ();" + << endl; - // void - // name (const std::string&) - // - os << "void" << endl - << value << " (const ::std::string&);" - << endl; - } - else - { - // d-tor - // - os << "~" << name << " ();" - << endl; + // void + // name (const std::string&) + // + os << "void" << endl + << value << " (const ::std::string&);" + << endl; + } + else + { + // d-tor + // + os << "~" << name << " ();" + << endl; - // const char* - // name () const - // - os << "const char*" << endl - << value << " () const;" - << endl; + // const char* + // name () const + // + os << "const char*" << endl + << value << " () const;" + << endl; - // char* - // name () - // - os << "char*" << endl - << value << " ();" - << endl; + // char* + // name () + // + os << "char*" << endl + << value << " ();" + << endl; - // void - // name (char*) - // - os << "void" << endl - << value << " (char*);" - << endl; + // void + // name (char*) + // + os << "void" << endl + << value << " (char*);" + << endl; - // char* - // detach () + // char* + // detach () + // + if (detach) + { + os << "char*" << endl + << uc.get ("value-detach") << " ();" + << endl; + } + } + + // Custom data. // - if (detach) + if (cd) { - os << "char*" << endl - << uc.get ("value-detach") << " ();" + String const& name (ecd_name (u)); + String const& sequence (ecd_sequence (u)); + String const& iterator (ecd_iterator (u)); + String const& const_iterator (ecd_const_iterator (u)); + + os << "// Custom data." << endl + << "//" << endl; + + // sequence & iterators + // + os << "typedef ::xsde::cxx::hybrid::data_seq " << sequence << ";" + << "typedef " << sequence << "::iterator " << iterator << ";" + << "typedef " << sequence << "::const_iterator " << + const_iterator << ";" << endl; - } - } - // Custom data. - // - if (cd) - { - String const& name (ecd_name (u)); - String const& sequence (ecd_sequence (u)); - String const& iterator (ecd_iterator (u)); - String const& const_iterator (ecd_const_iterator (u)); + // const seq& + // name () const + // + os << "const " << sequence << "&" << endl + << name << " () const;" + << endl; - os << "// Custom data." << endl - << "//" << endl; + // seq& + // name () + // + os << sequence << "&" << endl + << name << " ();" + << endl; + } - // sequence & iterators - // - os << "typedef ::xsde::cxx::hybrid::data_seq " << sequence << ";" - << "typedef " << sequence << "::iterator " << iterator << ";" - << "typedef " << sequence << "::const_iterator " << - const_iterator << ";" - << endl; + if (stl) + { + os << "private:" << endl + << "::std::string " << member << ";"; + } + else + { + os << "private:" << endl + << "char* " << member << ";"; + } - // const seq& - // name () const + // Custom data. // - os << "const " << sequence << "&" << endl - << name << " () const;" - << endl; + if (cd) + os << ecd_sequence (u) << " " << ecd_member (u) << ";"; - // seq& - // name () - // - os << sequence << "&" << endl - << name << " ();" - << endl; + os << "};"; } - if (stl) - { - os << "private:" << endl - << "::std::string " << member << ";"; - } - else + // Generate include for custom type. + // + if (uc.count ("name-include")) { - os << "private:" << endl - << "char* " << member << ";"; - } + close_ns (); - // Custom data. - // - if (cd) - os << ecd_sequence (u) << " " << ecd_member (u) << ";"; + os << "#include " << process_include_path ( + uc.get ("name-include")) << endl + << endl; - os << "};"; + open_ns (); + } } }; @@ -2313,109 +2352,130 @@ namespace CXX virtual Void traverse (Type& c) { - String name (ename (c)); - Boolean fl (fixed_length (c)); - Boolean restriction (restriction_p (c)); - Boolean cd (c.context ().count ("cd-name")); + SemanticGraph::Context& cc (c.context ()); + String const& name (ename_custom (c)); - os << "// " << comment (c.name ()) << " (" << - (fl ? "fixed-length" : "variable-length") << ")" << endl - << "//" << endl; - - os << "class " << name; - - if (c.inherits_p ()) + // We may not need to generate the class if this type is + // being customized. + // + if (name) { - os << ": public "; - base_name_.dispatch (c.inherits ().base ()); - } + Boolean fl (fixed_length (c)); + Boolean restriction (restriction_p (c)); + Boolean cd (cc.count ("cd-name")); - os << "{"; + os << "// " << comment (c.name ()) << " (" << + (fl ? "fixed-length" : "variable-length") << ")" << endl + << "//" << endl; - // c-tor - // - os << "public:" << endl - << name << " ();"; + os << "class " << name; - // d-tor - // - if (!restriction) - os << "~" << name << " ();"; + if (c.inherits_p ()) + { + os << ": public "; + base_name_.dispatch (c.inherits ().base ()); + } - // copy c-tor & operator= - // - if (!fl) - os << endl - << "private:" << endl; + os << "{"; - if (!fl || !restriction) - os << name << " (const " << name << "&);" - << name << "& operator= (const " << name << "&);" - << endl; + // c-tor + // + os << "public:" << endl + << name << " ();"; - if ((!restriction && !fl) || cd) - os << "public:" << endl; + // d-tor + // + if (!restriction) + os << "~" << name << " ();"; - if (!restriction) - { - Complex::names (c, attribute_names_); + // copy c-tor & operator= + // + if (!fl) + os << endl + << "private:" << endl; - if (c.contains_compositor_p ()) - Complex::contains_compositor (c, contains_compositor_); - } + if (!fl || !restriction) + os << name << " (const " << name << "&);" + << name << "& operator= (const " << name << "&);" + << endl; - // Custom data. - // - if (cd) - { - String const& name (ecd_name (c)); - String const& sequence (ecd_sequence (c)); - String const& iterator (ecd_iterator (c)); - String const& const_iterator (ecd_const_iterator (c)); + if ((!restriction && !fl) || cd) + os << "public:" << endl; - os << "// Custom data." << endl - << "//" << endl; + if (!restriction) + { + Complex::names (c, attribute_names_); - // sequence & iterators - // - os << "typedef ::xsde::cxx::hybrid::data_seq " << sequence << ";" - << "typedef " << sequence << "::iterator " << iterator << ";" - << "typedef " << sequence << "::const_iterator " << - const_iterator << ";" - << endl; + if (c.contains_compositor_p ()) + Complex::contains_compositor (c, contains_compositor_); + } - // const seq& - // name () const + // Custom data. // - os << "const " << sequence << "&" << endl - << name << " () const;" - << endl; + if (cd) + { + String const& name (ecd_name (c)); + String const& sequence (ecd_sequence (c)); + String const& iterator (ecd_iterator (c)); + String const& const_iterator (ecd_const_iterator (c)); - // seq& - // name () - // - os << sequence << "&" << endl - << name << " ();" - << endl; - } + os << "// Custom data." << endl + << "//" << endl; - if (!restriction || cd) - os << "private:" << endl; + // sequence & iterators + // + os << "typedef ::xsde::cxx::hybrid::data_seq " << sequence << ";" + << "typedef " << sequence << "::iterator " << iterator << ";" + << "typedef " << sequence << "::const_iterator " << + const_iterator << ";" + << endl; - if (!restriction) - { - Complex::names (c, attribute_names_data_); + // const seq& + // name () const + // + os << "const " << sequence << "&" << endl + << name << " () const;" + << endl; - if (c.contains_compositor_p ()) - Complex::contains_compositor (c, contains_compositor_data_); + // seq& + // name () + // + os << sequence << "&" << endl + << name << " ();" + << endl; + } + + if (!restriction || cd) + os << "private:" << endl; + + if (!restriction) + { + Complex::names (c, attribute_names_data_); + + if (c.contains_compositor_p ()) + Complex::contains_compositor (c, contains_compositor_data_); + } + + // Custom data. + // + if (cd) + os << ecd_sequence (c) << " " << ecd_member (c) << ";"; + + os << "};"; } - // Custom data. + // Generate include for custom type. // - if (cd) - os << ecd_sequence (c) << " " << ecd_member (c) << ";"; + if (cc.count ("name-include")) + { + close_ns (); - os << "};"; + os << "#include " << process_include_path ( + cc.get ("name-include")) << endl + << endl; + + open_ns (); + } } private: @@ -2499,7 +2559,7 @@ namespace CXX Traversal::Sources sources; Traversal::Names names_ns, names; - Namespace ns (ctx); + Namespace ns (ctx, true); List list (ctx); Union union_ (ctx); diff --git a/xsde/cxx/hybrid/tree-inline.cxx b/xsde/cxx/hybrid/tree-inline.cxx index 34d0cc3..b1c60e6 100644 --- a/xsde/cxx/hybrid/tree-inline.cxx +++ b/xsde/cxx/hybrid/tree-inline.cxx @@ -24,7 +24,13 @@ namespace CXX virtual Void traverse (Type& l) { - String name (ename (l)); + String const& name (ename_custom (l)); + + // We may not need to generate the class if this type is + // being customized. + // + if (!name) + return; os << "// " << comment (l.name ()) << endl << "//" << endl @@ -82,7 +88,13 @@ namespace CXX virtual Void traverse (Type& u) { - String name (ename (u)); + String const& name (ename_custom (u)); + + // We may not need to generate the class if this type is + // being customized. + // + if (!name) + return; os << "// " << comment (u.name ()) << endl << "//" << endl @@ -1810,12 +1822,20 @@ namespace CXX virtual Void traverse (Type& c) { + String const& scope (ename_custom (c)); + + // We may not need to generate the class if this type is + // being customized. + // + if (!scope) + return; + + os << "// " << comment (c.name ()) << endl + << "//" << endl + << endl; + if (!restriction_p (c)) { - os << "// " << comment (c.name ()) << endl - << "//" << endl - << endl; - Complex::names (c, attribute_names_func_); if (c.contains_compositor_p ()) @@ -1831,7 +1851,6 @@ namespace CXX // if (c.context ().count ("cd-name")) { - String const& scope (ename (c)); String const& name (ecd_name (c)); String const& member (ecd_member (c)); String const& sequence (ecd_sequence (c)); diff --git a/xsde/cxx/hybrid/tree-name-processor.cxx b/xsde/cxx/hybrid/tree-name-processor.cxx index 7783ba5..a3a1dd3 100644 --- a/xsde/cxx/hybrid/tree-name-processor.cxx +++ b/xsde/cxx/hybrid/tree-name-processor.cxx @@ -52,6 +52,7 @@ namespace CXX stl (!ops.value ()), detach (ops.value ()), custom_data_map (custom_data_map_), + custom_type_map (custom_type_map_), global_type_names (global_type_names_) { // Translate the type names with custom data. @@ -93,6 +94,82 @@ namespace CXX } while (true); } } + + // Custom type mapping. + // + { + typedef Containers::Vector Vector; + Vector const& v (ops.value ()); + + for (Vector::ConstIterator i (v.begin ()), e (v.end ()); + i != e; ++i) + { + String s (*i); + + if (s.empty ()) + continue; + + // Split the string in two parts at the last '='. + // + Size pos (s.rfind ('=')); + + // If no delimiter found type, base, and include are empty. + // + if (pos == String::npos) + { + custom_type_map_[s].type.clear (); + custom_type_map_[s].base.clear (); + custom_type_map_[s].include.clear (); + continue; + } + + String name (s, 0, pos); + + // Skip the flags component. + // + pos = s.find ('/', pos + 1); + + if (pos == String::npos) + { + custom_type_map_[name].type.clear (); + custom_type_map_[name].base.clear (); + custom_type_map_[name].include.clear (); + continue; + } + + String bi (s, pos + 1); + + // See if we've got the base/include part after '/'. + // + pos = bi.find ('/'); + + String type, base, include; + + if (pos != String::npos) + { + type.assign (bi, 0, pos); + String i (bi, pos + 1); + + // See if we've got the include part after '/'. + // + pos = i.find ('/'); + + if (pos != String::npos) + { + base.assign (i, 0, pos); + include.assign (i, pos + 1, String::npos); + } + else + base = i; + } + else + type = bi; + + custom_type_map_[name].type = type; + custom_type_map_[name].base = base; + custom_type_map_[name].include = include; + } + } } protected: @@ -103,6 +180,7 @@ namespace CXX stl (c.stl), detach (c.detach), custom_data_map (c.custom_data_map), + custom_type_map (c.custom_type_map), global_type_names (c.global_type_names) { } @@ -168,10 +246,31 @@ namespace CXX { }; + public: + struct CustomType + { + CustomType (String const& t = L"", + String const& b = L"", + String const& i = L"") + : type (t), base (b), include (i) + { + } + + String type; + String base; + String include; + }; + + typedef + Cult::Containers::Map + CustomTypeMap; + private: SemanticGraph::Path const schema_path_; CustomDataMap custom_data_map_; + CustomTypeMap custom_type_map_; + Cult::Containers::Map global_type_names_; public: @@ -182,6 +281,8 @@ namespace CXX Boolean detach; CustomDataMap& custom_data_map; + CustomTypeMap& custom_type_map; + Cult::Containers::Map& global_type_names; }; @@ -197,6 +298,17 @@ namespace CXX virtual Void traverse (Type& l) { + SemanticGraph::Context& lc (l.context ()); + + // In case of customization use name-base instead of name. + // If name is empty then we are not generating anything. + // + String const& name (lc.count ("name-base") + ? lc.get ("name-base") + : lc.get ("name")); + if (!name) + return; + if (!data_members_) { // Check if this type has custom data. @@ -206,12 +318,6 @@ namespace CXX if (i != custom_data_map.end () && i->second->find (L"") != i->second->end ()) { - SemanticGraph::Context& lc (l.context ()); - - // Use processed name. - // - String const& name (lc.get ("name")); - lc.set (member_set_key, NameSet ()); NameSet& set (lc.get (member_set_key)); set.insert (name); @@ -229,8 +335,6 @@ namespace CXX } else { - SemanticGraph::Context& lc (l.context ()); - // Custom data. // if (lc.count ("cd-name")) @@ -260,12 +364,17 @@ namespace CXX { SemanticGraph::Context& uc (u.context ()); + // In case of customization use name-base instead of name. + // If name is empty then we are not generating anything. + // + String const& name (uc.count ("name-base") + ? uc.get ("name-base") + : uc.get ("name")); + if (!name) + return; + if (!data_members_) { - // Use processed name. - // - String const& name (uc.get ("name")); - uc.set (member_set_key, NameSet ()); NameSet& set (uc.get (member_set_key)); set.insert (name); @@ -1173,6 +1282,15 @@ namespace CXX { SemanticGraph::Context& cc (c.context ()); + // In case of customization use name-base instead of name. + // If name is empty then we are not generating anything. + // + String const& name (cc.count ("name-base") + ? cc.get ("name-base") + : cc.get ("name")); + if (!name) + return; + // Check if this type or any of its nested types have // custom data. // @@ -1183,10 +1301,6 @@ namespace CXX map = i->second.get (); } - // Use processed name. - // - String const& name (cc.get ("name")); - cc.set (member_set_key, NameSet ()); NameSet& member_set (cc.get (member_set_key)); @@ -1207,8 +1321,14 @@ namespace CXX if (!bc.count (member_set_key)) dispatch (b); - NameSet const& bset (bc.get (member_set_key)); - member_set.insert (bset.begin (), bset.end ()); + // We may still not have the set if this type is being + // customized. + // + if (bc.count (member_set_key)) + { + NameSet const& bset (bc.get (member_set_key)); + member_set.insert (bset.begin (), bset.end ()); + } } // Inheritance by restriction from anyType is a special case. @@ -1335,6 +1455,18 @@ namespace CXX assign_data (Type& c) { SemanticGraph::Context& cc (c.context ()); + + // In case of customization use name-base instead of name. + // If name is empty then we are not generating anything. + // + String const& name (cc.count ("name-base") + ? cc.get ("name-base") + : cc.get ("name")); + if (!name) + return; + + // + // Boolean restriction (false); if (c.inherits_p ()) @@ -1421,8 +1553,30 @@ namespace CXX virtual Void traverse (SemanticGraph::Type& t) { - String name (find_name (t.name (), set_)); - t.context ().set ("name", name); + String const& name (t.name ()); + SemanticGraph::Context& tc (t.context ()); + + tc.set ("name", find_name (name, set_)); + + // See if this parser is being customized. + // + CustomTypeMap::ConstIterator i (custom_type_map.find (name)); + + if (i != custom_type_map.end ()) + { + if (i->second.type) + tc.set ("name-typedef", i->second.type); + + // The empty name-base indicates that we don't need to + // generate anything. + // + tc.set ("name-base", i->second.base + ? find_name (i->second.base, set_) + : i->second.base); + + if (i->second.include) + tc.set ("name-include", i->second.include); + } } private: diff --git a/xsde/cxx/hybrid/tree-size-processor.cxx b/xsde/cxx/hybrid/tree-size-processor.cxx index d492b24..a3b2231 100644 --- a/xsde/cxx/hybrid/tree-size-processor.cxx +++ b/xsde/cxx/hybrid/tree-size-processor.cxx @@ -9,9 +9,14 @@ #include #include +#include #include #include +#include + +using std::wcerr; + namespace CXX { namespace Hybrid @@ -20,6 +25,15 @@ namespace CXX { typedef Cult::Containers::Set TypeSet; + + struct CustomType + { + Boolean fixed; + String base; + }; + + typedef Cult::Containers::Map CustomTypeMap; + Boolean test (SemanticGraph::Type& t) { @@ -225,8 +239,14 @@ namespace CXX Traversal::Union, Traversal::Complex { - Type (TypeSet& custom_data, Boolean stl_) - : custom_data_ (custom_data), stl (stl_) + Type (Boolean& valid, + TypeSet& custom_data, + CustomTypeMap& custom_type_map, + Boolean stl_) + : valid_ (valid), + custom_data_ (custom_data), + custom_type_map_ (custom_type_map), + stl (stl_) { } @@ -263,7 +283,9 @@ namespace CXX if (ctx.count ("recurse")) { - set (c, false); + if (!test (c)) + set (c, false); + ctx.set ("recursive", true); // Mark all the types involved in the cycle as recursive. @@ -339,7 +361,35 @@ namespace CXX } private: + Void + set (SemanticGraph::Type& t, Boolean v) + { + // Check if this is a custom type. + // + CustomTypeMap::Iterator i = custom_type_map_.find (t.name ()); + + if (i != custom_type_map_.end ()) + { + if (i->second.base && i->second.fixed && !v) + { + wcerr << t.file () << ":" << t.line () << ":" << t.column () + << ": error: generated base type '" << i->second.base + << "' is variable-length while the custom type is " + << "declared fixed-length" << endl; + + valid_ = false; + } + + Hybrid::set (t, i->second.fixed); + } + else + Hybrid::set (t, v); + } + + private: + Boolean& valid_; TypeSet& custom_data_; + CustomTypeMap& custom_type_map_; Boolean stl; typedef Containers::Vector Path; @@ -751,11 +801,12 @@ namespace CXX } }; - Void + Boolean process_impl (CLI::Options const& ops, SemanticGraph::Schema& tu, SemanticGraph::Path const&) { + Boolean valid (true); Boolean stl (!ops.value ()); // Root schema in the file-per-type mode is just a bunch @@ -826,34 +877,111 @@ namespace CXX } } - Traversal::Schema schema; - Uses uses; + // Prepare a map of types custom types that specify type + // size. + // + CustomTypeMap custom_type_map; + + { + typedef Containers::Vector Vector; + Vector const& v (ops.value ()); - schema >> uses >> schema; + for (Vector::ConstIterator i (v.begin ()), e (v.end ()); + i != e; ++i) + { + String s (*i); - Traversal::Names schema_names; - Traversal::Namespace ns; - Traversal::Names ns_names; - Type type (custom_data_types, stl); + if (s.empty ()) + continue; - schema >> schema_names >> ns >> ns_names >> type; + // Split the string in two parts at the last '='. + // + Size pos (s.rfind ('=')); - // Some twisted schemas do recusive self-inclusion. - // - tu.context ().set ("cxx-hybrid-size-processor-seen", true); + if (pos == String::npos) + continue; - schema.dispatch (tu); + String name (s, 0, pos); + String fb (s, pos + 1); + + pos = fb.find ('/'); + + String flags, base; + + if (pos != String::npos) + { + flags.assign (fb, 0, pos); + + // Skip the type component. + // + pos = fb.find ('/', pos + 1); + + if (pos != String::npos) + { + String b (fb, pos + 1); + + // See if we've got the include component. + // + pos = b.find ('/'); + + if (pos != String::npos) + base.assign (b, 0, pos); + else + base = b; + } + } + else + flags = fb; + + if (!flags) + continue; + + if (flags != L"f" && flags != L"v") + { + wcerr << "error: invalid custom type flag: '" << + flags << "'" << endl; + + valid = false; + } + + custom_type_map[name].base = base; + custom_type_map[name].fixed = (flags == L"f"); + } + } + + if (valid) + { + Traversal::Schema schema; + Uses uses; + + schema >> uses >> schema; + + Traversal::Names schema_names; + Traversal::Namespace ns; + Traversal::Names ns_names; + Type type (valid, custom_data_types, custom_type_map, stl); + + schema >> schema_names >> ns >> ns_names >> type; + + // Some twisted schemas do recusive self-inclusion. + // + tu.context ().set ("cxx-hybrid-size-processor-seen", true); + + schema.dispatch (tu); + } } } + + return valid; } } - Void TreeSizeProcessor:: + Boolean TreeSizeProcessor:: process (CLI::Options const& ops, SemanticGraph::Schema& tu, SemanticGraph::Path const& file) { - process_impl (ops, tu, file); + return process_impl (ops, tu, file); } } } diff --git a/xsde/cxx/hybrid/tree-size-processor.hxx b/xsde/cxx/hybrid/tree-size-processor.hxx index 130451f..d9257a1 100644 --- a/xsde/cxx/hybrid/tree-size-processor.hxx +++ b/xsde/cxx/hybrid/tree-size-processor.hxx @@ -21,7 +21,7 @@ namespace CXX class TreeSizeProcessor { public: - Void + Boolean process (CLI::Options const& options, XSDFrontend::SemanticGraph::Schema&, XSDFrontend::SemanticGraph::Path const& file); diff --git a/xsde/cxx/hybrid/tree-source.cxx b/xsde/cxx/hybrid/tree-source.cxx index d6c3672..6de3e35 100644 --- a/xsde/cxx/hybrid/tree-source.cxx +++ b/xsde/cxx/hybrid/tree-source.cxx @@ -1456,9 +1456,15 @@ namespace CXX virtual Void traverse (Type& c) { - Boolean restriction (restriction_p (c)); + String const& name (ename_custom (c)); + + // We may not need to generate the class if this type is + // being customized. + // + if (!name) + return; - String name (ename (c)); + Boolean restriction (restriction_p (c)); os << "// " << comment (c.name ()) << endl << "//" << endl diff --git a/xsde/xsde.cxx b/xsde/xsde.cxx index acbc5db..97224ca 100644 --- a/xsde/xsde.cxx +++ b/xsde/xsde.cxx @@ -704,7 +704,16 @@ main (Int argc, Char* argv[]) // Calculate type sizes. // if (gen_hybrid) - CXX::Hybrid::Generator::calculate_size (*h_ops, *schema, tu); + { + try + { + CXX::Hybrid::Generator::calculate_size (*h_ops, *schema, tu); + } + catch (CXX::Hybrid::Generator::Failed const&) + { + return 1; // Diagnostic has already been issued. + } + } // Try to rearrange definitions so that there is no forward // inheritance. @@ -913,7 +922,16 @@ main (Int argc, Char* argv[]) // Calculate type sizes. // if (gen_hybrid) - CXX::Hybrid::Generator::calculate_size (*h_ops, *schema, ""); + { + try + { + CXX::Hybrid::Generator::calculate_size (*h_ops, *schema, ""); + } + catch (CXX::Hybrid::Generator::Failed const&) + { + return 1; // Diagnostic has already been issued. + } + } // Normalize and annotate complex content restrictions. // -- cgit v1.1