From a8ce5c380c69539fe0c7c62c397634d9d0c9fde2 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Fri, 18 Dec 2020 18:48:46 +0300 Subject: Switch to build2 --- xsd/cxx/parser/element-validation-source.cxx | 1600 -------------------------- 1 file changed, 1600 deletions(-) delete mode 100644 xsd/cxx/parser/element-validation-source.cxx (limited to 'xsd/cxx/parser/element-validation-source.cxx') diff --git a/xsd/cxx/parser/element-validation-source.cxx b/xsd/cxx/parser/element-validation-source.cxx deleted file mode 100644 index b34b3dd..0000000 --- a/xsd/cxx/parser/element-validation-source.cxx +++ /dev/null @@ -1,1600 +0,0 @@ -// file : xsd/cxx/parser/element-validation-source.cxx -// license : GNU GPL v2 + exceptions; see accompanying LICENSE file - -#include - -#include - -#include -#include - -using namespace std; - -namespace CXX -{ - namespace Parser - { - namespace - { - typedef vector Particles; - - // - // - struct ParticleTest: Traversal::Compositor, - Traversal::Element, - Traversal::Any, - Context - { - ParticleTest (Context& c) - : Context (c) - { - } - - virtual void - traverse (SemanticGraph::Element& e) - { - String const& name (e.name ()); - - if (polymorphic && e.global_p ()) - os << "("; - - if (e.qualified_p () && e.namespace_ ().name ()) - { - String const& ns (e.namespace_ ().name ()); - - os << "n == " << strlit (name) << " &&" << endl - << "ns == " << strlit (ns); - } - else - os << "n == " << strlit (name) << " && ns.empty ()"; - - - // Only a globally-defined element can be a subst-group root. - // - if (polymorphic && e.global_p ()) - { - os << ") ||" << endl - << "::xsd::cxx::parser::substitution_map_instance< " << - char_type << " > ().check (" << endl - << "ns, n, " << strlit (e.namespace_ ().name ()) << - ", " << 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 != " << strlit (ns) << ")"; - } - else - os << "!ns.empty ()"; - } - else if (*i == L"##local") - { - os << "(ns.empty () && !n.empty ())"; - } - else if (*i == L"##targetNamespace") - { - os << "ns == " << strlit (ns); - } - else - { - os << "ns == " << 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 ("prefixes")); - - bool paren (p.size () != 1); - - for (Particles::const_iterator i (p.begin ()), e (p.end ()); - i != e;) - { - if (paren) - os << "("; - - dispatch (**i); - - if (paren) - os << ")"; - - if (++i != e) - os << " ||" << endl; - } - } - }; - - - // Generates particle namespace-name pair. Used to generate - // the _expected_element call. - // - struct ParticleName: Traversal::Compositor, - Traversal::Element, - Traversal::Any, - Context - { - ParticleName (Context& c) - : Context (c) - { - } - - virtual void - traverse (SemanticGraph::Element& e) - { - String ns (e.qualified_p () ? e.namespace_ ().name () : String ()); - os << strlit (ns) << ", " << strlit (e.name ()); - } - - virtual void - traverse (SemanticGraph::Any& a) - { - String const& ns (*a.namespace_begin ()); - os << strlit (ns) << ", " << L << "\"*\""; - } - - virtual void - traverse (SemanticGraph::Compositor& c) - { - Particles const& p (c.context ().get ("prefixes")); - - dispatch (**p.begin ()); - } - }; - - - // Common base for the ParticleIn{All, Choice, Sequence} treversers. - // - struct ParticleInCompositor: 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 (&p)) - { - SemanticGraph::Type& type (e->type ()); - String const& fq_type (fq_name (type)); - bool poly (polymorphic && !anonymous (type)); - - String name, inst, def_parser, map; - - if (e->context ().count("name")) - { - name = ename (*e); - - if (poly) - { - def_parser = emember (*e); - map = emember_map (*e); - inst = "p"; - } - else - inst = L"this->" + emember (*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(ip.first->named ())); - - name = ename (fe); - - if (poly) - { - def_parser = emember (fe); - map = emember_map (fe); - inst = "p"; - } - else - inst = L"this->" + emember (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 << fq_type << "* p = 0;" - << endl - << "if (t == 0 && this->" << def_parser << " != 0)" << endl - << 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 - << 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 - << inst << " = dynamic_cast< " << fq_type << "* > (" << endl - << "this->" << map << "->find (*t));" - << "}" - << "}"; - } - - os << "this->" << complex_base << "::context_.top ()." << - "parser_ = " << inst << ";" - << endl - << "if (" << inst << ")" << endl - << inst << "->pre ();" - << "}" - << "else" // start - << "{"; - - if (poly) - os << fq_type << "* p =" << endl - << "dynamic_cast< " << fq_type << "* > (" << endl - << "this->" << complex_base << "::context_.top ().parser_);" - << endl; - - os << "if (" << inst << ")" - << "{"; - - String const& ret (ret_type (type)); - String const& post (post_name (type)); - - if (ret == L"void") - os << inst << "->" << post << " ();" - << "this->" << name << " ();"; - else - { - // Don't create an lvalue in C++11 (think std::unique_ptr). - // In C++98 we do it for compatibility with older/broken - // compilers (e.g., IBM xlC that needs an lvalue to pass - // std::auto_ptr). - // - if (std == cxx_version::cxx98) - os << arg_type (type) << " tmp (" << inst << "->" << - post << " ());" - << "this->" << name << " (tmp);"; - else - os << "this->" << name << " (" << inst << "->" << - post << " ());"; - } - - 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) - { - size_t state (e.context ().get ("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; - - size_t state (p.context ().get ("state")); - - size_t 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; - - size_t max (c.max ()); - size_t min (c.context ().get ("effective-min")); - size_t n (c.context ().get ("comp-number")); - size_t state (c.context ().get ("state")); - - String func (c.is_a () ? - "choice_" : "sequence_"); - - os << "case " << state << "UL:" << endl - << "{" - << "unsigned long s (~0UL);" - << endl; - - bool first (true); - - for (Compositor::ContainsIterator ci (c.contains_begin ()); - ci != c.contains_end (); ++ci) - { - SemanticGraph::Particle& p (ci->particle ()); - - if (p.is_a () && !c.context ().count ("comp-number")) - continue; // Empty compositor. - - if (!p.context ().count ("prefix")) - break; - - size_t state (p.context ().get ("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, - size_t state, - size_t 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) - { - size_t 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; - - size_t max (c.max ()); - size_t min (c.context ().get ("effective-min")); - size_t n (c.context ().get ("comp-number")); - - String func (c.is_a () ? - "choice_" : "sequence_"); - - os << "case " << state_ << "UL:" << endl - << "{" - << "unsigned long s (~0UL);" - << endl; - - bool first (true); - - for (Compositor::ContainsIterator ci (c.contains_begin ()); - ci != c.contains_end (); ++ci) - { - SemanticGraph::Particle& p (ci->particle ()); - - if (p.is_a () && !c.context ().count ("comp-number")) - continue; // Empty compositor. - - if (!p.context ().count ("prefix")) - break; - - size_t state (p.context ().get ("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: - size_t state_; - String next_state_; - - ParticleName particle_name_; - }; - - - // - // - struct ParticleFunction: Traversal::All, - Traversal::Choice, - Traversal::Sequence, - Context - { - ParticleFunction (Context& c, SemanticGraph::Complex& type) - : Context (c), type_ (type) - { - *this >> contains_particle_ >> *this; - } - - - virtual void - traverse (SemanticGraph::All& a) - { - if (!a.context().count ("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 (ci->particle ())); - String ns (e.qualified_p () ? e.namespace_ ().name () : String ()); - size_t state (e.context ().get ("state")); - - os << "if (count[" << state << "UL] == 0)" << endl - << "this->_expected_element (" << endl - << strlit (ns) << ", " << - 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; - - size_t n (c.context ().get ("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 () && !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; - - size_t n (s.context ().get ("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)" - << "{"; - - size_t state (0); - - for (Compositor::ContainsIterator ci (s.contains_begin ()), - ce (s.contains_end ()); ci != ce;) - { - SemanticGraph::Particle& p (ci->particle ()); - - if (p.is_a () && !p.context().count ("comp-number")) - { - // Empty compositor. - // - ++ci; - continue; - } - - // Find the next state. - // - do - ++ci; - while (ci != ce && - ci->particle ().is_a () && - !ci->particle ().context().count ("comp-number")); - - size_t 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, - Context - { - CompositorPre (Context& c) - : Context (c) - { - } - - 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;"; - } - }; - - - // - // - struct CompositorStartElement: Traversal::All, - Traversal::Compositor, - Context - { - CompositorStartElement (Context& c, SemanticGraph::Complex& type) - : Context (c), type_ (type), - particle_test_ (c), particle_name_ (c) - { - } - - virtual void - traverse (SemanticGraph::All&) - { - // The 'all' state machine reaches the final state only - // on an unknown element, in which case we won't get here - // again (it would be a validation error). Note that 'all' - // compositor cannot contain nested compositors so we don't - // need to re-set vd. - // - os << "all_0 (vd->state, v_all_count_.top (), ns, n, 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; - - size_t max (c.max ()); - size_t min (c.context ().get ("effective-min")); - size_t n (c.context ().get ("comp-number")); - - String func (c.is_a () ? - "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; - - bool 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 () && !c.context ().count ("comp-number")) - continue; // Empty compositor. - - if (!p.context ().count ("prefix")) - break; - - size_t state (p.context ().get ("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, - Context - { - CompositorEndElement (Context& c) - : Context (c) - { - } - - 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; - } - }; - - - // - // - struct CompositorPost: Traversal::All, - Traversal::Compositor, - Context - { - CompositorPost (Context& c) - : Context (c), 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 ("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. - { - size_t min (c.context ().get ("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: - ParticleName particle_name_; - }; - - - // - // - struct Complex: Traversal::Complex, Context - { - Complex (Context& c) - : Context (c) - { - } - - virtual void - traverse (Type& c) - { - // Nothing to generate if we don't have any elements and wildcards. - // - if (!has (c) && - !has_particle (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. - // - bool restriction ( - c.inherits_p () && - c.inherits ().is_a ()); - - 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 ()) - { - 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 ()) - { - 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); - 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); - 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 ()) - { - // 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 ()) - { - // 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); - 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 " << endl - << endl; - - Traversal::Schema schema; - - 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); - } - } -} -- cgit v1.1