diff options
Diffstat (limited to 'libxsd-frontend/xsd-frontend/parser.cxx')
-rw-r--r-- | libxsd-frontend/xsd-frontend/parser.cxx | 1224 |
1 files changed, 631 insertions, 593 deletions
diff --git a/libxsd-frontend/xsd-frontend/parser.cxx b/libxsd-frontend/xsd-frontend/parser.cxx index 901a8d3..6b582ab 100644 --- a/libxsd-frontend/xsd-frontend/parser.cxx +++ b/libxsd-frontend/xsd-frontend/parser.cxx @@ -1,21 +1,23 @@ // file : xsd-frontend/parser.cxx -// author : Boris Kolpackov <boris@codesynthesis.com> -// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// copyright : Copyright (c) 2005-2014 Code Synthesis Tools CC // license : GNU GPL v2 + exceptions; see accompanying LICENSE file -#include <xsd-frontend/types.hxx> -#include <xsd-frontend/parser.hxx> +#include <map> +#include <stack> +#include <vector> +#include <iostream> +#include <sstream> + +#include <cutl/compiler/type-id.hxx> + +#include <xsd-frontend/version.hxx> // Check Xerces-C++ version. #include <xsd-frontend/xml.hxx> +#include <xsd-frontend/parser.hxx> #include <xsd-frontend/schema-dom-parser.hxx> #include <xsd-frontend/semantic-graph.hxx> #include <xsd-frontend/traversal.hxx> -#include <cult/containers/map.hxx> -#include <cult/containers/stack.hxx> -#include <cult/containers/vector.hxx> -#include <cult/rtti/type-id.hxx> - //@@ Do i need this? // #include <xercesc/dom/DOM.hpp> @@ -38,15 +40,9 @@ #include <xercesc/framework/LocalFileInputSource.hpp> #include <xercesc/framework/Wrapper4InputSource.hpp> -#include <iostream> -#include <sstream> -#include <memory> // std::auto_ptr - -using std::wcout; -using std::wcerr; -using std::endl; +using namespace std; -using Cult::RTTI::TypeId; +using cutl::compiler::type_id; namespace XSDFrontend { @@ -55,7 +51,7 @@ namespace XSDFrontend //@@ Port to tracing facility. // - Boolean trace_ = false; + bool trace_ = false; String const xsd = L"http://www.w3.org/2001/XMLSchema"; String const xse = L"http://www.codesynthesis.com/xmlns/xml-schema-extension"; @@ -107,6 +103,43 @@ namespace XSDFrontend String name_; }; + // Trim leading and trailing whitespaces. + // + template <typename C> + StringTemplate<C> + trim (StringTemplate<C> const& s) + { + typedef StringTemplate<C> String; + + size_t size (s.size ()); + + if (size == 0) + return s; + + C const* f (s.c_str ()); + C const* l (f + size); + + C const* of (f); + + while (f < l && + (*f == C (0x20) || *f == C (0x0A) || + *f == C (0x0D) || *f == C (0x09))) + ++f; + + --l; + + C const* ol (l); + + while (l > f && + (*l == C (0x20) || *l == C (0x0A) || + *l == C (0x0D) || *l == C (0x09))) + --l; + + if (f != of || l != ol) + return f <= l ? String (f, l - f + 1) : String (); + else + return s; + } // Name cache. We only support maximum two nodes with the same // name in the cache (e.g., element and type). For (rare) cases @@ -120,9 +153,9 @@ namespace XSDFrontend Nameable* second; }; - typedef Cult::Containers::Map<String, CacheNodes> NodeMap; - typedef Cult::Containers::Map<String, NodeMap> NamespaceMap; - typedef Cult::Containers::Vector<SemanticGraph::Member*> DefaultValues; + typedef std::map<String, CacheNodes> NodeMap; + typedef std::map<String, NodeMap> NamespaceMap; + typedef std::vector<SemanticGraph::Member*> DefaultValues; template <typename X> X& @@ -133,11 +166,11 @@ namespace XSDFrontend { // First check the cache. // - NamespaceMap::Iterator i (cache.find (ns_name)); + NamespaceMap::iterator i (cache.find (ns_name)); if (i != cache.end ()) { - NodeMap::Iterator j (i->second.find (uq_name)); + NodeMap::iterator j (i->second.find (uq_name)); if (j != i->second.end ()) { @@ -188,12 +221,12 @@ namespace XSDFrontend // // - typedef Cult::Containers::Map<String, String> Facets; + typedef std::map<String, String> Facets; - Void + void copy_facets (Restricts& r, Facets const& f) { - for (Facets::ConstIterator i (f.begin ()), e (f.end ()); i != e; ++i) + for (Facets::const_iterator i (f.begin ()), e (f.end ()); i != e; ++i) r.facet_insert (i->first, i->second); } @@ -210,14 +243,14 @@ namespace XSDFrontend String uq_name; }; - typedef Cult::Containers::Vector<UnionMemberType> UnionMemberTypes; + typedef std::vector<UnionMemberType> UnionMemberTypes; // // struct ElementGroupRef { ElementGroupRef (String const& uq_name_, String const& ns_name_, - UnsignedLong min_, UnsignedLong max_, + unsigned long min_, unsigned long max_, Compositor& compositor, Scope& scope) : uq_name (uq_name_), ns_name (ns_name_), min (min_), max (max_) @@ -232,7 +265,7 @@ namespace XSDFrontend } ElementGroupRef (String const& uq_name_, String const& ns_name_, - UnsignedLong min_, UnsignedLong max_, + unsigned long min_, unsigned long max_, Scope& scope) : uq_name (uq_name_), ns_name (ns_name_), min (min_), max (max_) @@ -244,13 +277,12 @@ namespace XSDFrontend String uq_name; String ns_name; - UnsignedLong min, max; + unsigned long min, max; Compositor::ContainsIterator contains_pos; Scope::NamesIterator names_pos; }; - typedef Cult::Containers::Vector<ElementGroupRef> ElementGroupRefs; - + typedef std::vector<ElementGroupRef> ElementGroupRefs; // // @@ -271,7 +303,7 @@ namespace XSDFrontend Scope::NamesIterator names_pos; }; - typedef Cult::Containers::Vector<AttributeGroupRef> AttributeGroupRefs; + typedef std::vector<AttributeGroupRef> AttributeGroupRefs; // @@ -290,14 +322,14 @@ namespace XSDFrontend } template <typename E> - Void + void add_edge_left (E& e) { node_.add_edge_left (e, arg_); } template <typename E> - Void + void add_edge_right (E& e) { node_.add_edge_right (e, arg_); @@ -324,7 +356,7 @@ namespace XSDFrontend Traversal::Compositor { Resolver (Schema& s, - Boolean& valid, + bool& valid, NamespaceMap& cache, DefaultValues& default_values) : s_ (s), @@ -335,7 +367,7 @@ namespace XSDFrontend *this >> contains_compositor >> *this; } - Void + void traverse (SemanticGraph::Attribute& a) { // Avoid traversing attribute more than once. @@ -348,13 +380,13 @@ namespace XSDFrontend } } - Void + void traverse (SemanticGraph::Element& e) { resolve_element (e); } - Void + void resolve_element (SemanticGraph::Element& e) { // Avoid resolving element more than once. @@ -383,6 +415,15 @@ namespace XSDFrontend resolve<SemanticGraph::Element> (ns_name, uq_name, s_, cache_)); s_.new_edge<Substitutes> (e, root); + + // See if we need to derive the type of this element from the + // one it substitutes. + // + if (!e.typed_p ()) + { + resolve_member (root); // Make sure the type is resolved. + s_.new_edge<Belongs> (e, root.type ()); + } } catch (NotNamespace const& ex) { @@ -405,7 +446,7 @@ namespace XSDFrontend } } - Void + void resolve_member (SemanticGraph::Member& m) { using SemanticGraph::Member; @@ -437,8 +478,15 @@ namespace XSDFrontend m.context ().remove ("instance-ns-name"); m.context ().remove ("instance-uq-name"); - - Member& ref (resolve<Member> (ns_name, uq_name, s_, cache_)); + // Resolve the name to the same type. It is legal to have + // an element and an attribute with the same name. + // + Member& ref ( + m.is_a<Element> () + ? static_cast<Member&> ( + resolve<Element> (ns_name, uq_name, s_, cache_)) + : static_cast<Member&> ( + resolve<Attribute> (ns_name, uq_name, s_, cache_))); // Make sure the referenced member is fully resolved. // @@ Substitutes edge won't be resolved. @@ -509,19 +557,10 @@ namespace XSDFrontend if (!m.annotated_p () && ref.annotated_p ()) s_.new_edge<Annotates> (ref.annotation (), m); - // Type info. + // Type info. Can be missing for a substitution group member. // if (ref.typed_p ()) s_.new_edge<Belongs> (m, ref.type ()); - else - { - if (valid_) - { - wcerr << "ice: referenced instance '" << ns_name << "#" - << uq_name << "' is not typed" << endl; - abort (); - } - } } } catch (NotNamespace const& ex) @@ -544,19 +583,19 @@ namespace XSDFrontend } } - Void + void traverse (SemanticGraph::Fundamental::IdRef& i) { ref_type (i); } - Void + void traverse (SemanticGraph::Fundamental::IdRefs& i) { ref_type (i); } - Void + void ref_type (SemanticGraph::Specialization& s) { if (s.context ().count ("type-ns-name")) @@ -584,7 +623,7 @@ namespace XSDFrontend } } - Void + void traverse (SemanticGraph::List& l) { if (l.context ().count ("type-ns-name")) @@ -614,7 +653,7 @@ namespace XSDFrontend Traversal::List::traverse (l); } - Void + void traverse (SemanticGraph::Union& u) { using SemanticGraph::Union; @@ -627,7 +666,7 @@ namespace XSDFrontend // Process it backwards so that we can just insert each // edge in the front. // - for (UnionMemberTypes::ConstReverseIterator i (m.rbegin ()); + for (UnionMemberTypes::const_reverse_iterator i (m.rbegin ()); i != m.rend (); i++) { try @@ -655,7 +694,7 @@ namespace XSDFrontend Traversal::Union::traverse (u); } - Void + void traverse (SemanticGraph::Complex& c) { // Avoid traversing complex type more than once. @@ -669,11 +708,9 @@ namespace XSDFrontend // if (c.context ().count ("type-ns-name")) { - using Cult::RTTI::TypeId; - String ns_name (c.context ().get<String> ("type-ns-name")); String uq_name (c.context ().get<String> ("type-uq-name")); - TypeId edge_id (c.context ().get<TypeId> ("edge-type-id")); + type_id edge_id (c.context ().get<type_id> ("edge-type-id")); c.context ().remove ("type-ns-name"); c.context ().remove ("type-uq-name"); @@ -725,7 +762,7 @@ namespace XSDFrontend // Handle refs from last to first so that multiple insertions // to an empty list (always front) end up in proper order. // - for (AttributeGroupRefs::ReverseIterator i (refs.rbegin ()); + for (AttributeGroupRefs::reverse_iterator i (refs.rbegin ()); i != refs.rend (); ++i) { clone_attribute_group_content (*i, c); @@ -756,7 +793,7 @@ namespace XSDFrontend Traversal::Complex::traverse (c); } - Void + void traverse (SemanticGraph::Enumeration& e) { // Resolve base type if any. @@ -797,7 +834,7 @@ namespace XSDFrontend Traversal::Enumeration::traverse (e); } - Void + void traverse (SemanticGraph::ElementGroup& g) { // Avoid traversing groups more than once. @@ -818,7 +855,7 @@ namespace XSDFrontend // We need a "shallow" resolve to break possible recursing: // group->element->complexType->group. // - Void + void resolve_element_group (SemanticGraph::ElementGroup& g) { using SemanticGraph::Scope; @@ -841,7 +878,7 @@ namespace XSDFrontend } } - Void + void traverse (SemanticGraph::AttributeGroup& g) { // Avoid traversing groups more than once. @@ -861,7 +898,7 @@ namespace XSDFrontend // Handle refs from last to first so that multiple insertions // to an empty list (always front) end up in proper order. // - for (AttributeGroupRefs::ReverseIterator i (refs.rbegin ()); + for (AttributeGroupRefs::reverse_iterator i (refs.rbegin ()); i != refs.rend (); ++i) { clone_attribute_group_content (*i, g); @@ -873,7 +910,7 @@ namespace XSDFrontend Traversal::AttributeGroup::traverse (g); } - Void + void traverse (SemanticGraph::Compositor& c) { using SemanticGraph::Compositor; @@ -890,7 +927,7 @@ namespace XSDFrontend // Handle refs from last to first so that multiple insertions // to an empty list (always front) end up in proper order. // - for (ElementGroupRefs::ReverseIterator i (refs.rbegin ()); + for (ElementGroupRefs::reverse_iterator i (refs.rbegin ()); i != refs.rend (); ++i) { // Find our scope. @@ -1051,8 +1088,8 @@ namespace XSDFrontend // order to put it into the scope. Note that we cannot reuse // the name from the prototype. - UnsignedLong count; - FrontendElements::Context& ctx (scope.context ()); + unsigned long count; + SemanticGraph::Context& ctx (scope.context ()); if (!ctx.count ("any-name-count")) { @@ -1060,9 +1097,9 @@ namespace XSDFrontend ctx.set ("any-name-count", count); } else - count = ++(ctx.get<UnsignedLong> ("any-name-count")); + count = ++(ctx.get<unsigned long> ("any-name-count")); - std::basic_ostringstream<WideChar> os; + std::basic_ostringstream<wchar_t> os; os << "any #" << count; NodeArgs<Scope, Scope::NamesIterator> na (scope, pos); @@ -1126,7 +1163,7 @@ namespace XSDFrontend return copy; } - Void + void clone_attribute_group_content (AttributeGroupRef& ref, SemanticGraph::Scope& s) { @@ -1213,8 +1250,8 @@ namespace XSDFrontend // one in order to put it into the scope. Note that we cannot // reuse the name from the attribute group. - UnsignedLong count; - FrontendElements::Context& ctx (s.context ()); + unsigned long count; + SemanticGraph::Context& ctx (s.context ()); if (!ctx.count ("any-attribute-name-count")) { @@ -1222,9 +1259,9 @@ namespace XSDFrontend ctx.set ("any-attribute-name-count", count); } else - count = ++(ctx.get<UnsignedLong> ("any-attribute-name-count")); + count = ++(ctx.get<unsigned long> ("any-attribute-name-count")); - std::basic_ostringstream<WideChar> os; + std::basic_ostringstream<wchar_t> os; os << "any-attribute #" << count; NodeArgs<Scope, Scope::NamesIterator> na (s, pos); @@ -1256,7 +1293,7 @@ namespace XSDFrontend private: Schema& s_; - Boolean& valid_; + bool& valid_; NamespaceMap& cache_; DefaultValues& default_values_; @@ -1266,67 +1303,54 @@ namespace XSDFrontend }; } - // - // - struct FilePathComparator - { - Boolean - operator () (SemanticGraph::Path const& x, - SemanticGraph::Path const& y) const - { -#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 - return x.native_file_string () < y.native_file_string (); -#else - return x.string () < y.string (); -#endif - } - }; - // Parser::Impl // - class Parser::Impl: public NonCopyable + class Parser::Impl { + Impl (Impl const&); + Impl& operator= (Impl const&); + public: ~Impl (); - Impl (Boolean proper_restriction, - Boolean multiple_imports, - Boolean full_schema_check, + Impl (bool proper_restriction, + bool multiple_imports, + bool full_schema_check, LocationTranslator*, const WarningSet*); - Evptr<Schema> + auto_ptr<Schema> parse (Path const&); - Evptr<Schema> + auto_ptr<Schema> parse (Paths const&); - Evptr<Schema> + auto_ptr<Schema> xml_schema (Path const&); private: - Void + void fill_xml_schema (Schema&, Path const&); private: XML::AutoPtr<Xerces::DOMDocument> - dom (SemanticGraph::Path const&, Boolean validate); + dom (SemanticGraph::Path const&, bool validate); - Void + void schema (XML::Element const&); SemanticGraph::Annotation* - annotation (Boolean process); + annotation (bool process); - Void + void import (XML::Element const&); - Void + void include (XML::Element const&); - Void - element_group (XML::Element const&, Boolean in_compositor); + void + element_group (XML::Element const&, bool in_compositor); SemanticGraph::Type* simple_type (XML::Element const&); @@ -1340,7 +1364,7 @@ namespace XSDFrontend SemanticGraph::Type* restriction (XML::Element const& r, XML::Element const& type); - Void + void enumeration (XML::Element const&); SemanticGraph::Type* @@ -1350,47 +1374,47 @@ namespace XSDFrontend all (XML::Element const&); Choice* - choice (XML::Element const&, Boolean in_compositor); + choice (XML::Element const&, bool in_compositor); Sequence* - sequence (XML::Element const&, Boolean in_compositor); + sequence (XML::Element const&, bool in_compositor); - Void + void simple_content (XML::Element const&); - Void + void complex_content (XML::Element const&, Complex&); - Void + void simple_content_extension (XML::Element const&); - Void + void simple_content_restriction (XML::Element const&); - Void + void complex_content_extension (XML::Element const&, Complex&); - Void + void complex_content_restriction (XML::Element const&, Complex&); - Void - element (XML::Element const&, Boolean global); + void + element (XML::Element const&, bool global); - Void - attribute (XML::Element const&, Boolean global); + void + attribute (XML::Element const&, bool global); - Void + void attribute_group (XML::Element const&); - Void + void any (XML::Element const&); - Void + void any_attribute (XML::Element const&); private: - Boolean - is_disabled (Char const* warning) + bool + is_disabled (char const* warning) { return disabled_warnings_all_ || (disabled_warnings_ && @@ -1398,10 +1422,10 @@ namespace XSDFrontend } private: - Boolean + bool more () const { - Iterator const& it (iteration_state_.top ()); + iterator const& it (iteration_state_.top ()); return it.l_->getLength () > it.i_; } @@ -1409,41 +1433,41 @@ namespace XSDFrontend XML::Element next () { - Iterator& it (iteration_state_.top ()); + iterator& it (iteration_state_.top ()); return XML::Element ( dynamic_cast<Xerces::DOMElement*> (it.l_->item (it.i_++))); } - Void + void prev () { - Iterator& it (iteration_state_.top ()); + iterator& it (iteration_state_.top ()); if (it.i_) --it.i_; } - Void + void push (XML::Element const& e) { iteration_state_.push (e.dom_element ()); } - Void + void pop () { iteration_state_.pop (); } private: - Void + void push_scope (SemanticGraph::Scope& s) { scope_stack_.push (&s); } - Void + void pop_scope () { scope_stack_.pop (); @@ -1456,13 +1480,13 @@ namespace XSDFrontend } private: - Void + void push_compositor (SemanticGraph::Compositor& c) { compositor_stack_.push (&c); } - Void + void pop_compositor () { assert (!compositor_stack_.empty ()); @@ -1477,30 +1501,32 @@ namespace XSDFrontend } private: - UnsignedLong + static unsigned long const unbounded = ~static_cast<unsigned long> (0); + + unsigned long parse_min (String const& m) { if (m.empty ()) return 1; - UnsignedLong v; - std::basic_istringstream<WideChar> is (m); + unsigned long v; + std::basic_istringstream<wchar_t> is (m); is >> v; return v; } - UnsignedLong + unsigned long parse_max (String const& m) { if (m.empty ()) return 1; if (m == L"unbounded") - return 0; + return unbounded; - UnsignedLong v; - std::basic_istringstream<WideChar> is (m); + unsigned long v; + std::basic_istringstream<wchar_t> is (m); is >> v; return v; @@ -1590,32 +1616,32 @@ namespace XSDFrontend private: XML::PtrVector<Xerces::DOMDocument>* dom_docs_; - struct Iterator + struct iterator { - Iterator (Xerces::DOMElement* e) + iterator (Xerces::DOMElement* e) : l_ (e->getChildNodes ()), i_ (0) { } Xerces::DOMNodeList* l_; - Size i_; + size_t i_; }; - Cult::Containers::Stack<Iterator> iteration_state_; + std::stack<iterator> iteration_state_; SemanticGraph::Schema* s_; // root schema file SemanticGraph::Schema* cur_; // current schema file - Boolean cur_chameleon_; // whethere cur_ is chameleon + bool cur_chameleon_; // whethere cur_ is chameleon SemanticGraph::Schema* xml_schema_; // XML Schema file SemanticGraph::Path xml_schema_path_; // // - Cult::Containers::Stack<SemanticGraph::Scope*> scope_stack_; + std::stack<SemanticGraph::Scope*> scope_stack_; // // - Cult::Containers::Stack<SemanticGraph::Compositor*> compositor_stack_; + std::stack<SemanticGraph::Compositor*> compositor_stack_; // Map of absolute file path and namespace pair to a Schema node. @@ -1628,18 +1654,10 @@ namespace XSDFrontend } - friend Boolean + friend bool operator< (SchemaId const& x, SchemaId const& y) { -#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 - return x.path_.native_file_string () < y.path_.native_file_string () - || (x.path_.native_file_string () == y.path_.native_file_string () - && x.ns_ < y.ns_); -#else - return x.path_.string () < y.path_.string () - || (x.path_.string () == y.path_.string () - && x.ns_ < y.ns_); -#endif + return x.path_ < y.path_ || (x.path_ == y.path_ && x.ns_ < y.ns_); } private: @@ -1648,20 +1666,33 @@ namespace XSDFrontend }; - typedef - Cult::Containers::Map<SchemaId, SemanticGraph::Schema*> - SchemaMap; - + typedef std::map<SchemaId, SemanticGraph::Schema*> SchemaMap; SchemaMap schema_map_; // Path stack for diagnostic. // - Cult::Containers::Stack<SemanticGraph::Path> file_stack_; + struct PathPair + { + PathPair (SemanticGraph::Path const& r, SemanticGraph::Path const& a) + : rel (r), abs (a) + { + } + + SemanticGraph::Path rel, abs; + }; + + std::stack<PathPair> file_stack_; SemanticGraph::Path const& file () { - return file_stack_.top (); + return file_stack_.top ().rel; + } + + SemanticGraph::Path const& + abs_file () + { + return file_stack_.top ().abs; } // Members with default/fixed values (needed for QName handling). @@ -1669,26 +1700,26 @@ namespace XSDFrontend DefaultValues default_values_; private: - Boolean qualify_attribute_; - Boolean qualify_element_; + bool qualify_attribute_; + bool qualify_element_; - Boolean valid_; + bool valid_; - Boolean proper_restriction_; - Boolean multiple_imports_; - Boolean full_schema_check_; + bool proper_restriction_; + bool multiple_imports_; + bool full_schema_check_; LocationTranslator* loc_translator_; const WarningSet* disabled_warnings_; - Boolean disabled_warnings_all_; + bool disabled_warnings_all_; NamespaceMap* cache_; }; Parser::Impl:: - Impl (Boolean proper_restriction, - Boolean multiple_imports, - Boolean full_schema_check, + Impl (bool proper_restriction, + bool multiple_imports, + bool full_schema_check, LocationTranslator* t, const WarningSet* dw) : s_ (0), @@ -1730,7 +1761,7 @@ namespace XSDFrontend return node; } - Void Parser::Impl:: + void Parser::Impl:: fill_xml_schema (Schema& s, Path const& path) { Namespace& ns (s.new_node<Namespace> (path, 1, 1)); @@ -1829,12 +1860,12 @@ namespace XSDFrontend } - Evptr<Schema> Parser::Impl:: + auto_ptr<Schema> Parser::Impl:: xml_schema (Path const& tu) { valid_ = true; - Evptr<Schema> rs (new Schema (tu, 1, 1)); + auto_ptr<Schema> rs (new Schema (tu, 1, 1)); fill_xml_schema (*rs, tu); if (!valid_) @@ -1842,7 +1873,7 @@ namespace XSDFrontend return rs; } - Evptr<Schema> Parser::Impl:: + auto_ptr<Schema> Parser::Impl:: parse (Path const& tu) { valid_ = true; @@ -1861,12 +1892,12 @@ namespace XSDFrontend throw InvalidSchema (); XML::Element root (d->getDocumentElement ()); - String ns (root["targetNamespace"]); + String ns (trim (root["targetNamespace"])); if (trace_) wcout << "target namespace: " << ns << endl; - Evptr<Schema> rs (new Schema (tu, root.line (), root.column ())); + auto_ptr<Schema> rs (new Schema (tu, root.line (), root.column ())); // Implied schema with fundamental types. // @@ -1878,16 +1909,18 @@ namespace XSDFrontend // Parse. // { - // Enter the file into schema_map_. + // Enter the file into schema_map_. Do normalize() before + // complete() to avoid hitting system path limits with '..' + // directories. // - Path abs_path (system_complete (tu)); - abs_path.normalize (); + Path abs_path (tu); + abs_path.normalize ().complete (); schema_map_[SchemaId (abs_path, ns)] = rs.get (); rs->context ().set ("absolute-path", abs_path); s_ = cur_ = rs.get (); { - file_stack_.push (tu); + file_stack_.push (PathPair (tu, abs_path)); { push_scope ( @@ -1919,7 +1952,7 @@ namespace XSDFrontend struct Uses: Traversal::Uses { - virtual Void + virtual void traverse (Type& u) { Schema& s (u.schema ()); @@ -1945,24 +1978,24 @@ namespace XSDFrontend Traversal::Element, Traversal::Member { - AnonymousMember (Traversal::NodeDispatcherBase& d) + AnonymousMember (Traversal::NodeDispatcher& d) { belongs_.node_traverser (d); } - virtual Void + virtual void traverse (SemanticGraph::Attribute& a) { traverse_member (a); } - virtual Void + virtual void traverse (SemanticGraph::Element& e) { traverse_member (e); } - Void + void traverse_member (SemanticGraph::Member& m) { if (m.typed_p () && @@ -1983,12 +2016,12 @@ namespace XSDFrontend struct AnonymousBase: Traversal::Type { - AnonymousBase (Traversal::NodeDispatcherBase& d) + AnonymousBase (Traversal::NodeDispatcher& d) : base_ (d) { } - virtual Void + virtual void traverse (SemanticGraph::Type& t) { if (!t.named_p ()) @@ -1996,7 +2029,7 @@ namespace XSDFrontend } private: - Traversal::NodeDispatcherBase& base_; + Traversal::NodeDispatcher& base_; } anonymous_base (resolver); ns_names >> resolver; @@ -2020,7 +2053,7 @@ namespace XSDFrontend // if (valid_) { - for (DefaultValues::ConstIterator i (default_values_.begin ()), + for (DefaultValues::const_iterator i (default_values_.begin ()), e (default_values_.end ()); i != e; ++i) { SemanticGraph::Member& m (**i); @@ -2068,7 +2101,7 @@ namespace XSDFrontend return rs; } - Evptr<Schema> Parser::Impl:: + auto_ptr<Schema> Parser::Impl:: parse (Paths const& paths) { valid_ = true; @@ -2081,7 +2114,7 @@ namespace XSDFrontend NamespaceMap cache; cache_ = &cache; - Evptr<Schema> rs (new Schema ("", 0, 0)); + auto_ptr<Schema> rs (new Schema (Path (), 0, 0)); // Implied schema with fundamental types. // @@ -2094,7 +2127,7 @@ namespace XSDFrontend // s_ = rs.get (); - for (Paths::ConstIterator i (paths.begin ()); i != paths.end (); ++i) + for (Paths::const_iterator i (paths.begin ()); i != paths.end (); ++i) { Path const& tu (*i); XML::AutoPtr<Xerces::DOMDocument> d (dom (tu, true)); @@ -2103,15 +2136,17 @@ namespace XSDFrontend throw InvalidSchema (); XML::Element root (d->getDocumentElement ()); - String ns (root["targetNamespace"]); + String ns (trim (root["targetNamespace"])); if (trace_) wcout << "target namespace: " << ns << endl; - // Check if we already have this schema. + // Check if we already have this schema. Do normalize() before + // complete() to avoid hitting system path limits with '..' + // directories. // - Path abs_path (system_complete (tu)); - abs_path.normalize (); + Path abs_path (tu); + abs_path.normalize ().complete (); SchemaId schema_id (abs_path, ns); if (schema_map_.find (schema_id) != schema_map_.end ()) @@ -2129,7 +2164,7 @@ namespace XSDFrontend cur_ = &s; { - file_stack_.push (tu); + file_stack_.push (PathPair (tu, abs_path)); { push_scope ( @@ -2166,7 +2201,7 @@ namespace XSDFrontend struct Uses: Traversal::Uses { - virtual Void + virtual void traverse (Type& u) { Schema& s (u.schema ()); @@ -2192,24 +2227,24 @@ namespace XSDFrontend Traversal::Element, Traversal::Member { - AnonymousMember (Traversal::NodeDispatcherBase& d) + AnonymousMember (Traversal::NodeDispatcher& d) { belongs_.node_traverser (d); } - virtual Void + virtual void traverse (SemanticGraph::Attribute& a) { traverse_member (a); } - virtual Void + virtual void traverse (SemanticGraph::Element& e) { traverse_member (e); } - virtual Void + virtual void traverse_member (SemanticGraph::Member& m) { if (m.typed_p () && @@ -2230,12 +2265,12 @@ namespace XSDFrontend struct AnonymousBase: Traversal::Type { - AnonymousBase (Traversal::NodeDispatcherBase& d) + AnonymousBase (Traversal::NodeDispatcher& d) : base_ (d) { } - virtual Void + virtual void traverse (SemanticGraph::Type& t) { if (!t.named_p ()) @@ -2243,7 +2278,7 @@ namespace XSDFrontend } private: - Traversal::NodeDispatcherBase& base_; + Traversal::NodeDispatcher& base_; } anonymous_base (resolver); ns_names >> resolver; @@ -2267,7 +2302,7 @@ namespace XSDFrontend // if (valid_) { - for (DefaultValues::ConstIterator i (default_values_.begin ()), + for (DefaultValues::const_iterator i (default_values_.begin ()), e (default_values_.end ()); i != e; ++i) { SemanticGraph::Member& m (**i); @@ -2315,17 +2350,21 @@ namespace XSDFrontend return rs; } - Void Parser::Impl:: + void Parser::Impl:: schema (XML::Element const& s) { - Boolean old_qa (qualify_attribute_); - Boolean old_qe (qualify_element_); + bool old_qa (qualify_attribute_); + bool old_qe (qualify_element_); - if (String af = s["attributeFormDefault"]) + if (String af = trim (s["attributeFormDefault"])) qualify_attribute_ = af == L"qualified"; + else + qualify_attribute_ = false; - if (String ef = s["elementFormDefault"]) + if (String ef = trim (s["elementFormDefault"])) qualify_element_ = ef == L"qualified"; + else + qualify_element_ = false; push (s); @@ -2367,52 +2406,43 @@ namespace XSDFrontend qualify_element_ = old_qe; } - Void Parser::Impl:: + void Parser::Impl:: import (XML::Element const& i) { NarrowString loc ( - XML::transcode_to_narrow ( - i.dom_element ()->getAttribute ( - XML::XMLChString ("schemaLocation").c_str ()))); + trim ( + XML::transcode_to_narrow ( + i.dom_element ()->getAttribute ( + XML::XMLChString ("schemaLocation").c_str ())))); if (loc_translator_) loc = loc_translator_->translate (loc); + String ins (trim (i["namespace"])); + // Ignore empty <import>. // - if (!loc && !i["namespace"]) + if (!loc && !ins) return; Path path, rel_path, abs_path; try { -#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 - try - { - path = Path (loc); - } - catch (InvalidPath const&) - { - // Retry as a native path. - // - path = Path (loc, boost::filesystem::native); - } -#else - // The new ABI does not have a fallback native representation - path = Path (loc.c_str()); -#endif + path = Path (loc); - if (path.is_complete ()) + if (path.absolute ()) { abs_path = rel_path = path; + abs_path.normalize (); } else { - rel_path = file ().branch_path () / path; - abs_path = system_complete (rel_path); + // Do normalize() before complete() to avoid hitting system path + // limits with '..' directories. + // + abs_path = rel_path = file ().directory () / path; + abs_path.normalize ().complete (); } - - abs_path.normalize (); } catch (InvalidPath const&) { @@ -2424,7 +2454,7 @@ namespace XSDFrontend return; } - SchemaId schema_id (abs_path, i["namespace"]); + SchemaId schema_id (abs_path, ins); if (schema_map_.find (schema_id) != schema_map_.end ()) { @@ -2438,7 +2468,7 @@ namespace XSDFrontend if (XML::AutoPtr<Xerces::DOMDocument> d = dom (abs_path, false)) { XML::Element r (d->getDocumentElement ()); - String ns (r["targetNamespace"]); + String ns (trim (r["targetNamespace"])); if (trace_) wcout << "target namespace: " << ns << endl; @@ -2451,12 +2481,12 @@ namespace XSDFrontend s.context ().set ("absolute-path", abs_path); Schema* old_cur (cur_); - Boolean old_cur_chameleon (cur_chameleon_); + bool old_cur_chameleon (cur_chameleon_); cur_ = &s; cur_chameleon_ = false; { - file_stack_.push (rel_path); + file_stack_.push (PathPair (rel_path, abs_path)); { push_scope ( @@ -2480,13 +2510,14 @@ namespace XSDFrontend } } - Void Parser::Impl:: + void Parser::Impl:: include (XML::Element const& i) { NarrowString loc ( - XML::transcode_to_narrow ( - i.dom_element ()->getAttribute ( - XML::XMLChString ("schemaLocation").c_str ()))); + trim ( + XML::transcode_to_narrow ( + i.dom_element ()->getAttribute ( + XML::XMLChString ("schemaLocation").c_str ())))); if (loc_translator_) loc = loc_translator_->translate (loc); @@ -2494,33 +2525,21 @@ namespace XSDFrontend Path path, rel_path, abs_path; try { -#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 - try - { - path = Path (loc); - } - catch (InvalidPath const&) - { - // Retry as a native path. - // - path = Path (loc, boost::filesystem::native); - } -#else - // The new API does not have a fallback native representation. - path = Path (loc.c_str()); -#endif + path = Path (loc); - if (path.is_complete ()) + if (path.absolute ()) { abs_path = rel_path = path; + abs_path.normalize (); } else { - rel_path = file ().branch_path () / path; - abs_path = system_complete (rel_path); + // Do normalize() before complete() to avoid hitting system path + // limits with '..' directories. + // + abs_path = rel_path = file ().directory () / path; + abs_path.normalize ().complete (); } - - abs_path.normalize (); } catch (InvalidPath const&) { @@ -2559,7 +2578,7 @@ namespace XSDFrontend if (XML::AutoPtr<Xerces::DOMDocument> d = dom (abs_path, false)) { XML::Element r (d->getDocumentElement ()); - String ns (r["targetNamespace"]), cur_ns; + String ns (trim (r["targetNamespace"])), cur_ns; Schema& s (s_->new_node<Schema> (rel_path, r.line (), r.column ())); s_->new_edge<Implies> (s, *xml_schema_, xml_schema_path_); @@ -2567,7 +2586,7 @@ namespace XSDFrontend schema_map_[schema_id] = &s; s.context ().set ("absolute-path", abs_path); - Boolean chameleon (false); + bool chameleon (false); if (ns.empty () && !(cur_ns = (cur_->names_begin ())->name ()).empty ()) { @@ -2587,12 +2606,12 @@ namespace XSDFrontend wcout << "target namespace: " << ns << endl; Schema* old_cur (cur_); - Boolean old_cur_chameleon (cur_chameleon_); + bool old_cur_chameleon (cur_chameleon_); cur_ = &s; cur_chameleon_ = chameleon; { - file_stack_.push (rel_path); + file_stack_.push (PathPair (rel_path, abs_path)); { push_scope ( @@ -2616,10 +2635,10 @@ namespace XSDFrontend } } - Void Parser::Impl:: - element_group (XML::Element const& g, Boolean in_compositor) + void Parser::Impl:: + element_group (XML::Element const& g, bool in_compositor) { - if (String name = g["name"]) + if (String name = trim (g["name"])) { ElementGroup& group ( s_->new_node<ElementGroup> (file (), g.line (), g.column ())); @@ -2659,7 +2678,7 @@ namespace XSDFrontend pop (); pop_scope (); } - else if (String ref = g["ref"]) + else if (String ref = trim (g["ref"])) { if (trace_) wcout << "element-group-ref " << ref << endl; @@ -2681,10 +2700,15 @@ namespace XSDFrontend { Compositor& c (compositor ()); + unsigned long min (parse_min (trim (g["minOccurs"]))); + unsigned long max (parse_max (trim (g["maxOccurs"]))); + ElementGroupRef ref ( uq_name, ns_name, - parse_min (g["minOccurs"]), parse_max (g["maxOccurs"]), - c, scope ()); + min, + max == unbounded ? 0 : max, + c, + scope ()); if (!c.context ().count ("element-group-refs")) c.context ().set ("element-group-refs", ElementGroupRefs ()); @@ -2699,10 +2723,11 @@ namespace XSDFrontend Scope& s (scope ()); + unsigned long min (parse_min (trim (g["minOccurs"]))); + unsigned long max (parse_max (trim (g["maxOccurs"]))); + ElementGroupRef ref ( - uq_name, ns_name, - parse_min (g["minOccurs"]), parse_max (g["maxOccurs"]), - s); + uq_name, ns_name, min, max == unbounded ? 0 : max, s); s.context ().set ("element-group-ref", ref); } @@ -2782,7 +2807,7 @@ namespace XSDFrontend List& node (s_->new_node<List> (file (), t.line (), t.column ())); - if (String item_type = l["itemType"]) + if (String item_type = trim (l["itemType"])) { if (trace_) wcout << "item type: " << fq_name (l, item_type) << endl; @@ -2832,7 +2857,7 @@ namespace XSDFrontend pop (); } - if (String name = t["name"]) + if (String name = trim (t["name"])) s_->new_edge<Names> (scope (), node, name); return &node; @@ -2846,8 +2871,8 @@ namespace XSDFrontend // Find first non-space character. // - Size - find_ns (const WideChar* s, Size size, Size pos) + size_t + find_ns (const wchar_t* s, size_t size, size_t pos) { while (pos < size && (s[pos] == 0x20 || // space @@ -2861,8 +2886,8 @@ namespace XSDFrontend // Find first space character. // - Size - find_s (const WideChar* s, Size size, Size pos) + size_t + find_s (const wchar_t* s, size_t size, size_t pos) { while (pos < size && s[pos] != 0x20 && // space @@ -2883,26 +2908,26 @@ namespace XSDFrontend Union& node (s_->new_node<Union> (file (), t.line (), t.column ())); - Boolean has_members (false); + bool has_members (false); - if (String members = u["memberTypes"]) + if (String members = trim (u["memberTypes"])) { // Don't bother trying to resolve member types at this point // since the order is important so we would have to insert // the late resolutions into specific places. It is simpler // to just do the whole resolution later. // - const WideChar* data (members.c_str ()); - Size size (members.size ()); + const wchar_t* data (members.c_str ()); + size_t size (members.size ()); UnionMemberTypes* m (0); // Traverse the type list while logically collapsing spaces. // - for (Size i (find_ns (data, size, 0)); i != String::npos;) + for (size_t i (find_ns (data, size, 0)); i != String::npos;) { String s; - Size j (find_s (data, size, i)); + size_t j (find_s (data, size, i)); if (j != String::npos) { @@ -2985,7 +3010,7 @@ namespace XSDFrontend valid_ = false; } - if (String name = t["name"]) + if (String name = trim (t["name"])) s_->new_edge<Names> (scope (), node, name); return &node; @@ -2994,7 +3019,7 @@ namespace XSDFrontend Type* Parser::Impl:: restriction (XML::Element const& r, XML::Element const& t) { - String base (r["base"]); + String base (trim (r["base"])); Type* base_type (0); if (base) @@ -3009,7 +3034,7 @@ namespace XSDFrontend annotation (false); - Boolean enum_ (false); + bool enum_ (false); if (!base) { @@ -3051,6 +3076,7 @@ namespace XSDFrontend Facets facets; Restricts* restricts (0); + String pattern; while (more ()) { @@ -3077,7 +3103,7 @@ namespace XSDFrontend else restricts = set_type<Restricts> (base, r, node); - if (String name = t["name"]) + if (String name = trim (t["name"])) s_->new_edge<Names> (scope (), static_cast<Nameable&> (node), name); rv = &node; @@ -3094,10 +3120,16 @@ namespace XSDFrontend name == L"length" || name == L"minLength" || name == L"maxLength" || - name == L"whiteSpace" || - name == L"pattern") + name == L"whiteSpace") + { + facets[name] = trim (e["value"]); + } + else if (name == L"pattern") { - facets[name] = e["value"]; + if (pattern) + pattern += L'|'; + + pattern += e["value"]; } else { @@ -3109,6 +3141,9 @@ namespace XSDFrontend } } + if (pattern) + facets[L"pattern"] = pattern; + if (enum_) pop_scope (); else @@ -3120,7 +3155,7 @@ namespace XSDFrontend else restricts = set_type<Restricts> (base, r, node); - if (String name = t["name"]) + if (String name = trim (t["name"])) s_->new_edge<Names> (scope (), node, name); rv = &node; @@ -3139,7 +3174,7 @@ namespace XSDFrontend return rv; } - Void Parser::Impl:: + void Parser::Impl:: enumeration (XML::Element const& e) { String value (e["value"]); @@ -3169,9 +3204,10 @@ namespace XSDFrontend Complex& node (s_->new_node<Complex> (file (), t.line (), t.column ())); - node.mixed_p (t["mixed"] == L"true" || t["mixed"] == L"1"); + if (String m = trim (t["mixed"])) + node.mixed_p (m == L"true" || m == L"1"); - if (String name = t["name"]) + if (String name = trim (t["name"])) s_->new_edge<Names> (scope (), node, name); r = &node; @@ -3211,8 +3247,14 @@ namespace XSDFrontend } if (c) - s_->new_edge<ContainsCompositor> ( - node, *c, parse_min (e["minOccurs"]), parse_max (e["maxOccurs"])); + { + unsigned long min (parse_min (trim (e["minOccurs"]))); + unsigned long max (parse_max (trim (e["maxOccurs"]))); + + if (!(min == 0 && max == 0)) + s_->new_edge<ContainsCompositor> ( + node, *c, min, max == unbounded ? 0 : max); + } while (more ()) { @@ -3277,15 +3319,18 @@ namespace XSDFrontend } Choice* Parser::Impl:: - choice (XML::Element const& c, Boolean in_compositor) + choice (XML::Element const& c, bool in_compositor) { Choice& node (s_->new_node<Choice> (file (), c.line (), c.column ())); if (in_compositor) { - s_->new_edge<ContainsParticle> ( - compositor (), node, - parse_min (c["minOccurs"]), parse_max (c["maxOccurs"])); + unsigned long min (parse_min (trim (c["minOccurs"]))); + unsigned long max (parse_max (trim (c["maxOccurs"]))); + + if (!(min == 0 && max == 0)) + s_->new_edge<ContainsParticle> ( + compositor (), node, min, max == unbounded ? 0 : max); } push_compositor (node); @@ -3321,15 +3366,18 @@ namespace XSDFrontend } Sequence* Parser::Impl:: - sequence (XML::Element const& s, Boolean in_compositor) + sequence (XML::Element const& s, bool in_compositor) { Sequence& node (s_->new_node<Sequence> (file (), s.line (), s.column ())); if (in_compositor) { - s_->new_edge<ContainsParticle> ( - compositor (), node, - parse_min (s["minOccurs"]), parse_max (s["maxOccurs"])); + unsigned long min (parse_min (trim (s["minOccurs"]))); + unsigned long max (parse_max (trim (s["maxOccurs"]))); + + if (!(min == 0 && max == 0)) + s_->new_edge<ContainsParticle> ( + compositor (), node, min, max == unbounded ? 0 : max); } push_compositor (node); @@ -3364,7 +3412,7 @@ namespace XSDFrontend return &node; } - Void Parser::Impl:: + void Parser::Impl:: simple_content (XML::Element const& c) { push (c); @@ -3387,13 +3435,11 @@ namespace XSDFrontend pop (); } - Void Parser::Impl:: + void Parser::Impl:: complex_content (XML::Element const& c, Complex& type) { - if (c.attribute_p ("mixed")) - { - type.mixed_p (c["mixed"] == L"true" || c["mixed"] == L"1"); - } + if (String m = trim (c["mixed"])) + type.mixed_p (m == L"true" || m == L"1"); push (c); @@ -3415,13 +3461,13 @@ namespace XSDFrontend pop (); } - Void Parser::Impl:: + void Parser::Impl:: simple_content_extension (XML::Element const& e) { if (trace_) wcout << "extension base: " << fq_name (e, e["base"]) << endl; - set_type<Extends> (e["base"], e, dynamic_cast<Complex&> (scope ())); + set_type<Extends> (trim (e["base"]), e, dynamic_cast<Complex&> (scope ())); push (e); @@ -3447,11 +3493,10 @@ namespace XSDFrontend pop (); } - Void Parser::Impl:: + void Parser::Impl:: simple_content_restriction (XML::Element const& r) { - String base (r["base"]); - Type* base_type (0); + String base (trim (r["base"])); if (trace_ && base) wcout << "restriction base: " << fq_name (r, base) << endl; @@ -3471,7 +3516,7 @@ namespace XSDFrontend if (trace_) wcout << name << endl; - if (name == L"simpleType") base_type = simple_type (e); else + if (name == L"simpleType") simple_type (e); else { wcerr << file () << ":" << e.line () << ":" << e.column () << ": " << "error: expected 'simpleType' instead of " @@ -3497,6 +3542,7 @@ namespace XSDFrontend } Facets facets; + String pattern; while (more ()) { @@ -3532,10 +3578,16 @@ namespace XSDFrontend name == L"length" || name == L"minLength" || name == L"maxLength" || - name == L"whiteSpace" || - name == L"pattern") + name == L"whiteSpace") + { + facets[name] = trim (e["value"]); + } + else if (name == L"pattern") { - facets[name] = e["value"]; + if (pattern) + pattern += L'|'; + + pattern += e["value"]; } else if (name == L"attribute") { @@ -3562,6 +3614,9 @@ namespace XSDFrontend } } + if (pattern) + facets[L"pattern"] = pattern; + Complex& type (dynamic_cast<Complex&> (scope ())); Restricts* restricts = set_type<Restricts> (base, r, type); @@ -3576,13 +3631,13 @@ namespace XSDFrontend pop (); } - Void Parser::Impl:: + void Parser::Impl:: complex_content_extension (XML::Element const& e, Complex& type) { if (trace_) wcout << "extension base: " << fq_name (e, e["base"]) << endl; - set_type<Extends> (e["base"], e, dynamic_cast<Complex&> (scope ())); + set_type<Extends> (trim (e["base"]), e, dynamic_cast<Complex&> (scope ())); push (e); @@ -3609,8 +3664,14 @@ namespace XSDFrontend } if (c) - s_->new_edge<ContainsCompositor> ( - type, *c, parse_min (e["minOccurs"]), parse_max (e["maxOccurs"])); + { + unsigned long min (parse_min (trim (e["minOccurs"]))); + unsigned long max (parse_max (trim (e["maxOccurs"]))); + + if (!(min == 0 && max == 0)) + s_->new_edge<ContainsCompositor> ( + type, *c, min, max == unbounded ? 0 : max); + } while (more ()) { @@ -3633,13 +3694,16 @@ namespace XSDFrontend pop (); } - Void Parser::Impl:: + void Parser::Impl:: complex_content_restriction (XML::Element const& e, Complex& type) { if (trace_) wcout << "restriction base: " << fq_name (e, e["base"]) << endl; - set_type<Restricts> (e["base"], e, dynamic_cast<Complex&> (scope ())); + set_type<Restricts> ( + trim (e["base"]), + e, + dynamic_cast<Complex&> (scope ())); // @@ // For now we simply skip the contents unless the base is anyType @@ -3650,7 +3714,7 @@ namespace XSDFrontend // if (!proper_restriction_) { - String base (e["base"]); + String base (trim (e["base"])); String uq_name (unqualified_name (base)); String ns_name (namespace_name (e, base)); @@ -3683,8 +3747,14 @@ namespace XSDFrontend } if (c) - s_->new_edge<ContainsCompositor> ( - type, *c, parse_min (e["minOccurs"]), parse_max (e["maxOccurs"])); + { + unsigned long min (parse_min (trim (e["minOccurs"]))); + unsigned long max (parse_max (trim (e["maxOccurs"]))); + + if (!(min == 0 && max == 0)) + s_->new_edge<ContainsCompositor> ( + type, *c, min, max == unbounded ? 0 : max); + } while (more ()) { @@ -3707,18 +3777,18 @@ namespace XSDFrontend pop (); } - Void Parser::Impl:: - element (XML::Element const& e, Boolean global) + void Parser::Impl:: + element (XML::Element const& e, bool global) { - Boolean qualified (global ? true : qualify_element_); + bool qualified (global ? true : qualify_element_); - if (String form = e["form"]) + if (String form = trim (e["form"])) qualified = form == L"qualified"; if (trace_) wcout << "element qualified: " << qualified << endl; - if (String name = e["name"]) + if (String name = trim (e["name"])) { if (trace_) wcout << "element name '" << name << "'" << endl; @@ -3727,17 +3797,24 @@ namespace XSDFrontend s_->new_node<Element> ( file (), e.line (), e.column (), global, qualified)); - s_->new_edge<Names> (scope (), node, name); - - if (qualified) - s_->new_edge<BelongsToNamespace> (node, cur_ns ()); - if (!global) { - s_->new_edge<ContainsParticle> ( - compositor (), node, - parse_min (e["minOccurs"]), parse_max (e["maxOccurs"])); + unsigned long min (parse_min (trim (e["minOccurs"]))); + unsigned long max (parse_max (trim (e["maxOccurs"]))); + + if (!(min == 0 && max == 0)) + { + s_->new_edge<Names> (scope (), node, name); + + s_->new_edge<ContainsParticle> ( + compositor (), node, min, max == unbounded ? 0 : max); + } } + else + s_->new_edge<Names> (scope (), node, name); + + if (qualified) + s_->new_edge<BelongsToNamespace> (node, cur_ns ()); // Default and fixed values are mutually exclusive. // @@ -3752,13 +3829,16 @@ namespace XSDFrontend default_values_.push_back (&node); } + bool subst (false); if (global) { - if (String sg = e["substitutionGroup"]) + if (String sg = trim (e["substitutionGroup"])) { if (trace_) wcout << "substitutes " << sg << endl; + subst = true; + try { String uq_name (unqualified_name (sg)); @@ -3778,7 +3858,7 @@ namespace XSDFrontend } } - if (String type = e["type"]) + if (String type = trim (e["type"])) { if (trace_) wcout << "element type " << fq_name (e, type) << endl; @@ -3827,10 +3907,12 @@ namespace XSDFrontend if (t) s_->new_edge<Belongs> (node, *t); } - else + // By default the type is anyType unless this element is a + // member of a substitution group, in which case it has the + // same type as the element it substiutes. + // + else if (!subst) { - // anyType - // if (!is_disabled ("F001")) { wcerr << file () << ":" << e.line () << ":" << e.column () << ": " @@ -3851,18 +3933,14 @@ namespace XSDFrontend pop (); } } - else if (String ref = e["ref"]) + else if (String ref = trim (e["ref"])) { Element& node ( s_->new_node<Element> ( file (), e.line (), e.column (), true, true)); - // Ref can only be in compositor. - // - s_->new_edge<ContainsParticle> ( - compositor (), node, - parse_min (e["minOccurs"]), parse_max (e["maxOccurs"])); - + unsigned long min (parse_min (trim (e["minOccurs"]))); + unsigned long max (parse_max (trim (e["maxOccurs"]))); // Default and fixed values are mutually exclusive. // @@ -3886,119 +3964,127 @@ namespace XSDFrontend pop (); - // Try to resolve the prototype. - // - try + if (!(min == 0 && max == 0)) { - String uq_name (unqualified_name (ref)); - String ns_name (namespace_name (e, ref)); - - s_->new_edge<Names> (scope (), node, uq_name); - - Element& prot (resolve<Element> (ns_name, uq_name, *s_, *cache_)); - s_->new_edge<BelongsToNamespace> (node, prot.namespace_ ()); + // Ref can only be in compositor. + // + s_->new_edge<ContainsParticle> ( + compositor (), node, min, max == unbounded ? 0 : max); - // Copy substitution group information if any. + // Try to resolve the prototype. // - if (prot.context ().count ("substitution-ns-name")) + try { - node.context ().set ( - "substitution-ns-name", - prot.context ().get<String> ("substitution-ns-name")); + String uq_name (unqualified_name (ref)); + String ns_name (namespace_name (e, ref)); - node.context ().set ( - "substitution-uq-name", - prot.context ().get<String> ("substitution-uq-name")); - } + s_->new_edge<Names> (scope (), node, uq_name); - // Transfer default and fixed values if the ref declaration hasn't - // defined its own. - // - if (!node.default_p ()) - { - if (prot.fixed_p ()) - node.fixed (prot.value ()); - else if (prot.default_p ()) - node.default_ (prot.value ()); + Element& prot (resolve<Element> (ns_name, uq_name, *s_, *cache_)); + s_->new_edge<BelongsToNamespace> (node, prot.namespace_ ()); - if (node.default_p ()) + // Copy substitution group information if any. + // + if (prot.context ().count ("substitution-ns-name")) { node.context ().set ( - "dom-node", - prot.context ().get<Xerces::DOMElement*> ("dom-node")); - default_values_.push_back (&node); + "substitution-ns-name", + prot.context ().get<String> ("substitution-ns-name")); + + node.context ().set ( + "substitution-uq-name", + prot.context ().get<String> ("substitution-uq-name")); } - } - // Transfer annotation if the ref declaration hasn't defined its own. - // - if (!node.annotated_p () && prot.annotated_p ()) - s_->new_edge<Annotates> (prot.annotation (), node); + // Transfer default and fixed values if the ref declaration hasn't + // defined its own. + // + if (!node.default_p ()) + { + if (prot.fixed_p ()) + node.fixed (prot.value ()); + else if (prot.default_p ()) + node.default_ (prot.value ()); - // Set type information. - // - if (prot.typed_p ()) - { - s_->new_edge<Belongs> (node, prot.type ()); + if (node.default_p ()) + { + node.context ().set ( + "dom-node", + prot.context ().get<Xerces::DOMElement*> ("dom-node")); + default_values_.push_back (&node); + } + } + + // Transfer annotation if the ref declaration hasn't defined its own. + // + if (!node.annotated_p () && prot.annotated_p ()) + s_->new_edge<Annotates> (prot.annotation (), node); + + // Set type information. + // + if (prot.typed_p ()) + { + s_->new_edge<Belongs> (node, prot.type ()); + } + else if (prot.context ().count ("type-ns-name")) + { + String ns_name (prot.context ().get<String> ("type-ns-name")); + String uq_name (prot.context ().get<String> ("type-uq-name")); + + node.context ().set ("type-ns-name", ns_name); + node.context ().set ("type-uq-name", uq_name); + node.context ().set ("edge-type-id", type_id (typeid (Belongs))); + + if (trace_) + wcout << "element '" << ref << "' is not typed" << endl + << "deferring resolution until later" << endl; + } + else + { + // This could be a recursive reference to an element who's + // (anonymous) type is being defined. We are going to let + // resolver sort out this case. + // + node.context ().set ("instance-ns-name", ns_name); + node.context ().set ("instance-uq-name", uq_name); + + if (trace_) + wcout << "looks like a recursive reference to an element '" + << ns_name << "#" << uq_name << "' which is being " + << "defined" << endl + << "deferring resolution until later" << endl; + } } - else if (prot.context ().count ("type-ns-name")) + catch (NotNamespace const& ex) { - String ns_name (prot.context ().get<String> ("type-ns-name")); - String uq_name (prot.context ().get<String> ("type-uq-name")); - - node.context ().set ("type-ns-name", ns_name); - node.context ().set ("type-uq-name", uq_name); - node.context ().set ("edge-type-id", TypeId (typeid (Belongs))); + if (valid_) + { + wcerr << file () << ":" << e.line () << ":" << e.column () << ": " + << "ice: unable to resolve namespace '" << ex.ns () << "'" + << endl; - if (trace_) - wcout << "element '" << ref << "' is not typed" << endl - << "deferring resolution until later" << endl; + abort (); + } } - else + catch (NotName const& ex) { - // This could be a recursive reference to an element who's - // (anonymous) type is being defined. We are going to let - // resolver sort out this case. - // - node.context ().set ("instance-ns-name", ns_name); - node.context ().set ("instance-uq-name", uq_name); + node.context ().set ("instance-ns-name", ex.ns ()); + node.context ().set ("instance-uq-name", ex.name ()); if (trace_) - wcout << "looks like a recursive reference to an element '" - << ns_name << "#" << uq_name << "' which is being " - << "defined" << endl + wcout << "unable to resolve name '" << ex.name () + << "' inside namespace '" << ex.ns () << "'" << endl << "deferring resolution until later" << endl; } - } - catch (NotNamespace const& ex) - { - if (valid_) + catch (XML::NoMapping const& ex) { wcerr << file () << ":" << e.line () << ":" << e.column () << ": " - << "ice: unable to resolve namespace '" << ex.ns () << "'" - << endl; + << "error: unable to resolve namespace prefix '" + << ex.prefix () << "' in '" << ref << "'" << endl; - abort (); + valid_ = false; } } - catch (NotName const& ex) - { - node.context ().set ("instance-ns-name", ex.ns ()); - node.context ().set ("instance-uq-name", ex.name ()); - - if (trace_) - wcout << "unable to resolve name '" << ex.name () - << "' inside namespace '" << ex.ns () << "'" << endl - << "deferring resolution until later" << endl; - } - catch (XML::NoMapping const& ex) - { - wcerr << file () << ":" << e.line () << ":" << e.column () << ": " - << "error: unable to resolve namespace prefix '" - << ex.prefix () << "' in '" << ref << "'" << endl; - - valid_ = false; - } } else { @@ -4012,7 +4098,7 @@ namespace XSDFrontend } SemanticGraph::Annotation* Parser::Impl:: - annotation (Boolean process) + annotation (bool process) { Annotation* r (0); @@ -4039,7 +4125,7 @@ namespace XSDFrontend // Use first non-structured (text only) documentation element. // String text; - Boolean struc (false); + bool struc (false); DOMElement* de (doc.dom_element()); for (DOMNode* n (de->getFirstChild ()); @@ -4085,24 +4171,24 @@ namespace XSDFrontend } - Void Parser::Impl:: - attribute (XML::Element const& a, Boolean global) + void Parser::Impl:: + attribute (XML::Element const& a, bool global) { - Boolean optional (true); + bool optional (true); - String use (a["use"]); + String use (trim (a["use"])); if (use == L"prohibited") return; else if (use == L"required") optional = false; - Boolean qualified (global ? true : qualify_attribute_); + bool qualified (global ? true : qualify_attribute_); - if (String form = a["form"]) + if (String form = trim (a["form"])) qualified = form == L"qualified"; - if (String name = a["name"]) + if (String name = trim (a["name"])) { if (trace_) wcout << "attribute '" << name << "'" << endl; @@ -4130,7 +4216,7 @@ namespace XSDFrontend default_values_.push_back (&node); } - if (String type = a["type"]) + if (String type = trim (a["type"])) { if (trace_) wcout << "attribute type: '" << fq_name (a, type) << "'" << endl; @@ -4202,7 +4288,7 @@ namespace XSDFrontend pop (); } } - else if (String ref = a["ref"]) + else if (String ref = trim (a["ref"])) { Attribute& node ( s_->new_node<Attribute> ( @@ -4280,7 +4366,7 @@ namespace XSDFrontend node.context ().set ("type-ns-name", ns_name); node.context ().set ("type-uq-name", uq_name); - node.context ().set ("edge-type-id", TypeId (typeid (Belongs))); + node.context ().set ("edge-type-id", type_id (typeid (Belongs))); if (trace_) wcout << "attribute '" << ref << "' is not typed" << endl @@ -4342,10 +4428,10 @@ namespace XSDFrontend } } - Void Parser::Impl:: + void Parser::Impl:: attribute_group (XML::Element const& g) { - if (String name = g["name"]) + if (String name = trim (g["name"])) { // Global definition. // @@ -4384,7 +4470,7 @@ namespace XSDFrontend pop (); pop_scope (); } - else if (String ref = g["ref"]) + else if (String ref = trim (g["ref"])) { if (trace_) wcout << "attribute-group-ref " << ref << endl; @@ -4441,20 +4527,22 @@ namespace XSDFrontend } } - Void Parser::Impl:: + void Parser::Impl:: any (XML::Element const& a) { if (trace_) wcout << "any" << endl; - String namespaces (a["namespace"] ? a["namespace"] : L"##any"); + String namespaces (trim (a["namespace"])); + + if (!namespaces) + namespaces = L"##any"; Any& any ( s_->new_node<Any> (file (), a.line (), a.column (), namespaces)); - s_->new_edge<ContainsParticle> ( - compositor (), any, - parse_min (a["minOccurs"]), parse_max (a["maxOccurs"])); + unsigned long min (parse_min (trim (a["minOccurs"]))); + unsigned long max (parse_max (trim (a["maxOccurs"]))); // Parse annotation. // @@ -4465,33 +4553,42 @@ namespace XSDFrontend pop (); - // Any has no name so we have to come up with a fake one in order to - // put it into the scope. - // - UnsignedLong count; - FrontendElements::Context& ctx (scope ().context ()); - - if (!ctx.count ("any-name-count")) + if (!(min == 0 && max == 0)) { - count = 0; - ctx.set ("any-name-count", count); - } - else - count = ++(ctx.get<UnsignedLong> ("any-name-count")); + s_->new_edge<ContainsParticle> ( + compositor (), any, min, max == unbounded ? 0 : max); - std::basic_ostringstream<WideChar> os; - os << "any #" << count; + // Any has no name so we have to come up with a fake one in order to + // put it into the scope. + // + unsigned long count; + SemanticGraph::Context& ctx (scope ().context ()); - s_->new_edge<Names> (scope (), any, os.str ()); + if (!ctx.count ("any-name-count")) + { + count = 0; + ctx.set ("any-name-count", count); + } + else + count = ++(ctx.get<unsigned long> ("any-name-count")); + + std::basic_ostringstream<wchar_t> os; + os << "any #" << count; + + s_->new_edge<Names> (scope (), any, os.str ()); + } } - Void Parser::Impl:: + void Parser::Impl:: any_attribute (XML::Element const& a) { if (trace_) wcout << "anyAttribute" << endl; - String namespaces (a["namespace"] ? a["namespace"] : L"##any"); + String namespaces (trim (a["namespace"])); + + if (!namespaces) + namespaces = L"##any"; AnyAttribute& any ( s_->new_node<AnyAttribute> ( @@ -4510,8 +4607,8 @@ namespace XSDFrontend // in order to put it into the scope. // - UnsignedLong count; - FrontendElements::Context& ctx (scope ().context ()); + unsigned long count; + SemanticGraph::Context& ctx (scope ().context ()); if (!ctx.count ("any-attribute-name-count")) { @@ -4519,9 +4616,9 @@ namespace XSDFrontend ctx.set ("any-attribute-name-count", count); } else - count = ++(ctx.get<UnsignedLong> ("any-attribute-name-count")); + count = ++(ctx.get<unsigned long> ("any-attribute-name-count")); - std::basic_ostringstream<WideChar> os; + std::basic_ostringstream<wchar_t> os; os << "any-attribute #" << count; s_->new_edge<Names> (scope (), any, os.str ()); @@ -4573,7 +4670,7 @@ namespace XSDFrontend { // See if we've got 'xse:refType' attribute. // - if (String ref_type = e.attribute (xse, "refType")) + if (String ref_type = trim (e.attribute (xse, "refType"))) { if (trace_) wcout << "found refType attribute '" << ref_type << "'" << endl; @@ -4618,7 +4715,7 @@ namespace XSDFrontend { node.context ().set ("type-ns-name", ex.ns ()); node.context ().set ("type-uq-name", ex.name ()); - node.context ().set ("edge-type-id", TypeId (typeid (Edge))); + node.context ().set ("edge-type-id", type_id (typeid (Edge))); if (trace_) wcout << "unable to resolve name '" << ex.name () @@ -4641,14 +4738,16 @@ namespace XSDFrontend // that can later be used in diagnostics. Unfortunately, it doesn't // work. So we will have to keep our own track. // - struct Context: public NonCopyable + struct Context { + Context () {} + // File map for diagnostic. // Path const& file (Path const& abs) const { - FileMap::ConstIterator i (file_map_.find (abs)); + FileMap::const_iterator i (file_map_.find (abs)); if (i != file_map_.end ()) { @@ -4660,14 +4759,18 @@ namespace XSDFrontend } } - Void + void map_file (Path const& abs, Path const& rel) { file_map_[abs] = rel; } private: - typedef Cult::Containers::Map<Path, Path, FilePathComparator> FileMap; + Context (Context const&); + Context& operator= (Context const&); + + private: + typedef std::map<Path, Path> FileMap; FileMap file_map_; }; @@ -4676,13 +4779,13 @@ namespace XSDFrontend class ErrorHandler : public Xerces::DOMErrorHandler { public: - ErrorHandler (Boolean& valid, XSDFrontend::Context const& ctx) + ErrorHandler (bool& valid, XSDFrontend::Context const& ctx) : valid_ (valid), ctx_ (ctx) { } - virtual Boolean + virtual bool handleError (Xerces::DOMError const& e) { // Xerces likes to say "Fatal error encountered during schema scan". @@ -4694,14 +4797,8 @@ namespace XSDFrontend return true; -#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 - XSDFrontend::SemanticGraph::Path abs_path ( - XML::transcode_to_narrow (e.getLocation ()->getURI ()), - boost::filesystem::native); -#else XSDFrontend::SemanticGraph::Path abs_path ( - XML::transcode_to_narrow (e.getLocation ()->getURI ()).c_str()); -#endif + XML::transcode_to_narrow (e.getLocation ()->getURI ())); XSDFrontend::SemanticGraph::Path rel_path (ctx_.file (abs_path)); @@ -4730,7 +4827,7 @@ namespace XSDFrontend } private: - Boolean& valid_; + bool& valid_; XSDFrontend::Context const& ctx_; }; @@ -4754,12 +4851,7 @@ namespace XSDFrontend base_ (base), ctx_ (ctx) { -#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 - setSystemId (XML::XMLChString ( - String (abs_.native_file_string ())).c_str ()); -#else setSystemId (XML::XMLChString (String (abs_.string ())).c_str ()); -#endif } virtual Xerces::BinInputStream* @@ -4794,11 +4886,7 @@ namespace XSDFrontend class EntityResolver: public Xerces::XMemory, -#if _XERCES_VERSION >= 30000 public Xerces::DOMLSResourceResolver -#else - public Xerces::DOMEntityResolver -#endif { public: EntityResolver (XSDFrontend::Context& ctx, LocationTranslator* t) @@ -4806,19 +4894,12 @@ namespace XSDFrontend { } -#if _XERCES_VERSION >= 30000 virtual Xerces::DOMLSInput* resolveResource(XMLCh const* const, XMLCh const* const, XMLCh const* const /*pub_id*/, XMLCh const* const prv_id, XMLCh const* const base_uri) -#else - virtual Xerces::DOMInputSource* - resolveEntity (XMLCh const* const /*pub_id*/, - XMLCh const* const prv_id, - XMLCh const* const base_uri) -#endif { /* XMLCh empty[1]; @@ -4832,12 +4913,7 @@ namespace XSDFrontend // base_uri should be a valid path by now. // -#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 - Path base (XML::transcode_to_narrow (base_uri), - boost::filesystem::native); -#else - Path base (XML::transcode_to_narrow (base_uri).c_str()); -#endif + Path base (XML::transcode_to_narrow (base_uri)); if (prv_id == 0) { @@ -4861,36 +4937,19 @@ namespace XSDFrontend try { - Path path; - -#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 - try - { - path = Path (path_str); - } - catch (InvalidPath const&) - { - // Retry as a native path. - // - path = Path (path_str, boost::filesystem::native); - } -#else - // The new ABI does not have a fallback native representation - path = Path (path_str.c_str()); -#endif - - Path base_dir (base.branch_path ()); + Path path (path_str); + Path base_dir (base.directory ()); Path abs_path, rel_path; - if (path.is_complete ()) + if (path.absolute ()) { abs_path = rel_path = path; } else { abs_path = base_dir / path; - rel_path = ctx_.file (base).branch_path () / path; + rel_path = ctx_.file (base).directory () / path; } abs_path.normalize (); @@ -4928,7 +4987,7 @@ namespace XSDFrontend XML::AutoPtr<Xerces::DOMDocument> Parser::Impl:: - dom (Path const& tu, Boolean validate) + dom (Path const& tu, bool validate) { using namespace Xerces; @@ -4936,8 +4995,11 @@ namespace XSDFrontend { XSDFrontend::Context ctx; - Path abs_path (system_complete (tu)); - abs_path.normalize (); + // Do normalize() before complete() to avoid hitting system path + // limits with '..' directories. + // + Path abs_path (tu); + abs_path.normalize ().complete (); ctx.map_file (abs_path, tu); InputSource input_source (abs_path, tu, abs_path, ctx); @@ -4958,7 +5020,6 @@ namespace XSDFrontend // Create a DOMBuilder. // -#if _XERCES_VERSION >= 30000 XML::AutoPtr<DOMLSParser> parser ( impl->createLSParser (DOMImplementationLS::MODE_SYNCHRONOUS, 0)); @@ -4990,29 +5051,6 @@ namespace XSDFrontend Wrapper4InputSource wrap (&input_source, false); parser->loadGrammar (&wrap, Grammar::SchemaGrammarType); -#else - XML::AutoPtr<DOMBuilder> parser ( - impl->createDOMBuilder (DOMImplementationLS::MODE_SYNCHRONOUS, 0)); - - parser->setFeature (XMLUni::fgDOMComments, false); - parser->setFeature (XMLUni::fgDOMDatatypeNormalization, true); - parser->setFeature (XMLUni::fgDOMEntities, false); - parser->setFeature (XMLUni::fgDOMNamespaces, true); - parser->setFeature (XMLUni::fgDOMValidation, true); - parser->setFeature (XMLUni::fgDOMWhitespaceInElementContent, false); - parser->setFeature (XMLUni::fgXercesSchema, true); - parser->setFeature (XMLUni::fgXercesSchemaFullChecking, full_schema_check_); - parser->setFeature (XMLUni::fgXercesValidationErrorAsFatal, true); - - ErrorHandler eh (valid_, ctx); - parser->setErrorHandler (&eh); - - EntityResolver er (ctx, loc_translator_); - parser->setEntityResolver (&er); - - Wrapper4InputSource wrap (&input_source, false); - parser->loadGrammar (wrap, Grammar::SchemaGrammarType); -#endif } if (!valid_) @@ -5038,7 +5076,7 @@ namespace XSDFrontend } catch (Xerces::DOMException const& e) { - Size const size = 2047; + size_t const size = 2047; XMLCh text[size + 1]; wcerr << tu << ": ice: Xerces::DOMException: "; @@ -5081,9 +5119,9 @@ namespace XSDFrontend } Parser:: - Parser (Boolean proper_restriction, - Boolean multiple_imports, - Boolean full_schema_check) + Parser (bool proper_restriction, + bool multiple_imports, + bool full_schema_check) : impl_ (new Impl (proper_restriction, multiple_imports, full_schema_check, @@ -5093,9 +5131,9 @@ namespace XSDFrontend } Parser:: - Parser (Boolean proper_restriction, - Boolean multiple_imports, - Boolean full_schema_check, + Parser (bool proper_restriction, + bool multiple_imports, + bool full_schema_check, LocationTranslator& t, const WarningSet& d) : impl_ (new Impl (proper_restriction, @@ -5106,19 +5144,19 @@ namespace XSDFrontend { } - Evptr<SemanticGraph::Schema> Parser:: + auto_ptr<SemanticGraph::Schema> Parser:: parse (SemanticGraph::Path const& path) { return impl_->parse (path); } - Evptr<SemanticGraph::Schema> Parser:: + auto_ptr<SemanticGraph::Schema> Parser:: parse (SemanticGraph::Paths const& paths) { return impl_->parse (paths); } - Evptr<SemanticGraph::Schema> Parser:: + auto_ptr<SemanticGraph::Schema> Parser:: xml_schema (SemanticGraph::Path const& path) { return impl_->xml_schema (path); |