| /* | 
 |  * schemas.c : implementation of the XML Schema handling and | 
 |  *             schema validity checking | 
 |  * | 
 |  * See Copyright for the status of this software. | 
 |  * | 
 |  * Daniel Veillard <veillard@redhat.com> | 
 |  */ | 
 |  | 
 | /* | 
 |  * TODO: | 
 |  *   - when types are redefined in includes, check that all | 
 |  *     types in the redef list are equal | 
 |  *     -> need a type equality operation. | 
 |  *   - if we don't intend to use the schema for schemas, we | 
 |  *     need to validate all schema attributes (ref, type, name) | 
 |  *     against their types. | 
 |  *   - Eliminate item creation for: ?? | 
 |  * | 
 |  * URGENT TODO: | 
 |  *   - For xsi-driven schema acquisition, augment the IDCs after every | 
 |  *     acquisition episode (xmlSchemaAugmentIDC). | 
 |  * | 
 |  * NOTES: | 
 |  *   - Elimated item creation for: <restriction>, <extension>, | 
 |  *     <simpleContent>, <complexContent>, <list>, <union> | 
 |  * | 
 |  * PROBLEMS: | 
 |  *   - http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0337.html | 
 |  *     IDC XPath expression and chameleon includes: the targetNamespace is changed, so | 
 |  *     XPath will have trouble to resolve to this namespace, since not known. | 
 |  * | 
 |  * | 
 |  * CONSTRAINTS: | 
 |  * | 
 |  * Schema Component Constraint: | 
 |  *   All Group Limited (cos-all-limited) | 
 |  *   Status: complete | 
 |  *   (1.2) | 
 |  *     In xmlSchemaGroupDefReferenceTermFixup() and | 
 |  *   (2) | 
 |  *     In xmlSchemaParseModelGroup() | 
 |  *     TODO: Actually this should go to component-level checks, | 
 |  *     but is done here due to performance. Move it to an other layer | 
 |  *     is schema construction via an API is implemented. | 
 |  */ | 
 | #define IN_LIBXML | 
 | #include "libxml.h" | 
 |  | 
 | #ifdef LIBXML_SCHEMAS_ENABLED | 
 |  | 
 | #include <string.h> | 
 | #include <libxml/xmlmemory.h> | 
 | #include <libxml/parser.h> | 
 | #include <libxml/parserInternals.h> | 
 | #include <libxml/hash.h> | 
 | #include <libxml/uri.h> | 
 | #include <libxml/xmlschemas.h> | 
 | #include <libxml/schemasInternals.h> | 
 | #include <libxml/xmlschemastypes.h> | 
 | #include <libxml/xmlautomata.h> | 
 | #include <libxml/xmlregexp.h> | 
 | #include <libxml/dict.h> | 
 | #include <libxml/encoding.h> | 
 | #include <libxml/xmlIO.h> | 
 | #ifdef LIBXML_PATTERN_ENABLED | 
 | #include <libxml/pattern.h> | 
 | #endif | 
 | #ifdef LIBXML_READER_ENABLED | 
 | #include <libxml/xmlreader.h> | 
 | #endif | 
 |  | 
 | /* #define DEBUG 1 */ | 
 |  | 
 | /* #define DEBUG_CONTENT 1 */ | 
 |  | 
 | /* #define DEBUG_TYPE 1 */ | 
 |  | 
 | /* #define DEBUG_CONTENT_REGEXP 1 */ | 
 |  | 
 | /* #define DEBUG_AUTOMATA 1 */ | 
 |  | 
 | /* #define DEBUG_IDC */ | 
 |  | 
 | /* #define DEBUG_IDC_NODE_TABLE */ | 
 |  | 
 | /* #define WXS_ELEM_DECL_CONS_ENABLED */ | 
 |  | 
 | #ifdef DEBUG_IDC | 
 |  #ifndef DEBUG_IDC_NODE_TABLE | 
 |   #define DEBUG_IDC_NODE_TABLE | 
 |  #endif | 
 | #endif | 
 |  | 
 | /* #define ENABLE_PARTICLE_RESTRICTION 1 */ | 
 |  | 
 | #define ENABLE_REDEFINE | 
 |  | 
 | /* #define ENABLE_NAMED_LOCALS */ | 
 |  | 
 | /* #define ENABLE_IDC_NODE_TABLES_TEST */ | 
 |  | 
 | #define DUMP_CONTENT_MODEL | 
 |  | 
 | #ifdef LIBXML_READER_ENABLED | 
 | /* #define XML_SCHEMA_READER_ENABLED */ | 
 | #endif | 
 |  | 
 | #define UNBOUNDED (1 << 30) | 
 | #define TODO 								\ | 
 |     xmlGenericError(xmlGenericErrorContext,				\ | 
 | 	    "Unimplemented block at %s:%d\n",				\ | 
 |             __FILE__, __LINE__); | 
 |  | 
 | #define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##" | 
 |  | 
 | /* | 
 |  * The XML Schemas namespaces | 
 |  */ | 
 | static const xmlChar *xmlSchemaNs = (const xmlChar *) | 
 |     "http://www.w3.org/2001/XMLSchema"; | 
 |  | 
 | static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *) | 
 |     "http://www.w3.org/2001/XMLSchema-instance"; | 
 |  | 
 | static const xmlChar *xmlNamespaceNs = (const xmlChar *) | 
 |     "http://www.w3.org/2000/xmlns/"; | 
 |  | 
 | /* | 
 | * Come casting macros. | 
 | */ | 
 | #define ACTXT_CAST (xmlSchemaAbstractCtxtPtr) | 
 | #define PCTXT_CAST (xmlSchemaParserCtxtPtr) | 
 | #define VCTXT_CAST (xmlSchemaValidCtxtPtr) | 
 | #define WXS_BASIC_CAST (xmlSchemaBasicItemPtr) | 
 | #define WXS_TREE_CAST (xmlSchemaTreeItemPtr) | 
 | #define WXS_PTC_CAST (xmlSchemaParticlePtr) | 
 | #define WXS_TYPE_CAST (xmlSchemaTypePtr) | 
 | #define WXS_ELEM_CAST (xmlSchemaElementPtr) | 
 | #define WXS_ATTR_GROUP_CAST (xmlSchemaAttributeGroupPtr) | 
 | #define WXS_ATTR_CAST (xmlSchemaAttributePtr) | 
 | #define WXS_ATTR_USE_CAST (xmlSchemaAttributeUsePtr) | 
 | #define WXS_ATTR_PROHIB_CAST (xmlSchemaAttributeUseProhibPtr) | 
 | #define WXS_MODEL_GROUPDEF_CAST (xmlSchemaModelGroupDefPtr) | 
 | #define WXS_MODEL_GROUP_CAST (xmlSchemaModelGroupPtr) | 
 | #define WXS_IDC_CAST (xmlSchemaIDCPtr) | 
 | #define WXS_QNAME_CAST (xmlSchemaQNameRefPtr) | 
 | #define WXS_LIST_CAST (xmlSchemaItemListPtr) | 
 |  | 
 | /* | 
 | * Macros to query common properties of components. | 
 | */ | 
 | #define WXS_ITEM_NODE(i) xmlSchemaGetComponentNode(WXS_BASIC_CAST (i)) | 
 |  | 
 | #define WXS_ITEM_TYPE_NAME(i) xmlSchemaGetComponentTypeStr(WXS_BASIC_CAST (i)) | 
 | /* | 
 | * Macros for element declarations. | 
 | */ | 
 | #define WXS_ELEM_TYPEDEF(e) (e)->subtypes | 
 |  | 
 | #define WXS_SUBST_HEAD(item) (item)->refDecl | 
 | /* | 
 | * Macros for attribute declarations. | 
 | */ | 
 | #define WXS_ATTR_TYPEDEF(a) (a)->subtypes | 
 | /* | 
 | * Macros for attribute uses. | 
 | */ | 
 | #define WXS_ATTRUSE_DECL(au) WXS_ATTR_CAST (WXS_ATTR_USE_CAST (au))->attrDecl | 
 |  | 
 | #define WXS_ATTRUSE_TYPEDEF(au) WXS_ATTR_TYPEDEF(WXS_ATTRUSE_DECL( WXS_ATTR_USE_CAST au)) | 
 |  | 
 | #define WXS_ATTRUSE_DECL_NAME(au) (WXS_ATTRUSE_DECL(au))->name | 
 |  | 
 | #define WXS_ATTRUSE_DECL_TNS(au) (WXS_ATTRUSE_DECL(au))->targetNamespace | 
 | /* | 
 | * Macros for attribute groups. | 
 | */ | 
 | #define WXS_ATTR_GROUP_HAS_REFS(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) | 
 | #define WXS_ATTR_GROUP_EXPANDED(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) | 
 | /* | 
 | * Macros for particles. | 
 | */ | 
 | #define WXS_PARTICLE(p) WXS_PTC_CAST (p) | 
 |  | 
 | #define WXS_PARTICLE_TERM(p) (WXS_PARTICLE(p))->children | 
 |  | 
 | #define WXS_PARTICLE_TERM_AS_ELEM(p) (WXS_ELEM_CAST WXS_PARTICLE_TERM(p)) | 
 |  | 
 | #define WXS_PARTICLE_MODEL(p) WXS_MODEL_GROUP_CAST WXS_PARTICLE(p)->children | 
 | /* | 
 | * Macros for model groups definitions. | 
 | */ | 
 | #define WXS_MODELGROUPDEF_MODEL(mgd) (WXS_MODEL_GROUP_CAST (mgd))->children | 
 | /* | 
 | * Macros for model groups. | 
 | */ | 
 | #define WXS_IS_MODEL_GROUP(i) \ | 
 |     (((i)->type == XML_SCHEMA_TYPE_SEQUENCE) || \ | 
 |      ((i)->type == XML_SCHEMA_TYPE_CHOICE) || \ | 
 |      ((i)->type == XML_SCHEMA_TYPE_ALL)) | 
 |  | 
 | #define WXS_MODELGROUP_PARTICLE(mg) WXS_PTC_CAST (mg)->children | 
 | /* | 
 | * Macros for schema buckets. | 
 | */ | 
 | #define WXS_IS_BUCKET_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \ | 
 |     ((t) == XML_SCHEMA_SCHEMA_REDEFINE)) | 
 |  | 
 | #define WXS_IS_BUCKET_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \ | 
 |     ((t) == XML_SCHEMA_SCHEMA_IMPORT)) | 
 |  | 
 | #define WXS_IMPBUCKET(b) ((xmlSchemaImportPtr) (b)) | 
 |  | 
 | #define WXS_INCBUCKET(b) ((xmlSchemaIncludePtr) (b)) | 
 | /* | 
 | * Macros for complex/simple types. | 
 | */ | 
 | #define WXS_IS_ANYTYPE(i) \ | 
 |      (( (i)->type == XML_SCHEMA_TYPE_BASIC) && \ | 
 |       ( (WXS_TYPE_CAST (i))->builtInType == XML_SCHEMAS_ANYTYPE)) | 
 |  | 
 | #define WXS_IS_COMPLEX(i) \ | 
 |     (((i)->type == XML_SCHEMA_TYPE_COMPLEX) || \ | 
 |      ((i)->builtInType == XML_SCHEMAS_ANYTYPE)) | 
 |  | 
 | #define WXS_IS_SIMPLE(item) \ | 
 |     ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \ | 
 |      ((item->type == XML_SCHEMA_TYPE_BASIC) && \ | 
 |       (item->builtInType != XML_SCHEMAS_ANYTYPE))) | 
 |  | 
 | #define WXS_IS_ANY_SIMPLE_TYPE(i) \ | 
 |     (((i)->type == XML_SCHEMA_TYPE_BASIC) && \ | 
 |       ((i)->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) | 
 |  | 
 | #define WXS_IS_RESTRICTION(t) \ | 
 |     ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) | 
 |  | 
 | #define WXS_IS_EXTENSION(t) \ | 
 |     ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) | 
 |  | 
 | #define WXS_IS_TYPE_NOT_FIXED(i) \ | 
 |     (((i)->type != XML_SCHEMA_TYPE_BASIC) && \ | 
 |      (((i)->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0)) | 
 |  | 
 | #define WXS_IS_TYPE_NOT_FIXED_1(item) \ | 
 |     (((item)->type != XML_SCHEMA_TYPE_BASIC) && \ | 
 |      (((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0)) | 
 |  | 
 | #define WXS_TYPE_IS_GLOBAL(t) ((t)->flags & XML_SCHEMAS_TYPE_GLOBAL) | 
 |  | 
 | #define WXS_TYPE_IS_LOCAL(t) (((t)->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0) | 
 | /* | 
 | * Macros for exclusively for complex types. | 
 | */ | 
 | #define WXS_HAS_COMPLEX_CONTENT(item) \ | 
 |     ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \ | 
 |      (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \ | 
 |      (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) | 
 |  | 
 | #define WXS_HAS_SIMPLE_CONTENT(item) \ | 
 |     ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \ | 
 |      (item->contentType == XML_SCHEMA_CONTENT_BASIC)) | 
 |  | 
 | #define WXS_HAS_MIXED_CONTENT(item) \ | 
 |     (item->contentType == XML_SCHEMA_CONTENT_MIXED) | 
 |  | 
 | #define WXS_EMPTIABLE(t) \ | 
 |     (xmlSchemaIsParticleEmptiable(WXS_PTC_CAST (t)->subtypes)) | 
 |  | 
 | #define WXS_TYPE_CONTENTTYPE(t) (t)->subtypes | 
 |  | 
 | #define WXS_TYPE_PARTICLE(t) WXS_PTC_CAST (t)->subtypes | 
 |  | 
 | #define WXS_TYPE_PARTICLE_TERM(t) WXS_PARTICLE_TERM(WXS_TYPE_PARTICLE(t)) | 
 | /* | 
 | * Macros for exclusively for simple types. | 
 | */ | 
 | #define WXS_LIST_ITEMTYPE(t) (t)->subtypes | 
 |  | 
 | #define WXS_IS_ATOMIC(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) | 
 |  | 
 | #define WXS_IS_LIST(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) | 
 |  | 
 | #define WXS_IS_UNION(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) | 
 | /* | 
 | * Misc parser context macros. | 
 | */ | 
 | #define WXS_CONSTRUCTOR(ctx) (ctx)->constructor | 
 |  | 
 | #define WXS_HAS_BUCKETS(ctx) \ | 
 | ( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \ | 
 | (WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) ) | 
 |  | 
 | #define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups | 
 |  | 
 | #define WXS_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket | 
 |  | 
 | #define WXS_SCHEMA(ctx) (ctx)->schema | 
 |  | 
 | #define WXS_ADD_LOCAL(ctx, item) \ | 
 |     xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, item) | 
 |  | 
 | #define WXS_ADD_GLOBAL(ctx, item) \ | 
 |     xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, item) | 
 |  | 
 | #define WXS_ADD_PENDING(ctx, item) \ | 
 |     xmlSchemaAddItemSize(&((ctx)->constructor->pending), 10, item) | 
 | /* | 
 | * xmlSchemaItemList macros. | 
 | */ | 
 | #define WXS_ILIST_IS_EMPTY(l) ((l == NULL) || ((l)->nbItems == 0)) | 
 | /* | 
 | * Misc macros. | 
 | */ | 
 | #define IS_SCHEMA(node, type) \ | 
 |    ((node != NULL) && (node->ns != NULL) && \ | 
 |     (xmlStrEqual(node->name, (const xmlChar *) type)) && \ | 
 |     (xmlStrEqual(node->ns->href, xmlSchemaNs))) | 
 |  | 
 | #define FREE_AND_NULL(str) if ((str) != NULL) { xmlFree((xmlChar *) (str)); str = NULL; } | 
 |  | 
 | /* | 
 | * Since we put the default/fixed values into the dict, we can | 
 | * use pointer comparison for those values. | 
 | * REMOVED: (xmlStrEqual((v1), (v2))) | 
 | */ | 
 | #define WXS_ARE_DEFAULT_STR_EQUAL(v1, v2) ((v1) == (v2)) | 
 |  | 
 | #define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED) | 
 |  | 
 | #define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0)) | 
 |  | 
 | #define HFAILURE if (res == -1) goto exit_failure; | 
 |  | 
 | #define HERROR if (res != 0) goto exit_error; | 
 |  | 
 | #define HSTOP(ctx) if ((ctx)->stop) goto exit; | 
 | /* | 
 | * Some flags used for various schema constraints. | 
 | */ | 
 | #define SUBSET_RESTRICTION  1<<0 | 
 | #define SUBSET_EXTENSION    1<<1 | 
 | #define SUBSET_SUBSTITUTION 1<<2 | 
 | #define SUBSET_LIST         1<<3 | 
 | #define SUBSET_UNION        1<<4 | 
 |  | 
 | typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo; | 
 | typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr; | 
 |  | 
 | typedef struct _xmlSchemaItemList xmlSchemaItemList; | 
 | typedef xmlSchemaItemList *xmlSchemaItemListPtr; | 
 | struct _xmlSchemaItemList { | 
 |     void **items;  /* used for dynamic addition of schemata */ | 
 |     int nbItems; /* used for dynamic addition of schemata */ | 
 |     int sizeItems; /* used for dynamic addition of schemata */ | 
 | }; | 
 |  | 
 | #define XML_SCHEMA_CTXT_PARSER 1 | 
 | #define XML_SCHEMA_CTXT_VALIDATOR 2 | 
 |  | 
 | typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt; | 
 | typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr; | 
 | struct _xmlSchemaAbstractCtxt { | 
 |     int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */ | 
 | }; | 
 |  | 
 | typedef struct _xmlSchemaBucket xmlSchemaBucket; | 
 | typedef xmlSchemaBucket *xmlSchemaBucketPtr; | 
 |  | 
 | #define XML_SCHEMA_SCHEMA_MAIN 0 | 
 | #define XML_SCHEMA_SCHEMA_IMPORT 1 | 
 | #define XML_SCHEMA_SCHEMA_INCLUDE 2 | 
 | #define XML_SCHEMA_SCHEMA_REDEFINE 3 | 
 |  | 
 | /** | 
 |  * xmlSchemaSchemaRelation: | 
 |  * | 
 |  * Used to create a graph of schema relationships. | 
 |  */ | 
 | typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation; | 
 | typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr; | 
 | struct _xmlSchemaSchemaRelation { | 
 |     xmlSchemaSchemaRelationPtr next; | 
 |     int type; /* E.g. XML_SCHEMA_SCHEMA_IMPORT */ | 
 |     const xmlChar *importNamespace; | 
 |     xmlSchemaBucketPtr bucket; | 
 | }; | 
 |  | 
 | #define XML_SCHEMA_BUCKET_MARKED 1<<0 | 
 | #define XML_SCHEMA_BUCKET_COMPS_ADDED 1<<1 | 
 |  | 
 | struct _xmlSchemaBucket { | 
 |     int type; | 
 |     int flags; | 
 |     const xmlChar *schemaLocation; | 
 |     const xmlChar *origTargetNamespace; | 
 |     const xmlChar *targetNamespace; | 
 |     xmlDocPtr doc; | 
 |     xmlSchemaSchemaRelationPtr relations; | 
 |     int located; | 
 |     int parsed; | 
 |     int imported; | 
 |     int preserveDoc; | 
 |     xmlSchemaItemListPtr globals; /* Global components. */ | 
 |     xmlSchemaItemListPtr locals; /* Local components. */ | 
 | }; | 
 |  | 
 | /** | 
 |  * xmlSchemaImport: | 
 |  * (extends xmlSchemaBucket) | 
 |  * | 
 |  * Reflects a schema. Holds some information | 
 |  * about the schema and its toplevel components. Duplicate | 
 |  * toplevel components are not checked at this level. | 
 |  */ | 
 | typedef struct _xmlSchemaImport xmlSchemaImport; | 
 | typedef xmlSchemaImport *xmlSchemaImportPtr; | 
 | struct _xmlSchemaImport { | 
 |     int type; /* Main OR import OR include. */ | 
 |     int flags; | 
 |     const xmlChar *schemaLocation; /* The URI of the schema document. */ | 
 |     /* For chameleon includes, @origTargetNamespace will be NULL */ | 
 |     const xmlChar *origTargetNamespace; | 
 |     /* | 
 |     * For chameleon includes, @targetNamespace will be the | 
 |     * targetNamespace of the including schema. | 
 |     */ | 
 |     const xmlChar *targetNamespace; | 
 |     xmlDocPtr doc; /* The schema node-tree. */ | 
 |     /* @relations will hold any included/imported/redefined schemas. */ | 
 |     xmlSchemaSchemaRelationPtr relations; | 
 |     int located; | 
 |     int parsed; | 
 |     int imported; | 
 |     int preserveDoc; | 
 |     xmlSchemaItemListPtr globals; | 
 |     xmlSchemaItemListPtr locals; | 
 |     /* The imported schema. */ | 
 |     xmlSchemaPtr schema; | 
 | }; | 
 |  | 
 | /* | 
 | * (extends xmlSchemaBucket) | 
 | */ | 
 | typedef struct _xmlSchemaInclude xmlSchemaInclude; | 
 | typedef xmlSchemaInclude *xmlSchemaIncludePtr; | 
 | struct _xmlSchemaInclude { | 
 |     int type; | 
 |     int flags; | 
 |     const xmlChar *schemaLocation; | 
 |     const xmlChar *origTargetNamespace; | 
 |     const xmlChar *targetNamespace; | 
 |     xmlDocPtr doc; | 
 |     xmlSchemaSchemaRelationPtr relations; | 
 |     int located; | 
 |     int parsed; | 
 |     int imported; | 
 |     int preserveDoc; | 
 |     xmlSchemaItemListPtr globals; /* Global components. */ | 
 |     xmlSchemaItemListPtr locals; /* Local components. */ | 
 |  | 
 |     /* The owning main or import schema bucket. */ | 
 |     xmlSchemaImportPtr ownerImport; | 
 | }; | 
 |  | 
 | /** | 
 |  * xmlSchemaBasicItem: | 
 |  * | 
 |  * The abstract base type for schema components. | 
 |  */ | 
 | typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem; | 
 | typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr; | 
 | struct _xmlSchemaBasicItem { | 
 |     xmlSchemaTypeType type; | 
 | }; | 
 |  | 
 | /** | 
 |  * xmlSchemaAnnotItem: | 
 |  * | 
 |  * The abstract base type for annotated schema components. | 
 |  * (Extends xmlSchemaBasicItem) | 
 |  */ | 
 | typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem; | 
 | typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr; | 
 | struct _xmlSchemaAnnotItem { | 
 |     xmlSchemaTypeType type; | 
 |     xmlSchemaAnnotPtr annot; | 
 | }; | 
 |  | 
 | /** | 
 |  * xmlSchemaTreeItem: | 
 |  * | 
 |  * The abstract base type for tree-like structured schema components. | 
 |  * (Extends xmlSchemaAnnotItem) | 
 |  */ | 
 | typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem; | 
 | typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr; | 
 | struct _xmlSchemaTreeItem { | 
 |     xmlSchemaTypeType type; | 
 |     xmlSchemaAnnotPtr annot; | 
 |     xmlSchemaTreeItemPtr next; | 
 |     xmlSchemaTreeItemPtr children; | 
 | }; | 
 |  | 
 |  | 
 | #define XML_SCHEMA_ATTR_USE_FIXED 1<<0 | 
 | /** | 
 |  * xmlSchemaAttributeUsePtr: | 
 |  * | 
 |  * The abstract base type for tree-like structured schema components. | 
 |  * (Extends xmlSchemaTreeItem) | 
 |  */ | 
 | typedef struct _xmlSchemaAttributeUse xmlSchemaAttributeUse; | 
 | typedef xmlSchemaAttributeUse *xmlSchemaAttributeUsePtr; | 
 | struct _xmlSchemaAttributeUse { | 
 |     xmlSchemaTypeType type; | 
 |     xmlSchemaAnnotPtr annot; | 
 |     xmlSchemaAttributeUsePtr next; /* The next attr. use. */ | 
 |     /* | 
 |     * The attr. decl. OR a QName-ref. to an attr. decl. OR | 
 |     * a QName-ref. to an attribute group definition. | 
 |     */ | 
 |     xmlSchemaAttributePtr attrDecl; | 
 |  | 
 |     int flags; | 
 |     xmlNodePtr node; | 
 |     int occurs; /* required, optional */ | 
 |     const xmlChar * defValue; | 
 |     xmlSchemaValPtr defVal; | 
 | }; | 
 |  | 
 | /** | 
 |  * xmlSchemaAttributeUseProhibPtr: | 
 |  * | 
 |  * A helper component to reflect attribute prohibitions. | 
 |  * (Extends xmlSchemaBasicItem) | 
 |  */ | 
 | typedef struct _xmlSchemaAttributeUseProhib xmlSchemaAttributeUseProhib; | 
 | typedef xmlSchemaAttributeUseProhib *xmlSchemaAttributeUseProhibPtr; | 
 | struct _xmlSchemaAttributeUseProhib { | 
 |     xmlSchemaTypeType type; /* == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB */ | 
 |     xmlNodePtr node; | 
 |     const xmlChar *name; | 
 |     const xmlChar *targetNamespace; | 
 |     int isRef; | 
 | }; | 
 |  | 
 | /** | 
 |  * xmlSchemaRedef: | 
 |  */ | 
 | typedef struct _xmlSchemaRedef xmlSchemaRedef; | 
 | typedef xmlSchemaRedef *xmlSchemaRedefPtr; | 
 | struct _xmlSchemaRedef { | 
 |     xmlSchemaRedefPtr next; | 
 |     xmlSchemaBasicItemPtr item; /* The redefining component. */ | 
 |     xmlSchemaBasicItemPtr reference; /* The referencing component. */ | 
 |     xmlSchemaBasicItemPtr target; /* The to-be-redefined component. */ | 
 |     const xmlChar *refName; /* The name of the to-be-redefined component. */ | 
 |     const xmlChar *refTargetNs; /* The target namespace of the | 
 |                                    to-be-redefined comp. */ | 
 |     xmlSchemaBucketPtr targetBucket; /* The redefined schema. */ | 
 | }; | 
 |  | 
 | /** | 
 |  * xmlSchemaConstructionCtxt: | 
 |  */ | 
 | typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt; | 
 | typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr; | 
 | struct _xmlSchemaConstructionCtxt { | 
 |     xmlSchemaPtr mainSchema; /* The main schema. */ | 
 |     xmlSchemaBucketPtr mainBucket; /* The main schema bucket */ | 
 |     xmlDictPtr dict; | 
 |     xmlSchemaItemListPtr buckets; /* List of schema buckets. */ | 
 |     /* xmlSchemaItemListPtr relations; */ /* List of schema relations. */ | 
 |     xmlSchemaBucketPtr bucket; /* The current schema bucket */ | 
 |     xmlSchemaItemListPtr pending; /* All Components of all schemas that | 
 |                                      need to be fixed. */ | 
 |     xmlHashTablePtr substGroups; | 
 |     xmlSchemaRedefPtr redefs; | 
 |     xmlSchemaRedefPtr lastRedef; | 
 | }; | 
 |  | 
 | #define XML_SCHEMAS_PARSE_ERROR		1 | 
 | #define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT | 
 |  | 
 | struct _xmlSchemaParserCtxt { | 
 |     int type; | 
 |     void *errCtxt;             /* user specific error context */ | 
 |     xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */ | 
 |     xmlSchemaValidityWarningFunc warning;       /* the callback in case of warning */ | 
 |     int err; | 
 |     int nberrors; | 
 |     xmlStructuredErrorFunc serror; | 
 |  | 
 |     xmlSchemaConstructionCtxtPtr constructor; | 
 |     int ownsConstructor; /* TODO: Move this to parser *flags*. */ | 
 |  | 
 |     /* xmlSchemaPtr topschema;	*/ | 
 |     /* xmlHashTablePtr namespaces;  */ | 
 |  | 
 |     xmlSchemaPtr schema;        /* The main schema in use */ | 
 |     int counter; | 
 |  | 
 |     const xmlChar *URL; | 
 |     xmlDocPtr doc; | 
 |     int preserve;		/* Whether the doc should be freed  */ | 
 |  | 
 |     const char *buffer; | 
 |     int size; | 
 |  | 
 |     /* | 
 |      * Used to build complex element content models | 
 |      */ | 
 |     xmlAutomataPtr am; | 
 |     xmlAutomataStatePtr start; | 
 |     xmlAutomataStatePtr end; | 
 |     xmlAutomataStatePtr state; | 
 |  | 
 |     xmlDictPtr dict;		/* dictionnary for interned string names */ | 
 |     xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */ | 
 |     int options; | 
 |     xmlSchemaValidCtxtPtr vctxt; | 
 |     int isS4S; | 
 |     int isRedefine; | 
 |     int xsiAssemble; | 
 |     int stop; /* If the parser should stop; i.e. a critical error. */ | 
 |     const xmlChar *targetNamespace; | 
 |     xmlSchemaBucketPtr redefined; /* The schema to be redefined. */ | 
 |  | 
 |     xmlSchemaRedefPtr redef; /* Used for redefinitions. */ | 
 |     int redefCounter; /* Used for redefinitions. */ | 
 |     xmlSchemaItemListPtr attrProhibs; | 
 | }; | 
 |  | 
 | /** | 
 |  * xmlSchemaQNameRef: | 
 |  * | 
 |  * A component reference item (not a schema component) | 
 |  * (Extends xmlSchemaBasicItem) | 
 |  */ | 
 | typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef; | 
 | typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr; | 
 | struct _xmlSchemaQNameRef { | 
 |     xmlSchemaTypeType type; | 
 |     xmlSchemaBasicItemPtr item; /* The resolved referenced item. */ | 
 |     xmlSchemaTypeType itemType; | 
 |     const xmlChar *name; | 
 |     const xmlChar *targetNamespace; | 
 |     xmlNodePtr node; | 
 | }; | 
 |  | 
 | /** | 
 |  * xmlSchemaParticle: | 
 |  * | 
 |  * A particle component. | 
 |  * (Extends xmlSchemaTreeItem) | 
 |  */ | 
 | typedef struct _xmlSchemaParticle xmlSchemaParticle; | 
 | typedef xmlSchemaParticle *xmlSchemaParticlePtr; | 
 | struct _xmlSchemaParticle { | 
 |     xmlSchemaTypeType type; | 
 |     xmlSchemaAnnotPtr annot; | 
 |     xmlSchemaTreeItemPtr next; /* next particle */ | 
 |     xmlSchemaTreeItemPtr children; /* the "term" (e.g. a model group, | 
 | 	a group definition, a XML_SCHEMA_EXTRA_QNAMEREF (if a reference), | 
 |         etc.) */ | 
 |     int minOccurs; | 
 |     int maxOccurs; | 
 |     xmlNodePtr node; | 
 | }; | 
 |  | 
 | /** | 
 |  * xmlSchemaModelGroup: | 
 |  * | 
 |  * A model group component. | 
 |  * (Extends xmlSchemaTreeItem) | 
 |  */ | 
 | typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup; | 
 | typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr; | 
 | struct _xmlSchemaModelGroup { | 
 |     xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */ | 
 |     xmlSchemaAnnotPtr annot; | 
 |     xmlSchemaTreeItemPtr next; /* not used */ | 
 |     xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */ | 
 |     xmlNodePtr node; | 
 | }; | 
 |  | 
 | #define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0 | 
 | #define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1 | 
 | /** | 
 |  * xmlSchemaModelGroupDef: | 
 |  * | 
 |  * A model group definition component. | 
 |  * (Extends xmlSchemaTreeItem) | 
 |  */ | 
 | typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef; | 
 | typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr; | 
 | struct _xmlSchemaModelGroupDef { | 
 |     xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */ | 
 |     xmlSchemaAnnotPtr annot; | 
 |     xmlSchemaTreeItemPtr next; /* not used */ | 
 |     xmlSchemaTreeItemPtr children; /* the "model group" */ | 
 |     const xmlChar *name; | 
 |     const xmlChar *targetNamespace; | 
 |     xmlNodePtr node; | 
 |     int flags; | 
 | }; | 
 |  | 
 | typedef struct _xmlSchemaIDC xmlSchemaIDC; | 
 | typedef xmlSchemaIDC *xmlSchemaIDCPtr; | 
 |  | 
 | /** | 
 |  * xmlSchemaIDCSelect: | 
 |  * | 
 |  * The identity-constraint "field" and "selector" item, holding the | 
 |  * XPath expression. | 
 |  */ | 
 | typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect; | 
 | typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr; | 
 | struct _xmlSchemaIDCSelect { | 
 |     xmlSchemaIDCSelectPtr next; | 
 |     xmlSchemaIDCPtr idc; | 
 |     int index; /* an index position if significant for IDC key-sequences */ | 
 |     const xmlChar *xpath; /* the XPath expression */ | 
 |     void *xpathComp; /* the compiled XPath expression */ | 
 | }; | 
 |  | 
 | /** | 
 |  * xmlSchemaIDC: | 
 |  * | 
 |  * The identity-constraint definition component. | 
 |  * (Extends xmlSchemaAnnotItem) | 
 |  */ | 
 |  | 
 | struct _xmlSchemaIDC { | 
 |     xmlSchemaTypeType type; | 
 |     xmlSchemaAnnotPtr annot; | 
 |     xmlSchemaIDCPtr next; | 
 |     xmlNodePtr node; | 
 |     const xmlChar *name; | 
 |     const xmlChar *targetNamespace; | 
 |     xmlSchemaIDCSelectPtr selector; | 
 |     xmlSchemaIDCSelectPtr fields; | 
 |     int nbFields; | 
 |     xmlSchemaQNameRefPtr ref; | 
 | }; | 
 |  | 
 | /** | 
 |  * xmlSchemaIDCAug: | 
 |  * | 
 |  * The augmented IDC information used for validation. | 
 |  */ | 
 | typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug; | 
 | typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr; | 
 | struct _xmlSchemaIDCAug { | 
 |     xmlSchemaIDCAugPtr next; /* next in a list */ | 
 |     xmlSchemaIDCPtr def; /* the IDC definition */ | 
 |     int keyrefDepth; /* the lowest tree level to which IDC | 
 |                         tables need to be bubbled upwards */ | 
 | }; | 
 |  | 
 | /** | 
 |  * xmlSchemaPSVIIDCKeySequence: | 
 |  * | 
 |  * The key sequence of a node table item. | 
 |  */ | 
 | typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey; | 
 | typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr; | 
 | struct _xmlSchemaPSVIIDCKey { | 
 |     xmlSchemaTypePtr type; | 
 |     xmlSchemaValPtr val; | 
 | }; | 
 |  | 
 | /** | 
 |  * xmlSchemaPSVIIDCNode: | 
 |  * | 
 |  * The node table item of a node table. | 
 |  */ | 
 | typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode; | 
 | typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr; | 
 | struct _xmlSchemaPSVIIDCNode { | 
 |     xmlNodePtr node; | 
 |     xmlSchemaPSVIIDCKeyPtr *keys; | 
 |     int nodeLine; | 
 |     int nodeQNameID; | 
 |  | 
 | }; | 
 |  | 
 | /** | 
 |  * xmlSchemaPSVIIDCBinding: | 
 |  * | 
 |  * The identity-constraint binding item of the [identity-constraint table]. | 
 |  */ | 
 | typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding; | 
 | typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr; | 
 | struct _xmlSchemaPSVIIDCBinding { | 
 |     xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */ | 
 |     xmlSchemaIDCPtr definition; /* the IDC definition */ | 
 |     xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */ | 
 |     int nbNodes; /* number of entries in the node table */ | 
 |     int sizeNodes; /* size of the node table */ | 
 |     xmlSchemaItemListPtr dupls; | 
 | }; | 
 |  | 
 |  | 
 | #define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1 | 
 | #define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2 | 
 |  | 
 | #define XPATH_STATE_OBJ_MATCHES -2 | 
 | #define XPATH_STATE_OBJ_BLOCKED -3 | 
 |  | 
 | typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher; | 
 | typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr; | 
 |  | 
 | /** | 
 |  * xmlSchemaIDCStateObj: | 
 |  * | 
 |  * The state object used to evaluate XPath expressions. | 
 |  */ | 
 | typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj; | 
 | typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr; | 
 | struct _xmlSchemaIDCStateObj { | 
 |     int type; | 
 |     xmlSchemaIDCStateObjPtr next; /* next if in a list */ | 
 |     int depth; /* depth of creation */ | 
 |     int *history; /* list of (depth, state-id) tuples */ | 
 |     int nbHistory; | 
 |     int sizeHistory; | 
 |     xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector | 
 |                                        matcher */ | 
 |     xmlSchemaIDCSelectPtr sel; | 
 |     void *xpathCtxt; | 
 | }; | 
 |  | 
 | #define IDC_MATCHER 0 | 
 |  | 
 | /** | 
 |  * xmlSchemaIDCMatcher: | 
 |  * | 
 |  * Used to evaluate IDC selectors (and fields). | 
 |  */ | 
 | struct _xmlSchemaIDCMatcher { | 
 |     int type; | 
 |     int depth; /* the tree depth at creation time */ | 
 |     xmlSchemaIDCMatcherPtr next; /* next in the list */ | 
 |     xmlSchemaIDCMatcherPtr nextCached; /* next in the cache list */ | 
 |     xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */ | 
 |     int idcType; | 
 |     xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target | 
 |                                          elements */ | 
 |     int sizeKeySeqs; | 
 |     xmlSchemaItemListPtr targets; /* list of target-node | 
 |                                      (xmlSchemaPSVIIDCNodePtr) entries */ | 
 | }; | 
 |  | 
 | /* | 
 | * Element info flags. | 
 | */ | 
 | #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES  1<<0 | 
 | #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1 | 
 | #define XML_SCHEMA_ELEM_INFO_NILLED	       1<<2 | 
 | #define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE	       1<<3 | 
 |  | 
 | #define XML_SCHEMA_NODE_INFO_VALUE_NEEDED      1<<4 | 
 | #define XML_SCHEMA_ELEM_INFO_EMPTY             1<<5 | 
 | #define XML_SCHEMA_ELEM_INFO_HAS_CONTENT       1<<6 | 
 |  | 
 | #define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT  1<<7 | 
 | #define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT  1<<8 | 
 | #define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED  1<<9 | 
 | #define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE  1<<10 | 
 |  | 
 | /** | 
 |  * xmlSchemaNodeInfo: | 
 |  * | 
 |  * Holds information of an element node. | 
 |  */ | 
 | struct _xmlSchemaNodeInfo { | 
 |     int nodeType; | 
 |     xmlNodePtr node; | 
 |     int nodeLine; | 
 |     const xmlChar *localName; | 
 |     const xmlChar *nsName; | 
 |     const xmlChar *value; | 
 |     xmlSchemaValPtr val; /* the pre-computed value if any */ | 
 |     xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */ | 
 |  | 
 |     int flags; /* combination of node info flags */ | 
 |  | 
 |     int valNeeded; | 
 |     int normVal; | 
 |  | 
 |     xmlSchemaElementPtr decl; /* the element/attribute declaration */ | 
 |     int depth; | 
 |     xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings | 
 |                                             for the scope element*/ | 
 |     xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope | 
 |                                            element */ | 
 |     xmlRegExecCtxtPtr regexCtxt; | 
 |  | 
 |     const xmlChar **nsBindings; /* Namespace bindings on this element */ | 
 |     int nbNsBindings; | 
 |     int sizeNsBindings; | 
 |  | 
 |     int hasKeyrefs; | 
 |     int appliedXPath; /* Indicates that an XPath has been applied. */ | 
 | }; | 
 |  | 
 | #define XML_SCHEMAS_ATTR_UNKNOWN 1 | 
 | #define XML_SCHEMAS_ATTR_ASSESSED 2 | 
 | #define XML_SCHEMAS_ATTR_PROHIBITED 3 | 
 | #define XML_SCHEMAS_ATTR_ERR_MISSING 4 | 
 | #define XML_SCHEMAS_ATTR_INVALID_VALUE 5 | 
 | #define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6 | 
 | #define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7 | 
 | #define XML_SCHEMAS_ATTR_DEFAULT 8 | 
 | #define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9 | 
 | #define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10 | 
 | #define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11 | 
 | #define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12 | 
 | #define XML_SCHEMAS_ATTR_WILD_SKIP 13 | 
 | #define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14 | 
 | #define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15 | 
 | #define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16 | 
 | #define XML_SCHEMAS_ATTR_META 17 | 
 | /* | 
 | * @metaType values of xmlSchemaAttrInfo. | 
 | */ | 
 | #define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1 | 
 | #define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2 | 
 | #define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3 | 
 | #define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4 | 
 | #define XML_SCHEMA_ATTR_INFO_META_XMLNS 5 | 
 |  | 
 | typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo; | 
 | typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr; | 
 | struct _xmlSchemaAttrInfo { | 
 |     int nodeType; | 
 |     xmlNodePtr node; | 
 |     int nodeLine; | 
 |     const xmlChar *localName; | 
 |     const xmlChar *nsName; | 
 |     const xmlChar *value; | 
 |     xmlSchemaValPtr val; /* the pre-computed value if any */ | 
 |     xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */ | 
 |     int flags; /* combination of node info flags */ | 
 |  | 
 |     xmlSchemaAttributePtr decl; /* the attribute declaration */ | 
 |     xmlSchemaAttributeUsePtr use;  /* the attribute use */ | 
 |     int state; | 
 |     int metaType; | 
 |     const xmlChar *vcValue; /* the value constraint value */ | 
 |     xmlSchemaNodeInfoPtr parent; | 
 | }; | 
 |  | 
 |  | 
 | #define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1 | 
 | /** | 
 |  * xmlSchemaValidCtxt: | 
 |  * | 
 |  * A Schemas validation context | 
 |  */ | 
 | struct _xmlSchemaValidCtxt { | 
 |     int type; | 
 |     void *errCtxt;             /* user specific data block */ | 
 |     xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */ | 
 |     xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */ | 
 |     xmlStructuredErrorFunc serror; | 
 |  | 
 |     xmlSchemaPtr schema;        /* The schema in use */ | 
 |     xmlDocPtr doc; | 
 |     xmlParserInputBufferPtr input; | 
 |     xmlCharEncoding enc; | 
 |     xmlSAXHandlerPtr sax; | 
 |     xmlParserCtxtPtr parserCtxt; | 
 |     void *user_data; /* TODO: What is this for? */ | 
 |  | 
 |     int err; | 
 |     int nberrors; | 
 |  | 
 |     xmlNodePtr node; | 
 |     xmlNodePtr cur; | 
 |     /* xmlSchemaTypePtr type; */ | 
 |  | 
 |     xmlRegExecCtxtPtr regexp; | 
 |     xmlSchemaValPtr value; | 
 |  | 
 |     int valueWS; | 
 |     int options; | 
 |     xmlNodePtr validationRoot; | 
 |     xmlSchemaParserCtxtPtr pctxt; | 
 |     int xsiAssemble; | 
 |  | 
 |     int depth; | 
 |     xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */ | 
 |     int sizeElemInfos; | 
 |     xmlSchemaNodeInfoPtr inode; /* the current element information */ | 
 |  | 
 |     xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */ | 
 |  | 
 |     xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */ | 
 |     xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */ | 
 |     xmlSchemaIDCMatcherPtr idcMatcherCache; /* Cache for IDC matcher objects. */ | 
 |  | 
 |     xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/ | 
 |     int nbIdcNodes; | 
 |     int sizeIdcNodes; | 
 |  | 
 |     xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */ | 
 |     int nbIdcKeys; | 
 |     int sizeIdcKeys; | 
 |  | 
 |     int flags; | 
 |  | 
 |     xmlDictPtr dict; | 
 |  | 
 | #ifdef LIBXML_READER_ENABLED | 
 |     xmlTextReaderPtr reader; | 
 | #endif | 
 |  | 
 |     xmlSchemaAttrInfoPtr *attrInfos; | 
 |     int nbAttrInfos; | 
 |     int sizeAttrInfos; | 
 |  | 
 |     int skipDepth; | 
 |     xmlSchemaItemListPtr nodeQNames; | 
 |     int hasKeyrefs; | 
 |     int createIDCNodeTables; | 
 |     int psviExposeIDCNodeTables; | 
 | }; | 
 |  | 
 | /** | 
 |  * xmlSchemaSubstGroup: | 
 |  * | 
 |  * | 
 |  */ | 
 | typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup; | 
 | typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr; | 
 | struct _xmlSchemaSubstGroup { | 
 |     xmlSchemaElementPtr head; | 
 |     xmlSchemaItemListPtr members; | 
 | }; | 
 |  | 
 | /************************************************************************ | 
 |  * 									* | 
 |  * 			Some predeclarations				* | 
 |  * 									* | 
 |  ************************************************************************/ | 
 |  | 
 | static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, | 
 |                                  xmlSchemaPtr schema, | 
 |                                  xmlNodePtr node); | 
 | static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt, | 
 |                                  xmlSchemaPtr schema, | 
 |                                  xmlNodePtr node); | 
 | static int | 
 | xmlSchemaTypeFixup(xmlSchemaTypePtr type, | 
 |                    xmlSchemaAbstractCtxtPtr ctxt); | 
 | static const xmlChar * | 
 | xmlSchemaFacetTypeToString(xmlSchemaTypeType type); | 
 | static int | 
 | xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | 
 |                      xmlNodePtr node); | 
 | static int | 
 | xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl, | 
 |                        xmlSchemaParserCtxtPtr ctxt); | 
 | static void | 
 | xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt); | 
 | static xmlSchemaWhitespaceValueType | 
 | xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type); | 
 | static xmlSchemaTreeItemPtr | 
 | xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | 
 | 			 xmlNodePtr node, xmlSchemaTypeType type, | 
 | 			 int withParticle); | 
 | static const xmlChar * | 
 | xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item); | 
 | static xmlSchemaTypeLinkPtr | 
 | xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type); | 
 | static void | 
 | xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt, | 
 | 		     const char *funcName, | 
 | 		     const char *message); | 
 | static int | 
 | xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt, | 
 | 			     xmlSchemaTypePtr type, | 
 | 			     xmlSchemaTypePtr baseType, | 
 | 			     int subset); | 
 | static void | 
 | xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl, | 
 | 				   xmlSchemaParserCtxtPtr ctxt); | 
 | static void | 
 | xmlSchemaComponentListFree(xmlSchemaItemListPtr list); | 
 | static xmlSchemaQNameRefPtr | 
 | xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt, | 
 | 				xmlSchemaPtr schema, | 
 | 				xmlNodePtr node); | 
 |  | 
 | /************************************************************************ | 
 |  *									* | 
 |  * 			Helper functions			        * | 
 |  *									* | 
 |  ************************************************************************/ | 
 |  | 
 | /** | 
 |  * xmlSchemaItemTypeToStr: | 
 |  * @type: the type of the schema item | 
 |  * | 
 |  * Returns the component name of a schema item. | 
 |  */ | 
 | static const xmlChar * | 
 | xmlSchemaItemTypeToStr(xmlSchemaTypeType type) | 
 | { | 
 |     switch (type) { | 
 | 	case XML_SCHEMA_TYPE_BASIC: | 
 | 	    return(BAD_CAST "simple type definition"); | 
 | 	case XML_SCHEMA_TYPE_SIMPLE: | 
 | 	    return(BAD_CAST "simple type definition"); | 
 | 	case XML_SCHEMA_TYPE_COMPLEX: | 
 | 	    return(BAD_CAST "complex type definition"); | 
 | 	case XML_SCHEMA_TYPE_ELEMENT: | 
 | 	    return(BAD_CAST "element declaration"); | 
 | 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE: | 
 | 	    return(BAD_CAST "attribute use"); | 
 | 	case XML_SCHEMA_TYPE_ATTRIBUTE: | 
 | 	    return(BAD_CAST "attribute declaration"); | 
 | 	case XML_SCHEMA_TYPE_GROUP: | 
 | 	    return(BAD_CAST "model group definition"); | 
 | 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: | 
 | 	    return(BAD_CAST "attribute group definition"); | 
 | 	case XML_SCHEMA_TYPE_NOTATION: | 
 | 	    return(BAD_CAST "notation declaration"); | 
 | 	case XML_SCHEMA_TYPE_SEQUENCE: | 
 | 	    return(BAD_CAST "model group (sequence)"); | 
 | 	case XML_SCHEMA_TYPE_CHOICE: | 
 | 	    return(BAD_CAST "model group (choice)"); | 
 | 	case XML_SCHEMA_TYPE_ALL: | 
 | 	    return(BAD_CAST "model group (all)"); | 
 | 	case XML_SCHEMA_TYPE_PARTICLE: | 
 | 	    return(BAD_CAST "particle"); | 
 | 	case XML_SCHEMA_TYPE_IDC_UNIQUE: | 
 | 	    return(BAD_CAST "unique identity-constraint"); | 
 | 	    /* return(BAD_CAST "IDC (unique)"); */ | 
 | 	case XML_SCHEMA_TYPE_IDC_KEY: | 
 | 	    return(BAD_CAST "key identity-constraint"); | 
 | 	    /* return(BAD_CAST "IDC (key)"); */ | 
 | 	case XML_SCHEMA_TYPE_IDC_KEYREF: | 
 | 	    return(BAD_CAST "keyref identity-constraint"); | 
 | 	    /* return(BAD_CAST "IDC (keyref)"); */ | 
 | 	case XML_SCHEMA_TYPE_ANY: | 
 | 	    return(BAD_CAST "wildcard (any)"); | 
 | 	case XML_SCHEMA_EXTRA_QNAMEREF: | 
 | 	    return(BAD_CAST "[helper component] QName reference"); | 
 | 	case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB: | 
 | 	    return(BAD_CAST "[helper component] attribute use prohibition"); | 
 | 	default: | 
 | 	    return(BAD_CAST "Not a schema component"); | 
 |     } | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaGetComponentTypeStr: | 
 |  * @type: the type of the schema item | 
 |  * | 
 |  * Returns the component name of a schema item. | 
 |  */ | 
 | static const xmlChar * | 
 | xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item) | 
 | { | 
 |     switch (item->type) { | 
 | 	case XML_SCHEMA_TYPE_BASIC: | 
 | 	    if (WXS_IS_COMPLEX(WXS_TYPE_CAST item)) | 
 | 		return(BAD_CAST "complex type definition"); | 
 | 	    else | 
 | 		return(BAD_CAST "simple type definition"); | 
 | 	default: | 
 | 	    return(xmlSchemaItemTypeToStr(item->type)); | 
 |     } | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaGetComponentNode: | 
 |  * @item: a schema component | 
 |  * | 
 |  * Returns node associated with the schema component. | 
 |  * NOTE that such a node need not be available; plus, a component's | 
 |  * node need not to reflect the component directly, since there is no | 
 |  * one-to-one relationship between the XML Schema representation and | 
 |  * the component representation. | 
 |  */ | 
 | static xmlNodePtr | 
 | xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item) | 
 | { | 
 |     switch (item->type) { | 
 | 	case XML_SCHEMA_TYPE_ELEMENT: | 
 | 	    return (((xmlSchemaElementPtr) item)->node); | 
 | 	case XML_SCHEMA_TYPE_ATTRIBUTE: | 
 | 	    return (((xmlSchemaAttributePtr) item)->node); | 
 | 	case XML_SCHEMA_TYPE_COMPLEX: | 
 | 	case XML_SCHEMA_TYPE_SIMPLE: | 
 | 	    return (((xmlSchemaTypePtr) item)->node); | 
 | 	case XML_SCHEMA_TYPE_ANY: | 
 | 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE: | 
 | 	    return (((xmlSchemaWildcardPtr) item)->node); | 
 | 	case XML_SCHEMA_TYPE_PARTICLE: | 
 | 	    return (((xmlSchemaParticlePtr) item)->node); | 
 | 	case XML_SCHEMA_TYPE_SEQUENCE: | 
 | 	case XML_SCHEMA_TYPE_CHOICE: | 
 | 	case XML_SCHEMA_TYPE_ALL: | 
 | 	    return (((xmlSchemaModelGroupPtr) item)->node); | 
 | 	case XML_SCHEMA_TYPE_GROUP: | 
 | 	    return (((xmlSchemaModelGroupDefPtr) item)->node); | 
 | 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: | 
 | 	    return (((xmlSchemaAttributeGroupPtr) item)->node); | 
 | 	case XML_SCHEMA_TYPE_IDC_UNIQUE: | 
 | 	case XML_SCHEMA_TYPE_IDC_KEY: | 
 | 	case XML_SCHEMA_TYPE_IDC_KEYREF: | 
 | 	    return (((xmlSchemaIDCPtr) item)->node); | 
 | 	case XML_SCHEMA_EXTRA_QNAMEREF: | 
 | 	    return(((xmlSchemaQNameRefPtr) item)->node); | 
 | 	/* TODO: What to do with NOTATIONs? | 
 | 	case XML_SCHEMA_TYPE_NOTATION: | 
 | 	    return (((xmlSchemaNotationPtr) item)->node); | 
 | 	*/ | 
 | 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE: | 
 | 	    return (((xmlSchemaAttributeUsePtr) item)->node); | 
 | 	default: | 
 | 	    return (NULL); | 
 |     } | 
 | } | 
 |  | 
 | #if 0 | 
 | /** | 
 |  * xmlSchemaGetNextComponent: | 
 |  * @item: a schema component | 
 |  * | 
 |  * Returns the next sibling of the schema component. | 
 |  */ | 
 | static xmlSchemaBasicItemPtr | 
 | xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item) | 
 | { | 
 |     switch (item->type) { | 
 | 	case XML_SCHEMA_TYPE_ELEMENT: | 
 | 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next); | 
 | 	case XML_SCHEMA_TYPE_ATTRIBUTE: | 
 | 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next); | 
 | 	case XML_SCHEMA_TYPE_COMPLEX: | 
 | 	case XML_SCHEMA_TYPE_SIMPLE: | 
 | 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next); | 
 | 	case XML_SCHEMA_TYPE_ANY: | 
 | 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE: | 
 | 	    return (NULL); | 
 | 	case XML_SCHEMA_TYPE_PARTICLE: | 
 | 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next); | 
 | 	case XML_SCHEMA_TYPE_SEQUENCE: | 
 | 	case XML_SCHEMA_TYPE_CHOICE: | 
 | 	case XML_SCHEMA_TYPE_ALL: | 
 | 	    return (NULL); | 
 | 	case XML_SCHEMA_TYPE_GROUP: | 
 | 	    return (NULL); | 
 | 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: | 
 | 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next); | 
 | 	case XML_SCHEMA_TYPE_IDC_UNIQUE: | 
 | 	case XML_SCHEMA_TYPE_IDC_KEY: | 
 | 	case XML_SCHEMA_TYPE_IDC_KEYREF: | 
 | 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next); | 
 | 	default: | 
 | 	    return (NULL); | 
 |     } | 
 | } | 
 | #endif | 
 |  | 
 |  | 
 | /** | 
 |  * xmlSchemaFormatQName: | 
 |  * @buf: the string buffer | 
 |  * @namespaceName:  the namespace name | 
 |  * @localName: the local name | 
 |  * | 
 |  * Returns the given QName in the format "{namespaceName}localName" or | 
 |  * just "localName" if @namespaceName is NULL. | 
 |  * | 
 |  * Returns the localName if @namespaceName is NULL, a formatted | 
 |  * string otherwise. | 
 |  */ | 
 | static const xmlChar* | 
 | xmlSchemaFormatQName(xmlChar **buf, | 
 | 		     const xmlChar *namespaceName, | 
 | 		     const xmlChar *localName) | 
 | { | 
 |     FREE_AND_NULL(*buf) | 
 |     if (namespaceName != NULL) { | 
 | 	*buf = xmlStrdup(BAD_CAST "{"); | 
 | 	*buf = xmlStrcat(*buf, namespaceName); | 
 | 	*buf = xmlStrcat(*buf, BAD_CAST "}"); | 
 |     } | 
 |     if (localName != NULL) { | 
 | 	if (namespaceName == NULL) | 
 | 	    return(localName); | 
 | 	*buf = xmlStrcat(*buf, localName); | 
 |     } else { | 
 | 	*buf = xmlStrcat(*buf, BAD_CAST "(NULL)"); | 
 |     } | 
 |     return ((const xmlChar *) *buf); | 
 | } | 
 |  | 
 | static const xmlChar* | 
 | xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName) | 
 | { | 
 |     if (ns != NULL) | 
 | 	return (xmlSchemaFormatQName(buf, ns->href, localName)); | 
 |     else | 
 | 	return (xmlSchemaFormatQName(buf, NULL, localName)); | 
 | } | 
 |  | 
 | static const xmlChar * | 
 | xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item) | 
 | { | 
 |     switch (item->type) { | 
 | 	case XML_SCHEMA_TYPE_ELEMENT: | 
 | 	    return (((xmlSchemaElementPtr) item)->name); | 
 | 	case XML_SCHEMA_TYPE_ATTRIBUTE: | 
 | 	    return (((xmlSchemaAttributePtr) item)->name); | 
 | 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: | 
 | 	    return (((xmlSchemaAttributeGroupPtr) item)->name); | 
 | 	case XML_SCHEMA_TYPE_BASIC: | 
 | 	case XML_SCHEMA_TYPE_SIMPLE: | 
 | 	case XML_SCHEMA_TYPE_COMPLEX: | 
 | 	    return (((xmlSchemaTypePtr) item)->name); | 
 | 	case XML_SCHEMA_TYPE_GROUP: | 
 | 	    return (((xmlSchemaModelGroupDefPtr) item)->name); | 
 | 	case XML_SCHEMA_TYPE_IDC_KEY: | 
 | 	case XML_SCHEMA_TYPE_IDC_UNIQUE: | 
 | 	case XML_SCHEMA_TYPE_IDC_KEYREF: | 
 | 	    return (((xmlSchemaIDCPtr) item)->name); | 
 | 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE: | 
 | 	    if (WXS_ATTRUSE_DECL(item) != NULL) { | 
 | 		return(xmlSchemaGetComponentName( | 
 | 		    WXS_BASIC_CAST WXS_ATTRUSE_DECL(item))); | 
 | 	    } else | 
 | 		return(NULL); | 
 | 	case XML_SCHEMA_EXTRA_QNAMEREF: | 
 | 	    return (((xmlSchemaQNameRefPtr) item)->name); | 
 | 	case XML_SCHEMA_TYPE_NOTATION: | 
 | 	    return (((xmlSchemaNotationPtr) item)->name); | 
 | 	default: | 
 | 	    /* | 
 | 	    * Other components cannot have names. | 
 | 	    */ | 
 | 	    break; | 
 |     } | 
 |     return (NULL); | 
 | } | 
 |  | 
 | #define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name | 
 | #define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace | 
 | /* | 
 | static const xmlChar * | 
 | xmlSchemaGetQNameRefName(void *ref) | 
 | { | 
 |     return(((xmlSchemaQNameRefPtr) ref)->name); | 
 | } | 
 |  | 
 | static const xmlChar * | 
 | xmlSchemaGetQNameRefTargetNs(void *ref) | 
 | { | 
 |     return(((xmlSchemaQNameRefPtr) ref)->targetNamespace); | 
 | } | 
 | */ | 
 |  | 
 | static const xmlChar * | 
 | xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item) | 
 | { | 
 |     switch (item->type) { | 
 | 	case XML_SCHEMA_TYPE_ELEMENT: | 
 | 	    return (((xmlSchemaElementPtr) item)->targetNamespace); | 
 | 	case XML_SCHEMA_TYPE_ATTRIBUTE: | 
 | 	    return (((xmlSchemaAttributePtr) item)->targetNamespace); | 
 | 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: | 
 | 	    return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace); | 
 | 	case XML_SCHEMA_TYPE_BASIC: | 
 | 	    return (BAD_CAST "http://www.w3.org/2001/XMLSchema"); | 
 | 	case XML_SCHEMA_TYPE_SIMPLE: | 
 | 	case XML_SCHEMA_TYPE_COMPLEX: | 
 | 	    return (((xmlSchemaTypePtr) item)->targetNamespace); | 
 | 	case XML_SCHEMA_TYPE_GROUP: | 
 | 	    return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace); | 
 | 	case XML_SCHEMA_TYPE_IDC_KEY: | 
 | 	case XML_SCHEMA_TYPE_IDC_UNIQUE: | 
 | 	case XML_SCHEMA_TYPE_IDC_KEYREF: | 
 | 	    return (((xmlSchemaIDCPtr) item)->targetNamespace); | 
 | 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE: | 
 | 	    if (WXS_ATTRUSE_DECL(item) != NULL) { | 
 | 		return(xmlSchemaGetComponentTargetNs( | 
 | 		    WXS_BASIC_CAST WXS_ATTRUSE_DECL(item))); | 
 | 	    } | 
 | 	    /* TODO: Will returning NULL break something? */ | 
 | 	    break; | 
 | 	case XML_SCHEMA_EXTRA_QNAMEREF: | 
 | 	    return (((xmlSchemaQNameRefPtr) item)->targetNamespace); | 
 | 	case XML_SCHEMA_TYPE_NOTATION: | 
 | 	    return (((xmlSchemaNotationPtr) item)->targetNamespace); | 
 | 	default: | 
 | 	    /* | 
 | 	    * Other components cannot have names. | 
 | 	    */ | 
 | 	    break; | 
 |     } | 
 |     return (NULL); | 
 | } | 
 |  | 
 | static const xmlChar* | 
 | xmlSchemaGetComponentQName(xmlChar **buf, | 
 | 			   void *item) | 
 | { | 
 |     return (xmlSchemaFormatQName(buf, | 
 | 	xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item), | 
 | 	xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item))); | 
 | } | 
 |  | 
 | static const xmlChar* | 
 | xmlSchemaGetComponentDesignation(xmlChar **buf, void *item) | 
 | { | 
 |     xmlChar *str = NULL; | 
 |  | 
 |     *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item)); | 
 |     *buf = xmlStrcat(*buf, BAD_CAST " '"); | 
 |     *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, | 
 | 	(xmlSchemaBasicItemPtr) item)); | 
 |     *buf = xmlStrcat(*buf, BAD_CAST "'"); | 
 |     FREE_AND_NULL(str); | 
 |     return(*buf); | 
 | } | 
 |  | 
 | static const xmlChar* | 
 | xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc) | 
 | { | 
 |     return(xmlSchemaGetComponentDesignation(buf, idc)); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaWildcardPCToString: | 
 |  * @pc: the type of processContents | 
 |  * | 
 |  * Returns a string representation of the type of | 
 |  * processContents. | 
 |  */ | 
 | static const xmlChar * | 
 | xmlSchemaWildcardPCToString(int pc) | 
 | { | 
 |     switch (pc) { | 
 | 	case XML_SCHEMAS_ANY_SKIP: | 
 | 	    return (BAD_CAST "skip"); | 
 | 	case XML_SCHEMAS_ANY_LAX: | 
 | 	    return (BAD_CAST "lax"); | 
 | 	case XML_SCHEMAS_ANY_STRICT: | 
 | 	    return (BAD_CAST "strict"); | 
 | 	default: | 
 | 	    return (BAD_CAST "invalid process contents"); | 
 |     } | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaGetCanonValueWhtspExt: | 
 |  * @val: the precomputed value | 
 |  * @retValue: the returned value | 
 |  * @ws: the whitespace type of the value | 
 |  * | 
 |  * Get a the cononical representation of the value. | 
 |  * The caller has to free the returned retValue. | 
 |  * | 
 |  * Returns 0 if the value could be built and -1 in case of | 
 |  *         API errors or if the value type is not supported yet. | 
 |  */ | 
 | static int | 
 | xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val, | 
 | 			       xmlSchemaWhitespaceValueType ws, | 
 | 			       xmlChar **retValue) | 
 | { | 
 |     int list; | 
 |     xmlSchemaValType valType; | 
 |     const xmlChar *value, *value2 = NULL; | 
 |  | 
 |  | 
 |     if ((retValue == NULL) || (val == NULL)) | 
 | 	return (-1); | 
 |     list = xmlSchemaValueGetNext(val) ? 1 : 0; | 
 |     *retValue = NULL; | 
 |     do { | 
 | 	value = NULL; | 
 | 	valType = xmlSchemaGetValType(val); | 
 | 	switch (valType) { | 
 | 	    case XML_SCHEMAS_STRING: | 
 | 	    case XML_SCHEMAS_NORMSTRING: | 
 | 	    case XML_SCHEMAS_ANYSIMPLETYPE: | 
 | 		value = xmlSchemaValueGetAsString(val); | 
 | 		if (value != NULL) { | 
 | 		    if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE) | 
 | 			value2 = xmlSchemaCollapseString(value); | 
 | 		    else if (ws == XML_SCHEMA_WHITESPACE_REPLACE) | 
 | 			value2 = xmlSchemaWhiteSpaceReplace(value); | 
 | 		    if (value2 != NULL) | 
 | 			value = value2; | 
 | 		} | 
 | 		break; | 
 | 	    default: | 
 | 		if (xmlSchemaGetCanonValue(val, &value2) == -1) { | 
 | 		    if (value2 != NULL) | 
 | 			xmlFree((xmlChar *) value2); | 
 | 		    goto internal_error; | 
 | 		} | 
 | 		value = value2; | 
 | 	} | 
 | 	if (*retValue == NULL) | 
 | 	    if (value == NULL) { | 
 | 		if (! list) | 
 | 		    *retValue = xmlStrdup(BAD_CAST ""); | 
 | 	    } else | 
 | 		*retValue = xmlStrdup(value); | 
 | 	else if (value != NULL) { | 
 | 	    /* List. */ | 
 | 	    *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " "); | 
 | 	    *retValue = xmlStrcat((xmlChar *) *retValue, value); | 
 | 	} | 
 | 	FREE_AND_NULL(value2) | 
 | 	val = xmlSchemaValueGetNext(val); | 
 |     } while (val != NULL); | 
 |  | 
 |     return (0); | 
 | internal_error: | 
 |     if (*retValue != NULL) | 
 | 	xmlFree((xmlChar *) (*retValue)); | 
 |     if (value2 != NULL) | 
 | 	xmlFree((xmlChar *) value2); | 
 |     return (-1); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaFormatItemForReport: | 
 |  * @buf: the string buffer | 
 |  * @itemDes: the designation of the item | 
 |  * @itemName: the name of the item | 
 |  * @item: the item as an object | 
 |  * @itemNode: the node of the item | 
 |  * @local: the local name | 
 |  * @parsing: if the function is used during the parse | 
 |  * | 
 |  * Returns a representation of the given item used | 
 |  * for error reports. | 
 |  * | 
 |  * The following order is used to build the resulting | 
 |  * designation if the arguments are not NULL: | 
 |  * 1a. If itemDes not NULL -> itemDes | 
 |  * 1b. If (itemDes not NULL) and (itemName not NULL) | 
 |  *     -> itemDes + itemName | 
 |  * 2. If the preceding was NULL and (item not NULL) -> item | 
 |  * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode | 
 |  * | 
 |  * If the itemNode is an attribute node, the name of the attribute | 
 |  * will be appended to the result. | 
 |  * | 
 |  * Returns the formatted string and sets @buf to the resulting value. | 
 |  */ | 
 | static xmlChar* | 
 | xmlSchemaFormatItemForReport(xmlChar **buf, | 
 | 		     const xmlChar *itemDes, | 
 | 		     xmlSchemaBasicItemPtr item, | 
 | 		     xmlNodePtr itemNode) | 
 | { | 
 |     xmlChar *str = NULL; | 
 |     int named = 1; | 
 |  | 
 |     if (*buf != NULL) { | 
 | 	xmlFree(*buf); | 
 | 	*buf = NULL; | 
 |     } | 
 |  | 
 |     if (itemDes != NULL) { | 
 | 	*buf = xmlStrdup(itemDes); | 
 |     } else if (item != NULL) { | 
 | 	switch (item->type) { | 
 | 	case XML_SCHEMA_TYPE_BASIC: { | 
 | 	    xmlSchemaTypePtr type = WXS_TYPE_CAST item; | 
 |  | 
 | 	    if (WXS_IS_ATOMIC(type)) | 
 | 		*buf = xmlStrdup(BAD_CAST "atomic type 'xs:"); | 
 | 	    else if (WXS_IS_LIST(type)) | 
 | 		*buf = xmlStrdup(BAD_CAST "list type 'xs:"); | 
 | 	    else if (WXS_IS_UNION(type)) | 
 | 		*buf = xmlStrdup(BAD_CAST "union type 'xs:"); | 
 | 	    else | 
 | 		*buf = xmlStrdup(BAD_CAST "simple type 'xs:"); | 
 | 	    *buf = xmlStrcat(*buf, type->name); | 
 | 	    *buf = xmlStrcat(*buf, BAD_CAST "'"); | 
 | 	    } | 
 | 	    break; | 
 | 	case XML_SCHEMA_TYPE_SIMPLE: { | 
 | 	    xmlSchemaTypePtr type = WXS_TYPE_CAST item; | 
 |  | 
 | 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) { | 
 | 		*buf = xmlStrdup(BAD_CAST""); | 
 | 	    } else { | 
 | 		*buf = xmlStrdup(BAD_CAST "local "); | 
 | 	    } | 
 | 	    if (WXS_IS_ATOMIC(type)) | 
 | 		*buf = xmlStrcat(*buf, BAD_CAST "atomic type"); | 
 | 	    else if (WXS_IS_LIST(type)) | 
 | 		*buf = xmlStrcat(*buf, BAD_CAST "list type"); | 
 | 	    else if (WXS_IS_UNION(type)) | 
 | 		*buf = xmlStrcat(*buf, BAD_CAST "union type"); | 
 | 	    else | 
 | 		*buf = xmlStrcat(*buf, BAD_CAST "simple type"); | 
 | 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) { | 
 | 		*buf = xmlStrcat(*buf, BAD_CAST " '"); | 
 | 		*buf = xmlStrcat(*buf, type->name); | 
 | 		*buf = xmlStrcat(*buf, BAD_CAST "'"); | 
 | 	    } | 
 | 	    } | 
 | 	    break; | 
 | 	case XML_SCHEMA_TYPE_COMPLEX: { | 
 | 	    xmlSchemaTypePtr type = WXS_TYPE_CAST item; | 
 |  | 
 | 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) | 
 | 		*buf = xmlStrdup(BAD_CAST ""); | 
 | 	    else | 
 | 		*buf = xmlStrdup(BAD_CAST "local "); | 
 | 	    *buf = xmlStrcat(*buf, BAD_CAST "complex type"); | 
 | 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) { | 
 | 		*buf = xmlStrcat(*buf, BAD_CAST " '"); | 
 | 		*buf = xmlStrcat(*buf, type->name); | 
 | 		*buf = xmlStrcat(*buf, BAD_CAST "'"); | 
 | 	    } | 
 | 	    } | 
 | 	    break; | 
 | 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE: { | 
 | 		xmlSchemaAttributeUsePtr ause; | 
 |  | 
 | 		ause = WXS_ATTR_USE_CAST item; | 
 | 		*buf = xmlStrdup(BAD_CAST "attribute use "); | 
 | 		if (WXS_ATTRUSE_DECL(ause) != NULL) { | 
 | 		    *buf = xmlStrcat(*buf, BAD_CAST "'"); | 
 | 		    *buf = xmlStrcat(*buf, | 
 | 			xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause))); | 
 | 		    FREE_AND_NULL(str) | 
 | 			*buf = xmlStrcat(*buf, BAD_CAST "'"); | 
 | 		} else { | 
 | 		    *buf = xmlStrcat(*buf, BAD_CAST "(unknown)"); | 
 | 		} | 
 | 	    } | 
 | 	    break; | 
 | 	case XML_SCHEMA_TYPE_ATTRIBUTE: { | 
 | 		xmlSchemaAttributePtr attr; | 
 |  | 
 | 		attr = (xmlSchemaAttributePtr) item; | 
 | 		*buf = xmlStrdup(BAD_CAST "attribute decl."); | 
 | 		*buf = xmlStrcat(*buf, BAD_CAST " '"); | 
 | 		*buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str, | 
 | 		    attr->targetNamespace, attr->name)); | 
 | 		FREE_AND_NULL(str) | 
 | 		    *buf = xmlStrcat(*buf, BAD_CAST "'"); | 
 | 	    } | 
 | 	    break; | 
 | 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: | 
 | 	    xmlSchemaGetComponentDesignation(buf, item); | 
 | 	    break; | 
 | 	case XML_SCHEMA_TYPE_ELEMENT: { | 
 | 		xmlSchemaElementPtr elem; | 
 |  | 
 | 		elem = (xmlSchemaElementPtr) item; | 
 | 		*buf = xmlStrdup(BAD_CAST "element decl."); | 
 | 		*buf = xmlStrcat(*buf, BAD_CAST " '"); | 
 | 		*buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str, | 
 | 		    elem->targetNamespace, elem->name)); | 
 | 		*buf = xmlStrcat(*buf, BAD_CAST "'"); | 
 | 	    } | 
 | 	    break; | 
 | 	case XML_SCHEMA_TYPE_IDC_UNIQUE: | 
 | 	case XML_SCHEMA_TYPE_IDC_KEY: | 
 | 	case XML_SCHEMA_TYPE_IDC_KEYREF: | 
 | 	    if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE) | 
 | 		*buf = xmlStrdup(BAD_CAST "unique '"); | 
 | 	    else if (item->type == XML_SCHEMA_TYPE_IDC_KEY) | 
 | 		*buf = xmlStrdup(BAD_CAST "key '"); | 
 | 	    else | 
 | 		*buf = xmlStrdup(BAD_CAST "keyRef '"); | 
 | 	    *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name); | 
 | 	    *buf = xmlStrcat(*buf, BAD_CAST "'"); | 
 | 	    break; | 
 | 	case XML_SCHEMA_TYPE_ANY: | 
 | 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE: | 
 | 	    *buf = xmlStrdup(xmlSchemaWildcardPCToString( | 
 | 		    ((xmlSchemaWildcardPtr) item)->processContents)); | 
 | 	    *buf = xmlStrcat(*buf, BAD_CAST " wildcard"); | 
 | 	    break; | 
 | 	case XML_SCHEMA_FACET_MININCLUSIVE: | 
 | 	case XML_SCHEMA_FACET_MINEXCLUSIVE: | 
 | 	case XML_SCHEMA_FACET_MAXINCLUSIVE: | 
 | 	case XML_SCHEMA_FACET_MAXEXCLUSIVE: | 
 | 	case XML_SCHEMA_FACET_TOTALDIGITS: | 
 | 	case XML_SCHEMA_FACET_FRACTIONDIGITS: | 
 | 	case XML_SCHEMA_FACET_PATTERN: | 
 | 	case XML_SCHEMA_FACET_ENUMERATION: | 
 | 	case XML_SCHEMA_FACET_WHITESPACE: | 
 | 	case XML_SCHEMA_FACET_LENGTH: | 
 | 	case XML_SCHEMA_FACET_MAXLENGTH: | 
 | 	case XML_SCHEMA_FACET_MINLENGTH: | 
 | 	    *buf = xmlStrdup(BAD_CAST "facet '"); | 
 | 	    *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type)); | 
 | 	    *buf = xmlStrcat(*buf, BAD_CAST "'"); | 
 | 	    break; | 
 | 	case XML_SCHEMA_TYPE_GROUP: { | 
 | 		*buf = xmlStrdup(BAD_CAST "model group def."); | 
 | 		*buf = xmlStrcat(*buf, BAD_CAST " '"); | 
 | 		*buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item)); | 
 | 		*buf = xmlStrcat(*buf, BAD_CAST "'"); | 
 | 		FREE_AND_NULL(str) | 
 | 	    } | 
 | 	    break; | 
 | 	case XML_SCHEMA_TYPE_SEQUENCE: | 
 | 	case XML_SCHEMA_TYPE_CHOICE: | 
 | 	case XML_SCHEMA_TYPE_ALL: | 
 | 	case XML_SCHEMA_TYPE_PARTICLE: | 
 | 	    *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item)); | 
 | 	    break; | 
 | 	case XML_SCHEMA_TYPE_NOTATION: { | 
 | 		*buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item)); | 
 | 		*buf = xmlStrcat(*buf, BAD_CAST " '"); | 
 | 		*buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item)); | 
 | 		*buf = xmlStrcat(*buf, BAD_CAST "'"); | 
 | 		FREE_AND_NULL(str); | 
 | 	    } | 
 | 	default: | 
 | 	    named = 0; | 
 | 	} | 
 |     } else | 
 | 	named = 0; | 
 |  | 
 |     if ((named == 0) && (itemNode != NULL)) { | 
 | 	xmlNodePtr elem; | 
 |  | 
 | 	if (itemNode->type == XML_ATTRIBUTE_NODE) | 
 | 	    elem = itemNode->parent; | 
 | 	else | 
 | 	    elem = itemNode; | 
 | 	*buf = xmlStrdup(BAD_CAST "Element '"); | 
 | 	if (elem->ns != NULL) { | 
 | 	    *buf = xmlStrcat(*buf, | 
 | 		xmlSchemaFormatQName(&str, elem->ns->href, elem->name)); | 
 | 	    FREE_AND_NULL(str) | 
 | 	} else | 
 | 	    *buf = xmlStrcat(*buf, elem->name); | 
 | 	*buf = xmlStrcat(*buf, BAD_CAST "'"); | 
 |  | 
 |     } | 
 |     if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) { | 
 | 	*buf = xmlStrcat(*buf, BAD_CAST ", attribute '"); | 
 | 	if (itemNode->ns != NULL) { | 
 | 	    *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str, | 
 | 		itemNode->ns->href, itemNode->name)); | 
 | 	    FREE_AND_NULL(str) | 
 | 	} else | 
 | 	    *buf = xmlStrcat(*buf, itemNode->name); | 
 | 	*buf = xmlStrcat(*buf, BAD_CAST "'"); | 
 |     } | 
 |     FREE_AND_NULL(str) | 
 |  | 
 |     return (*buf); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaFormatFacetEnumSet: | 
 |  * @buf: the string buffer | 
 |  * @type: the type holding the enumeration facets | 
 |  * | 
 |  * Builds a string consisting of all enumeration elements. | 
 |  * | 
 |  * Returns a string of all enumeration elements. | 
 |  */ | 
 | static const xmlChar * | 
 | xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt, | 
 | 			    xmlChar **buf, xmlSchemaTypePtr type) | 
 | { | 
 |     xmlSchemaFacetPtr facet; | 
 |     xmlSchemaWhitespaceValueType ws; | 
 |     xmlChar *value = NULL; | 
 |     int res, found = 0; | 
 |  | 
 |     if (*buf != NULL) | 
 | 	xmlFree(*buf); | 
 |     *buf = NULL; | 
 |  | 
 |     do { | 
 | 	/* | 
 | 	* Use the whitespace type of the base type. | 
 | 	*/ | 
 | 	ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType); | 
 | 	for (facet = type->facets; facet != NULL; facet = facet->next) { | 
 | 	    if (facet->type != XML_SCHEMA_FACET_ENUMERATION) | 
 | 		continue; | 
 | 	    found = 1; | 
 | 	    res = xmlSchemaGetCanonValueWhtspExt(facet->val, | 
 | 		ws, &value); | 
 | 	    if (res == -1) { | 
 | 		xmlSchemaInternalErr(actxt, | 
 | 		    "xmlSchemaFormatFacetEnumSet", | 
 | 		    "compute the canonical lexical representation"); | 
 | 		if (*buf != NULL) | 
 | 		    xmlFree(*buf); | 
 | 		*buf = NULL; | 
 | 		return (NULL); | 
 | 	    } | 
 | 	    if (*buf == NULL) | 
 | 		*buf = xmlStrdup(BAD_CAST "'"); | 
 | 	    else | 
 | 		*buf = xmlStrcat(*buf, BAD_CAST ", '"); | 
 | 	    *buf = xmlStrcat(*buf, BAD_CAST value); | 
 | 	    *buf = xmlStrcat(*buf, BAD_CAST "'"); | 
 | 	    if (value != NULL) { | 
 | 		xmlFree((xmlChar *)value); | 
 | 		value = NULL; | 
 | 	    } | 
 | 	} | 
 | 	/* | 
 | 	* The enumeration facet of a type restricts the enumeration | 
 | 	* facet of the ancestor type; i.e., such restricted enumerations | 
 | 	* do not belong to the set of the given type. Thus we break | 
 | 	* on the first found enumeration. | 
 | 	*/ | 
 | 	if (found) | 
 | 	    break; | 
 | 	type = type->baseType; | 
 |     } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC)); | 
 |  | 
 |     return ((const xmlChar *) *buf); | 
 | } | 
 |  | 
 | /************************************************************************ | 
 |  *									* | 
 |  * 			Error functions				        * | 
 |  *									* | 
 |  ************************************************************************/ | 
 |  | 
 | #if 0 | 
 | static void | 
 | xmlSchemaErrMemory(const char *msg) | 
 | { | 
 |     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL, | 
 |                      msg); | 
 | } | 
 | #endif | 
 |  | 
 | static void | 
 | xmlSchemaPSimpleErr(const char *msg) | 
 | { | 
 |     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL, | 
 |                      msg); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaPErrMemory: | 
 |  * @node: a context node | 
 |  * @extra:  extra informations | 
 |  * | 
 |  * Handle an out of memory condition | 
 |  */ | 
 | static void | 
 | xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt, | 
 |                     const char *extra, xmlNodePtr node) | 
 | { | 
 |     if (ctxt != NULL) | 
 |         ctxt->nberrors++; | 
 |     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL, | 
 |                      extra); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaPErr: | 
 |  * @ctxt: the parsing context | 
 |  * @node: the context node | 
 |  * @error: the error code | 
 |  * @msg: the error message | 
 |  * @str1: extra data | 
 |  * @str2: extra data | 
 |  * | 
 |  * Handle a parser error | 
 |  */ | 
 | static void | 
 | xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error, | 
 |               const char *msg, const xmlChar * str1, const xmlChar * str2) | 
 | { | 
 |     xmlGenericErrorFunc channel = NULL; | 
 |     xmlStructuredErrorFunc schannel = NULL; | 
 |     void *data = NULL; | 
 |  | 
 |     if (ctxt != NULL) { | 
 |         ctxt->nberrors++; | 
 | 	ctxt->err = error; | 
 |         channel = ctxt->error; | 
 |         data = ctxt->errCtxt; | 
 | 	schannel = ctxt->serror; | 
 |     } | 
 |     __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP, | 
 |                     error, XML_ERR_ERROR, NULL, 0, | 
 |                     (const char *) str1, (const char *) str2, NULL, 0, 0, | 
 |                     msg, str1, str2); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaPErr2: | 
 |  * @ctxt: the parsing context | 
 |  * @node: the context node | 
 |  * @node: the current child | 
 |  * @error: the error code | 
 |  * @msg: the error message | 
 |  * @str1: extra data | 
 |  * @str2: extra data | 
 |  * | 
 |  * Handle a parser error | 
 |  */ | 
 | static void | 
 | xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, | 
 |                xmlNodePtr child, int error, | 
 |                const char *msg, const xmlChar * str1, const xmlChar * str2) | 
 | { | 
 |     if (child != NULL) | 
 |         xmlSchemaPErr(ctxt, child, error, msg, str1, str2); | 
 |     else | 
 |         xmlSchemaPErr(ctxt, node, error, msg, str1, str2); | 
 | } | 
 |  | 
 |  | 
 | /** | 
 |  * xmlSchemaPErrExt: | 
 |  * @ctxt: the parsing context | 
 |  * @node: the context node | 
 |  * @error: the error code | 
 |  * @strData1: extra data | 
 |  * @strData2: extra data | 
 |  * @strData3: extra data | 
 |  * @msg: the message | 
 |  * @str1:  extra parameter for the message display | 
 |  * @str2:  extra parameter for the message display | 
 |  * @str3:  extra parameter for the message display | 
 |  * @str4:  extra parameter for the message display | 
 |  * @str5:  extra parameter for the message display | 
 |  * | 
 |  * Handle a parser error | 
 |  */ | 
 | static void | 
 | xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error, | 
 | 		const xmlChar * strData1, const xmlChar * strData2, | 
 | 		const xmlChar * strData3, const char *msg, const xmlChar * str1, | 
 | 		const xmlChar * str2, const xmlChar * str3, const xmlChar * str4, | 
 | 		const xmlChar * str5) | 
 | { | 
 |  | 
 |     xmlGenericErrorFunc channel = NULL; | 
 |     xmlStructuredErrorFunc schannel = NULL; | 
 |     void *data = NULL; | 
 |  | 
 |     if (ctxt != NULL) { | 
 |         ctxt->nberrors++; | 
 | 	ctxt->err = error; | 
 |         channel = ctxt->error; | 
 |         data = ctxt->errCtxt; | 
 | 	schannel = ctxt->serror; | 
 |     } | 
 |     __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP, | 
 |                     error, XML_ERR_ERROR, NULL, 0, | 
 |                     (const char *) strData1, (const char *) strData2, | 
 | 		    (const char *) strData3, 0, 0, msg, str1, str2, | 
 | 		    str3, str4, str5); | 
 | } | 
 |  | 
 | /************************************************************************ | 
 |  *									* | 
 |  * 			Allround error functions			* | 
 |  *									* | 
 |  ************************************************************************/ | 
 |  | 
 | /** | 
 |  * xmlSchemaVTypeErrMemory: | 
 |  * @node: a context node | 
 |  * @extra:  extra informations | 
 |  * | 
 |  * Handle an out of memory condition | 
 |  */ | 
 | static void | 
 | xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt, | 
 |                     const char *extra, xmlNodePtr node) | 
 | { | 
 |     if (ctxt != NULL) { | 
 |         ctxt->nberrors++; | 
 |         ctxt->err = XML_SCHEMAV_INTERNAL; | 
 |     } | 
 |     __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL, | 
 |                      extra); | 
 | } | 
 |  | 
 | static void | 
 | xmlSchemaPSimpleInternalErr(xmlNodePtr node, | 
 | 			    const char *msg, const xmlChar *str) | 
 | { | 
 |      __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node, | 
 | 	 msg, (const char *) str); | 
 | } | 
 |  | 
 | #define WXS_ERROR_TYPE_ERROR 1 | 
 | #define WXS_ERROR_TYPE_WARNING 2 | 
 | /** | 
 |  * xmlSchemaErr3: | 
 |  * @ctxt: the validation context | 
 |  * @node: the context node | 
 |  * @error: the error code | 
 |  * @msg: the error message | 
 |  * @str1: extra data | 
 |  * @str2: extra data | 
 |  * @str3: extra data | 
 |  * | 
 |  * Handle a validation error | 
 |  */ | 
 | static void | 
 | xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt, | 
 | 		  xmlErrorLevel errorLevel, | 
 | 		  int error, xmlNodePtr node, int line, const char *msg, | 
 | 		  const xmlChar *str1, const xmlChar *str2, | 
 | 		  const xmlChar *str3, const xmlChar *str4) | 
 | { | 
 |     xmlStructuredErrorFunc schannel = NULL; | 
 |     xmlGenericErrorFunc channel = NULL; | 
 |     void *data = NULL; | 
 |  | 
 |     if (ctxt != NULL) { | 
 | 	if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) { | 
 | 	    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt; | 
 | 	    const char *file = NULL; | 
 | 	    if (errorLevel != XML_ERR_WARNING) { | 
 | 		vctxt->nberrors++; | 
 | 		vctxt->err = error; | 
 | 		channel = vctxt->error; | 
 | 	    } else { | 
 | 		channel = vctxt->warning; | 
 | 	    } | 
 | 	    schannel = vctxt->serror; | 
 | 	    data = vctxt->errCtxt; | 
 |  | 
 | 	    /* | 
 | 	    * Error node. If we specify a line number, then | 
 | 	    * do not channel any node to the error function. | 
 | 	    */ | 
 | 	    if (line == 0) { | 
 | 		if ((node == NULL) && | 
 | 		    (vctxt->depth >= 0) && | 
 | 		    (vctxt->inode != NULL)) { | 
 | 		    node = vctxt->inode->node; | 
 | 		} | 
 | 		/* | 
 | 		* Get filename and line if no node-tree. | 
 | 		*/ | 
 | 		if ((node == NULL) && | 
 | 		    (vctxt->parserCtxt != NULL) && | 
 | 		    (vctxt->parserCtxt->input != NULL)) { | 
 | 		    file = vctxt->parserCtxt->input->filename; | 
 | 		    line = vctxt->parserCtxt->input->line; | 
 | 		} | 
 | 	    } else { | 
 | 		/* | 
 | 		* Override the given node's (if any) position | 
 | 		* and channel only the given line number. | 
 | 		*/ | 
 | 		node = NULL; | 
 | 		/* | 
 | 		* Get filename. | 
 | 		*/ | 
 | 		if (vctxt->doc != NULL) | 
 | 		    file = (const char *) vctxt->doc->URL; | 
 | 		else if ((vctxt->parserCtxt != NULL) && | 
 | 		    (vctxt->parserCtxt->input != NULL)) | 
 | 		    file = vctxt->parserCtxt->input->filename; | 
 | 	    } | 
 | 	    __xmlRaiseError(schannel, channel, data, ctxt, | 
 | 		node, XML_FROM_SCHEMASV, | 
 | 		error, errorLevel, file, line, | 
 | 		(const char *) str1, (const char *) str2, | 
 | 		(const char *) str3, 0, 0, msg, str1, str2, str3, str4); | 
 |  | 
 | 	} else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) { | 
 | 	    xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt; | 
 | 	    if (errorLevel != XML_ERR_WARNING) { | 
 | 		pctxt->nberrors++; | 
 | 		pctxt->err = error; | 
 | 		channel = pctxt->error; | 
 | 	    } else { | 
 | 		channel = pctxt->warning; | 
 | 	    } | 
 | 	    schannel = pctxt->serror; | 
 | 	    data = pctxt->errCtxt; | 
 | 	    __xmlRaiseError(schannel, channel, data, ctxt, | 
 | 		node, XML_FROM_SCHEMASP, error, | 
 | 		errorLevel, NULL, 0, | 
 | 		(const char *) str1, (const char *) str2, | 
 | 		(const char *) str3, 0, 0, msg, str1, str2, str3, str4); | 
 | 	} else { | 
 | 	    TODO | 
 | 	} | 
 |     } | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaErr3: | 
 |  * @ctxt: the validation context | 
 |  * @node: the context node | 
 |  * @error: the error code | 
 |  * @msg: the error message | 
 |  * @str1: extra data | 
 |  * @str2: extra data | 
 |  * @str3: extra data | 
 |  * | 
 |  * Handle a validation error | 
 |  */ | 
 | static void | 
 | xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt, | 
 | 	      int error, xmlNodePtr node, const char *msg, | 
 | 	      const xmlChar *str1, const xmlChar *str2, const xmlChar *str3) | 
 | { | 
 |     xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0, | 
 | 	msg, str1, str2, str3, NULL); | 
 | } | 
 |  | 
 | static void | 
 | xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt, | 
 | 	      int error, xmlNodePtr node, const char *msg, | 
 | 	      const xmlChar *str1, const xmlChar *str2, | 
 | 	      const xmlChar *str3, const xmlChar *str4) | 
 | { | 
 |     xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0, | 
 | 	msg, str1, str2, str3, str4); | 
 | } | 
 |  | 
 | static void | 
 | xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt, | 
 | 	     int error, xmlNodePtr node, const char *msg, | 
 | 	     const xmlChar *str1, const xmlChar *str2) | 
 | { | 
 |     xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL); | 
 | } | 
 |  | 
 | static xmlChar * | 
 | xmlSchemaFormatNodeForError(xmlChar ** msg, | 
 | 			    xmlSchemaAbstractCtxtPtr actxt, | 
 | 			    xmlNodePtr node) | 
 | { | 
 |     xmlChar *str = NULL; | 
 |  | 
 |     *msg = NULL; | 
 |     if ((node != NULL) && | 
 | 	(node->type != XML_ELEMENT_NODE) && | 
 | 	(node->type != XML_ATTRIBUTE_NODE)) | 
 |     { | 
 | 	/* | 
 | 	* Don't try to format other nodes than element and | 
 | 	* attribute nodes. | 
 | 	* Play save and return an empty string. | 
 | 	*/ | 
 | 	*msg = xmlStrdup(BAD_CAST ""); | 
 | 	return(*msg); | 
 |     } | 
 |     if (node != NULL) { | 
 | 	/* | 
 | 	* Work on tree nodes. | 
 | 	*/ | 
 | 	if (node->type == XML_ATTRIBUTE_NODE) { | 
 | 	    xmlNodePtr elem = node->parent; | 
 |  | 
 | 	    *msg = xmlStrdup(BAD_CAST "Element '"); | 
 | 	    if (elem->ns != NULL) | 
 | 		*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str, | 
 | 		    elem->ns->href, elem->name)); | 
 | 	    else | 
 | 		*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str, | 
 | 		    NULL, elem->name)); | 
 | 	    FREE_AND_NULL(str); | 
 | 	    *msg = xmlStrcat(*msg, BAD_CAST "', "); | 
 | 	    *msg = xmlStrcat(*msg, BAD_CAST "attribute '"); | 
 | 	} else { | 
 | 	    *msg = xmlStrdup(BAD_CAST "Element '"); | 
 | 	} | 
 | 	if (node->ns != NULL) | 
 | 	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str, | 
 | 	    node->ns->href, node->name)); | 
 | 	else | 
 | 	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str, | 
 | 	    NULL, node->name)); | 
 | 	FREE_AND_NULL(str); | 
 | 	*msg = xmlStrcat(*msg, BAD_CAST "': "); | 
 |     } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) { | 
 | 	xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt; | 
 | 	/* | 
 | 	* Work on node infos. | 
 | 	*/ | 
 | 	if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) { | 
 | 	    xmlSchemaNodeInfoPtr ielem = | 
 | 		vctxt->elemInfos[vctxt->depth]; | 
 |  | 
 | 	    *msg = xmlStrdup(BAD_CAST "Element '"); | 
 | 	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str, | 
 | 		ielem->nsName, ielem->localName)); | 
 | 	    FREE_AND_NULL(str); | 
 | 	    *msg = xmlStrcat(*msg, BAD_CAST "', "); | 
 | 	    *msg = xmlStrcat(*msg, BAD_CAST "attribute '"); | 
 | 	} else { | 
 | 	    *msg = xmlStrdup(BAD_CAST "Element '"); | 
 | 	} | 
 | 	*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str, | 
 | 	    vctxt->inode->nsName, vctxt->inode->localName)); | 
 | 	FREE_AND_NULL(str); | 
 | 	*msg = xmlStrcat(*msg, BAD_CAST "': "); | 
 |     } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) { | 
 | 	/* | 
 | 	* Hmm, no node while parsing? | 
 | 	* Return an empty string, in case NULL will break something. | 
 | 	*/ | 
 | 	*msg = xmlStrdup(BAD_CAST ""); | 
 |     } else { | 
 | 	TODO | 
 | 	return (NULL); | 
 |     } | 
 |     /* | 
 |     * VAL TODO: The output of the given schema component is currently | 
 |     * disabled. | 
 |     */ | 
 | #if 0 | 
 |     if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) { | 
 | 	*msg = xmlStrcat(*msg, BAD_CAST " ["); | 
 | 	*msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str, | 
 | 	    NULL, type, NULL, 0)); | 
 | 	FREE_AND_NULL(str) | 
 | 	*msg = xmlStrcat(*msg, BAD_CAST "]"); | 
 |     } | 
 | #endif | 
 |     return (*msg); | 
 | } | 
 |  | 
 | static void | 
 | xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt, | 
 | 		     const char *funcName, | 
 | 		     const char *message, | 
 | 		     const xmlChar *str1, | 
 | 		     const xmlChar *str2) | 
 | { | 
 |     xmlChar *msg = NULL; | 
 |  | 
 |     if (actxt == NULL) | 
 |         return; | 
 |     msg = xmlStrdup(BAD_CAST "Internal error: "); | 
 |     msg = xmlStrcat(msg, BAD_CAST funcName); | 
 |     msg = xmlStrcat(msg, BAD_CAST ", "); | 
 |     msg = xmlStrcat(msg, BAD_CAST message); | 
 |     msg = xmlStrcat(msg, BAD_CAST ".\n"); | 
 |  | 
 |     if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) | 
 | 	xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL, | 
 | 	    (const char *) msg, str1, str2); | 
 |  | 
 |     else if (actxt->type == XML_SCHEMA_CTXT_PARSER) | 
 | 	xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL, | 
 | 	    (const char *) msg, str1, str2); | 
 |  | 
 |     FREE_AND_NULL(msg) | 
 | } | 
 |  | 
 | static void | 
 | xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt, | 
 | 		     const char *funcName, | 
 | 		     const char *message) | 
 | { | 
 |     xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL); | 
 | } | 
 |  | 
 | #if 0 | 
 | static void | 
 | xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt, | 
 | 		     const char *funcName, | 
 | 		     const char *message, | 
 | 		     const xmlChar *str1, | 
 | 		     const xmlChar *str2) | 
 | { | 
 |     xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message, | 
 | 	str1, str2); | 
 | } | 
 | #endif | 
 |  | 
 | static void | 
 | xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt, | 
 | 		   xmlParserErrors error, | 
 | 		   xmlNodePtr node, | 
 | 		   xmlSchemaBasicItemPtr item, | 
 | 		   const char *message, | 
 | 		   const xmlChar *str1, const xmlChar *str2, | 
 | 		   const xmlChar *str3, const xmlChar *str4) | 
 | { | 
 |     xmlChar *msg = NULL; | 
 |  | 
 |     if ((node == NULL) && (item != NULL) && | 
 | 	(actxt->type == XML_SCHEMA_CTXT_PARSER)) { | 
 | 	node = WXS_ITEM_NODE(item); | 
 | 	xmlSchemaFormatItemForReport(&msg, NULL, item, NULL); | 
 | 	msg = xmlStrcat(msg, BAD_CAST ": "); | 
 |     } else | 
 | 	xmlSchemaFormatNodeForError(&msg, actxt, node); | 
 |     msg = xmlStrcat(msg, (const xmlChar *) message); | 
 |     msg = xmlStrcat(msg, BAD_CAST ".\n"); | 
 |     xmlSchemaErr4(actxt, error, node, | 
 | 	(const char *) msg, str1, str2, str3, str4); | 
 |     FREE_AND_NULL(msg) | 
 | } | 
 |  | 
 | static void | 
 | xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt, | 
 | 		   xmlParserErrors error, | 
 | 		   xmlNodePtr node, | 
 | 		   xmlSchemaBasicItemPtr item, | 
 | 		   const char *message, | 
 | 		   const xmlChar *str1, | 
 | 		   const xmlChar *str2) | 
 | { | 
 |     xmlSchemaCustomErr4(actxt, error, node, item, | 
 | 	message, str1, str2, NULL, NULL); | 
 | } | 
 |  | 
 |  | 
 |  | 
 | static void | 
 | xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt, | 
 | 		   xmlParserErrors error, | 
 | 		   xmlNodePtr node, | 
 | 		   xmlSchemaTypePtr type ATTRIBUTE_UNUSED, | 
 | 		   const char *message, | 
 | 		   const xmlChar *str1, | 
 | 		   const xmlChar *str2, | 
 | 		   const xmlChar *str3) | 
 | { | 
 |     xmlChar *msg = NULL; | 
 |  | 
 |     xmlSchemaFormatNodeForError(&msg, actxt, node); | 
 |     msg = xmlStrcat(msg, (const xmlChar *) message); | 
 |     msg = xmlStrcat(msg, BAD_CAST ".\n"); | 
 |  | 
 |     /* URGENT TODO: Set the error code to something sane. */ | 
 |     xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0, | 
 | 	(const char *) msg, str1, str2, str3, NULL); | 
 |  | 
 |     FREE_AND_NULL(msg) | 
 | } | 
 |  | 
 |  | 
 |  | 
 | static void | 
 | xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt, | 
 | 		   xmlParserErrors error, | 
 | 		   xmlSchemaPSVIIDCNodePtr idcNode, | 
 | 		   xmlSchemaTypePtr type ATTRIBUTE_UNUSED, | 
 | 		   const char *message, | 
 | 		   const xmlChar *str1, | 
 | 		   const xmlChar *str2) | 
 | { | 
 |     xmlChar *msg = NULL, *qname = NULL; | 
 |  | 
 |     msg = xmlStrdup(BAD_CAST "Element '%s': "); | 
 |     msg = xmlStrcat(msg, (const xmlChar *) message); | 
 |     msg = xmlStrcat(msg, BAD_CAST ".\n"); | 
 |     xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR, | 
 | 	error, NULL, idcNode->nodeLine, (const char *) msg, | 
 | 	xmlSchemaFormatQName(&qname, | 
 | 	    vctxt->nodeQNames->items[idcNode->nodeQNameID +1], | 
 | 	    vctxt->nodeQNames->items[idcNode->nodeQNameID]), | 
 | 	str1, str2, NULL); | 
 |     FREE_AND_NULL(qname); | 
 |     FREE_AND_NULL(msg); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt, | 
 | 			   xmlNodePtr node) | 
 | { | 
 |     if (node != NULL) | 
 | 	return (node->type); | 
 |     if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) && | 
 | 	(((xmlSchemaValidCtxtPtr) actxt)->inode != NULL)) | 
 | 	return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType); | 
 |     return (-1); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaIsGlobalItem(xmlSchemaTypePtr item) | 
 | { | 
 |     switch (item->type) { | 
 | 	case XML_SCHEMA_TYPE_COMPLEX: | 
 | 	case XML_SCHEMA_TYPE_SIMPLE: | 
 | 	    if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) | 
 | 		return(1); | 
 | 	    break; | 
 | 	case XML_SCHEMA_TYPE_GROUP: | 
 | 	    return (1); | 
 | 	case XML_SCHEMA_TYPE_ELEMENT: | 
 | 	    if ( ((xmlSchemaElementPtr) item)->flags & | 
 | 		XML_SCHEMAS_ELEM_GLOBAL) | 
 | 		return(1); | 
 | 	    break; | 
 | 	case XML_SCHEMA_TYPE_ATTRIBUTE: | 
 | 	    if ( ((xmlSchemaAttributePtr) item)->flags & | 
 | 		XML_SCHEMAS_ATTR_GLOBAL) | 
 | 		return(1); | 
 | 	    break; | 
 | 	/* Note that attribute groups are always global. */ | 
 | 	default: | 
 | 	    return(1); | 
 |     } | 
 |     return (0); | 
 | } | 
 |  | 
 | static void | 
 | xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt, | 
 | 		       xmlParserErrors error, | 
 | 		       xmlNodePtr node, | 
 | 		       const xmlChar *value, | 
 | 		       xmlSchemaTypePtr type, | 
 | 		       int displayValue) | 
 | { | 
 |     xmlChar *msg = NULL; | 
 |  | 
 |     xmlSchemaFormatNodeForError(&msg, actxt, node); | 
 |  | 
 |     if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) == | 
 | 	    XML_ATTRIBUTE_NODE)) | 
 | 	msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of "); | 
 |     else | 
 | 	msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid " | 
 | 	    "value of "); | 
 |  | 
 |     if (! xmlSchemaIsGlobalItem(type)) | 
 | 	msg = xmlStrcat(msg, BAD_CAST "the local "); | 
 |     else | 
 | 	msg = xmlStrcat(msg, BAD_CAST "the "); | 
 |  | 
 |     if (WXS_IS_ATOMIC(type)) | 
 | 	msg = xmlStrcat(msg, BAD_CAST "atomic type"); | 
 |     else if (WXS_IS_LIST(type)) | 
 | 	msg = xmlStrcat(msg, BAD_CAST "list type"); | 
 |     else if (WXS_IS_UNION(type)) | 
 | 	msg = xmlStrcat(msg, BAD_CAST "union type"); | 
 |  | 
 |     if (xmlSchemaIsGlobalItem(type)) { | 
 | 	xmlChar *str = NULL; | 
 | 	msg = xmlStrcat(msg, BAD_CAST " '"); | 
 | 	if (type->builtInType != 0) { | 
 | 	    msg = xmlStrcat(msg, BAD_CAST "xs:"); | 
 | 	    msg = xmlStrcat(msg, type->name); | 
 | 	} else | 
 | 	    msg = xmlStrcat(msg, | 
 | 		xmlSchemaFormatQName(&str, | 
 | 		    type->targetNamespace, type->name)); | 
 | 	msg = xmlStrcat(msg, BAD_CAST "'"); | 
 | 	FREE_AND_NULL(str); | 
 |     } | 
 |     msg = xmlStrcat(msg, BAD_CAST ".\n"); | 
 |     if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) == | 
 | 	    XML_ATTRIBUTE_NODE)) | 
 | 	xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL); | 
 |     else | 
 | 	xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL); | 
 |     FREE_AND_NULL(msg) | 
 | } | 
 |  | 
 | static const xmlChar * | 
 | xmlSchemaFormatErrorNodeQName(xmlChar ** str, | 
 | 			      xmlSchemaNodeInfoPtr ni, | 
 | 			      xmlNodePtr node) | 
 | { | 
 |     if (node != NULL) { | 
 | 	if (node->ns != NULL) | 
 | 	    return (xmlSchemaFormatQName(str, node->ns->href, node->name)); | 
 | 	else | 
 | 	    return (xmlSchemaFormatQName(str, NULL, node->name)); | 
 |     } else if (ni != NULL) | 
 | 	return (xmlSchemaFormatQName(str, ni->nsName, ni->localName)); | 
 |     return (NULL); | 
 | } | 
 |  | 
 | static void | 
 | xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt, | 
 | 			xmlParserErrors error, | 
 | 			xmlSchemaAttrInfoPtr ni, | 
 | 			xmlNodePtr node) | 
 | { | 
 |     xmlChar *msg = NULL, *str = NULL; | 
 |  | 
 |     xmlSchemaFormatNodeForError(&msg, actxt, node); | 
 |     msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n"); | 
 |     xmlSchemaErr(actxt, error, node, (const char *) msg, | 
 | 	xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node), | 
 | 	NULL); | 
 |     FREE_AND_NULL(str) | 
 |     FREE_AND_NULL(msg) | 
 | } | 
 |  | 
 | static void | 
 | xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt, | 
 | 		        xmlParserErrors error, | 
 | 		        xmlNodePtr node, | 
 | 			xmlSchemaTypePtr type ATTRIBUTE_UNUSED, | 
 | 			const char *message, | 
 | 			int nbval, | 
 | 			int nbneg, | 
 | 			xmlChar **values) | 
 | { | 
 |     xmlChar *str = NULL, *msg = NULL; | 
 |     xmlChar *localName, *nsName; | 
 |     const xmlChar *cur, *end; | 
 |     int i; | 
 |  | 
 |     xmlSchemaFormatNodeForError(&msg, actxt, node); | 
 |     msg = xmlStrcat(msg, (const xmlChar *) message); | 
 |     msg = xmlStrcat(msg, BAD_CAST "."); | 
 |     /* | 
 |     * Note that is does not make sense to report that we have a | 
 |     * wildcard here, since the wildcard might be unfolded into | 
 |     * multiple transitions. | 
 |     */ | 
 |     if (nbval + nbneg > 0) { | 
 | 	if (nbval + nbneg > 1) { | 
 | 	    str = xmlStrdup(BAD_CAST " Expected is one of ( "); | 
 | 	} else | 
 | 	    str = xmlStrdup(BAD_CAST " Expected is ( "); | 
 | 	nsName = NULL; | 
 |  | 
 | 	for (i = 0; i < nbval + nbneg; i++) { | 
 | 	    cur = values[i]; | 
 | 	    if (cur == NULL) | 
 | 	        continue; | 
 | 	    if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') && | 
 | 	        (cur[3] == ' ')) { | 
 | 		cur += 4; | 
 | 		str = xmlStrcat(str, BAD_CAST "##other"); | 
 | 	    } | 
 | 	    /* | 
 | 	    * Get the local name. | 
 | 	    */ | 
 | 	    localName = NULL; | 
 |  | 
 | 	    end = cur; | 
 | 	    if (*end == '*') { | 
 | 		localName = xmlStrdup(BAD_CAST "*"); | 
 | 		end++; | 
 | 	    } else { | 
 | 		while ((*end != 0) && (*end != '|')) | 
 | 		    end++; | 
 | 		localName = xmlStrncat(localName, BAD_CAST cur, end - cur); | 
 | 	    } | 
 | 	    if (*end != 0) { | 
 | 		end++; | 
 | 		/* | 
 | 		* Skip "*|*" if they come with negated expressions, since | 
 | 		* they represent the same negated wildcard. | 
 | 		*/ | 
 | 		if ((nbneg == 0) || (*end != '*') || (*localName != '*')) { | 
 | 		    /* | 
 | 		    * Get the namespace name. | 
 | 		    */ | 
 | 		    cur = end; | 
 | 		    if (*end == '*') { | 
 | 			nsName = xmlStrdup(BAD_CAST "{*}"); | 
 | 		    } else { | 
 | 			while (*end != 0) | 
 | 			    end++; | 
 |  | 
 | 			if (i >= nbval) | 
 | 			    nsName = xmlStrdup(BAD_CAST "{##other:"); | 
 | 			else | 
 | 			    nsName = xmlStrdup(BAD_CAST "{"); | 
 |  | 
 | 			nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur); | 
 | 			nsName = xmlStrcat(nsName, BAD_CAST "}"); | 
 | 		    } | 
 | 		    str = xmlStrcat(str, BAD_CAST nsName); | 
 | 		    FREE_AND_NULL(nsName) | 
 | 		} else { | 
 | 		    FREE_AND_NULL(localName); | 
 | 		    continue; | 
 | 		} | 
 | 	    } | 
 | 	    str = xmlStrcat(str, BAD_CAST localName); | 
 | 	    FREE_AND_NULL(localName); | 
 |  | 
 | 	    if (i < nbval + nbneg -1) | 
 | 		str = xmlStrcat(str, BAD_CAST ", "); | 
 | 	} | 
 | 	str = xmlStrcat(str, BAD_CAST " ).\n"); | 
 | 	msg = xmlStrcat(msg, BAD_CAST str); | 
 | 	FREE_AND_NULL(str) | 
 |     } else | 
 |       msg = xmlStrcat(msg, BAD_CAST "\n"); | 
 |     xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL); | 
 |     xmlFree(msg); | 
 | } | 
 |  | 
 | static void | 
 | xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt, | 
 | 		  xmlParserErrors error, | 
 | 		  xmlNodePtr node, | 
 | 		  const xmlChar *value, | 
 | 		  unsigned long length, | 
 | 		  xmlSchemaTypePtr type, | 
 | 		  xmlSchemaFacetPtr facet, | 
 | 		  const char *message, | 
 | 		  const xmlChar *str1, | 
 | 		  const xmlChar *str2) | 
 | { | 
 |     xmlChar *str = NULL, *msg = NULL; | 
 |     xmlSchemaTypeType facetType; | 
 |     int nodeType = xmlSchemaEvalErrorNodeType(actxt, node); | 
 |  | 
 |     xmlSchemaFormatNodeForError(&msg, actxt, node); | 
 |     if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) { | 
 | 	facetType = XML_SCHEMA_FACET_ENUMERATION; | 
 | 	/* | 
 | 	* If enumerations are validated, one must not expect the | 
 | 	* facet to be given. | 
 | 	*/ | 
 |     } else | 
 | 	facetType = facet->type; | 
 |     msg = xmlStrcat(msg, BAD_CAST "["); | 
 |     msg = xmlStrcat(msg, BAD_CAST "facet '"); | 
 |     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType)); | 
 |     msg = xmlStrcat(msg, BAD_CAST "'] "); | 
 |     if (message == NULL) { | 
 | 	/* | 
 | 	* Use a default message. | 
 | 	*/ | 
 | 	if ((facetType == XML_SCHEMA_FACET_LENGTH) || | 
 | 	    (facetType == XML_SCHEMA_FACET_MINLENGTH) || | 
 | 	    (facetType == XML_SCHEMA_FACET_MAXLENGTH)) { | 
 |  | 
 | 	    char len[25], actLen[25]; | 
 |  | 
 | 	    /* FIXME, TODO: What is the max expected string length of the | 
 | 	    * this value? | 
 | 	    */ | 
 | 	    if (nodeType == XML_ATTRIBUTE_NODE) | 
 | 		msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; "); | 
 | 	    else | 
 | 		msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; "); | 
 |  | 
 | 	    snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet)); | 
 | 	    snprintf(actLen, 24, "%lu", length); | 
 |  | 
 | 	    if (facetType == XML_SCHEMA_FACET_LENGTH) | 
 | 		msg = xmlStrcat(msg, | 
 | 		BAD_CAST "this differs from the allowed length of '%s'.\n"); | 
 | 	    else if (facetType == XML_SCHEMA_FACET_MAXLENGTH) | 
 | 		msg = xmlStrcat(msg, | 
 | 		BAD_CAST "this exceeds the allowed maximum length of '%s'.\n"); | 
 | 	    else if (facetType == XML_SCHEMA_FACET_MINLENGTH) | 
 | 		msg = xmlStrcat(msg, | 
 | 		BAD_CAST "this underruns the allowed minimum length of '%s'.\n"); | 
 |  | 
 | 	    if (nodeType == XML_ATTRIBUTE_NODE) | 
 | 		xmlSchemaErr3(actxt, error, node, (const char *) msg, | 
 | 		    value, (const xmlChar *) actLen, (const xmlChar *) len); | 
 | 	    else | 
 | 		xmlSchemaErr(actxt, error, node, (const char *) msg, | 
 | 		    (const xmlChar *) actLen, (const xmlChar *) len); | 
 |  | 
 | 	} else if (facetType == XML_SCHEMA_FACET_ENUMERATION) { | 
 | 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element " | 
 | 		"of the set {%s}.\n"); | 
 | 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value, | 
 | 		xmlSchemaFormatFacetEnumSet(actxt, &str, type)); | 
 | 	} else if (facetType == XML_SCHEMA_FACET_PATTERN) { | 
 | 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted " | 
 | 		"by the pattern '%s'.\n"); | 
 | 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value, | 
 | 		facet->value); | 
 | 	} else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) { | 
 | 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the " | 
 | 		"minimum value allowed ('%s').\n"); | 
 | 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value, | 
 | 		facet->value); | 
 | 	} else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) { | 
 | 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the " | 
 | 		"maximum value allowed ('%s').\n"); | 
 | 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value, | 
 | 		facet->value); | 
 | 	} else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) { | 
 | 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than " | 
 | 		"'%s'.\n"); | 
 | 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value, | 
 | 		facet->value); | 
 | 	} else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) { | 
 | 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than " | 
 | 		"'%s'.\n"); | 
 | 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value, | 
 | 		facet->value); | 
 | 	} else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) { | 
 | 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more " | 
 | 		"digits than are allowed ('%s').\n"); | 
 | 	    xmlSchemaErr(actxt, error, node, (const char*) msg, value, | 
 | 		facet->value); | 
 | 	} else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) { | 
 | 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional " | 
 | 		"digits than are allowed ('%s').\n"); | 
 | 	    xmlSchemaErr(actxt, error, node, (const char*) msg, value, | 
 | 		facet->value); | 
 | 	} else if (nodeType == XML_ATTRIBUTE_NODE) { | 
 | 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n"); | 
 | 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL); | 
 | 	} else { | 
 | 	    msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n"); | 
 | 	    xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL); | 
 | 	} | 
 |     } else { | 
 | 	msg = xmlStrcat(msg, (const xmlChar *) message); | 
 | 	msg = xmlStrcat(msg, BAD_CAST ".\n"); | 
 | 	xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2); | 
 |     } | 
 |     FREE_AND_NULL(str) | 
 |     xmlFree(msg); | 
 | } | 
 |  | 
 | #define VERROR(err, type, msg) \ | 
 |     xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL); | 
 |  | 
 | #define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg); | 
 |  | 
 | #define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg); | 
 | #define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg); | 
 |  | 
 | #define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg); | 
 |  | 
 |  | 
 | /** | 
 |  * xmlSchemaPMissingAttrErr: | 
 |  * @ctxt: the schema validation context | 
 |  * @ownerDes: the designation of  the owner | 
 |  * @ownerName: the name of the owner | 
 |  * @ownerItem: the owner as a schema object | 
 |  * @ownerElem: the owner as an element node | 
 |  * @node: the parent element node of the missing attribute node | 
 |  * @type: the corresponding type of the attribute node | 
 |  * | 
 |  * Reports an illegal attribute. | 
 |  */ | 
 | static void | 
 | xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt, | 
 | 			 xmlParserErrors error, | 
 | 			 xmlSchemaBasicItemPtr ownerItem, | 
 | 			 xmlNodePtr ownerElem, | 
 | 			 const char *name, | 
 | 			 const char *message) | 
 | { | 
 |     xmlChar *des = NULL; | 
 |  | 
 |     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem); | 
 |  | 
 |     if (message != NULL) | 
 | 	xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message); | 
 |     else | 
 | 	xmlSchemaPErr(ctxt, ownerElem, error, | 
 | 	    "%s: The attribute '%s' is required but missing.\n", | 
 | 	    BAD_CAST des, BAD_CAST name); | 
 |     FREE_AND_NULL(des); | 
 | } | 
 |  | 
 |  | 
 | /** | 
 |  * xmlSchemaPResCompAttrErr: | 
 |  * @ctxt: the schema validation context | 
 |  * @error: the error code | 
 |  * @ownerDes: the designation of  the owner | 
 |  * @ownerItem: the owner as a schema object | 
 |  * @ownerElem: the owner as an element node | 
 |  * @name: the name of the attribute holding the QName | 
 |  * @refName: the referenced local name | 
 |  * @refURI: the referenced namespace URI | 
 |  * @message: optional message | 
 |  * | 
 |  * Used to report QName attribute values that failed to resolve | 
 |  * to schema components. | 
 |  */ | 
 | static void | 
 | xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt, | 
 | 			 xmlParserErrors error, | 
 | 			 xmlSchemaBasicItemPtr ownerItem, | 
 | 			 xmlNodePtr ownerElem, | 
 | 			 const char *name, | 
 | 			 const xmlChar *refName, | 
 | 			 const xmlChar *refURI, | 
 | 			 xmlSchemaTypeType refType, | 
 | 			 const char *refTypeStr) | 
 | { | 
 |     xmlChar *des = NULL, *strA = NULL; | 
 |  | 
 |     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem); | 
 |     if (refTypeStr == NULL) | 
 | 	refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType); | 
 | 	xmlSchemaPErrExt(ctxt, ownerElem, error, | 
 | 	    NULL, NULL, NULL, | 
 | 	    "%s, attribute '%s': The QName value '%s' does not resolve to a(n) " | 
 | 	    "%s.\n", BAD_CAST des, BAD_CAST name, | 
 | 	    xmlSchemaFormatQName(&strA, refURI, refName), | 
 | 	    BAD_CAST refTypeStr, NULL); | 
 |     FREE_AND_NULL(des) | 
 |     FREE_AND_NULL(strA) | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaPCustomAttrErr: | 
 |  * @ctxt: the schema parser context | 
 |  * @error: the error code | 
 |  * @ownerDes: the designation of the owner | 
 |  * @ownerItem: the owner as a schema object | 
 |  * @attr: the illegal attribute node | 
 |  * | 
 |  * Reports an illegal attribute during the parse. | 
 |  */ | 
 | static void | 
 | xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt, | 
 | 			xmlParserErrors error, | 
 | 			xmlChar **ownerDes, | 
 | 			xmlSchemaBasicItemPtr ownerItem, | 
 | 			xmlAttrPtr attr, | 
 | 			const char *msg) | 
 | { | 
 |     xmlChar *des = NULL; | 
 |  | 
 |     if (ownerDes == NULL) | 
 | 	xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent); | 
 |     else if (*ownerDes == NULL) { | 
 | 	xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent); | 
 | 	des = *ownerDes; | 
 |     } else | 
 | 	des = *ownerDes; | 
 |     if (attr == NULL) { | 
 | 	xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL, | 
 | 	    "%s, attribute '%s': %s.\n", | 
 | 	    BAD_CAST des, (const xmlChar *) "Unknown", | 
 | 	    (const xmlChar *) msg, NULL, NULL); | 
 |     } else { | 
 | 	xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL, | 
 | 	    "%s, attribute '%s': %s.\n", | 
 | 	    BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL); | 
 |     } | 
 |     if (ownerDes == NULL) | 
 | 	FREE_AND_NULL(des); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaPIllegalAttrErr: | 
 |  * @ctxt: the schema parser context | 
 |  * @error: the error code | 
 |  * @ownerDes: the designation of the attribute's owner | 
 |  * @ownerItem: the attribute's owner item | 
 |  * @attr: the illegal attribute node | 
 |  * | 
 |  * Reports an illegal attribute during the parse. | 
 |  */ | 
 | static void | 
 | xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt, | 
 | 			 xmlParserErrors error, | 
 | 			 xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED, | 
 | 			 xmlAttrPtr attr) | 
 | { | 
 |     xmlChar *strA = NULL, *strB = NULL; | 
 |  | 
 |     xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent); | 
 |     xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr, | 
 | 	"%sThe attribute '%s' is not allowed.\n", BAD_CAST strA, | 
 | 	xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name), | 
 | 	NULL, NULL); | 
 |     FREE_AND_NULL(strA); | 
 |     FREE_AND_NULL(strB); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaPCustomErr: | 
 |  * @ctxt: the schema parser context | 
 |  * @error: the error code | 
 |  * @itemDes: the designation of the schema item | 
 |  * @item: the schema item | 
 |  * @itemElem: the node of the schema item | 
 |  * @message: the error message | 
 |  * @str1: an optional param for the error message | 
 |  * @str2: an optional param for the error message | 
 |  * @str3: an optional param for the error message | 
 |  * | 
 |  * Reports an error during parsing. | 
 |  */ | 
 | static void | 
 | xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt, | 
 | 		    xmlParserErrors error, | 
 | 		    xmlSchemaBasicItemPtr item, | 
 | 		    xmlNodePtr itemElem, | 
 | 		    const char *message, | 
 | 		    const xmlChar *str1, | 
 | 		    const xmlChar *str2, | 
 | 		    const xmlChar *str3) | 
 | { | 
 |     xmlChar *des = NULL, *msg = NULL; | 
 |  | 
 |     xmlSchemaFormatItemForReport(&des, NULL, item, itemElem); | 
 |     msg = xmlStrdup(BAD_CAST "%s: "); | 
 |     msg = xmlStrcat(msg, (const xmlChar *) message); | 
 |     msg = xmlStrcat(msg, BAD_CAST ".\n"); | 
 |     if ((itemElem == NULL) && (item != NULL)) | 
 | 	itemElem = WXS_ITEM_NODE(item); | 
 |     xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL, | 
 | 	(const char *) msg, BAD_CAST des, str1, str2, str3, NULL); | 
 |     FREE_AND_NULL(des); | 
 |     FREE_AND_NULL(msg); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaPCustomErr: | 
 |  * @ctxt: the schema parser context | 
 |  * @error: the error code | 
 |  * @itemDes: the designation of the schema item | 
 |  * @item: the schema item | 
 |  * @itemElem: the node of the schema item | 
 |  * @message: the error message | 
 |  * @str1: the optional param for the error message | 
 |  * | 
 |  * Reports an error during parsing. | 
 |  */ | 
 | static void | 
 | xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt, | 
 | 		    xmlParserErrors error, | 
 | 		    xmlSchemaBasicItemPtr item, | 
 | 		    xmlNodePtr itemElem, | 
 | 		    const char *message, | 
 | 		    const xmlChar *str1) | 
 | { | 
 |     xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message, | 
 | 	str1, NULL, NULL); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaPAttrUseErr: | 
 |  * @ctxt: the schema parser context | 
 |  * @error: the error code | 
 |  * @itemDes: the designation of the schema type | 
 |  * @item: the schema type | 
 |  * @itemElem: the node of the schema type | 
 |  * @attr: the invalid schema attribute | 
 |  * @message: the error message | 
 |  * @str1: the optional param for the error message | 
 |  * | 
 |  * Reports an attribute use error during parsing. | 
 |  */ | 
 | static void | 
 | xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt, | 
 | 		    xmlParserErrors error, | 
 | 		    xmlNodePtr node, | 
 | 		    xmlSchemaBasicItemPtr ownerItem, | 
 | 		    const xmlSchemaAttributeUsePtr attruse, | 
 | 		    const char *message, | 
 | 		    const xmlChar *str1, const xmlChar *str2, | 
 | 		    const xmlChar *str3,const xmlChar *str4) | 
 | { | 
 |     xmlChar *str = NULL, *msg = NULL; | 
 |  | 
 |     xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL); | 
 |     msg = xmlStrcat(msg, BAD_CAST ", "); | 
 |     msg = xmlStrcat(msg, | 
 | 	BAD_CAST xmlSchemaFormatItemForReport(&str, NULL, | 
 | 	WXS_BASIC_CAST attruse, NULL)); | 
 |     FREE_AND_NULL(str); | 
 |     msg = xmlStrcat(msg, BAD_CAST ": "); | 
 |     msg = xmlStrcat(msg, (const xmlChar *) message); | 
 |     msg = xmlStrcat(msg, BAD_CAST ".\n"); | 
 |     xmlSchemaErr4(ACTXT_CAST ctxt, error, node, | 
 | 	(const char *) msg, str1, str2, str3, str4); | 
 |     xmlFree(msg); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaPIllegalFacetAtomicErr: | 
 |  * @ctxt: the schema parser context | 
 |  * @error: the error code | 
 |  * @type: the schema type | 
 |  * @baseType: the base type of type | 
 |  * @facet: the illegal facet | 
 |  * | 
 |  * Reports an illegal facet for atomic simple types. | 
 |  */ | 
 | static void | 
 | xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt, | 
 | 			  xmlParserErrors error, | 
 | 			  xmlSchemaTypePtr type, | 
 | 			  xmlSchemaTypePtr baseType, | 
 | 			  xmlSchemaFacetPtr facet) | 
 | { | 
 |     xmlChar *des = NULL, *strT = NULL; | 
 |  | 
 |     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node); | 
 |     xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL, | 
 | 	"%s: The facet '%s' is not allowed on types derived from the " | 
 | 	"type %s.\n", | 
 | 	BAD_CAST des, xmlSchemaFacetTypeToString(facet->type), | 
 | 	xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL), | 
 | 	NULL, NULL); | 
 |     FREE_AND_NULL(des); | 
 |     FREE_AND_NULL(strT); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaPIllegalFacetListUnionErr: | 
 |  * @ctxt: the schema parser context | 
 |  * @error: the error code | 
 |  * @itemDes: the designation of the schema item involved | 
 |  * @item: the schema item involved | 
 |  * @facet: the illegal facet | 
 |  * | 
 |  * Reports an illegal facet for <list> and <union>. | 
 |  */ | 
 | static void | 
 | xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt, | 
 | 			  xmlParserErrors error, | 
 | 			  xmlSchemaTypePtr type, | 
 | 			  xmlSchemaFacetPtr facet) | 
 | { | 
 |     xmlChar *des = NULL; | 
 |  | 
 |     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, | 
 | 	type->node); | 
 |     xmlSchemaPErr(ctxt, type->node, error, | 
 | 	"%s: The facet '%s' is not allowed.\n", | 
 | 	BAD_CAST des, xmlSchemaFacetTypeToString(facet->type)); | 
 |     FREE_AND_NULL(des); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaPMutualExclAttrErr: | 
 |  * @ctxt: the schema validation context | 
 |  * @error: the error code | 
 |  * @elemDes: the designation of the parent element node | 
 |  * @attr: the bad attribute node | 
 |  * @type: the corresponding type of the attribute node | 
 |  * | 
 |  * Reports an illegal attribute. | 
 |  */ | 
 | static void | 
 | xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt, | 
 | 			 xmlParserErrors error, | 
 | 			 xmlSchemaBasicItemPtr ownerItem, | 
 | 			 xmlAttrPtr attr, | 
 | 			 const char *name1, | 
 | 			 const char *name2) | 
 | { | 
 |     xmlChar *des = NULL; | 
 |  | 
 |     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent); | 
 |     xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL, | 
 | 	"%s: The attributes '%s' and '%s' are mutually exclusive.\n", | 
 | 	BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL); | 
 |     FREE_AND_NULL(des); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaPSimpleTypeErr: | 
 |  * @ctxt:  the schema validation context | 
 |  * @error: the error code | 
 |  * @type: the type specifier | 
 |  * @ownerDes: the designation of the owner | 
 |  * @ownerItem: the schema object if existent | 
 |  * @node: the validated node | 
 |  * @value: the validated value | 
 |  * | 
 |  * Reports a simple type validation error. | 
 |  * TODO: Should this report the value of an element as well? | 
 |  */ | 
 | static void | 
 | xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt, | 
 | 			xmlParserErrors error, | 
 | 			xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED, | 
 | 			xmlNodePtr node, | 
 | 			xmlSchemaTypePtr type, | 
 | 			const char *expected, | 
 | 			const xmlChar *value, | 
 | 			const char *message, | 
 | 			const xmlChar *str1, | 
 | 			const xmlChar *str2) | 
 | { | 
 |     xmlChar *msg = NULL; | 
 |  | 
 |     xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node); | 
 |     if (message == NULL) { | 
 | 	/* | 
 | 	* Use default messages. | 
 | 	*/ | 
 | 	if (type != NULL) { | 
 | 	    if (node->type == XML_ATTRIBUTE_NODE) | 
 | 		msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of "); | 
 | 	    else | 
 | 		msg = xmlStrcat(msg, BAD_CAST "The character content is not a " | 
 | 		"valid value of "); | 
 | 	    if (! xmlSchemaIsGlobalItem(type)) | 
 | 		msg = xmlStrcat(msg, BAD_CAST "the local "); | 
 | 	    else | 
 | 		msg = xmlStrcat(msg, BAD_CAST "the "); | 
 |  | 
 | 	    if (WXS_IS_ATOMIC(type)) | 
 | 		msg = xmlStrcat(msg, BAD_CAST "atomic type"); | 
 | 	    else if (WXS_IS_LIST(type)) | 
 | 		msg = xmlStrcat(msg, BAD_CAST "list type"); | 
 | 	    else if (WXS_IS_UNION(type)) | 
 | 		msg = xmlStrcat(msg, BAD_CAST "union type"); | 
 |  | 
 | 	    if (xmlSchemaIsGlobalItem(type)) { | 
 | 		xmlChar *str = NULL; | 
 | 		msg = xmlStrcat(msg, BAD_CAST " '"); | 
 | 		if (type->builtInType != 0) { | 
 | 		    msg = xmlStrcat(msg, BAD_CAST "xs:"); | 
 | 		    msg = xmlStrcat(msg, type->name); | 
 | 		} else | 
 | 		    msg = xmlStrcat(msg, | 
 | 			xmlSchemaFormatQName(&str, | 
 | 			    type->targetNamespace, type->name)); | 
 | 		msg = xmlStrcat(msg, BAD_CAST "'."); | 
 | 		FREE_AND_NULL(str); | 
 | 	    } | 
 | 	} else { | 
 | 	    if (node->type == XML_ATTRIBUTE_NODE) | 
 | 		msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid."); | 
 | 	    else | 
 | 		msg = xmlStrcat(msg, BAD_CAST "The character content is not " | 
 | 		"valid."); | 
 | 	} | 
 | 	if (expected) { | 
 | 	    msg = xmlStrcat(msg, BAD_CAST " Expected is '"); | 
 | 	    msg = xmlStrcat(msg, BAD_CAST expected); | 
 | 	    msg = xmlStrcat(msg, BAD_CAST "'.\n"); | 
 | 	} else | 
 | 	    msg = xmlStrcat(msg, BAD_CAST "\n"); | 
 | 	if (node->type == XML_ATTRIBUTE_NODE) | 
 | 	    xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL); | 
 | 	else | 
 | 	    xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL); | 
 |     } else { | 
 | 	msg = xmlStrcat(msg, BAD_CAST message); | 
 | 	msg = xmlStrcat(msg, BAD_CAST ".\n"); | 
 | 	xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL, | 
 | 	     (const char*) msg, str1, str2, NULL, NULL, NULL); | 
 |     } | 
 |     /* Cleanup. */ | 
 |     FREE_AND_NULL(msg) | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaPContentErr: | 
 |  * @ctxt: the schema parser context | 
 |  * @error: the error code | 
 |  * @onwerDes: the designation of the holder of the content | 
 |  * @ownerItem: the owner item of the holder of the content | 
 |  * @ownerElem: the node of the holder of the content | 
 |  * @child: the invalid child node | 
 |  * @message: the optional error message | 
 |  * @content: the optional string describing the correct content | 
 |  * | 
 |  * Reports an error concerning the content of a schema element. | 
 |  */ | 
 | static void | 
 | xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt, | 
 | 		     xmlParserErrors error, | 
 | 		     xmlSchemaBasicItemPtr ownerItem, | 
 | 		     xmlNodePtr ownerElem, | 
 | 		     xmlNodePtr child, | 
 | 		     const char *message, | 
 | 		     const char *content) | 
 | { | 
 |     xmlChar *des = NULL; | 
 |  | 
 |     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem); | 
 |     if (message != NULL) | 
 | 	xmlSchemaPErr2(ctxt, ownerElem, child, error, | 
 | 	    "%s: %s.\n", | 
 | 	    BAD_CAST des, BAD_CAST message); | 
 |     else { | 
 | 	if (content != NULL) { | 
 | 	    xmlSchemaPErr2(ctxt, ownerElem, child, error, | 
 | 		"%s: The content is not valid. Expected is %s.\n", | 
 | 		BAD_CAST des, BAD_CAST content); | 
 | 	} else { | 
 | 	    xmlSchemaPErr2(ctxt, ownerElem, child, error, | 
 | 		"%s: The content is not valid.\n", | 
 | 		BAD_CAST des, NULL); | 
 | 	} | 
 |     } | 
 |     FREE_AND_NULL(des) | 
 | } | 
 |  | 
 | /************************************************************************ | 
 |  * 									* | 
 |  * 			Streamable error functions                      * | 
 |  * 									* | 
 |  ************************************************************************/ | 
 |  | 
 |  | 
 |  | 
 |  | 
 | /************************************************************************ | 
 |  * 									* | 
 |  * 			Validation helper functions			* | 
 |  * 									* | 
 |  ************************************************************************/ | 
 |  | 
 |  | 
 | /************************************************************************ | 
 |  * 									* | 
 |  * 			Allocation functions				* | 
 |  * 									* | 
 |  ************************************************************************/ | 
 |  | 
 | /** | 
 |  * xmlSchemaNewSchemaForParserCtxt: | 
 |  * @ctxt:  a schema validation context | 
 |  * | 
 |  * Allocate a new Schema structure. | 
 |  * | 
 |  * Returns the newly allocated structure or NULL in case or error | 
 |  */ | 
 | static xmlSchemaPtr | 
 | xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt) | 
 | { | 
 |     xmlSchemaPtr ret; | 
 |  | 
 |     ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema)); | 
 |     if (ret == NULL) { | 
 |         xmlSchemaPErrMemory(ctxt, "allocating schema", NULL); | 
 |         return (NULL); | 
 |     } | 
 |     memset(ret, 0, sizeof(xmlSchema)); | 
 |     ret->dict = ctxt->dict; | 
 |     xmlDictReference(ret->dict); | 
 |  | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaNewFacet: | 
 |  * | 
 |  * Allocate a new Facet structure. | 
 |  * | 
 |  * Returns the newly allocated structure or NULL in case or error | 
 |  */ | 
 | xmlSchemaFacetPtr | 
 | xmlSchemaNewFacet(void) | 
 | { | 
 |     xmlSchemaFacetPtr ret; | 
 |  | 
 |     ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet)); | 
 |     if (ret == NULL) { | 
 |         return (NULL); | 
 |     } | 
 |     memset(ret, 0, sizeof(xmlSchemaFacet)); | 
 |  | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaNewAnnot: | 
 |  * @ctxt:  a schema validation context | 
 |  * @node:  a node | 
 |  * | 
 |  * Allocate a new annotation structure. | 
 |  * | 
 |  * Returns the newly allocated structure or NULL in case or error | 
 |  */ | 
 | static xmlSchemaAnnotPtr | 
 | xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node) | 
 | { | 
 |     xmlSchemaAnnotPtr ret; | 
 |  | 
 |     ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot)); | 
 |     if (ret == NULL) { | 
 |         xmlSchemaPErrMemory(ctxt, "allocating annotation", node); | 
 |         return (NULL); | 
 |     } | 
 |     memset(ret, 0, sizeof(xmlSchemaAnnot)); | 
 |     ret->content = node; | 
 |     return (ret); | 
 | } | 
 |  | 
 | static xmlSchemaItemListPtr | 
 | xmlSchemaItemListCreate(void) | 
 | { | 
 |     xmlSchemaItemListPtr ret; | 
 |  | 
 |     ret = xmlMalloc(sizeof(xmlSchemaItemList)); | 
 |     if (ret == NULL) { | 
 | 	xmlSchemaPErrMemory(NULL, | 
 | 	    "allocating an item list structure", NULL); | 
 | 	return (NULL); | 
 |     } | 
 |     memset(ret, 0, sizeof(xmlSchemaItemList)); | 
 |     return (ret); | 
 | } | 
 |  | 
 | static void | 
 | xmlSchemaItemListClear(xmlSchemaItemListPtr list) | 
 | { | 
 |     if (list->items != NULL) { | 
 | 	xmlFree(list->items); | 
 | 	list->items = NULL; | 
 |     } | 
 |     list->nbItems = 0; | 
 |     list->sizeItems = 0; | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item) | 
 | { | 
 |     if (list->items == NULL) { | 
 | 	list->items = (void **) xmlMalloc( | 
 | 	    20 * sizeof(void *)); | 
 | 	if (list->items == NULL) { | 
 | 	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL); | 
 | 	    return(-1); | 
 | 	} | 
 | 	list->sizeItems = 20; | 
 |     } else if (list->sizeItems <= list->nbItems) { | 
 | 	list->sizeItems *= 2; | 
 | 	list->items = (void **) xmlRealloc(list->items, | 
 | 	    list->sizeItems * sizeof(void *)); | 
 | 	if (list->items == NULL) { | 
 | 	    xmlSchemaPErrMemory(NULL, "growing item list", NULL); | 
 | 	    list->sizeItems = 0; | 
 | 	    return(-1); | 
 | 	} | 
 |     } | 
 |     list->items[list->nbItems++] = item; | 
 |     return(0); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaItemListAddSize(xmlSchemaItemListPtr list, | 
 | 			 int initialSize, | 
 | 			 void *item) | 
 | { | 
 |     if (list->items == NULL) { | 
 | 	if (initialSize <= 0) | 
 | 	    initialSize = 1; | 
 | 	list->items = (void **) xmlMalloc( | 
 | 	    initialSize * sizeof(void *)); | 
 | 	if (list->items == NULL) { | 
 | 	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL); | 
 | 	    return(-1); | 
 | 	} | 
 | 	list->sizeItems = initialSize; | 
 |     } else if (list->sizeItems <= list->nbItems) { | 
 | 	list->sizeItems *= 2; | 
 | 	list->items = (void **) xmlRealloc(list->items, | 
 | 	    list->sizeItems * sizeof(void *)); | 
 | 	if (list->items == NULL) { | 
 | 	    xmlSchemaPErrMemory(NULL, "growing item list", NULL); | 
 | 	    list->sizeItems = 0; | 
 | 	    return(-1); | 
 | 	} | 
 |     } | 
 |     list->items[list->nbItems++] = item; | 
 |     return(0); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx) | 
 | { | 
 |     if (list->items == NULL) { | 
 | 	list->items = (void **) xmlMalloc( | 
 | 	    20 * sizeof(void *)); | 
 | 	if (list->items == NULL) { | 
 | 	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL); | 
 | 	    return(-1); | 
 | 	} | 
 | 	list->sizeItems = 20; | 
 |     } else if (list->sizeItems <= list->nbItems) { | 
 | 	list->sizeItems *= 2; | 
 | 	list->items = (void **) xmlRealloc(list->items, | 
 | 	    list->sizeItems * sizeof(void *)); | 
 | 	if (list->items == NULL) { | 
 | 	    xmlSchemaPErrMemory(NULL, "growing item list", NULL); | 
 | 	    list->sizeItems = 0; | 
 | 	    return(-1); | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * Just append if the index is greater/equal than the item count. | 
 |     */ | 
 |     if (idx >= list->nbItems) { | 
 | 	list->items[list->nbItems++] = item; | 
 |     } else { | 
 | 	int i; | 
 | 	for (i = list->nbItems; i > idx; i--) | 
 | 	    list->items[i] = list->items[i-1]; | 
 | 	list->items[idx] = item; | 
 | 	list->nbItems++; | 
 |     } | 
 |     return(0); | 
 | } | 
 |  | 
 | #if 0 /* enable if ever needed */ | 
 | static int | 
 | xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list, | 
 | 			    int initialSize, | 
 | 			    void *item, | 
 | 			    int idx) | 
 | { | 
 |     if (list->items == NULL) { | 
 | 	if (initialSize <= 0) | 
 | 	    initialSize = 1; | 
 | 	list->items = (void **) xmlMalloc( | 
 | 	    initialSize * sizeof(void *)); | 
 | 	if (list->items == NULL) { | 
 | 	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL); | 
 | 	    return(-1); | 
 | 	} | 
 | 	list->sizeItems = initialSize; | 
 |     } else if (list->sizeItems <= list->nbItems) { | 
 | 	list->sizeItems *= 2; | 
 | 	list->items = (void **) xmlRealloc(list->items, | 
 | 	    list->sizeItems * sizeof(void *)); | 
 | 	if (list->items == NULL) { | 
 | 	    xmlSchemaPErrMemory(NULL, "growing item list", NULL); | 
 | 	    list->sizeItems = 0; | 
 | 	    return(-1); | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * Just append if the index is greater/equal than the item count. | 
 |     */ | 
 |     if (idx >= list->nbItems) { | 
 | 	list->items[list->nbItems++] = item; | 
 |     } else { | 
 | 	int i; | 
 | 	for (i = list->nbItems; i > idx; i--) | 
 | 	    list->items[i] = list->items[i-1]; | 
 | 	list->items[idx] = item; | 
 | 	list->nbItems++; | 
 |     } | 
 |     return(0); | 
 | } | 
 | #endif | 
 |  | 
 | static int | 
 | xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx) | 
 | { | 
 |     int i; | 
 |     if ((list->items == NULL) || (idx >= list->nbItems)) { | 
 | 	xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, " | 
 | 	    "index error.\n"); | 
 | 	return(-1); | 
 |     } | 
 |  | 
 |     if (list->nbItems == 1) { | 
 | 	/* TODO: Really free the list? */ | 
 | 	xmlFree(list->items); | 
 | 	list->items = NULL; | 
 | 	list->nbItems = 0; | 
 | 	list->sizeItems = 0; | 
 |     } else if (list->nbItems -1 == idx) { | 
 | 	list->nbItems--; | 
 |     } else { | 
 | 	for (i = idx; i < list->nbItems -1; i++) | 
 | 	    list->items[i] = list->items[i+1]; | 
 | 	list->nbItems--; | 
 |     } | 
 |     return(0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaItemListFree: | 
 |  * @annot:  a schema type structure | 
 |  * | 
 |  * Deallocate a annotation structure | 
 |  */ | 
 | static void | 
 | xmlSchemaItemListFree(xmlSchemaItemListPtr list) | 
 | { | 
 |     if (list == NULL) | 
 | 	return; | 
 |     if (list->items != NULL) | 
 | 	xmlFree(list->items); | 
 |     xmlFree(list); | 
 | } | 
 |  | 
 | static void | 
 | xmlSchemaBucketFree(xmlSchemaBucketPtr bucket) | 
 | { | 
 |     if (bucket == NULL) | 
 | 	return; | 
 |     if (bucket->globals != NULL) { | 
 | 	xmlSchemaComponentListFree(bucket->globals); | 
 | 	xmlSchemaItemListFree(bucket->globals); | 
 |     } | 
 |     if (bucket->locals != NULL) { | 
 | 	xmlSchemaComponentListFree(bucket->locals); | 
 | 	xmlSchemaItemListFree(bucket->locals); | 
 |     } | 
 |     if (bucket->relations != NULL) { | 
 | 	xmlSchemaSchemaRelationPtr prev, cur = bucket->relations; | 
 | 	do { | 
 | 	    prev = cur; | 
 | 	    cur = cur->next; | 
 | 	    xmlFree(prev); | 
 | 	} while (cur != NULL); | 
 |     } | 
 |     if ((! bucket->preserveDoc) && (bucket->doc != NULL)) { | 
 | 	xmlFreeDoc(bucket->doc); | 
 |     } | 
 |     if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) { | 
 | 	if (WXS_IMPBUCKET(bucket)->schema != NULL) | 
 | 	    xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema); | 
 |     } | 
 |     xmlFree(bucket); | 
 | } | 
 |  | 
 | static xmlSchemaBucketPtr | 
 | xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt, | 
 | 			 int type, const xmlChar *targetNamespace) | 
 | { | 
 |     xmlSchemaBucketPtr ret; | 
 |     int size; | 
 |     xmlSchemaPtr mainSchema; | 
 |  | 
 |     if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) { | 
 | 	PERROR_INT("xmlSchemaBucketCreate", | 
 | 	    "no main schema on constructor"); | 
 | 	return(NULL); | 
 |     } | 
 |     mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema; | 
 |     /* Create the schema bucket. */ | 
 |     if (WXS_IS_BUCKET_INCREDEF(type)) | 
 | 	size = sizeof(xmlSchemaInclude); | 
 |     else | 
 | 	size = sizeof(xmlSchemaImport); | 
 |     ret = (xmlSchemaBucketPtr) xmlMalloc(size); | 
 |     if (ret == NULL) { | 
 | 	xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL); | 
 | 	return(NULL); | 
 |     } | 
 |     memset(ret, 0, size); | 
 |     ret->targetNamespace = targetNamespace; | 
 |     ret->type = type; | 
 |     ret->globals = xmlSchemaItemListCreate(); | 
 |     if (ret->globals == NULL) { | 
 | 	xmlFree(ret); | 
 | 	return(NULL); | 
 |     } | 
 |     ret->locals = xmlSchemaItemListCreate(); | 
 |     if (ret->locals == NULL) { | 
 | 	xmlFree(ret); | 
 | 	return(NULL); | 
 |     } | 
 |     /* | 
 |     * The following will assure that only the first bucket is marked as | 
 |     * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema. | 
 |     * For each following import buckets an xmlSchema will be created. | 
 |     * An xmlSchema will be created for every distinct targetNamespace. | 
 |     * We assign the targetNamespace to the schemata here. | 
 |     */ | 
 |     if (! WXS_HAS_BUCKETS(pctxt)) { | 
 | 	if (WXS_IS_BUCKET_INCREDEF(type)) { | 
 | 	    PERROR_INT("xmlSchemaBucketCreate", | 
 | 		"first bucket but it's an include or redefine"); | 
 | 	    xmlSchemaBucketFree(ret); | 
 | 	    return(NULL); | 
 | 	} | 
 | 	/* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */ | 
 | 	ret->type = XML_SCHEMA_SCHEMA_MAIN; | 
 | 	/* Point to the *main* schema. */ | 
 | 	WXS_CONSTRUCTOR(pctxt)->mainBucket = ret; | 
 | 	WXS_IMPBUCKET(ret)->schema = mainSchema; | 
 | 	/* | 
 | 	* Ensure that the main schema gets a targetNamespace. | 
 | 	*/ | 
 | 	mainSchema->targetNamespace = targetNamespace; | 
 |     } else { | 
 | 	if (type == XML_SCHEMA_SCHEMA_MAIN) { | 
 | 	    PERROR_INT("xmlSchemaBucketCreate", | 
 | 		"main bucket but it's not the first one"); | 
 | 	    xmlSchemaBucketFree(ret); | 
 | 	    return(NULL); | 
 | 	} else if (type == XML_SCHEMA_SCHEMA_IMPORT) { | 
 | 	    /* | 
 | 	    * Create a schema for imports and assign the | 
 | 	    * targetNamespace. | 
 | 	    */ | 
 | 	    WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt); | 
 | 	    if (WXS_IMPBUCKET(ret)->schema == NULL) { | 
 | 		xmlSchemaBucketFree(ret); | 
 | 		return(NULL); | 
 | 	    } | 
 | 	    WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace; | 
 | 	} | 
 |     } | 
 |     if (WXS_IS_BUCKET_IMPMAIN(type)) { | 
 | 	int res; | 
 | 	/* | 
 | 	* Imports go into the "schemasImports" slot of the main *schema*. | 
 | 	* Note that we create an import entry for the main schema as well; i.e., | 
 | 	* even if there's only one schema, we'll get an import. | 
 | 	*/ | 
 | 	if (mainSchema->schemasImports == NULL) { | 
 | 	    mainSchema->schemasImports = xmlHashCreateDict(5, | 
 | 		WXS_CONSTRUCTOR(pctxt)->dict); | 
 | 	    if (mainSchema->schemasImports == NULL) { | 
 | 		xmlSchemaBucketFree(ret); | 
 | 		return(NULL); | 
 | 	    } | 
 | 	} | 
 | 	if (targetNamespace == NULL) | 
 | 	    res = xmlHashAddEntry(mainSchema->schemasImports, | 
 | 		XML_SCHEMAS_NO_NAMESPACE, ret); | 
 | 	else | 
 | 	    res = xmlHashAddEntry(mainSchema->schemasImports, | 
 | 		targetNamespace, ret); | 
 | 	if (res != 0) { | 
 | 	    PERROR_INT("xmlSchemaBucketCreate", | 
 | 		"failed to add the schema bucket to the hash"); | 
 | 	    xmlSchemaBucketFree(ret); | 
 | 	    return(NULL); | 
 | 	} | 
 |     } else { | 
 | 	/* Set the @ownerImport of an include bucket. */ | 
 | 	if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type)) | 
 | 	    WXS_INCBUCKET(ret)->ownerImport = | 
 | 		WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket); | 
 | 	else | 
 | 	    WXS_INCBUCKET(ret)->ownerImport = | 
 | 		WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport; | 
 |  | 
 | 	/* Includes got into the "includes" slot of the *main* schema. */ | 
 | 	if (mainSchema->includes == NULL) { | 
 | 	    mainSchema->includes = xmlSchemaItemListCreate(); | 
 | 	    if (mainSchema->includes == NULL) { | 
 | 		xmlSchemaBucketFree(ret); | 
 | 		return(NULL); | 
 | 	    } | 
 | 	} | 
 | 	xmlSchemaItemListAdd(mainSchema->includes, ret); | 
 |     } | 
 |     /* | 
 |     * Add to list of all buckets; this is used for lookup | 
 |     * during schema construction time only. | 
 |     */ | 
 |     if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1) | 
 | 	return(NULL); | 
 |     return(ret); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item) | 
 | { | 
 |     if (*list == NULL) { | 
 | 	*list = xmlSchemaItemListCreate(); | 
 | 	if (*list == NULL) | 
 | 	    return(-1); | 
 |     } | 
 |     xmlSchemaItemListAddSize(*list, initialSize, item); | 
 |     return(0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaFreeAnnot: | 
 |  * @annot:  a schema type structure | 
 |  * | 
 |  * Deallocate a annotation structure | 
 |  */ | 
 | static void | 
 | xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot) | 
 | { | 
 |     if (annot == NULL) | 
 |         return; | 
 |     if (annot->next == NULL) { | 
 | 	xmlFree(annot); | 
 |     } else { | 
 | 	xmlSchemaAnnotPtr prev; | 
 |  | 
 | 	do { | 
 | 	    prev = annot; | 
 | 	    annot = annot->next; | 
 | 	    xmlFree(prev); | 
 | 	} while (annot != NULL); | 
 |     } | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaFreeNotation: | 
 |  * @schema:  a schema notation structure | 
 |  * | 
 |  * Deallocate a Schema Notation structure. | 
 |  */ | 
 | static void | 
 | xmlSchemaFreeNotation(xmlSchemaNotationPtr nota) | 
 | { | 
 |     if (nota == NULL) | 
 |         return; | 
 |     xmlFree(nota); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaFreeAttribute: | 
 |  * @attr:  an attribute declaration | 
 |  * | 
 |  * Deallocates an attribute declaration structure. | 
 |  */ | 
 | static void | 
 | xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr) | 
 | { | 
 |     if (attr == NULL) | 
 |         return; | 
 |     if (attr->annot != NULL) | 
 | 	xmlSchemaFreeAnnot(attr->annot); | 
 |     if (attr->defVal != NULL) | 
 | 	xmlSchemaFreeValue(attr->defVal); | 
 |     xmlFree(attr); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaFreeAttributeUse: | 
 |  * @use:  an attribute use | 
 |  * | 
 |  * Deallocates an attribute use structure. | 
 |  */ | 
 | static void | 
 | xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use) | 
 | { | 
 |     if (use == NULL) | 
 |         return; | 
 |     if (use->annot != NULL) | 
 | 	xmlSchemaFreeAnnot(use->annot); | 
 |     if (use->defVal != NULL) | 
 | 	xmlSchemaFreeValue(use->defVal); | 
 |     xmlFree(use); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaFreeAttributeUseProhib: | 
 |  * @prohib:  an attribute use prohibition | 
 |  * | 
 |  * Deallocates an attribute use structure. | 
 |  */ | 
 | static void | 
 | xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib) | 
 | { | 
 |     if (prohib == NULL) | 
 |         return; | 
 |     xmlFree(prohib); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaFreeWildcardNsSet: | 
 |  * set:  a schema wildcard namespace | 
 |  * | 
 |  * Deallocates a list of wildcard constraint structures. | 
 |  */ | 
 | static void | 
 | xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set) | 
 | { | 
 |     xmlSchemaWildcardNsPtr next; | 
 |  | 
 |     while (set != NULL) { | 
 | 	next = set->next; | 
 | 	xmlFree(set); | 
 | 	set = next; | 
 |     } | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaFreeWildcard: | 
 |  * @wildcard:  a wildcard structure | 
 |  * | 
 |  * Deallocates a wildcard structure. | 
 |  */ | 
 | void | 
 | xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard) | 
 | { | 
 |     if (wildcard == NULL) | 
 |         return; | 
 |     if (wildcard->annot != NULL) | 
 |         xmlSchemaFreeAnnot(wildcard->annot); | 
 |     if (wildcard->nsSet != NULL) | 
 | 	xmlSchemaFreeWildcardNsSet(wildcard->nsSet); | 
 |     if (wildcard->negNsSet != NULL) | 
 | 	xmlFree(wildcard->negNsSet); | 
 |     xmlFree(wildcard); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaFreeAttributeGroup: | 
 |  * @schema:  a schema attribute group structure | 
 |  * | 
 |  * Deallocate a Schema Attribute Group structure. | 
 |  */ | 
 | static void | 
 | xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr) | 
 | { | 
 |     if (attrGr == NULL) | 
 |         return; | 
 |     if (attrGr->annot != NULL) | 
 |         xmlSchemaFreeAnnot(attrGr->annot); | 
 |     if (attrGr->attrUses != NULL) | 
 | 	xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses); | 
 |     xmlFree(attrGr); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaFreeQNameRef: | 
 |  * @item: a QName reference structure | 
 |  * | 
 |  * Deallocatea a QName reference structure. | 
 |  */ | 
 | static void | 
 | xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item) | 
 | { | 
 |     xmlFree(item); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaFreeTypeLinkList: | 
 |  * @alink: a type link | 
 |  * | 
 |  * Deallocate a list of types. | 
 |  */ | 
 | static void | 
 | xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link) | 
 | { | 
 |     xmlSchemaTypeLinkPtr next; | 
 |  | 
 |     while (link != NULL) { | 
 | 	next = link->next; | 
 | 	xmlFree(link); | 
 | 	link = next; | 
 |     } | 
 | } | 
 |  | 
 | static void | 
 | xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto) | 
 | { | 
 |     xmlSchemaIDCStateObjPtr next; | 
 |     while (sto != NULL) { | 
 | 	next = sto->next; | 
 | 	if (sto->history != NULL) | 
 | 	    xmlFree(sto->history); | 
 | 	if (sto->xpathCtxt != NULL) | 
 | 	    xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt); | 
 | 	xmlFree(sto); | 
 | 	sto = next; | 
 |     } | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaFreeIDC: | 
 |  * @idc: a identity-constraint definition | 
 |  * | 
 |  * Deallocates an identity-constraint definition. | 
 |  */ | 
 | static void | 
 | xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef) | 
 | { | 
 |     xmlSchemaIDCSelectPtr cur, prev; | 
 |  | 
 |     if (idcDef == NULL) | 
 | 	return; | 
 |     if (idcDef->annot != NULL) | 
 |         xmlSchemaFreeAnnot(idcDef->annot); | 
 |     /* Selector */ | 
 |     if (idcDef->selector != NULL) { | 
 | 	if (idcDef->selector->xpathComp != NULL) | 
 | 	    xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp); | 
 | 	xmlFree(idcDef->selector); | 
 |     } | 
 |     /* Fields */ | 
 |     if (idcDef->fields != NULL) { | 
 | 	cur = idcDef->fields; | 
 | 	do { | 
 | 	    prev = cur; | 
 | 	    cur = cur->next; | 
 | 	    if (prev->xpathComp != NULL) | 
 | 		xmlFreePattern((xmlPatternPtr) prev->xpathComp); | 
 | 	    xmlFree(prev); | 
 | 	} while (cur != NULL); | 
 |     } | 
 |     xmlFree(idcDef); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaFreeElement: | 
 |  * @schema:  a schema element structure | 
 |  * | 
 |  * Deallocate a Schema Element structure. | 
 |  */ | 
 | static void | 
 | xmlSchemaFreeElement(xmlSchemaElementPtr elem) | 
 | { | 
 |     if (elem == NULL) | 
 |         return; | 
 |     if (elem->annot != NULL) | 
 |         xmlSchemaFreeAnnot(elem->annot); | 
 |     if (elem->contModel != NULL) | 
 |         xmlRegFreeRegexp(elem->contModel); | 
 |     if (elem->defVal != NULL) | 
 | 	xmlSchemaFreeValue(elem->defVal); | 
 |     xmlFree(elem); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaFreeFacet: | 
 |  * @facet:  a schema facet structure | 
 |  * | 
 |  * Deallocate a Schema Facet structure. | 
 |  */ | 
 | void | 
 | xmlSchemaFreeFacet(xmlSchemaFacetPtr facet) | 
 | { | 
 |     if (facet == NULL) | 
 |         return; | 
 |     if (facet->val != NULL) | 
 |         xmlSchemaFreeValue(facet->val); | 
 |     if (facet->regexp != NULL) | 
 |         xmlRegFreeRegexp(facet->regexp); | 
 |     if (facet->annot != NULL) | 
 |         xmlSchemaFreeAnnot(facet->annot); | 
 |     xmlFree(facet); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaFreeType: | 
 |  * @type:  a schema type structure | 
 |  * | 
 |  * Deallocate a Schema Type structure. | 
 |  */ | 
 | void | 
 | xmlSchemaFreeType(xmlSchemaTypePtr type) | 
 | { | 
 |     if (type == NULL) | 
 |         return; | 
 |     if (type->annot != NULL) | 
 |         xmlSchemaFreeAnnot(type->annot); | 
 |     if (type->facets != NULL) { | 
 |         xmlSchemaFacetPtr facet, next; | 
 |  | 
 |         facet = type->facets; | 
 |         while (facet != NULL) { | 
 |             next = facet->next; | 
 |             xmlSchemaFreeFacet(facet); | 
 |             facet = next; | 
 |         } | 
 |     } | 
 |     if (type->attrUses != NULL) | 
 | 	xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses); | 
 |     if (type->memberTypes != NULL) | 
 | 	xmlSchemaFreeTypeLinkList(type->memberTypes); | 
 |     if (type->facetSet != NULL) { | 
 | 	xmlSchemaFacetLinkPtr next, link; | 
 |  | 
 | 	link = type->facetSet; | 
 | 	do { | 
 | 	    next = link->next; | 
 | 	    xmlFree(link); | 
 | 	    link = next; | 
 | 	} while (link != NULL); | 
 |     } | 
 |     if (type->contModel != NULL) | 
 |         xmlRegFreeRegexp(type->contModel); | 
 |     xmlFree(type); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaFreeModelGroupDef: | 
 |  * @item:  a schema model group definition | 
 |  * | 
 |  * Deallocates a schema model group definition. | 
 |  */ | 
 | static void | 
 | xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item) | 
 | { | 
 |     if (item->annot != NULL) | 
 | 	xmlSchemaFreeAnnot(item->annot); | 
 |     xmlFree(item); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaFreeModelGroup: | 
 |  * @item:  a schema model group | 
 |  * | 
 |  * Deallocates a schema model group structure. | 
 |  */ | 
 | static void | 
 | xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item) | 
 | { | 
 |     if (item->annot != NULL) | 
 | 	xmlSchemaFreeAnnot(item->annot); | 
 |     xmlFree(item); | 
 | } | 
 |  | 
 | static void | 
 | xmlSchemaComponentListFree(xmlSchemaItemListPtr list) | 
 | { | 
 |     if ((list == NULL) || (list->nbItems == 0)) | 
 | 	return; | 
 |     { | 
 | 	xmlSchemaTreeItemPtr item; | 
 | 	xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items; | 
 | 	int i; | 
 |  | 
 | 	for (i = 0; i < list->nbItems; i++) { | 
 | 	    item = items[i]; | 
 | 	    if (item == NULL) | 
 | 		continue; | 
 | 	    switch (item->type) { | 
 | 		case XML_SCHEMA_TYPE_SIMPLE: | 
 | 		case XML_SCHEMA_TYPE_COMPLEX: | 
 | 		    xmlSchemaFreeType((xmlSchemaTypePtr) item); | 
 | 		    break; | 
 | 		case XML_SCHEMA_TYPE_ATTRIBUTE: | 
 | 		    xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item); | 
 | 		    break; | 
 | 		case XML_SCHEMA_TYPE_ATTRIBUTE_USE: | 
 | 		    xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item); | 
 | 		    break; | 
 | 		case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB: | 
 | 		    xmlSchemaFreeAttributeUseProhib( | 
 | 			(xmlSchemaAttributeUseProhibPtr) item); | 
 | 		    break; | 
 | 		case XML_SCHEMA_TYPE_ELEMENT: | 
 | 		    xmlSchemaFreeElement((xmlSchemaElementPtr) item); | 
 | 		    break; | 
 | 		case XML_SCHEMA_TYPE_PARTICLE: | 
 | 		    if (item->annot != NULL) | 
 | 			xmlSchemaFreeAnnot(item->annot); | 
 | 		    xmlFree(item); | 
 | 		    break; | 
 | 		case XML_SCHEMA_TYPE_SEQUENCE: | 
 | 		case XML_SCHEMA_TYPE_CHOICE: | 
 | 		case XML_SCHEMA_TYPE_ALL: | 
 | 		    xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item); | 
 | 		    break; | 
 | 		case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: | 
 | 		    xmlSchemaFreeAttributeGroup( | 
 | 			(xmlSchemaAttributeGroupPtr) item); | 
 | 		    break; | 
 | 		case XML_SCHEMA_TYPE_GROUP: | 
 | 		    xmlSchemaFreeModelGroupDef( | 
 | 			(xmlSchemaModelGroupDefPtr) item); | 
 | 		    break; | 
 | 		case XML_SCHEMA_TYPE_ANY: | 
 | 		case XML_SCHEMA_TYPE_ANY_ATTRIBUTE: | 
 | 		    xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item); | 
 | 		    break; | 
 | 		case XML_SCHEMA_TYPE_IDC_KEY: | 
 | 		case XML_SCHEMA_TYPE_IDC_UNIQUE: | 
 | 		case XML_SCHEMA_TYPE_IDC_KEYREF: | 
 | 		    xmlSchemaFreeIDC((xmlSchemaIDCPtr) item); | 
 | 		    break; | 
 | 		case XML_SCHEMA_TYPE_NOTATION: | 
 | 		    xmlSchemaFreeNotation((xmlSchemaNotationPtr) item); | 
 | 		    break; | 
 | 		case XML_SCHEMA_EXTRA_QNAMEREF: | 
 | 		    xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item); | 
 | 		    break; | 
 | 		default: { | 
 | 		    /* TODO: This should never be hit. */ | 
 | 		    xmlSchemaPSimpleInternalErr(NULL, | 
 | 			"Internal error: xmlSchemaComponentListFree, " | 
 | 			"unexpected component type '%s'\n", | 
 | 			(const xmlChar *) WXS_ITEM_TYPE_NAME(item)); | 
 | 			 } | 
 | 		    break; | 
 | 	    } | 
 | 	} | 
 | 	list->nbItems = 0; | 
 |     } | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaFree: | 
 |  * @schema:  a schema structure | 
 |  * | 
 |  * Deallocate a Schema structure. | 
 |  */ | 
 | void | 
 | xmlSchemaFree(xmlSchemaPtr schema) | 
 | { | 
 |     if (schema == NULL) | 
 |         return; | 
 |     /* @volatiles is not used anymore :-/ */ | 
 |     if (schema->volatiles != NULL) | 
 | 	TODO | 
 |     /* | 
 |     * Note that those slots are not responsible for freeing | 
 |     * schema components anymore; this will now be done by | 
 |     * the schema buckets. | 
 |     */ | 
 |     if (schema->notaDecl != NULL) | 
 |         xmlHashFree(schema->notaDecl, NULL); | 
 |     if (schema->attrDecl != NULL) | 
 |         xmlHashFree(schema->attrDecl, NULL); | 
 |     if (schema->attrgrpDecl != NULL) | 
 |         xmlHashFree(schema->attrgrpDecl, NULL); | 
 |     if (schema->elemDecl != NULL) | 
 |         xmlHashFree(schema->elemDecl, NULL); | 
 |     if (schema->typeDecl != NULL) | 
 |         xmlHashFree(schema->typeDecl, NULL); | 
 |     if (schema->groupDecl != NULL) | 
 |         xmlHashFree(schema->groupDecl, NULL); | 
 |     if (schema->idcDef != NULL) | 
 |         xmlHashFree(schema->idcDef, NULL); | 
 |  | 
 |     if (schema->schemasImports != NULL) | 
 | 	xmlHashFree(schema->schemasImports, | 
 | 		    (xmlHashDeallocator) xmlSchemaBucketFree); | 
 |     if (schema->includes != NULL) { | 
 | 	xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes; | 
 | 	int i; | 
 | 	for (i = 0; i < list->nbItems; i++) { | 
 | 	    xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]); | 
 | 	} | 
 | 	xmlSchemaItemListFree(list); | 
 |     } | 
 |     if (schema->annot != NULL) | 
 |         xmlSchemaFreeAnnot(schema->annot); | 
 |     /* Never free the doc here, since this will be done by the buckets. */ | 
 |  | 
 |     xmlDictFree(schema->dict); | 
 |     xmlFree(schema); | 
 | } | 
 |  | 
 | /************************************************************************ | 
 |  * 									* | 
 |  * 			Debug functions					* | 
 |  * 									* | 
 |  ************************************************************************/ | 
 |  | 
 | #ifdef LIBXML_OUTPUT_ENABLED | 
 |  | 
 | static void | 
 | xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */ | 
 |  | 
 | /** | 
 |  * xmlSchemaElementDump: | 
 |  * @elem:  an element | 
 |  * @output:  the file output | 
 |  * | 
 |  * Dump the element | 
 |  */ | 
 | static void | 
 | xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output, | 
 |                      const xmlChar * name ATTRIBUTE_UNUSED, | 
 | 		     const xmlChar * namespace ATTRIBUTE_UNUSED, | 
 |                      const xmlChar * context ATTRIBUTE_UNUSED) | 
 | { | 
 |     if (elem == NULL) | 
 |         return; | 
 |  | 
 |  | 
 |     fprintf(output, "Element"); | 
 |     if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL) | 
 | 	fprintf(output, " (global)"); | 
 |     fprintf(output, ": '%s' ", elem->name); | 
 |     if (namespace != NULL) | 
 | 	fprintf(output, "ns '%s'", namespace); | 
 |     fprintf(output, "\n"); | 
 | #if 0 | 
 |     if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) { | 
 | 	fprintf(output, "  min %d ", elem->minOccurs); | 
 |         if (elem->maxOccurs >= UNBOUNDED) | 
 |             fprintf(output, "max: unbounded\n"); | 
 |         else if (elem->maxOccurs != 1) | 
 |             fprintf(output, "max: %d\n", elem->maxOccurs); | 
 |         else | 
 |             fprintf(output, "\n"); | 
 |     } | 
 | #endif | 
 |     /* | 
 |     * Misc other properties. | 
 |     */ | 
 |     if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) || | 
 | 	(elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) || | 
 | 	(elem->flags & XML_SCHEMAS_ELEM_FIXED) || | 
 | 	(elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) { | 
 | 	fprintf(output, "  props: "); | 
 | 	if (elem->flags & XML_SCHEMAS_ELEM_FIXED) | 
 | 	    fprintf(output, "[fixed] "); | 
 | 	if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) | 
 | 	    fprintf(output, "[default] "); | 
 | 	if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) | 
 | 	    fprintf(output, "[abstract] "); | 
 | 	if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE) | 
 | 	    fprintf(output, "[nillable] "); | 
 | 	fprintf(output, "\n"); | 
 |     } | 
 |     /* | 
 |     * Default/fixed value. | 
 |     */ | 
 |     if (elem->value != NULL) | 
 | 	fprintf(output, "  value: '%s'\n", elem->value); | 
 |     /* | 
 |     * Type. | 
 |     */ | 
 |     if (elem->namedType != NULL) { | 
 | 	fprintf(output, "  type: '%s' ", elem->namedType); | 
 | 	if (elem->namedTypeNs != NULL) | 
 | 	    fprintf(output, "ns '%s'\n", elem->namedTypeNs); | 
 | 	else | 
 | 	    fprintf(output, "\n"); | 
 |     } else if (elem->subtypes != NULL) { | 
 | 	/* | 
 | 	* Dump local types. | 
 | 	*/ | 
 | 	xmlSchemaTypeDump(elem->subtypes, output); | 
 |     } | 
 |     /* | 
 |     * Substitution group. | 
 |     */ | 
 |     if (elem->substGroup != NULL) { | 
 | 	fprintf(output, "  substitutionGroup: '%s' ", elem->substGroup); | 
 | 	if (elem->substGroupNs != NULL) | 
 | 	    fprintf(output, "ns '%s'\n", elem->substGroupNs); | 
 | 	else | 
 | 	    fprintf(output, "\n"); | 
 |     } | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaAnnotDump: | 
 |  * @output:  the file output | 
 |  * @annot:  a annotation | 
 |  * | 
 |  * Dump the annotation | 
 |  */ | 
 | static void | 
 | xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot) | 
 | { | 
 |     xmlChar *content; | 
 |  | 
 |     if (annot == NULL) | 
 |         return; | 
 |  | 
 |     content = xmlNodeGetContent(annot->content); | 
 |     if (content != NULL) { | 
 |         fprintf(output, "  Annot: %s\n", content); | 
 |         xmlFree(content); | 
 |     } else | 
 |         fprintf(output, "  Annot: empty\n"); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaContentModelDump: | 
 |  * @particle: the schema particle | 
 |  * @output: the file output | 
 |  * @depth: the depth used for intentation | 
 |  * | 
 |  * Dump a SchemaType structure | 
 |  */ | 
 | static void | 
 | xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth) | 
 | { | 
 |     xmlChar *str = NULL; | 
 |     xmlSchemaTreeItemPtr term; | 
 |     char shift[100]; | 
 |     int i; | 
 |  | 
 |     if (particle == NULL) | 
 | 	return; | 
 |     for (i = 0;((i < depth) && (i < 25));i++) | 
 |         shift[2 * i] = shift[2 * i + 1] = ' '; | 
 |     shift[2 * i] = shift[2 * i + 1] = 0; | 
 |     fprintf(output, "%s", shift); | 
 |     if (particle->children == NULL) { | 
 | 	fprintf(output, "MISSING particle term\n"); | 
 | 	return; | 
 |     } | 
 |     term = particle->children; | 
 |     if (term == NULL) { | 
 | 	fprintf(output, "(NULL)"); | 
 |     } else { | 
 | 	switch (term->type) { | 
 | 	    case XML_SCHEMA_TYPE_ELEMENT: | 
 | 		fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str, | 
 | 		    ((xmlSchemaElementPtr)term)->targetNamespace, | 
 | 		    ((xmlSchemaElementPtr)term)->name)); | 
 | 		FREE_AND_NULL(str); | 
 | 		break; | 
 | 	    case XML_SCHEMA_TYPE_SEQUENCE: | 
 | 		fprintf(output, "SEQUENCE"); | 
 | 		break; | 
 | 	    case XML_SCHEMA_TYPE_CHOICE: | 
 | 		fprintf(output, "CHOICE"); | 
 | 		break; | 
 | 	    case XML_SCHEMA_TYPE_ALL: | 
 | 		fprintf(output, "ALL"); | 
 | 		break; | 
 | 	    case XML_SCHEMA_TYPE_ANY: | 
 | 		fprintf(output, "ANY"); | 
 | 		break; | 
 | 	    default: | 
 | 		fprintf(output, "UNKNOWN\n"); | 
 | 		return; | 
 | 	} | 
 |     } | 
 |     if (particle->minOccurs != 1) | 
 | 	fprintf(output, " min: %d", particle->minOccurs); | 
 |     if (particle->maxOccurs >= UNBOUNDED) | 
 | 	fprintf(output, " max: unbounded"); | 
 |     else if (particle->maxOccurs != 1) | 
 | 	fprintf(output, " max: %d", particle->maxOccurs); | 
 |     fprintf(output, "\n"); | 
 |     if (term && | 
 | 	((term->type == XML_SCHEMA_TYPE_SEQUENCE) || | 
 | 	 (term->type == XML_SCHEMA_TYPE_CHOICE) || | 
 | 	 (term->type == XML_SCHEMA_TYPE_ALL)) && | 
 | 	 (term->children != NULL)) { | 
 | 	xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children, | 
 | 	    output, depth +1); | 
 |     } | 
 |     if (particle->next != NULL) | 
 | 	xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next, | 
 | 		output, depth); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaAttrUsesDump: | 
 |  * @uses:  attribute uses list | 
 |  * @output:  the file output | 
 |  * | 
 |  * Dumps a list of attribute use components. | 
 |  */ | 
 | static void | 
 | xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output) | 
 | { | 
 |     xmlSchemaAttributeUsePtr use; | 
 |     xmlSchemaAttributeUseProhibPtr prohib; | 
 |     xmlSchemaQNameRefPtr ref; | 
 |     const xmlChar *name, *tns; | 
 |     xmlChar *str = NULL; | 
 |     int i; | 
 |  | 
 |     if ((uses == NULL) || (uses->nbItems == 0)) | 
 |         return; | 
 |  | 
 |     fprintf(output, "  attributes:\n"); | 
 |     for (i = 0; i < uses->nbItems; i++) { | 
 | 	use = uses->items[i]; | 
 | 	if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) { | 
 | 	    fprintf(output, "  [prohibition] "); | 
 | 	    prohib = (xmlSchemaAttributeUseProhibPtr) use; | 
 | 	    name = prohib->name; | 
 | 	    tns = prohib->targetNamespace; | 
 | 	} else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) { | 
 | 	    fprintf(output, "  [reference] "); | 
 | 	    ref = (xmlSchemaQNameRefPtr) use; | 
 | 	    name = ref->name; | 
 | 	    tns = ref->targetNamespace; | 
 | 	} else { | 
 | 	    fprintf(output, "  [use] "); | 
 | 	    name = WXS_ATTRUSE_DECL_NAME(use); | 
 | 	    tns = WXS_ATTRUSE_DECL_TNS(use); | 
 | 	} | 
 | 	fprintf(output, "'%s'\n", | 
 | 	    (const char *) xmlSchemaFormatQName(&str, tns, name)); | 
 | 	FREE_AND_NULL(str); | 
 |     } | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaTypeDump: | 
 |  * @output:  the file output | 
 |  * @type:  a type structure | 
 |  * | 
 |  * Dump a SchemaType structure | 
 |  */ | 
 | static void | 
 | xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output) | 
 | { | 
 |     if (type == NULL) { | 
 |         fprintf(output, "Type: NULL\n"); | 
 |         return; | 
 |     } | 
 |     fprintf(output, "Type: "); | 
 |     if (type->name != NULL) | 
 |         fprintf(output, "'%s' ", type->name); | 
 |     else | 
 |         fprintf(output, "(no name) "); | 
 |     if (type->targetNamespace != NULL) | 
 | 	fprintf(output, "ns '%s' ", type->targetNamespace); | 
 |     switch (type->type) { | 
 |         case XML_SCHEMA_TYPE_BASIC: | 
 |             fprintf(output, "[basic] "); | 
 |             break; | 
 |         case XML_SCHEMA_TYPE_SIMPLE: | 
 |             fprintf(output, "[simple] "); | 
 |             break; | 
 |         case XML_SCHEMA_TYPE_COMPLEX: | 
 |             fprintf(output, "[complex] "); | 
 |             break; | 
 |         case XML_SCHEMA_TYPE_SEQUENCE: | 
 |             fprintf(output, "[sequence] "); | 
 |             break; | 
 |         case XML_SCHEMA_TYPE_CHOICE: | 
 |             fprintf(output, "[choice] "); | 
 |             break; | 
 |         case XML_SCHEMA_TYPE_ALL: | 
 |             fprintf(output, "[all] "); | 
 |             break; | 
 |         case XML_SCHEMA_TYPE_UR: | 
 |             fprintf(output, "[ur] "); | 
 |             break; | 
 |         case XML_SCHEMA_TYPE_RESTRICTION: | 
 |             fprintf(output, "[restriction] "); | 
 |             break; | 
 |         case XML_SCHEMA_TYPE_EXTENSION: | 
 |             fprintf(output, "[extension] "); | 
 |             break; | 
 |         default: | 
 |             fprintf(output, "[unknown type %d] ", type->type); | 
 |             break; | 
 |     } | 
 |     fprintf(output, "content: "); | 
 |     switch (type->contentType) { | 
 |         case XML_SCHEMA_CONTENT_UNKNOWN: | 
 |             fprintf(output, "[unknown] "); | 
 |             break; | 
 |         case XML_SCHEMA_CONTENT_EMPTY: | 
 |             fprintf(output, "[empty] "); | 
 |             break; | 
 |         case XML_SCHEMA_CONTENT_ELEMENTS: | 
 |             fprintf(output, "[element] "); | 
 |             break; | 
 |         case XML_SCHEMA_CONTENT_MIXED: | 
 |             fprintf(output, "[mixed] "); | 
 |             break; | 
 |         case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS: | 
 | 	/* not used. */ | 
 |             break; | 
 |         case XML_SCHEMA_CONTENT_BASIC: | 
 |             fprintf(output, "[basic] "); | 
 |             break; | 
 |         case XML_SCHEMA_CONTENT_SIMPLE: | 
 |             fprintf(output, "[simple] "); | 
 |             break; | 
 |         case XML_SCHEMA_CONTENT_ANY: | 
 |             fprintf(output, "[any] "); | 
 |             break; | 
 |     } | 
 |     fprintf(output, "\n"); | 
 |     if (type->base != NULL) { | 
 |         fprintf(output, "  base type: '%s'", type->base); | 
 | 	if (type->baseNs != NULL) | 
 | 	    fprintf(output, " ns '%s'\n", type->baseNs); | 
 | 	else | 
 | 	    fprintf(output, "\n"); | 
 |     } | 
 |     if (type->attrUses != NULL) | 
 | 	xmlSchemaAttrUsesDump(type->attrUses, output); | 
 |     if (type->annot != NULL) | 
 |         xmlSchemaAnnotDump(output, type->annot); | 
 | #ifdef DUMP_CONTENT_MODEL | 
 |     if ((type->type == XML_SCHEMA_TYPE_COMPLEX) && | 
 | 	(type->subtypes != NULL)) { | 
 | 	xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes, | 
 | 	    output, 1); | 
 |     } | 
 | #endif | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaDump: | 
 |  * @output:  the file output | 
 |  * @schema:  a schema structure | 
 |  * | 
 |  * Dump a Schema structure. | 
 |  */ | 
 | void | 
 | xmlSchemaDump(FILE * output, xmlSchemaPtr schema) | 
 | { | 
 |     if (output == NULL) | 
 |         return; | 
 |     if (schema == NULL) { | 
 |         fprintf(output, "Schemas: NULL\n"); | 
 |         return; | 
 |     } | 
 |     fprintf(output, "Schemas: "); | 
 |     if (schema->name != NULL) | 
 |         fprintf(output, "%s, ", schema->name); | 
 |     else | 
 |         fprintf(output, "no name, "); | 
 |     if (schema->targetNamespace != NULL) | 
 |         fprintf(output, "%s", (const char *) schema->targetNamespace); | 
 |     else | 
 |         fprintf(output, "no target namespace"); | 
 |     fprintf(output, "\n"); | 
 |     if (schema->annot != NULL) | 
 |         xmlSchemaAnnotDump(output, schema->annot); | 
 |     xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump, | 
 |                 output); | 
 |     xmlHashScanFull(schema->elemDecl, | 
 |                     (xmlHashScannerFull) xmlSchemaElementDump, output); | 
 | } | 
 |  | 
 | #ifdef DEBUG_IDC_NODE_TABLE | 
 | /** | 
 |  * xmlSchemaDebugDumpIDCTable: | 
 |  * @vctxt: the WXS validation context | 
 |  * | 
 |  * Displays the current IDC table for debug purposes. | 
 |  */ | 
 | static void | 
 | xmlSchemaDebugDumpIDCTable(FILE * output, | 
 | 			   const xmlChar *namespaceName, | 
 | 			   const xmlChar *localName, | 
 | 			   xmlSchemaPSVIIDCBindingPtr bind) | 
 | { | 
 |     xmlChar *str = NULL; | 
 |     const xmlChar *value; | 
 |     xmlSchemaPSVIIDCNodePtr tab; | 
 |     xmlSchemaPSVIIDCKeyPtr key; | 
 |     int i, j, res; | 
 |  | 
 |     fprintf(output, "IDC: TABLES on '%s'\n", | 
 | 	xmlSchemaFormatQName(&str, namespaceName, localName)); | 
 |     FREE_AND_NULL(str) | 
 |  | 
 |     if (bind == NULL) | 
 | 	return; | 
 |     do { | 
 | 	fprintf(output, "IDC:   BINDING '%s' (%d)\n", | 
 | 	    xmlSchemaGetComponentQName(&str, | 
 | 		bind->definition), bind->nbNodes); | 
 | 	FREE_AND_NULL(str) | 
 | 	for (i = 0; i < bind->nbNodes; i++) { | 
 | 	    tab = bind->nodeTable[i]; | 
 | 	    fprintf(output, "         ( "); | 
 | 	    for (j = 0; j < bind->definition->nbFields; j++) { | 
 | 		key = tab->keys[j]; | 
 | 		if ((key != NULL) && (key->val != NULL)) { | 
 | 		    res = xmlSchemaGetCanonValue(key->val, &value); | 
 | 		    if (res >= 0) | 
 | 			fprintf(output, "'%s' ", value); | 
 | 		    else | 
 | 			fprintf(output, "CANON-VALUE-FAILED "); | 
 | 		    if (res == 0) | 
 | 			FREE_AND_NULL(value) | 
 | 		} else if (key != NULL) | 
 | 		    fprintf(output, "(no val), "); | 
 | 		else | 
 | 		    fprintf(output, "(key missing), "); | 
 | 	    } | 
 | 	    fprintf(output, ")\n"); | 
 | 	} | 
 | 	if (bind->dupls && bind->dupls->nbItems) { | 
 | 	    fprintf(output, "IDC:     dupls (%d):\n", bind->dupls->nbItems); | 
 | 	    for (i = 0; i < bind->dupls->nbItems; i++) { | 
 | 		tab = bind->dupls->items[i]; | 
 | 		fprintf(output, "         ( "); | 
 | 		for (j = 0; j < bind->definition->nbFields; j++) { | 
 | 		    key = tab->keys[j]; | 
 | 		    if ((key != NULL) && (key->val != NULL)) { | 
 | 			res = xmlSchemaGetCanonValue(key->val, &value); | 
 | 			if (res >= 0) | 
 | 			    fprintf(output, "'%s' ", value); | 
 | 			else | 
 | 			    fprintf(output, "CANON-VALUE-FAILED "); | 
 | 			if (res == 0) | 
 | 			    FREE_AND_NULL(value) | 
 | 		    } else if (key != NULL) | 
 | 		    fprintf(output, "(no val), "); | 
 | 			else | 
 | 			    fprintf(output, "(key missing), "); | 
 | 		} | 
 | 		fprintf(output, ")\n"); | 
 | 	    } | 
 | 	} | 
 | 	bind = bind->next; | 
 |     } while (bind != NULL); | 
 | } | 
 | #endif /* DEBUG_IDC */ | 
 | #endif /* LIBXML_OUTPUT_ENABLED */ | 
 |  | 
 | /************************************************************************ | 
 |  *									* | 
 |  * 			Utilities					* | 
 |  *									* | 
 |  ************************************************************************/ | 
 |  | 
 | /** | 
 |  * xmlSchemaGetPropNode: | 
 |  * @node: the element node | 
 |  * @name: the name of the attribute | 
 |  * | 
 |  * Seeks an attribute with a name of @name in | 
 |  * no namespace. | 
 |  * | 
 |  * Returns the attribute or NULL if not present. | 
 |  */ | 
 | static xmlAttrPtr | 
 | xmlSchemaGetPropNode(xmlNodePtr node, const char *name) | 
 | { | 
 |     xmlAttrPtr prop; | 
 |  | 
 |     if ((node == NULL) || (name == NULL)) | 
 | 	return(NULL); | 
 |     prop = node->properties; | 
 |     while (prop != NULL) { | 
 |         if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name)) | 
 | 	    return(prop); | 
 | 	prop = prop->next; | 
 |     } | 
 |     return (NULL); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaGetPropNodeNs: | 
 |  * @node: the element node | 
 |  * @uri: the uri | 
 |  * @name: the name of the attribute | 
 |  * | 
 |  * Seeks an attribute with a local name of @name and | 
 |  * a namespace URI of @uri. | 
 |  * | 
 |  * Returns the attribute or NULL if not present. | 
 |  */ | 
 | static xmlAttrPtr | 
 | xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name) | 
 | { | 
 |     xmlAttrPtr prop; | 
 |  | 
 |     if ((node == NULL) || (name == NULL)) | 
 | 	return(NULL); | 
 |     prop = node->properties; | 
 |     while (prop != NULL) { | 
 | 	if ((prop->ns != NULL) && | 
 | 	    xmlStrEqual(prop->name, BAD_CAST name) && | 
 | 	    xmlStrEqual(prop->ns->href, BAD_CAST uri)) | 
 | 	    return(prop); | 
 | 	prop = prop->next; | 
 |     } | 
 |     return (NULL); | 
 | } | 
 |  | 
 | static const xmlChar * | 
 | xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node) | 
 | { | 
 |     xmlChar *val; | 
 |     const xmlChar *ret; | 
 |  | 
 |     val = xmlNodeGetContent(node); | 
 |     if (val == NULL) | 
 | 	val = xmlStrdup((xmlChar *)""); | 
 |     ret = xmlDictLookup(ctxt->dict, val, -1); | 
 |     xmlFree(val); | 
 |     return(ret); | 
 | } | 
 |  | 
 | static const xmlChar * | 
 | xmlSchemaGetNodeContentNoDict(xmlNodePtr node) | 
 | { | 
 |     return((const xmlChar*) xmlNodeGetContent(node)); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaGetProp: | 
 |  * @ctxt: the parser context | 
 |  * @node: the node | 
 |  * @name: the property name | 
 |  * | 
 |  * Read a attribute value and internalize the string | 
 |  * | 
 |  * Returns the string or NULL if not present. | 
 |  */ | 
 | static const xmlChar * | 
 | xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, | 
 |                  const char *name) | 
 | { | 
 |     xmlChar *val; | 
 |     const xmlChar *ret; | 
 |  | 
 |     val = xmlGetNoNsProp(node, BAD_CAST name); | 
 |     if (val == NULL) | 
 |         return(NULL); | 
 |     ret = xmlDictLookup(ctxt->dict, val, -1); | 
 |     xmlFree(val); | 
 |     return(ret); | 
 | } | 
 |  | 
 | /************************************************************************ | 
 |  * 									* | 
 |  * 			Parsing functions				* | 
 |  * 									* | 
 |  ************************************************************************/ | 
 |  | 
 | #define WXS_FIND_GLOBAL_ITEM(slot)			\ | 
 |     if (xmlStrEqual(nsName, schema->targetNamespace)) { \ | 
 | 	ret = xmlHashLookup(schema->slot, name); \ | 
 | 	if (ret != NULL) goto exit; \ | 
 |     } \ | 
 |     if (xmlHashSize(schema->schemasImports) > 1) { \ | 
 | 	xmlSchemaImportPtr import; \ | 
 | 	if (nsName == NULL) \ | 
 | 	    import = xmlHashLookup(schema->schemasImports, \ | 
 | 		XML_SCHEMAS_NO_NAMESPACE); \ | 
 | 	else \ | 
 | 	    import = xmlHashLookup(schema->schemasImports, nsName); \ | 
 | 	if (import == NULL) \ | 
 | 	    goto exit; \ | 
 | 	ret = xmlHashLookup(import->schema->slot, name); \ | 
 |     } | 
 |  | 
 | /** | 
 |  * xmlSchemaGetElem: | 
 |  * @schema:  the schema context | 
 |  * @name:  the element name | 
 |  * @ns:  the element namespace | 
 |  * | 
 |  * Lookup a global element declaration in the schema. | 
 |  * | 
 |  * Returns the element declaration or NULL if not found. | 
 |  */ | 
 | static xmlSchemaElementPtr | 
 | xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name, | 
 |                  const xmlChar * nsName) | 
 | { | 
 |     xmlSchemaElementPtr ret = NULL; | 
 |  | 
 |     if ((name == NULL) || (schema == NULL)) | 
 |         return(NULL); | 
 |     if (schema != NULL) { | 
 | 	WXS_FIND_GLOBAL_ITEM(elemDecl) | 
 |     } | 
 | exit: | 
 | #ifdef DEBUG | 
 |     if (ret == NULL) { | 
 |         if (nsName == NULL) | 
 |             fprintf(stderr, "Unable to lookup element decl. %s", name); | 
 |         else | 
 |             fprintf(stderr, "Unable to lookup element decl. %s:%s", name, | 
 |                     nsName); | 
 |     } | 
 | #endif | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaGetType: | 
 |  * @schema:  the main schema | 
 |  * @name:  the type's name | 
 |  * nsName:  the type's namespace | 
 |  * | 
 |  * Lookup a type in the schemas or the predefined types | 
 |  * | 
 |  * Returns the group definition or NULL if not found. | 
 |  */ | 
 | static xmlSchemaTypePtr | 
 | xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name, | 
 |                  const xmlChar * nsName) | 
 | { | 
 |     xmlSchemaTypePtr ret = NULL; | 
 |  | 
 |     if (name == NULL) | 
 |         return (NULL); | 
 |     /* First try the built-in types. */ | 
 |     if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) { | 
 | 	ret = xmlSchemaGetPredefinedType(name, nsName); | 
 | 	if (ret != NULL) | 
 | 	    goto exit; | 
 | 	/* | 
 | 	* Note that we try the parsed schemas as well here | 
 | 	* since one might have parsed the S4S, which contain more | 
 | 	* than the built-in types. | 
 | 	* TODO: Can we optimize this? | 
 | 	*/ | 
 |     } | 
 |     if (schema != NULL) { | 
 | 	WXS_FIND_GLOBAL_ITEM(typeDecl) | 
 |     } | 
 | exit: | 
 |  | 
 | #ifdef DEBUG | 
 |     if (ret == NULL) { | 
 |         if (nsName == NULL) | 
 |             fprintf(stderr, "Unable to lookup type %s", name); | 
 |         else | 
 |             fprintf(stderr, "Unable to lookup type %s:%s", name, | 
 |                     nsName); | 
 |     } | 
 | #endif | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaGetAttributeDecl: | 
 |  * @schema:  the context of the schema | 
 |  * @name:  the name of the attribute | 
 |  * @ns:  the target namespace of the attribute | 
 |  * | 
 |  * Lookup a an attribute in the schema or imported schemas | 
 |  * | 
 |  * Returns the attribute declaration or NULL if not found. | 
 |  */ | 
 | static xmlSchemaAttributePtr | 
 | xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name, | 
 |                  const xmlChar * nsName) | 
 | { | 
 |     xmlSchemaAttributePtr ret = NULL; | 
 |  | 
 |     if ((name == NULL) || (schema == NULL)) | 
 |         return (NULL); | 
 |     if (schema != NULL) { | 
 | 	WXS_FIND_GLOBAL_ITEM(attrDecl) | 
 |     } | 
 | exit: | 
 | #ifdef DEBUG | 
 |     if (ret == NULL) { | 
 |         if (nsName == NULL) | 
 |             fprintf(stderr, "Unable to lookup attribute %s", name); | 
 |         else | 
 |             fprintf(stderr, "Unable to lookup attribute %s:%s", name, | 
 |                     nsName); | 
 |     } | 
 | #endif | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaGetAttributeGroup: | 
 |  * @schema:  the context of the schema | 
 |  * @name:  the name of the attribute group | 
 |  * @ns:  the target namespace of the attribute group | 
 |  * | 
 |  * Lookup a an attribute group in the schema or imported schemas | 
 |  * | 
 |  * Returns the attribute group definition or NULL if not found. | 
 |  */ | 
 | static xmlSchemaAttributeGroupPtr | 
 | xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name, | 
 |                  const xmlChar * nsName) | 
 | { | 
 |     xmlSchemaAttributeGroupPtr ret = NULL; | 
 |  | 
 |     if ((name == NULL) || (schema == NULL)) | 
 |         return (NULL); | 
 |     if (schema != NULL) { | 
 | 	WXS_FIND_GLOBAL_ITEM(attrgrpDecl) | 
 |     } | 
 | exit: | 
 |     /* TODO: | 
 |     if ((ret != NULL) && (ret->redef != NULL)) { | 
 | 	* Return the last redefinition. * | 
 | 	ret = ret->redef; | 
 |     } | 
 |     */ | 
 | #ifdef DEBUG | 
 |     if (ret == NULL) { | 
 |         if (nsName == NULL) | 
 |             fprintf(stderr, "Unable to lookup attribute group %s", name); | 
 |         else | 
 |             fprintf(stderr, "Unable to lookup attribute group %s:%s", name, | 
 |                     nsName); | 
 |     } | 
 | #endif | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaGetGroup: | 
 |  * @schema:  the context of the schema | 
 |  * @name:  the name of the group | 
 |  * @ns:  the target namespace of the group | 
 |  * | 
 |  * Lookup a group in the schema or imported schemas | 
 |  * | 
 |  * Returns the group definition or NULL if not found. | 
 |  */ | 
 | static xmlSchemaModelGroupDefPtr | 
 | xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name, | 
 |                  const xmlChar * nsName) | 
 | { | 
 |     xmlSchemaModelGroupDefPtr ret = NULL; | 
 |  | 
 |     if ((name == NULL) || (schema == NULL)) | 
 |         return (NULL); | 
 |     if (schema != NULL) { | 
 | 	WXS_FIND_GLOBAL_ITEM(groupDecl) | 
 |     } | 
 | exit: | 
 |  | 
 | #ifdef DEBUG | 
 |     if (ret == NULL) { | 
 |         if (nsName == NULL) | 
 |             fprintf(stderr, "Unable to lookup group %s", name); | 
 |         else | 
 |             fprintf(stderr, "Unable to lookup group %s:%s", name, | 
 |                     nsName); | 
 |     } | 
 | #endif | 
 |     return (ret); | 
 | } | 
 |  | 
 | static xmlSchemaNotationPtr | 
 | xmlSchemaGetNotation(xmlSchemaPtr schema, | 
 | 		     const xmlChar *name, | 
 | 		     const xmlChar *nsName) | 
 | { | 
 |     xmlSchemaNotationPtr ret = NULL; | 
 |  | 
 |     if ((name == NULL) || (schema == NULL)) | 
 |         return (NULL); | 
 |     if (schema != NULL) { | 
 | 	WXS_FIND_GLOBAL_ITEM(notaDecl) | 
 |     } | 
 | exit: | 
 |     return (ret); | 
 | } | 
 |  | 
 | static xmlSchemaIDCPtr | 
 | xmlSchemaGetIDC(xmlSchemaPtr schema, | 
 | 		const xmlChar *name, | 
 | 		const xmlChar *nsName) | 
 | { | 
 |     xmlSchemaIDCPtr ret = NULL; | 
 |  | 
 |     if ((name == NULL) || (schema == NULL)) | 
 |         return (NULL); | 
 |     if (schema != NULL) { | 
 | 	WXS_FIND_GLOBAL_ITEM(idcDef) | 
 |     } | 
 | exit: | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaGetNamedComponent: | 
 |  * @schema:  the schema | 
 |  * @name:  the name of the group | 
 |  * @ns:  the target namespace of the group | 
 |  * | 
 |  * Lookup a group in the schema or imported schemas | 
 |  * | 
 |  * Returns the group definition or NULL if not found. | 
 |  */ | 
 | static xmlSchemaBasicItemPtr | 
 | xmlSchemaGetNamedComponent(xmlSchemaPtr schema, | 
 | 			   xmlSchemaTypeType itemType, | 
 | 			   const xmlChar *name, | 
 | 			   const xmlChar *targetNs) | 
 | { | 
 |     switch (itemType) { | 
 | 	case XML_SCHEMA_TYPE_GROUP: | 
 | 	    return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema, | 
 | 		name, targetNs)); | 
 | 	case XML_SCHEMA_TYPE_ELEMENT: | 
 | 	    return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema, | 
 | 		name, targetNs)); | 
 | 	default: | 
 | 	    TODO | 
 | 	    return (NULL); | 
 |     } | 
 | } | 
 |  | 
 | /************************************************************************ | 
 |  * 									* | 
 |  * 			Parsing functions				* | 
 |  * 									* | 
 |  ************************************************************************/ | 
 |  | 
 | #define IS_BLANK_NODE(n)						\ | 
 |     (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1))) | 
 |  | 
 | /** | 
 |  * xmlSchemaIsBlank: | 
 |  * @str:  a string | 
 |  * @len: the length of the string or -1 | 
 |  * | 
 |  * Check if a string is ignorable | 
 |  * | 
 |  * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise | 
 |  */ | 
 | static int | 
 | xmlSchemaIsBlank(xmlChar * str, int len) | 
 | { | 
 |     if (str == NULL) | 
 |         return (1); | 
 |     if (len < 0) { | 
 | 	while (*str != 0) { | 
 | 	    if (!(IS_BLANK_CH(*str))) | 
 | 		return (0); | 
 | 	    str++; | 
 | 	} | 
 |     } else while ((*str != 0) && (len != 0)) { | 
 | 	if (!(IS_BLANK_CH(*str))) | 
 | 	    return (0); | 
 | 	str++; | 
 | 	len--; | 
 |     } | 
 |  | 
 |     return (1); | 
 | } | 
 |  | 
 | #define WXS_COMP_NAME(c, t) ((t) (c))->name | 
 | #define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace | 
 | /* | 
 | * xmlSchemaFindRedefCompInGraph: | 
 | * ATTENTION TODO: This uses pointer comp. for strings. | 
 | */ | 
 | static xmlSchemaBasicItemPtr | 
 | xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket, | 
 | 			      xmlSchemaTypeType type, | 
 | 			      const xmlChar *name, | 
 | 			      const xmlChar *nsName) | 
 | { | 
 |     xmlSchemaBasicItemPtr ret; | 
 |     int i; | 
 |  | 
 |     if ((bucket == NULL) || (name == NULL)) | 
 | 	return(NULL); | 
 |     if ((bucket->globals == NULL) || | 
 | 	(bucket->globals->nbItems == 0)) | 
 | 	goto subschemas; | 
 |     /* | 
 |     * Search in global components. | 
 |     */ | 
 |     for (i = 0; i < bucket->globals->nbItems; i++) { | 
 | 	ret = bucket->globals->items[i]; | 
 | 	if (ret->type == type) { | 
 | 	    switch (type) { | 
 | 		case XML_SCHEMA_TYPE_COMPLEX: | 
 | 		case XML_SCHEMA_TYPE_SIMPLE: | 
 | 		    if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) && | 
 | 			(WXS_COMP_TNS(ret, xmlSchemaTypePtr) == | 
 | 			nsName)) | 
 | 		    { | 
 | 			return(ret); | 
 | 		    } | 
 | 		    break; | 
 | 		case XML_SCHEMA_TYPE_GROUP: | 
 | 		    if ((WXS_COMP_NAME(ret, | 
 | 			    xmlSchemaModelGroupDefPtr) == name) && | 
 | 			(WXS_COMP_TNS(ret, | 
 | 			    xmlSchemaModelGroupDefPtr) == nsName)) | 
 | 		    { | 
 | 			return(ret); | 
 | 		    } | 
 | 		    break; | 
 | 		case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: | 
 | 		    if ((WXS_COMP_NAME(ret, | 
 | 			    xmlSchemaAttributeGroupPtr) == name) && | 
 | 			(WXS_COMP_TNS(ret, | 
 | 			    xmlSchemaAttributeGroupPtr) == nsName)) | 
 | 		    { | 
 | 			return(ret); | 
 | 		    } | 
 | 		    break; | 
 | 		default: | 
 | 		    /* Should not be hit. */ | 
 | 		    return(NULL); | 
 | 	    } | 
 | 	} | 
 |     } | 
 | subschemas: | 
 |     /* | 
 |     * Process imported/included schemas. | 
 |     */ | 
 |     if (bucket->relations != NULL) { | 
 | 	xmlSchemaSchemaRelationPtr rel = bucket->relations; | 
 |  | 
 | 	/* | 
 | 	* TODO: Marking the bucket will not avoid multiple searches | 
 | 	* in the same schema, but avoids at least circularity. | 
 | 	*/ | 
 | 	bucket->flags |= XML_SCHEMA_BUCKET_MARKED; | 
 | 	do { | 
 | 	    if ((rel->bucket != NULL) && | 
 | 		((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) { | 
 | 		ret = xmlSchemaFindRedefCompInGraph(rel->bucket, | 
 | 		    type, name, nsName); | 
 | 		if (ret != NULL) | 
 | 		    return(ret); | 
 | 	    } | 
 | 	    rel = rel->next; | 
 | 	} while (rel != NULL); | 
 | 	 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED; | 
 |     } | 
 |     return(NULL); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaAddNotation: | 
 |  * @ctxt:  a schema parser context | 
 |  * @schema:  the schema being built | 
 |  * @name:  the item name | 
 |  * | 
 |  * Add an XML schema annotation declaration | 
 |  * *WARNING* this interface is highly subject to change | 
 |  * | 
 |  * Returns the new struture or NULL in case of error | 
 |  */ | 
 | static xmlSchemaNotationPtr | 
 | xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | 
 |                      const xmlChar *name, const xmlChar *nsName, | 
 | 		     xmlNodePtr node ATTRIBUTE_UNUSED) | 
 | { | 
 |     xmlSchemaNotationPtr ret = NULL; | 
 |  | 
 |     if ((ctxt == NULL) || (schema == NULL) || (name == NULL)) | 
 |         return (NULL); | 
 |  | 
 |     ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation)); | 
 |     if (ret == NULL) { | 
 |         xmlSchemaPErrMemory(ctxt, "add annotation", NULL); | 
 |         return (NULL); | 
 |     } | 
 |     memset(ret, 0, sizeof(xmlSchemaNotation)); | 
 |     ret->type = XML_SCHEMA_TYPE_NOTATION; | 
 |     ret->name = name; | 
 |     ret->targetNamespace = nsName; | 
 |     /* TODO: do we need the node to be set? | 
 |     * ret->node = node;*/ | 
 |     WXS_ADD_GLOBAL(ctxt, ret); | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaAddAttribute: | 
 |  * @ctxt:  a schema parser context | 
 |  * @schema:  the schema being built | 
 |  * @name:  the item name | 
 |  * @namespace:  the namespace | 
 |  * | 
 |  * Add an XML schema Attrribute declaration | 
 |  * *WARNING* this interface is highly subject to change | 
 |  * | 
 |  * Returns the new struture or NULL in case of error | 
 |  */ | 
 | static xmlSchemaAttributePtr | 
 | xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | 
 |                       const xmlChar * name, const xmlChar * nsName, | 
 | 		      xmlNodePtr node, int topLevel) | 
 | { | 
 |     xmlSchemaAttributePtr ret = NULL; | 
 |  | 
 |     if ((ctxt == NULL) || (schema == NULL)) | 
 |         return (NULL); | 
 |  | 
 |     ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute)); | 
 |     if (ret == NULL) { | 
 |         xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL); | 
 |         return (NULL); | 
 |     } | 
 |     memset(ret, 0, sizeof(xmlSchemaAttribute)); | 
 |     ret->type = XML_SCHEMA_TYPE_ATTRIBUTE; | 
 |     ret->node = node; | 
 |     ret->name = name; | 
 |     ret->targetNamespace = nsName; | 
 |  | 
 |     if (topLevel) | 
 | 	WXS_ADD_GLOBAL(ctxt, ret); | 
 |     else | 
 | 	WXS_ADD_LOCAL(ctxt, ret); | 
 |     WXS_ADD_PENDING(ctxt, ret); | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaAddAttributeUse: | 
 |  * @ctxt:  a schema parser context | 
 |  * @schema:  the schema being built | 
 |  * @name:  the item name | 
 |  * @namespace:  the namespace | 
 |  * | 
 |  * Add an XML schema Attrribute declaration | 
 |  * *WARNING* this interface is highly subject to change | 
 |  * | 
 |  * Returns the new struture or NULL in case of error | 
 |  */ | 
 | static xmlSchemaAttributeUsePtr | 
 | xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt, | 
 | 			 xmlNodePtr node) | 
 | { | 
 |     xmlSchemaAttributeUsePtr ret = NULL; | 
 |  | 
 |     if (pctxt == NULL) | 
 |         return (NULL); | 
 |  | 
 |     ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse)); | 
 |     if (ret == NULL) { | 
 |         xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL); | 
 |         return (NULL); | 
 |     } | 
 |     memset(ret, 0, sizeof(xmlSchemaAttributeUse)); | 
 |     ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE; | 
 |     ret->node = node; | 
 |  | 
 |     WXS_ADD_LOCAL(pctxt, ret); | 
 |     return (ret); | 
 | } | 
 |  | 
 | /* | 
 | * xmlSchemaAddRedef: | 
 | * | 
 | * Adds a redefinition information. This is used at a later stage to: | 
 | * resolve references to the redefined components and to check constraints. | 
 | */ | 
 | static xmlSchemaRedefPtr | 
 | xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt, | 
 | 		  xmlSchemaBucketPtr targetBucket, | 
 | 		  void *item, | 
 | 		  const xmlChar *refName, | 
 | 		  const xmlChar *refTargetNs) | 
 | { | 
 |     xmlSchemaRedefPtr ret; | 
 |  | 
 |     ret = (xmlSchemaRedefPtr) | 
 | 	xmlMalloc(sizeof(xmlSchemaRedef)); | 
 |     if (ret == NULL) { | 
 | 	xmlSchemaPErrMemory(pctxt, | 
 | 	    "allocating redefinition info", NULL); | 
 | 	return (NULL); | 
 |     } | 
 |     memset(ret, 0, sizeof(xmlSchemaRedef)); | 
 |     ret->item = item; | 
 |     ret->targetBucket = targetBucket; | 
 |     ret->refName = refName; | 
 |     ret->refTargetNs = refTargetNs; | 
 |     if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL) | 
 | 	WXS_CONSTRUCTOR(pctxt)->redefs = ret; | 
 |     else | 
 | 	WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret; | 
 |     WXS_CONSTRUCTOR(pctxt)->lastRedef = ret; | 
 |  | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaAddAttributeGroupDefinition: | 
 |  * @ctxt:  a schema parser context | 
 |  * @schema:  the schema being built | 
 |  * @name:  the item name | 
 |  * @nsName:  the target namespace | 
 |  * @node: the corresponding node | 
 |  * | 
 |  * Add an XML schema Attrribute Group definition. | 
 |  * | 
 |  * Returns the new struture or NULL in case of error | 
 |  */ | 
 | static xmlSchemaAttributeGroupPtr | 
 | xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt, | 
 |                            xmlSchemaPtr schema ATTRIBUTE_UNUSED, | 
 | 			   const xmlChar *name, | 
 | 			   const xmlChar *nsName, | 
 | 			   xmlNodePtr node) | 
 | { | 
 |     xmlSchemaAttributeGroupPtr ret = NULL; | 
 |  | 
 |     if ((pctxt == NULL) || (name == NULL)) | 
 |         return (NULL); | 
 |  | 
 |     ret = (xmlSchemaAttributeGroupPtr) | 
 |         xmlMalloc(sizeof(xmlSchemaAttributeGroup)); | 
 |     if (ret == NULL) { | 
 | 	xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL); | 
 | 	return (NULL); | 
 |     } | 
 |     memset(ret, 0, sizeof(xmlSchemaAttributeGroup)); | 
 |     ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP; | 
 |     ret->name = name; | 
 |     ret->targetNamespace = nsName; | 
 |     ret->node = node; | 
 |  | 
 |     /* TODO: Remove the flag. */ | 
 |     ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL; | 
 |     if (pctxt->isRedefine) { | 
 | 	pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined, | 
 | 	    ret, name, nsName); | 
 | 	if (pctxt->redef == NULL) { | 
 | 	    xmlFree(ret); | 
 | 	    return(NULL); | 
 | 	} | 
 | 	pctxt->redefCounter = 0; | 
 |     } | 
 |     WXS_ADD_GLOBAL(pctxt, ret); | 
 |     WXS_ADD_PENDING(pctxt, ret); | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaAddElement: | 
 |  * @ctxt:  a schema parser context | 
 |  * @schema:  the schema being built | 
 |  * @name:  the type name | 
 |  * @namespace:  the type namespace | 
 |  * | 
 |  * Add an XML schema Element declaration | 
 |  * *WARNING* this interface is highly subject to change | 
 |  * | 
 |  * Returns the new struture or NULL in case of error | 
 |  */ | 
 | static xmlSchemaElementPtr | 
 | xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, | 
 |                     const xmlChar * name, const xmlChar * nsName, | 
 | 		    xmlNodePtr node, int topLevel) | 
 | { | 
 |     xmlSchemaElementPtr ret = NULL; | 
 |  | 
 |     if ((ctxt == NULL) || (name == NULL)) | 
 |         return (NULL); | 
 |  | 
 |     ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement)); | 
 |     if (ret == NULL) { | 
 |         xmlSchemaPErrMemory(ctxt, "allocating element", NULL); | 
 |         return (NULL); | 
 |     } | 
 |     memset(ret, 0, sizeof(xmlSchemaElement)); | 
 |     ret->type = XML_SCHEMA_TYPE_ELEMENT; | 
 |     ret->name = name; | 
 |     ret->targetNamespace = nsName; | 
 |     ret->node = node; | 
 |  | 
 |     if (topLevel) | 
 | 	WXS_ADD_GLOBAL(ctxt, ret); | 
 |     else | 
 | 	WXS_ADD_LOCAL(ctxt, ret); | 
 |     WXS_ADD_PENDING(ctxt, ret); | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaAddType: | 
 |  * @ctxt:  a schema parser context | 
 |  * @schema:  the schema being built | 
 |  * @name:  the item name | 
 |  * @namespace:  the namespace | 
 |  * | 
 |  * Add an XML schema item | 
 |  * *WARNING* this interface is highly subject to change | 
 |  * | 
 |  * Returns the new struture or NULL in case of error | 
 |  */ | 
 | static xmlSchemaTypePtr | 
 | xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | 
 | 		 xmlSchemaTypeType type, | 
 |                  const xmlChar * name, const xmlChar * nsName, | 
 | 		 xmlNodePtr node, int topLevel) | 
 | { | 
 |     xmlSchemaTypePtr ret = NULL; | 
 |  | 
 |     if ((ctxt == NULL) || (schema == NULL)) | 
 |         return (NULL); | 
 |  | 
 |     ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType)); | 
 |     if (ret == NULL) { | 
 |         xmlSchemaPErrMemory(ctxt, "allocating type", NULL); | 
 |         return (NULL); | 
 |     } | 
 |     memset(ret, 0, sizeof(xmlSchemaType)); | 
 |     ret->type = type; | 
 |     ret->name = name; | 
 |     ret->targetNamespace = nsName; | 
 |     ret->node = node; | 
 |     if (topLevel) { | 
 | 	if (ctxt->isRedefine) { | 
 | 	    ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined, | 
 | 		ret, name, nsName); | 
 | 	    if (ctxt->redef == NULL) { | 
 | 		xmlFree(ret); | 
 | 		return(NULL); | 
 | 	    } | 
 | 	    ctxt->redefCounter = 0; | 
 | 	} | 
 | 	WXS_ADD_GLOBAL(ctxt, ret); | 
 |     } else | 
 | 	WXS_ADD_LOCAL(ctxt, ret); | 
 |     WXS_ADD_PENDING(ctxt, ret); | 
 |     return (ret); | 
 | } | 
 |  | 
 | static xmlSchemaQNameRefPtr | 
 | xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt, | 
 | 		     xmlSchemaTypeType refType, | 
 | 		     const xmlChar *refName, | 
 | 		     const xmlChar *refNs) | 
 | { | 
 |     xmlSchemaQNameRefPtr ret; | 
 |  | 
 |     ret = (xmlSchemaQNameRefPtr) | 
 | 	xmlMalloc(sizeof(xmlSchemaQNameRef)); | 
 |     if (ret == NULL) { | 
 | 	xmlSchemaPErrMemory(pctxt, | 
 | 	    "allocating QName reference item", NULL); | 
 | 	return (NULL); | 
 |     } | 
 |     ret->node = NULL; | 
 |     ret->type = XML_SCHEMA_EXTRA_QNAMEREF; | 
 |     ret->name = refName; | 
 |     ret->targetNamespace = refNs; | 
 |     ret->item = NULL; | 
 |     ret->itemType = refType; | 
 |     /* | 
 |     * Store the reference item in the schema. | 
 |     */ | 
 |     WXS_ADD_LOCAL(pctxt, ret); | 
 |     return (ret); | 
 | } | 
 |  | 
 | static xmlSchemaAttributeUseProhibPtr | 
 | xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt) | 
 | { | 
 |     xmlSchemaAttributeUseProhibPtr ret; | 
 |  | 
 |     ret = (xmlSchemaAttributeUseProhibPtr) | 
 | 	xmlMalloc(sizeof(xmlSchemaAttributeUseProhib)); | 
 |     if (ret == NULL) { | 
 | 	xmlSchemaPErrMemory(pctxt, | 
 | 	    "allocating attribute use prohibition", NULL); | 
 | 	return (NULL); | 
 |     } | 
 |     memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib)); | 
 |     ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB; | 
 |     WXS_ADD_LOCAL(pctxt, ret); | 
 |     return (ret); | 
 | } | 
 |  | 
 |  | 
 | /** | 
 |  * xmlSchemaAddModelGroup: | 
 |  * @ctxt:  a schema parser context | 
 |  * @schema:  the schema being built | 
 |  * @type: the "compositor" type of the model group | 
 |  * @node: the node in the schema doc | 
 |  * | 
 |  * Adds a schema model group | 
 |  * *WARNING* this interface is highly subject to change | 
 |  * | 
 |  * Returns the new struture or NULL in case of error | 
 |  */ | 
 | static xmlSchemaModelGroupPtr | 
 | xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt, | 
 | 		       xmlSchemaPtr schema, | 
 | 		       xmlSchemaTypeType type, | 
 | 		       xmlNodePtr node) | 
 | { | 
 |     xmlSchemaModelGroupPtr ret = NULL; | 
 |  | 
 |     if ((ctxt == NULL) || (schema == NULL)) | 
 |         return (NULL); | 
 |  | 
 |     ret = (xmlSchemaModelGroupPtr) | 
 | 	xmlMalloc(sizeof(xmlSchemaModelGroup)); | 
 |     if (ret == NULL) { | 
 | 	xmlSchemaPErrMemory(ctxt, "allocating model group component", | 
 | 	    NULL); | 
 | 	return (NULL); | 
 |     } | 
 |     memset(ret, 0, sizeof(xmlSchemaModelGroup)); | 
 |     ret->type = type; | 
 |     ret->node = node; | 
 |     WXS_ADD_LOCAL(ctxt, ret); | 
 |     if ((type == XML_SCHEMA_TYPE_SEQUENCE) || | 
 | 	(type == XML_SCHEMA_TYPE_CHOICE)) | 
 | 	WXS_ADD_PENDING(ctxt, ret); | 
 |     return (ret); | 
 | } | 
 |  | 
 |  | 
 | /** | 
 |  * xmlSchemaAddParticle: | 
 |  * @ctxt:  a schema parser context | 
 |  * @schema:  the schema being built | 
 |  * @node: the corresponding node in the schema doc | 
 |  * @min: the minOccurs | 
 |  * @max: the maxOccurs | 
 |  * | 
 |  * Adds an XML schema particle component. | 
 |  * *WARNING* this interface is highly subject to change | 
 |  * | 
 |  * Returns the new struture or NULL in case of error | 
 |  */ | 
 | static xmlSchemaParticlePtr | 
 | xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, | 
 | 		     xmlNodePtr node, int min, int max) | 
 | { | 
 |     xmlSchemaParticlePtr ret = NULL; | 
 |     if (ctxt == NULL) | 
 |         return (NULL); | 
 |  | 
 | #ifdef DEBUG | 
 |     fprintf(stderr, "Adding particle component\n"); | 
 | #endif | 
 |     ret = (xmlSchemaParticlePtr) | 
 | 	xmlMalloc(sizeof(xmlSchemaParticle)); | 
 |     if (ret == NULL) { | 
 | 	xmlSchemaPErrMemory(ctxt, "allocating particle component", | 
 | 	    NULL); | 
 | 	return (NULL); | 
 |     } | 
 |     ret->type = XML_SCHEMA_TYPE_PARTICLE; | 
 |     ret->annot = NULL; | 
 |     ret->node = node; | 
 |     ret->minOccurs = min; | 
 |     ret->maxOccurs = max; | 
 |     ret->next = NULL; | 
 |     ret->children = NULL; | 
 |  | 
 |     WXS_ADD_LOCAL(ctxt, ret); | 
 |     /* | 
 |     * Note that addition to pending components will be done locally | 
 |     * to the specific parsing function, since the most particles | 
 |     * need not to be fixed up (i.e. the reference to be resolved). | 
 |     * REMOVED: WXS_ADD_PENDING(ctxt, ret); | 
 |     */ | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaAddModelGroupDefinition: | 
 |  * @ctxt:  a schema validation context | 
 |  * @schema:  the schema being built | 
 |  * @name:  the group name | 
 |  * | 
 |  * Add an XML schema Group definition | 
 |  * | 
 |  * Returns the new struture or NULL in case of error | 
 |  */ | 
 | static xmlSchemaModelGroupDefPtr | 
 | xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt, | 
 | 				 xmlSchemaPtr schema, | 
 | 				 const xmlChar *name, | 
 | 				 const xmlChar *nsName, | 
 | 				 xmlNodePtr node) | 
 | { | 
 |     xmlSchemaModelGroupDefPtr ret = NULL; | 
 |  | 
 |     if ((ctxt == NULL) || (schema == NULL) || (name == NULL)) | 
 |         return (NULL); | 
 |  | 
 |     ret = (xmlSchemaModelGroupDefPtr) | 
 | 	xmlMalloc(sizeof(xmlSchemaModelGroupDef)); | 
 |     if (ret == NULL) { | 
 |         xmlSchemaPErrMemory(ctxt, "adding group", NULL); | 
 |         return (NULL); | 
 |     } | 
 |     memset(ret, 0, sizeof(xmlSchemaModelGroupDef)); | 
 |     ret->name = name; | 
 |     ret->type = XML_SCHEMA_TYPE_GROUP; | 
 |     ret->node = node; | 
 |     ret->targetNamespace = nsName; | 
 |  | 
 |     if (ctxt->isRedefine) { | 
 | 	ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined, | 
 | 	    ret, name, nsName); | 
 | 	if (ctxt->redef == NULL) { | 
 | 	    xmlFree(ret); | 
 | 	    return(NULL); | 
 | 	} | 
 | 	ctxt->redefCounter = 0; | 
 |     } | 
 |     WXS_ADD_GLOBAL(ctxt, ret); | 
 |     WXS_ADD_PENDING(ctxt, ret); | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaNewWildcardNs: | 
 |  * @ctxt:  a schema validation context | 
 |  * | 
 |  * Creates a new wildcard namespace constraint. | 
 |  * | 
 |  * Returns the new struture or NULL in case of error | 
 |  */ | 
 | static xmlSchemaWildcardNsPtr | 
 | xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt) | 
 | { | 
 |     xmlSchemaWildcardNsPtr ret; | 
 |  | 
 |     ret = (xmlSchemaWildcardNsPtr) | 
 | 	xmlMalloc(sizeof(xmlSchemaWildcardNs)); | 
 |     if (ret == NULL) { | 
 | 	xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL); | 
 | 	return (NULL); | 
 |     } | 
 |     ret->value = NULL; | 
 |     ret->next = NULL; | 
 |     return (ret); | 
 | } | 
 |  | 
 | static xmlSchemaIDCPtr | 
 | xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | 
 |                   const xmlChar *name, const xmlChar *nsName, | 
 | 		  int category, xmlNodePtr node) | 
 | { | 
 |     xmlSchemaIDCPtr ret = NULL; | 
 |  | 
 |     if ((ctxt == NULL) || (schema == NULL) || (name == NULL)) | 
 |         return (NULL); | 
 |  | 
 |     ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC)); | 
 |     if (ret == NULL) { | 
 |         xmlSchemaPErrMemory(ctxt, | 
 | 	    "allocating an identity-constraint definition", NULL); | 
 |         return (NULL); | 
 |     } | 
 |     memset(ret, 0, sizeof(xmlSchemaIDC)); | 
 |     /* The target namespace of the parent element declaration. */ | 
 |     ret->targetNamespace = nsName; | 
 |     ret->name = name; | 
 |     ret->type = category; | 
 |     ret->node = node; | 
 |  | 
 |     WXS_ADD_GLOBAL(ctxt, ret); | 
 |     /* | 
 |     * Only keyrefs need to be fixup up. | 
 |     */ | 
 |     if (category == XML_SCHEMA_TYPE_IDC_KEYREF) | 
 | 	WXS_ADD_PENDING(ctxt, ret); | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaAddWildcard: | 
 |  * @ctxt:  a schema validation context | 
 |  * @schema: a schema | 
 |  * | 
 |  * Adds a wildcard. | 
 |  * It corresponds to a xsd:anyAttribute and xsd:any. | 
 |  * | 
 |  * Returns the new struture or NULL in case of error | 
 |  */ | 
 | static xmlSchemaWildcardPtr | 
 | xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | 
 | 		     xmlSchemaTypeType type, xmlNodePtr node) | 
 | { | 
 |     xmlSchemaWildcardPtr ret = NULL; | 
 |  | 
 |     if ((ctxt == NULL) || (schema == NULL)) | 
 |         return (NULL); | 
 |  | 
 |     ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard)); | 
 |     if (ret == NULL) { | 
 |         xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL); | 
 |         return (NULL); | 
 |     } | 
 |     memset(ret, 0, sizeof(xmlSchemaWildcard)); | 
 |     ret->type = type; | 
 |     ret->node = node; | 
 |     WXS_ADD_LOCAL(ctxt, ret); | 
 |     return (ret); | 
 | } | 
 |  | 
 | static void | 
 | xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group) | 
 | { | 
 |     if (group == NULL) | 
 | 	return; | 
 |     if (group->members != NULL) | 
 | 	xmlSchemaItemListFree(group->members); | 
 |     xmlFree(group); | 
 | } | 
 |  | 
 | static xmlSchemaSubstGroupPtr | 
 | xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt, | 
 | 		       xmlSchemaElementPtr head) | 
 | { | 
 |     xmlSchemaSubstGroupPtr ret; | 
 |  | 
 |     /* Init subst group hash. */ | 
 |     if (WXS_SUBST_GROUPS(pctxt) == NULL) { | 
 | 	WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict); | 
 | 	if (WXS_SUBST_GROUPS(pctxt) == NULL) | 
 | 	    return(NULL); | 
 |     } | 
 |     /* Create a new substitution group. */ | 
 |     ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup)); | 
 |     if (ret == NULL) { | 
 | 	xmlSchemaPErrMemory(NULL, | 
 | 	    "allocating a substitution group container", NULL); | 
 | 	return(NULL); | 
 |     } | 
 |     memset(ret, 0, sizeof(xmlSchemaSubstGroup)); | 
 |     ret->head = head; | 
 |     /* Create list of members. */ | 
 |     ret->members = xmlSchemaItemListCreate(); | 
 |     if (ret->members == NULL) { | 
 | 	xmlSchemaSubstGroupFree(ret); | 
 | 	return(NULL); | 
 |     } | 
 |     /* Add subst group to hash. */ | 
 |     if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt), | 
 | 	head->name, head->targetNamespace, ret) != 0) { | 
 | 	PERROR_INT("xmlSchemaSubstGroupAdd", | 
 | 	    "failed to add a new substitution container"); | 
 | 	xmlSchemaSubstGroupFree(ret); | 
 | 	return(NULL); | 
 |     } | 
 |     return(ret); | 
 | } | 
 |  | 
 | static xmlSchemaSubstGroupPtr | 
 | xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt, | 
 | 		       xmlSchemaElementPtr head) | 
 | { | 
 |     if (WXS_SUBST_GROUPS(pctxt) == NULL) | 
 | 	return(NULL); | 
 |     return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt), | 
 | 	head->name, head->targetNamespace)); | 
 |  | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaAddElementSubstitutionMember: | 
 |  * @pctxt:  a schema parser context | 
 |  * @head:  the head of the substitution group | 
 |  * @member: the new member of the substitution group | 
 |  * | 
 |  * Allocate a new annotation structure. | 
 |  * | 
 |  * Returns the newly allocated structure or NULL in case or error | 
 |  */ | 
 | static int | 
 | xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt, | 
 | 				      xmlSchemaElementPtr head, | 
 | 				      xmlSchemaElementPtr member) | 
 | { | 
 |     xmlSchemaSubstGroupPtr substGroup = NULL; | 
 |  | 
 |     if ((pctxt == NULL) || (head == NULL) || (member == NULL)) | 
 | 	return (-1); | 
 |  | 
 |     substGroup = xmlSchemaSubstGroupGet(pctxt, head); | 
 |     if (substGroup == NULL) | 
 | 	substGroup = xmlSchemaSubstGroupAdd(pctxt, head); | 
 |     if (substGroup == NULL) | 
 | 	return(-1); | 
 |     if (xmlSchemaItemListAdd(substGroup->members, member) == -1) | 
 | 	return(-1); | 
 |     return(0); | 
 | } | 
 |  | 
 | /************************************************************************ | 
 |  * 									* | 
 |  *		Utilities for parsing					* | 
 |  * 									* | 
 |  ************************************************************************/ | 
 |  | 
 | /** | 
 |  * xmlSchemaPValAttrNodeQNameValue: | 
 |  * @ctxt:  a schema parser context | 
 |  * @schema: the schema context | 
 |  * @ownerDes: the designation of the parent element | 
 |  * @ownerItem: the parent as a schema object | 
 |  * @value:  the QName value | 
 |  * @local: the resulting local part if found, the attribute value otherwise | 
 |  * @uri:  the resulting namespace URI if found | 
 |  * | 
 |  * Extracts the local name and the URI of a QName value and validates it. | 
 |  * This one is intended to be used on attribute values that | 
 |  * should resolve to schema components. | 
 |  * | 
 |  * Returns 0, in case the QName is valid, a positive error code | 
 |  * if not valid and -1 if an internal error occurs. | 
 |  */ | 
 | static int | 
 | xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt, | 
 | 				       xmlSchemaPtr schema, | 
 | 				       xmlSchemaBasicItemPtr ownerItem, | 
 | 				       xmlAttrPtr attr, | 
 | 				       const xmlChar *value, | 
 | 				       const xmlChar **uri, | 
 | 				       const xmlChar **local) | 
 | { | 
 |     const xmlChar *pref; | 
 |     xmlNsPtr ns; | 
 |     int len, ret; | 
 |  | 
 |     *uri = NULL; | 
 |     *local = NULL; | 
 |     ret = xmlValidateQName(value, 1); | 
 |     if (ret > 0) { | 
 | 	xmlSchemaPSimpleTypeErr(ctxt, | 
 | 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | 
 | 	    ownerItem, (xmlNodePtr) attr, | 
 | 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), | 
 | 	    NULL, value, NULL, NULL, NULL); | 
 | 	*local = value; | 
 | 	return (ctxt->err); | 
 |     } else if (ret < 0) | 
 | 	return (-1); | 
 |  | 
 |     if (!strchr((char *) value, ':')) { | 
 | 	ns = xmlSearchNs(attr->doc, attr->parent, NULL); | 
 | 	if (ns) | 
 | 	    *uri = xmlDictLookup(ctxt->dict, ns->href, -1); | 
 | 	else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) { | 
 | 	    /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the | 
 | 	    * parser context. */ | 
 | 	    /* | 
 | 	    * This one takes care of included schemas with no | 
 | 	    * target namespace. | 
 | 	    */ | 
 | 	    *uri = ctxt->targetNamespace; | 
 | 	} | 
 | 	*local = xmlDictLookup(ctxt->dict, value, -1); | 
 | 	return (0); | 
 |     } | 
 |     /* | 
 |     * At this point xmlSplitQName3 has to return a local name. | 
 |     */ | 
 |     *local = xmlSplitQName3(value, &len); | 
 |     *local = xmlDictLookup(ctxt->dict, *local, -1); | 
 |     pref = xmlDictLookup(ctxt->dict, value, len); | 
 |     ns = xmlSearchNs(attr->doc, attr->parent, pref); | 
 |     if (ns == NULL) { | 
 | 	xmlSchemaPSimpleTypeErr(ctxt, | 
 | 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | 
 | 	    ownerItem, (xmlNodePtr) attr, | 
 | 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value, | 
 | 	    "The value '%s' of simple type 'xs:QName' has no " | 
 | 	    "corresponding namespace declaration in scope", value, NULL); | 
 | 	return (ctxt->err); | 
 |     } else { | 
 |         *uri = xmlDictLookup(ctxt->dict, ns->href, -1); | 
 |     } | 
 |     return (0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaPValAttrNodeQName: | 
 |  * @ctxt:  a schema parser context | 
 |  * @schema: the schema context | 
 |  * @ownerDes: the designation of the owner element | 
 |  * @ownerItem: the owner as a schema object | 
 |  * @attr:  the attribute node | 
 |  * @local: the resulting local part if found, the attribute value otherwise | 
 |  * @uri:  the resulting namespace URI if found | 
 |  * | 
 |  * Extracts and validates the QName of an attribute value. | 
 |  * This one is intended to be used on attribute values that | 
 |  * should resolve to schema components. | 
 |  * | 
 |  * Returns 0, in case the QName is valid, a positive error code | 
 |  * if not valid and -1 if an internal error occurs. | 
 |  */ | 
 | static int | 
 | xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt, | 
 | 				       xmlSchemaPtr schema, | 
 | 				       xmlSchemaBasicItemPtr ownerItem, | 
 | 				       xmlAttrPtr attr, | 
 | 				       const xmlChar **uri, | 
 | 				       const xmlChar **local) | 
 | { | 
 |     const xmlChar *value; | 
 |  | 
 |     value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); | 
 |     return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema, | 
 | 	ownerItem, attr, value, uri, local)); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaPValAttrQName: | 
 |  * @ctxt:  a schema parser context | 
 |  * @schema: the schema context | 
 |  * @ownerDes: the designation of the parent element | 
 |  * @ownerItem: the owner as a schema object | 
 |  * @ownerElem:  the parent node of the attribute | 
 |  * @name:  the name of the attribute | 
 |  * @local: the resulting local part if found, the attribute value otherwise | 
 |  * @uri:  the resulting namespace URI if found | 
 |  * | 
 |  * Extracts and validates the QName of an attribute value. | 
 |  * | 
 |  * Returns 0, in case the QName is valid, a positive error code | 
 |  * if not valid and -1 if an internal error occurs. | 
 |  */ | 
 | static int | 
 | xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt, | 
 | 				   xmlSchemaPtr schema, | 
 | 				   xmlSchemaBasicItemPtr ownerItem, | 
 | 				   xmlNodePtr ownerElem, | 
 | 				   const char *name, | 
 | 				   const xmlChar **uri, | 
 | 				   const xmlChar **local) | 
 | { | 
 |     xmlAttrPtr attr; | 
 |  | 
 |     attr = xmlSchemaGetPropNode(ownerElem, name); | 
 |     if (attr == NULL) { | 
 | 	*local = NULL; | 
 | 	*uri = NULL; | 
 | 	return (0); | 
 |     } | 
 |     return (xmlSchemaPValAttrNodeQName(ctxt, schema, | 
 | 	ownerItem, attr, uri, local)); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaPValAttrID: | 
 |  * @ctxt:  a schema parser context | 
 |  * @schema: the schema context | 
 |  * @ownerDes: the designation of the parent element | 
 |  * @ownerItem: the owner as a schema object | 
 |  * @ownerElem:  the parent node of the attribute | 
 |  * @name:  the name of the attribute | 
 |  * | 
 |  * Extracts and validates the ID of an attribute value. | 
 |  * | 
 |  * Returns 0, in case the ID is valid, a positive error code | 
 |  * if not valid and -1 if an internal error occurs. | 
 |  */ | 
 | static int | 
 | xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr) | 
 | { | 
 |     int ret; | 
 |     const xmlChar *value; | 
 |  | 
 |     if (attr == NULL) | 
 | 	return(0); | 
 |     value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr); | 
 |     ret = xmlValidateNCName(value, 1); | 
 |     if (ret == 0) { | 
 | 	/* | 
 | 	* NOTE: the IDness might have already be declared in the DTD | 
 | 	*/ | 
 | 	if (attr->atype != XML_ATTRIBUTE_ID) { | 
 | 	    xmlIDPtr res; | 
 | 	    xmlChar *strip; | 
 |  | 
 | 	    /* | 
 | 	    * TODO: Use xmlSchemaStrip here; it's not exported at this | 
 | 	    * moment. | 
 | 	    */ | 
 | 	    strip = xmlSchemaCollapseString(value); | 
 | 	    if (strip != NULL) { | 
 | 		xmlFree((xmlChar *) value); | 
 | 		value = strip; | 
 | 	    } | 
 |     	    res = xmlAddID(NULL, attr->doc, value, attr); | 
 | 	    if (res == NULL) { | 
 | 		ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE; | 
 | 		xmlSchemaPSimpleTypeErr(ctxt, | 
 | 		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | 
 | 		    NULL, (xmlNodePtr) attr, | 
 | 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_ID), | 
 | 		    NULL, NULL, "Duplicate value '%s' of simple " | 
 | 		    "type 'xs:ID'", value, NULL); | 
 | 	    } else | 
 | 		attr->atype = XML_ATTRIBUTE_ID; | 
 | 	} | 
 |     } else if (ret > 0) { | 
 | 	ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE; | 
 | 	xmlSchemaPSimpleTypeErr(ctxt, | 
 | 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | 
 | 	    NULL, (xmlNodePtr) attr, | 
 | 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ID), | 
 | 	    NULL, NULL, "The value '%s' of simple type 'xs:ID' is " | 
 | 	    "not a valid 'xs:NCName'", | 
 | 	    value, NULL); | 
 |     } | 
 |     if (value != NULL) | 
 | 	xmlFree((xmlChar *)value); | 
 |  | 
 |     return (ret); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt, | 
 | 		    xmlNodePtr ownerElem, | 
 | 		    const xmlChar *name) | 
 | { | 
 |     xmlAttrPtr attr; | 
 |  | 
 |     attr = xmlSchemaGetPropNode(ownerElem, (const char *) name); | 
 |     if (attr == NULL) | 
 | 	return(0); | 
 |     return(xmlSchemaPValAttrNodeID(ctxt, attr)); | 
 |  | 
 | } | 
 |  | 
 | /** | 
 |  * xmlGetMaxOccurs: | 
 |  * @ctxt:  a schema validation context | 
 |  * @node:  a subtree containing XML Schema informations | 
 |  * | 
 |  * Get the maxOccurs property | 
 |  * | 
 |  * Returns the default if not found, or the value | 
 |  */ | 
 | static int | 
 | xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, | 
 | 		int min, int max, int def, const char *expected) | 
 | { | 
 |     const xmlChar *val, *cur; | 
 |     int ret = 0; | 
 |     xmlAttrPtr attr; | 
 |  | 
 |     attr = xmlSchemaGetPropNode(node, "maxOccurs"); | 
 |     if (attr == NULL) | 
 | 	return (def); | 
 |     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); | 
 |  | 
 |     if (xmlStrEqual(val, (const xmlChar *) "unbounded")) { | 
 | 	if (max != UNBOUNDED) { | 
 | 	    xmlSchemaPSimpleTypeErr(ctxt, | 
 | 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | 
 | 		/* XML_SCHEMAP_INVALID_MINOCCURS, */ | 
 | 		NULL, (xmlNodePtr) attr, NULL, expected, | 
 | 		val, NULL, NULL, NULL); | 
 | 	    return (def); | 
 | 	} else | 
 | 	    return (UNBOUNDED);  /* encoding it with -1 might be another option */ | 
 |     } | 
 |  | 
 |     cur = val; | 
 |     while (IS_BLANK_CH(*cur)) | 
 |         cur++; | 
 |     if (*cur == 0) { | 
 |         xmlSchemaPSimpleTypeErr(ctxt, | 
 | 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | 
 | 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */ | 
 | 	    NULL, (xmlNodePtr) attr, NULL, expected, | 
 | 	    val, NULL, NULL, NULL); | 
 | 	return (def); | 
 |     } | 
 |     while ((*cur >= '0') && (*cur <= '9')) { | 
 |         ret = ret * 10 + (*cur - '0'); | 
 |         cur++; | 
 |     } | 
 |     while (IS_BLANK_CH(*cur)) | 
 |         cur++; | 
 |     /* | 
 |     * TODO: Restrict the maximal value to Integer. | 
 |     */ | 
 |     if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) { | 
 | 	xmlSchemaPSimpleTypeErr(ctxt, | 
 | 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | 
 | 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */ | 
 | 	    NULL, (xmlNodePtr) attr, NULL, expected, | 
 | 	    val, NULL, NULL, NULL); | 
 |         return (def); | 
 |     } | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlGetMinOccurs: | 
 |  * @ctxt:  a schema validation context | 
 |  * @node:  a subtree containing XML Schema informations | 
 |  * | 
 |  * Get the minOccurs property | 
 |  * | 
 |  * Returns the default if not found, or the value | 
 |  */ | 
 | static int | 
 | xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, | 
 | 		int min, int max, int def, const char *expected) | 
 | { | 
 |     const xmlChar *val, *cur; | 
 |     int ret = 0; | 
 |     xmlAttrPtr attr; | 
 |  | 
 |     attr = xmlSchemaGetPropNode(node, "minOccurs"); | 
 |     if (attr == NULL) | 
 | 	return (def); | 
 |     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); | 
 |     cur = val; | 
 |     while (IS_BLANK_CH(*cur)) | 
 |         cur++; | 
 |     if (*cur == 0) { | 
 |         xmlSchemaPSimpleTypeErr(ctxt, | 
 | 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | 
 | 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */ | 
 | 	    NULL, (xmlNodePtr) attr, NULL, expected, | 
 | 	    val, NULL, NULL, NULL); | 
 |         return (def); | 
 |     } | 
 |     while ((*cur >= '0') && (*cur <= '9')) { | 
 |         ret = ret * 10 + (*cur - '0'); | 
 |         cur++; | 
 |     } | 
 |     while (IS_BLANK_CH(*cur)) | 
 |         cur++; | 
 |     /* | 
 |     * TODO: Restrict the maximal value to Integer. | 
 |     */ | 
 |     if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) { | 
 | 	xmlSchemaPSimpleTypeErr(ctxt, | 
 | 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | 
 | 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */ | 
 | 	    NULL, (xmlNodePtr) attr, NULL, expected, | 
 | 	    val, NULL, NULL, NULL); | 
 |         return (def); | 
 |     } | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaPGetBoolNodeValue: | 
 |  * @ctxt:  a schema validation context | 
 |  * @ownerDes:  owner designation | 
 |  * @ownerItem:  the owner as a schema item | 
 |  * @node: the node holding the value | 
 |  * | 
 |  * Converts a boolean string value into 1 or 0. | 
 |  * | 
 |  * Returns 0 or 1. | 
 |  */ | 
 | static int | 
 | xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt, | 
 | 			   xmlSchemaBasicItemPtr ownerItem, | 
 | 			   xmlNodePtr node) | 
 | { | 
 |     xmlChar *value = NULL; | 
 |     int res = 0; | 
 |  | 
 |     value = xmlNodeGetContent(node); | 
 |     /* | 
 |     * 3.2.2.1 Lexical representation | 
 |     * An instance of a datatype that is defined as �boolean� | 
 |     * can have the following legal literals {true, false, 1, 0}. | 
 |     */ | 
 |     if (xmlStrEqual(BAD_CAST value, BAD_CAST "true")) | 
 |         res = 1; | 
 |     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false")) | 
 |         res = 0; | 
 |     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1")) | 
 | 	res = 1; | 
 |     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0")) | 
 |         res = 0; | 
 |     else { | 
 |         xmlSchemaPSimpleTypeErr(ctxt, | 
 | 	    XML_SCHEMAP_INVALID_BOOLEAN, | 
 | 	    ownerItem, node, | 
 | 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN), | 
 | 	    NULL, BAD_CAST value, | 
 | 	    NULL, NULL, NULL); | 
 |     } | 
 |     if (value != NULL) | 
 | 	xmlFree(value); | 
 |     return (res); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlGetBooleanProp: | 
 |  * @ctxt:  a schema validation context | 
 |  * @node:  a subtree containing XML Schema informations | 
 |  * @name:  the attribute name | 
 |  * @def:  the default value | 
 |  * | 
 |  * Evaluate if a boolean property is set | 
 |  * | 
 |  * Returns the default if not found, 0 if found to be false, | 
 |  * 1 if found to be true | 
 |  */ | 
 | static int | 
 | xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt, | 
 | 		  xmlNodePtr node, | 
 |                   const char *name, int def) | 
 | { | 
 |     const xmlChar *val; | 
 |  | 
 |     val = xmlSchemaGetProp(ctxt, node, name); | 
 |     if (val == NULL) | 
 |         return (def); | 
 |     /* | 
 |     * 3.2.2.1 Lexical representation | 
 |     * An instance of a datatype that is defined as �boolean� | 
 |     * can have the following legal literals {true, false, 1, 0}. | 
 |     */ | 
 |     if (xmlStrEqual(val, BAD_CAST "true")) | 
 |         def = 1; | 
 |     else if (xmlStrEqual(val, BAD_CAST "false")) | 
 |         def = 0; | 
 |     else if (xmlStrEqual(val, BAD_CAST "1")) | 
 | 	def = 1; | 
 |     else if (xmlStrEqual(val, BAD_CAST "0")) | 
 |         def = 0; | 
 |     else { | 
 |         xmlSchemaPSimpleTypeErr(ctxt, | 
 | 	    XML_SCHEMAP_INVALID_BOOLEAN, | 
 | 	    NULL, | 
 | 	    (xmlNodePtr) xmlSchemaGetPropNode(node, name), | 
 | 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN), | 
 | 	    NULL, val, NULL, NULL, NULL); | 
 |     } | 
 |     return (def); | 
 | } | 
 |  | 
 | /************************************************************************ | 
 |  * 									* | 
 |  *		Shema extraction from an Infoset			* | 
 |  * 									* | 
 |  ************************************************************************/ | 
 | static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr | 
 |                                                  ctxt, xmlSchemaPtr schema, | 
 |                                                  xmlNodePtr node, | 
 | 						 int topLevel); | 
 | static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr | 
 |                                                   ctxt, | 
 |                                                   xmlSchemaPtr schema, | 
 |                                                   xmlNodePtr node, | 
 | 						  int topLevel); | 
 | static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr | 
 |                                                   ctxt, | 
 |                                                   xmlSchemaPtr schema, | 
 |                                                   xmlNodePtr node, | 
 | 						  xmlSchemaTypeType parentType); | 
 | static xmlSchemaBasicItemPtr | 
 | xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt, | 
 | 			     xmlSchemaPtr schema, | 
 | 			     xmlNodePtr node, | 
 | 			     xmlSchemaItemListPtr uses, | 
 | 			     int parentType); | 
 | static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, | 
 |                                            xmlSchemaPtr schema, | 
 |                                            xmlNodePtr node); | 
 | static xmlSchemaWildcardPtr | 
 | xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt, | 
 |                            xmlSchemaPtr schema, xmlNodePtr node); | 
 |  | 
 | /** | 
 |  * xmlSchemaPValAttrNodeValue: | 
 |  * | 
 |  * @ctxt:  a schema parser context | 
 |  * @ownerDes: the designation of the parent element | 
 |  * @ownerItem: the schema object owner if existent | 
 |  * @attr:  the schema attribute node being validated | 
 |  * @value: the value | 
 |  * @type: the built-in type to be validated against | 
 |  * | 
 |  * Validates a value against the given built-in type. | 
 |  * This one is intended to be used internally for validation | 
 |  * of schema attribute values during parsing of the schema. | 
 |  * | 
 |  * Returns 0 if the value is valid, a positive error code | 
 |  * number otherwise and -1 in case of an internal or API error. | 
 |  */ | 
 | static int | 
 | xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt, | 
 | 			   xmlSchemaBasicItemPtr ownerItem, | 
 | 			   xmlAttrPtr attr, | 
 | 			   const xmlChar *value, | 
 | 			   xmlSchemaTypePtr type) | 
 | { | 
 |  | 
 |     int ret = 0; | 
 |  | 
 |     /* | 
 |     * NOTE: Should we move this to xmlschematypes.c? Hmm, but this | 
 |     * one is really meant to be used internally, so better not. | 
 |     */ | 
 |     if ((pctxt == NULL) || (type == NULL) || (attr == NULL)) | 
 | 	return (-1); | 
 |     if (type->type != XML_SCHEMA_TYPE_BASIC) { | 
 | 	PERROR_INT("xmlSchemaPValAttrNodeValue", | 
 | 	    "the given type is not a built-in type"); | 
 | 	return (-1); | 
 |     } | 
 |     switch (type->builtInType) { | 
 | 	case XML_SCHEMAS_NCNAME: | 
 | 	case XML_SCHEMAS_QNAME: | 
 | 	case XML_SCHEMAS_ANYURI: | 
 | 	case XML_SCHEMAS_TOKEN: | 
 | 	case XML_SCHEMAS_LANGUAGE: | 
 | 	    ret = xmlSchemaValPredefTypeNode(type, value, NULL, | 
 | 		(xmlNodePtr) attr); | 
 | 	    break; | 
 | 	default: { | 
 | 	    PERROR_INT("xmlSchemaPValAttrNodeValue", | 
 | 		"validation using the given type is not supported while " | 
 | 		"parsing a schema"); | 
 | 	    return (-1); | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * TODO: Should we use the S4S error codes instead? | 
 |     */ | 
 |     if (ret < 0) { | 
 | 	PERROR_INT("xmlSchemaPValAttrNodeValue", | 
 | 	    "failed to validate a schema attribute value"); | 
 | 	return (-1); | 
 |     } else if (ret > 0) { | 
 | 	if (WXS_IS_LIST(type)) | 
 | 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2; | 
 | 	else | 
 | 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1; | 
 | 	xmlSchemaPSimpleTypeErr(pctxt, | 
 | 	    ret, ownerItem, (xmlNodePtr) attr, | 
 | 	    type, NULL, value, NULL, NULL, NULL); | 
 |     } | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaPValAttrNode: | 
 |  * | 
 |  * @ctxt:  a schema parser context | 
 |  * @ownerDes: the designation of the parent element | 
 |  * @ownerItem: the schema object owner if existent | 
 |  * @attr:  the schema attribute node being validated | 
 |  * @type: the built-in type to be validated against | 
 |  * @value: the resulting value if any | 
 |  * | 
 |  * Extracts and validates a value against the given built-in type. | 
 |  * This one is intended to be used internally for validation | 
 |  * of schema attribute values during parsing of the schema. | 
 |  * | 
 |  * Returns 0 if the value is valid, a positive error code | 
 |  * number otherwise and -1 in case of an internal or API error. | 
 |  */ | 
 | static int | 
 | xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt, | 
 | 			   xmlSchemaBasicItemPtr ownerItem, | 
 | 			   xmlAttrPtr attr, | 
 | 			   xmlSchemaTypePtr type, | 
 | 			   const xmlChar **value) | 
 | { | 
 |     const xmlChar *val; | 
 |  | 
 |     if ((ctxt == NULL) || (type == NULL) || (attr == NULL)) | 
 | 	return (-1); | 
 |  | 
 |     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); | 
 |     if (value != NULL) | 
 | 	*value = val; | 
 |  | 
 |     return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr, | 
 | 	val, type)); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaPValAttr: | 
 |  * | 
 |  * @ctxt:  a schema parser context | 
 |  * @node: the element node of the attribute | 
 |  * @ownerDes: the designation of the parent element | 
 |  * @ownerItem: the schema object owner if existent | 
 |  * @ownerElem: the owner element node | 
 |  * @name:  the name of the schema attribute node | 
 |  * @type: the built-in type to be validated against | 
 |  * @value: the resulting value if any | 
 |  * | 
 |  * Extracts and validates a value against the given built-in type. | 
 |  * This one is intended to be used internally for validation | 
 |  * of schema attribute values during parsing of the schema. | 
 |  * | 
 |  * Returns 0 if the value is valid, a positive error code | 
 |  * number otherwise and -1 in case of an internal or API error. | 
 |  */ | 
 | static int | 
 | xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt, | 
 | 		       xmlSchemaBasicItemPtr ownerItem, | 
 | 		       xmlNodePtr ownerElem, | 
 | 		       const char *name, | 
 | 		       xmlSchemaTypePtr type, | 
 | 		       const xmlChar **value) | 
 | { | 
 |     xmlAttrPtr attr; | 
 |  | 
 |     if ((ctxt == NULL) || (type == NULL)) { | 
 | 	if (value != NULL) | 
 | 	    *value = NULL; | 
 | 	return (-1); | 
 |     } | 
 |     if (type->type != XML_SCHEMA_TYPE_BASIC) { | 
 | 	if (value != NULL) | 
 | 	    *value = NULL; | 
 | 	xmlSchemaPErr(ctxt, ownerElem, | 
 | 	    XML_SCHEMAP_INTERNAL, | 
 | 	    "Internal error: xmlSchemaPValAttr, the given " | 
 | 	    "type '%s' is not a built-in type.\n", | 
 | 	    type->name, NULL); | 
 | 	return (-1); | 
 |     } | 
 |     attr = xmlSchemaGetPropNode(ownerElem, name); | 
 |     if (attr == NULL) { | 
 | 	if (value != NULL) | 
 | 	    *value = NULL; | 
 | 	return (0); | 
 |     } | 
 |     return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr, | 
 | 	type, value)); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt, | 
 | 		  xmlSchemaPtr schema ATTRIBUTE_UNUSED, | 
 | 		  xmlNodePtr node, | 
 | 		  xmlAttrPtr attr, | 
 | 		  const xmlChar *namespaceName) | 
 | { | 
 |     /* TODO: Pointer comparison instead? */ | 
 |     if (xmlStrEqual(pctxt->targetNamespace, namespaceName)) | 
 | 	return (0); | 
 |     if (xmlStrEqual(xmlSchemaNs, namespaceName)) | 
 | 	return (0); | 
 |     /* | 
 |     * Check if the referenced namespace was <import>ed. | 
 |     */ | 
 |     if (WXS_BUCKET(pctxt)->relations != NULL) { | 
 | 	xmlSchemaSchemaRelationPtr rel; | 
 |  | 
 | 	rel = WXS_BUCKET(pctxt)->relations; | 
 | 	do { | 
 | 	    if (WXS_IS_BUCKET_IMPMAIN(rel->type) && | 
 | 		xmlStrEqual(namespaceName, rel->importNamespace)) | 
 | 		return (0); | 
 | 	    rel = rel->next; | 
 | 	} while (rel != NULL); | 
 |     } | 
 |     /* | 
 |     * No matching <import>ed namespace found. | 
 |     */ | 
 |     { | 
 | 	xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node; | 
 |  | 
 | 	if (namespaceName == NULL) | 
 | 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, | 
 | 		XML_SCHEMAP_SRC_RESOLVE, n, NULL, | 
 | 		"References from this schema to components in no " | 
 | 		"namespace are not allowed, since not indicated by an " | 
 | 		"import statement", NULL, NULL); | 
 | 	else | 
 | 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, | 
 | 		XML_SCHEMAP_SRC_RESOLVE, n, NULL, | 
 | 		"References from this schema to components in the " | 
 | 		"namespace '%s' are not allowed, since not indicated by an " | 
 | 		"import statement", namespaceName, NULL); | 
 |     } | 
 |     return (XML_SCHEMAP_SRC_RESOLVE); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaParseLocalAttributes: | 
 |  * @ctxt:  a schema validation context | 
 |  * @schema:  the schema being built | 
 |  * @node:  a subtree containing XML Schema informations | 
 |  * @type:  the hosting type where the attributes will be anchored | 
 |  * | 
 |  * Parses attribute uses and attribute declarations and | 
 |  * attribute group references. | 
 |  */ | 
 | static int | 
 | xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | 
 |                         xmlNodePtr *child, xmlSchemaItemListPtr *list, | 
 | 			int parentType, int *hasRefs) | 
 | { | 
 |     void *item; | 
 |  | 
 |     while ((IS_SCHEMA((*child), "attribute")) || | 
 |            (IS_SCHEMA((*child), "attributeGroup"))) { | 
 |         if (IS_SCHEMA((*child), "attribute")) { | 
 | 	    item = xmlSchemaParseLocalAttribute(ctxt, schema, *child, | 
 | 		*list, parentType); | 
 |         } else { | 
 |             item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child); | 
 | 	    if ((item != NULL) && (hasRefs != NULL)) | 
 | 		*hasRefs = 1; | 
 |         } | 
 | 	if (item != NULL) { | 
 | 	    if (*list == NULL) { | 
 | 		/* TODO: Customize grow factor. */ | 
 | 		*list = xmlSchemaItemListCreate(); | 
 | 		if (*list == NULL) | 
 | 		    return(-1); | 
 | 	    } | 
 | 	    if (xmlSchemaItemListAddSize(*list, 2, item) == -1) | 
 | 		return(-1); | 
 | 	} | 
 |         *child = (*child)->next; | 
 |     } | 
 |     return (0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaParseAnnotation: | 
 |  * @ctxt:  a schema validation context | 
 |  * @schema:  the schema being built | 
 |  * @node:  a subtree containing XML Schema informations | 
 |  * | 
 |  * parse a XML schema Attrribute declaration | 
 |  * *WARNING* this interface is highly subject to change | 
 |  * | 
 |  * Returns -1 in case of error, 0 if the declaration is improper and | 
 |  *         1 in case of success. | 
 |  */ | 
 | static xmlSchemaAnnotPtr | 
 | xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed) | 
 | { | 
 |     xmlSchemaAnnotPtr ret; | 
 |     xmlNodePtr child = NULL; | 
 |     xmlAttrPtr attr; | 
 |     int barked = 0; | 
 |  | 
 |     /* | 
 |     * INFO: S4S completed. | 
 |     */ | 
 |     /* | 
 |     * id = ID | 
 |     * {any attributes with non-schema namespace . . .}> | 
 |     * Content: (appinfo | documentation)* | 
 |     */ | 
 |     if ((ctxt == NULL) || (node == NULL)) | 
 |         return (NULL); | 
 |     if (needed) | 
 | 	ret = xmlSchemaNewAnnot(ctxt, node); | 
 |     else | 
 | 	ret = NULL; | 
 |     attr = node->properties; | 
 |     while (attr != NULL) { | 
 | 	if (((attr->ns == NULL) && | 
 | 	    (!xmlStrEqual(attr->name, BAD_CAST "id"))) || | 
 | 	    ((attr->ns != NULL) && | 
 | 	    xmlStrEqual(attr->ns->href, xmlSchemaNs))) { | 
 |  | 
 | 	    xmlSchemaPIllegalAttrErr(ctxt, | 
 | 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	} | 
 | 	attr = attr->next; | 
 |     } | 
 |     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | 
 |     /* | 
 |     * And now for the children... | 
 |     */ | 
 |     child = node->children; | 
 |     while (child != NULL) { | 
 | 	if (IS_SCHEMA(child, "appinfo")) { | 
 | 	    /* TODO: make available the content of "appinfo". */ | 
 | 	    /* | 
 | 	    * source = anyURI | 
 | 	    * {any attributes with non-schema namespace . . .}> | 
 | 	    * Content: ({any})* | 
 | 	    */ | 
 | 	    attr = child->properties; | 
 | 	    while (attr != NULL) { | 
 | 		if (((attr->ns == NULL) && | 
 | 		     (!xmlStrEqual(attr->name, BAD_CAST "source"))) || | 
 | 		     ((attr->ns != NULL) && | 
 | 		      xmlStrEqual(attr->ns->href, xmlSchemaNs))) { | 
 |  | 
 | 		    xmlSchemaPIllegalAttrErr(ctxt, | 
 | 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 		} | 
 | 		attr = attr->next; | 
 | 	    } | 
 | 	    xmlSchemaPValAttr(ctxt, NULL, child, "source", | 
 | 		xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL); | 
 | 	    child = child->next; | 
 | 	} else if (IS_SCHEMA(child, "documentation")) { | 
 | 	    /* TODO: make available the content of "documentation". */ | 
 | 	    /* | 
 | 	    * source = anyURI | 
 | 	    * {any attributes with non-schema namespace . . .}> | 
 | 	    * Content: ({any})* | 
 | 	    */ | 
 | 	    attr = child->properties; | 
 | 	    while (attr != NULL) { | 
 | 		if (attr->ns == NULL) { | 
 | 		    if (!xmlStrEqual(attr->name, BAD_CAST "source")) { | 
 | 			xmlSchemaPIllegalAttrErr(ctxt, | 
 | 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 		    } | 
 | 		} else { | 
 | 		    if (xmlStrEqual(attr->ns->href, xmlSchemaNs) || | 
 | 			(xmlStrEqual(attr->name, BAD_CAST "lang") && | 
 | 			(!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) { | 
 |  | 
 | 			xmlSchemaPIllegalAttrErr(ctxt, | 
 | 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 		    } | 
 | 		} | 
 | 		attr = attr->next; | 
 | 	    } | 
 | 	    /* | 
 | 	    * Attribute "xml:lang". | 
 | 	    */ | 
 | 	    attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang"); | 
 | 	    if (attr != NULL) | 
 | 		xmlSchemaPValAttrNode(ctxt, NULL, attr, | 
 | 		xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL); | 
 | 	    child = child->next; | 
 | 	} else { | 
 | 	    if (!barked) | 
 | 		xmlSchemaPContentErr(ctxt, | 
 | 		    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | 
 | 		    NULL, node, child, NULL, "(appinfo | documentation)*"); | 
 | 	    barked = 1; | 
 | 	    child = child->next; | 
 | 	} | 
 |     } | 
 |  | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaParseFacet: | 
 |  * @ctxt:  a schema validation context | 
 |  * @schema:  the schema being built | 
 |  * @node:  a subtree containing XML Schema informations | 
 |  * | 
 |  * parse a XML schema Facet declaration | 
 |  * *WARNING* this interface is highly subject to change | 
 |  * | 
 |  * Returns the new type structure or NULL in case of error | 
 |  */ | 
 | static xmlSchemaFacetPtr | 
 | xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | 
 |                     xmlNodePtr node) | 
 | { | 
 |     xmlSchemaFacetPtr facet; | 
 |     xmlNodePtr child = NULL; | 
 |     const xmlChar *value; | 
 |  | 
 |     if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) | 
 |         return (NULL); | 
 |  | 
 |     facet = xmlSchemaNewFacet(); | 
 |     if (facet == NULL) { | 
 |         xmlSchemaPErrMemory(ctxt, "allocating facet", node); | 
 |         return (NULL); | 
 |     } | 
 |     facet->node = node; | 
 |     value = xmlSchemaGetProp(ctxt, node, "value"); | 
 |     if (value == NULL) { | 
 |         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE, | 
 |                        "Facet %s has no value\n", node->name, NULL); | 
 |         xmlSchemaFreeFacet(facet); | 
 |         return (NULL); | 
 |     } | 
 |     if (IS_SCHEMA(node, "minInclusive")) { | 
 |         facet->type = XML_SCHEMA_FACET_MININCLUSIVE; | 
 |     } else if (IS_SCHEMA(node, "minExclusive")) { | 
 |         facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE; | 
 |     } else if (IS_SCHEMA(node, "maxInclusive")) { | 
 |         facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE; | 
 |     } else if (IS_SCHEMA(node, "maxExclusive")) { | 
 |         facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE; | 
 |     } else if (IS_SCHEMA(node, "totalDigits")) { | 
 |         facet->type = XML_SCHEMA_FACET_TOTALDIGITS; | 
 |     } else if (IS_SCHEMA(node, "fractionDigits")) { | 
 |         facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS; | 
 |     } else if (IS_SCHEMA(node, "pattern")) { | 
 |         facet->type = XML_SCHEMA_FACET_PATTERN; | 
 |     } else if (IS_SCHEMA(node, "enumeration")) { | 
 |         facet->type = XML_SCHEMA_FACET_ENUMERATION; | 
 |     } else if (IS_SCHEMA(node, "whiteSpace")) { | 
 |         facet->type = XML_SCHEMA_FACET_WHITESPACE; | 
 |     } else if (IS_SCHEMA(node, "length")) { | 
 |         facet->type = XML_SCHEMA_FACET_LENGTH; | 
 |     } else if (IS_SCHEMA(node, "maxLength")) { | 
 |         facet->type = XML_SCHEMA_FACET_MAXLENGTH; | 
 |     } else if (IS_SCHEMA(node, "minLength")) { | 
 |         facet->type = XML_SCHEMA_FACET_MINLENGTH; | 
 |     } else { | 
 |         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE, | 
 |                        "Unknown facet type %s\n", node->name, NULL); | 
 |         xmlSchemaFreeFacet(facet); | 
 |         return (NULL); | 
 |     } | 
 |     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | 
 |     facet->value = value; | 
 |     if ((facet->type != XML_SCHEMA_FACET_PATTERN) && | 
 | 	(facet->type != XML_SCHEMA_FACET_ENUMERATION)) { | 
 | 	const xmlChar *fixed; | 
 |  | 
 | 	fixed = xmlSchemaGetProp(ctxt, node, "fixed"); | 
 | 	if (fixed != NULL) { | 
 | 	    if (xmlStrEqual(fixed, BAD_CAST "true")) | 
 | 		facet->fixed = 1; | 
 | 	} | 
 |     } | 
 |     child = node->children; | 
 |  | 
 |     if (IS_SCHEMA(child, "annotation")) { | 
 |         facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1); | 
 |         child = child->next; | 
 |     } | 
 |     if (child != NULL) { | 
 |         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD, | 
 |                        "Facet %s has unexpected child content\n", | 
 |                        node->name, NULL); | 
 |     } | 
 |     return (facet); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaParseWildcardNs: | 
 |  * @ctxt:  a schema parser context | 
 |  * @wildc:  the wildcard, already created | 
 |  * @node:  a subtree containing XML Schema informations | 
 |  * | 
 |  * Parses the attribute "processContents" and "namespace" | 
 |  * of a xsd:anyAttribute and xsd:any. | 
 |  * *WARNING* this interface is highly subject to change | 
 |  * | 
 |  * Returns 0 if everything goes fine, a positive error code | 
 |  * if something is not valid and -1 if an internal error occurs. | 
 |  */ | 
 | static int | 
 | xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt, | 
 | 			 xmlSchemaPtr schema ATTRIBUTE_UNUSED, | 
 | 			 xmlSchemaWildcardPtr wildc, | 
 | 			 xmlNodePtr node) | 
 | { | 
 |     const xmlChar *pc, *ns, *dictnsItem; | 
 |     int ret = 0; | 
 |     xmlChar *nsItem; | 
 |     xmlSchemaWildcardNsPtr tmp, lastNs = NULL; | 
 |     xmlAttrPtr attr; | 
 |  | 
 |     pc = xmlSchemaGetProp(ctxt, node, "processContents"); | 
 |     if ((pc == NULL) | 
 |         || (xmlStrEqual(pc, (const xmlChar *) "strict"))) { | 
 |         wildc->processContents = XML_SCHEMAS_ANY_STRICT; | 
 |     } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) { | 
 |         wildc->processContents = XML_SCHEMAS_ANY_SKIP; | 
 |     } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) { | 
 |         wildc->processContents = XML_SCHEMAS_ANY_LAX; | 
 |     } else { | 
 |         xmlSchemaPSimpleTypeErr(ctxt, | 
 | 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | 
 | 	    NULL, node, | 
 | 	    NULL, "(strict | skip | lax)", pc, | 
 | 	    NULL, NULL, NULL); | 
 |         wildc->processContents = XML_SCHEMAS_ANY_STRICT; | 
 | 	ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE; | 
 |     } | 
 |     /* | 
 |      * Build the namespace constraints. | 
 |      */ | 
 |     attr = xmlSchemaGetPropNode(node, "namespace"); | 
 |     ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); | 
 |     if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any"))) | 
 | 	wildc->any = 1; | 
 |     else if (xmlStrEqual(ns, BAD_CAST "##other")) { | 
 | 	wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt); | 
 | 	if (wildc->negNsSet == NULL) { | 
 | 	    return (-1); | 
 | 	} | 
 | 	wildc->negNsSet->value = ctxt->targetNamespace; | 
 |     } else { | 
 | 	const xmlChar *end, *cur; | 
 |  | 
 | 	cur = ns; | 
 | 	do { | 
 | 	    while (IS_BLANK_CH(*cur)) | 
 | 		cur++; | 
 | 	    end = cur; | 
 | 	    while ((*end != 0) && (!(IS_BLANK_CH(*end)))) | 
 | 		end++; | 
 | 	    if (end == cur) | 
 | 		break; | 
 | 	    nsItem = xmlStrndup(cur, end - cur); | 
 | 	    if ((xmlStrEqual(nsItem, BAD_CAST "##other")) || | 
 | 		    (xmlStrEqual(nsItem, BAD_CAST "##any"))) { | 
 | 		xmlSchemaPSimpleTypeErr(ctxt, | 
 | 		    XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER, | 
 | 		    NULL, (xmlNodePtr) attr, | 
 | 		    NULL, | 
 | 		    "((##any | ##other) | List of (xs:anyURI | " | 
 | 		    "(##targetNamespace | ##local)))", | 
 | 		    nsItem, NULL, NULL, NULL); | 
 | 		ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER; | 
 | 	    } else { | 
 | 		if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) { | 
 | 		    dictnsItem = ctxt->targetNamespace; | 
 | 		} else if (xmlStrEqual(nsItem, BAD_CAST "##local")) { | 
 | 		    dictnsItem = NULL; | 
 | 		} else { | 
 | 		    /* | 
 | 		    * Validate the item (anyURI). | 
 | 		    */ | 
 | 		    xmlSchemaPValAttrNodeValue(ctxt, NULL, attr, | 
 | 			nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI)); | 
 | 		    dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1); | 
 | 		} | 
 | 		/* | 
 | 		* Avoid dublicate namespaces. | 
 | 		*/ | 
 | 		tmp = wildc->nsSet; | 
 | 		while (tmp != NULL) { | 
 | 		    if (dictnsItem == tmp->value) | 
 | 			break; | 
 | 		    tmp = tmp->next; | 
 | 		} | 
 | 		if (tmp == NULL) { | 
 | 		    tmp = xmlSchemaNewWildcardNsConstraint(ctxt); | 
 | 		    if (tmp == NULL) { | 
 | 			xmlFree(nsItem); | 
 | 			return (-1); | 
 | 		    } | 
 | 		    tmp->value = dictnsItem; | 
 | 		    tmp->next = NULL; | 
 | 		    if (wildc->nsSet == NULL) | 
 | 			wildc->nsSet = tmp; | 
 | 		    else if (lastNs != NULL) | 
 | 			lastNs->next = tmp; | 
 | 		    lastNs = tmp; | 
 | 		} | 
 |  | 
 | 	    } | 
 | 	    xmlFree(nsItem); | 
 | 	    cur = end; | 
 | 	} while (*cur != 0); | 
 |     } | 
 |     return (ret); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt, | 
 | 				 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED, | 
 | 				 xmlNodePtr node, | 
 | 				 int minOccurs, | 
 | 				 int maxOccurs) { | 
 |  | 
 |     if ((maxOccurs == 0) && ( minOccurs == 0)) | 
 | 	return (0); | 
 |     if (maxOccurs != UNBOUNDED) { | 
 | 	/* | 
 | 	* TODO: Maybe we should better not create the particle, | 
 | 	* if min/max is invalid, since it could confuse the build of the | 
 | 	* content model. | 
 | 	*/ | 
 | 	/* | 
 | 	* 3.9.6 Schema Component Constraint: Particle Correct | 
 | 	* | 
 | 	*/ | 
 | 	if (maxOccurs < 1) { | 
 | 	    /* | 
 | 	    * 2.2 {max occurs} must be greater than or equal to 1. | 
 | 	    */ | 
 | 	    xmlSchemaPCustomAttrErr(ctxt, | 
 | 		XML_SCHEMAP_P_PROPS_CORRECT_2_2, | 
 | 		NULL, NULL, | 
 | 		xmlSchemaGetPropNode(node, "maxOccurs"), | 
 | 		"The value must be greater than or equal to 1"); | 
 | 	    return (XML_SCHEMAP_P_PROPS_CORRECT_2_2); | 
 | 	} else if (minOccurs > maxOccurs) { | 
 | 	    /* | 
 | 	    * 2.1 {min occurs} must not be greater than {max occurs}. | 
 | 	    */ | 
 | 	    xmlSchemaPCustomAttrErr(ctxt, | 
 | 		XML_SCHEMAP_P_PROPS_CORRECT_2_1, | 
 | 		NULL, NULL, | 
 | 		xmlSchemaGetPropNode(node, "minOccurs"), | 
 | 		"The value must not be greater than the value of 'maxOccurs'"); | 
 | 	    return (XML_SCHEMAP_P_PROPS_CORRECT_2_1); | 
 | 	} | 
 |     } | 
 |     return (0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaParseAny: | 
 |  * @ctxt:  a schema validation context | 
 |  * @schema:  the schema being built | 
 |  * @node:  a subtree containing XML Schema informations | 
 |  * | 
 |  * Parsea a XML schema <any> element. A particle and wildcard | 
 |  * will be created (except if minOccurs==maxOccurs==0, in this case | 
 |  * nothing will be created). | 
 |  * *WARNING* this interface is highly subject to change | 
 |  * | 
 |  * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0 | 
 |  */ | 
 | static xmlSchemaParticlePtr | 
 | xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | 
 |                   xmlNodePtr node) | 
 | { | 
 |     xmlSchemaParticlePtr particle; | 
 |     xmlNodePtr child = NULL; | 
 |     xmlSchemaWildcardPtr wild; | 
 |     int min, max; | 
 |     xmlAttrPtr attr; | 
 |     xmlSchemaAnnotPtr annot = NULL; | 
 |  | 
 |     if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) | 
 |         return (NULL); | 
 |     /* | 
 |     * Check for illegal attributes. | 
 |     */ | 
 |     attr = node->properties; | 
 |     while (attr != NULL) { | 
 | 	if (attr->ns == NULL) { | 
 | 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && | 
 | 		(!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) && | 
 | 		(!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) && | 
 | 	        (!xmlStrEqual(attr->name, BAD_CAST "namespace")) && | 
 | 		(!xmlStrEqual(attr->name, BAD_CAST "processContents"))) { | 
 | 		xmlSchemaPIllegalAttrErr(ctxt, | 
 | 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	    } | 
 | 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | 
 | 	    xmlSchemaPIllegalAttrErr(ctxt, | 
 | 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	} | 
 | 	attr = attr->next; | 
 |     } | 
 |     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | 
 |     /* | 
 |     * minOccurs/maxOccurs. | 
 |     */ | 
 |     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, | 
 | 	"(xs:nonNegativeInteger | unbounded)"); | 
 |     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, | 
 | 	"xs:nonNegativeInteger"); | 
 |     xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max); | 
 |     /* | 
 |     * Create & parse the wildcard. | 
 |     */ | 
 |     wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node); | 
 |     if (wild == NULL) | 
 | 	return (NULL); | 
 |     xmlSchemaParseWildcardNs(ctxt, schema, wild, node); | 
 |     /* | 
 |     * And now for the children... | 
 |     */ | 
 |     child = node->children; | 
 |     if (IS_SCHEMA(child, "annotation")) { | 
 |         annot = xmlSchemaParseAnnotation(ctxt, child, 1); | 
 |         child = child->next; | 
 |     } | 
 |     if (child != NULL) { | 
 | 	xmlSchemaPContentErr(ctxt, | 
 | 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | 
 | 	    NULL, node, child, | 
 | 	    NULL, "(annotation?)"); | 
 |     } | 
 |     /* | 
 |     * No component if minOccurs==maxOccurs==0. | 
 |     */ | 
 |     if ((min == 0) && (max == 0)) { | 
 | 	/* Don't free the wildcard, since it's already on the list. */ | 
 | 	return (NULL); | 
 |     } | 
 |     /* | 
 |     * Create the particle. | 
 |     */ | 
 |     particle = xmlSchemaAddParticle(ctxt, node, min, max); | 
 |     if (particle == NULL) | 
 |         return (NULL); | 
 |     particle->annot = annot; | 
 |     particle->children = (xmlSchemaTreeItemPtr) wild; | 
 |  | 
 |     return (particle); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaParseNotation: | 
 |  * @ctxt:  a schema validation context | 
 |  * @schema:  the schema being built | 
 |  * @node:  a subtree containing XML Schema informations | 
 |  * | 
 |  * parse a XML schema Notation declaration | 
 |  * | 
 |  * Returns the new structure or NULL in case of error | 
 |  */ | 
 | static xmlSchemaNotationPtr | 
 | xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | 
 |                        xmlNodePtr node) | 
 | { | 
 |     const xmlChar *name; | 
 |     xmlSchemaNotationPtr ret; | 
 |     xmlNodePtr child = NULL; | 
 |  | 
 |     if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) | 
 |         return (NULL); | 
 |     name = xmlSchemaGetProp(ctxt, node, "name"); | 
 |     if (name == NULL) { | 
 |         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME, | 
 |                        "Notation has no name\n", NULL, NULL); | 
 |         return (NULL); | 
 |     } | 
 |     ret = xmlSchemaAddNotation(ctxt, schema, name, | 
 | 	ctxt->targetNamespace, node); | 
 |     if (ret == NULL) | 
 |         return (NULL); | 
 |     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | 
 |  | 
 |     child = node->children; | 
 |     if (IS_SCHEMA(child, "annotation")) { | 
 |         ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1); | 
 |         child = child->next; | 
 |     } | 
 |     if (child != NULL) { | 
 | 	xmlSchemaPContentErr(ctxt, | 
 | 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | 
 | 	    NULL, node, child, | 
 | 	    NULL, "(annotation?)"); | 
 |     } | 
 |  | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaParseAnyAttribute: | 
 |  * @ctxt:  a schema validation context | 
 |  * @schema:  the schema being built | 
 |  * @node:  a subtree containing XML Schema informations | 
 |  * | 
 |  * parse a XML schema AnyAttrribute declaration | 
 |  * *WARNING* this interface is highly subject to change | 
 |  * | 
 |  * Returns a wildcard or NULL. | 
 |  */ | 
 | static xmlSchemaWildcardPtr | 
 | xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt, | 
 |                            xmlSchemaPtr schema, xmlNodePtr node) | 
 | { | 
 |     xmlSchemaWildcardPtr ret; | 
 |     xmlNodePtr child = NULL; | 
 |     xmlAttrPtr attr; | 
 |  | 
 |     if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) | 
 |         return (NULL); | 
 |  | 
 |     ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE, | 
 | 	node); | 
 |     if (ret == NULL) { | 
 |         return (NULL); | 
 |     } | 
 |     /* | 
 |     * Check for illegal attributes. | 
 |     */ | 
 |     attr = node->properties; | 
 |     while (attr != NULL) { | 
 | 	if (attr->ns == NULL) { | 
 | 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && | 
 | 	        (!xmlStrEqual(attr->name, BAD_CAST "namespace")) && | 
 | 		(!xmlStrEqual(attr->name, BAD_CAST "processContents"))) { | 
 | 		xmlSchemaPIllegalAttrErr(ctxt, | 
 | 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	    } | 
 | 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | 
 | 	    xmlSchemaPIllegalAttrErr(ctxt, | 
 | 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	} | 
 | 	attr = attr->next; | 
 |     } | 
 |     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | 
 |     /* | 
 |     * Parse the namespace list. | 
 |     */ | 
 |     if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0) | 
 | 	return (NULL); | 
 |     /* | 
 |     * And now for the children... | 
 |     */ | 
 |     child = node->children; | 
 |     if (IS_SCHEMA(child, "annotation")) { | 
 |         ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1); | 
 |         child = child->next; | 
 |     } | 
 |     if (child != NULL) { | 
 | 	xmlSchemaPContentErr(ctxt, | 
 | 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | 
 | 	    NULL, node, child, | 
 | 	    NULL, "(annotation?)"); | 
 |     } | 
 |  | 
 |     return (ret); | 
 | } | 
 |  | 
 |  | 
 | /** | 
 |  * xmlSchemaParseAttribute: | 
 |  * @ctxt:  a schema validation context | 
 |  * @schema:  the schema being built | 
 |  * @node:  a subtree containing XML Schema informations | 
 |  * | 
 |  * parse a XML schema Attrribute declaration | 
 |  * *WARNING* this interface is highly subject to change | 
 |  * | 
 |  * Returns the attribute declaration. | 
 |  */ | 
 | static xmlSchemaBasicItemPtr | 
 | xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt, | 
 | 			     xmlSchemaPtr schema, | 
 | 			     xmlNodePtr node, | 
 | 			     xmlSchemaItemListPtr uses, | 
 | 			     int parentType) | 
 | { | 
 |     const xmlChar *attrValue, *name = NULL, *ns = NULL; | 
 |     xmlSchemaAttributeUsePtr use = NULL; | 
 |     xmlNodePtr child = NULL; | 
 |     xmlAttrPtr attr; | 
 |     const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL; | 
 |     int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL; | 
 |     int	nberrors, hasForm = 0, defValueType = 0; | 
 |  | 
 | #define WXS_ATTR_DEF_VAL_DEFAULT 1 | 
 | #define WXS_ATTR_DEF_VAL_FIXED 2 | 
 |  | 
 |     /* | 
 |      * 3.2.3 Constraints on XML Representations of Attribute Declarations | 
 |      */ | 
 |  | 
 |     if ((pctxt == NULL) || (schema == NULL) || (node == NULL)) | 
 |         return (NULL); | 
 |     attr = xmlSchemaGetPropNode(node, "ref"); | 
 |     if (attr != NULL) { | 
 | 	if (xmlSchemaPValAttrNodeQName(pctxt, schema, | 
 | 	    NULL, attr, &tmpNs, &tmpName) != 0) { | 
 | 	    return (NULL); | 
 | 	} | 
 | 	if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0) | 
 | 	    return(NULL); | 
 | 	isRef = 1; | 
 |     } | 
 |     nberrors = pctxt->nberrors; | 
 |     /* | 
 |     * Check for illegal attributes. | 
 |     */ | 
 |     attr = node->properties; | 
 |     while (attr != NULL) { | 
 | 	if (attr->ns == NULL) { | 
 | 	    if (isRef) { | 
 | 		if (xmlStrEqual(attr->name, BAD_CAST "id")) { | 
 | 		    xmlSchemaPValAttrNodeID(pctxt, attr); | 
 | 		    goto attr_next; | 
 | 		} else if (xmlStrEqual(attr->name, BAD_CAST "ref")) { | 
 | 		    goto attr_next; | 
 | 		} | 
 | 	    } else { | 
 | 		if (xmlStrEqual(attr->name, BAD_CAST "name")) { | 
 | 		    goto attr_next; | 
 | 		} else if (xmlStrEqual(attr->name, BAD_CAST "id")) { | 
 | 		    xmlSchemaPValAttrNodeID(pctxt, attr); | 
 | 		    goto attr_next; | 
 | 		} else if (xmlStrEqual(attr->name, BAD_CAST "type")) { | 
 | 		    xmlSchemaPValAttrNodeQName(pctxt, schema, NULL, | 
 | 			attr, &tmpNs, &tmpName); | 
 | 		    goto attr_next; | 
 | 		} else if (xmlStrEqual(attr->name, BAD_CAST "form")) { | 
 | 		    /* | 
 | 		    * Evaluate the target namespace | 
 | 		    */ | 
 | 		    hasForm = 1; | 
 | 		    attrValue = xmlSchemaGetNodeContent(pctxt, | 
 | 			(xmlNodePtr) attr); | 
 | 		    if (xmlStrEqual(attrValue, BAD_CAST "qualified")) { | 
 | 			ns = pctxt->targetNamespace; | 
 | 		    } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) | 
 | 		    { | 
 | 			xmlSchemaPSimpleTypeErr(pctxt, | 
 | 			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | 
 | 			    NULL, (xmlNodePtr) attr, | 
 | 			    NULL, "(qualified | unqualified)", | 
 | 			    attrValue, NULL, NULL, NULL); | 
 | 		    } | 
 | 		    goto attr_next; | 
 | 		} | 
 | 	    } | 
 | 	    if (xmlStrEqual(attr->name, BAD_CAST "use")) { | 
 |  | 
 | 		attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr); | 
 | 		/* TODO: Maybe we need to normalize the value beforehand. */ | 
 | 		if (xmlStrEqual(attrValue, BAD_CAST "optional")) | 
 | 		    occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL; | 
 | 		else if (xmlStrEqual(attrValue, BAD_CAST "prohibited")) | 
 | 		    occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED; | 
 | 		else if (xmlStrEqual(attrValue, BAD_CAST "required")) | 
 | 		    occurs = XML_SCHEMAS_ATTR_USE_REQUIRED; | 
 | 		else { | 
 | 		    xmlSchemaPSimpleTypeErr(pctxt, | 
 | 			XML_SCHEMAP_INVALID_ATTR_USE, | 
 | 			NULL, (xmlNodePtr) attr, | 
 | 			NULL, "(optional | prohibited | required)", | 
 | 			attrValue, NULL, NULL, NULL); | 
 | 		} | 
 | 		goto attr_next; | 
 | 	    } else if (xmlStrEqual(attr->name, BAD_CAST "default")) { | 
 | 		/* | 
 | 		* 3.2.3 : 1 | 
 | 		* default and fixed must not both be present. | 
 | 		*/ | 
 | 		if (defValue) { | 
 | 		    xmlSchemaPMutualExclAttrErr(pctxt, | 
 | 			XML_SCHEMAP_SRC_ATTRIBUTE_1, | 
 | 			NULL, attr, "default", "fixed"); | 
 | 		} else { | 
 | 		    defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr); | 
 | 		    defValueType = WXS_ATTR_DEF_VAL_DEFAULT; | 
 | 		} | 
 | 		goto attr_next; | 
 | 	    } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) { | 
 | 		/* | 
 | 		* 3.2.3 : 1 | 
 | 		* default and fixed must not both be present. | 
 | 		*/ | 
 | 		if (defValue) { | 
 | 		    xmlSchemaPMutualExclAttrErr(pctxt, | 
 | 			XML_SCHEMAP_SRC_ATTRIBUTE_1, | 
 | 			NULL, attr, "default", "fixed"); | 
 | 		} else { | 
 | 		    defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr); | 
 | 		    defValueType = WXS_ATTR_DEF_VAL_FIXED; | 
 | 		} | 
 | 		goto attr_next; | 
 | 	    } | 
 | 	} else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs)) | 
 | 	    goto attr_next; | 
 |  | 
 | 	xmlSchemaPIllegalAttrErr(pctxt, | 
 | 	    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 |  | 
 | attr_next: | 
 | 	attr = attr->next; | 
 |     } | 
 |     /* | 
 |     * 3.2.3 : 2 | 
 |     * If default and use are both present, use must have | 
 |     * the actual value optional. | 
 |     */ | 
 |     if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) && | 
 | 	(occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) { | 
 | 	xmlSchemaPSimpleTypeErr(pctxt, | 
 | 	    XML_SCHEMAP_SRC_ATTRIBUTE_2, | 
 | 	    NULL, node, NULL, | 
 | 	    "(optional | prohibited | required)", NULL, | 
 | 	    "The value of the attribute 'use' must be 'optional' " | 
 | 	    "if the attribute 'default' is present", | 
 | 	    NULL, NULL); | 
 |     } | 
 |     /* | 
 |     * We want correct attributes. | 
 |     */ | 
 |     if (nberrors != pctxt->nberrors) | 
 | 	return(NULL); | 
 |     if (! isRef) { | 
 | 	xmlSchemaAttributePtr attrDecl; | 
 |  | 
 | 	/* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */ | 
 | 	if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR)) | 
 | 	    ns = pctxt->targetNamespace; | 
 | 	/* | 
 | 	* 3.2.6 Schema Component Constraint: xsi: Not Allowed | 
 | 	* TODO: Move this to the component layer. | 
 | 	*/ | 
 | 	if (xmlStrEqual(ns, xmlSchemaInstanceNs)) { | 
 | 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, | 
 | 		XML_SCHEMAP_NO_XSI, | 
 | 		node, NULL, | 
 | 		"The target namespace must not match '%s'", | 
 | 		xmlSchemaInstanceNs, NULL); | 
 | 	} | 
 | 	attr = xmlSchemaGetPropNode(node, "name"); | 
 | 	if (attr == NULL) { | 
 | 	    xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING, | 
 | 		NULL, node, "name", NULL); | 
 | 	    return (NULL); | 
 | 	} | 
 | 	if (xmlSchemaPValAttrNode(pctxt, NULL, attr, | 
 | 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) { | 
 | 	    return (NULL); | 
 | 	} | 
 | 	/* | 
 | 	* 3.2.6 Schema Component Constraint: xmlns Not Allowed | 
 | 	* TODO: Move this to the component layer. | 
 | 	*/ | 
 | 	if (xmlStrEqual(name, BAD_CAST "xmlns")) { | 
 | 	    xmlSchemaPSimpleTypeErr(pctxt, | 
 | 		XML_SCHEMAP_NO_XMLNS, | 
 | 		NULL, (xmlNodePtr) attr, | 
 | 		xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL, | 
 | 		"The value of the attribute must not match 'xmlns'", | 
 | 		NULL, NULL); | 
 | 	    return (NULL); | 
 | 	} | 
 | 	if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) | 
 | 	    goto check_children; | 
 | 	/* | 
 | 	* Create the attribute use component. | 
 | 	*/ | 
 | 	use = xmlSchemaAddAttributeUse(pctxt, node); | 
 | 	if (use == NULL) | 
 | 	    return(NULL); | 
 | 	use->occurs = occurs; | 
 | 	/* | 
 | 	* Create the attribute declaration. | 
 | 	*/ | 
 | 	attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0); | 
 | 	if (attrDecl == NULL) | 
 | 	    return (NULL); | 
 | 	if (tmpName != NULL) { | 
 | 	    attrDecl->typeName = tmpName; | 
 | 	    attrDecl->typeNs = tmpNs; | 
 | 	} | 
 | 	use->attrDecl = attrDecl; | 
 | 	/* | 
 | 	* Value constraint. | 
 | 	*/ | 
 | 	if (defValue != NULL) { | 
 | 	    attrDecl->defValue = defValue; | 
 | 	    if (defValueType == WXS_ATTR_DEF_VAL_FIXED) | 
 | 		attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED; | 
 | 	} | 
 |     } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) { | 
 | 	xmlSchemaQNameRefPtr ref; | 
 |  | 
 | 	/* | 
 | 	* Create the attribute use component. | 
 | 	*/ | 
 | 	use = xmlSchemaAddAttributeUse(pctxt, node); | 
 | 	if (use == NULL) | 
 | 	    return(NULL); | 
 | 	/* | 
 | 	* We need to resolve the reference at later stage. | 
 | 	*/ | 
 | 	WXS_ADD_PENDING(pctxt, use); | 
 | 	use->occurs = occurs; | 
 | 	/* | 
 | 	* Create a QName reference to the attribute declaration. | 
 | 	*/ | 
 | 	ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE, | 
 | 	    tmpName, tmpNs); | 
 | 	if (ref == NULL) | 
 | 	    return(NULL); | 
 | 	/* | 
 | 	* Assign the reference. This will be substituted for the | 
 | 	* referenced attribute declaration when the QName is resolved. | 
 | 	*/ | 
 | 	use->attrDecl = WXS_ATTR_CAST ref; | 
 | 	/* | 
 | 	* Value constraint. | 
 | 	*/ | 
 | 	if (defValue != NULL) | 
 | 	    use->defValue = defValue; | 
 | 	    if (defValueType == WXS_ATTR_DEF_VAL_FIXED) | 
 | 		use->flags |= XML_SCHEMA_ATTR_USE_FIXED; | 
 |     } | 
 |  | 
 | check_children: | 
 |     /* | 
 |     * And now for the children... | 
 |     */ | 
 |     child = node->children; | 
 |     if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) { | 
 | 	xmlSchemaAttributeUseProhibPtr prohib; | 
 |  | 
 | 	if (IS_SCHEMA(child, "annotation")) { | 
 | 	    xmlSchemaParseAnnotation(pctxt, child, 0); | 
 | 	    child = child->next; | 
 | 	} | 
 | 	if (child != NULL) { | 
 | 	    xmlSchemaPContentErr(pctxt, | 
 | 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | 
 | 		NULL, node, child, NULL, | 
 | 		"(annotation?)"); | 
 | 	} | 
 | 	/* | 
 | 	* Check for pointlessness of attribute prohibitions. | 
 | 	*/ | 
 | 	if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) { | 
 | 	    xmlSchemaCustomWarning(ACTXT_CAST pctxt, | 
 | 		XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH, | 
 | 		node, NULL, | 
 | 		"Skipping attribute use prohibition, since it is " | 
 | 		"pointless inside an <attributeGroup>", | 
 | 		NULL, NULL, NULL); | 
 | 	    return(NULL); | 
 | 	} else if (parentType == XML_SCHEMA_TYPE_EXTENSION) { | 
 | 	    xmlSchemaCustomWarning(ACTXT_CAST pctxt, | 
 | 		XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH, | 
 | 		node, NULL, | 
 | 		"Skipping attribute use prohibition, since it is " | 
 | 		"pointless when extending a type", | 
 | 		NULL, NULL, NULL); | 
 | 	    return(NULL); | 
 | 	} | 
 | 	if (! isRef) { | 
 | 	    tmpName = name; | 
 | 	    tmpNs = ns; | 
 | 	} | 
 | 	/* | 
 | 	* Check for duplicate attribute prohibitions. | 
 | 	*/ | 
 | 	if (uses) { | 
 | 	    int i; | 
 |  | 
 | 	    for (i = 0; i < uses->nbItems; i++) { | 
 | 		use = uses->items[i]; | 
 | 		if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) && | 
 | 		    (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) && | 
 | 		    (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace)) | 
 | 		{ | 
 | 		    xmlChar *str = NULL; | 
 |  | 
 | 		    xmlSchemaCustomWarning(ACTXT_CAST pctxt, | 
 | 			XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH, | 
 | 			node, NULL, | 
 | 			"Skipping duplicate attribute use prohibition '%s'", | 
 | 			xmlSchemaFormatQName(&str, tmpNs, tmpName), | 
 | 			NULL, NULL); | 
 | 		    FREE_AND_NULL(str) | 
 | 		    return(NULL); | 
 | 		} | 
 | 	    } | 
 | 	} | 
 | 	/* | 
 | 	* Create the attribute prohibition helper component. | 
 | 	*/ | 
 | 	prohib = xmlSchemaAddAttributeUseProhib(pctxt); | 
 | 	if (prohib == NULL) | 
 | 	    return(NULL); | 
 | 	prohib->node = node; | 
 | 	prohib->name = tmpName; | 
 | 	prohib->targetNamespace = tmpNs; | 
 | 	if (isRef) { | 
 | 	    /* | 
 | 	    * We need at least to resolve to the attribute declaration. | 
 | 	    */ | 
 | 	    WXS_ADD_PENDING(pctxt, prohib); | 
 | 	} | 
 | 	return(WXS_BASIC_CAST prohib); | 
 |     } else { | 
 | 	if (IS_SCHEMA(child, "annotation")) { | 
 | 	    /* | 
 | 	    * TODO: Should this go into the attr decl? | 
 | 	    */ | 
 | 	    use->annot = xmlSchemaParseAnnotation(pctxt, child, 1); | 
 | 	    child = child->next; | 
 | 	} | 
 | 	if (isRef) { | 
 | 	    if (child != NULL) { | 
 | 		if (IS_SCHEMA(child, "simpleType")) | 
 | 		    /* | 
 | 		    * 3.2.3 : 3.2 | 
 | 		    * If ref is present, then all of <simpleType>, | 
 | 		    * form and type must be absent. | 
 | 		    */ | 
 | 		    xmlSchemaPContentErr(pctxt, | 
 | 			XML_SCHEMAP_SRC_ATTRIBUTE_3_2, | 
 | 			NULL, node, child, NULL, | 
 | 			"(annotation?)"); | 
 | 		else | 
 | 		    xmlSchemaPContentErr(pctxt, | 
 | 			XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | 
 | 			NULL, node, child, NULL, | 
 | 			"(annotation?)"); | 
 | 	    } | 
 | 	} else { | 
 | 	    if (IS_SCHEMA(child, "simpleType")) { | 
 | 		if (WXS_ATTRUSE_DECL(use)->typeName != NULL) { | 
 | 		    /* | 
 | 		    * 3.2.3 : 4 | 
 | 		    * type and <simpleType> must not both be present. | 
 | 		    */ | 
 | 		    xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4, | 
 | 			NULL, node, child, | 
 | 			"The attribute 'type' and the <simpleType> child " | 
 | 			"are mutually exclusive", NULL); | 
 | 		} else | 
 | 		    WXS_ATTRUSE_TYPEDEF(use) = | 
 | 			xmlSchemaParseSimpleType(pctxt, schema, child, 0); | 
 | 		child = child->next; | 
 | 	    } | 
 | 	    if (child != NULL) | 
 | 		xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | 
 | 		NULL, node, child, NULL, | 
 | 		"(annotation?, simpleType?)"); | 
 | 	} | 
 |     } | 
 |     return (WXS_BASIC_CAST use); | 
 | } | 
 |  | 
 |  | 
 | static xmlSchemaAttributePtr | 
 | xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt, | 
 | 			      xmlSchemaPtr schema, | 
 | 			      xmlNodePtr node) | 
 | { | 
 |     const xmlChar *attrValue; | 
 |     xmlSchemaAttributePtr ret; | 
 |     xmlNodePtr child = NULL; | 
 |     xmlAttrPtr attr; | 
 |  | 
 |     /* | 
 |      * Note that the w3c spec assumes the schema to be validated with schema | 
 |      * for schemas beforehand. | 
 |      * | 
 |      * 3.2.3 Constraints on XML Representations of Attribute Declarations | 
 |      */ | 
 |     if ((pctxt == NULL) || (schema == NULL) || (node == NULL)) | 
 |         return (NULL); | 
 |     /* | 
 |     * 3.2.3 : 3.1 | 
 |     * One of ref or name must be present, but not both | 
 |     */ | 
 |     attr = xmlSchemaGetPropNode(node, "name"); | 
 |     if (attr == NULL) { | 
 | 	xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING, | 
 | 	    NULL, node, "name", NULL); | 
 | 	return (NULL); | 
 |     } | 
 |     if (xmlSchemaPValAttrNode(pctxt, NULL, attr, | 
 | 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) { | 
 | 	return (NULL); | 
 |     } | 
 |     /* | 
 |     * 3.2.6 Schema Component Constraint: xmlns Not Allowed | 
 |     * TODO: Move this to the component layer. | 
 |     */ | 
 |     if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) { | 
 | 	xmlSchemaPSimpleTypeErr(pctxt, | 
 | 	    XML_SCHEMAP_NO_XMLNS, | 
 | 	    NULL, (xmlNodePtr) attr, | 
 | 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL, | 
 | 	    "The value of the attribute must not match 'xmlns'", | 
 | 	    NULL, NULL); | 
 | 	return (NULL); | 
 |     } | 
 |     /* | 
 |     * 3.2.6 Schema Component Constraint: xsi: Not Allowed | 
 |     * TODO: Move this to the component layer. | 
 |     *       Or better leave it here and add it to the component layer | 
 |     *       if we have a schema construction API. | 
 |     */ | 
 |     if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) { | 
 | 	xmlSchemaCustomErr(ACTXT_CAST pctxt, | 
 | 	    XML_SCHEMAP_NO_XSI, node, NULL, | 
 | 	    "The target namespace must not match '%s'", | 
 | 	    xmlSchemaInstanceNs, NULL); | 
 |     } | 
 |  | 
 |     ret = xmlSchemaAddAttribute(pctxt, schema, attrValue, | 
 | 	pctxt->targetNamespace, node, 1); | 
 |     if (ret == NULL) | 
 | 	return (NULL); | 
 |     ret->flags |= XML_SCHEMAS_ATTR_GLOBAL; | 
 |  | 
 |     /* | 
 |     * Check for illegal attributes. | 
 |     */ | 
 |     attr = node->properties; | 
 |     while (attr != NULL) { | 
 | 	if (attr->ns == NULL) { | 
 | 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && | 
 | 		(!xmlStrEqual(attr->name, BAD_CAST "default")) && | 
 | 		(!xmlStrEqual(attr->name, BAD_CAST "fixed")) && | 
 | 		(!xmlStrEqual(attr->name, BAD_CAST "name")) && | 
 | 		(!xmlStrEqual(attr->name, BAD_CAST "type"))) | 
 | 	    { | 
 | 		xmlSchemaPIllegalAttrErr(pctxt, | 
 | 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	    } | 
 | 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | 
 | 	    xmlSchemaPIllegalAttrErr(pctxt, | 
 | 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	} | 
 | 	attr = attr->next; | 
 |     } | 
 |     xmlSchemaPValAttrQName(pctxt, schema, NULL, | 
 | 	node, "type", &ret->typeNs, &ret->typeName); | 
 |  | 
 |     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id"); | 
 |     /* | 
 |     * Attribute "fixed". | 
 |     */ | 
 |     ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed"); | 
 |     if (ret->defValue != NULL) | 
 | 	ret->flags |= XML_SCHEMAS_ATTR_FIXED; | 
 |     /* | 
 |     * Attribute "default". | 
 |     */ | 
 |     attr = xmlSchemaGetPropNode(node, "default"); | 
 |     if (attr != NULL) { | 
 | 	/* | 
 | 	* 3.2.3 : 1 | 
 | 	* default and fixed must not both be present. | 
 | 	*/ | 
 | 	if (ret->flags & XML_SCHEMAS_ATTR_FIXED) { | 
 | 	    xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1, | 
 | 		WXS_BASIC_CAST ret, attr, "default", "fixed"); | 
 | 	} else | 
 | 	    ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr); | 
 |     } | 
 |     /* | 
 |     * And now for the children... | 
 |     */ | 
 |     child = node->children; | 
 |     if (IS_SCHEMA(child, "annotation")) { | 
 |         ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1); | 
 |         child = child->next; | 
 |     } | 
 |     if (IS_SCHEMA(child, "simpleType")) { | 
 | 	if (ret->typeName != NULL) { | 
 | 	    /* | 
 | 	    * 3.2.3 : 4 | 
 | 	    * type and <simpleType> must not both be present. | 
 | 	    */ | 
 | 	    xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4, | 
 | 		NULL, node, child, | 
 | 		"The attribute 'type' and the <simpleType> child " | 
 | 		"are mutually exclusive", NULL); | 
 | 	} else | 
 | 	    ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0); | 
 | 	child = child->next; | 
 |     } | 
 |     if (child != NULL) | 
 | 	xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | 
 | 	    NULL, node, child, NULL, | 
 | 	    "(annotation?, simpleType?)"); | 
 |  | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaParseAttributeGroupRef: | 
 |  * @ctxt:  a schema validation context | 
 |  * @schema:  the schema being built | 
 |  * @node:  a subtree containing XML Schema informations | 
 |  * | 
 |  * Parse an attribute group definition reference. | 
 |  * Note that a reference to an attribute group does not | 
 |  * correspond to any component at all. | 
 |  * *WARNING* this interface is highly subject to change | 
 |  * | 
 |  * Returns the attribute group or NULL in case of error. | 
 |  */ | 
 | static xmlSchemaQNameRefPtr | 
 | xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt, | 
 | 				xmlSchemaPtr schema, | 
 | 				xmlNodePtr node) | 
 | { | 
 |     xmlSchemaQNameRefPtr ret; | 
 |     xmlNodePtr child = NULL; | 
 |     xmlAttrPtr attr; | 
 |     const xmlChar *refNs = NULL, *ref = NULL; | 
 |  | 
 |     if ((pctxt == NULL) || (schema == NULL) || (node == NULL)) | 
 |         return (NULL); | 
 |  | 
 |     attr = xmlSchemaGetPropNode(node, "ref"); | 
 |     if (attr == NULL) { | 
 | 	xmlSchemaPMissingAttrErr(pctxt, | 
 | 	    XML_SCHEMAP_S4S_ATTR_MISSING, | 
 | 	    NULL, node, "ref", NULL); | 
 | 	return (NULL); | 
 |     } | 
 |     xmlSchemaPValAttrNodeQName(pctxt, schema, | 
 | 	NULL, attr, &refNs, &ref); | 
 |     if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0) | 
 | 	return(NULL); | 
 |  | 
 |     /* | 
 |     * Check for illegal attributes. | 
 |     */ | 
 |     attr = node->properties; | 
 |     while (attr != NULL) { | 
 | 	if (attr->ns == NULL) { | 
 | 	    if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) && | 
 | 		(!xmlStrEqual(attr->name, BAD_CAST "id"))) | 
 | 	    { | 
 | 		xmlSchemaPIllegalAttrErr(pctxt, | 
 | 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	    } | 
 | 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | 
 | 	    xmlSchemaPIllegalAttrErr(pctxt, | 
 | 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	} | 
 | 	attr = attr->next; | 
 |     } | 
 |     /* Attribute ID */ | 
 |     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id"); | 
 |  | 
 |     /* | 
 |     * And now for the children... | 
 |     */ | 
 |     child = node->children; | 
 |     if (IS_SCHEMA(child, "annotation")) { | 
 | 	/* | 
 | 	* TODO: We do not have a place to store the annotation, do we? | 
 | 	*/ | 
 |         xmlSchemaParseAnnotation(pctxt, child, 0); | 
 |         child = child->next; | 
 |     } | 
 |     if (child != NULL) { | 
 | 	xmlSchemaPContentErr(pctxt, | 
 | 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | 
 | 	    NULL, node, child, NULL, | 
 | 	    "(annotation?)"); | 
 |     } | 
 |  | 
 |     /* | 
 |     * Handle attribute group redefinitions. | 
 |     */ | 
 |     if (pctxt->isRedefine && pctxt->redef && | 
 | 	(pctxt->redef->item->type == | 
 | 	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP) && | 
 | 	(ref == pctxt->redef->refName) && | 
 | 	(refNs == pctxt->redef->refTargetNs)) | 
 |     { | 
 | 	/* | 
 | 	* SPEC src-redefine: | 
 | 	* (7.1) "If it has an <attributeGroup> among its contents | 
 | 	* the �actual value� of whose ref [attribute] is the same | 
 | 	* as the �actual value� of its own name attribute plus | 
 | 	* target namespace, then it must have exactly one such group." | 
 | 	*/ | 
 | 	if (pctxt->redefCounter != 0) { | 
 | 	    xmlChar *str = NULL; | 
 |  | 
 | 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, | 
 | 		XML_SCHEMAP_SRC_REDEFINE, node, NULL, | 
 | 		"The redefining attribute group definition " | 
 | 		"'%s' must not contain more than one " | 
 | 		"reference to the redefined definition", | 
 | 		xmlSchemaFormatQName(&str, refNs, ref), NULL); | 
 | 	    FREE_AND_NULL(str); | 
 | 	    return(NULL); | 
 | 	} | 
 | 	pctxt->redefCounter++; | 
 | 	/* | 
 | 	* URGENT TODO: How to ensure that the reference will not be | 
 | 	* handled by the normal component resolution mechanism? | 
 | 	*/ | 
 | 	ret = xmlSchemaNewQNameRef(pctxt, | 
 | 	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs); | 
 | 	if (ret == NULL) | 
 | 	    return(NULL); | 
 | 	ret->node = node; | 
 | 	pctxt->redef->reference = WXS_BASIC_CAST ret; | 
 |     } else { | 
 | 	/* | 
 | 	* Create a QName-reference helper component. We will substitute this | 
 | 	* component for the attribute uses of the referenced attribute group | 
 | 	* definition. | 
 | 	*/ | 
 | 	ret = xmlSchemaNewQNameRef(pctxt, | 
 | 	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs); | 
 | 	if (ret == NULL) | 
 | 	    return(NULL); | 
 | 	ret->node = node; | 
 | 	/* Add to pending items, to be able to resolve the reference. */ | 
 | 	WXS_ADD_PENDING(pctxt, ret); | 
 |     } | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaParseAttributeGroupDefinition: | 
 |  * @pctxt:  a schema validation context | 
 |  * @schema:  the schema being built | 
 |  * @node:  a subtree containing XML Schema informations | 
 |  * | 
 |  * parse a XML schema Attribute Group declaration | 
 |  * *WARNING* this interface is highly subject to change | 
 |  * | 
 |  * Returns the attribute group definition or NULL in case of error. | 
 |  */ | 
 | static xmlSchemaAttributeGroupPtr | 
 | xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt, | 
 | 				       xmlSchemaPtr schema, | 
 | 				       xmlNodePtr node) | 
 | { | 
 |     const xmlChar *name; | 
 |     xmlSchemaAttributeGroupPtr ret; | 
 |     xmlNodePtr child = NULL; | 
 |     xmlAttrPtr attr; | 
 |     int hasRefs = 0; | 
 |  | 
 |     if ((pctxt == NULL) || (schema == NULL) || (node == NULL)) | 
 |         return (NULL); | 
 |  | 
 |     attr = xmlSchemaGetPropNode(node, "name"); | 
 |     if (attr == NULL) { | 
 | 	xmlSchemaPMissingAttrErr(pctxt, | 
 | 	    XML_SCHEMAP_S4S_ATTR_MISSING, | 
 | 	    NULL, node, "name", NULL); | 
 | 	return (NULL); | 
 |     } | 
 |     /* | 
 |     * The name is crucial, exit if invalid. | 
 |     */ | 
 |     if (xmlSchemaPValAttrNode(pctxt, | 
 | 	NULL, attr, | 
 | 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) { | 
 | 	return (NULL); | 
 |     } | 
 |     ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema, | 
 | 	name, pctxt->targetNamespace, node); | 
 |     if (ret == NULL) | 
 | 	return (NULL); | 
 |     /* | 
 |     * Check for illegal attributes. | 
 |     */ | 
 |     attr = node->properties; | 
 |     while (attr != NULL) { | 
 | 	if (attr->ns == NULL) { | 
 | 	    if ((!xmlStrEqual(attr->name, BAD_CAST "name")) && | 
 | 		(!xmlStrEqual(attr->name, BAD_CAST "id"))) | 
 | 	    { | 
 | 		xmlSchemaPIllegalAttrErr(pctxt, | 
 | 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	    } | 
 | 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | 
 | 	    xmlSchemaPIllegalAttrErr(pctxt, | 
 | 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	} | 
 | 	attr = attr->next; | 
 |     } | 
 |     /* Attribute ID */ | 
 |     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id"); | 
 |     /* | 
 |     * And now for the children... | 
 |     */ | 
 |     child = node->children; | 
 |     if (IS_SCHEMA(child, "annotation")) { | 
 |         ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1); | 
 |         child = child->next; | 
 |     } | 
 |     /* | 
 |     * Parse contained attribute decls/refs. | 
 |     */ | 
 |     if (xmlSchemaParseLocalAttributes(pctxt, schema, &child, | 
 | 	(xmlSchemaItemListPtr *) &(ret->attrUses), | 
 | 	XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1) | 
 | 	return(NULL); | 
 |     if (hasRefs) | 
 | 	ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS; | 
 |     /* | 
 |     * Parse the attribute wildcard. | 
 |     */ | 
 |     if (IS_SCHEMA(child, "anyAttribute")) { | 
 | 	ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt, | 
 | 	    schema, child); | 
 | 	child = child->next; | 
 |     } | 
 |     if (child != NULL) { | 
 | 	xmlSchemaPContentErr(pctxt, | 
 | 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | 
 | 	    NULL, node, child, NULL, | 
 | 	    "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))"); | 
 |     } | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaPValAttrFormDefault: | 
 |  * @value:  the value | 
 |  * @flags: the flags to be modified | 
 |  * @flagQualified: the specific flag for "qualified" | 
 |  * | 
 |  * Returns 0 if the value is valid, 1 otherwise. | 
 |  */ | 
 | static int | 
 | xmlSchemaPValAttrFormDefault(const xmlChar *value, | 
 | 			     int *flags, | 
 | 			     int flagQualified) | 
 | { | 
 |     if (xmlStrEqual(value, BAD_CAST "qualified")) { | 
 | 	if  ((*flags & flagQualified) == 0) | 
 | 	    *flags |= flagQualified; | 
 |     } else if (!xmlStrEqual(value, BAD_CAST "unqualified")) | 
 | 	return (1); | 
 |  | 
 |     return (0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaPValAttrBlockFinal: | 
 |  * @value:  the value | 
 |  * @flags: the flags to be modified | 
 |  * @flagAll: the specific flag for "#all" | 
 |  * @flagExtension: the specific flag for "extension" | 
 |  * @flagRestriction: the specific flag for "restriction" | 
 |  * @flagSubstitution: the specific flag for "substitution" | 
 |  * @flagList: the specific flag for "list" | 
 |  * @flagUnion: the specific flag for "union" | 
 |  * | 
 |  * Validates the value of the attribute "final" and "block". The value | 
 |  * is converted into the specified flag values and returned in @flags. | 
 |  * | 
 |  * Returns 0 if the value is valid, 1 otherwise. | 
 |  */ | 
 |  | 
 | static int | 
 | xmlSchemaPValAttrBlockFinal(const xmlChar *value, | 
 | 			    int *flags, | 
 | 			    int flagAll, | 
 | 			    int flagExtension, | 
 | 			    int flagRestriction, | 
 | 			    int flagSubstitution, | 
 | 			    int flagList, | 
 | 			    int flagUnion) | 
 | { | 
 |     int ret = 0; | 
 |  | 
 |     /* | 
 |     * TODO: This does not check for dublicate entries. | 
 |     */ | 
 |     if ((flags == NULL) || (value == NULL)) | 
 | 	return (-1); | 
 |     if (value[0] == 0) | 
 | 	return (0); | 
 |     if (xmlStrEqual(value, BAD_CAST "#all")) { | 
 | 	if (flagAll != -1) | 
 | 	    *flags |= flagAll; | 
 | 	else { | 
 | 	    if (flagExtension != -1) | 
 | 		*flags |= flagExtension; | 
 | 	    if (flagRestriction != -1) | 
 | 		*flags |= flagRestriction; | 
 | 	    if (flagSubstitution != -1) | 
 | 		*flags |= flagSubstitution; | 
 | 	    if (flagList != -1) | 
 | 		*flags |= flagList; | 
 | 	    if (flagUnion != -1) | 
 | 		*flags |= flagUnion; | 
 | 	} | 
 |     } else { | 
 | 	const xmlChar *end, *cur = value; | 
 | 	xmlChar *item; | 
 |  | 
 | 	do { | 
 | 	    while (IS_BLANK_CH(*cur)) | 
 | 		cur++; | 
 | 	    end = cur; | 
 | 	    while ((*end != 0) && (!(IS_BLANK_CH(*end)))) | 
 | 		end++; | 
 | 	    if (end == cur) | 
 | 		break; | 
 | 	    item = xmlStrndup(cur, end - cur); | 
 | 	    if (xmlStrEqual(item, BAD_CAST "extension")) { | 
 | 		if (flagExtension != -1) { | 
 | 		    if ((*flags & flagExtension) == 0) | 
 | 			*flags |= flagExtension; | 
 | 		} else | 
 | 		    ret = 1; | 
 | 	    } else if (xmlStrEqual(item, BAD_CAST "restriction")) { | 
 | 		if (flagRestriction != -1) { | 
 | 		    if ((*flags & flagRestriction) == 0) | 
 | 			*flags |= flagRestriction; | 
 | 		} else | 
 | 		    ret = 1; | 
 | 	    } else if (xmlStrEqual(item, BAD_CAST "substitution")) { | 
 | 		if (flagSubstitution != -1) { | 
 | 		    if ((*flags & flagSubstitution) == 0) | 
 | 			*flags |= flagSubstitution; | 
 | 		} else | 
 | 		    ret = 1; | 
 | 	    } else if (xmlStrEqual(item, BAD_CAST "list")) { | 
 | 		if (flagList != -1) { | 
 | 		    if ((*flags & flagList) == 0) | 
 | 			*flags |= flagList; | 
 | 		} else | 
 | 		    ret = 1; | 
 | 	    } else if (xmlStrEqual(item, BAD_CAST "union")) { | 
 | 		if (flagUnion != -1) { | 
 | 		    if ((*flags & flagUnion) == 0) | 
 | 			*flags |= flagUnion; | 
 | 		} else | 
 | 		    ret = 1; | 
 | 	    } else | 
 | 		ret = 1; | 
 | 	    if (item != NULL) | 
 | 		xmlFree(item); | 
 | 	    cur = end; | 
 | 	} while ((ret == 0) && (*cur != 0)); | 
 |     } | 
 |  | 
 |     return (ret); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt, | 
 | 			     xmlSchemaIDCPtr idc, | 
 | 			     xmlSchemaIDCSelectPtr selector, | 
 | 			     xmlAttrPtr attr, | 
 | 			     int isField) | 
 | { | 
 |     xmlNodePtr node; | 
 |  | 
 |     /* | 
 |     * c-selector-xpath: | 
 |     * Schema Component Constraint: Selector Value OK | 
 |     * | 
 |     * TODO: 1 The {selector} must be a valid XPath expression, as defined | 
 |     * in [XPath]. | 
 |     */ | 
 |     if (selector == NULL) { | 
 | 	xmlSchemaPErr(ctxt, idc->node, | 
 | 	    XML_SCHEMAP_INTERNAL, | 
 | 	    "Internal error: xmlSchemaCheckCSelectorXPath, " | 
 | 	    "the selector is not specified.\n", NULL, NULL); | 
 | 	return (-1); | 
 |     } | 
 |     if (attr == NULL) | 
 | 	node = idc->node; | 
 |     else | 
 | 	node = (xmlNodePtr) attr; | 
 |     if (selector->xpath == NULL) { | 
 | 	xmlSchemaPCustomErr(ctxt, | 
 | 	    /* TODO: Adjust error code. */ | 
 | 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | 
 | 	    NULL, node, | 
 | 	    "The XPath expression of the selector is not valid", NULL); | 
 | 	return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE); | 
 |     } else { | 
 | 	const xmlChar **nsArray = NULL; | 
 | 	xmlNsPtr *nsList = NULL; | 
 | 	/* | 
 | 	* Compile the XPath expression. | 
 | 	*/ | 
 | 	/* | 
 | 	* TODO: We need the array of in-scope namespaces for compilation. | 
 | 	* TODO: Call xmlPatterncompile with different options for selector/ | 
 | 	* field. | 
 | 	*/ | 
 | 	if (attr == NULL) | 
 | 	    nsList = NULL; | 
 | 	else | 
 | 	    nsList = xmlGetNsList(attr->doc, attr->parent); | 
 | 	/* | 
 | 	* Build an array of prefixes and namespaces. | 
 | 	*/ | 
 | 	if (nsList != NULL) { | 
 | 	    int i, count = 0; | 
 |  | 
 | 	    for (i = 0; nsList[i] != NULL; i++) | 
 | 		count++; | 
 |  | 
 | 	    nsArray = (const xmlChar **) xmlMalloc( | 
 | 		(count * 2 + 1) * sizeof(const xmlChar *)); | 
 | 	    if (nsArray == NULL) { | 
 | 		xmlSchemaPErrMemory(ctxt, "allocating a namespace array", | 
 | 		    NULL); | 
 | 		xmlFree(nsList); | 
 | 		return (-1); | 
 | 	    } | 
 | 	    for (i = 0; i < count; i++) { | 
 | 		nsArray[2 * i] = nsList[i]->href; | 
 | 		nsArray[2 * i + 1] = nsList[i]->prefix; | 
 | 	    } | 
 | 	    nsArray[count * 2] = NULL; | 
 | 	    xmlFree(nsList); | 
 | 	} | 
 | 	/* | 
 | 	* TODO: Differentiate between "selector" and "field". | 
 | 	*/ | 
 | 	if (isField) | 
 | 	    selector->xpathComp = (void *) xmlPatterncompile(selector->xpath, | 
 | 		NULL, XML_PATTERN_XSFIELD, nsArray); | 
 | 	else | 
 | 	    selector->xpathComp = (void *) xmlPatterncompile(selector->xpath, | 
 | 		NULL, XML_PATTERN_XSSEL, nsArray); | 
 | 	if (nsArray != NULL) | 
 | 	    xmlFree((xmlChar **) nsArray); | 
 |  | 
 | 	if (selector->xpathComp == NULL) { | 
 | 	    xmlSchemaPCustomErr(ctxt, | 
 | 		/* TODO: Adjust error code? */ | 
 | 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | 
 | 		NULL, node, | 
 | 		"The XPath expression '%s' could not be " | 
 | 		"compiled", selector->xpath); | 
 | 	    return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE); | 
 | 	} | 
 |     } | 
 |     return (0); | 
 | } | 
 |  | 
 | #define ADD_ANNOTATION(annot)   \ | 
 |     xmlSchemaAnnotPtr cur = item->annot; \ | 
 |     if (item->annot == NULL) {  \ | 
 | 	item->annot = annot;    \ | 
 | 	return (annot);         \ | 
 |     }                           \ | 
 |     cur = item->annot;          \ | 
 |     if (cur->next != NULL) {    \ | 
 | 	cur = cur->next;	\ | 
 |     }                           \ | 
 |     cur->next = annot; | 
 |  | 
 | /** | 
 |  * xmlSchemaAssignAnnotation: | 
 |  * @item: the schema component | 
 |  * @annot: the annotation | 
 |  * | 
 |  * Adds the annotation to the given schema component. | 
 |  * | 
 |  * Returns the given annotaion. | 
 |  */ | 
 | static xmlSchemaAnnotPtr | 
 | xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem, | 
 | 		       xmlSchemaAnnotPtr annot) | 
 | { | 
 |     if ((annItem == NULL) || (annot == NULL)) | 
 | 	return (NULL); | 
 |     switch (annItem->type) { | 
 | 	case XML_SCHEMA_TYPE_ELEMENT: { | 
 | 		xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem; | 
 | 		ADD_ANNOTATION(annot) | 
 | 	    } | 
 | 	    break; | 
 | 	case XML_SCHEMA_TYPE_ATTRIBUTE: { | 
 | 		xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem; | 
 | 		ADD_ANNOTATION(annot) | 
 | 	    } | 
 | 	    break; | 
 | 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE: | 
 | 	case XML_SCHEMA_TYPE_ANY: { | 
 | 		xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem; | 
 | 		ADD_ANNOTATION(annot) | 
 | 	    } | 
 | 	    break; | 
 | 	case XML_SCHEMA_TYPE_PARTICLE: | 
 | 	case XML_SCHEMA_TYPE_IDC_KEY: | 
 | 	case XML_SCHEMA_TYPE_IDC_KEYREF: | 
 | 	case XML_SCHEMA_TYPE_IDC_UNIQUE: { | 
 | 		xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem; | 
 | 		ADD_ANNOTATION(annot) | 
 | 	    } | 
 | 	    break; | 
 | 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: { | 
 | 		xmlSchemaAttributeGroupPtr item = | 
 | 		    (xmlSchemaAttributeGroupPtr) annItem; | 
 | 		ADD_ANNOTATION(annot) | 
 | 	    } | 
 | 	    break; | 
 | 	case XML_SCHEMA_TYPE_NOTATION: { | 
 | 		xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem; | 
 | 		ADD_ANNOTATION(annot) | 
 | 	    } | 
 | 	    break; | 
 | 	case XML_SCHEMA_FACET_MININCLUSIVE: | 
 | 	case XML_SCHEMA_FACET_MINEXCLUSIVE: | 
 | 	case XML_SCHEMA_FACET_MAXINCLUSIVE: | 
 | 	case XML_SCHEMA_FACET_MAXEXCLUSIVE: | 
 | 	case XML_SCHEMA_FACET_TOTALDIGITS: | 
 | 	case XML_SCHEMA_FACET_FRACTIONDIGITS: | 
 | 	case XML_SCHEMA_FACET_PATTERN: | 
 | 	case XML_SCHEMA_FACET_ENUMERATION: | 
 | 	case XML_SCHEMA_FACET_WHITESPACE: | 
 | 	case XML_SCHEMA_FACET_LENGTH: | 
 | 	case XML_SCHEMA_FACET_MAXLENGTH: | 
 | 	case XML_SCHEMA_FACET_MINLENGTH: { | 
 | 		xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem; | 
 | 		ADD_ANNOTATION(annot) | 
 | 	    } | 
 | 	    break; | 
 | 	case XML_SCHEMA_TYPE_SIMPLE: | 
 | 	case XML_SCHEMA_TYPE_COMPLEX: { | 
 | 		xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem; | 
 | 		ADD_ANNOTATION(annot) | 
 | 	    } | 
 | 	    break; | 
 | 	case XML_SCHEMA_TYPE_GROUP: { | 
 | 		xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem; | 
 | 		ADD_ANNOTATION(annot) | 
 | 	    } | 
 | 	    break; | 
 | 	case XML_SCHEMA_TYPE_SEQUENCE: | 
 | 	case XML_SCHEMA_TYPE_CHOICE: | 
 | 	case XML_SCHEMA_TYPE_ALL: { | 
 | 		xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem; | 
 | 		ADD_ANNOTATION(annot) | 
 | 	    } | 
 | 	    break; | 
 | 	default: | 
 | 	     xmlSchemaPCustomErr(NULL, | 
 | 		XML_SCHEMAP_INTERNAL, | 
 | 		NULL, NULL, | 
 | 		"Internal error: xmlSchemaAddAnnotation, " | 
 | 		"The item is not a annotated schema component", NULL); | 
 | 	     break; | 
 |     } | 
 |     return (annot); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaParseIDCSelectorAndField: | 
 |  * @ctxt:  a schema validation context | 
 |  * @schema:  the schema being built | 
 |  * @node:  a subtree containing XML Schema informations | 
 |  * | 
 |  * Parses a XML Schema identity-contraint definition's | 
 |  * <selector> and <field> elements. | 
 |  * | 
 |  * Returns the parsed identity-constraint definition. | 
 |  */ | 
 | static xmlSchemaIDCSelectPtr | 
 | xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt, | 
 | 			  xmlSchemaIDCPtr idc, | 
 | 			  xmlNodePtr node, | 
 | 			  int isField) | 
 | { | 
 |     xmlSchemaIDCSelectPtr item; | 
 |     xmlNodePtr child = NULL; | 
 |     xmlAttrPtr attr; | 
 |  | 
 |     /* | 
 |     * Check for illegal attributes. | 
 |     */ | 
 |     attr = node->properties; | 
 |     while (attr != NULL) { | 
 | 	if (attr->ns == NULL) { | 
 | 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && | 
 | 		(!xmlStrEqual(attr->name, BAD_CAST "xpath"))) { | 
 | 		xmlSchemaPIllegalAttrErr(ctxt, | 
 | 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	    } | 
 | 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | 
 | 	    xmlSchemaPIllegalAttrErr(ctxt, | 
 | 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	} | 
 | 	attr = attr->next; | 
 |     } | 
 |     /* | 
 |     * Create the item. | 
 |     */ | 
 |     item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect)); | 
 |     if (item == NULL) { | 
 |         xmlSchemaPErrMemory(ctxt, | 
 | 	    "allocating a 'selector' of an identity-constraint definition", | 
 | 	    NULL); | 
 |         return (NULL); | 
 |     } | 
 |     memset(item, 0, sizeof(xmlSchemaIDCSelect)); | 
 |     /* | 
 |     * Attribute "xpath" (mandatory). | 
 |     */ | 
 |     attr = xmlSchemaGetPropNode(node, "xpath"); | 
 |     if (attr == NULL) { | 
 |     	xmlSchemaPMissingAttrErr(ctxt, | 
 | 	    XML_SCHEMAP_S4S_ATTR_MISSING, | 
 | 	    NULL, node, | 
 | 	    "name", NULL); | 
 |     } else { | 
 | 	item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); | 
 | 	/* | 
 | 	* URGENT TODO: "field"s have an other syntax than "selector"s. | 
 | 	*/ | 
 |  | 
 | 	if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr, | 
 | 	    isField) == -1) { | 
 | 	    xmlSchemaPErr(ctxt, | 
 | 		(xmlNodePtr) attr, | 
 | 		XML_SCHEMAP_INTERNAL, | 
 | 		"Internal error: xmlSchemaParseIDCSelectorAndField, " | 
 | 		"validating the XPath expression of a IDC selector.\n", | 
 | 		NULL, NULL); | 
 | 	} | 
 |  | 
 |     } | 
 |     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | 
 |     /* | 
 |     * And now for the children... | 
 |     */ | 
 |     child = node->children; | 
 |     if (IS_SCHEMA(child, "annotation")) { | 
 | 	/* | 
 | 	* Add the annotation to the parent IDC. | 
 | 	*/ | 
 | 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc, | 
 | 	    xmlSchemaParseAnnotation(ctxt, child, 1)); | 
 | 	child = child->next; | 
 |     } | 
 |     if (child != NULL) { | 
 | 	xmlSchemaPContentErr(ctxt, | 
 | 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | 
 | 	    NULL, node, child, | 
 | 	    NULL, "(annotation?)"); | 
 |     } | 
 |  | 
 |     return (item); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaParseIDC: | 
 |  * @ctxt:  a schema validation context | 
 |  * @schema:  the schema being built | 
 |  * @node:  a subtree containing XML Schema informations | 
 |  * | 
 |  * Parses a XML Schema identity-contraint definition. | 
 |  * | 
 |  * Returns the parsed identity-constraint definition. | 
 |  */ | 
 | static xmlSchemaIDCPtr | 
 | xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt, | 
 | 		  xmlSchemaPtr schema, | 
 | 		  xmlNodePtr node, | 
 | 		  xmlSchemaTypeType idcCategory, | 
 | 		  const xmlChar *targetNamespace) | 
 | { | 
 |     xmlSchemaIDCPtr item = NULL; | 
 |     xmlNodePtr child = NULL; | 
 |     xmlAttrPtr attr; | 
 |     const xmlChar *name = NULL; | 
 |     xmlSchemaIDCSelectPtr field = NULL, lastField = NULL; | 
 |  | 
 |     /* | 
 |     * Check for illegal attributes. | 
 |     */ | 
 |     attr = node->properties; | 
 |     while (attr != NULL) { | 
 | 	if (attr->ns == NULL) { | 
 | 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && | 
 | 		(!xmlStrEqual(attr->name, BAD_CAST "name")) && | 
 | 		((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) || | 
 | 		 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) { | 
 | 		xmlSchemaPIllegalAttrErr(ctxt, | 
 | 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	    } | 
 | 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | 
 | 	    xmlSchemaPIllegalAttrErr(ctxt, | 
 | 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	} | 
 | 	attr = attr->next; | 
 |     } | 
 |     /* | 
 |     * Attribute "name" (mandatory). | 
 |     */ | 
 |     attr = xmlSchemaGetPropNode(node, "name"); | 
 |     if (attr == NULL) { | 
 | 	xmlSchemaPMissingAttrErr(ctxt, | 
 | 	    XML_SCHEMAP_S4S_ATTR_MISSING, | 
 | 	    NULL, node, | 
 | 	    "name", NULL); | 
 | 	return (NULL); | 
 |     } else if (xmlSchemaPValAttrNode(ctxt, | 
 | 	NULL, attr, | 
 | 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) { | 
 | 	return (NULL); | 
 |     } | 
 |     /* Create the component. */ | 
 |     item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace, | 
 | 	idcCategory, node); | 
 |     if (item == NULL) | 
 | 	return(NULL); | 
 |  | 
 |     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | 
 |     if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) { | 
 | 	/* | 
 | 	* Attribute "refer" (mandatory). | 
 | 	*/ | 
 | 	attr = xmlSchemaGetPropNode(node, "refer"); | 
 | 	if (attr == NULL) { | 
 | 	    xmlSchemaPMissingAttrErr(ctxt, | 
 | 		XML_SCHEMAP_S4S_ATTR_MISSING, | 
 | 		NULL, node, | 
 | 		"refer", NULL); | 
 | 	} else { | 
 | 	    /* | 
 | 	    * Create a reference item. | 
 | 	    */ | 
 | 	    item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY, | 
 | 		NULL, NULL); | 
 | 	    if (item->ref == NULL) | 
 | 		return (NULL); | 
 | 	    xmlSchemaPValAttrNodeQName(ctxt, schema, | 
 | 		NULL, attr, | 
 | 		&(item->ref->targetNamespace), | 
 | 		&(item->ref->name)); | 
 | 	    xmlSchemaCheckReference(ctxt, schema, node, attr, | 
 | 		item->ref->targetNamespace); | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * And now for the children... | 
 |     */ | 
 |     child = node->children; | 
 |     if (IS_SCHEMA(child, "annotation")) { | 
 | 	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1); | 
 | 	child = child->next; | 
 |     } | 
 |     if (child == NULL) { | 
 | 	xmlSchemaPContentErr(ctxt, | 
 | 		XML_SCHEMAP_S4S_ELEM_MISSING, | 
 | 		NULL, node, child, | 
 | 		"A child element is missing", | 
 | 		"(annotation?, (selector, field+))"); | 
 |     } | 
 |     /* | 
 |     * Child element <selector>. | 
 |     */ | 
 |     if (IS_SCHEMA(child, "selector")) { | 
 | 	item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, | 
 | 	    item, child, 0); | 
 | 	child = child->next; | 
 | 	/* | 
 | 	* Child elements <field>. | 
 | 	*/ | 
 | 	if (IS_SCHEMA(child, "field")) { | 
 | 	    do { | 
 | 		field = xmlSchemaParseIDCSelectorAndField(ctxt, | 
 | 		    item, child, 1); | 
 | 		if (field != NULL) { | 
 | 		    field->index = item->nbFields; | 
 | 		    item->nbFields++; | 
 | 		    if (lastField != NULL) | 
 | 			lastField->next = field; | 
 | 		    else | 
 | 			item->fields = field; | 
 | 		    lastField = field; | 
 | 		} | 
 | 		child = child->next; | 
 | 	    } while (IS_SCHEMA(child, "field")); | 
 | 	} else { | 
 | 	    xmlSchemaPContentErr(ctxt, | 
 | 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | 
 | 		NULL, node, child, | 
 | 		NULL, "(annotation?, (selector, field+))"); | 
 | 	} | 
 |     } | 
 |     if (child != NULL) { | 
 | 	xmlSchemaPContentErr(ctxt, | 
 | 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | 
 | 	    NULL, node, child, | 
 | 	    NULL, "(annotation?, (selector, field+))"); | 
 |     } | 
 |  | 
 |     return (item); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaParseElement: | 
 |  * @ctxt:  a schema validation context | 
 |  * @schema:  the schema being built | 
 |  * @node:  a subtree containing XML Schema informations | 
 |  * @topLevel: indicates if this is global declaration | 
 |  * | 
 |  * Parses a XML schema element declaration. | 
 |  * *WARNING* this interface is highly subject to change | 
 |  * | 
 |  * Returns the element declaration or a particle; NULL in case | 
 |  * of an error or if the particle has minOccurs==maxOccurs==0. | 
 |  */ | 
 | static xmlSchemaBasicItemPtr | 
 | xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | 
 |                       xmlNodePtr node, int *isElemRef, int topLevel) | 
 | { | 
 |     xmlSchemaElementPtr decl = NULL; | 
 |     xmlSchemaParticlePtr particle = NULL; | 
 |     xmlSchemaAnnotPtr annot = NULL; | 
 |     xmlNodePtr child = NULL; | 
 |     xmlAttrPtr attr, nameAttr; | 
 |     int min, max, isRef = 0; | 
 |     xmlChar *des = NULL; | 
 |  | 
 |     /* 3.3.3 Constraints on XML Representations of Element Declarations */ | 
 |     /* TODO: Complete implementation of 3.3.6 */ | 
 |  | 
 |     if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) | 
 |         return (NULL); | 
 |  | 
 |     if (isElemRef != NULL) | 
 | 	*isElemRef = 0; | 
 |     /* | 
 |     * If we get a "ref" attribute on a local <element> we will assume it's | 
 |     * a reference - even if there's a "name" attribute; this seems to be more | 
 |     * robust. | 
 |     */ | 
 |     nameAttr = xmlSchemaGetPropNode(node, "name"); | 
 |     attr = xmlSchemaGetPropNode(node, "ref"); | 
 |     if ((topLevel) || (attr == NULL)) { | 
 | 	if (nameAttr == NULL) { | 
 | 	    xmlSchemaPMissingAttrErr(ctxt, | 
 | 		XML_SCHEMAP_S4S_ATTR_MISSING, | 
 | 		NULL, node, "name", NULL); | 
 | 	    return (NULL); | 
 | 	} | 
 |     } else | 
 | 	isRef = 1; | 
 |  | 
 |     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | 
 |     child = node->children; | 
 |     if (IS_SCHEMA(child, "annotation")) { | 
 | 	annot = xmlSchemaParseAnnotation(ctxt, child, 1); | 
 | 	child = child->next; | 
 |     } | 
 |     /* | 
 |     * Skip particle part if a global declaration. | 
 |     */ | 
 |     if (topLevel) | 
 | 	goto declaration_part; | 
 |     /* | 
 |     * The particle part ================================================== | 
 |     */ | 
 |     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger"); | 
 |     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)"); | 
 |     xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max); | 
 |     particle = xmlSchemaAddParticle(ctxt, node, min, max); | 
 |     if (particle == NULL) | 
 | 	goto return_null; | 
 |  | 
 |     /* ret->flags |= XML_SCHEMAS_ELEM_REF; */ | 
 |  | 
 |     if (isRef) { | 
 | 	const xmlChar *refNs = NULL, *ref = NULL; | 
 | 	xmlSchemaQNameRefPtr refer = NULL; | 
 | 	/* | 
 | 	* The reference part ============================================= | 
 | 	*/ | 
 | 	if (isElemRef != NULL) | 
 | 	    *isElemRef = 1; | 
 |  | 
 | 	xmlSchemaPValAttrNodeQName(ctxt, schema, | 
 | 	    NULL, attr, &refNs, &ref); | 
 | 	xmlSchemaCheckReference(ctxt, schema, node, attr, refNs); | 
 | 	/* | 
 | 	* SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both" | 
 | 	*/ | 
 | 	if (nameAttr != NULL) { | 
 | 	    xmlSchemaPMutualExclAttrErr(ctxt, | 
 | 		XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name"); | 
 | 	} | 
 | 	/* | 
 | 	* Check for illegal attributes. | 
 | 	*/ | 
 | 	attr = node->properties; | 
 | 	while (attr != NULL) { | 
 | 	    if (attr->ns == NULL) { | 
 | 		if (xmlStrEqual(attr->name, BAD_CAST "ref") || | 
 | 		    xmlStrEqual(attr->name, BAD_CAST "name") || | 
 | 		    xmlStrEqual(attr->name, BAD_CAST "id") || | 
 | 		    xmlStrEqual(attr->name, BAD_CAST "maxOccurs") || | 
 | 		    xmlStrEqual(attr->name, BAD_CAST "minOccurs")) | 
 | 		{ | 
 | 		    attr = attr->next; | 
 | 		    continue; | 
 | 		} else { | 
 | 		    /* SPEC (3.3.3 : 2.2) */ | 
 | 		    xmlSchemaPCustomAttrErr(ctxt, | 
 | 			XML_SCHEMAP_SRC_ELEMENT_2_2, | 
 | 			NULL, NULL, attr, | 
 | 			"Only the attributes 'minOccurs', 'maxOccurs' and " | 
 | 			"'id' are allowed in addition to 'ref'"); | 
 | 		    break; | 
 | 		} | 
 | 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | 
 | 		xmlSchemaPIllegalAttrErr(ctxt, | 
 | 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	    } | 
 | 	    attr = attr->next; | 
 | 	} | 
 | 	/* | 
 | 	* No children except <annotation> expected. | 
 | 	*/ | 
 | 	if (child != NULL) { | 
 | 	    xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | 
 | 		NULL, node, child, NULL, "(annotation?)"); | 
 | 	} | 
 | 	if ((min == 0) && (max == 0)) | 
 | 	    goto return_null; | 
 | 	/* | 
 | 	* Create the reference item and attach it to the particle. | 
 | 	*/ | 
 | 	refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT, | 
 | 	    ref, refNs); | 
 | 	if (refer == NULL) | 
 | 	    goto return_null; | 
 | 	particle->children = (xmlSchemaTreeItemPtr) refer; | 
 | 	particle->annot = annot; | 
 | 	/* | 
 | 	* Add the particle to pending components, since the reference | 
 | 	* need to be resolved. | 
 | 	*/ | 
 | 	WXS_ADD_PENDING(ctxt, particle); | 
 | 	return ((xmlSchemaBasicItemPtr) particle); | 
 |     } | 
 |     /* | 
 |     * The declaration part =============================================== | 
 |     */ | 
 | declaration_part: | 
 |     { | 
 | 	const xmlChar *ns = NULL, *fixed, *name, *attrValue; | 
 | 	xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL; | 
 |  | 
 | 	if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr, | 
 | 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) | 
 | 	    goto return_null; | 
 | 	/* | 
 | 	* Evaluate the target namespace. | 
 | 	*/ | 
 | 	if (topLevel) { | 
 | 	    ns = ctxt->targetNamespace; | 
 | 	} else { | 
 | 	    attr = xmlSchemaGetPropNode(node, "form"); | 
 | 	    if (attr != NULL) { | 
 | 		attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); | 
 | 		if (xmlStrEqual(attrValue, BAD_CAST "qualified")) { | 
 | 		    ns = ctxt->targetNamespace; | 
 | 		} else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) { | 
 | 		    xmlSchemaPSimpleTypeErr(ctxt, | 
 | 			XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | 
 | 			NULL, (xmlNodePtr) attr, | 
 | 			NULL, "(qualified | unqualified)", | 
 | 			attrValue, NULL, NULL, NULL); | 
 | 		} | 
 | 	    } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM) | 
 | 		ns = ctxt->targetNamespace; | 
 | 	} | 
 | 	decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel); | 
 | 	if (decl == NULL) { | 
 | 	    goto return_null; | 
 | 	} | 
 | 	/* | 
 | 	* Check for illegal attributes. | 
 | 	*/ | 
 | 	attr = node->properties; | 
 | 	while (attr != NULL) { | 
 | 	    if (attr->ns == NULL) { | 
 | 		if ((!xmlStrEqual(attr->name, BAD_CAST "name")) && | 
 | 		    (!xmlStrEqual(attr->name, BAD_CAST "type")) && | 
 | 		    (!xmlStrEqual(attr->name, BAD_CAST "id")) && | 
 | 		    (!xmlStrEqual(attr->name, BAD_CAST "default")) && | 
 | 		    (!xmlStrEqual(attr->name, BAD_CAST "fixed")) && | 
 | 		    (!xmlStrEqual(attr->name, BAD_CAST "block")) && | 
 | 		    (!xmlStrEqual(attr->name, BAD_CAST "nillable"))) | 
 | 		{ | 
 | 		    if (topLevel == 0) { | 
 | 			if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) && | 
 | 			    (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) && | 
 | 			    (!xmlStrEqual(attr->name, BAD_CAST "form"))) | 
 | 			{ | 
 | 			    xmlSchemaPIllegalAttrErr(ctxt, | 
 | 				XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 			} | 
 | 		    } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) && | 
 | 			(!xmlStrEqual(attr->name, BAD_CAST "abstract")) && | 
 | 			(!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) { | 
 |  | 
 | 			xmlSchemaPIllegalAttrErr(ctxt, | 
 | 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 		    } | 
 | 		} | 
 | 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | 
 |  | 
 | 		xmlSchemaPIllegalAttrErr(ctxt, | 
 | 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	    } | 
 | 	    attr = attr->next; | 
 | 	} | 
 | 	/* | 
 | 	* Extract/validate attributes. | 
 | 	*/ | 
 | 	if (topLevel) { | 
 | 	    /* | 
 | 	    * Process top attributes of global element declarations here. | 
 | 	    */ | 
 | 	    decl->flags |= XML_SCHEMAS_ELEM_GLOBAL; | 
 | 	    decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL; | 
 | 	    xmlSchemaPValAttrQName(ctxt, schema, | 
 | 		NULL, node, "substitutionGroup", | 
 | 		&(decl->substGroupNs), &(decl->substGroup)); | 
 | 	    if (xmlGetBooleanProp(ctxt, node, "abstract", 0)) | 
 | 		decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT; | 
 | 	    /* | 
 | 	    * Attribute "final". | 
 | 	    */ | 
 | 	    attr = xmlSchemaGetPropNode(node, "final"); | 
 | 	    if (attr == NULL) { | 
 | 		if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION) | 
 | 		    decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION; | 
 | 		if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION) | 
 | 		    decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION; | 
 | 	    } else { | 
 | 		attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); | 
 | 		if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags), | 
 | 		    -1, | 
 | 		    XML_SCHEMAS_ELEM_FINAL_EXTENSION, | 
 | 		    XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) { | 
 | 		    xmlSchemaPSimpleTypeErr(ctxt, | 
 | 			XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | 
 | 			NULL, (xmlNodePtr) attr, | 
 | 			NULL, "(#all | List of (extension | restriction))", | 
 | 			attrValue, NULL, NULL, NULL); | 
 | 		} | 
 | 	    } | 
 | 	} | 
 | 	/* | 
 | 	* Attribute "block". | 
 | 	*/ | 
 | 	attr = xmlSchemaGetPropNode(node, "block"); | 
 | 	if (attr == NULL) { | 
 | 	    /* | 
 | 	    * Apply default "block" values. | 
 | 	    */ | 
 | 	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION) | 
 | 		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION; | 
 | 	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION) | 
 | 		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION; | 
 | 	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION) | 
 | 		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION; | 
 | 	} else { | 
 | 	    attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); | 
 | 	    if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags), | 
 | 		-1, | 
 | 		XML_SCHEMAS_ELEM_BLOCK_EXTENSION, | 
 | 		XML_SCHEMAS_ELEM_BLOCK_RESTRICTION, | 
 | 		XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) { | 
 | 		xmlSchemaPSimpleTypeErr(ctxt, | 
 | 		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | 
 | 		    NULL, (xmlNodePtr) attr, | 
 | 		    NULL, "(#all | List of (extension | " | 
 | 		    "restriction | substitution))", attrValue, | 
 | 		    NULL, NULL, NULL); | 
 | 	    } | 
 | 	} | 
 | 	if (xmlGetBooleanProp(ctxt, node, "nillable", 0)) | 
 | 	    decl->flags |= XML_SCHEMAS_ELEM_NILLABLE; | 
 |  | 
 | 	attr = xmlSchemaGetPropNode(node, "type"); | 
 | 	if (attr != NULL) { | 
 | 	    xmlSchemaPValAttrNodeQName(ctxt, schema, | 
 | 		NULL, attr, | 
 | 		&(decl->namedTypeNs), &(decl->namedType)); | 
 | 	    xmlSchemaCheckReference(ctxt, schema, node, | 
 | 		attr, decl->namedTypeNs); | 
 | 	} | 
 | 	decl->value = xmlSchemaGetProp(ctxt, node, "default"); | 
 | 	attr = xmlSchemaGetPropNode(node, "fixed"); | 
 | 	if (attr != NULL) { | 
 | 	    fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); | 
 | 	    if (decl->value != NULL) { | 
 | 		/* | 
 | 		* 3.3.3 : 1 | 
 | 		* default and fixed must not both be present. | 
 | 		*/ | 
 | 		xmlSchemaPMutualExclAttrErr(ctxt, | 
 | 		    XML_SCHEMAP_SRC_ELEMENT_1, | 
 | 		    NULL, attr, "default", "fixed"); | 
 | 	    } else { | 
 | 		decl->flags |= XML_SCHEMAS_ELEM_FIXED; | 
 | 		decl->value = fixed; | 
 | 	    } | 
 | 	} | 
 | 	/* | 
 | 	* And now for the children... | 
 | 	*/ | 
 | 	if (IS_SCHEMA(child, "complexType")) { | 
 | 	    /* | 
 | 	    * 3.3.3 : 3 | 
 | 	    * "type" and either <simpleType> or <complexType> are mutually | 
 | 	    * exclusive | 
 | 	    */ | 
 | 	    if (decl->namedType != NULL) { | 
 | 		xmlSchemaPContentErr(ctxt, | 
 | 		    XML_SCHEMAP_SRC_ELEMENT_3, | 
 | 		    NULL, node, child, | 
 | 		    "The attribute 'type' and the <complexType> child are " | 
 | 		    "mutually exclusive", NULL); | 
 | 	    } else | 
 | 		WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0); | 
 | 	    child = child->next; | 
 | 	} else if (IS_SCHEMA(child, "simpleType")) { | 
 | 	    /* | 
 | 	    * 3.3.3 : 3 | 
 | 	    * "type" and either <simpleType> or <complexType> are | 
 | 	    * mutually exclusive | 
 | 	    */ | 
 | 	    if (decl->namedType != NULL) { | 
 | 		xmlSchemaPContentErr(ctxt, | 
 | 		    XML_SCHEMAP_SRC_ELEMENT_3, | 
 | 		    NULL, node, child, | 
 | 		    "The attribute 'type' and the <simpleType> child are " | 
 | 		    "mutually exclusive", NULL); | 
 | 	    } else | 
 | 		WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0); | 
 | 	    child = child->next; | 
 | 	} | 
 | 	while ((IS_SCHEMA(child, "unique")) || | 
 | 	    (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) { | 
 | 	    if (IS_SCHEMA(child, "unique")) { | 
 | 		curIDC = xmlSchemaParseIDC(ctxt, schema, child, | 
 | 		    XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace); | 
 | 	    } else if (IS_SCHEMA(child, "key")) { | 
 | 		curIDC = xmlSchemaParseIDC(ctxt, schema, child, | 
 | 		    XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace); | 
 | 	    } else if (IS_SCHEMA(child, "keyref")) { | 
 | 		curIDC = xmlSchemaParseIDC(ctxt, schema, child, | 
 | 		    XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace); | 
 | 	    } | 
 | 	    if (lastIDC != NULL) | 
 | 		lastIDC->next = curIDC; | 
 | 	    else | 
 | 		decl->idcs = (void *) curIDC; | 
 | 	    lastIDC = curIDC; | 
 | 	    child = child->next; | 
 | 	} | 
 | 	if (child != NULL) { | 
 | 	    xmlSchemaPContentErr(ctxt, | 
 | 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | 
 | 		NULL, node, child, | 
 | 		NULL, "(annotation?, ((simpleType | complexType)?, " | 
 | 		"(unique | key | keyref)*))"); | 
 | 	} | 
 | 	decl->annot = annot; | 
 |     } | 
 |     /* | 
 |     * NOTE: Element Declaration Representation OK 4. will be checked at a | 
 |     * different layer. | 
 |     */ | 
 |     FREE_AND_NULL(des) | 
 |     if (topLevel) | 
 | 	return ((xmlSchemaBasicItemPtr) decl); | 
 |     else { | 
 | 	particle->children = (xmlSchemaTreeItemPtr) decl; | 
 | 	return ((xmlSchemaBasicItemPtr) particle); | 
 |     } | 
 |  | 
 | return_null: | 
 |     FREE_AND_NULL(des); | 
 |     if (annot != NULL) { | 
 | 	if (particle != NULL) | 
 | 	    particle->annot = NULL; | 
 | 	if (decl != NULL) | 
 | 	    decl->annot = NULL; | 
 | 	xmlSchemaFreeAnnot(annot); | 
 |     } | 
 |     return (NULL); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaParseUnion: | 
 |  * @ctxt:  a schema validation context | 
 |  * @schema:  the schema being built | 
 |  * @node:  a subtree containing XML Schema informations | 
 |  * | 
 |  * parse a XML schema Union definition | 
 |  * *WARNING* this interface is highly subject to change | 
 |  * | 
 |  * Returns -1 in case of internal error, 0 in case of success and a positive | 
 |  * error code otherwise. | 
 |  */ | 
 | static int | 
 | xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | 
 |                     xmlNodePtr node) | 
 | { | 
 |     xmlSchemaTypePtr type; | 
 |     xmlNodePtr child = NULL; | 
 |     xmlAttrPtr attr; | 
 |     const xmlChar *cur = NULL; | 
 |  | 
 |     if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) | 
 |         return (-1); | 
 |     /* Not a component, don't create it. */ | 
 |     type = ctxt->ctxtType; | 
 |     /* | 
 |     * Mark the simple type as being of variety "union". | 
 |     */ | 
 |     type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION; | 
 |     /* | 
 |     * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen, | 
 |     * then the �simple ur-type definition�." | 
 |     */ | 
 |     type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE); | 
 |     /* | 
 |     * Check for illegal attributes. | 
 |     */ | 
 |     attr = node->properties; | 
 |     while (attr != NULL) { | 
 | 	if (attr->ns == NULL) { | 
 | 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && | 
 | 		(!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) { | 
 | 		xmlSchemaPIllegalAttrErr(ctxt, | 
 | 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	    } | 
 | 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | 
 | 	    xmlSchemaPIllegalAttrErr(ctxt, | 
 | 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	} | 
 | 	attr = attr->next; | 
 |     } | 
 |     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | 
 |     /* | 
 |     * Attribute "memberTypes". This is a list of QNames. | 
 |     * TODO: Check the value to contain anything. | 
 |     */ | 
 |     attr = xmlSchemaGetPropNode(node, "memberTypes"); | 
 |     if (attr != NULL) { | 
 | 	const xmlChar *end; | 
 | 	xmlChar *tmp; | 
 | 	const xmlChar *localName, *nsName; | 
 | 	xmlSchemaTypeLinkPtr link, lastLink = NULL; | 
 | 	xmlSchemaQNameRefPtr ref; | 
 |  | 
 | 	cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); | 
 | 	type->base = cur; | 
 | 	do { | 
 | 	    while (IS_BLANK_CH(*cur)) | 
 | 		cur++; | 
 | 	    end = cur; | 
 | 	    while ((*end != 0) && (!(IS_BLANK_CH(*end)))) | 
 | 		end++; | 
 | 	    if (end == cur) | 
 | 		break; | 
 | 	    tmp = xmlStrndup(cur, end - cur); | 
 | 	    if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema, | 
 | 		NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) { | 
 | 		/* | 
 | 		* Create the member type link. | 
 | 		*/ | 
 | 		link = (xmlSchemaTypeLinkPtr) | 
 | 		    xmlMalloc(sizeof(xmlSchemaTypeLink)); | 
 | 		if (link == NULL) { | 
 | 		    xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, " | 
 | 			"allocating a type link", NULL); | 
 | 		    return (-1); | 
 | 		} | 
 | 		link->type = NULL; | 
 | 		link->next = NULL; | 
 | 		if (lastLink == NULL) | 
 | 		    type->memberTypes = link; | 
 | 		else | 
 | 		    lastLink->next = link; | 
 | 		lastLink = link; | 
 | 		/* | 
 | 		* Create a reference item. | 
 | 		*/ | 
 | 		ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE, | 
 | 		    localName, nsName); | 
 | 		if (ref == NULL) { | 
 | 		    FREE_AND_NULL(tmp) | 
 | 		    return (-1); | 
 | 		} | 
 | 		/* | 
 | 		* Assign the reference to the link, it will be resolved | 
 | 		* later during fixup of the union simple type. | 
 | 		*/ | 
 | 		link->type = (xmlSchemaTypePtr) ref; | 
 | 	    } | 
 | 	    FREE_AND_NULL(tmp) | 
 | 	    cur = end; | 
 | 	} while (*cur != 0); | 
 |  | 
 |     } | 
 |     /* | 
 |     * And now for the children... | 
 |     */ | 
 |     child = node->children; | 
 |     if (IS_SCHEMA(child, "annotation")) { | 
 | 	/* | 
 | 	* Add the annotation to the simple type ancestor. | 
 | 	*/ | 
 | 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type, | 
 | 	    xmlSchemaParseAnnotation(ctxt, child, 1)); | 
 |         child = child->next; | 
 |     } | 
 |     if (IS_SCHEMA(child, "simpleType")) { | 
 | 	xmlSchemaTypePtr subtype, last = NULL; | 
 |  | 
 | 	/* | 
 | 	* Anchor the member types in the "subtypes" field of the | 
 | 	* simple type. | 
 | 	*/ | 
 | 	while (IS_SCHEMA(child, "simpleType")) { | 
 | 	    subtype = (xmlSchemaTypePtr) | 
 | 		xmlSchemaParseSimpleType(ctxt, schema, child, 0); | 
 | 	    if (subtype != NULL) { | 
 | 		if (last == NULL) { | 
 | 		    type->subtypes = subtype; | 
 | 		    last = subtype; | 
 | 		} else { | 
 | 		    last->next = subtype; | 
 | 		    last = subtype; | 
 | 		} | 
 | 		last->next = NULL; | 
 | 	    } | 
 | 	    child = child->next; | 
 | 	} | 
 |     } | 
 |     if (child != NULL) { | 
 | 	xmlSchemaPContentErr(ctxt, | 
 | 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | 
 | 	    NULL, node, child, NULL, "(annotation?, simpleType*)"); | 
 |     } | 
 |     if ((attr == NULL) && (type->subtypes == NULL)) { | 
 | 	 /* | 
 | 	* src-union-memberTypes-or-simpleTypes | 
 | 	* Either the memberTypes [attribute] of the <union> element must | 
 | 	* be non-empty or there must be at least one simpleType [child]. | 
 | 	*/ | 
 | 	xmlSchemaPCustomErr(ctxt, | 
 | 	    XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES, | 
 | 	    NULL, node, | 
 | 	    "Either the attribute 'memberTypes' or " | 
 | 	    "at least one <simpleType> child must be present", NULL); | 
 |     } | 
 |     return (0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaParseList: | 
 |  * @ctxt:  a schema validation context | 
 |  * @schema:  the schema being built | 
 |  * @node:  a subtree containing XML Schema informations | 
 |  * | 
 |  * parse a XML schema List definition | 
 |  * *WARNING* this interface is highly subject to change | 
 |  * | 
 |  * Returns -1 in case of error, 0 if the declaration is improper and | 
 |  *         1 in case of success. | 
 |  */ | 
 | static xmlSchemaTypePtr | 
 | xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | 
 |                    xmlNodePtr node) | 
 | { | 
 |     xmlSchemaTypePtr type; | 
 |     xmlNodePtr child = NULL; | 
 |     xmlAttrPtr attr; | 
 |  | 
 |     if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) | 
 |         return (NULL); | 
 |     /* Not a component, don't create it. */ | 
 |     type = ctxt->ctxtType; | 
 |     /* | 
 |     * Mark the type as being of variety "list". | 
 |     */ | 
 |     type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST; | 
 |     /* | 
 |     * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen, | 
 |     * then the �simple ur-type definition�." | 
 |     */ | 
 |     type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE); | 
 |     /* | 
 |     * Check for illegal attributes. | 
 |     */ | 
 |     attr = node->properties; | 
 |     while (attr != NULL) { | 
 | 	if (attr->ns == NULL) { | 
 | 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && | 
 | 		(!xmlStrEqual(attr->name, BAD_CAST "itemType"))) { | 
 | 		xmlSchemaPIllegalAttrErr(ctxt, | 
 | 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	    } | 
 | 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | 
 | 	    xmlSchemaPIllegalAttrErr(ctxt, | 
 | 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	} | 
 | 	attr = attr->next; | 
 |     } | 
 |  | 
 |     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | 
 |  | 
 |     /* | 
 |     * Attribute "itemType". NOTE that we will use the "ref" and "refNs" | 
 |     * fields for holding the reference to the itemType. | 
 |     * | 
 |     * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove | 
 |     * the "ref" fields. | 
 |     */ | 
 |     xmlSchemaPValAttrQName(ctxt, schema, NULL, | 
 | 	node, "itemType", &(type->baseNs), &(type->base)); | 
 |     /* | 
 |     * And now for the children... | 
 |     */ | 
 |     child = node->children; | 
 |     if (IS_SCHEMA(child, "annotation")) { | 
 | 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type, | 
 | 	    xmlSchemaParseAnnotation(ctxt, child, 1)); | 
 |         child = child->next; | 
 |     } | 
 |     if (IS_SCHEMA(child, "simpleType")) { | 
 | 	/* | 
 | 	* src-list-itemType-or-simpleType | 
 | 	* Either the itemType [attribute] or the <simpleType> [child] of | 
 | 	* the <list> element must be present, but not both. | 
 | 	*/ | 
 | 	if (type->base != NULL) { | 
 | 	    xmlSchemaPCustomErr(ctxt, | 
 | 		XML_SCHEMAP_SRC_SIMPLE_TYPE_1, | 
 | 		NULL, node, | 
 | 		"The attribute 'itemType' and the <simpleType> child " | 
 | 		"are mutually exclusive", NULL); | 
 | 	} else { | 
 | 	    type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0); | 
 | 	} | 
 |         child = child->next; | 
 |     } else if (type->base == NULL) { | 
 | 	xmlSchemaPCustomErr(ctxt, | 
 | 	    XML_SCHEMAP_SRC_SIMPLE_TYPE_1, | 
 | 	    NULL, node, | 
 | 	    "Either the attribute 'itemType' or the <simpleType> child " | 
 | 	    "must be present", NULL); | 
 |     } | 
 |     if (child != NULL) { | 
 | 	xmlSchemaPContentErr(ctxt, | 
 | 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | 
 | 	    NULL, node, child, NULL, "(annotation?, simpleType?)"); | 
 |     } | 
 |     if ((type->base == NULL) && | 
 | 	(type->subtypes == NULL) && | 
 | 	(xmlSchemaGetPropNode(node, "itemType") == NULL)) { | 
 | 	xmlSchemaPCustomErr(ctxt, | 
 | 	    XML_SCHEMAP_SRC_SIMPLE_TYPE_1, | 
 | 	    NULL, node, | 
 | 	    "Either the attribute 'itemType' or the <simpleType> child " | 
 | 	    "must be present", NULL); | 
 |     } | 
 |     return (NULL); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaParseSimpleType: | 
 |  * @ctxt:  a schema validation context | 
 |  * @schema:  the schema being built | 
 |  * @node:  a subtree containing XML Schema informations | 
 |  * | 
 |  * parse a XML schema Simple Type definition | 
 |  * *WARNING* this interface is highly subject to change | 
 |  * | 
 |  * Returns -1 in case of error, 0 if the declaration is improper and | 
 |  * 1 in case of success. | 
 |  */ | 
 | static xmlSchemaTypePtr | 
 | xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | 
 |                          xmlNodePtr node, int topLevel) | 
 | { | 
 |     xmlSchemaTypePtr type, oldCtxtType; | 
 |     xmlNodePtr child = NULL; | 
 |     const xmlChar *attrValue = NULL; | 
 |     xmlAttrPtr attr; | 
 |     int hasRestriction = 0; | 
 |  | 
 |     if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) | 
 |         return (NULL); | 
 |  | 
 |     if (topLevel) { | 
 | 	attr = xmlSchemaGetPropNode(node, "name"); | 
 | 	if (attr == NULL) { | 
 | 	    xmlSchemaPMissingAttrErr(ctxt, | 
 | 		XML_SCHEMAP_S4S_ATTR_MISSING, | 
 | 		NULL, node, | 
 | 		"name", NULL); | 
 | 	    return (NULL); | 
 | 	} else { | 
 | 	    if (xmlSchemaPValAttrNode(ctxt, | 
 | 		NULL, attr, | 
 | 		xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) | 
 | 		return (NULL); | 
 | 	    /* | 
 | 	    * Skip built-in types. | 
 | 	    */ | 
 | 	    if (ctxt->isS4S) { | 
 | 		xmlSchemaTypePtr biType; | 
 |  | 
 | 		if (ctxt->isRedefine) { | 
 | 		    /* | 
 | 		    * REDEFINE: Disallow redefinition of built-in-types. | 
 | 		    * TODO: It seems that the spec does not say anything | 
 | 		    * about this case. | 
 | 		    */ | 
 | 		    xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE, | 
 | 			NULL, node, | 
 | 			"Redefinition of built-in simple types is not " | 
 | 			"supported", NULL); | 
 | 		    return(NULL); | 
 | 		} | 
 | 		biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs); | 
 | 		if (biType != NULL) | 
 | 		    return (biType); | 
 | 	    } | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * TargetNamespace: | 
 |     * SPEC "The �actual value� of the targetNamespace [attribute] | 
 |     * of the <schema> ancestor element information item if present, | 
 |     * otherwise �absent�. | 
 |     */ | 
 |     if (topLevel == 0) { | 
 | #ifdef ENABLE_NAMED_LOCALS | 
 |         char buf[40]; | 
 | #endif | 
 | 	/* | 
 | 	* Parse as local simple type definition. | 
 | 	*/ | 
 | #ifdef ENABLE_NAMED_LOCALS | 
 |         snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1); | 
 | 	type = xmlSchemaAddType(ctxt, schema, | 
 | 	    XML_SCHEMA_TYPE_SIMPLE, | 
 | 	    xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1), | 
 | 	    ctxt->targetNamespace, node, 0); | 
 | #else | 
 | 	type = xmlSchemaAddType(ctxt, schema, | 
 | 	    XML_SCHEMA_TYPE_SIMPLE, | 
 | 	    NULL, ctxt->targetNamespace, node, 0); | 
 | #endif | 
 | 	if (type == NULL) | 
 | 	    return (NULL); | 
 | 	type->type = XML_SCHEMA_TYPE_SIMPLE; | 
 | 	type->contentType = XML_SCHEMA_CONTENT_SIMPLE; | 
 | 	/* | 
 | 	* Check for illegal attributes. | 
 | 	*/ | 
 | 	attr = node->properties; | 
 | 	while (attr != NULL) { | 
 | 	    if (attr->ns == NULL) { | 
 | 		if (!xmlStrEqual(attr->name, BAD_CAST "id")) { | 
 | 		    xmlSchemaPIllegalAttrErr(ctxt, | 
 | 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 		} | 
 | 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | 
 | 		    xmlSchemaPIllegalAttrErr(ctxt, | 
 | 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	    } | 
 | 	    attr = attr->next; | 
 | 	} | 
 |     } else { | 
 | 	/* | 
 | 	* Parse as global simple type definition. | 
 | 	* | 
 | 	* Note that attrValue is the value of the attribute "name" here. | 
 | 	*/ | 
 | 	type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE, | 
 | 	    attrValue, ctxt->targetNamespace, node, 1); | 
 | 	if (type == NULL) | 
 | 	    return (NULL); | 
 | 	type->type = XML_SCHEMA_TYPE_SIMPLE; | 
 | 	type->contentType = XML_SCHEMA_CONTENT_SIMPLE; | 
 | 	type->flags |= XML_SCHEMAS_TYPE_GLOBAL; | 
 | 	/* | 
 | 	* Check for illegal attributes. | 
 | 	*/ | 
 | 	attr = node->properties; | 
 | 	while (attr != NULL) { | 
 | 	    if (attr->ns == NULL) { | 
 | 		if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && | 
 | 		    (!xmlStrEqual(attr->name, BAD_CAST "name")) && | 
 | 		    (!xmlStrEqual(attr->name, BAD_CAST "final"))) { | 
 | 		    xmlSchemaPIllegalAttrErr(ctxt, | 
 | 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 		} | 
 | 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | 
 | 		xmlSchemaPIllegalAttrErr(ctxt, | 
 | 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	    } | 
 | 	    attr = attr->next; | 
 | 	} | 
 | 	/* | 
 | 	* Attribute "final". | 
 | 	*/ | 
 | 	attr = xmlSchemaGetPropNode(node, "final"); | 
 | 	if (attr == NULL) { | 
 | 	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION) | 
 | 		type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION; | 
 | 	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST) | 
 | 		type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST; | 
 | 	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION) | 
 | 		type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION; | 
 | 	} else { | 
 | 	    attrValue = xmlSchemaGetProp(ctxt, node, "final"); | 
 | 	    if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags), | 
 | 		-1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1, | 
 | 		XML_SCHEMAS_TYPE_FINAL_LIST, | 
 | 		XML_SCHEMAS_TYPE_FINAL_UNION) != 0) { | 
 |  | 
 | 		xmlSchemaPSimpleTypeErr(ctxt, | 
 | 		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | 
 | 		    WXS_BASIC_CAST type, (xmlNodePtr) attr, | 
 | 		    NULL, "(#all | List of (list | union | restriction)", | 
 | 		    attrValue, NULL, NULL, NULL); | 
 | 	    } | 
 | 	} | 
 |     } | 
 |     type->targetNamespace = ctxt->targetNamespace; | 
 |     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | 
 |     /* | 
 |     * And now for the children... | 
 |     */ | 
 |     oldCtxtType = ctxt->ctxtType; | 
 |  | 
 |     ctxt->ctxtType = type; | 
 |  | 
 |     child = node->children; | 
 |     if (IS_SCHEMA(child, "annotation")) { | 
 |         type->annot = xmlSchemaParseAnnotation(ctxt, child, 1); | 
 |         child = child->next; | 
 |     } | 
 |     if (child == NULL) { | 
 | 	xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING, | 
 | 	    NULL, node, child, NULL, | 
 | 	    "(annotation?, (restriction | list | union))"); | 
 |     } else if (IS_SCHEMA(child, "restriction")) { | 
 |         xmlSchemaParseRestriction(ctxt, schema, child, | 
 | 	    XML_SCHEMA_TYPE_SIMPLE); | 
 | 	hasRestriction = 1; | 
 |         child = child->next; | 
 |     } else if (IS_SCHEMA(child, "list")) { | 
 |         xmlSchemaParseList(ctxt, schema, child); | 
 |         child = child->next; | 
 |     } else if (IS_SCHEMA(child, "union")) { | 
 |         xmlSchemaParseUnion(ctxt, schema, child); | 
 |         child = child->next; | 
 |     } | 
 |     if (child != NULL) { | 
 | 	xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | 
 | 	    NULL, node, child, NULL, | 
 | 	    "(annotation?, (restriction | list | union))"); | 
 |     } | 
 |     /* | 
 |     * REDEFINE: SPEC src-redefine (5) | 
 |     * "Within the [children], each <simpleType> must have a | 
 |     * <restriction> among its [children] ... the �actual value� of whose | 
 |     * base [attribute] must be the same as the �actual value� of its own | 
 |     * name attribute plus target namespace;" | 
 |     */ | 
 |     if (topLevel && ctxt->isRedefine && (! hasRestriction)) { | 
 | 	xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE, | 
 | 	    NULL, node, "This is a redefinition, thus the " | 
 | 	    "<simpleType> must have a <restriction> child", NULL); | 
 |     } | 
 |  | 
 |     ctxt->ctxtType = oldCtxtType; | 
 |     return (type); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaParseModelGroupDefRef: | 
 |  * @ctxt:  the parser context | 
 |  * @schema: the schema being built | 
 |  * @node:  the node | 
 |  * | 
 |  * Parses a reference to a model group definition. | 
 |  * | 
 |  * We will return a particle component with a qname-component or | 
 |  * NULL in case of an error. | 
 |  */ | 
 | static xmlSchemaTreeItemPtr | 
 | xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt, | 
 | 			       xmlSchemaPtr schema, | 
 | 			       xmlNodePtr node) | 
 | { | 
 |     xmlSchemaParticlePtr item; | 
 |     xmlNodePtr child = NULL; | 
 |     xmlAttrPtr attr; | 
 |     const xmlChar *ref = NULL, *refNs = NULL; | 
 |     int min, max; | 
 |  | 
 |     if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) | 
 |         return (NULL); | 
 |  | 
 |     attr = xmlSchemaGetPropNode(node, "ref"); | 
 |     if (attr == NULL) { | 
 | 	xmlSchemaPMissingAttrErr(ctxt, | 
 | 	    XML_SCHEMAP_S4S_ATTR_MISSING, | 
 | 	    NULL, node, "ref", NULL); | 
 | 	return (NULL); | 
 |     } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL, | 
 | 	attr, &refNs, &ref) != 0) { | 
 | 	return (NULL); | 
 |     } | 
 |     xmlSchemaCheckReference(ctxt, schema, node, attr, refNs); | 
 |     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger"); | 
 |     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, | 
 | 	"(xs:nonNegativeInteger | unbounded)"); | 
 |     /* | 
 |     * Check for illegal attributes. | 
 |     */ | 
 |     attr = node->properties; | 
 |     while (attr != NULL) { | 
 | 	if (attr->ns == NULL) { | 
 | 	    if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) && | 
 | 		(!xmlStrEqual(attr->name, BAD_CAST "id")) && | 
 | 		(!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) && | 
 | 		(!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) { | 
 | 		xmlSchemaPIllegalAttrErr(ctxt, | 
 | 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	    } | 
 | 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | 
 | 	    xmlSchemaPIllegalAttrErr(ctxt, | 
 | 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	} | 
 | 	attr = attr->next; | 
 |     } | 
 |     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | 
 |     item = xmlSchemaAddParticle(ctxt, node, min, max); | 
 |     if (item == NULL) | 
 | 	return (NULL); | 
 |     /* | 
 |     * Create a qname-reference and set as the term; it will be substituted | 
 |     * for the model group after the reference has been resolved. | 
 |     */ | 
 |     item->children = (xmlSchemaTreeItemPtr) | 
 | 	xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs); | 
 |     xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max); | 
 |     /* | 
 |     * And now for the children... | 
 |     */ | 
 |     child = node->children; | 
 |     /* TODO: Is annotation even allowed for a model group reference? */ | 
 |     if (IS_SCHEMA(child, "annotation")) { | 
 | 	/* | 
 | 	* TODO: What to do exactly with the annotation? | 
 | 	*/ | 
 | 	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1); | 
 | 	child = child->next; | 
 |     } | 
 |     if (child != NULL) { | 
 | 	xmlSchemaPContentErr(ctxt, | 
 | 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | 
 | 	    NULL, node, child, NULL, | 
 | 	    "(annotation?)"); | 
 |     } | 
 |     /* | 
 |     * Corresponds to no component at all if minOccurs==maxOccurs==0. | 
 |     */ | 
 |     if ((min == 0) && (max == 0)) | 
 | 	return (NULL); | 
 |  | 
 |     return ((xmlSchemaTreeItemPtr) item); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaParseModelGroupDefinition: | 
 |  * @ctxt:  a schema validation context | 
 |  * @schema:  the schema being built | 
 |  * @node:  a subtree containing XML Schema informations | 
 |  * | 
 |  * Parses a XML schema model group definition. | 
 |  * | 
 |  * Note that the contraint src-redefine (6.2) can't be applied until | 
 |  * references have been resolved. So we will do this at the | 
 |  * component fixup level. | 
 |  * | 
 |  * *WARNING* this interface is highly subject to change | 
 |  * | 
 |  * Returns -1 in case of error, 0 if the declaration is improper and | 
 |  *         1 in case of success. | 
 |  */ | 
 | static xmlSchemaModelGroupDefPtr | 
 | xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt, | 
 | 				   xmlSchemaPtr schema, | 
 | 				   xmlNodePtr node) | 
 | { | 
 |     xmlSchemaModelGroupDefPtr item; | 
 |     xmlNodePtr child = NULL; | 
 |     xmlAttrPtr attr; | 
 |     const xmlChar *name; | 
 |  | 
 |     if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) | 
 |         return (NULL); | 
 |  | 
 |     attr = xmlSchemaGetPropNode(node, "name"); | 
 |     if (attr == NULL) { | 
 | 	xmlSchemaPMissingAttrErr(ctxt, | 
 | 	    XML_SCHEMAP_S4S_ATTR_MISSING, | 
 | 	    NULL, node, | 
 | 	    "name", NULL); | 
 | 	return (NULL); | 
 |     } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr, | 
 | 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) { | 
 | 	return (NULL); | 
 |     } | 
 |     item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name, | 
 | 	ctxt->targetNamespace, node); | 
 |     if (item == NULL) | 
 | 	return (NULL); | 
 |     /* | 
 |     * Check for illegal attributes. | 
 |     */ | 
 |     attr = node->properties; | 
 |     while (attr != NULL) { | 
 | 	if (attr->ns == NULL) { | 
 | 	    if ((!xmlStrEqual(attr->name, BAD_CAST "name")) && | 
 | 		(!xmlStrEqual(attr->name, BAD_CAST "id"))) { | 
 | 		xmlSchemaPIllegalAttrErr(ctxt, | 
 | 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	    } | 
 | 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | 
 | 	    xmlSchemaPIllegalAttrErr(ctxt, | 
 | 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	} | 
 | 	attr = attr->next; | 
 |     } | 
 |     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | 
 |     /* | 
 |     * And now for the children... | 
 |     */ | 
 |     child = node->children; | 
 |     if (IS_SCHEMA(child, "annotation")) { | 
 | 	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1); | 
 | 	child = child->next; | 
 |     } | 
 |     if (IS_SCHEMA(child, "all")) { | 
 | 	item->children = xmlSchemaParseModelGroup(ctxt, schema, child, | 
 | 	    XML_SCHEMA_TYPE_ALL, 0); | 
 | 	child = child->next; | 
 |     } else if (IS_SCHEMA(child, "choice")) { | 
 | 	item->children = xmlSchemaParseModelGroup(ctxt, schema, child, | 
 | 	    XML_SCHEMA_TYPE_CHOICE, 0); | 
 | 	child = child->next; | 
 |     } else if (IS_SCHEMA(child, "sequence")) { | 
 | 	item->children = xmlSchemaParseModelGroup(ctxt, schema, child, | 
 | 	    XML_SCHEMA_TYPE_SEQUENCE, 0); | 
 | 	child = child->next; | 
 |     } | 
 |  | 
 |  | 
 |  | 
 |     if (child != NULL) { | 
 | 	xmlSchemaPContentErr(ctxt, | 
 | 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | 
 | 	    NULL, node, child, NULL, | 
 | 	    "(annotation?, (all | choice | sequence)?)"); | 
 |     } | 
 |     return (item); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaCleanupDoc: | 
 |  * @ctxt:  a schema validation context | 
 |  * @node:  the root of the document. | 
 |  * | 
 |  * removes unwanted nodes in a schemas document tree | 
 |  */ | 
 | static void | 
 | xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root) | 
 | { | 
 |     xmlNodePtr delete, cur; | 
 |  | 
 |     if ((ctxt == NULL) || (root == NULL)) return; | 
 |  | 
 |     /* | 
 |      * Remove all the blank text nodes | 
 |      */ | 
 |     delete = NULL; | 
 |     cur = root; | 
 |     while (cur != NULL) { | 
 |         if (delete != NULL) { | 
 |             xmlUnlinkNode(delete); | 
 |             xmlFreeNode(delete); | 
 |             delete = NULL; | 
 |         } | 
 |         if (cur->type == XML_TEXT_NODE) { | 
 |             if (IS_BLANK_NODE(cur)) { | 
 |                 if (xmlNodeGetSpacePreserve(cur) != 1) { | 
 |                     delete = cur; | 
 |                 } | 
 |             } | 
 |         } else if ((cur->type != XML_ELEMENT_NODE) && | 
 |                    (cur->type != XML_CDATA_SECTION_NODE)) { | 
 |             delete = cur; | 
 |             goto skip_children; | 
 |         } | 
 |  | 
 |         /* | 
 |          * Skip to next node | 
 |          */ | 
 |         if (cur->children != NULL) { | 
 |             if ((cur->children->type != XML_ENTITY_DECL) && | 
 |                 (cur->children->type != XML_ENTITY_REF_NODE) && | 
 |                 (cur->children->type != XML_ENTITY_NODE)) { | 
 |                 cur = cur->children; | 
 |                 continue; | 
 |             } | 
 |         } | 
 |       skip_children: | 
 |         if (cur->next != NULL) { | 
 |             cur = cur->next; | 
 |             continue; | 
 |         } | 
 |  | 
 |         do { | 
 |             cur = cur->parent; | 
 |             if (cur == NULL) | 
 |                 break; | 
 |             if (cur == root) { | 
 |                 cur = NULL; | 
 |                 break; | 
 |             } | 
 |             if (cur->next != NULL) { | 
 |                 cur = cur->next; | 
 |                 break; | 
 |             } | 
 |         } while (cur != NULL); | 
 |     } | 
 |     if (delete != NULL) { | 
 |         xmlUnlinkNode(delete); | 
 |         xmlFreeNode(delete); | 
 |         delete = NULL; | 
 |     } | 
 | } | 
 |  | 
 |  | 
 | static void | 
 | xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema) | 
 | { | 
 |     if (schema->flags & XML_SCHEMAS_QUALIF_ELEM) | 
 | 	schema->flags ^= XML_SCHEMAS_QUALIF_ELEM; | 
 |  | 
 |     if (schema->flags & XML_SCHEMAS_QUALIF_ATTR) | 
 | 	schema->flags ^= XML_SCHEMAS_QUALIF_ATTR; | 
 |  | 
 |     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION) | 
 | 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION; | 
 |     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION) | 
 | 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION; | 
 |     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST) | 
 | 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST; | 
 |     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION) | 
 | 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION; | 
 |  | 
 |     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION) | 
 | 	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION; | 
 |     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION) | 
 | 	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION; | 
 |     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION) | 
 | 	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION; | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt, | 
 | 			     xmlSchemaPtr schema, | 
 | 			     xmlNodePtr node) | 
 | { | 
 |     xmlAttrPtr attr; | 
 |     const xmlChar *val; | 
 |     int res = 0, oldErrs = ctxt->nberrors; | 
 |  | 
 |     /* | 
 |     * Those flags should be moved to the parser context flags, | 
 |     * since they are not visible at the component level. I.e. | 
 |     * they are used if processing schema *documents* only. | 
 |     */ | 
 |     res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | 
 |     HFAILURE; | 
 |  | 
 |     /* | 
 |     * Since the version is of type xs:token, we won't bother to | 
 |     * check it. | 
 |     */ | 
 |     /* REMOVED: | 
 |     attr = xmlSchemaGetPropNode(node, "version"); | 
 |     if (attr != NULL) { | 
 | 	res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr, | 
 | 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val); | 
 | 	HFAILURE; | 
 |     } | 
 |     */ | 
 |     attr = xmlSchemaGetPropNode(node, "targetNamespace"); | 
 |     if (attr != NULL) { | 
 | 	res = xmlSchemaPValAttrNode(ctxt, NULL, attr, | 
 | 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL); | 
 | 	HFAILURE; | 
 | 	if (res != 0) { | 
 | 	    ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE; | 
 | 	    goto exit; | 
 | 	} | 
 |     } | 
 |     attr = xmlSchemaGetPropNode(node, "elementFormDefault"); | 
 |     if (attr != NULL) { | 
 | 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); | 
 | 	res = xmlSchemaPValAttrFormDefault(val, &schema->flags, | 
 | 	    XML_SCHEMAS_QUALIF_ELEM); | 
 | 	HFAILURE; | 
 | 	if (res != 0) { | 
 | 	    xmlSchemaPSimpleTypeErr(ctxt, | 
 | 		XML_SCHEMAP_ELEMFORMDEFAULT_VALUE, | 
 | 		NULL, (xmlNodePtr) attr, NULL, | 
 | 		"(qualified | unqualified)", val, NULL, NULL, NULL); | 
 | 	} | 
 |     } | 
 |     attr = xmlSchemaGetPropNode(node, "attributeFormDefault"); | 
 |     if (attr != NULL) { | 
 | 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); | 
 | 	res = xmlSchemaPValAttrFormDefault(val, &schema->flags, | 
 | 	    XML_SCHEMAS_QUALIF_ATTR); | 
 | 	HFAILURE; | 
 | 	if (res != 0) { | 
 | 	    xmlSchemaPSimpleTypeErr(ctxt, | 
 | 		XML_SCHEMAP_ATTRFORMDEFAULT_VALUE, | 
 | 		NULL, (xmlNodePtr) attr, NULL, | 
 | 		"(qualified | unqualified)", val, NULL, NULL, NULL); | 
 | 	} | 
 |     } | 
 |     attr = xmlSchemaGetPropNode(node, "finalDefault"); | 
 |     if (attr != NULL) { | 
 | 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); | 
 | 	res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1, | 
 | 	    XML_SCHEMAS_FINAL_DEFAULT_EXTENSION, | 
 | 	    XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION, | 
 | 	    -1, | 
 | 	    XML_SCHEMAS_FINAL_DEFAULT_LIST, | 
 | 	    XML_SCHEMAS_FINAL_DEFAULT_UNION); | 
 | 	HFAILURE; | 
 | 	if (res != 0) { | 
 | 	    xmlSchemaPSimpleTypeErr(ctxt, | 
 | 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | 
 | 		NULL, (xmlNodePtr) attr, NULL, | 
 | 		"(#all | List of (extension | restriction | list | union))", | 
 | 		val, NULL, NULL, NULL); | 
 | 	} | 
 |     } | 
 |     attr = xmlSchemaGetPropNode(node, "blockDefault"); | 
 |     if (attr != NULL) { | 
 | 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr); | 
 | 	res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1, | 
 | 	    XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION, | 
 | 	    XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION, | 
 | 	    XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1); | 
 | 	HFAILURE; | 
 | 	if (res != 0) { | 
 | 	    xmlSchemaPSimpleTypeErr(ctxt, | 
 | 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | 
 | 		NULL, (xmlNodePtr) attr, NULL, | 
 | 		"(#all | List of (extension | restriction | substitution))", | 
 | 		val, NULL, NULL, NULL); | 
 | 	} | 
 |     } | 
 |  | 
 | exit: | 
 |     if (oldErrs != ctxt->nberrors) | 
 | 	res = ctxt->err; | 
 |     return(res); | 
 | exit_failure: | 
 |     return(-1); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaParseSchemaTopLevel: | 
 |  * @ctxt:  a schema validation context | 
 |  * @schema:  the schemas | 
 |  * @nodes:  the list of top level nodes | 
 |  * | 
 |  * Returns the internal XML Schema structure built from the resource or | 
 |  *         NULL in case of error | 
 |  */ | 
 | static int | 
 | xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt, | 
 |                              xmlSchemaPtr schema, xmlNodePtr nodes) | 
 | { | 
 |     xmlNodePtr child; | 
 |     xmlSchemaAnnotPtr annot; | 
 |     int res = 0, oldErrs, tmpOldErrs; | 
 |  | 
 |     if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL)) | 
 |         return(-1); | 
 |  | 
 |     oldErrs = ctxt->nberrors; | 
 |     child = nodes; | 
 |     while ((IS_SCHEMA(child, "include")) || | 
 | 	   (IS_SCHEMA(child, "import")) || | 
 | 	   (IS_SCHEMA(child, "redefine")) || | 
 | 	   (IS_SCHEMA(child, "annotation"))) { | 
 | 	if (IS_SCHEMA(child, "annotation")) { | 
 | 	    annot = xmlSchemaParseAnnotation(ctxt, child, 1); | 
 | 	    if (schema->annot == NULL) | 
 | 		schema->annot = annot; | 
 | 	    else | 
 | 		xmlSchemaFreeAnnot(annot); | 
 | 	} else if (IS_SCHEMA(child, "import")) { | 
 | 	    tmpOldErrs = ctxt->nberrors; | 
 | 	    res = xmlSchemaParseImport(ctxt, schema, child); | 
 | 	    HFAILURE; | 
 | 	    HSTOP(ctxt); | 
 | 	    if (tmpOldErrs != ctxt->nberrors) | 
 | 		goto exit; | 
 | 	} else if (IS_SCHEMA(child, "include")) { | 
 | 	    tmpOldErrs = ctxt->nberrors; | 
 | 	    res = xmlSchemaParseInclude(ctxt, schema, child); | 
 | 	    HFAILURE; | 
 | 	    HSTOP(ctxt); | 
 | 	    if (tmpOldErrs != ctxt->nberrors) | 
 | 		goto exit; | 
 | 	} else if (IS_SCHEMA(child, "redefine")) { | 
 | 	    tmpOldErrs = ctxt->nberrors; | 
 | 	    res = xmlSchemaParseRedefine(ctxt, schema, child); | 
 | 	    HFAILURE; | 
 | 	    HSTOP(ctxt); | 
 | 	    if (tmpOldErrs != ctxt->nberrors) | 
 | 		goto exit; | 
 | 	} | 
 | 	child = child->next; | 
 |     } | 
 |     /* | 
 |     * URGENT TODO: Change the functions to return int results. | 
 |     * We need especially to catch internal errors. | 
 |     */ | 
 |     while (child != NULL) { | 
 | 	if (IS_SCHEMA(child, "complexType")) { | 
 | 	    xmlSchemaParseComplexType(ctxt, schema, child, 1); | 
 | 	    child = child->next; | 
 | 	} else if (IS_SCHEMA(child, "simpleType")) { | 
 | 	    xmlSchemaParseSimpleType(ctxt, schema, child, 1); | 
 | 	    child = child->next; | 
 | 	} else if (IS_SCHEMA(child, "element")) { | 
 | 	    xmlSchemaParseElement(ctxt, schema, child, NULL, 1); | 
 | 	    child = child->next; | 
 | 	} else if (IS_SCHEMA(child, "attribute")) { | 
 | 	    xmlSchemaParseGlobalAttribute(ctxt, schema, child); | 
 | 	    child = child->next; | 
 | 	} else if (IS_SCHEMA(child, "attributeGroup")) { | 
 | 	    xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child); | 
 | 	    child = child->next; | 
 | 	} else if (IS_SCHEMA(child, "group")) { | 
 | 	    xmlSchemaParseModelGroupDefinition(ctxt, schema, child); | 
 | 	    child = child->next; | 
 | 	} else if (IS_SCHEMA(child, "notation")) { | 
 | 	    xmlSchemaParseNotation(ctxt, schema, child); | 
 | 	    child = child->next; | 
 | 	} else { | 
 | 	    xmlSchemaPContentErr(ctxt, | 
 | 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | 
 | 		NULL, child->parent, child, | 
 | 		NULL, "((include | import | redefine | annotation)*, " | 
 | 		"(((simpleType | complexType | group | attributeGroup) " | 
 | 		"| element | attribute | notation), annotation*)*)"); | 
 | 	    child = child->next; | 
 | 	} | 
 | 	while (IS_SCHEMA(child, "annotation")) { | 
 | 	    /* | 
 | 	    * TODO: We should add all annotations. | 
 | 	    */ | 
 | 	    annot = xmlSchemaParseAnnotation(ctxt, child, 1); | 
 | 	    if (schema->annot == NULL) | 
 | 		schema->annot = annot; | 
 | 	    else | 
 | 		xmlSchemaFreeAnnot(annot); | 
 | 	    child = child->next; | 
 | 	} | 
 |     } | 
 | exit: | 
 |     ctxt->ctxtType = NULL; | 
 |     if (oldErrs != ctxt->nberrors) | 
 | 	res = ctxt->err; | 
 |     return(res); | 
 | exit_failure: | 
 |     return(-1); | 
 | } | 
 |  | 
 | static xmlSchemaSchemaRelationPtr | 
 | xmlSchemaSchemaRelationCreate(void) | 
 | { | 
 |     xmlSchemaSchemaRelationPtr ret; | 
 |  | 
 |     ret = (xmlSchemaSchemaRelationPtr) | 
 | 	xmlMalloc(sizeof(xmlSchemaSchemaRelation)); | 
 |     if (ret == NULL) { | 
 | 	xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL); | 
 | 	return(NULL); | 
 |     } | 
 |     memset(ret, 0, sizeof(xmlSchemaSchemaRelation)); | 
 |     return(ret); | 
 | } | 
 |  | 
 | #if 0 | 
 | static void | 
 | xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel) | 
 | { | 
 |     xmlFree(rel); | 
 | } | 
 | #endif | 
 |  | 
 | static void | 
 | xmlSchemaRedefListFree(xmlSchemaRedefPtr redef) | 
 | { | 
 |     xmlSchemaRedefPtr prev; | 
 |  | 
 |     while (redef != NULL) { | 
 | 	prev = redef; | 
 | 	redef = redef->next; | 
 | 	xmlFree(prev); | 
 |     } | 
 | } | 
 |  | 
 | static void | 
 | xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con) | 
 | { | 
 |     /* | 
 |     * After the construction context has been freed, there will be | 
 |     * no schema graph available any more. Only the schema buckets | 
 |     * will stay alive, which are put into the "schemasImports" and | 
 |     * "includes" slots of the xmlSchema. | 
 |     */ | 
 |     if (con->buckets != NULL) | 
 | 	xmlSchemaItemListFree(con->buckets); | 
 |     if (con->pending != NULL) | 
 | 	xmlSchemaItemListFree(con->pending); | 
 |     if (con->substGroups != NULL) | 
 | 	xmlHashFree(con->substGroups, | 
 | 	    (xmlHashDeallocator) xmlSchemaSubstGroupFree); | 
 |     if (con->redefs != NULL) | 
 | 	xmlSchemaRedefListFree(con->redefs); | 
 |     if (con->dict != NULL) | 
 | 	xmlDictFree(con->dict); | 
 |     xmlFree(con); | 
 | } | 
 |  | 
 | static xmlSchemaConstructionCtxtPtr | 
 | xmlSchemaConstructionCtxtCreate(xmlDictPtr dict) | 
 | { | 
 |     xmlSchemaConstructionCtxtPtr ret; | 
 |  | 
 |     ret = (xmlSchemaConstructionCtxtPtr) | 
 | 	xmlMalloc(sizeof(xmlSchemaConstructionCtxt)); | 
 |     if (ret == NULL) { | 
 |         xmlSchemaPErrMemory(NULL, | 
 | 	    "allocating schema construction context", NULL); | 
 |         return (NULL); | 
 |     } | 
 |     memset(ret, 0, sizeof(xmlSchemaConstructionCtxt)); | 
 |  | 
 |     ret->buckets = xmlSchemaItemListCreate(); | 
 |     if (ret->buckets == NULL) { | 
 | 	xmlSchemaPErrMemory(NULL, | 
 | 	    "allocating list of schema buckets", NULL); | 
 | 	xmlFree(ret); | 
 |         return (NULL); | 
 |     } | 
 |     ret->pending = xmlSchemaItemListCreate(); | 
 |     if (ret->pending == NULL) { | 
 | 	xmlSchemaPErrMemory(NULL, | 
 | 	    "allocating list of pending global components", NULL); | 
 | 	xmlSchemaConstructionCtxtFree(ret); | 
 |         return (NULL); | 
 |     } | 
 |     ret->dict = dict; | 
 |     xmlDictReference(dict); | 
 |     return(ret); | 
 | } | 
 |  | 
 | static xmlSchemaParserCtxtPtr | 
 | xmlSchemaParserCtxtCreate(void) | 
 | { | 
 |     xmlSchemaParserCtxtPtr ret; | 
 |  | 
 |     ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt)); | 
 |     if (ret == NULL) { | 
 |         xmlSchemaPErrMemory(NULL, "allocating schema parser context", | 
 |                             NULL); | 
 |         return (NULL); | 
 |     } | 
 |     memset(ret, 0, sizeof(xmlSchemaParserCtxt)); | 
 |     ret->type = XML_SCHEMA_CTXT_PARSER; | 
 |     ret->attrProhibs = xmlSchemaItemListCreate(); | 
 |     if (ret->attrProhibs == NULL) { | 
 | 	xmlFree(ret); | 
 | 	return(NULL); | 
 |     } | 
 |     return(ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaNewParserCtxtUseDict: | 
 |  * @URL:  the location of the schema | 
 |  * @dict: the dictionary to be used | 
 |  * | 
 |  * Create an XML Schemas parse context for that file/resource expected | 
 |  * to contain an XML Schemas file. | 
 |  * | 
 |  * Returns the parser context or NULL in case of error | 
 |  */ | 
 | static xmlSchemaParserCtxtPtr | 
 | xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict) | 
 | { | 
 |     xmlSchemaParserCtxtPtr ret; | 
 |  | 
 |     ret = xmlSchemaParserCtxtCreate(); | 
 |     if (ret == NULL) | 
 |         return (NULL); | 
 |     ret->dict = dict; | 
 |     xmlDictReference(dict); | 
 |     if (URL != NULL) | 
 | 	ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1); | 
 |     return (ret); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt) | 
 | { | 
 |     if (vctxt->pctxt == NULL) { | 
 |         if (vctxt->schema != NULL) | 
 | 	    vctxt->pctxt = | 
 | 		xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict); | 
 | 	else | 
 | 	    vctxt->pctxt = xmlSchemaNewParserCtxt("*"); | 
 | 	if (vctxt->pctxt == NULL) { | 
 | 	    VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt", | 
 | 		"failed to create a temp. parser context"); | 
 | 	    return (-1); | 
 | 	} | 
 | 	/* TODO: Pass user data. */ | 
 | 	xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, | 
 | 	    vctxt->warning, vctxt->errCtxt); | 
 | 	xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror, | 
 | 	    vctxt->errCtxt); | 
 |     } | 
 |     return (0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaGetSchemaBucket: | 
 |  * @pctxt: the schema parser context | 
 |  * @schemaLocation: the URI of the schema document | 
 |  * | 
 |  * Returns a schema bucket if it was already parsed. | 
 |  * | 
 |  * Returns a schema bucket if it was already parsed from | 
 |  *         @schemaLocation, NULL otherwise. | 
 |  */ | 
 | static xmlSchemaBucketPtr | 
 | xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt, | 
 | 			    const xmlChar *schemaLocation) | 
 | { | 
 |     xmlSchemaBucketPtr cur; | 
 |     xmlSchemaItemListPtr list; | 
 |  | 
 |     list = pctxt->constructor->buckets; | 
 |     if (list->nbItems == 0) | 
 | 	return(NULL); | 
 |     else { | 
 | 	int i; | 
 | 	for (i = 0; i < list->nbItems; i++) { | 
 | 	    cur = (xmlSchemaBucketPtr) list->items[i]; | 
 | 	    /* Pointer comparison! */ | 
 | 	    if (cur->schemaLocation == schemaLocation) | 
 | 		return(cur); | 
 | 	} | 
 |     } | 
 |     return(NULL); | 
 | } | 
 |  | 
 | static xmlSchemaBucketPtr | 
 | xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt, | 
 | 				     const xmlChar *schemaLocation, | 
 | 				     const xmlChar *targetNamespace) | 
 | { | 
 |     xmlSchemaBucketPtr cur; | 
 |     xmlSchemaItemListPtr list; | 
 |  | 
 |     list = pctxt->constructor->buckets; | 
 |     if (list->nbItems == 0) | 
 | 	return(NULL); | 
 |     else { | 
 | 	int i; | 
 | 	for (i = 0; i < list->nbItems; i++) { | 
 | 	    cur = (xmlSchemaBucketPtr) list->items[i]; | 
 | 	    /* Pointer comparison! */ | 
 | 	    if ((cur->origTargetNamespace == NULL) && | 
 | 		(cur->schemaLocation == schemaLocation) && | 
 | 		(cur->targetNamespace == targetNamespace)) | 
 | 		return(cur); | 
 | 	} | 
 |     } | 
 |     return(NULL); | 
 | } | 
 |  | 
 |  | 
 | #define IS_BAD_SCHEMA_DOC(b) \ | 
 |     (((b)->doc == NULL) && ((b)->schemaLocation != NULL)) | 
 |  | 
 | static xmlSchemaBucketPtr | 
 | xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt, | 
 | 				 const xmlChar *targetNamespace, | 
 | 				 int imported) | 
 | { | 
 |     xmlSchemaBucketPtr cur; | 
 |     xmlSchemaItemListPtr list; | 
 |  | 
 |     list = pctxt->constructor->buckets; | 
 |     if (list->nbItems == 0) | 
 | 	return(NULL); | 
 |     else { | 
 | 	int i; | 
 | 	for (i = 0; i < list->nbItems; i++) { | 
 | 	    cur = (xmlSchemaBucketPtr) list->items[i]; | 
 | 	    if ((! IS_BAD_SCHEMA_DOC(cur)) && | 
 | 		(cur->origTargetNamespace == targetNamespace) && | 
 | 		((imported && cur->imported) || | 
 | 		 ((!imported) && (!cur->imported)))) | 
 | 		return(cur); | 
 | 	} | 
 |     } | 
 |     return(NULL); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt, | 
 | 		     xmlSchemaPtr schema, | 
 | 		     xmlSchemaBucketPtr bucket) | 
 | { | 
 |     int oldFlags; | 
 |     xmlDocPtr oldDoc; | 
 |     xmlNodePtr node; | 
 |     int ret, oldErrs; | 
 |     xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket; | 
 |  | 
 |     /* | 
 |     * Save old values; reset the *main* schema. | 
 |     * URGENT TODO: This is not good; move the per-document information | 
 |     * to the parser. Get rid of passing the main schema to the | 
 |     * parsing functions. | 
 |     */ | 
 |     oldFlags = schema->flags; | 
 |     oldDoc = schema->doc; | 
 |     if (schema->flags != 0) | 
 | 	xmlSchemaClearSchemaDefaults(schema); | 
 |     schema->doc = bucket->doc; | 
 |     pctxt->schema = schema; | 
 |     /* | 
 |     * Keep the current target namespace on the parser *not* on the | 
 |     * main schema. | 
 |     */ | 
 |     pctxt->targetNamespace = bucket->targetNamespace; | 
 |     WXS_CONSTRUCTOR(pctxt)->bucket = bucket; | 
 |  | 
 |     if ((bucket->targetNamespace != NULL) && | 
 | 	xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) { | 
 | 	/* | 
 | 	* We are parsing the schema for schemas! | 
 | 	*/ | 
 | 	pctxt->isS4S = 1; | 
 |     } | 
 |     /* Mark it as parsed, even if parsing fails. */ | 
 |     bucket->parsed++; | 
 |     /* Compile the schema doc. */ | 
 |     node = xmlDocGetRootElement(bucket->doc); | 
 |     ret = xmlSchemaParseSchemaElement(pctxt, schema, node); | 
 |     if (ret != 0) | 
 | 	goto exit; | 
 |     /* An empty schema; just get out. */ | 
 |     if (node->children == NULL) | 
 | 	goto exit; | 
 |     oldErrs = pctxt->nberrors; | 
 |     ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children); | 
 |     if (ret != 0) | 
 | 	goto exit; | 
 |     /* | 
 |     * TODO: Not nice, but I'm not 100% sure we will get always an error | 
 |     * as a result of the obove functions; so better rely on pctxt->err | 
 |     * as well. | 
 |     */ | 
 |     if ((ret == 0) && (oldErrs != pctxt->nberrors)) { | 
 | 	ret = pctxt->err; | 
 | 	goto exit; | 
 |     } | 
 |  | 
 | exit: | 
 |     WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket; | 
 |     /* Restore schema values. */ | 
 |     schema->doc = oldDoc; | 
 |     schema->flags = oldFlags; | 
 |     return(ret); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt, | 
 | 		     xmlSchemaPtr schema, | 
 | 		     xmlSchemaBucketPtr bucket) | 
 | { | 
 |     xmlSchemaParserCtxtPtr newpctxt; | 
 |     int res = 0; | 
 |  | 
 |     if (bucket == NULL) | 
 | 	return(0); | 
 |     if (bucket->parsed) { | 
 | 	PERROR_INT("xmlSchemaParseNewDoc", | 
 | 	    "reparsing a schema doc"); | 
 | 	return(-1); | 
 |     } | 
 |     if (bucket->doc == NULL) { | 
 | 	PERROR_INT("xmlSchemaParseNewDoc", | 
 | 	    "parsing a schema doc, but there's no doc"); | 
 | 	return(-1); | 
 |     } | 
 |     if (pctxt->constructor == NULL) { | 
 | 	PERROR_INT("xmlSchemaParseNewDoc", | 
 | 	    "no constructor"); | 
 | 	return(-1); | 
 |     } | 
 |     /* Create and init the temporary parser context. */ | 
 |     newpctxt = xmlSchemaNewParserCtxtUseDict( | 
 | 	(const char *) bucket->schemaLocation, pctxt->dict); | 
 |     if (newpctxt == NULL) | 
 | 	return(-1); | 
 |     newpctxt->constructor = pctxt->constructor; | 
 |     /* | 
 |     * TODO: Can we avoid that the parser knows about the main schema? | 
 |     * It would be better if he knows about the current schema bucket | 
 |     * only. | 
 |     */ | 
 |     newpctxt->schema = schema; | 
 |     xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning, | 
 | 	pctxt->errCtxt); | 
 |     xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror, | 
 | 	pctxt->errCtxt); | 
 |     newpctxt->counter = pctxt->counter; | 
 |  | 
 |  | 
 |     res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket); | 
 |  | 
 |     /* Channel back errors and cleanup the temporary parser context. */ | 
 |     if (res != 0) | 
 | 	pctxt->err = res; | 
 |     pctxt->nberrors += newpctxt->nberrors; | 
 |     pctxt->counter = newpctxt->counter; | 
 |     newpctxt->constructor = NULL; | 
 |     /* Free the parser context. */ | 
 |     xmlSchemaFreeParserCtxt(newpctxt); | 
 |     return(res); | 
 | } | 
 |  | 
 | static void | 
 | xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket, | 
 | 				xmlSchemaSchemaRelationPtr rel) | 
 | { | 
 |     xmlSchemaSchemaRelationPtr cur = bucket->relations; | 
 |  | 
 |     if (cur == NULL) { | 
 | 	bucket->relations = rel; | 
 | 	return; | 
 |     } | 
 |     while (cur->next != NULL) | 
 | 	cur = cur->next; | 
 |     cur->next = rel; | 
 | } | 
 |  | 
 |  | 
 | static const xmlChar * | 
 | xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location, | 
 | 			  xmlNodePtr ctxtNode) | 
 | { | 
 |     /* | 
 |     * Build an absolue location URI. | 
 |     */ | 
 |     if (location != NULL) { | 
 | 	if (ctxtNode == NULL) | 
 | 	    return(location); | 
 | 	else { | 
 | 	    xmlChar *base, *URI; | 
 | 	    const xmlChar *ret = NULL; | 
 |  | 
 | 	    base = xmlNodeGetBase(ctxtNode->doc, ctxtNode); | 
 | 	    if (base == NULL) { | 
 | 		URI = xmlBuildURI(location, ctxtNode->doc->URL); | 
 | 	    } else { | 
 | 		URI = xmlBuildURI(location, base); | 
 | 		xmlFree(base); | 
 | 	    } | 
 | 	    if (URI != NULL) { | 
 | 		ret = xmlDictLookup(dict, URI, -1); | 
 | 		xmlFree(URI); | 
 | 		return(ret); | 
 | 	    } | 
 | 	} | 
 |     } | 
 |     return(NULL); | 
 | } | 
 |  | 
 |  | 
 |  | 
 | /** | 
 |  * xmlSchemaAddSchemaDoc: | 
 |  * @pctxt:  a schema validation context | 
 |  * @schema:  the schema being built | 
 |  * @node:  a subtree containing XML Schema informations | 
 |  * | 
 |  * Parse an included (and to-be-redefined) XML schema document. | 
 |  * | 
 |  * Returns 0 on success, a positive error code on errors and | 
 |  *         -1 in case of an internal or API error. | 
 |  */ | 
 |  | 
 | static int | 
 | xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt, | 
 | 		int type, /* import or include or redefine */ | 
 | 		const xmlChar *schemaLocation, | 
 | 		xmlDocPtr schemaDoc, | 
 | 		const char *schemaBuffer, | 
 | 		int schemaBufferLen, | 
 | 		xmlNodePtr invokingNode, | 
 | 		const xmlChar *sourceTargetNamespace, | 
 | 		const xmlChar *importNamespace, | 
 | 		xmlSchemaBucketPtr *bucket) | 
 | { | 
 |     const xmlChar *targetNamespace = NULL; | 
 |     xmlSchemaSchemaRelationPtr relation = NULL; | 
 |     xmlDocPtr doc = NULL; | 
 |     int res = 0, err = 0, located = 0, preserveDoc = 0; | 
 |     xmlSchemaBucketPtr bkt = NULL; | 
 |  | 
 |     if (bucket != NULL) | 
 | 	*bucket = NULL; | 
 |  | 
 |     switch (type) { | 
 | 	case XML_SCHEMA_SCHEMA_IMPORT: | 
 | 	case XML_SCHEMA_SCHEMA_MAIN: | 
 | 	    err = XML_SCHEMAP_SRC_IMPORT; | 
 | 	    break; | 
 | 	case XML_SCHEMA_SCHEMA_INCLUDE: | 
 | 	    err = XML_SCHEMAP_SRC_INCLUDE; | 
 | 	    break; | 
 | 	case XML_SCHEMA_SCHEMA_REDEFINE: | 
 | 	    err = XML_SCHEMAP_SRC_REDEFINE; | 
 | 	    break; | 
 |     } | 
 |  | 
 |  | 
 |     /* Special handling for the main schema: | 
 |     * skip the location and relation logic and just parse the doc. | 
 |     * We need just a bucket to be returned in this case. | 
 |     */ | 
 |     if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt))) | 
 | 	goto doc_load; | 
 |  | 
 |     /* Note that we expect the location to be an absulute URI. */ | 
 |     if (schemaLocation != NULL) { | 
 | 	bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation); | 
 | 	if ((bkt != NULL) && | 
 | 	    (pctxt->constructor->bucket == bkt)) { | 
 | 	    /* Report self-imports/inclusions/redefinitions. */ | 
 |  | 
 | 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, err, | 
 | 		invokingNode, NULL, | 
 | 		"The schema must not import/include/redefine itself", | 
 | 		NULL, NULL); | 
 | 	    goto exit; | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * Create a relation for the graph of schemas. | 
 |     */ | 
 |     relation = xmlSchemaSchemaRelationCreate(); | 
 |     if (relation == NULL) | 
 | 	return(-1); | 
 |     xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket, | 
 | 	relation); | 
 |     relation->type = type; | 
 |  | 
 |     /* | 
 |     * Save the namespace import information. | 
 |     */ | 
 |     if (WXS_IS_BUCKET_IMPMAIN(type)) { | 
 | 	relation->importNamespace = importNamespace; | 
 | 	if (schemaLocation == NULL) { | 
 | 	    /* | 
 | 	    * No location; this is just an import of the namespace. | 
 | 	    * Note that we don't assign a bucket to the relation | 
 | 	    * in this case. | 
 | 	    */ | 
 | 	    goto exit; | 
 | 	} | 
 | 	targetNamespace = importNamespace; | 
 |     } | 
 |  | 
 |     /* Did we already fetch the doc? */ | 
 |     if (bkt != NULL) { | 
 | 	if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) { | 
 | 	    /* | 
 | 	    * We included/redefined and then try to import a schema, | 
 | 	    * but the new location provided for import was different. | 
 | 	    */ | 
 | 	    if (schemaLocation == NULL) | 
 | 		schemaLocation = BAD_CAST "in_memory_buffer"; | 
 | 	    if (!xmlStrEqual(schemaLocation, | 
 | 		bkt->schemaLocation)) { | 
 | 		xmlSchemaCustomErr(ACTXT_CAST pctxt, err, | 
 | 		    invokingNode, NULL, | 
 | 		    "The schema document '%s' cannot be imported, since " | 
 | 		    "it was already included or redefined", | 
 | 		    schemaLocation, NULL); | 
 | 		goto exit; | 
 | 	    } | 
 | 	} else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) { | 
 | 	    /* | 
 | 	    * We imported and then try to include/redefine a schema, | 
 | 	    * but the new location provided for the include/redefine | 
 | 	    * was different. | 
 | 	    */ | 
 | 	    if (schemaLocation == NULL) | 
 | 		schemaLocation = BAD_CAST "in_memory_buffer"; | 
 | 	    if (!xmlStrEqual(schemaLocation, | 
 | 		bkt->schemaLocation)) { | 
 | 		xmlSchemaCustomErr(ACTXT_CAST pctxt, err, | 
 | 		    invokingNode, NULL, | 
 | 		    "The schema document '%s' cannot be included or " | 
 | 		    "redefined, since it was already imported", | 
 | 		    schemaLocation, NULL); | 
 | 		goto exit; | 
 | 	    } | 
 | 	} | 
 |     } | 
 |  | 
 |     if (WXS_IS_BUCKET_IMPMAIN(type)) { | 
 | 	/* | 
 | 	* Given that the schemaLocation [attribute] is only a hint, it is open | 
 | 	* to applications to ignore all but the first <import> for a given | 
 | 	* namespace, regardless of the �actual value� of schemaLocation, but | 
 | 	* such a strategy risks missing useful information when new | 
 | 	* schemaLocations are offered. | 
 | 	* | 
 | 	* We will use the first <import> that comes with a location. | 
 | 	* Further <import>s *with* a location, will result in an error. | 
 | 	* TODO: Better would be to just report a warning here, but | 
 | 	* we'll try it this way until someone complains. | 
 | 	* | 
 | 	* Schema Document Location Strategy: | 
 | 	* 3 Based on the namespace name, identify an existing schema document, | 
 | 	* either as a resource which is an XML document or a <schema> element | 
 | 	* information item, in some local schema repository; | 
 | 	* 5 Attempt to resolve the namespace name to locate such a resource. | 
 | 	* | 
 | 	* NOTE: (3) and (5) are not supported. | 
 | 	*/ | 
 | 	if (bkt != NULL) { | 
 | 	    relation->bucket = bkt; | 
 | 	    goto exit; | 
 | 	} | 
 | 	bkt = xmlSchemaGetSchemaBucketByTNS(pctxt, | 
 | 	    importNamespace, 1); | 
 |  | 
 | 	if (bkt != NULL) { | 
 | 	    relation->bucket = bkt; | 
 | 	    if (bkt->schemaLocation == NULL) { | 
 | 		/* First given location of the schema; load the doc. */ | 
 | 		bkt->schemaLocation = schemaLocation; | 
 | 	    } else { | 
 | 		if (!xmlStrEqual(schemaLocation, | 
 | 		    bkt->schemaLocation)) { | 
 | 		    /* | 
 | 		    * Additional location given; just skip it. | 
 | 		    * URGENT TODO: We should report a warning here. | 
 | 		    * res = XML_SCHEMAP_SRC_IMPORT; | 
 | 		    */ | 
 | 		    if (schemaLocation == NULL) | 
 | 			schemaLocation = BAD_CAST "in_memory_buffer"; | 
 |  | 
 | 		    xmlSchemaCustomWarning(ACTXT_CAST pctxt, | 
 | 			XML_SCHEMAP_WARN_SKIP_SCHEMA, | 
 | 			invokingNode, NULL, | 
 | 			"Skipping import of schema located at '%s' for the " | 
 | 			"namespace '%s', since this namespace was already " | 
 | 			"imported with the schema located at '%s'", | 
 | 			schemaLocation, importNamespace, bkt->schemaLocation); | 
 | 		} | 
 | 		goto exit; | 
 | 	    } | 
 | 	} | 
 | 	/* | 
 | 	* No bucket + first location: load the doc and create a | 
 | 	* bucket. | 
 | 	*/ | 
 |     } else { | 
 | 	/* <include> and <redefine> */ | 
 | 	if (bkt != NULL) { | 
 |  | 
 | 	    if ((bkt->origTargetNamespace == NULL) && | 
 | 		(bkt->targetNamespace != sourceTargetNamespace)) { | 
 | 		xmlSchemaBucketPtr chamel; | 
 |  | 
 | 		/* | 
 | 		* Chameleon include/redefine: skip loading only if it was | 
 | 		* aleady build for the targetNamespace of the including | 
 | 		* schema. | 
 | 		*/ | 
 | 		/* | 
 | 		* URGENT TODO: If the schema is a chameleon-include then copy | 
 | 		* the components into the including schema and modify the | 
 | 		* targetNamespace of those components, do nothing otherwise. | 
 | 		* NOTE: This is currently worked-around by compiling the | 
 | 		* chameleon for every destinct including targetNamespace; thus | 
 | 		* not performant at the moment. | 
 | 		* TODO: Check when the namespace in wildcards for chameleons | 
 | 		* needs to be converted: before we built wildcard intersections | 
 | 		* or after. | 
 | 		*   Answer: after! | 
 | 		*/ | 
 | 		chamel = xmlSchemaGetChameleonSchemaBucket(pctxt, | 
 | 		    schemaLocation, sourceTargetNamespace); | 
 | 		if (chamel != NULL) { | 
 | 		    /* A fitting chameleon was already parsed; NOP. */ | 
 | 		    relation->bucket = chamel; | 
 | 		    goto exit; | 
 | 		} | 
 | 		/* | 
 | 		* We need to parse the chameleon again for a different | 
 | 		* targetNamespace. | 
 | 		* CHAMELEON TODO: Optimize this by only parsing the | 
 | 		* chameleon once, and then copying the components to | 
 | 		* the new targetNamespace. | 
 | 		*/ | 
 | 		bkt = NULL; | 
 | 	    } else { | 
 | 		relation->bucket = bkt; | 
 | 		goto exit; | 
 | 	    } | 
 | 	} | 
 |     } | 
 |     if ((bkt != NULL) && (bkt->doc != NULL)) { | 
 | 	PERROR_INT("xmlSchemaAddSchemaDoc", | 
 | 	    "trying to load a schema doc, but a doc is already " | 
 | 	    "assigned to the schema bucket"); | 
 | 	goto exit_failure; | 
 |     } | 
 |  | 
 | doc_load: | 
 |     /* | 
 |     * Load the document. | 
 |     */ | 
 |     if (schemaDoc != NULL) { | 
 | 	doc = schemaDoc; | 
 | 	/* Don' free this one, since it was provided by the caller. */ | 
 | 	preserveDoc = 1; | 
 | 	/* TODO: Does the context or the doc hold the location? */ | 
 | 	if (schemaDoc->URL != NULL) | 
 | 	    schemaLocation = xmlDictLookup(pctxt->dict, | 
 | 		schemaDoc->URL, -1); | 
 |         else | 
 | 	    schemaLocation = BAD_CAST "in_memory_buffer"; | 
 |     } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) { | 
 | 	xmlParserCtxtPtr parserCtxt; | 
 |  | 
 | 	parserCtxt = xmlNewParserCtxt(); | 
 | 	if (parserCtxt == NULL) { | 
 | 	    xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, " | 
 | 		"allocating a parser context", NULL); | 
 | 	    goto exit_failure; | 
 | 	} | 
 | 	if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) { | 
 | 	    /* | 
 | 	    * TODO: Do we have to burden the schema parser dict with all | 
 | 	    * the content of the schema doc? | 
 | 	    */ | 
 | 	    xmlDictFree(parserCtxt->dict); | 
 | 	    parserCtxt->dict = pctxt->dict; | 
 | 	    xmlDictReference(parserCtxt->dict); | 
 | 	} | 
 | 	if (schemaLocation != NULL) { | 
 | 	    /* Parse from file. */ | 
 | 	    doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation, | 
 | 		NULL, SCHEMAS_PARSE_OPTIONS); | 
 | 	} else if (schemaBuffer != NULL) { | 
 | 	    /* Parse from memory buffer. */ | 
 | 	    doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen, | 
 | 		NULL, NULL, SCHEMAS_PARSE_OPTIONS); | 
 | 	    schemaLocation = BAD_CAST "in_memory_buffer"; | 
 | 	    if (doc != NULL) | 
 | 		doc->URL = xmlStrdup(schemaLocation); | 
 | 	} | 
 | 	/* | 
 | 	* For <import>: | 
 | 	* 2.1 The referent is (a fragment of) a resource which is an | 
 | 	* XML document (see clause 1.1), which in turn corresponds to | 
 | 	* a <schema> element information item in a well-formed information | 
 | 	* set, which in turn corresponds to a valid schema. | 
 | 	* TODO: (2.1) fragments of XML documents are not supported. | 
 | 	* | 
 | 	* 2.2 The referent is a <schema> element information item in | 
 | 	* a well-formed information set, which in turn corresponds | 
 | 	* to a valid schema. | 
 | 	* TODO: (2.2) is not supported. | 
 | 	*/ | 
 | 	if (doc == NULL) { | 
 | 	    xmlErrorPtr lerr; | 
 | 	    lerr = xmlGetLastError(); | 
 | 	    /* | 
 | 	    * Check if this a parser error, or if the document could | 
 | 	    * just not be located. | 
 | 	    * TODO: Try to find specific error codes to react only on | 
 | 	    * localisation failures. | 
 | 	    */ | 
 | 	    if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) { | 
 | 		/* | 
 | 		* We assume a parser error here. | 
 | 		*/ | 
 | 		located = 1; | 
 | 		/* TODO: Error code ?? */ | 
 | 		res = XML_SCHEMAP_SRC_IMPORT_2_1; | 
 | 		xmlSchemaCustomErr(ACTXT_CAST pctxt, res, | 
 | 		    invokingNode, NULL, | 
 | 		    "Failed to parse the XML resource '%s'", | 
 | 		    schemaLocation, NULL); | 
 | 	    } | 
 | 	} | 
 | 	xmlFreeParserCtxt(parserCtxt); | 
 | 	if ((doc == NULL) && located) | 
 | 	    goto exit_error; | 
 |     } else { | 
 | 	xmlSchemaPErr(pctxt, NULL, | 
 | 	    XML_SCHEMAP_NOTHING_TO_PARSE, | 
 | 	    "No information for parsing was provided with the " | 
 | 	    "given schema parser context.\n", | 
 | 	    NULL, NULL); | 
 | 	goto exit_failure; | 
 |     } | 
 |     /* | 
 |     * Preprocess the document. | 
 |     */ | 
 |     if (doc != NULL) { | 
 | 	xmlNodePtr docElem = NULL; | 
 |  | 
 | 	located = 1; | 
 | 	docElem = xmlDocGetRootElement(doc); | 
 | 	if (docElem == NULL) { | 
 | 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT, | 
 | 		invokingNode, NULL, | 
 | 		"The document '%s' has no document element", | 
 | 		schemaLocation, NULL); | 
 | 	    goto exit_error; | 
 | 	} | 
 | 	/* | 
 | 	* Remove all the blank text nodes. | 
 | 	*/ | 
 | 	xmlSchemaCleanupDoc(pctxt, docElem); | 
 | 	/* | 
 | 	* Check the schema's top level element. | 
 | 	*/ | 
 | 	if (!IS_SCHEMA(docElem, "schema")) { | 
 | 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA, | 
 | 		invokingNode, NULL, | 
 | 		"The XML document '%s' is not a schema document", | 
 | 		schemaLocation, NULL); | 
 | 	    goto exit_error; | 
 | 	} | 
 | 	/* | 
 | 	* Note that we don't apply a type check for the | 
 | 	* targetNamespace value here. | 
 | 	*/ | 
 | 	targetNamespace = xmlSchemaGetProp(pctxt, docElem, | 
 | 	    "targetNamespace"); | 
 |     } | 
 |  | 
 | /* after_doc_loading: */ | 
 |     if ((bkt == NULL) && located) { | 
 | 	/* Only create a bucket if the schema was located. */ | 
 |         bkt = xmlSchemaBucketCreate(pctxt, type, | 
 | 	    targetNamespace); | 
 | 	if (bkt == NULL) | 
 | 	    goto exit_failure; | 
 |     } | 
 |     if (bkt != NULL) { | 
 | 	bkt->schemaLocation = schemaLocation; | 
 | 	bkt->located = located; | 
 | 	if (doc != NULL) { | 
 | 	    bkt->doc = doc; | 
 | 	    bkt->targetNamespace = targetNamespace; | 
 | 	    bkt->origTargetNamespace = targetNamespace; | 
 | 	    if (preserveDoc) | 
 | 		bkt->preserveDoc = 1; | 
 | 	} | 
 | 	if (WXS_IS_BUCKET_IMPMAIN(type)) | 
 | 	    bkt->imported++; | 
 | 	    /* | 
 | 	    * Add it to the graph of schemas. | 
 | 	    */ | 
 | 	if (relation != NULL) | 
 | 	    relation->bucket = bkt; | 
 |     } | 
 |  | 
 | exit: | 
 |     /* | 
 |     * Return the bucket explicitely; this is needed for the | 
 |     * main schema. | 
 |     */ | 
 |     if (bucket != NULL) | 
 | 	*bucket = bkt; | 
 |     return (0); | 
 |  | 
 | exit_error: | 
 |     if ((doc != NULL) && (! preserveDoc)) { | 
 | 	xmlFreeDoc(doc); | 
 | 	if (bkt != NULL) | 
 | 	    bkt->doc = NULL; | 
 |     } | 
 |     return(pctxt->err); | 
 |  | 
 | exit_failure: | 
 |     if ((doc != NULL) && (! preserveDoc)) { | 
 | 	xmlFreeDoc(doc); | 
 | 	if (bkt != NULL) | 
 | 	    bkt->doc = NULL; | 
 |     } | 
 |     return (-1); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaParseImport: | 
 |  * @ctxt:  a schema validation context | 
 |  * @schema:  the schema being built | 
 |  * @node:  a subtree containing XML Schema informations | 
 |  * | 
 |  * parse a XML schema Import definition | 
 |  * *WARNING* this interface is highly subject to change | 
 |  * | 
 |  * Returns 0 in case of success, a positive error code if | 
 |  * not valid and -1 in case of an internal error. | 
 |  */ | 
 | static int | 
 | xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema, | 
 |                      xmlNodePtr node) | 
 | { | 
 |     xmlNodePtr child; | 
 |     const xmlChar *namespaceName = NULL, *schemaLocation = NULL; | 
 |     const xmlChar *thisTargetNamespace; | 
 |     xmlAttrPtr attr; | 
 |     int ret = 0; | 
 |     xmlSchemaBucketPtr bucket = NULL; | 
 |  | 
 |     if ((pctxt == NULL) || (schema == NULL) || (node == NULL)) | 
 |         return (-1); | 
 |  | 
 |     /* | 
 |     * Check for illegal attributes. | 
 |     */ | 
 |     attr = node->properties; | 
 |     while (attr != NULL) { | 
 | 	if (attr->ns == NULL) { | 
 | 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && | 
 | 		(!xmlStrEqual(attr->name, BAD_CAST "namespace")) && | 
 | 		(!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) { | 
 | 		xmlSchemaPIllegalAttrErr(pctxt, | 
 | 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	    } | 
 | 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | 
 | 	    xmlSchemaPIllegalAttrErr(pctxt, | 
 | 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	} | 
 | 	attr = attr->next; | 
 |     } | 
 |     /* | 
 |     * Extract and validate attributes. | 
 |     */ | 
 |     if (xmlSchemaPValAttr(pctxt, NULL, node, | 
 | 	"namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), | 
 | 	&namespaceName) != 0) { | 
 | 	xmlSchemaPSimpleTypeErr(pctxt, | 
 | 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | 
 | 	    NULL, node, | 
 | 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), | 
 | 	    NULL, namespaceName, NULL, NULL, NULL); | 
 | 	return (pctxt->err); | 
 |     } | 
 |  | 
 |     if (xmlSchemaPValAttr(pctxt, NULL, node, | 
 | 	"schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), | 
 | 	&schemaLocation) != 0) { | 
 | 	xmlSchemaPSimpleTypeErr(pctxt, | 
 | 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | 
 | 	    NULL, node, | 
 | 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), | 
 | 	    NULL, namespaceName, NULL, NULL, NULL); | 
 | 	return (pctxt->err); | 
 |     } | 
 |     /* | 
 |     * And now for the children... | 
 |     */ | 
 |     child = node->children; | 
 |     if (IS_SCHEMA(child, "annotation")) { | 
 |         /* | 
 |          * the annotation here is simply discarded ... | 
 | 	 * TODO: really? | 
 |          */ | 
 |         child = child->next; | 
 |     } | 
 |     if (child != NULL) { | 
 | 	xmlSchemaPContentErr(pctxt, | 
 | 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | 
 | 	    NULL, node, child, NULL, | 
 | 	    "(annotation?)"); | 
 |     } | 
 |     /* | 
 |     * Apply additional constraints. | 
 |     * | 
 |     * Note that it is important to use the original @targetNamespace | 
 |     * (or none at all), to rule out imports of schemas _with_ a | 
 |     * @targetNamespace if the importing schema is a chameleon schema | 
 |     * (with no @targetNamespace). | 
 |     */ | 
 |     thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace; | 
 |     if (namespaceName != NULL) { | 
 | 	/* | 
 | 	* 1.1 If the namespace [attribute] is present, then its �actual value� | 
 | 	* must not match the �actual value� of the enclosing <schema>'s | 
 | 	* targetNamespace [attribute]. | 
 | 	*/ | 
 | 	if (xmlStrEqual(thisTargetNamespace, namespaceName)) { | 
 | 	    xmlSchemaPCustomErr(pctxt, | 
 | 		XML_SCHEMAP_SRC_IMPORT_1_1, | 
 | 		NULL, node, | 
 | 		"The value of the attribute 'namespace' must not match " | 
 | 		"the target namespace '%s' of the importing schema", | 
 | 		thisTargetNamespace); | 
 | 	    return (pctxt->err); | 
 | 	} | 
 |     } else { | 
 | 	/* | 
 | 	* 1.2 If the namespace [attribute] is not present, then the enclosing | 
 | 	* <schema> must have a targetNamespace [attribute]. | 
 | 	*/ | 
 | 	if (thisTargetNamespace == NULL) { | 
 | 	    xmlSchemaPCustomErr(pctxt, | 
 | 		XML_SCHEMAP_SRC_IMPORT_1_2, | 
 | 		NULL, node, | 
 | 		"The attribute 'namespace' must be existent if " | 
 | 		"the importing schema has no target namespace", | 
 | 		NULL); | 
 | 	    return (pctxt->err); | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * Locate and acquire the schema document. | 
 |     */ | 
 |     if (schemaLocation != NULL) | 
 | 	schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict, | 
 | 	    schemaLocation, node); | 
 |     ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT, | 
 | 	schemaLocation, NULL, NULL, 0, node, thisTargetNamespace, | 
 | 	namespaceName, &bucket); | 
 |  | 
 |     if (ret != 0) | 
 | 	return(ret); | 
 |  | 
 |     /* | 
 |     * For <import>: "It is *not* an error for the application | 
 |     * schema reference strategy to fail." | 
 |     * So just don't parse if no schema document was found. | 
 |     * Note that we will get no bucket if the schema could not be | 
 |     * located or if there was no schemaLocation. | 
 |     */ | 
 |     if ((bucket == NULL) && (schemaLocation != NULL)) { | 
 | 	xmlSchemaCustomWarning(ACTXT_CAST pctxt, | 
 | 	    XML_SCHEMAP_WARN_UNLOCATED_SCHEMA, | 
 | 	    node, NULL, | 
 | 	    "Failed to locate a schema at location '%s'. " | 
 | 	    "Skipping the import", schemaLocation, NULL, NULL); | 
 |     } | 
 |  | 
 |     if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) { | 
 | 	ret = xmlSchemaParseNewDoc(pctxt, schema, bucket); | 
 |     } | 
 |  | 
 |     return (ret); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt, | 
 | 				     xmlSchemaPtr schema, | 
 | 				     xmlNodePtr node, | 
 | 				     xmlChar **schemaLocation, | 
 | 				     int type) | 
 | { | 
 |     xmlAttrPtr attr; | 
 |  | 
 |     if ((pctxt == NULL) || (schema == NULL) || (node == NULL) || | 
 | 	(schemaLocation == NULL)) | 
 |         return (-1); | 
 |  | 
 |     *schemaLocation = NULL; | 
 |     /* | 
 |     * Check for illegal attributes. | 
 |     * Applies for both <include> and <redefine>. | 
 |     */ | 
 |     attr = node->properties; | 
 |     while (attr != NULL) { | 
 | 	if (attr->ns == NULL) { | 
 | 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && | 
 | 		(!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) { | 
 | 		xmlSchemaPIllegalAttrErr(pctxt, | 
 | 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	    } | 
 | 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | 
 | 	    xmlSchemaPIllegalAttrErr(pctxt, | 
 | 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	} | 
 | 	attr = attr->next; | 
 |     } | 
 |     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id"); | 
 |     /* | 
 |     * Preliminary step, extract the URI-Reference and make an URI | 
 |     * from the base. | 
 |     */ | 
 |     /* | 
 |     * Attribute "schemaLocation" is mandatory. | 
 |     */ | 
 |     attr = xmlSchemaGetPropNode(node, "schemaLocation"); | 
 |     if (attr != NULL) { | 
 |         xmlChar *base = NULL; | 
 |         xmlChar *uri = NULL; | 
 |  | 
 | 	if (xmlSchemaPValAttrNode(pctxt, NULL, attr, | 
 | 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), | 
 | 	    (const xmlChar **) schemaLocation) != 0) | 
 | 	    goto exit_error; | 
 | 	base = xmlNodeGetBase(node->doc, node); | 
 | 	if (base == NULL) { | 
 | 	    uri = xmlBuildURI(*schemaLocation, node->doc->URL); | 
 | 	} else { | 
 | 	    uri = xmlBuildURI(*schemaLocation, base); | 
 | 	    xmlFree(base); | 
 | 	} | 
 | 	if (uri == NULL) { | 
 | 	    PERROR_INT("xmlSchemaParseIncludeOrRedefine", | 
 | 		"could not build an URI from the schemaLocation") | 
 | 	    goto exit_failure; | 
 | 	} | 
 | 	(*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1); | 
 | 	xmlFree(uri); | 
 |     } else { | 
 | 	xmlSchemaPMissingAttrErr(pctxt, | 
 | 	    XML_SCHEMAP_S4S_ATTR_MISSING, | 
 | 	    NULL, node, "schemaLocation", NULL); | 
 | 	goto exit_error; | 
 |     } | 
 |     /* | 
 |     * Report self-inclusion and self-redefinition. | 
 |     */ | 
 |     if (xmlStrEqual(*schemaLocation, pctxt->URL)) { | 
 | 	if (type == XML_SCHEMA_SCHEMA_REDEFINE) { | 
 | 	    xmlSchemaPCustomErr(pctxt, | 
 | 		XML_SCHEMAP_SRC_REDEFINE, | 
 | 		NULL, node, | 
 | 		"The schema document '%s' cannot redefine itself.", | 
 | 		*schemaLocation); | 
 | 	} else { | 
 | 	    xmlSchemaPCustomErr(pctxt, | 
 | 		XML_SCHEMAP_SRC_INCLUDE, | 
 | 		NULL, node, | 
 | 		"The schema document '%s' cannot include itself.", | 
 | 		*schemaLocation); | 
 | 	} | 
 | 	goto exit_error; | 
 |     } | 
 |  | 
 |     return(0); | 
 | exit_error: | 
 |     return(pctxt->err); | 
 | exit_failure: | 
 |     return(-1); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt, | 
 | 				xmlSchemaPtr schema, | 
 | 				xmlNodePtr node, | 
 | 				int type) | 
 | { | 
 |     xmlNodePtr child = NULL; | 
 |     const xmlChar *schemaLocation = NULL; | 
 |     int res = 0; /* hasRedefinitions = 0 */ | 
 |     int isChameleon = 0, wasChameleon = 0; | 
 |     xmlSchemaBucketPtr bucket = NULL; | 
 |  | 
 |     if ((pctxt == NULL) || (schema == NULL) || (node == NULL)) | 
 |         return (-1); | 
 |  | 
 |     /* | 
 |     * Parse attributes. Note that the returned schemaLocation will | 
 |     * be already converted to an absolute URI. | 
 |     */ | 
 |     res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema, | 
 | 	node, (xmlChar **) (&schemaLocation), type); | 
 |     if (res != 0) | 
 | 	return(res); | 
 |     /* | 
 |     * Load and add the schema document. | 
 |     */ | 
 |     res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL, | 
 | 	NULL, 0, node, pctxt->targetNamespace, NULL, &bucket); | 
 |     if (res != 0) | 
 | 	return(res); | 
 |     /* | 
 |     * If we get no schema bucket back, then this means that the schema | 
 |     * document could not be located or was broken XML or was not | 
 |     * a schema document. | 
 |     */ | 
 |     if ((bucket == NULL) || (bucket->doc == NULL)) { | 
 | 	if (type == XML_SCHEMA_SCHEMA_INCLUDE) { | 
 | 	    /* | 
 | 	    * WARNING for <include>: | 
 | 	    * We will raise an error if the schema cannot be located | 
 | 	    * for inclusions, since the that was the feedback from the | 
 | 	    * schema people. I.e. the following spec piece will *not* be | 
 | 	    * satisfied: | 
 | 	    * SPEC src-include: "It is not an error for the �actual value� of the | 
 | 	    * schemaLocation [attribute] to fail to resolve it all, in which | 
 | 	    * case no corresponding inclusion is performed. | 
 | 	    * So do we need a warning report here?" | 
 | 	    */ | 
 | 	    res = XML_SCHEMAP_SRC_INCLUDE; | 
 | 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, res, | 
 | 		node, NULL, | 
 | 		"Failed to load the document '%s' for inclusion", | 
 | 		schemaLocation, NULL); | 
 | 	} else { | 
 | 	    /* | 
 | 	    * NOTE: This was changed to raise an error even if no redefinitions | 
 | 	    * are specified. | 
 | 	    * | 
 | 	    * SPEC src-redefine (1) | 
 | 	    * "If there are any element information items among the [children] | 
 | 	    * other than <annotation> then the �actual value� of the | 
 | 	    * schemaLocation [attribute] must successfully resolve." | 
 | 	    * TODO: Ask the WG if a the location has always to resolve | 
 | 	    * here as well! | 
 | 	    */ | 
 | 	    res = XML_SCHEMAP_SRC_REDEFINE; | 
 | 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, res, | 
 | 		node, NULL, | 
 | 		"Failed to load the document '%s' for redefinition", | 
 | 		schemaLocation, NULL); | 
 | 	} | 
 |     } else { | 
 | 	/* | 
 | 	* Check targetNamespace sanity before parsing the new schema. | 
 | 	* TODO: Note that we won't check further content if the | 
 | 	* targetNamespace was bad. | 
 | 	*/ | 
 | 	if (bucket->origTargetNamespace != NULL) { | 
 | 	    /* | 
 | 	    * SPEC src-include (2.1) | 
 | 	    * "SII has a targetNamespace [attribute], and its �actual | 
 | 	    * value� is identical to the �actual value� of the targetNamespace | 
 | 	    * [attribute] of SII� (which must have such an [attribute])." | 
 | 	    */ | 
 | 	    if (pctxt->targetNamespace == NULL) { | 
 | 		xmlSchemaCustomErr(ACTXT_CAST pctxt, | 
 | 		    XML_SCHEMAP_SRC_INCLUDE, | 
 | 		    node, NULL, | 
 | 		    "The target namespace of the included/redefined schema " | 
 | 		    "'%s' has to be absent, since the including/redefining " | 
 | 		    "schema has no target namespace", | 
 | 		    schemaLocation, NULL); | 
 | 		goto exit_error; | 
 | 	    } else if (!xmlStrEqual(bucket->origTargetNamespace, | 
 | 		pctxt->targetNamespace)) { | 
 | 		/* TODO: Change error function. */ | 
 | 		xmlSchemaPCustomErrExt(pctxt, | 
 | 		    XML_SCHEMAP_SRC_INCLUDE, | 
 | 		    NULL, node, | 
 | 		    "The target namespace '%s' of the included/redefined " | 
 | 		    "schema '%s' differs from '%s' of the " | 
 | 		    "including/redefining schema", | 
 | 		    bucket->origTargetNamespace, schemaLocation, | 
 | 		    pctxt->targetNamespace); | 
 | 		goto exit_error; | 
 | 	    } | 
 | 	} else if (pctxt->targetNamespace != NULL) { | 
 | 	    /* | 
 | 	    * Chameleons: the original target namespace will | 
 | 	    * differ from the resulting namespace. | 
 | 	    */ | 
 | 	    isChameleon = 1; | 
 | 	    if (bucket->parsed && | 
 | 		bucket->origTargetNamespace != NULL) { | 
 | 		xmlSchemaCustomErr(ACTXT_CAST pctxt, | 
 | 		    XML_SCHEMAP_SRC_INCLUDE, | 
 | 		    node, NULL, | 
 | 		    "The target namespace of the included/redefined schema " | 
 | 		    "'%s' has to be absent or the same as the " | 
 | 		    "including/redefining schema's target namespace", | 
 | 		    schemaLocation, NULL); | 
 | 		goto exit_error; | 
 | 	    } | 
 | 	    bucket->targetNamespace = pctxt->targetNamespace; | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * Parse the schema. | 
 |     */ | 
 |     if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) { | 
 | 	if (isChameleon) { | 
 | 	    /* TODO: Get rid of this flag on the schema itself. */ | 
 | 	    if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) { | 
 | 		schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS; | 
 | 	    } else | 
 | 		wasChameleon = 1; | 
 | 	} | 
 | 	xmlSchemaParseNewDoc(pctxt, schema, bucket); | 
 | 	/* Restore chameleon flag. */ | 
 | 	if (isChameleon && (!wasChameleon)) | 
 | 	    schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS; | 
 |     } | 
 |     /* | 
 |     * And now for the children... | 
 |     */ | 
 |     child = node->children; | 
 |     if (type == XML_SCHEMA_SCHEMA_REDEFINE) { | 
 | 	/* | 
 | 	* Parse (simpleType | complexType | group | attributeGroup))* | 
 | 	*/ | 
 | 	pctxt->redefined = bucket; | 
 | 	/* | 
 | 	* How to proceed if the redefined schema was not located? | 
 | 	*/ | 
 | 	pctxt->isRedefine = 1; | 
 | 	while (IS_SCHEMA(child, "annotation") || | 
 | 	    IS_SCHEMA(child, "simpleType") || | 
 | 	    IS_SCHEMA(child, "complexType") || | 
 | 	    IS_SCHEMA(child, "group") || | 
 | 	    IS_SCHEMA(child, "attributeGroup")) { | 
 | 	    if (IS_SCHEMA(child, "annotation")) { | 
 | 		/* | 
 | 		* TODO: discard or not? | 
 | 		*/ | 
 | 	    } else if (IS_SCHEMA(child, "simpleType")) { | 
 | 		xmlSchemaParseSimpleType(pctxt, schema, child, 1); | 
 | 	    } else if (IS_SCHEMA(child, "complexType")) { | 
 | 		xmlSchemaParseComplexType(pctxt, schema, child, 1); | 
 | 		/* hasRedefinitions = 1; */ | 
 | 	    } else if (IS_SCHEMA(child, "group")) { | 
 | 		/* hasRedefinitions = 1; */ | 
 | 		xmlSchemaParseModelGroupDefinition(pctxt, | 
 | 		    schema, child); | 
 | 	    } else if (IS_SCHEMA(child, "attributeGroup")) { | 
 | 		/* hasRedefinitions = 1; */ | 
 | 		xmlSchemaParseAttributeGroupDefinition(pctxt, schema, | 
 | 		    child); | 
 | 	    } | 
 | 	    child = child->next; | 
 | 	} | 
 | 	pctxt->redefined = NULL; | 
 | 	pctxt->isRedefine = 0; | 
 |     } else { | 
 | 	if (IS_SCHEMA(child, "annotation")) { | 
 | 	    /* | 
 | 	    * TODO: discard or not? | 
 | 	    */ | 
 | 	    child = child->next; | 
 | 	} | 
 |     } | 
 |     if (child != NULL) { | 
 | 	res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED; | 
 | 	if (type == XML_SCHEMA_SCHEMA_REDEFINE) { | 
 | 	    xmlSchemaPContentErr(pctxt, res, | 
 | 		NULL, node, child, NULL, | 
 | 		"(annotation | (simpleType | complexType | group | attributeGroup))*"); | 
 | 	} else { | 
 | 	     xmlSchemaPContentErr(pctxt, res, | 
 | 		NULL, node, child, NULL, | 
 | 		"(annotation?)"); | 
 | 	} | 
 |     } | 
 |     return(res); | 
 |  | 
 | exit_error: | 
 |     return(pctxt->err); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema, | 
 |                        xmlNodePtr node) | 
 | { | 
 |     int res; | 
 | #ifndef ENABLE_REDEFINE | 
 |     TODO | 
 |     return(0); | 
 | #endif | 
 |     res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node, | 
 | 	XML_SCHEMA_SCHEMA_REDEFINE); | 
 |     if (res != 0) | 
 | 	return(res); | 
 |     return(0); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema, | 
 |                        xmlNodePtr node) | 
 | { | 
 |     int res; | 
 |  | 
 |     res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node, | 
 | 	XML_SCHEMA_SCHEMA_INCLUDE); | 
 |     if (res != 0) | 
 | 	return(res); | 
 |     return(0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaParseModelGroup: | 
 |  * @ctxt:  a schema validation context | 
 |  * @schema:  the schema being built | 
 |  * @node:  a subtree containing XML Schema informations | 
 |  * @type: the "compositor" type | 
 |  * @particleNeeded: if a a model group with a particle | 
 |  * | 
 |  * parse a XML schema Sequence definition. | 
 |  * Applies parts of: | 
 |  *   Schema Representation Constraint: | 
 |  *     Redefinition Constraints and Semantics (src-redefine) | 
 |  *     (6.1), (6.1.1), (6.1.2) | 
 |  * | 
 |  *   Schema Component Constraint: | 
 |  *     All Group Limited (cos-all-limited) (2) | 
 |  *     TODO: Actually this should go to component-level checks, | 
 |  *     but is done here due to performance. Move it to an other layer | 
 |  *     is schema construction via an API is implemented. | 
 |  * | 
 |  * *WARNING* this interface is highly subject to change | 
 |  * | 
 |  * Returns -1 in case of error, 0 if the declaration is improper and | 
 |  *         1 in case of success. | 
 |  */ | 
 | static xmlSchemaTreeItemPtr | 
 | xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | 
 | 			 xmlNodePtr node, xmlSchemaTypeType type, | 
 | 			 int withParticle) | 
 | { | 
 |     xmlSchemaModelGroupPtr item; | 
 |     xmlSchemaParticlePtr particle = NULL; | 
 |     xmlNodePtr child = NULL; | 
 |     xmlAttrPtr attr; | 
 |     int min = 1, max = 1, isElemRef, hasRefs = 0; | 
 |  | 
 |     if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) | 
 |         return (NULL); | 
 |     /* | 
 |     * Create a model group with the given compositor. | 
 |     */ | 
 |     item = xmlSchemaAddModelGroup(ctxt, schema, type, node); | 
 |     if (item == NULL) | 
 | 	return (NULL); | 
 |  | 
 |     if (withParticle) { | 
 | 	if (type == XML_SCHEMA_TYPE_ALL) { | 
 | 	    min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)"); | 
 | 	    max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1"); | 
 | 	} else { | 
 | 	    /* choice + sequence */ | 
 | 	    min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger"); | 
 | 	    max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, | 
 | 		"(xs:nonNegativeInteger | unbounded)"); | 
 | 	} | 
 | 	xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max); | 
 | 	/* | 
 | 	* Create a particle | 
 | 	*/ | 
 | 	particle = xmlSchemaAddParticle(ctxt, node, min, max); | 
 | 	if (particle == NULL) | 
 | 	    return (NULL); | 
 | 	particle->children = (xmlSchemaTreeItemPtr) item; | 
 | 	/* | 
 | 	* Check for illegal attributes. | 
 | 	*/ | 
 | 	attr = node->properties; | 
 | 	while (attr != NULL) { | 
 | 	    if (attr->ns == NULL) { | 
 | 		if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && | 
 | 		    (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) && | 
 | 		    (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) { | 
 | 		    xmlSchemaPIllegalAttrErr(ctxt, | 
 | 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 		} | 
 | 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | 
 | 		xmlSchemaPIllegalAttrErr(ctxt, | 
 | 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	    } | 
 | 	    attr = attr->next; | 
 | 	} | 
 |     } else { | 
 | 	/* | 
 | 	* Check for illegal attributes. | 
 | 	*/ | 
 | 	attr = node->properties; | 
 | 	while (attr != NULL) { | 
 | 	    if (attr->ns == NULL) { | 
 | 		if (!xmlStrEqual(attr->name, BAD_CAST "id")) { | 
 | 		    xmlSchemaPIllegalAttrErr(ctxt, | 
 | 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 		} | 
 | 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | 
 | 		xmlSchemaPIllegalAttrErr(ctxt, | 
 | 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	    } | 
 | 	    attr = attr->next; | 
 | 	} | 
 |     } | 
 |  | 
 |     /* | 
 |     * Extract and validate attributes. | 
 |     */ | 
 |     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | 
 |     /* | 
 |     * And now for the children... | 
 |     */ | 
 |     child = node->children; | 
 |     if (IS_SCHEMA(child, "annotation")) { | 
 |         item->annot = xmlSchemaParseAnnotation(ctxt, child, 1); | 
 |         child = child->next; | 
 |     } | 
 |     if (type == XML_SCHEMA_TYPE_ALL) { | 
 | 	xmlSchemaParticlePtr part, last = NULL; | 
 |  | 
 | 	while (IS_SCHEMA(child, "element")) { | 
 | 	    part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt, | 
 | 		schema, child, &isElemRef, 0); | 
 | 	    /* | 
 | 	    * SPEC cos-all-limited (2) | 
 | 	    * "The {max occurs} of all the particles in the {particles} | 
 | 	    * of the ('all') group must be 0 or 1. | 
 | 	    */ | 
 | 	    if (part != NULL) { | 
 | 		if (isElemRef) | 
 | 		    hasRefs++; | 
 | 		if (part->minOccurs > 1) { | 
 | 		    xmlSchemaPCustomErr(ctxt, | 
 | 			XML_SCHEMAP_COS_ALL_LIMITED, | 
 | 			NULL, child, | 
 | 			"Invalid value for minOccurs (must be 0 or 1)", | 
 | 			NULL); | 
 | 		    /* Reset to 1. */ | 
 | 		    part->minOccurs = 1; | 
 | 		} | 
 | 		if (part->maxOccurs > 1) { | 
 | 		    xmlSchemaPCustomErr(ctxt, | 
 | 			XML_SCHEMAP_COS_ALL_LIMITED, | 
 | 			NULL, child, | 
 | 			"Invalid value for maxOccurs (must be 0 or 1)", | 
 | 			NULL); | 
 | 		    /* Reset to 1. */ | 
 | 		    part->maxOccurs = 1; | 
 | 		} | 
 | 		if (last == NULL) | 
 | 		    item->children = (xmlSchemaTreeItemPtr) part; | 
 | 		else | 
 | 		    last->next = (xmlSchemaTreeItemPtr) part; | 
 | 		last = part; | 
 | 	    } | 
 | 	    child = child->next; | 
 | 	} | 
 | 	if (child != NULL) { | 
 | 	    xmlSchemaPContentErr(ctxt, | 
 | 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | 
 | 		NULL, node, child, NULL, | 
 | 		"(annotation?, (annotation?, element*)"); | 
 | 	} | 
 |     } else { | 
 | 	/* choice + sequence */ | 
 | 	xmlSchemaTreeItemPtr part = NULL, last = NULL; | 
 |  | 
 | 	while ((IS_SCHEMA(child, "element")) || | 
 | 	    (IS_SCHEMA(child, "group")) || | 
 | 	    (IS_SCHEMA(child, "any")) || | 
 | 	    (IS_SCHEMA(child, "choice")) || | 
 | 	    (IS_SCHEMA(child, "sequence"))) { | 
 |  | 
 | 	    if (IS_SCHEMA(child, "element")) { | 
 | 		part = (xmlSchemaTreeItemPtr) | 
 | 		    xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0); | 
 | 		if (part && isElemRef) | 
 | 		    hasRefs++; | 
 | 	    } else if (IS_SCHEMA(child, "group")) { | 
 | 		part = | 
 | 		    xmlSchemaParseModelGroupDefRef(ctxt, schema, child); | 
 | 		if (part != NULL) | 
 | 		    hasRefs++; | 
 | 		/* | 
 | 		* Handle redefinitions. | 
 | 		*/ | 
 | 		if (ctxt->isRedefine && ctxt->redef && | 
 | 		    (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) && | 
 | 		    part && part->children) | 
 | 		{ | 
 | 		    if ((xmlSchemaGetQNameRefName(part->children) == | 
 | 			    ctxt->redef->refName) && | 
 | 			(xmlSchemaGetQNameRefTargetNs(part->children) == | 
 | 			    ctxt->redef->refTargetNs)) | 
 | 		    { | 
 | 			/* | 
 | 			* SPEC src-redefine: | 
 | 			* (6.1) "If it has a <group> among its contents at | 
 | 			* some level the �actual value� of whose ref | 
 | 			* [attribute] is the same as the �actual value� of | 
 | 			* its own name attribute plus target namespace, then | 
 | 			* all of the following must be true:" | 
 | 			* (6.1.1) "It must have exactly one such group." | 
 | 			*/ | 
 | 			if (ctxt->redefCounter != 0) { | 
 | 			    xmlChar *str = NULL; | 
 |  | 
 | 			    xmlSchemaCustomErr(ACTXT_CAST ctxt, | 
 | 				XML_SCHEMAP_SRC_REDEFINE, child, NULL, | 
 | 				"The redefining model group definition " | 
 | 				"'%s' must not contain more than one " | 
 | 				"reference to the redefined definition", | 
 | 				xmlSchemaFormatQName(&str, | 
 | 				    ctxt->redef->refTargetNs, | 
 | 				    ctxt->redef->refName), | 
 | 				NULL); | 
 | 			    FREE_AND_NULL(str) | 
 | 			    part = NULL; | 
 | 			} else if (((WXS_PARTICLE(part))->minOccurs != 1) || | 
 | 			    ((WXS_PARTICLE(part))->maxOccurs != 1)) | 
 | 			{ | 
 | 			    xmlChar *str = NULL; | 
 | 			    /* | 
 | 			    * SPEC src-redefine: | 
 | 			    * (6.1.2) "The �actual value� of both that | 
 | 			    * group's minOccurs and maxOccurs [attribute] | 
 | 			    * must be 1 (or �absent�). | 
 | 			    */ | 
 | 			    xmlSchemaCustomErr(ACTXT_CAST ctxt, | 
 | 				XML_SCHEMAP_SRC_REDEFINE, child, NULL, | 
 | 				"The redefining model group definition " | 
 | 				"'%s' must not contain a reference to the " | 
 | 				"redefined definition with a " | 
 | 				"maxOccurs/minOccurs other than 1", | 
 | 				xmlSchemaFormatQName(&str, | 
 | 				    ctxt->redef->refTargetNs, | 
 | 				    ctxt->redef->refName), | 
 | 				NULL); | 
 | 			    FREE_AND_NULL(str) | 
 | 			    part = NULL; | 
 | 			} | 
 | 			ctxt->redef->reference = WXS_BASIC_CAST part; | 
 | 			ctxt->redefCounter++; | 
 | 		    } | 
 | 		} | 
 | 	    } else if (IS_SCHEMA(child, "any")) { | 
 | 		part = (xmlSchemaTreeItemPtr) | 
 | 		    xmlSchemaParseAny(ctxt, schema, child); | 
 | 	    } else if (IS_SCHEMA(child, "choice")) { | 
 | 		part = xmlSchemaParseModelGroup(ctxt, schema, child, | 
 | 		    XML_SCHEMA_TYPE_CHOICE, 1); | 
 | 	    } else if (IS_SCHEMA(child, "sequence")) { | 
 | 		part = xmlSchemaParseModelGroup(ctxt, schema, child, | 
 | 		    XML_SCHEMA_TYPE_SEQUENCE, 1); | 
 | 	    } | 
 | 	    if (part != NULL) { | 
 | 		if (last == NULL) | 
 | 		    item->children = part; | 
 | 		else | 
 | 		    last->next = part; | 
 | 		last = part; | 
 | 	    } | 
 | 	    child = child->next; | 
 | 	} | 
 | 	if (child != NULL) { | 
 | 	    xmlSchemaPContentErr(ctxt, | 
 | 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | 
 | 		NULL, node, child, NULL, | 
 | 		"(annotation?, (element | group | choice | sequence | any)*)"); | 
 | 	} | 
 |     } | 
 |     if ((max == 0) && (min == 0)) | 
 | 	return (NULL); | 
 |     if (hasRefs) { | 
 | 	/* | 
 | 	* We need to resolve references. | 
 | 	*/ | 
 | 	WXS_ADD_PENDING(ctxt, item); | 
 |     } | 
 |     if (withParticle) | 
 | 	return ((xmlSchemaTreeItemPtr) particle); | 
 |     else | 
 | 	return ((xmlSchemaTreeItemPtr) item); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaParseRestriction: | 
 |  * @ctxt:  a schema validation context | 
 |  * @schema:  the schema being built | 
 |  * @node:  a subtree containing XML Schema informations | 
 |  * | 
 |  * parse a XML schema Restriction definition | 
 |  * *WARNING* this interface is highly subject to change | 
 |  * | 
 |  * Returns the type definition or NULL in case of error | 
 |  */ | 
 | static xmlSchemaTypePtr | 
 | xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | 
 |                           xmlNodePtr node, xmlSchemaTypeType parentType) | 
 | { | 
 |     xmlSchemaTypePtr type; | 
 |     xmlNodePtr child = NULL; | 
 |     xmlAttrPtr attr; | 
 |  | 
 |     if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) | 
 |         return (NULL); | 
 |     /* Not a component, don't create it. */ | 
 |     type = ctxt->ctxtType; | 
 |     type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION; | 
 |  | 
 |     /* | 
 |     * Check for illegal attributes. | 
 |     */ | 
 |     attr = node->properties; | 
 |     while (attr != NULL) { | 
 | 	if (attr->ns == NULL) { | 
 | 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && | 
 | 		(!xmlStrEqual(attr->name, BAD_CAST "base"))) { | 
 | 		xmlSchemaPIllegalAttrErr(ctxt, | 
 | 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	    } | 
 | 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | 
 | 	    xmlSchemaPIllegalAttrErr(ctxt, | 
 | 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	} | 
 | 	attr = attr->next; | 
 |     } | 
 |     /* | 
 |     * Extract and validate attributes. | 
 |     */ | 
 |     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | 
 |     /* | 
 |     * Attribute | 
 |     */ | 
 |     /* | 
 |     * Extract the base type. The "base" attribute is mandatory if inside | 
 |     * a complex type or if redefining. | 
 |     * | 
 |     * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> " | 
 |     * among its [children]), the simple type definition which is | 
 |     * the {content type} of the type definition �resolved� to by | 
 |     * the �actual value� of the base [attribute]" | 
 |     */ | 
 |     if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base", | 
 | 	&(type->baseNs), &(type->base)) == 0) | 
 |     { | 
 | 	if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) { | 
 | 	    xmlSchemaPMissingAttrErr(ctxt, | 
 | 		XML_SCHEMAP_S4S_ATTR_MISSING, | 
 | 		NULL, node, "base", NULL); | 
 | 	} else if ((ctxt->isRedefine) && | 
 | 	    (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) | 
 | 	{ | 
 | 	    if (type->base == NULL) { | 
 | 		xmlSchemaPMissingAttrErr(ctxt, | 
 | 		    XML_SCHEMAP_S4S_ATTR_MISSING, | 
 | 		    NULL, node, "base", NULL); | 
 | 	    } else if ((! xmlStrEqual(type->base, type->name)) || | 
 | 		(! xmlStrEqual(type->baseNs, type->targetNamespace))) | 
 | 	    { | 
 | 		xmlChar *str1 = NULL, *str2 = NULL; | 
 | 		/* | 
 | 		* REDEFINE: SPEC src-redefine (5) | 
 | 		* "Within the [children], each <simpleType> must have a | 
 | 		* <restriction> among its [children] ... the �actual value� of | 
 | 		* whose base [attribute] must be the same as the �actual value� | 
 | 		* of its own name attribute plus target namespace;" | 
 | 		*/ | 
 | 		xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE, | 
 | 		    NULL, node, "This is a redefinition, but the QName " | 
 | 		    "value '%s' of the 'base' attribute does not match the " | 
 | 		    "type's designation '%s'", | 
 | 		    xmlSchemaFormatQName(&str1, type->baseNs, type->base), | 
 | 		    xmlSchemaFormatQName(&str2, type->targetNamespace, | 
 | 			type->name), NULL); | 
 | 		FREE_AND_NULL(str1); | 
 | 		FREE_AND_NULL(str2); | 
 | 		/* Avoid confusion and erase the values. */ | 
 | 		type->base = NULL; | 
 | 		type->baseNs = NULL; | 
 | 	    } | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * And now for the children... | 
 |     */ | 
 |     child = node->children; | 
 |     if (IS_SCHEMA(child, "annotation")) { | 
 | 	/* | 
 | 	* Add the annotation to the simple type ancestor. | 
 | 	*/ | 
 | 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type, | 
 | 	    xmlSchemaParseAnnotation(ctxt, child, 1)); | 
 |         child = child->next; | 
 |     } | 
 |     if (parentType == XML_SCHEMA_TYPE_SIMPLE) { | 
 | 	/* | 
 | 	* Corresponds to <simpleType><restriction><simpleType>. | 
 | 	*/ | 
 | 	if (IS_SCHEMA(child, "simpleType")) { | 
 | 	    if (type->base != NULL) { | 
 | 		/* | 
 | 		* src-restriction-base-or-simpleType | 
 | 		* Either the base [attribute] or the simpleType [child] of the | 
 | 		* <restriction> element must be present, but not both. | 
 | 		*/ | 
 | 		xmlSchemaPContentErr(ctxt, | 
 | 		    XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE, | 
 | 		    NULL, node, child, | 
 | 		    "The attribute 'base' and the <simpleType> child are " | 
 | 		    "mutually exclusive", NULL); | 
 | 	    } else { | 
 | 		type->baseType = (xmlSchemaTypePtr) | 
 | 		    xmlSchemaParseSimpleType(ctxt, schema, child, 0); | 
 | 	    } | 
 | 	    child = child->next; | 
 | 	} else if (type->base == NULL) { | 
 | 	    xmlSchemaPContentErr(ctxt, | 
 | 		XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE, | 
 | 		NULL, node, child, | 
 | 		"Either the attribute 'base' or a <simpleType> child " | 
 | 		"must be present", NULL); | 
 | 	} | 
 |     } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) { | 
 | 	/* | 
 | 	* Corresponds to <complexType><complexContent><restriction>... | 
 | 	* followed by: | 
 | 	* | 
 | 	* Model groups <all>, <choice> and <sequence>. | 
 | 	*/ | 
 | 	if (IS_SCHEMA(child, "all")) { | 
 | 	    type->subtypes = (xmlSchemaTypePtr) | 
 | 		xmlSchemaParseModelGroup(ctxt, schema, child, | 
 | 		    XML_SCHEMA_TYPE_ALL, 1); | 
 | 	    child = child->next; | 
 | 	} else if (IS_SCHEMA(child, "choice")) { | 
 | 	    type->subtypes = (xmlSchemaTypePtr) | 
 | 		xmlSchemaParseModelGroup(ctxt, | 
 | 		    schema, child, XML_SCHEMA_TYPE_CHOICE, 1); | 
 | 	    child = child->next; | 
 | 	} else if (IS_SCHEMA(child, "sequence")) { | 
 | 	    type->subtypes = (xmlSchemaTypePtr) | 
 | 		xmlSchemaParseModelGroup(ctxt, schema, child, | 
 | 		    XML_SCHEMA_TYPE_SEQUENCE, 1); | 
 | 	    child = child->next; | 
 | 	/* | 
 | 	* Model group reference <group>. | 
 | 	*/ | 
 | 	} else if (IS_SCHEMA(child, "group")) { | 
 | 	    type->subtypes = (xmlSchemaTypePtr) | 
 | 		xmlSchemaParseModelGroupDefRef(ctxt, schema, child); | 
 | 	    /* | 
 | 	    * Note that the reference will be resolved in | 
 | 	    * xmlSchemaResolveTypeReferences(); | 
 | 	    */ | 
 | 	    child = child->next; | 
 | 	} | 
 |     } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) { | 
 | 	/* | 
 | 	* Corresponds to <complexType><simpleContent><restriction>... | 
 | 	* | 
 | 	* "1.1 the simple type definition corresponding to the <simpleType> | 
 | 	* among the [children] of <restriction> if there is one;" | 
 | 	*/ | 
 | 	if (IS_SCHEMA(child, "simpleType")) { | 
 | 	    /* | 
 | 	    * We will store the to-be-restricted simple type in | 
 | 	    * type->contentTypeDef *temporarily*. | 
 | 	    */ | 
 | 	    type->contentTypeDef = (xmlSchemaTypePtr) | 
 | 		xmlSchemaParseSimpleType(ctxt, schema, child, 0); | 
 | 	    if ( type->contentTypeDef == NULL) | 
 | 		return (NULL); | 
 | 	    child = child->next; | 
 | 	} | 
 |     } | 
 |  | 
 |     if ((parentType == XML_SCHEMA_TYPE_SIMPLE) || | 
 | 	(parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) { | 
 | 	xmlSchemaFacetPtr facet, lastfacet = NULL; | 
 | 	/* | 
 | 	* Corresponds to <complexType><simpleContent><restriction>... | 
 | 	* <simpleType><restriction>... | 
 | 	*/ | 
 |  | 
 | 	/* | 
 | 	* Add the facets to the simple type ancestor. | 
 | 	*/ | 
 | 	/* | 
 | 	* TODO: Datatypes: 4.1.3 Constraints on XML Representation of | 
 | 	* Simple Type Definition Schema Representation Constraint: | 
 | 	* *Single Facet Value* | 
 | 	*/ | 
 | 	while ((IS_SCHEMA(child, "minInclusive")) || | 
 | 	    (IS_SCHEMA(child, "minExclusive")) || | 
 | 	    (IS_SCHEMA(child, "maxInclusive")) || | 
 | 	    (IS_SCHEMA(child, "maxExclusive")) || | 
 | 	    (IS_SCHEMA(child, "totalDigits")) || | 
 | 	    (IS_SCHEMA(child, "fractionDigits")) || | 
 | 	    (IS_SCHEMA(child, "pattern")) || | 
 | 	    (IS_SCHEMA(child, "enumeration")) || | 
 | 	    (IS_SCHEMA(child, "whiteSpace")) || | 
 | 	    (IS_SCHEMA(child, "length")) || | 
 | 	    (IS_SCHEMA(child, "maxLength")) || | 
 | 	    (IS_SCHEMA(child, "minLength"))) { | 
 | 	    facet = xmlSchemaParseFacet(ctxt, schema, child); | 
 | 	    if (facet != NULL) { | 
 | 		if (lastfacet == NULL) | 
 | 		    type->facets = facet; | 
 | 		else | 
 | 		    lastfacet->next = facet; | 
 | 		lastfacet = facet; | 
 | 		lastfacet->next = NULL; | 
 | 	    } | 
 | 	    child = child->next; | 
 | 	} | 
 | 	/* | 
 | 	* Create links for derivation and validation. | 
 | 	*/ | 
 | 	if (type->facets != NULL) { | 
 | 	    xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL; | 
 |  | 
 | 	    facet = type->facets; | 
 | 	    do { | 
 | 		facetLink = (xmlSchemaFacetLinkPtr) | 
 | 		    xmlMalloc(sizeof(xmlSchemaFacetLink)); | 
 | 		if (facetLink == NULL) { | 
 | 		    xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL); | 
 | 		    xmlFree(facetLink); | 
 | 		    return (NULL); | 
 | 		} | 
 | 		facetLink->facet = facet; | 
 | 		facetLink->next = NULL; | 
 | 		if (lastFacetLink == NULL) | 
 | 		    type->facetSet = facetLink; | 
 | 		else | 
 | 		    lastFacetLink->next = facetLink; | 
 | 		lastFacetLink = facetLink; | 
 | 		facet = facet->next; | 
 | 	    } while (facet != NULL); | 
 | 	} | 
 |     } | 
 |     if (type->type == XML_SCHEMA_TYPE_COMPLEX) { | 
 | 	/* | 
 | 	* Attribute uses/declarations. | 
 | 	*/ | 
 | 	if (xmlSchemaParseLocalAttributes(ctxt, schema, &child, | 
 | 	    (xmlSchemaItemListPtr *) &(type->attrUses), | 
 | 	    XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1) | 
 | 	    return(NULL); | 
 | 	/* | 
 | 	* Attribute wildcard. | 
 | 	*/ | 
 | 	if (IS_SCHEMA(child, "anyAttribute")) { | 
 | 	    type->attributeWildcard = | 
 | 		xmlSchemaParseAnyAttribute(ctxt, schema, child); | 
 | 	    child = child->next; | 
 | 	} | 
 |     } | 
 |     if (child != NULL) { | 
 | 	if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) { | 
 | 	    xmlSchemaPContentErr(ctxt, | 
 | 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | 
 | 		NULL, node, child, NULL, | 
 | 		"annotation?, (group | all | choice | sequence)?, " | 
 | 		"((attribute | attributeGroup)*, anyAttribute?))"); | 
 | 	} else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) { | 
 | 	     xmlSchemaPContentErr(ctxt, | 
 | 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | 
 | 		NULL, node, child, NULL, | 
 | 		"(annotation?, (simpleType?, (minExclusive | minInclusive | " | 
 | 		"maxExclusive | maxInclusive | totalDigits | fractionDigits | " | 
 | 		"length | minLength | maxLength | enumeration | whiteSpace | " | 
 | 		"pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))"); | 
 | 	} else { | 
 | 	    /* Simple type */ | 
 | 	    xmlSchemaPContentErr(ctxt, | 
 | 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | 
 | 		NULL, node, child, NULL, | 
 | 		"(annotation?, (simpleType?, (minExclusive | minInclusive | " | 
 | 		"maxExclusive | maxInclusive | totalDigits | fractionDigits | " | 
 | 		"length | minLength | maxLength | enumeration | whiteSpace | " | 
 | 		"pattern)*))"); | 
 | 	} | 
 |     } | 
 |     return (NULL); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaParseExtension: | 
 |  * @ctxt:  a schema validation context | 
 |  * @schema:  the schema being built | 
 |  * @node:  a subtree containing XML Schema informations | 
 |  * | 
 |  * Parses an <extension>, which is found inside a | 
 |  * <simpleContent> or <complexContent>. | 
 |  * *WARNING* this interface is highly subject to change. | 
 |  * | 
 |  * TODO: Returns the type definition or NULL in case of error | 
 |  */ | 
 | static xmlSchemaTypePtr | 
 | xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | 
 |                         xmlNodePtr node, xmlSchemaTypeType parentType) | 
 | { | 
 |     xmlSchemaTypePtr type; | 
 |     xmlNodePtr child = NULL; | 
 |     xmlAttrPtr attr; | 
 |  | 
 |     if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) | 
 |         return (NULL); | 
 |     /* Not a component, don't create it. */ | 
 |     type = ctxt->ctxtType; | 
 |     type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION; | 
 |  | 
 |     /* | 
 |     * Check for illegal attributes. | 
 |     */ | 
 |     attr = node->properties; | 
 |     while (attr != NULL) { | 
 | 	if (attr->ns == NULL) { | 
 | 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && | 
 | 		(!xmlStrEqual(attr->name, BAD_CAST "base"))) { | 
 | 		xmlSchemaPIllegalAttrErr(ctxt, | 
 | 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	    } | 
 | 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | 
 | 	    xmlSchemaPIllegalAttrErr(ctxt, | 
 | 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	} | 
 | 	attr = attr->next; | 
 |     } | 
 |  | 
 |     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | 
 |  | 
 |     /* | 
 |     * Attribute "base" - mandatory. | 
 |     */ | 
 |     if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node, | 
 | 	"base", &(type->baseNs), &(type->base)) == 0) && | 
 | 	(type->base == NULL)) { | 
 | 	xmlSchemaPMissingAttrErr(ctxt, | 
 | 	    XML_SCHEMAP_S4S_ATTR_MISSING, | 
 | 	    NULL, node, "base", NULL); | 
 |     } | 
 |     /* | 
 |     * And now for the children... | 
 |     */ | 
 |     child = node->children; | 
 |     if (IS_SCHEMA(child, "annotation")) { | 
 | 	/* | 
 | 	* Add the annotation to the type ancestor. | 
 | 	*/ | 
 | 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type, | 
 | 	    xmlSchemaParseAnnotation(ctxt, child, 1)); | 
 |         child = child->next; | 
 |     } | 
 |     if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) { | 
 | 	/* | 
 | 	* Corresponds to <complexType><complexContent><extension>... and: | 
 | 	* | 
 | 	* Model groups <all>, <choice>, <sequence> and <group>. | 
 | 	*/ | 
 | 	if (IS_SCHEMA(child, "all")) { | 
 | 	    type->subtypes = (xmlSchemaTypePtr) | 
 | 		xmlSchemaParseModelGroup(ctxt, schema, | 
 | 		    child, XML_SCHEMA_TYPE_ALL, 1); | 
 | 	    child = child->next; | 
 | 	} else if (IS_SCHEMA(child, "choice")) { | 
 | 	    type->subtypes = (xmlSchemaTypePtr) | 
 | 		xmlSchemaParseModelGroup(ctxt, schema, | 
 | 		    child, XML_SCHEMA_TYPE_CHOICE, 1); | 
 | 	    child = child->next; | 
 | 	} else if (IS_SCHEMA(child, "sequence")) { | 
 | 	    type->subtypes = (xmlSchemaTypePtr) | 
 | 		xmlSchemaParseModelGroup(ctxt, schema, | 
 | 		child, XML_SCHEMA_TYPE_SEQUENCE, 1); | 
 | 	    child = child->next; | 
 | 	} else if (IS_SCHEMA(child, "group")) { | 
 | 	    type->subtypes = (xmlSchemaTypePtr) | 
 | 		xmlSchemaParseModelGroupDefRef(ctxt, schema, child); | 
 | 	    /* | 
 | 	    * Note that the reference will be resolved in | 
 | 	    * xmlSchemaResolveTypeReferences(); | 
 | 	    */ | 
 | 	    child = child->next; | 
 | 	} | 
 |     } | 
 |     if (child != NULL) { | 
 | 	/* | 
 | 	* Attribute uses/declarations. | 
 | 	*/ | 
 | 	if (xmlSchemaParseLocalAttributes(ctxt, schema, &child, | 
 | 	    (xmlSchemaItemListPtr *) &(type->attrUses), | 
 | 	    XML_SCHEMA_TYPE_EXTENSION, NULL) == -1) | 
 | 	    return(NULL); | 
 | 	/* | 
 | 	* Attribute wildcard. | 
 | 	*/ | 
 | 	if (IS_SCHEMA(child, "anyAttribute")) { | 
 | 	    ctxt->ctxtType->attributeWildcard = | 
 | 		xmlSchemaParseAnyAttribute(ctxt, schema, child); | 
 | 	    child = child->next; | 
 | 	} | 
 |     } | 
 |     if (child != NULL) { | 
 | 	if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) { | 
 | 	    /* Complex content extension. */ | 
 | 	    xmlSchemaPContentErr(ctxt, | 
 | 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | 
 | 		NULL, node, child, NULL, | 
 | 		"(annotation?, ((group | all | choice | sequence)?, " | 
 | 		"((attribute | attributeGroup)*, anyAttribute?)))"); | 
 | 	} else { | 
 | 	    /* Simple content extension. */ | 
 | 	    xmlSchemaPContentErr(ctxt, | 
 | 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | 
 | 		NULL, node, child, NULL, | 
 | 		"(annotation?, ((attribute | attributeGroup)*, " | 
 | 		"anyAttribute?))"); | 
 | 	} | 
 |     } | 
 |     return (NULL); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaParseSimpleContent: | 
 |  * @ctxt:  a schema validation context | 
 |  * @schema:  the schema being built | 
 |  * @node:  a subtree containing XML Schema informations | 
 |  * | 
 |  * parse a XML schema SimpleContent definition | 
 |  * *WARNING* this interface is highly subject to change | 
 |  * | 
 |  * Returns the type definition or NULL in case of error | 
 |  */ | 
 | static int | 
 | xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt, | 
 |                             xmlSchemaPtr schema, xmlNodePtr node, | 
 | 			    int *hasRestrictionOrExtension) | 
 | { | 
 |     xmlSchemaTypePtr type; | 
 |     xmlNodePtr child = NULL; | 
 |     xmlAttrPtr attr; | 
 |  | 
 |     if ((ctxt == NULL) || (schema == NULL) || (node == NULL) || | 
 | 	(hasRestrictionOrExtension == NULL)) | 
 |         return (-1); | 
 |     *hasRestrictionOrExtension = 0; | 
 |     /* Not a component, don't create it. */ | 
 |     type = ctxt->ctxtType; | 
 |     type->contentType = XML_SCHEMA_CONTENT_SIMPLE; | 
 |     /* | 
 |     * Check for illegal attributes. | 
 |     */ | 
 |     attr = node->properties; | 
 |     while (attr != NULL) { | 
 | 	if (attr->ns == NULL) { | 
 | 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) { | 
 | 		xmlSchemaPIllegalAttrErr(ctxt, | 
 | 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	    } | 
 | 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | 
 | 	    xmlSchemaPIllegalAttrErr(ctxt, | 
 | 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	} | 
 | 	attr = attr->next; | 
 |     } | 
 |  | 
 |     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | 
 |  | 
 |     /* | 
 |     * And now for the children... | 
 |     */ | 
 |     child = node->children; | 
 |     if (IS_SCHEMA(child, "annotation")) { | 
 | 	/* | 
 | 	* Add the annotation to the complex type ancestor. | 
 | 	*/ | 
 | 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type, | 
 | 	    xmlSchemaParseAnnotation(ctxt, child, 1)); | 
 |         child = child->next; | 
 |     } | 
 |     if (child == NULL) { | 
 | 	xmlSchemaPContentErr(ctxt, | 
 | 	    XML_SCHEMAP_S4S_ELEM_MISSING, | 
 | 	    NULL, node, NULL, NULL, | 
 | 	    "(annotation?, (restriction | extension))"); | 
 |     } | 
 |     if (child == NULL) { | 
 | 	xmlSchemaPContentErr(ctxt, | 
 | 	    XML_SCHEMAP_S4S_ELEM_MISSING, | 
 | 	    NULL, node, NULL, NULL, | 
 | 	    "(annotation?, (restriction | extension))"); | 
 |     } | 
 |     if (IS_SCHEMA(child, "restriction")) { | 
 |         xmlSchemaParseRestriction(ctxt, schema, child, | 
 | 	    XML_SCHEMA_TYPE_SIMPLE_CONTENT); | 
 | 	(*hasRestrictionOrExtension) = 1; | 
 |         child = child->next; | 
 |     } else if (IS_SCHEMA(child, "extension")) { | 
 |         xmlSchemaParseExtension(ctxt, schema, child, | 
 | 	    XML_SCHEMA_TYPE_SIMPLE_CONTENT); | 
 | 	(*hasRestrictionOrExtension) = 1; | 
 |         child = child->next; | 
 |     } | 
 |     if (child != NULL) { | 
 | 	xmlSchemaPContentErr(ctxt, | 
 | 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | 
 | 	    NULL, node, child, NULL, | 
 | 	    "(annotation?, (restriction | extension))"); | 
 |     } | 
 |     return (0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaParseComplexContent: | 
 |  * @ctxt:  a schema validation context | 
 |  * @schema:  the schema being built | 
 |  * @node:  a subtree containing XML Schema informations | 
 |  * | 
 |  * parse a XML schema ComplexContent definition | 
 |  * *WARNING* this interface is highly subject to change | 
 |  * | 
 |  * Returns the type definition or NULL in case of error | 
 |  */ | 
 | static int | 
 | xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt, | 
 |                              xmlSchemaPtr schema, xmlNodePtr node, | 
 | 			     int *hasRestrictionOrExtension) | 
 | { | 
 |     xmlSchemaTypePtr type; | 
 |     xmlNodePtr child = NULL; | 
 |     xmlAttrPtr attr; | 
 |  | 
 |     if ((ctxt == NULL) || (schema == NULL) || (node == NULL) || | 
 | 	(hasRestrictionOrExtension == NULL)) | 
 |         return (-1); | 
 |     *hasRestrictionOrExtension = 0; | 
 |     /* Not a component, don't create it. */ | 
 |     type = ctxt->ctxtType; | 
 |     /* | 
 |     * Check for illegal attributes. | 
 |     */ | 
 |     attr = node->properties; | 
 |     while (attr != NULL) { | 
 | 	if (attr->ns == NULL) { | 
 | 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) && | 
 | 		(!xmlStrEqual(attr->name, BAD_CAST "mixed"))) | 
 | 	    { | 
 | 		xmlSchemaPIllegalAttrErr(ctxt, | 
 | 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	    } | 
 | 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | 
 | 	    xmlSchemaPIllegalAttrErr(ctxt, | 
 | 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	} | 
 | 	attr = attr->next; | 
 |     } | 
 |  | 
 |     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | 
 |  | 
 |     /* | 
 |     * Set the 'mixed' on the complex type ancestor. | 
 |     */ | 
 |     if (xmlGetBooleanProp(ctxt, node, "mixed", 0))  { | 
 | 	if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0) | 
 | 	    type->flags |= XML_SCHEMAS_TYPE_MIXED; | 
 |     } | 
 |     child = node->children; | 
 |     if (IS_SCHEMA(child, "annotation")) { | 
 | 	/* | 
 | 	* Add the annotation to the complex type ancestor. | 
 | 	*/ | 
 | 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type, | 
 | 	    xmlSchemaParseAnnotation(ctxt, child, 1)); | 
 |         child = child->next; | 
 |     } | 
 |     if (child == NULL) { | 
 | 	xmlSchemaPContentErr(ctxt, | 
 | 	    XML_SCHEMAP_S4S_ELEM_MISSING, | 
 | 	    NULL, node, NULL, | 
 | 	    NULL, "(annotation?, (restriction | extension))"); | 
 |     } | 
 |     if (child == NULL) { | 
 | 	xmlSchemaPContentErr(ctxt, | 
 | 	    XML_SCHEMAP_S4S_ELEM_MISSING, | 
 | 	    NULL, node, NULL, | 
 | 	    NULL, "(annotation?, (restriction | extension))"); | 
 |     } | 
 |     if (IS_SCHEMA(child, "restriction")) { | 
 |         xmlSchemaParseRestriction(ctxt, schema, child, | 
 | 	    XML_SCHEMA_TYPE_COMPLEX_CONTENT); | 
 | 	(*hasRestrictionOrExtension) = 1; | 
 |         child = child->next; | 
 |     } else if (IS_SCHEMA(child, "extension")) { | 
 |         xmlSchemaParseExtension(ctxt, schema, child, | 
 | 	    XML_SCHEMA_TYPE_COMPLEX_CONTENT); | 
 | 	(*hasRestrictionOrExtension) = 1; | 
 |         child = child->next; | 
 |     } | 
 |     if (child != NULL) { | 
 | 	xmlSchemaPContentErr(ctxt, | 
 | 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | 
 | 	    NULL, node, child, | 
 | 	    NULL, "(annotation?, (restriction | extension))"); | 
 |     } | 
 |     return (0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaParseComplexType: | 
 |  * @ctxt:  a schema validation context | 
 |  * @schema:  the schema being built | 
 |  * @node:  a subtree containing XML Schema informations | 
 |  * | 
 |  * parse a XML schema Complex Type definition | 
 |  * *WARNING* this interface is highly subject to change | 
 |  * | 
 |  * Returns the type definition or NULL in case of error | 
 |  */ | 
 | static xmlSchemaTypePtr | 
 | xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, | 
 |                           xmlNodePtr node, int topLevel) | 
 | { | 
 |     xmlSchemaTypePtr type, ctxtType; | 
 |     xmlNodePtr child = NULL; | 
 |     const xmlChar *name = NULL; | 
 |     xmlAttrPtr attr; | 
 |     const xmlChar *attrValue; | 
 | #ifdef ENABLE_NAMED_LOCALS | 
 |     char buf[40]; | 
 | #endif | 
 |     int final = 0, block = 0, hasRestrictionOrExtension = 0; | 
 |  | 
 |  | 
 |     if ((ctxt == NULL) || (schema == NULL) || (node == NULL)) | 
 |         return (NULL); | 
 |  | 
 |     ctxtType = ctxt->ctxtType; | 
 |  | 
 |     if (topLevel) { | 
 | 	attr = xmlSchemaGetPropNode(node, "name"); | 
 | 	if (attr == NULL) { | 
 | 	    xmlSchemaPMissingAttrErr(ctxt, | 
 | 		XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL); | 
 | 	    return (NULL); | 
 | 	} else if (xmlSchemaPValAttrNode(ctxt, NULL, attr, | 
 | 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) { | 
 | 	    return (NULL); | 
 | 	} | 
 |     } | 
 |  | 
 |     if (topLevel == 0) { | 
 | 	/* | 
 | 	* Parse as local complex type definition. | 
 | 	*/ | 
 | #ifdef ENABLE_NAMED_LOCALS | 
 |         snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1); | 
 | 	type = xmlSchemaAddType(ctxt, schema, | 
 | 	    XML_SCHEMA_TYPE_COMPLEX, | 
 | 	    xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1), | 
 | 	    ctxt->targetNamespace, node, 0); | 
 | #else | 
 | 	type = xmlSchemaAddType(ctxt, schema, | 
 | 	    XML_SCHEMA_TYPE_COMPLEX, | 
 | 	    NULL, ctxt->targetNamespace, node, 0); | 
 | #endif | 
 | 	if (type == NULL) | 
 | 	    return (NULL); | 
 | 	name = type->name; | 
 | 	type->node = node; | 
 | 	type->type = XML_SCHEMA_TYPE_COMPLEX; | 
 | 	/* | 
 | 	* TODO: We need the target namespace. | 
 | 	*/ | 
 |     } else { | 
 | 	/* | 
 | 	* Parse as global complex type definition. | 
 | 	*/ | 
 | 	type = xmlSchemaAddType(ctxt, schema, | 
 | 	    XML_SCHEMA_TYPE_COMPLEX, | 
 | 	    name, ctxt->targetNamespace, node, 1); | 
 | 	if (type == NULL) | 
 | 	    return (NULL); | 
 | 	type->node = node; | 
 | 	type->type = XML_SCHEMA_TYPE_COMPLEX; | 
 | 	type->flags |= XML_SCHEMAS_TYPE_GLOBAL; | 
 |     } | 
 |     type->targetNamespace = ctxt->targetNamespace; | 
 |     /* | 
 |     * Handle attributes. | 
 |     */ | 
 |     attr = node->properties; | 
 |     while (attr != NULL) { | 
 | 	if (attr->ns == NULL) { | 
 | 	    if (xmlStrEqual(attr->name, BAD_CAST "id")) { | 
 | 		/* | 
 | 		* Attribute "id". | 
 | 		*/ | 
 | 		xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id"); | 
 | 	    } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) { | 
 | 		/* | 
 | 		* Attribute "mixed". | 
 | 		*/ | 
 | 		if (xmlSchemaPGetBoolNodeValue(ctxt, | 
 | 			NULL, (xmlNodePtr) attr)) | 
 | 		    type->flags |= XML_SCHEMAS_TYPE_MIXED; | 
 | 	    } else if (topLevel) { | 
 | 		/* | 
 | 		* Attributes of global complex type definitions. | 
 | 		*/ | 
 | 		if (xmlStrEqual(attr->name, BAD_CAST "name")) { | 
 | 		    /* Pass. */ | 
 | 		} else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) { | 
 | 		    /* | 
 | 		    * Attribute "abstract". | 
 | 		    */ | 
 | 		    if (xmlSchemaPGetBoolNodeValue(ctxt, | 
 | 			    NULL, (xmlNodePtr) attr)) | 
 | 			type->flags |= XML_SCHEMAS_TYPE_ABSTRACT; | 
 | 		} else if (xmlStrEqual(attr->name, BAD_CAST "final")) { | 
 | 		    /* | 
 | 		    * Attribute "final". | 
 | 		    */ | 
 | 		    attrValue = xmlSchemaGetNodeContent(ctxt, | 
 | 			(xmlNodePtr) attr); | 
 | 		    if (xmlSchemaPValAttrBlockFinal(attrValue, | 
 | 			&(type->flags), | 
 | 			-1, | 
 | 			XML_SCHEMAS_TYPE_FINAL_EXTENSION, | 
 | 			XML_SCHEMAS_TYPE_FINAL_RESTRICTION, | 
 | 			-1, -1, -1) != 0) | 
 | 		    { | 
 | 			xmlSchemaPSimpleTypeErr(ctxt, | 
 | 			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | 
 | 			    NULL, (xmlNodePtr) attr, NULL, | 
 | 			    "(#all | List of (extension | restriction))", | 
 | 			    attrValue, NULL, NULL, NULL); | 
 | 		    } else | 
 | 			final = 1; | 
 | 		} else if (xmlStrEqual(attr->name, BAD_CAST "block")) { | 
 | 		    /* | 
 | 		    * Attribute "block". | 
 | 		    */ | 
 | 		    attrValue = xmlSchemaGetNodeContent(ctxt, | 
 | 			(xmlNodePtr) attr); | 
 | 		    if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags), | 
 | 			-1, | 
 | 			XML_SCHEMAS_TYPE_BLOCK_EXTENSION, | 
 | 			XML_SCHEMAS_TYPE_BLOCK_RESTRICTION, | 
 | 			-1, -1, -1) != 0) { | 
 | 			xmlSchemaPSimpleTypeErr(ctxt, | 
 | 			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, | 
 | 			    NULL, (xmlNodePtr) attr, NULL, | 
 | 			    "(#all | List of (extension | restriction)) ", | 
 | 			    attrValue, NULL, NULL, NULL); | 
 | 		    } else | 
 | 			block = 1; | 
 | 		} else { | 
 | 			xmlSchemaPIllegalAttrErr(ctxt, | 
 | 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 		} | 
 | 	    } else { | 
 | 		xmlSchemaPIllegalAttrErr(ctxt, | 
 | 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	    } | 
 | 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) { | 
 | 	    xmlSchemaPIllegalAttrErr(ctxt, | 
 | 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr); | 
 | 	} | 
 | 	attr = attr->next; | 
 |     } | 
 |     if (! block) { | 
 | 	/* | 
 | 	* Apply default "block" values. | 
 | 	*/ | 
 | 	if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION) | 
 | 	    type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION; | 
 | 	if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION) | 
 | 	    type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION; | 
 |     } | 
 |     if (! final) { | 
 | 	/* | 
 | 	* Apply default "block" values. | 
 | 	*/ | 
 | 	if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION) | 
 | 	    type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION; | 
 | 	if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION) | 
 | 	    type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION; | 
 |     } | 
 |     /* | 
 |     * And now for the children... | 
 |     */ | 
 |     child = node->children; | 
 |     if (IS_SCHEMA(child, "annotation")) { | 
 |         type->annot = xmlSchemaParseAnnotation(ctxt, child, 1); | 
 |         child = child->next; | 
 |     } | 
 |     ctxt->ctxtType = type; | 
 |     if (IS_SCHEMA(child, "simpleContent")) { | 
 | 	/* | 
 | 	* <complexType><simpleContent>... | 
 | 	* 3.4.3 : 2.2 | 
 | 	* Specifying mixed='true' when the <simpleContent> | 
 | 	* alternative is chosen has no effect | 
 | 	*/ | 
 | 	if (type->flags & XML_SCHEMAS_TYPE_MIXED) | 
 | 	    type->flags ^= XML_SCHEMAS_TYPE_MIXED; | 
 |         xmlSchemaParseSimpleContent(ctxt, schema, child, | 
 | 	    &hasRestrictionOrExtension); | 
 |         child = child->next; | 
 |     } else if (IS_SCHEMA(child, "complexContent")) { | 
 | 	/* | 
 | 	* <complexType><complexContent>... | 
 | 	*/ | 
 | 	type->contentType = XML_SCHEMA_CONTENT_EMPTY; | 
 |         xmlSchemaParseComplexContent(ctxt, schema, child, | 
 | 	    &hasRestrictionOrExtension); | 
 |         child = child->next; | 
 |     } else { | 
 | 	/* | 
 | 	* E.g <complexType><sequence>... or <complexType><attribute>... etc. | 
 | 	* | 
 | 	* SPEC | 
 | 	* "...the third alternative (neither <simpleContent> nor | 
 | 	* <complexContent>) is chosen. This case is understood as shorthand | 
 | 	* for complex content restricting the �ur-type definition�, and the | 
 | 	* details of the mappings should be modified as necessary. | 
 | 	*/ | 
 | 	type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE); | 
 | 	type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION; | 
 | 	/* | 
 | 	* Parse model groups. | 
 | 	*/ | 
 |         if (IS_SCHEMA(child, "all")) { | 
 |             type->subtypes = (xmlSchemaTypePtr) | 
 | 		xmlSchemaParseModelGroup(ctxt, schema, child, | 
 | 		    XML_SCHEMA_TYPE_ALL, 1); | 
 |             child = child->next; | 
 |         } else if (IS_SCHEMA(child, "choice")) { | 
 |             type->subtypes = (xmlSchemaTypePtr) | 
 | 		xmlSchemaParseModelGroup(ctxt, schema, child, | 
 | 		    XML_SCHEMA_TYPE_CHOICE, 1); | 
 |             child = child->next; | 
 |         } else if (IS_SCHEMA(child, "sequence")) { | 
 |             type->subtypes = (xmlSchemaTypePtr) | 
 | 		xmlSchemaParseModelGroup(ctxt, schema, child, | 
 | 		    XML_SCHEMA_TYPE_SEQUENCE, 1); | 
 |             child = child->next; | 
 |         } else if (IS_SCHEMA(child, "group")) { | 
 |             type->subtypes = (xmlSchemaTypePtr) | 
 | 		xmlSchemaParseModelGroupDefRef(ctxt, schema, child); | 
 | 	    /* | 
 | 	    * Note that the reference will be resolved in | 
 | 	    * xmlSchemaResolveTypeReferences(); | 
 | 	    */ | 
 |             child = child->next; | 
 |         } | 
 | 	/* | 
 | 	* Parse attribute decls/refs. | 
 | 	*/ | 
 |         if (xmlSchemaParseLocalAttributes(ctxt, schema, &child, | 
 | 	    (xmlSchemaItemListPtr *) &(type->attrUses), | 
 | 	    XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1) | 
 | 	    return(NULL); | 
 | 	/* | 
 | 	* Parse attribute wildcard. | 
 | 	*/ | 
 | 	if (IS_SCHEMA(child, "anyAttribute")) { | 
 | 	    type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child); | 
 | 	    child = child->next; | 
 | 	} | 
 |     } | 
 |     if (child != NULL) { | 
 | 	xmlSchemaPContentErr(ctxt, | 
 | 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, | 
 | 	    NULL, node, child, | 
 | 	    NULL, "(annotation?, (simpleContent | complexContent | " | 
 | 	    "((group | all | choice | sequence)?, ((attribute | " | 
 | 	    "attributeGroup)*, anyAttribute?))))"); | 
 |     } | 
 |     /* | 
 |     * REDEFINE: SPEC src-redefine (5) | 
 |     */ | 
 |     if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) { | 
 | 	xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE, | 
 | 	    NULL, node, "This is a redefinition, thus the " | 
 | 	    "<complexType> must have a <restriction> or <extension> " | 
 | 	    "grand-child", NULL); | 
 |     } | 
 |     ctxt->ctxtType = ctxtType; | 
 |     return (type); | 
 | } | 
 |  | 
 | /************************************************************************ | 
 |  * 									* | 
 |  * 			Validating using Schemas			* | 
 |  * 									* | 
 |  ************************************************************************/ | 
 |  | 
 | /************************************************************************ | 
 |  * 									* | 
 |  * 			Reading/Writing Schemas				* | 
 |  * 									* | 
 |  ************************************************************************/ | 
 |  | 
 | #if 0 /* Will be enabled if it is clear what options are needed. */ | 
 | /** | 
 |  * xmlSchemaParserCtxtSetOptions: | 
 |  * @ctxt:	a schema parser context | 
 |  * @options: a combination of xmlSchemaParserOption | 
 |  * | 
 |  * Sets the options to be used during the parse. | 
 |  * | 
 |  * Returns 0 in case of success, -1 in case of an | 
 |  * API error. | 
 |  */ | 
 | static int | 
 | xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt, | 
 | 			      int options) | 
 |  | 
 | { | 
 |     int i; | 
 |  | 
 |     if (ctxt == NULL) | 
 | 	return (-1); | 
 |     /* | 
 |     * WARNING: Change the start value if adding to the | 
 |     * xmlSchemaParseOption. | 
 |     */ | 
 |     for (i = 1; i < (int) sizeof(int) * 8; i++) { | 
 |         if (options & 1<<i) { | 
 | 	    return (-1); | 
 |         } | 
 |     } | 
 |     ctxt->options = options; | 
 |     return (0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaValidCtxtGetOptions: | 
 |  * @ctxt: a schema parser context | 
 |  * | 
 |  * Returns the option combination of the parser context. | 
 |  */ | 
 | static int | 
 | xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt) | 
 |  | 
 | { | 
 |     if (ctxt == NULL) | 
 | 	return (-1); | 
 |     else | 
 | 	return (ctxt->options); | 
 | } | 
 | #endif | 
 |  | 
 | /** | 
 |  * xmlSchemaNewParserCtxt: | 
 |  * @URL:  the location of the schema | 
 |  * | 
 |  * Create an XML Schemas parse context for that file/resource expected | 
 |  * to contain an XML Schemas file. | 
 |  * | 
 |  * Returns the parser context or NULL in case of error | 
 |  */ | 
 | xmlSchemaParserCtxtPtr | 
 | xmlSchemaNewParserCtxt(const char *URL) | 
 | { | 
 |     xmlSchemaParserCtxtPtr ret; | 
 |  | 
 |     if (URL == NULL) | 
 |         return (NULL); | 
 |  | 
 |     ret = xmlSchemaParserCtxtCreate(); | 
 |     if (ret == NULL) | 
 | 	return(NULL); | 
 |     ret->dict = xmlDictCreate(); | 
 |     ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1); | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaNewMemParserCtxt: | 
 |  * @buffer:  a pointer to a char array containing the schemas | 
 |  * @size:  the size of the array | 
 |  * | 
 |  * Create an XML Schemas parse context for that memory buffer expected | 
 |  * to contain an XML Schemas file. | 
 |  * | 
 |  * Returns the parser context or NULL in case of error | 
 |  */ | 
 | xmlSchemaParserCtxtPtr | 
 | xmlSchemaNewMemParserCtxt(const char *buffer, int size) | 
 | { | 
 |     xmlSchemaParserCtxtPtr ret; | 
 |  | 
 |     if ((buffer == NULL) || (size <= 0)) | 
 |         return (NULL); | 
 |     ret = xmlSchemaParserCtxtCreate(); | 
 |     if (ret == NULL) | 
 | 	return(NULL); | 
 |     ret->buffer = buffer; | 
 |     ret->size = size; | 
 |     ret->dict = xmlDictCreate(); | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaNewDocParserCtxt: | 
 |  * @doc:  a preparsed document tree | 
 |  * | 
 |  * Create an XML Schemas parse context for that document. | 
 |  * NB. The document may be modified during the parsing process. | 
 |  * | 
 |  * Returns the parser context or NULL in case of error | 
 |  */ | 
 | xmlSchemaParserCtxtPtr | 
 | xmlSchemaNewDocParserCtxt(xmlDocPtr doc) | 
 | { | 
 |     xmlSchemaParserCtxtPtr ret; | 
 |  | 
 |     if (doc == NULL) | 
 |       return (NULL); | 
 |     ret = xmlSchemaParserCtxtCreate(); | 
 |     if (ret == NULL) | 
 | 	return(NULL); | 
 |     ret->doc = doc; | 
 |     ret->dict = xmlDictCreate(); | 
 |     /* The application has responsibility for the document */ | 
 |     ret->preserve = 1; | 
 |  | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaFreeParserCtxt: | 
 |  * @ctxt:  the schema parser context | 
 |  * | 
 |  * Free the resources associated to the schema parser context | 
 |  */ | 
 | void | 
 | xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt) | 
 | { | 
 |     if (ctxt == NULL) | 
 |         return; | 
 |     if (ctxt->doc != NULL && !ctxt->preserve) | 
 |         xmlFreeDoc(ctxt->doc); | 
 |     if (ctxt->vctxt != NULL) { | 
 | 	xmlSchemaFreeValidCtxt(ctxt->vctxt); | 
 |     } | 
 |     if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) { | 
 | 	xmlSchemaConstructionCtxtFree(ctxt->constructor); | 
 | 	ctxt->constructor = NULL; | 
 | 	ctxt->ownsConstructor = 0; | 
 |     } | 
 |     if (ctxt->attrProhibs != NULL) | 
 | 	xmlSchemaItemListFree(ctxt->attrProhibs); | 
 |     xmlDictFree(ctxt->dict); | 
 |     xmlFree(ctxt); | 
 | } | 
 |  | 
 | /************************************************************************ | 
 |  *									* | 
 |  *			Building the content models			* | 
 |  *									* | 
 |  ************************************************************************/ | 
 |  | 
 | /** | 
 |  * xmlSchemaBuildContentModelForSubstGroup: | 
 |  * | 
 |  * Returns 1 if nillable, 0 otherwise | 
 |  */ | 
 | static int | 
 | xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt, | 
 | 	xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end) | 
 | { | 
 |     xmlAutomataStatePtr start, tmp; | 
 |     xmlSchemaElementPtr elemDecl, member; | 
 |     xmlSchemaSubstGroupPtr substGroup; | 
 |     int i; | 
 |     int ret = 0; | 
 |  | 
 |     elemDecl = (xmlSchemaElementPtr) particle->children; | 
 |     /* | 
 |     * Wrap the substitution group with a CHOICE. | 
 |     */ | 
 |     start = pctxt->state; | 
 |     if (end == NULL) | 
 | 	end = xmlAutomataNewState(pctxt->am); | 
 |     substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl); | 
 |     if (substGroup == NULL) { | 
 | 	xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle), | 
 | 	    XML_SCHEMAP_INTERNAL, | 
 | 	    "Internal error: xmlSchemaBuildContentModelForSubstGroup, " | 
 | 	    "declaration is marked having a subst. group but none " | 
 | 	    "available.\n", elemDecl->name, NULL); | 
 | 	return(0); | 
 |     } | 
 |     if (counter >= 0) { | 
 | 	/* | 
 | 	* NOTE that we put the declaration in, even if it's abstract. | 
 | 	* However, an error will be raised during *validation* if an element | 
 | 	* information item shall be validated against an abstract element | 
 | 	* declaration. | 
 | 	*/ | 
 | 	tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter); | 
 |         xmlAutomataNewTransition2(pctxt->am, tmp, end, | 
 | 	            elemDecl->name, elemDecl->targetNamespace, elemDecl); | 
 | 	/* | 
 | 	* Add subst. group members. | 
 | 	*/ | 
 | 	for (i = 0; i < substGroup->members->nbItems; i++) { | 
 | 	    member = (xmlSchemaElementPtr) substGroup->members->items[i]; | 
 |             xmlAutomataNewTransition2(pctxt->am, tmp, end, | 
 | 		               member->name, member->targetNamespace, member); | 
 | 	} | 
 |     } else if (particle->maxOccurs == 1) { | 
 | 	/* | 
 | 	* NOTE that we put the declaration in, even if it's abstract, | 
 | 	*/ | 
 | 	xmlAutomataNewEpsilon(pctxt->am, | 
 | 	    xmlAutomataNewTransition2(pctxt->am, | 
 | 	    start, NULL, | 
 | 	    elemDecl->name, elemDecl->targetNamespace, elemDecl), end); | 
 | 	/* | 
 | 	* Add subst. group members. | 
 | 	*/ | 
 | 	for (i = 0; i < substGroup->members->nbItems; i++) { | 
 | 	    member = (xmlSchemaElementPtr) substGroup->members->items[i]; | 
 | 	    /* | 
 | 	    * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2() | 
 | 	    *  was incorrectly used instead of xmlAutomataNewTransition2() | 
 | 	    *  (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL | 
 | 	    *  section in xmlSchemaBuildAContentModel() ). | 
 | 	    * TODO: Check if xmlAutomataNewOnceTrans2() was instead | 
 | 	    *  intended for the above "counter" section originally. I.e., | 
 | 	    *  check xs:all with subst-groups. | 
 | 	    * | 
 | 	    * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL, | 
 | 	    *	               member->name, member->targetNamespace, | 
 | 	    *		       1, 1, member); | 
 | 	    */ | 
 | 	    tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL, | 
 | 		member->name, member->targetNamespace, member); | 
 | 	    xmlAutomataNewEpsilon(pctxt->am, tmp, end); | 
 | 	} | 
 |     } else { | 
 | 	xmlAutomataStatePtr hop; | 
 | 	int maxOccurs = particle->maxOccurs == UNBOUNDED ? | 
 | 	    UNBOUNDED : particle->maxOccurs - 1; | 
 | 	int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1; | 
 |  | 
 | 	counter = | 
 | 	    xmlAutomataNewCounter(pctxt->am, minOccurs, | 
 | 	    maxOccurs); | 
 | 	hop = xmlAutomataNewState(pctxt->am); | 
 |  | 
 | 	xmlAutomataNewEpsilon(pctxt->am, | 
 | 	    xmlAutomataNewTransition2(pctxt->am, | 
 | 	    start, NULL, | 
 | 	    elemDecl->name, elemDecl->targetNamespace, elemDecl), | 
 | 	    hop); | 
 | 	/* | 
 | 	 * Add subst. group members. | 
 | 	 */ | 
 | 	for (i = 0; i < substGroup->members->nbItems; i++) { | 
 | 	    member = (xmlSchemaElementPtr) substGroup->members->items[i]; | 
 | 	    xmlAutomataNewEpsilon(pctxt->am, | 
 | 		xmlAutomataNewTransition2(pctxt->am, | 
 | 		start, NULL, | 
 | 		member->name, member->targetNamespace, member), | 
 | 		hop); | 
 | 	} | 
 | 	xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter); | 
 | 	xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter); | 
 |     } | 
 |     if (particle->minOccurs == 0) { | 
 | 	xmlAutomataNewEpsilon(pctxt->am, start, end); | 
 |         ret = 1; | 
 |     } | 
 |     pctxt->state = end; | 
 |     return(ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaBuildContentModelForElement: | 
 |  * | 
 |  * Returns 1 if nillable, 0 otherwise | 
 |  */ | 
 | static int | 
 | xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt, | 
 | 				     xmlSchemaParticlePtr particle) | 
 | { | 
 |     int ret = 0; | 
 |  | 
 |     if (((xmlSchemaElementPtr) particle->children)->flags & | 
 | 	XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) { | 
 | 	/* | 
 | 	* Substitution groups. | 
 | 	*/ | 
 | 	ret = xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL); | 
 |     } else { | 
 | 	xmlSchemaElementPtr elemDecl; | 
 | 	xmlAutomataStatePtr start; | 
 |  | 
 | 	elemDecl = (xmlSchemaElementPtr) particle->children; | 
 |  | 
 | 	if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) | 
 | 	    return(0); | 
 | 	if (particle->maxOccurs == 1) { | 
 | 	    start = ctxt->state; | 
 | 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL, | 
 | 		    elemDecl->name, elemDecl->targetNamespace, elemDecl); | 
 | 	} else if ((particle->maxOccurs >= UNBOUNDED) && | 
 | 	           (particle->minOccurs < 2)) { | 
 | 	    /* Special case. */ | 
 | 	    start = ctxt->state; | 
 | 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL, | 
 | 		elemDecl->name, elemDecl->targetNamespace, elemDecl); | 
 | 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state, | 
 | 		elemDecl->name, elemDecl->targetNamespace, elemDecl); | 
 | 	} else { | 
 | 	    int counter; | 
 | 	    int maxOccurs = particle->maxOccurs == UNBOUNDED ? | 
 | 			    UNBOUNDED : particle->maxOccurs - 1; | 
 | 	    int minOccurs = particle->minOccurs < 1 ? | 
 | 			    0 : particle->minOccurs - 1; | 
 |  | 
 | 	    start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL); | 
 | 	    counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs); | 
 | 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL, | 
 | 		elemDecl->name, elemDecl->targetNamespace, elemDecl); | 
 | 	    xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter); | 
 | 	    ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state, | 
 | 		NULL, counter); | 
 | 	} | 
 | 	if (particle->minOccurs == 0) { | 
 | 	    xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state); | 
 |             ret = 1; | 
 |         } | 
 |     } | 
 |     return(ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaBuildAContentModel: | 
 |  * @ctxt:  the schema parser context | 
 |  * @particle:  the particle component | 
 |  * @name:  the complex type's name whose content is being built | 
 |  * | 
 |  * Create the automaton for the {content type} of a complex type. | 
 |  * | 
 |  * Returns 1 if the content is nillable, 0 otherwise | 
 |  */ | 
 | static int | 
 | xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt, | 
 | 			    xmlSchemaParticlePtr particle) | 
 | { | 
 |     int ret = 0, tmp2; | 
 |  | 
 |     if (particle == NULL) { | 
 | 	PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL"); | 
 | 	return(1); | 
 |     } | 
 |     if (particle->children == NULL) { | 
 | 	/* | 
 | 	* Just return in this case. A missing "term" of the particle | 
 | 	* might arise due to an invalid "term" component. | 
 | 	*/ | 
 | 	return(1); | 
 |     } | 
 |  | 
 |     switch (particle->children->type) { | 
 | 	case XML_SCHEMA_TYPE_ANY: { | 
 | 	    xmlAutomataStatePtr start, end; | 
 | 	    xmlSchemaWildcardPtr wild; | 
 | 	    xmlSchemaWildcardNsPtr ns; | 
 |  | 
 | 	    wild = (xmlSchemaWildcardPtr) particle->children; | 
 |  | 
 | 	    start = pctxt->state; | 
 | 	    end = xmlAutomataNewState(pctxt->am); | 
 |  | 
 | 	    if (particle->maxOccurs == 1) { | 
 | 		if (wild->any == 1) { | 
 | 		    /* | 
 | 		    * We need to add both transitions: | 
 | 		    * | 
 | 		    * 1. the {"*", "*"} for elements in a namespace. | 
 | 		    */ | 
 | 		    pctxt->state = | 
 | 			xmlAutomataNewTransition2(pctxt->am, | 
 | 			start, NULL, BAD_CAST "*", BAD_CAST "*", wild); | 
 | 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end); | 
 | 		    /* | 
 | 		    * 2. the {"*"} for elements in no namespace. | 
 | 		    */ | 
 | 		    pctxt->state = | 
 | 			xmlAutomataNewTransition2(pctxt->am, | 
 | 			start, NULL, BAD_CAST "*", NULL, wild); | 
 | 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end); | 
 |  | 
 | 		} else if (wild->nsSet != NULL) { | 
 | 		    ns = wild->nsSet; | 
 | 		    do { | 
 | 			pctxt->state = start; | 
 | 			pctxt->state = xmlAutomataNewTransition2(pctxt->am, | 
 | 			    pctxt->state, NULL, BAD_CAST "*", ns->value, wild); | 
 | 			xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end); | 
 | 			ns = ns->next; | 
 | 		    } while (ns != NULL); | 
 |  | 
 | 		} else if (wild->negNsSet != NULL) { | 
 | 		    pctxt->state = xmlAutomataNewNegTrans(pctxt->am, | 
 | 			start, end, BAD_CAST "*", wild->negNsSet->value, | 
 | 			wild); | 
 | 		} | 
 | 	    } else { | 
 | 		int counter; | 
 | 		xmlAutomataStatePtr hop; | 
 | 		int maxOccurs = | 
 | 		    particle->maxOccurs == UNBOUNDED ? UNBOUNDED : | 
 |                                            particle->maxOccurs - 1; | 
 | 		int minOccurs = | 
 | 		    particle->minOccurs < 1 ? 0 : particle->minOccurs - 1; | 
 |  | 
 | 		counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs); | 
 | 		hop = xmlAutomataNewState(pctxt->am); | 
 | 		if (wild->any == 1) { | 
 | 		    pctxt->state = | 
 | 			xmlAutomataNewTransition2(pctxt->am, | 
 | 			start, NULL, BAD_CAST "*", BAD_CAST "*", wild); | 
 | 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop); | 
 | 		    pctxt->state = | 
 | 			xmlAutomataNewTransition2(pctxt->am, | 
 | 			start, NULL, BAD_CAST "*", NULL, wild); | 
 | 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop); | 
 | 		} else if (wild->nsSet != NULL) { | 
 | 		    ns = wild->nsSet; | 
 | 		    do { | 
 | 			pctxt->state = | 
 | 			    xmlAutomataNewTransition2(pctxt->am, | 
 | 				start, NULL, BAD_CAST "*", ns->value, wild); | 
 | 			xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop); | 
 | 			ns = ns->next; | 
 | 		    } while (ns != NULL); | 
 |  | 
 | 		} else if (wild->negNsSet != NULL) { | 
 | 		    pctxt->state = xmlAutomataNewNegTrans(pctxt->am, | 
 | 			start, hop, BAD_CAST "*", wild->negNsSet->value, | 
 | 			wild); | 
 | 		} | 
 | 		xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter); | 
 | 		xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter); | 
 | 	    } | 
 | 	    if (particle->minOccurs == 0) { | 
 | 		xmlAutomataNewEpsilon(pctxt->am, start, end); | 
 |                 ret = 1; | 
 | 	    } | 
 | 	    pctxt->state = end; | 
 |             break; | 
 | 	} | 
 |         case XML_SCHEMA_TYPE_ELEMENT: | 
 | 	    ret = xmlSchemaBuildContentModelForElement(pctxt, particle); | 
 | 	    break; | 
 |         case XML_SCHEMA_TYPE_SEQUENCE:{ | 
 |             xmlSchemaTreeItemPtr sub; | 
 |  | 
 |             ret = 1; | 
 |             /* | 
 |              * If max and min occurances are default (1) then | 
 |              * simply iterate over the particles of the <sequence>. | 
 |              */ | 
 |             if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) { | 
 |                 sub = particle->children->children; | 
 |  | 
 |                 while (sub != NULL) { | 
 |                     tmp2 = xmlSchemaBuildAContentModel(pctxt, | 
 |                                         (xmlSchemaParticlePtr) sub); | 
 |                     if (tmp2 != 1) ret = 0; | 
 |                     sub = sub->next; | 
 |                 } | 
 |             } else { | 
 |                 xmlAutomataStatePtr oldstate = pctxt->state; | 
 |  | 
 |                 if (particle->maxOccurs >= UNBOUNDED) { | 
 |                     if (particle->minOccurs > 1) { | 
 |                         xmlAutomataStatePtr tmp; | 
 |                         int counter; | 
 |  | 
 |                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am, | 
 |                             oldstate, NULL); | 
 |                         oldstate = pctxt->state; | 
 |  | 
 |                         counter = xmlAutomataNewCounter(pctxt->am, | 
 |                             particle->minOccurs - 1, UNBOUNDED); | 
 |  | 
 |                         sub = particle->children->children; | 
 |                         while (sub != NULL) { | 
 |                             tmp2 = xmlSchemaBuildAContentModel(pctxt, | 
 |                                             (xmlSchemaParticlePtr) sub); | 
 |                             if (tmp2 != 1) ret = 0; | 
 |                             sub = sub->next; | 
 |                         } | 
 |                         tmp = pctxt->state; | 
 |                         xmlAutomataNewCountedTrans(pctxt->am, tmp, | 
 |                                                    oldstate, counter); | 
 |                         pctxt->state = | 
 |                             xmlAutomataNewCounterTrans(pctxt->am, tmp, | 
 |                                                        NULL, counter); | 
 |                         if (ret == 1) | 
 |                             xmlAutomataNewEpsilon(pctxt->am, | 
 |                                                 oldstate, pctxt->state); | 
 |  | 
 |                     } else { | 
 |                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am, | 
 |                             oldstate, NULL); | 
 |                         oldstate = pctxt->state; | 
 |  | 
 |                         sub = particle->children->children; | 
 |                         while (sub != NULL) { | 
 |                             tmp2 = xmlSchemaBuildAContentModel(pctxt, | 
 |                                         (xmlSchemaParticlePtr) sub); | 
 |                             if (tmp2 != 1) ret = 0; | 
 |                             sub = sub->next; | 
 |                         } | 
 |                         xmlAutomataNewEpsilon(pctxt->am, pctxt->state, | 
 |                                               oldstate); | 
 |                         /* | 
 |                          * epsilon needed to block previous trans from | 
 |                          * being allowed to enter back from another | 
 |                          * construct | 
 |                          */ | 
 |                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am, | 
 |                                             pctxt->state, NULL); | 
 |                         if (particle->minOccurs == 0) { | 
 |                             xmlAutomataNewEpsilon(pctxt->am, | 
 |                                 oldstate, pctxt->state); | 
 |                             ret = 1; | 
 |                         } | 
 |                     } | 
 |                 } else if ((particle->maxOccurs > 1) | 
 |                            || (particle->minOccurs > 1)) { | 
 |                     xmlAutomataStatePtr tmp; | 
 |                     int counter; | 
 |  | 
 |                     pctxt->state = xmlAutomataNewEpsilon(pctxt->am, | 
 |                         oldstate, NULL); | 
 |                     oldstate = pctxt->state; | 
 |  | 
 |                     counter = xmlAutomataNewCounter(pctxt->am, | 
 |                         particle->minOccurs - 1, | 
 |                         particle->maxOccurs - 1); | 
 |  | 
 |                     sub = particle->children->children; | 
 |                     while (sub != NULL) { | 
 |                         tmp2 = xmlSchemaBuildAContentModel(pctxt, | 
 |                                         (xmlSchemaParticlePtr) sub); | 
 |                         if (tmp2 != 1) ret = 0; | 
 |                         sub = sub->next; | 
 |                     } | 
 |                     tmp = pctxt->state; | 
 |                     xmlAutomataNewCountedTrans(pctxt->am, | 
 |                         tmp, oldstate, counter); | 
 |                     pctxt->state = | 
 |                         xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL, | 
 |                                                    counter); | 
 |                     if ((particle->minOccurs == 0) || (ret == 1)) { | 
 |                         xmlAutomataNewEpsilon(pctxt->am, | 
 |                                             oldstate, pctxt->state); | 
 |                         ret = 1; | 
 |                     } | 
 |                 } else { | 
 |                     sub = particle->children->children; | 
 |                     while (sub != NULL) { | 
 |                         tmp2 = xmlSchemaBuildAContentModel(pctxt, | 
 |                                         (xmlSchemaParticlePtr) sub); | 
 |                         if (tmp2 != 1) ret = 0; | 
 |                         sub = sub->next; | 
 |                     } | 
 |                     if (particle->minOccurs == 0) { | 
 |                         xmlAutomataNewEpsilon(pctxt->am, oldstate, | 
 |                                               pctxt->state); | 
 |                         ret = 1; | 
 |                     } | 
 |                 } | 
 |             } | 
 |             break; | 
 |         } | 
 |         case XML_SCHEMA_TYPE_CHOICE:{ | 
 |             xmlSchemaTreeItemPtr sub; | 
 |             xmlAutomataStatePtr start, end; | 
 |  | 
 |             ret = 0; | 
 |             start = pctxt->state; | 
 |             end = xmlAutomataNewState(pctxt->am); | 
 |  | 
 |             /* | 
 |              * iterate over the subtypes and remerge the end with an | 
 |              * epsilon transition | 
 |              */ | 
 |             if (particle->maxOccurs == 1) { | 
 |                 sub = particle->children->children; | 
 |                 while (sub != NULL) { | 
 |                     pctxt->state = start; | 
 |                     tmp2 = xmlSchemaBuildAContentModel(pctxt, | 
 |                                         (xmlSchemaParticlePtr) sub); | 
 |                     if (tmp2 == 1) ret = 1; | 
 |                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end); | 
 |                     sub = sub->next; | 
 |                 } | 
 |             } else { | 
 |                 int counter; | 
 |                 xmlAutomataStatePtr hop, base; | 
 |                 int maxOccurs = particle->maxOccurs == UNBOUNDED ? | 
 |                     UNBOUNDED : particle->maxOccurs - 1; | 
 |                 int minOccurs = | 
 |                     particle->minOccurs < 1 ? 0 : particle->minOccurs - 1; | 
 |  | 
 |                 /* | 
 |                  * use a counter to keep track of the number of transtions | 
 |                  * which went through the choice. | 
 |                  */ | 
 |                 counter = | 
 |                     xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs); | 
 |                 hop = xmlAutomataNewState(pctxt->am); | 
 |                 base = xmlAutomataNewState(pctxt->am); | 
 |  | 
 |                 sub = particle->children->children; | 
 |                 while (sub != NULL) { | 
 |                     pctxt->state = base; | 
 |                     tmp2 = xmlSchemaBuildAContentModel(pctxt, | 
 |                                         (xmlSchemaParticlePtr) sub); | 
 |                     if (tmp2 == 1) ret = 1; | 
 |                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop); | 
 |                     sub = sub->next; | 
 |                 } | 
 |                 xmlAutomataNewEpsilon(pctxt->am, start, base); | 
 |                 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter); | 
 |                 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter); | 
 |                 if (ret == 1) | 
 |                     xmlAutomataNewEpsilon(pctxt->am, base, end); | 
 |             } | 
 |             if (particle->minOccurs == 0) { | 
 |                 xmlAutomataNewEpsilon(pctxt->am, start, end); | 
 |                 ret = 1; | 
 |             } | 
 |             pctxt->state = end; | 
 |             break; | 
 |         } | 
 |         case XML_SCHEMA_TYPE_ALL:{ | 
 |             xmlAutomataStatePtr start, tmp; | 
 |             xmlSchemaParticlePtr sub; | 
 |             xmlSchemaElementPtr elemDecl; | 
 |  | 
 |             ret = 1; | 
 |  | 
 |             sub = (xmlSchemaParticlePtr) particle->children->children; | 
 |             if (sub == NULL) | 
 |                 break; | 
 |  | 
 |             ret = 0; | 
 |  | 
 |             start = pctxt->state; | 
 |             tmp = xmlAutomataNewState(pctxt->am); | 
 |             xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp); | 
 |             pctxt->state = tmp; | 
 |             while (sub != NULL) { | 
 |                 pctxt->state = tmp; | 
 |  | 
 |                 elemDecl = (xmlSchemaElementPtr) sub->children; | 
 |                 if (elemDecl == NULL) { | 
 |                     PERROR_INT("xmlSchemaBuildAContentModel", | 
 |                         "<element> particle has no term"); | 
 |                     return(ret); | 
 |                 }; | 
 |                 /* | 
 |                 * NOTE: The {max occurs} of all the particles in the | 
 |                 * {particles} of the group must be 0 or 1; this is | 
 |                 * already ensured during the parse of the content of | 
 |                 * <all>. | 
 |                 */ | 
 |                 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) { | 
 |                     int counter; | 
 |  | 
 |                     /* | 
 |                      * This is an abstract group, we need to share | 
 |                      * the same counter for all the element transitions | 
 |                      * derived from the group | 
 |                      */ | 
 |                     counter = xmlAutomataNewCounter(pctxt->am, | 
 |                                        sub->minOccurs, sub->maxOccurs); | 
 |                     xmlSchemaBuildContentModelForSubstGroup(pctxt, | 
 |                                        sub, counter, pctxt->state); | 
 |                 } else { | 
 |                     if ((sub->minOccurs == 1) && | 
 |                         (sub->maxOccurs == 1)) { | 
 |                         xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state, | 
 |                                                 pctxt->state, | 
 |                                                 elemDecl->name, | 
 |                                                 elemDecl->targetNamespace, | 
 |                                                 1, 1, elemDecl); | 
 |                     } else if ((sub->minOccurs == 0) && | 
 |                         (sub->maxOccurs == 1)) { | 
 |  | 
 |                         xmlAutomataNewCountTrans2(pctxt->am, pctxt->state, | 
 |                                                  pctxt->state, | 
 |                                                  elemDecl->name, | 
 |                                                  elemDecl->targetNamespace, | 
 |                                                  0, | 
 |                                                  1, | 
 |                                                  elemDecl); | 
 |                     } | 
 |                 } | 
 |                 sub = (xmlSchemaParticlePtr) sub->next; | 
 |             } | 
 |             pctxt->state = | 
 |                 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0); | 
 |             if (particle->minOccurs == 0) { | 
 |                 xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state); | 
 |                 ret = 1; | 
 |             } | 
 |             break; | 
 |         } | 
 | 	case XML_SCHEMA_TYPE_GROUP: | 
 | 	    /* | 
 | 	    * If we hit a model group definition, then this means that | 
 | 	    * it was empty, thus was not substituted for the containing | 
 | 	    * model group. Just do nothing in this case. | 
 | 	    * TODO: But the group should be substituted and not occur at | 
 | 	    * all in the content model at this point. Fix this. | 
 | 	    */ | 
 |             ret = 1; | 
 | 	    break; | 
 |         default: | 
 | 	    xmlSchemaInternalErr2(ACTXT_CAST pctxt, | 
 | 		"xmlSchemaBuildAContentModel", | 
 | 		"found unexpected term of type '%s' in content model", | 
 | 		WXS_ITEM_TYPE_NAME(particle->children), NULL); | 
 |             return(ret); | 
 |     } | 
 |     return(ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaBuildContentModel: | 
 |  * @ctxt:  the schema parser context | 
 |  * @type:  the complex type definition | 
 |  * @name:  the element name | 
 |  * | 
 |  * Builds the content model of the complex type. | 
 |  */ | 
 | static void | 
 | xmlSchemaBuildContentModel(xmlSchemaTypePtr type, | 
 | 			   xmlSchemaParserCtxtPtr ctxt) | 
 | { | 
 |     if ((type->type != XML_SCHEMA_TYPE_COMPLEX) || | 
 | 	(type->contModel != NULL) || | 
 | 	((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) && | 
 | 	(type->contentType != XML_SCHEMA_CONTENT_MIXED))) | 
 | 	return; | 
 |  | 
 | #ifdef DEBUG_CONTENT | 
 |     xmlGenericError(xmlGenericErrorContext, | 
 |                     "Building content model for %s\n", name); | 
 | #endif | 
 |     ctxt->am = NULL; | 
 |     ctxt->am = xmlNewAutomata(); | 
 |     if (ctxt->am == NULL) { | 
 |         xmlGenericError(xmlGenericErrorContext, | 
 | 	    "Cannot create automata for complex type %s\n", type->name); | 
 |         return; | 
 |     } | 
 |     ctxt->state = xmlAutomataGetInitState(ctxt->am); | 
 |     /* | 
 |     * Build the automaton. | 
 |     */ | 
 |     xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type)); | 
 |     xmlAutomataSetFinalState(ctxt->am, ctxt->state); | 
 |     type->contModel = xmlAutomataCompile(ctxt->am); | 
 |     if (type->contModel == NULL) { | 
 |         xmlSchemaPCustomErr(ctxt, | 
 | 	    XML_SCHEMAP_INTERNAL, | 
 | 	    WXS_BASIC_CAST type, type->node, | 
 | 	    "Failed to compile the content model", NULL); | 
 |     } else if (xmlRegexpIsDeterminist(type->contModel) != 1) { | 
 |         xmlSchemaPCustomErr(ctxt, | 
 | 	    XML_SCHEMAP_NOT_DETERMINISTIC, | 
 | 	    /* XML_SCHEMAS_ERR_NOTDETERMINIST, */ | 
 | 	    WXS_BASIC_CAST type, type->node, | 
 | 	    "The content model is not determinist", NULL); | 
 |     } else { | 
 | #ifdef DEBUG_CONTENT_REGEXP | 
 |         xmlGenericError(xmlGenericErrorContext, | 
 |                         "Content model of %s:\n", type->name); | 
 |         xmlRegexpPrint(stderr, type->contModel); | 
 | #endif | 
 |     } | 
 |     ctxt->state = NULL; | 
 |     xmlFreeAutomata(ctxt->am); | 
 |     ctxt->am = NULL; | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaResolveElementReferences: | 
 |  * @elem:  the schema element context | 
 |  * @ctxt:  the schema parser context | 
 |  * | 
 |  * Resolves the references of an element declaration | 
 |  * or particle, which has an element declaration as it's | 
 |  * term. | 
 |  */ | 
 | static void | 
 | xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl, | 
 | 				  xmlSchemaParserCtxtPtr ctxt) | 
 | { | 
 |     if ((ctxt == NULL) || (elemDecl == NULL) || | 
 | 	((elemDecl != NULL) && | 
 | 	(elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED))) | 
 |         return; | 
 |     elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED; | 
 |  | 
 |     if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) { | 
 | 	xmlSchemaTypePtr type; | 
 |  | 
 | 	/* (type definition) ... otherwise the type definition �resolved� | 
 | 	* to by the �actual value� of the type [attribute] ... | 
 | 	*/ | 
 | 	type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType, | 
 | 	    elemDecl->namedTypeNs); | 
 | 	if (type == NULL) { | 
 | 	    xmlSchemaPResCompAttrErr(ctxt, | 
 | 		XML_SCHEMAP_SRC_RESOLVE, | 
 | 		WXS_BASIC_CAST elemDecl, elemDecl->node, | 
 | 		"type", elemDecl->namedType, elemDecl->namedTypeNs, | 
 | 		XML_SCHEMA_TYPE_BASIC, "type definition"); | 
 | 	} else | 
 | 	    elemDecl->subtypes = type; | 
 |     } | 
 |     if (elemDecl->substGroup != NULL) { | 
 | 	xmlSchemaElementPtr substHead; | 
 |  | 
 | 	/* | 
 | 	* FIXME TODO: Do we need a new field in _xmlSchemaElement for | 
 | 	* substitutionGroup? | 
 | 	*/ | 
 | 	substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup, | 
 | 	    elemDecl->substGroupNs); | 
 | 	if (substHead == NULL) { | 
 | 	    xmlSchemaPResCompAttrErr(ctxt, | 
 | 		XML_SCHEMAP_SRC_RESOLVE, | 
 | 		WXS_BASIC_CAST elemDecl, NULL, | 
 | 		"substitutionGroup", elemDecl->substGroup, | 
 | 		elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL); | 
 | 	} else { | 
 | 	    xmlSchemaResolveElementReferences(substHead, ctxt); | 
 | 	    /* | 
 | 	    * Set the "substitution group affiliation". | 
 | 	    * NOTE that now we use the "refDecl" field for this. | 
 | 	    */ | 
 | 	    WXS_SUBST_HEAD(elemDecl) = substHead; | 
 | 	    /* | 
 | 	    * The type definitions is set to: | 
 | 	    * SPEC "...the {type definition} of the element | 
 | 	    * declaration �resolved� to by the �actual value� | 
 | 	    * of the substitutionGroup [attribute], if present" | 
 | 	    */ | 
 | 	    if (elemDecl->subtypes == NULL) | 
 | 		elemDecl->subtypes = substHead->subtypes; | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * SPEC "The definition of anyType serves as the default type definition | 
 |     * for element declarations whose XML representation does not specify one." | 
 |     */ | 
 |     if ((elemDecl->subtypes == NULL) && | 
 | 	(elemDecl->namedType == NULL) && | 
 | 	(elemDecl->substGroup == NULL)) | 
 | 	elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaResolveUnionMemberTypes: | 
 |  * @ctxt:  the schema parser context | 
 |  * @type:  the schema simple type definition | 
 |  * | 
 |  * Checks and builds the "member type definitions" property of the union | 
 |  * simple type. This handles part (1), part (2) is done in | 
 |  * xmlSchemaFinishMemberTypeDefinitionsProperty() | 
 |  * | 
 |  * Returns -1 in case of an internal error, 0 otherwise. | 
 |  */ | 
 | static int | 
 | xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt, | 
 | 				 xmlSchemaTypePtr type) | 
 | { | 
 |  | 
 |     xmlSchemaTypeLinkPtr link, lastLink, newLink; | 
 |     xmlSchemaTypePtr memberType; | 
 |  | 
 |     /* | 
 |     * SPEC (1) "If the <union> alternative is chosen, then [Definition:] | 
 |     * define the explicit members as the type definitions �resolved� | 
 |     * to by the items in the �actual value� of the memberTypes [attribute], | 
 |     * if any, followed by the type definitions corresponding to the | 
 |     * <simpleType>s among the [children] of <union>, if any." | 
 |     */ | 
 |     /* | 
 |     * Resolve references. | 
 |     */ | 
 |     link = type->memberTypes; | 
 |     lastLink = NULL; | 
 |     while (link != NULL) { | 
 | 	const xmlChar *name, *nsName; | 
 |  | 
 | 	name = ((xmlSchemaQNameRefPtr) link->type)->name; | 
 | 	nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace; | 
 |  | 
 | 	memberType = xmlSchemaGetType(ctxt->schema, name, nsName); | 
 | 	if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) { | 
 | 	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE, | 
 | 		WXS_BASIC_CAST type, type->node, "memberTypes", | 
 | 		name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL); | 
 | 	    /* | 
 | 	    * Remove the member type link. | 
 | 	    */ | 
 | 	    if (lastLink == NULL) | 
 | 		type->memberTypes = link->next; | 
 | 	    else | 
 | 		lastLink->next = link->next; | 
 | 	    newLink = link; | 
 | 	    link = link->next; | 
 | 	    xmlFree(newLink); | 
 | 	} else { | 
 | 	    link->type = memberType; | 
 | 	    lastLink = link; | 
 | 	    link = link->next; | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * Add local simple types, | 
 |     */ | 
 |     memberType = type->subtypes; | 
 |     while (memberType != NULL) { | 
 | 	link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink)); | 
 | 	if (link == NULL) { | 
 | 	    xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL); | 
 | 	    return (-1); | 
 | 	} | 
 | 	link->type = memberType; | 
 | 	link->next = NULL; | 
 | 	if (lastLink == NULL) | 
 | 	    type->memberTypes = link; | 
 | 	else | 
 | 	    lastLink->next = link; | 
 | 	lastLink = link; | 
 | 	memberType = memberType->next; | 
 |     } | 
 |     return (0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaIsDerivedFromBuiltInType: | 
 |  * @ctxt:  the schema parser context | 
 |  * @type:  the type definition | 
 |  * @valType: the value type | 
 |  * | 
 |  * | 
 |  * Returns 1 if the type has the given value type, or | 
 |  * is derived from such a type. | 
 |  */ | 
 | static int | 
 | xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType) | 
 | { | 
 |     if (type == NULL) | 
 | 	return (0); | 
 |     if (WXS_IS_COMPLEX(type)) | 
 | 	return (0); | 
 |     if (type->type == XML_SCHEMA_TYPE_BASIC) { | 
 | 	if (type->builtInType == valType) | 
 | 	    return(1); | 
 | 	if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) || | 
 | 	    (type->builtInType == XML_SCHEMAS_ANYTYPE)) | 
 | 	    return (0); | 
 | 	return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType)); | 
 |     } | 
 |     return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType)); | 
 | } | 
 |  | 
 | #if 0 | 
 | /** | 
 |  * xmlSchemaIsDerivedFromBuiltInType: | 
 |  * @ctxt:  the schema parser context | 
 |  * @type:  the type definition | 
 |  * @valType: the value type | 
 |  * | 
 |  * | 
 |  * Returns 1 if the type has the given value type, or | 
 |  * is derived from such a type. | 
 |  */ | 
 | static int | 
 | xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType) | 
 | { | 
 |     if (type == NULL) | 
 | 	return (0); | 
 |     if (WXS_IS_COMPLEX(type)) | 
 | 	return (0); | 
 |     if (type->type == XML_SCHEMA_TYPE_BASIC) { | 
 | 	if (type->builtInType == valType) | 
 | 	    return(1); | 
 | 	return (0); | 
 |     } else | 
 | 	return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType)); | 
 |  | 
 |     return (0); | 
 | } | 
 |  | 
 | static xmlSchemaTypePtr | 
 | xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type) | 
 | { | 
 |     if (type == NULL) | 
 | 	return (NULL); | 
 |     if (WXS_IS_COMPLEX(type)) | 
 | 	return (NULL); | 
 |     if (type->type == XML_SCHEMA_TYPE_BASIC) | 
 | 	return(type); | 
 |     return(xmlSchemaQueryBuiltInType(type->subtypes)); | 
 | } | 
 | #endif | 
 |  | 
 | /** | 
 |  * xmlSchemaGetPrimitiveType: | 
 |  * @type:  the simpleType definition | 
 |  * | 
 |  * Returns the primitive type of the given type or | 
 |  * NULL in case of error. | 
 |  */ | 
 | static xmlSchemaTypePtr | 
 | xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type) | 
 | { | 
 |  | 
 |     while (type != NULL) { | 
 | 	/* | 
 | 	* Note that anySimpleType is actually not a primitive type | 
 | 	* but we need that here. | 
 | 	*/ | 
 | 	if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) || | 
 | 	   (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE)) | 
 | 	    return (type); | 
 | 	type = type->baseType; | 
 |     } | 
 |  | 
 |     return (NULL); | 
 | } | 
 |  | 
 | #if 0 | 
 | /** | 
 |  * xmlSchemaGetBuiltInTypeAncestor: | 
 |  * @type:  the simpleType definition | 
 |  * | 
 |  * Returns the primitive type of the given type or | 
 |  * NULL in case of error. | 
 |  */ | 
 | static xmlSchemaTypePtr | 
 | xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type) | 
 | { | 
 |     if (WXS_IS_LIST(type) || WXS_IS_UNION(type)) | 
 | 	return (0); | 
 |     while (type != NULL) { | 
 | 	if (type->type == XML_SCHEMA_TYPE_BASIC) | 
 | 	    return (type); | 
 | 	type = type->baseType; | 
 |     } | 
 |  | 
 |     return (NULL); | 
 | } | 
 | #endif | 
 |  | 
 | /** | 
 |  * xmlSchemaCloneWildcardNsConstraints: | 
 |  * @ctxt:  the schema parser context | 
 |  * @dest:  the destination wildcard | 
 |  * @source: the source wildcard | 
 |  * | 
 |  * Clones the namespace constraints of source | 
 |  * and assignes them to dest. | 
 |  * Returns -1 on internal error, 0 otherwise. | 
 |  */ | 
 | static int | 
 | xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt, | 
 | 				    xmlSchemaWildcardPtr dest, | 
 | 				    xmlSchemaWildcardPtr source) | 
 | { | 
 |     xmlSchemaWildcardNsPtr cur, tmp, last; | 
 |  | 
 |     if ((source == NULL) || (dest == NULL)) | 
 | 	return(-1); | 
 |     dest->any = source->any; | 
 |     cur = source->nsSet; | 
 |     last = NULL; | 
 |     while (cur != NULL) { | 
 | 	tmp = xmlSchemaNewWildcardNsConstraint(ctxt); | 
 | 	if (tmp == NULL) | 
 | 	    return(-1); | 
 | 	tmp->value = cur->value; | 
 | 	if (last == NULL) | 
 | 	    dest->nsSet = tmp; | 
 | 	else | 
 | 	    last->next = tmp; | 
 | 	last = tmp; | 
 | 	cur = cur->next; | 
 |     } | 
 |     if (dest->negNsSet != NULL) | 
 | 	xmlSchemaFreeWildcardNsSet(dest->negNsSet); | 
 |     if (source->negNsSet != NULL) { | 
 | 	dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt); | 
 | 	if (dest->negNsSet == NULL) | 
 | 	    return(-1); | 
 | 	dest->negNsSet->value = source->negNsSet->value; | 
 |     } else | 
 | 	dest->negNsSet = NULL; | 
 |     return(0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaUnionWildcards: | 
 |  * @ctxt:  the schema parser context | 
 |  * @completeWild:  the first wildcard | 
 |  * @curWild: the second wildcard | 
 |  * | 
 |  * Unions the namespace constraints of the given wildcards. | 
 |  * @completeWild will hold the resulting union. | 
 |  * Returns a positive error code on failure, -1 in case of an | 
 |  * internal error, 0 otherwise. | 
 |  */ | 
 | static int | 
 | xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt, | 
 | 			    xmlSchemaWildcardPtr completeWild, | 
 | 			    xmlSchemaWildcardPtr curWild) | 
 | { | 
 |     xmlSchemaWildcardNsPtr cur, curB, tmp; | 
 |  | 
 |     /* | 
 |     * 1 If O1 and O2 are the same value, then that value must be the | 
 |     * value. | 
 |     */ | 
 |     if ((completeWild->any == curWild->any) && | 
 | 	((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) && | 
 | 	((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) { | 
 |  | 
 | 	if ((completeWild->negNsSet == NULL) || | 
 | 	    (completeWild->negNsSet->value == curWild->negNsSet->value)) { | 
 |  | 
 | 	    if (completeWild->nsSet != NULL) { | 
 | 		int found = 0; | 
 |  | 
 | 		/* | 
 | 		* Check equality of sets. | 
 | 		*/ | 
 | 		cur = completeWild->nsSet; | 
 | 		while (cur != NULL) { | 
 | 		    found = 0; | 
 | 		    curB = curWild->nsSet; | 
 | 		    while (curB != NULL) { | 
 | 			if (cur->value == curB->value) { | 
 | 			    found = 1; | 
 | 			    break; | 
 | 			} | 
 | 			curB = curB->next; | 
 | 		    } | 
 | 		    if (!found) | 
 | 			break; | 
 | 		    cur = cur->next; | 
 | 		} | 
 | 		if (found) | 
 | 		    return(0); | 
 | 	    } else | 
 | 		return(0); | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * 2 If either O1 or O2 is any, then any must be the value | 
 |     */ | 
 |     if (completeWild->any != curWild->any) { | 
 | 	if (completeWild->any == 0) { | 
 | 	    completeWild->any = 1; | 
 | 	    if (completeWild->nsSet != NULL) { | 
 | 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet); | 
 | 		completeWild->nsSet = NULL; | 
 | 	    } | 
 | 	    if (completeWild->negNsSet != NULL) { | 
 | 		xmlFree(completeWild->negNsSet); | 
 | 		completeWild->negNsSet = NULL; | 
 | 	    } | 
 | 	} | 
 | 	return (0); | 
 |     } | 
 |     /* | 
 |     * 3 If both O1 and O2 are sets of (namespace names or �absent�), | 
 |     * then the union of those sets must be the value. | 
 |     */ | 
 |     if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) { | 
 | 	int found; | 
 | 	xmlSchemaWildcardNsPtr start; | 
 |  | 
 | 	cur = curWild->nsSet; | 
 | 	start = completeWild->nsSet; | 
 | 	while (cur != NULL) { | 
 | 	    found = 0; | 
 | 	    curB = start; | 
 | 	    while (curB != NULL) { | 
 | 		if (cur->value == curB->value) { | 
 | 		    found = 1; | 
 | 		    break; | 
 | 		} | 
 | 		curB = curB->next; | 
 | 	    } | 
 | 	    if (!found) { | 
 | 		tmp = xmlSchemaNewWildcardNsConstraint(ctxt); | 
 | 		if (tmp == NULL) | 
 | 		    return (-1); | 
 | 		tmp->value = cur->value; | 
 | 		tmp->next = completeWild->nsSet; | 
 | 		completeWild->nsSet = tmp; | 
 | 	    } | 
 | 	    cur = cur->next; | 
 | 	} | 
 |  | 
 | 	return(0); | 
 |     } | 
 |     /* | 
 |     * 4 If the two are negations of different values (namespace names | 
 |     * or �absent�), then a pair of not and �absent� must be the value. | 
 |     */ | 
 |     if ((completeWild->negNsSet != NULL) && | 
 | 	(curWild->negNsSet != NULL) && | 
 | 	(completeWild->negNsSet->value != curWild->negNsSet->value)) { | 
 | 	completeWild->negNsSet->value = NULL; | 
 |  | 
 | 	return(0); | 
 |     } | 
 |     /* | 
 |      * 5. | 
 |      */ | 
 |     if (((completeWild->negNsSet != NULL) && | 
 | 	(completeWild->negNsSet->value != NULL) && | 
 | 	(curWild->nsSet != NULL)) || | 
 | 	((curWild->negNsSet != NULL) && | 
 | 	(curWild->negNsSet->value != NULL) && | 
 | 	(completeWild->nsSet != NULL))) { | 
 |  | 
 | 	int nsFound, absentFound = 0; | 
 |  | 
 | 	if (completeWild->nsSet != NULL) { | 
 | 	    cur = completeWild->nsSet; | 
 | 	    curB = curWild->negNsSet; | 
 | 	} else { | 
 | 	    cur = curWild->nsSet; | 
 | 	    curB = completeWild->negNsSet; | 
 | 	} | 
 | 	nsFound = 0; | 
 | 	while (cur != NULL) { | 
 | 	    if (cur->value == NULL) | 
 | 		absentFound = 1; | 
 | 	    else if (cur->value == curB->value) | 
 | 		nsFound = 1; | 
 | 	    if (nsFound && absentFound) | 
 | 		break; | 
 | 	    cur = cur->next; | 
 | 	} | 
 |  | 
 | 	if (nsFound && absentFound) { | 
 | 	    /* | 
 | 	    * 5.1 If the set S includes both the negated namespace | 
 | 	    * name and �absent�, then any must be the value. | 
 | 	    */ | 
 | 	    completeWild->any = 1; | 
 | 	    if (completeWild->nsSet != NULL) { | 
 | 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet); | 
 | 		completeWild->nsSet = NULL; | 
 | 	    } | 
 | 	    if (completeWild->negNsSet != NULL) { | 
 | 		xmlFree(completeWild->negNsSet); | 
 | 		completeWild->negNsSet = NULL; | 
 | 	    } | 
 | 	} else if (nsFound && (!absentFound)) { | 
 | 	    /* | 
 | 	    * 5.2 If the set S includes the negated namespace name | 
 | 	    * but not �absent�, then a pair of not and �absent� must | 
 | 	    * be the value. | 
 | 	    */ | 
 | 	    if (completeWild->nsSet != NULL) { | 
 | 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet); | 
 | 		completeWild->nsSet = NULL; | 
 | 	    } | 
 | 	    if (completeWild->negNsSet == NULL) { | 
 | 		completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt); | 
 | 		if (completeWild->negNsSet == NULL) | 
 | 		    return (-1); | 
 | 	    } | 
 | 	    completeWild->negNsSet->value = NULL; | 
 | 	} else if ((!nsFound) && absentFound) { | 
 | 	    /* | 
 | 	    * 5.3 If the set S includes �absent� but not the negated | 
 | 	    * namespace name, then the union is not expressible. | 
 | 	    */ | 
 | 	    xmlSchemaPErr(ctxt, completeWild->node, | 
 | 		XML_SCHEMAP_UNION_NOT_EXPRESSIBLE, | 
 | 		"The union of the wilcard is not expressible.\n", | 
 | 		NULL, NULL); | 
 | 	    return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE); | 
 | 	} else if ((!nsFound) && (!absentFound)) { | 
 | 	    /* | 
 | 	    * 5.4 If the set S does not include either the negated namespace | 
 | 	    * name or �absent�, then whichever of O1 or O2 is a pair of not | 
 | 	    * and a namespace name must be the value. | 
 | 	    */ | 
 | 	    if (completeWild->negNsSet == NULL) { | 
 | 		if (completeWild->nsSet != NULL) { | 
 | 		    xmlSchemaFreeWildcardNsSet(completeWild->nsSet); | 
 | 		    completeWild->nsSet = NULL; | 
 | 		} | 
 | 		completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt); | 
 | 		if (completeWild->negNsSet == NULL) | 
 | 		    return (-1); | 
 | 		completeWild->negNsSet->value = curWild->negNsSet->value; | 
 | 	    } | 
 | 	} | 
 | 	return (0); | 
 |     } | 
 |     /* | 
 |      * 6. | 
 |      */ | 
 |     if (((completeWild->negNsSet != NULL) && | 
 | 	(completeWild->negNsSet->value == NULL) && | 
 | 	(curWild->nsSet != NULL)) || | 
 | 	((curWild->negNsSet != NULL) && | 
 | 	(curWild->negNsSet->value == NULL) && | 
 | 	(completeWild->nsSet != NULL))) { | 
 |  | 
 | 	if (completeWild->nsSet != NULL) { | 
 | 	    cur = completeWild->nsSet; | 
 | 	} else { | 
 | 	    cur = curWild->nsSet; | 
 | 	} | 
 | 	while (cur != NULL) { | 
 | 	    if (cur->value == NULL) { | 
 | 		/* | 
 | 		* 6.1 If the set S includes �absent�, then any must be the | 
 | 		* value. | 
 | 		*/ | 
 | 		completeWild->any = 1; | 
 | 		if (completeWild->nsSet != NULL) { | 
 | 		    xmlSchemaFreeWildcardNsSet(completeWild->nsSet); | 
 | 		    completeWild->nsSet = NULL; | 
 | 		} | 
 | 		if (completeWild->negNsSet != NULL) { | 
 | 		    xmlFree(completeWild->negNsSet); | 
 | 		    completeWild->negNsSet = NULL; | 
 | 		} | 
 | 		return (0); | 
 | 	    } | 
 | 	    cur = cur->next; | 
 | 	} | 
 | 	if (completeWild->negNsSet == NULL) { | 
 | 	    /* | 
 | 	    * 6.2 If the set S does not include �absent�, then a pair of not | 
 | 	    * and �absent� must be the value. | 
 | 	    */ | 
 | 	    if (completeWild->nsSet != NULL) { | 
 | 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet); | 
 | 		completeWild->nsSet = NULL; | 
 | 	    } | 
 | 	    completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt); | 
 | 	    if (completeWild->negNsSet == NULL) | 
 | 		return (-1); | 
 | 	    completeWild->negNsSet->value = NULL; | 
 | 	} | 
 | 	return (0); | 
 |     } | 
 |     return (0); | 
 |  | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaIntersectWildcards: | 
 |  * @ctxt:  the schema parser context | 
 |  * @completeWild:  the first wildcard | 
 |  * @curWild: the second wildcard | 
 |  * | 
 |  * Intersects the namespace constraints of the given wildcards. | 
 |  * @completeWild will hold the resulting intersection. | 
 |  * Returns a positive error code on failure, -1 in case of an | 
 |  * internal error, 0 otherwise. | 
 |  */ | 
 | static int | 
 | xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt, | 
 | 			    xmlSchemaWildcardPtr completeWild, | 
 | 			    xmlSchemaWildcardPtr curWild) | 
 | { | 
 |     xmlSchemaWildcardNsPtr cur, curB, prev,  tmp; | 
 |  | 
 |     /* | 
 |     * 1 If O1 and O2 are the same value, then that value must be the | 
 |     * value. | 
 |     */ | 
 |     if ((completeWild->any == curWild->any) && | 
 | 	((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) && | 
 | 	((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) { | 
 |  | 
 | 	if ((completeWild->negNsSet == NULL) || | 
 | 	    (completeWild->negNsSet->value == curWild->negNsSet->value)) { | 
 |  | 
 | 	    if (completeWild->nsSet != NULL) { | 
 | 		int found = 0; | 
 |  | 
 | 		/* | 
 | 		* Check equality of sets. | 
 | 		*/ | 
 | 		cur = completeWild->nsSet; | 
 | 		while (cur != NULL) { | 
 | 		    found = 0; | 
 | 		    curB = curWild->nsSet; | 
 | 		    while (curB != NULL) { | 
 | 			if (cur->value == curB->value) { | 
 | 			    found = 1; | 
 | 			    break; | 
 | 			} | 
 | 			curB = curB->next; | 
 | 		    } | 
 | 		    if (!found) | 
 | 			break; | 
 | 		    cur = cur->next; | 
 | 		} | 
 | 		if (found) | 
 | 		    return(0); | 
 | 	    } else | 
 | 		return(0); | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * 2 If either O1 or O2 is any, then the other must be the value. | 
 |     */ | 
 |     if ((completeWild->any != curWild->any) && (completeWild->any)) { | 
 | 	if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1) | 
 | 	    return(-1); | 
 | 	return(0); | 
 |     } | 
 |     /* | 
 |     * 3 If either O1 or O2 is a pair of not and a value (a namespace | 
 |     * name or �absent�) and the other is a set of (namespace names or | 
 |     * �absent�), then that set, minus the negated value if it was in | 
 |     * the set, minus �absent� if it was in the set, must be the value. | 
 |     */ | 
 |     if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) || | 
 | 	((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) { | 
 | 	const xmlChar *neg; | 
 |  | 
 | 	if (completeWild->nsSet == NULL) { | 
 | 	    neg = completeWild->negNsSet->value; | 
 | 	    if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1) | 
 | 		return(-1); | 
 | 	} else | 
 | 	    neg = curWild->negNsSet->value; | 
 | 	/* | 
 | 	* Remove absent and negated. | 
 | 	*/ | 
 | 	prev = NULL; | 
 | 	cur = completeWild->nsSet; | 
 | 	while (cur != NULL) { | 
 | 	    if (cur->value == NULL) { | 
 | 		if (prev == NULL) | 
 | 		    completeWild->nsSet = cur->next; | 
 | 		else | 
 | 		    prev->next = cur->next; | 
 | 		xmlFree(cur); | 
 | 		break; | 
 | 	    } | 
 | 	    prev = cur; | 
 | 	    cur = cur->next; | 
 | 	} | 
 | 	if (neg != NULL) { | 
 | 	    prev = NULL; | 
 | 	    cur = completeWild->nsSet; | 
 | 	    while (cur != NULL) { | 
 | 		if (cur->value == neg) { | 
 | 		    if (prev == NULL) | 
 | 			completeWild->nsSet = cur->next; | 
 | 		    else | 
 | 			prev->next = cur->next; | 
 | 		    xmlFree(cur); | 
 | 		    break; | 
 | 		} | 
 | 		prev = cur; | 
 | 		cur = cur->next; | 
 | 	    } | 
 | 	} | 
 |  | 
 | 	return(0); | 
 |     } | 
 |     /* | 
 |     * 4 If both O1 and O2 are sets of (namespace names or �absent�), | 
 |     * then the intersection of those sets must be the value. | 
 |     */ | 
 |     if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) { | 
 | 	int found; | 
 |  | 
 | 	cur = completeWild->nsSet; | 
 | 	prev = NULL; | 
 | 	while (cur != NULL) { | 
 | 	    found = 0; | 
 | 	    curB = curWild->nsSet; | 
 | 	    while (curB != NULL) { | 
 | 		if (cur->value == curB->value) { | 
 | 		    found = 1; | 
 | 		    break; | 
 | 		} | 
 | 		curB = curB->next; | 
 | 	    } | 
 | 	    if (!found) { | 
 | 		if (prev == NULL) | 
 | 		    completeWild->nsSet = cur->next; | 
 | 		else | 
 | 		    prev->next = cur->next; | 
 | 		tmp = cur->next; | 
 | 		xmlFree(cur); | 
 | 		cur = tmp; | 
 | 		continue; | 
 | 	    } | 
 | 	    prev = cur; | 
 | 	    cur = cur->next; | 
 | 	} | 
 |  | 
 | 	return(0); | 
 |     } | 
 |     /* 5 If the two are negations of different namespace names, | 
 |     * then the intersection is not expressible | 
 |     */ | 
 |     if ((completeWild->negNsSet != NULL) && | 
 | 	(curWild->negNsSet != NULL) && | 
 | 	(completeWild->negNsSet->value != curWild->negNsSet->value) && | 
 | 	(completeWild->negNsSet->value != NULL) && | 
 | 	(curWild->negNsSet->value != NULL)) { | 
 |  | 
 | 	xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE, | 
 | 	    "The intersection of the wilcard is not expressible.\n", | 
 | 	    NULL, NULL); | 
 | 	return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE); | 
 |     } | 
 |     /* | 
 |     * 6 If the one is a negation of a namespace name and the other | 
 |     * is a negation of �absent�, then the one which is the negation | 
 |     * of a namespace name must be the value. | 
 |     */ | 
 |     if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) && | 
 | 	(completeWild->negNsSet->value != curWild->negNsSet->value) && | 
 | 	(completeWild->negNsSet->value == NULL)) { | 
 | 	completeWild->negNsSet->value =  curWild->negNsSet->value; | 
 |     } | 
 |     return(0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaIsWildcardNsConstraintSubset: | 
 |  * @ctxt:  the schema parser context | 
 |  * @sub:  the first wildcard | 
 |  * @super: the second wildcard | 
 |  * | 
 |  * Schema Component Constraint: Wildcard Subset (cos-ns-subset) | 
 |  * | 
 |  * Returns 0 if the namespace constraint of @sub is an intensional | 
 |  * subset of @super, 1 otherwise. | 
 |  */ | 
 | static int | 
 | xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub, | 
 | 			  xmlSchemaWildcardPtr super) | 
 | { | 
 |     /* | 
 |     * 1 super must be any. | 
 |     */ | 
 |     if (super->any) | 
 | 	return (0); | 
 |     /* | 
 |     * 2.1 sub must be a pair of not and a namespace name or �absent�. | 
 |     * 2.2 super must be a pair of not and the same value. | 
 |     */ | 
 |     if ((sub->negNsSet != NULL) && | 
 | 	(super->negNsSet != NULL) && | 
 | 	(sub->negNsSet->value == super->negNsSet->value)) | 
 | 	return (0); | 
 |     /* | 
 |     * 3.1 sub must be a set whose members are either namespace names or �absent�. | 
 |     */ | 
 |     if (sub->nsSet != NULL) { | 
 | 	/* | 
 | 	* 3.2.1 super must be the same set or a superset thereof. | 
 | 	*/ | 
 | 	if (super->nsSet != NULL) { | 
 | 	    xmlSchemaWildcardNsPtr cur, curB; | 
 | 	    int found = 0; | 
 |  | 
 | 	    cur = sub->nsSet; | 
 | 	    while (cur != NULL) { | 
 | 		found = 0; | 
 | 		curB = super->nsSet; | 
 | 		while (curB != NULL) { | 
 | 		    if (cur->value == curB->value) { | 
 | 			found = 1; | 
 | 			break; | 
 | 		    } | 
 | 		    curB = curB->next; | 
 | 		} | 
 | 		if (!found) | 
 | 		    return (1); | 
 | 		cur = cur->next; | 
 | 	    } | 
 | 	    if (found) | 
 | 		return (0); | 
 | 	} else if (super->negNsSet != NULL) { | 
 | 	    xmlSchemaWildcardNsPtr cur; | 
 | 	    /* | 
 | 	    * 3.2.2 super must be a pair of not and a namespace name or | 
 | 	    * �absent� and that value must not be in sub's set. | 
 | 	    */ | 
 | 	    cur = sub->nsSet; | 
 | 	    while (cur != NULL) { | 
 | 		if (cur->value == super->negNsSet->value) | 
 | 		    return (1); | 
 | 		cur = cur->next; | 
 | 	    } | 
 | 	    return (0); | 
 | 	} | 
 |     } | 
 |     return (1); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse, | 
 | 				     int *fixed, | 
 | 				     const xmlChar **value, | 
 | 				     xmlSchemaValPtr *val) | 
 | { | 
 |     *fixed = 0; | 
 |     *value = NULL; | 
 |     if (val != 0) | 
 | 	*val = NULL; | 
 |  | 
 |     if (attruse->defValue != NULL) { | 
 | 	*value = attruse->defValue; | 
 | 	if (val != NULL) | 
 | 	    *val = attruse->defVal; | 
 | 	if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED) | 
 | 	    *fixed = 1; | 
 | 	return(1); | 
 |     } else if ((attruse->attrDecl != NULL) && | 
 | 	(attruse->attrDecl->defValue != NULL)) { | 
 | 	*value = attruse->attrDecl->defValue; | 
 | 	if (val != NULL) | 
 | 	    *val = attruse->attrDecl->defVal; | 
 | 	if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED) | 
 | 	    *fixed = 1; | 
 | 	return(1); | 
 |     } | 
 |     return(0); | 
 | } | 
 | /** | 
 |  * xmlSchemaCheckCVCWildcardNamespace: | 
 |  * @wild:  the wildcard | 
 |  * @ns:  the namespace | 
 |  * | 
 |  * Validation Rule: Wildcard allows Namespace Name | 
 |  * (cvc-wildcard-namespace) | 
 |  * | 
 |  * Returns 0 if the given namespace matches the wildcard, | 
 |  * 1 otherwise and -1 on API errors. | 
 |  */ | 
 | static int | 
 | xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild, | 
 | 				   const xmlChar* ns) | 
 | { | 
 |     if (wild == NULL) | 
 | 	return(-1); | 
 |  | 
 |     if (wild->any) | 
 | 	return(0); | 
 |     else if (wild->nsSet != NULL) { | 
 | 	xmlSchemaWildcardNsPtr cur; | 
 |  | 
 | 	cur = wild->nsSet; | 
 | 	while (cur != NULL) { | 
 | 	    if (xmlStrEqual(cur->value, ns)) | 
 | 		return(0); | 
 | 	    cur = cur->next; | 
 | 	} | 
 |     } else if ((wild->negNsSet != NULL) && (ns != NULL) && | 
 | 	(!xmlStrEqual(wild->negNsSet->value, ns))) | 
 | 	return(0); | 
 |  | 
 |     return(1); | 
 | } | 
 |  | 
 | #define XML_SCHEMA_ACTION_DERIVE 0 | 
 | #define XML_SCHEMA_ACTION_REDEFINE 1 | 
 |  | 
 | #define WXS_ACTION_STR(a) \ | 
 | ((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined" | 
 |  | 
 | /* | 
 | * Schema Component Constraint: | 
 | *   Derivation Valid (Restriction, Complex) | 
 | *   derivation-ok-restriction (2) - (4) | 
 | * | 
 | * ATTENTION: | 
 | * In XML Schema 1.1 this will be: | 
 | * Validation Rule: | 
 | *     Checking complex type subsumption (practicalSubsumption) (1, 2 and 3) | 
 | * | 
 | */ | 
 | static int | 
 | xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt, | 
 | 				       int action, | 
 | 				       xmlSchemaBasicItemPtr item, | 
 | 				       xmlSchemaBasicItemPtr baseItem, | 
 | 				       xmlSchemaItemListPtr uses, | 
 | 				       xmlSchemaItemListPtr baseUses, | 
 | 				       xmlSchemaWildcardPtr wild, | 
 | 				       xmlSchemaWildcardPtr baseWild) | 
 | { | 
 |     xmlSchemaAttributeUsePtr cur = NULL, bcur; | 
 |     int i, j, found; /* err = 0; */ | 
 |     const xmlChar *bEffValue; | 
 |     int effFixed; | 
 |  | 
 |     if (uses != NULL) { | 
 | 	for (i = 0; i < uses->nbItems; i++) { | 
 | 	    cur = uses->items[i]; | 
 | 	    found = 0; | 
 | 	    if (baseUses == NULL) | 
 | 		goto not_found; | 
 | 	    for (j = 0; j < baseUses->nbItems; j++) { | 
 | 		bcur = baseUses->items[j]; | 
 | 		if ((WXS_ATTRUSE_DECL_NAME(cur) == | 
 | 			WXS_ATTRUSE_DECL_NAME(bcur)) && | 
 | 		    (WXS_ATTRUSE_DECL_TNS(cur) == | 
 | 			WXS_ATTRUSE_DECL_TNS(bcur))) | 
 | 		{ | 
 | 		    /* | 
 | 		    * (2.1) "If there is an attribute use in the {attribute | 
 | 		    * uses} of the {base type definition} (call this B) whose | 
 | 		    * {attribute declaration} has the same {name} and {target | 
 | 		    * namespace}, then  all of the following must be true:" | 
 | 		    */ | 
 | 		    found = 1; | 
 |  | 
 | 		    if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) && | 
 | 			(bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) | 
 | 		    { | 
 | 			xmlChar *str = NULL; | 
 | 			/* | 
 | 			* (2.1.1) "one of the following must be true:" | 
 | 			* (2.1.1.1) "B's {required} is false." | 
 | 			* (2.1.1.2) "R's {required} is true." | 
 | 			*/ | 
 | 			xmlSchemaPAttrUseErr4(pctxt, | 
 | 			    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1, | 
 | 			    WXS_ITEM_NODE(item), item, cur, | 
 | 			    "The 'optional' attribute use is inconsistent " | 
 | 			    "with the corresponding 'required' attribute use of " | 
 | 			    "the %s %s", | 
 | 			    WXS_ACTION_STR(action), | 
 | 			    xmlSchemaGetComponentDesignation(&str, baseItem), | 
 | 			    NULL, NULL); | 
 | 			FREE_AND_NULL(str); | 
 | 			/* err = pctxt->err; */ | 
 | 		    } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, | 
 | 			WXS_ATTRUSE_TYPEDEF(cur), | 
 | 			WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0) | 
 | 		    { | 
 | 			xmlChar *strA = NULL, *strB = NULL, *strC = NULL; | 
 |  | 
 | 			/* | 
 | 			* SPEC (2.1.2) "R's {attribute declaration}'s | 
 | 			* {type definition} must be validly derived from | 
 | 			* B's {type definition} given the empty set as | 
 | 			* defined in Type Derivation OK (Simple) (�3.14.6)." | 
 | 			*/ | 
 | 			xmlSchemaPAttrUseErr4(pctxt, | 
 | 			    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2, | 
 | 			    WXS_ITEM_NODE(item), item, cur, | 
 | 			    "The attribute declaration's %s " | 
 | 			    "is not validly derived from " | 
 | 			    "the corresponding %s of the " | 
 | 			    "attribute declaration in the %s %s", | 
 | 			    xmlSchemaGetComponentDesignation(&strA, | 
 | 				WXS_ATTRUSE_TYPEDEF(cur)), | 
 | 			    xmlSchemaGetComponentDesignation(&strB, | 
 | 				WXS_ATTRUSE_TYPEDEF(bcur)), | 
 | 			    WXS_ACTION_STR(action), | 
 | 			    xmlSchemaGetComponentDesignation(&strC, baseItem)); | 
 | 			    /* xmlSchemaGetComponentDesignation(&str, baseItem), */ | 
 | 			FREE_AND_NULL(strA); | 
 | 			FREE_AND_NULL(strB); | 
 | 			FREE_AND_NULL(strC); | 
 | 			/* err = pctxt->err; */ | 
 | 		    } else { | 
 | 			/* | 
 | 			* 2.1.3 [Definition:]  Let the effective value | 
 | 			* constraint of an attribute use be its {value | 
 | 			* constraint}, if present, otherwise its {attribute | 
 | 			* declaration}'s {value constraint} . | 
 | 			*/ | 
 | 			xmlSchemaGetEffectiveValueConstraint(bcur, | 
 | 			    &effFixed, &bEffValue, NULL); | 
 | 			/* | 
 | 			* 2.1.3 ... one of the following must be true | 
 | 			* | 
 | 			* 2.1.3.1 B's �effective value constraint� is | 
 | 			* �absent� or default. | 
 | 			*/ | 
 | 			if ((bEffValue != NULL) && | 
 | 			    (effFixed == 1)) { | 
 | 			    const xmlChar *rEffValue = NULL; | 
 |  | 
 | 			    xmlSchemaGetEffectiveValueConstraint(bcur, | 
 | 				&effFixed, &rEffValue, NULL); | 
 | 			    /* | 
 | 			    * 2.1.3.2 R's �effective value constraint� is | 
 | 			    * fixed with the same string as B's. | 
 | 			    * MAYBE TODO: Compare the computed values. | 
 | 			    *       Hmm, it says "same string" so | 
 | 			    *       string-equality might really be sufficient. | 
 | 			    */ | 
 | 			    if ((effFixed == 0) || | 
 | 				(! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue))) | 
 | 			    { | 
 | 				xmlChar *str = NULL; | 
 |  | 
 | 				xmlSchemaPAttrUseErr4(pctxt, | 
 | 				    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3, | 
 | 				    WXS_ITEM_NODE(item), item, cur, | 
 | 				    "The effective value constraint of the " | 
 | 				    "attribute use is inconsistent with " | 
 | 				    "its correspondent in the %s %s", | 
 | 				    WXS_ACTION_STR(action), | 
 | 				    xmlSchemaGetComponentDesignation(&str, | 
 | 					baseItem), | 
 | 				    NULL, NULL); | 
 | 				FREE_AND_NULL(str); | 
 | 				/* err = pctxt->err; */ | 
 | 			    } | 
 | 			} | 
 | 		    } | 
 | 		    break; | 
 | 		} | 
 | 	    } | 
 | not_found: | 
 | 	    if (!found) { | 
 | 		/* | 
 | 		* (2.2) "otherwise the {base type definition} must have an | 
 | 		* {attribute wildcard} and the {target namespace} of the | 
 | 		* R's {attribute declaration} must be �valid� with respect | 
 | 		* to that wildcard, as defined in Wildcard allows Namespace | 
 | 		* Name (�3.10.4)." | 
 | 		*/ | 
 | 		if ((baseWild == NULL) || | 
 | 		    (xmlSchemaCheckCVCWildcardNamespace(baseWild, | 
 | 		    (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0)) | 
 | 		{ | 
 | 		    xmlChar *str = NULL; | 
 |  | 
 | 		    xmlSchemaPAttrUseErr4(pctxt, | 
 | 			XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2, | 
 | 			WXS_ITEM_NODE(item), item, cur, | 
 | 			"Neither a matching attribute use, " | 
 | 			"nor a matching wildcard exists in the %s %s", | 
 | 			WXS_ACTION_STR(action), | 
 | 			xmlSchemaGetComponentDesignation(&str, baseItem), | 
 | 			NULL, NULL); | 
 | 		    FREE_AND_NULL(str); | 
 | 		    /* err = pctxt->err; */ | 
 | 		} | 
 | 	    } | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * SPEC derivation-ok-restriction (3): | 
 |     * (3) "For each attribute use in the {attribute uses} of the {base type | 
 |     * definition} whose {required} is true, there must be an attribute | 
 |     * use with an {attribute declaration} with the same {name} and | 
 |     * {target namespace} as its {attribute declaration} in the {attribute | 
 |     * uses} of the complex type definition itself whose {required} is true. | 
 |     */ | 
 |     if (baseUses != NULL) { | 
 | 	for (j = 0; j < baseUses->nbItems; j++) { | 
 | 	    bcur = baseUses->items[j]; | 
 | 	    if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED) | 
 | 		continue; | 
 | 	    found = 0; | 
 | 	    if (uses != NULL) { | 
 | 		for (i = 0; i < uses->nbItems; i++) { | 
 | 		    cur = uses->items[i]; | 
 | 		    if ((WXS_ATTRUSE_DECL_NAME(cur) == | 
 | 			WXS_ATTRUSE_DECL_NAME(bcur)) && | 
 | 			(WXS_ATTRUSE_DECL_TNS(cur) == | 
 | 			WXS_ATTRUSE_DECL_TNS(bcur))) { | 
 | 			found = 1; | 
 | 			break; | 
 | 		    } | 
 | 		} | 
 | 	    } | 
 | 	    if (!found) { | 
 | 		xmlChar *strA = NULL, *strB = NULL; | 
 |  | 
 | 		xmlSchemaCustomErr4(ACTXT_CAST pctxt, | 
 | 		    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3, | 
 | 		    NULL, item, | 
 | 		    "A matching attribute use for the " | 
 | 		    "'required' %s of the %s %s is missing", | 
 | 		    xmlSchemaGetComponentDesignation(&strA, bcur), | 
 | 		    WXS_ACTION_STR(action), | 
 | 		    xmlSchemaGetComponentDesignation(&strB, baseItem), | 
 | 		    NULL); | 
 | 		FREE_AND_NULL(strA); | 
 | 		FREE_AND_NULL(strB); | 
 | 	    } | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * derivation-ok-restriction (4) | 
 |     */ | 
 |     if (wild != NULL) { | 
 | 	/* | 
 | 	* (4) "If there is an {attribute wildcard}, all of the | 
 | 	* following must be true:" | 
 | 	*/ | 
 | 	if (baseWild == NULL) { | 
 | 	    xmlChar *str = NULL; | 
 |  | 
 | 	    /* | 
 | 	    * (4.1) "The {base type definition} must also have one." | 
 | 	    */ | 
 | 	    xmlSchemaCustomErr4(ACTXT_CAST pctxt, | 
 | 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1, | 
 | 		NULL, item, | 
 | 		"The %s has an attribute wildcard, " | 
 | 		"but the %s %s '%s' does not have one", | 
 | 		WXS_ITEM_TYPE_NAME(item), | 
 | 		WXS_ACTION_STR(action), | 
 | 		WXS_ITEM_TYPE_NAME(baseItem), | 
 | 		xmlSchemaGetComponentQName(&str, baseItem)); | 
 | 	    FREE_AND_NULL(str); | 
 | 	    return(pctxt->err); | 
 | 	} else if ((baseWild->any == 0) && | 
 | 		xmlSchemaCheckCOSNSSubset(wild, baseWild)) | 
 | 	{ | 
 | 	    xmlChar *str = NULL; | 
 | 	    /* | 
 | 	    * (4.2) "The complex type definition's {attribute wildcard}'s | 
 | 	    * {namespace constraint} must be a subset of the {base type | 
 | 	    * definition}'s {attribute wildcard}'s {namespace constraint}, | 
 | 	    * as defined by Wildcard Subset (�3.10.6)." | 
 | 	    */ | 
 | 	    xmlSchemaCustomErr4(ACTXT_CAST pctxt, | 
 | 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2, | 
 | 		NULL, item, | 
 | 		"The attribute wildcard is not a valid " | 
 | 		"subset of the wildcard in the %s %s '%s'", | 
 | 		WXS_ACTION_STR(action), | 
 | 		WXS_ITEM_TYPE_NAME(baseItem), | 
 | 		xmlSchemaGetComponentQName(&str, baseItem), | 
 | 		NULL); | 
 | 	    FREE_AND_NULL(str); | 
 | 	    return(pctxt->err); | 
 | 	} | 
 | 	/* 4.3 Unless the {base type definition} is the �ur-type | 
 | 	* definition�, the complex type definition's {attribute | 
 | 	* wildcard}'s {process contents} must be identical to or | 
 | 	* stronger than the {base type definition}'s {attribute | 
 | 	* wildcard}'s {process contents}, where strict is stronger | 
 | 	* than lax is stronger than skip. | 
 | 	*/ | 
 | 	if ((! WXS_IS_ANYTYPE(baseItem)) && | 
 | 	    (wild->processContents < baseWild->processContents)) { | 
 | 	    xmlChar *str = NULL; | 
 | 	    xmlSchemaCustomErr4(ACTXT_CAST pctxt, | 
 | 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3, | 
 | 		NULL, baseItem, | 
 | 		"The {process contents} of the attribute wildcard is " | 
 | 		"weaker than the one in the %s %s '%s'", | 
 | 		WXS_ACTION_STR(action), | 
 | 		WXS_ITEM_TYPE_NAME(baseItem), | 
 | 		xmlSchemaGetComponentQName(&str, baseItem), | 
 | 		NULL); | 
 | 	    FREE_AND_NULL(str) | 
 | 		return(pctxt->err); | 
 | 	} | 
 |     } | 
 |     return(0); | 
 | } | 
 |  | 
 |  | 
 | static int | 
 | xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt, | 
 | 				  xmlSchemaBasicItemPtr item, | 
 | 				  xmlSchemaWildcardPtr *completeWild, | 
 | 				  xmlSchemaItemListPtr list, | 
 | 				  xmlSchemaItemListPtr prohibs); | 
 | /** | 
 |  * xmlSchemaFixupTypeAttributeUses: | 
 |  * @ctxt:  the schema parser context | 
 |  * @type:  the complex type definition | 
 |  * | 
 |  * | 
 |  * Builds the wildcard and the attribute uses on the given complex type. | 
 |  * Returns -1 if an internal error occurs, 0 otherwise. | 
 |  * | 
 |  * ATTENTION TODO: Experimantally this uses pointer comparisons for | 
 |  * strings, so recheck this if we start to hardcode some schemata, since | 
 |  * they might not be in the same dict. | 
 |  * NOTE: It is allowed to "extend" the xs:anyType type. | 
 |  */ | 
 | static int | 
 | xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt, | 
 | 				  xmlSchemaTypePtr type) | 
 | { | 
 |     xmlSchemaTypePtr baseType = NULL; | 
 |     xmlSchemaAttributeUsePtr use; | 
 |     xmlSchemaItemListPtr uses, baseUses, prohibs = NULL; | 
 |  | 
 |     if (type->baseType == NULL) { | 
 | 	PERROR_INT("xmlSchemaFixupTypeAttributeUses", | 
 | 	    "no base type"); | 
 |         return (-1); | 
 |     } | 
 |     baseType = type->baseType; | 
 |     if (WXS_IS_TYPE_NOT_FIXED(baseType)) | 
 | 	if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1) | 
 | 	    return(-1); | 
 |  | 
 |     uses = type->attrUses; | 
 |     baseUses = baseType->attrUses; | 
 |     /* | 
 |     * Expand attribute group references. And build the 'complete' | 
 |     * wildcard, i.e. intersect multiple wildcards. | 
 |     * Move attribute prohibitions into a separate list. | 
 |     */ | 
 |     if (uses != NULL) { | 
 | 	if (WXS_IS_RESTRICTION(type)) { | 
 | 	    /* | 
 | 	    * This one will transfer all attr. prohibitions | 
 | 	    * into pctxt->attrProhibs. | 
 | 	    */ | 
 | 	    if (xmlSchemaExpandAttributeGroupRefs(pctxt, | 
 | 		WXS_BASIC_CAST type, &(type->attributeWildcard), uses, | 
 | 		pctxt->attrProhibs) == -1) | 
 | 	    { | 
 | 		PERROR_INT("xmlSchemaFixupTypeAttributeUses", | 
 | 		"failed to expand attributes"); | 
 | 	    } | 
 | 	    if (pctxt->attrProhibs->nbItems != 0) | 
 | 		prohibs = pctxt->attrProhibs; | 
 | 	} else { | 
 | 	    if (xmlSchemaExpandAttributeGroupRefs(pctxt, | 
 | 		WXS_BASIC_CAST type, &(type->attributeWildcard), uses, | 
 | 		NULL) == -1) | 
 | 	    { | 
 | 		PERROR_INT("xmlSchemaFixupTypeAttributeUses", | 
 | 		"failed to expand attributes"); | 
 | 	    } | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * Inherit the attribute uses of the base type. | 
 |     */ | 
 |     if (baseUses != NULL) { | 
 | 	int i, j; | 
 | 	xmlSchemaAttributeUseProhibPtr pro; | 
 |  | 
 | 	if (WXS_IS_RESTRICTION(type)) { | 
 | 	    int usesCount; | 
 | 	    xmlSchemaAttributeUsePtr tmp; | 
 |  | 
 | 	    if (uses != NULL) | 
 | 		usesCount = uses->nbItems; | 
 | 	    else | 
 | 		usesCount = 0; | 
 |  | 
 | 	    /* Restriction. */ | 
 | 	    for (i = 0; i < baseUses->nbItems; i++) { | 
 | 		use = baseUses->items[i]; | 
 | 		if (prohibs) { | 
 | 		    /* | 
 | 		    * Filter out prohibited uses. | 
 | 		    */ | 
 | 		    for (j = 0; j < prohibs->nbItems; j++) { | 
 | 			pro = prohibs->items[j]; | 
 | 			if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) && | 
 | 			    (WXS_ATTRUSE_DECL_TNS(use) == | 
 | 				pro->targetNamespace)) | 
 | 			{ | 
 | 			    goto inherit_next; | 
 | 			} | 
 | 		    } | 
 | 		} | 
 | 		if (usesCount) { | 
 | 		    /* | 
 | 		    * Filter out existing uses. | 
 | 		    */ | 
 | 		    for (j = 0; j < usesCount; j++) { | 
 | 			tmp = uses->items[j]; | 
 | 			if ((WXS_ATTRUSE_DECL_NAME(use) == | 
 | 				WXS_ATTRUSE_DECL_NAME(tmp)) && | 
 | 			    (WXS_ATTRUSE_DECL_TNS(use) == | 
 | 				WXS_ATTRUSE_DECL_TNS(tmp))) | 
 | 			{ | 
 | 			    goto inherit_next; | 
 | 			} | 
 | 		    } | 
 | 		} | 
 | 		if (uses == NULL) { | 
 | 		    type->attrUses = xmlSchemaItemListCreate(); | 
 | 		    if (type->attrUses == NULL) | 
 | 			goto exit_failure; | 
 | 		    uses = type->attrUses; | 
 | 		} | 
 | 		xmlSchemaItemListAddSize(uses, 2, use); | 
 | inherit_next: {} | 
 | 	    } | 
 | 	} else { | 
 | 	    /* Extension. */ | 
 | 	    for (i = 0; i < baseUses->nbItems; i++) { | 
 | 		use = baseUses->items[i]; | 
 | 		if (uses == NULL) { | 
 | 		    type->attrUses = xmlSchemaItemListCreate(); | 
 | 		    if (type->attrUses == NULL) | 
 | 			goto exit_failure; | 
 | 		    uses = type->attrUses; | 
 | 		} | 
 | 		xmlSchemaItemListAddSize(uses, baseUses->nbItems, use); | 
 | 	    } | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * Shrink attr. uses. | 
 |     */ | 
 |     if (uses) { | 
 | 	if (uses->nbItems == 0) { | 
 | 	    xmlSchemaItemListFree(uses); | 
 | 	    type->attrUses = NULL; | 
 | 	} | 
 | 	/* | 
 | 	* TODO: We could shrink the size of the array | 
 | 	* to fit the actual number of items. | 
 | 	*/ | 
 |     } | 
 |     /* | 
 |     * Compute the complete wildcard. | 
 |     */ | 
 |     if (WXS_IS_EXTENSION(type)) { | 
 | 	if (baseType->attributeWildcard != NULL) { | 
 | 	    /* | 
 | 	    * (3.2.2.1) "If the �base wildcard� is non-�absent�, then | 
 | 	    * the appropriate case among the following:" | 
 | 	    */ | 
 | 	    if (type->attributeWildcard != NULL) { | 
 | 		/* | 
 | 		* Union the complete wildcard with the base wildcard. | 
 | 		* SPEC {attribute wildcard} | 
 | 		* (3.2.2.1.2) "otherwise a wildcard whose {process contents} | 
 | 		* and {annotation} are those of the �complete wildcard�, | 
 | 		* and whose {namespace constraint} is the intensional union | 
 | 		* of the {namespace constraint} of the �complete wildcard� | 
 | 		* and of the �base wildcard�, as defined in Attribute | 
 | 		* Wildcard Union (�3.10.6)." | 
 | 		*/ | 
 | 		if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard, | 
 | 		    baseType->attributeWildcard) == -1) | 
 | 		    goto exit_failure; | 
 | 	    } else { | 
 | 		/* | 
 | 		* (3.2.2.1.1) "If the �complete wildcard� is �absent�, | 
 | 		* then the �base wildcard�." | 
 | 		*/ | 
 | 		type->attributeWildcard = baseType->attributeWildcard; | 
 | 	    } | 
 | 	} else { | 
 | 	    /* | 
 | 	    * (3.2.2.2) "otherwise (the �base wildcard� is �absent�) the | 
 | 	    * �complete wildcard" | 
 | 	    * NOOP | 
 | 	    */ | 
 | 	} | 
 |     } else { | 
 | 	/* | 
 | 	* SPEC {attribute wildcard} | 
 | 	* (3.1) "If the <restriction> alternative is chosen, then the | 
 | 	* �complete wildcard�;" | 
 | 	* NOOP | 
 | 	*/ | 
 |     } | 
 |  | 
 |     return (0); | 
 |  | 
 | exit_failure: | 
 |     return(-1); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaTypeFinalContains: | 
 |  * @schema:  the schema | 
 |  * @type:  the type definition | 
 |  * @final: the final | 
 |  * | 
 |  * Evaluates if a type definition contains the given "final". | 
 |  * This does take "finalDefault" into account as well. | 
 |  * | 
 |  * Returns 1 if the type does containt the given "final", | 
 |  * 0 otherwise. | 
 |  */ | 
 | static int | 
 | xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final) | 
 | { | 
 |     if (type == NULL) | 
 | 	return (0); | 
 |     if (type->flags & final) | 
 | 	return (1); | 
 |     else | 
 | 	return (0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaGetUnionSimpleTypeMemberTypes: | 
 |  * @type:  the Union Simple Type | 
 |  * | 
 |  * Returns a list of member types of @type if existing, | 
 |  * returns NULL otherwise. | 
 |  */ | 
 | static xmlSchemaTypeLinkPtr | 
 | xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type) | 
 | { | 
 |     while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) { | 
 | 	if (type->memberTypes != NULL) | 
 | 	    return (type->memberTypes); | 
 | 	else | 
 | 	    type = type->baseType; | 
 |     } | 
 |     return (NULL); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaGetParticleTotalRangeMin: | 
 |  * @particle: the particle | 
 |  * | 
 |  * Schema Component Constraint: Effective Total Range | 
 |  * (all and sequence) + (choice) | 
 |  * | 
 |  * Returns the minimun Effective Total Range. | 
 |  */ | 
 | static int | 
 | xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle) | 
 | { | 
 |     if ((particle->children == NULL) || | 
 | 	(particle->minOccurs == 0)) | 
 | 	return (0); | 
 |     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) { | 
 | 	int min = -1, cur; | 
 | 	xmlSchemaParticlePtr part = | 
 | 	    (xmlSchemaParticlePtr) particle->children->children; | 
 |  | 
 | 	if (part == NULL) | 
 | 	    return (0); | 
 | 	while (part != NULL) { | 
 | 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) || | 
 | 		(part->children->type == XML_SCHEMA_TYPE_ANY)) | 
 | 		cur = part->minOccurs; | 
 | 	    else | 
 | 		cur = xmlSchemaGetParticleTotalRangeMin(part); | 
 | 	    if (cur == 0) | 
 | 		return (0); | 
 | 	    if ((min > cur) || (min == -1)) | 
 | 		min = cur; | 
 | 	    part = (xmlSchemaParticlePtr) part->next; | 
 | 	} | 
 | 	return (particle->minOccurs * min); | 
 |     } else { | 
 | 	/* <all> and <sequence> */ | 
 | 	int sum = 0; | 
 | 	xmlSchemaParticlePtr part = | 
 | 	    (xmlSchemaParticlePtr) particle->children->children; | 
 |  | 
 | 	if (part == NULL) | 
 | 	    return (0); | 
 | 	do { | 
 | 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) || | 
 | 		(part->children->type == XML_SCHEMA_TYPE_ANY)) | 
 | 		sum += part->minOccurs; | 
 | 	    else | 
 | 		sum += xmlSchemaGetParticleTotalRangeMin(part); | 
 | 	    part = (xmlSchemaParticlePtr) part->next; | 
 | 	} while (part != NULL); | 
 | 	return (particle->minOccurs * sum); | 
 |     } | 
 | } | 
 |  | 
 | #if 0 | 
 | /** | 
 |  * xmlSchemaGetParticleTotalRangeMax: | 
 |  * @particle: the particle | 
 |  * | 
 |  * Schema Component Constraint: Effective Total Range | 
 |  * (all and sequence) + (choice) | 
 |  * | 
 |  * Returns the maximum Effective Total Range. | 
 |  */ | 
 | static int | 
 | xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle) | 
 | { | 
 |     if ((particle->children == NULL) || | 
 | 	(particle->children->children == NULL)) | 
 | 	return (0); | 
 |     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) { | 
 | 	int max = -1, cur; | 
 | 	xmlSchemaParticlePtr part = | 
 | 	    (xmlSchemaParticlePtr) particle->children->children; | 
 |  | 
 | 	for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) { | 
 | 	    if (part->children == NULL) | 
 | 		continue; | 
 | 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) || | 
 | 		(part->children->type == XML_SCHEMA_TYPE_ANY)) | 
 | 		cur = part->maxOccurs; | 
 | 	    else | 
 | 		cur = xmlSchemaGetParticleTotalRangeMax(part); | 
 | 	    if (cur == UNBOUNDED) | 
 | 		return (UNBOUNDED); | 
 | 	    if ((max < cur) || (max == -1)) | 
 | 		max = cur; | 
 | 	} | 
 | 	/* TODO: Handle overflows? */ | 
 | 	return (particle->maxOccurs * max); | 
 |     } else { | 
 | 	/* <all> and <sequence> */ | 
 | 	int sum = 0, cur; | 
 | 	xmlSchemaParticlePtr part = | 
 | 	    (xmlSchemaParticlePtr) particle->children->children; | 
 |  | 
 | 	for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) { | 
 | 	    if (part->children == NULL) | 
 | 		continue; | 
 | 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) || | 
 | 		(part->children->type == XML_SCHEMA_TYPE_ANY)) | 
 | 		cur = part->maxOccurs; | 
 | 	    else | 
 | 		cur = xmlSchemaGetParticleTotalRangeMax(part); | 
 | 	    if (cur == UNBOUNDED) | 
 | 		return (UNBOUNDED); | 
 | 	    if ((cur > 0) && (particle->maxOccurs == UNBOUNDED)) | 
 | 		return (UNBOUNDED); | 
 | 	    sum += cur; | 
 | 	} | 
 | 	/* TODO: Handle overflows? */ | 
 | 	return (particle->maxOccurs * sum); | 
 |     } | 
 | } | 
 | #endif | 
 |  | 
 | /** | 
 |  * xmlSchemaIsParticleEmptiable: | 
 |  * @particle: the particle | 
 |  * | 
 |  * Schema Component Constraint: Particle Emptiable | 
 |  * Checks whether the given particle is emptiable. | 
 |  * | 
 |  * Returns 1 if emptiable, 0 otherwise. | 
 |  */ | 
 | static int | 
 | xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle) | 
 | { | 
 |     /* | 
 |     * SPEC (1) "Its {min occurs} is 0." | 
 |     */ | 
 |     if ((particle == NULL) || (particle->minOccurs == 0) || | 
 | 	(particle->children == NULL)) | 
 | 	return (1); | 
 |     /* | 
 |     * SPEC (2) "Its {term} is a group and the minimum part of the | 
 |     * effective total range of that group, [...] is 0." | 
 |     */ | 
 |     if (WXS_IS_MODEL_GROUP(particle->children)) { | 
 | 	if (xmlSchemaGetParticleTotalRangeMin(particle) == 0) | 
 | 	    return (1); | 
 |     } | 
 |     return (0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaCheckCOSSTDerivedOK: | 
 |  * @actxt: a context | 
 |  * @type:  the derived simple type definition | 
 |  * @baseType:  the base type definition | 
 |  * @subset: the subset of ('restriction', ect.) | 
 |  * | 
 |  * Schema Component Constraint: | 
 |  * Type Derivation OK (Simple) (cos-st-derived-OK) | 
 |  * | 
 |  * Checks wheter @type can be validly | 
 |  * derived from @baseType. | 
 |  * | 
 |  * Returns 0 on success, an positive error code otherwise. | 
 |  */ | 
 | static int | 
 | xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt, | 
 | 			     xmlSchemaTypePtr type, | 
 | 			     xmlSchemaTypePtr baseType, | 
 | 			     int subset) | 
 | { | 
 |     /* | 
 |     * 1 They are the same type definition. | 
 |     * TODO: The identy check might have to be more complex than this. | 
 |     */ | 
 |     if (type == baseType) | 
 | 	return (0); | 
 |     /* | 
 |     * 2.1 restriction is not in the subset, or in the {final} | 
 |     * of its own {base type definition}; | 
 |     * | 
 |     * NOTE that this will be used also via "xsi:type". | 
 |     * | 
 |     * TODO: Revise this, it looks strange. How can the "type" | 
 |     * not be fixed or *in* fixing? | 
 |     */ | 
 |     if (WXS_IS_TYPE_NOT_FIXED(type)) | 
 | 	if (xmlSchemaTypeFixup(type, actxt) == -1) | 
 | 	    return(-1); | 
 |     if (WXS_IS_TYPE_NOT_FIXED(baseType)) | 
 | 	if (xmlSchemaTypeFixup(baseType, actxt) == -1) | 
 | 	    return(-1); | 
 |     if ((subset & SUBSET_RESTRICTION) || | 
 | 	(xmlSchemaTypeFinalContains(type->baseType, | 
 | 	    XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) { | 
 | 	return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1); | 
 |     } | 
 |     /* 2.2 */ | 
 |     if (type->baseType == baseType) { | 
 | 	/* | 
 | 	* 2.2.1 D's �base type definition� is B. | 
 | 	*/ | 
 | 	return (0); | 
 |     } | 
 |     /* | 
 |     * 2.2.2 D's �base type definition� is not the �ur-type definition� | 
 |     * and is validly derived from B given the subset, as defined by this | 
 |     * constraint. | 
 |     */ | 
 |     if ((! WXS_IS_ANYTYPE(type->baseType)) && | 
 | 	(xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType, | 
 | 	    baseType, subset) == 0)) { | 
 | 	return (0); | 
 |     } | 
 |     /* | 
 |     * 2.2.3 D's {variety} is list or union and B is the �simple ur-type | 
 |     * definition�. | 
 |     */ | 
 |     if (WXS_IS_ANY_SIMPLE_TYPE(baseType) && | 
 | 	(WXS_IS_LIST(type) || WXS_IS_UNION(type))) { | 
 | 	return (0); | 
 |     } | 
 |     /* | 
 |     * 2.2.4 B's {variety} is union and D is validly derived from a type | 
 |     * definition in B's {member type definitions} given the subset, as | 
 |     * defined by this constraint. | 
 |     * | 
 |     * NOTE: This seems not to involve built-in types, since there is no | 
 |     * built-in Union Simple Type. | 
 |     */ | 
 |     if (WXS_IS_UNION(baseType)) { | 
 | 	xmlSchemaTypeLinkPtr cur; | 
 |  | 
 | 	cur = baseType->memberTypes; | 
 | 	while (cur != NULL) { | 
 | 	    if (WXS_IS_TYPE_NOT_FIXED(cur->type)) | 
 | 		if (xmlSchemaTypeFixup(cur->type, actxt) == -1) | 
 | 		    return(-1); | 
 | 	    if (xmlSchemaCheckCOSSTDerivedOK(actxt, | 
 | 		    type, cur->type, subset) == 0) | 
 | 	    { | 
 | 		/* | 
 | 		* It just has to be validly derived from at least one | 
 | 		* member-type. | 
 | 		*/ | 
 | 		return (0); | 
 | 	    } | 
 | 	    cur = cur->next; | 
 | 	} | 
 |     } | 
 |     return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaCheckTypeDefCircularInternal: | 
 |  * @pctxt:  the schema parser context | 
 |  * @ctxtType:  the type definition | 
 |  * @ancestor: an ancestor of @ctxtType | 
 |  * | 
 |  * Checks st-props-correct (2) + ct-props-correct (3). | 
 |  * Circular type definitions are not allowed. | 
 |  * | 
 |  * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is | 
 |  * circular, 0 otherwise. | 
 |  */ | 
 | static int | 
 | xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt, | 
 | 			   xmlSchemaTypePtr ctxtType, | 
 | 			   xmlSchemaTypePtr ancestor) | 
 | { | 
 |     int ret; | 
 |  | 
 |     if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC)) | 
 | 	return (0); | 
 |  | 
 |     if (ctxtType == ancestor) { | 
 | 	xmlSchemaPCustomErr(pctxt, | 
 | 	    XML_SCHEMAP_ST_PROPS_CORRECT_2, | 
 | 	    WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType), | 
 | 	    "The definition is circular", NULL); | 
 | 	return (XML_SCHEMAP_ST_PROPS_CORRECT_2); | 
 |     } | 
 |     if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) { | 
 | 	/* | 
 | 	* Avoid inifinite recursion on circular types not yet checked. | 
 | 	*/ | 
 | 	return (0); | 
 |     } | 
 |     ancestor->flags |= XML_SCHEMAS_TYPE_MARKED; | 
 |     ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType, | 
 | 	ancestor->baseType); | 
 |     ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED; | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaCheckTypeDefCircular: | 
 |  * @item:  the complex/simple type definition | 
 |  * @ctxt:  the parser context | 
 |  * @name:  the name | 
 |  * | 
 |  * Checks for circular type definitions. | 
 |  */ | 
 | static void | 
 | xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item, | 
 | 			      xmlSchemaParserCtxtPtr ctxt) | 
 | { | 
 |     if ((item == NULL) || | 
 | 	(item->type == XML_SCHEMA_TYPE_BASIC) || | 
 | 	(item->baseType == NULL)) | 
 | 	return; | 
 |     xmlSchemaCheckTypeDefCircularInternal(ctxt, item, | 
 | 	item->baseType); | 
 | } | 
 |  | 
 | /* | 
 | * Simple Type Definition Representation OK (src-simple-type) 4 | 
 | * | 
 | * "4 Circular union type definition is disallowed. That is, if the | 
 | * <union> alternative is chosen, there must not be any entries in the | 
 | * memberTypes [attribute] at any depth which resolve to the component | 
 | * corresponding to the <simpleType>." | 
 | * | 
 | * Note that this should work on the *representation* of a component, | 
 | * thus assumes any union types in the member types not being yet | 
 | * substituted. At this stage we need the variety of the types | 
 | * to be already computed. | 
 | */ | 
 | static int | 
 | xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt, | 
 | 					xmlSchemaTypePtr ctxType, | 
 | 					xmlSchemaTypeLinkPtr members) | 
 | { | 
 |     xmlSchemaTypeLinkPtr member; | 
 |     xmlSchemaTypePtr memberType; | 
 |  | 
 |     member = members; | 
 |     while (member != NULL) { | 
 | 	memberType = member->type; | 
 | 	while ((memberType != NULL) && | 
 | 	    (memberType->type != XML_SCHEMA_TYPE_BASIC)) { | 
 | 	    if (memberType == ctxType) { | 
 | 		xmlSchemaPCustomErr(pctxt, | 
 | 		    XML_SCHEMAP_SRC_SIMPLE_TYPE_4, | 
 | 		    WXS_BASIC_CAST ctxType, NULL, | 
 | 		    "The union type definition is circular", NULL); | 
 | 		return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4); | 
 | 	    } | 
 | 	    if ((WXS_IS_UNION(memberType)) && | 
 | 		((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0)) | 
 | 	    { | 
 | 		int res; | 
 | 		memberType->flags |= XML_SCHEMAS_TYPE_MARKED; | 
 | 		res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, | 
 | 		    ctxType, | 
 | 		    xmlSchemaGetUnionSimpleTypeMemberTypes(memberType)); | 
 | 		memberType->flags ^= XML_SCHEMAS_TYPE_MARKED; | 
 | 		if (res != 0) | 
 | 		    return(res); | 
 | 	    } | 
 | 	    memberType = memberType->baseType; | 
 | 	} | 
 | 	member = member->next; | 
 |     } | 
 |     return(0); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt, | 
 | 				   xmlSchemaTypePtr type) | 
 | { | 
 |     if (! WXS_IS_UNION(type)) | 
 | 	return(0); | 
 |     return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type, | 
 | 	type->memberTypes)); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaResolveTypeReferences: | 
 |  * @item:  the complex/simple type definition | 
 |  * @ctxt:  the parser context | 
 |  * @name:  the name | 
 |  * | 
 |  * Resolvese type definition references | 
 |  */ | 
 | static void | 
 | xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef, | 
 | 			 xmlSchemaParserCtxtPtr ctxt) | 
 | { | 
 |     if (typeDef == NULL) | 
 | 	return; | 
 |  | 
 |     /* | 
 |     * Resolve the base type. | 
 |     */ | 
 |     if (typeDef->baseType == NULL) { | 
 | 	typeDef->baseType = xmlSchemaGetType(ctxt->schema, | 
 | 	    typeDef->base, typeDef->baseNs); | 
 | 	if (typeDef->baseType == NULL) { | 
 | 	    xmlSchemaPResCompAttrErr(ctxt, | 
 | 		XML_SCHEMAP_SRC_RESOLVE, | 
 | 		WXS_BASIC_CAST typeDef, typeDef->node, | 
 | 		"base", typeDef->base, typeDef->baseNs, | 
 | 		XML_SCHEMA_TYPE_SIMPLE, NULL); | 
 | 	    return; | 
 | 	} | 
 |     } | 
 |     if (WXS_IS_SIMPLE(typeDef)) { | 
 | 	if (WXS_IS_UNION(typeDef)) { | 
 | 	    /* | 
 | 	    * Resolve the memberTypes. | 
 | 	    */ | 
 | 	    xmlSchemaResolveUnionMemberTypes(ctxt, typeDef); | 
 | 	    return; | 
 | 	} else if (WXS_IS_LIST(typeDef)) { | 
 | 	    /* | 
 | 	    * Resolve the itemType. | 
 | 	    */ | 
 | 	    if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) { | 
 |  | 
 | 		typeDef->subtypes = xmlSchemaGetType(ctxt->schema, | 
 | 		    typeDef->base, typeDef->baseNs); | 
 |  | 
 | 		if ((typeDef->subtypes == NULL) || | 
 | 		    (! WXS_IS_SIMPLE(typeDef->subtypes))) | 
 | 		{ | 
 | 		    typeDef->subtypes = NULL; | 
 | 		    xmlSchemaPResCompAttrErr(ctxt, | 
 | 			XML_SCHEMAP_SRC_RESOLVE, | 
 | 			WXS_BASIC_CAST typeDef, typeDef->node, | 
 | 			"itemType", typeDef->base, typeDef->baseNs, | 
 | 			XML_SCHEMA_TYPE_SIMPLE, NULL); | 
 | 		} | 
 | 	    } | 
 | 	    return; | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * The ball of letters below means, that if we have a particle | 
 |     * which has a QName-helper component as its {term}, we want | 
 |     * to resolve it... | 
 |     */ | 
 |     else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) && | 
 | 	((WXS_TYPE_CONTENTTYPE(typeDef))->type == | 
 | 	    XML_SCHEMA_TYPE_PARTICLE) && | 
 | 	(WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) && | 
 | 	((WXS_TYPE_PARTICLE_TERM(typeDef))->type == | 
 | 	    XML_SCHEMA_EXTRA_QNAMEREF)) | 
 |     { | 
 | 	xmlSchemaQNameRefPtr ref = | 
 | 	    WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef); | 
 | 	xmlSchemaModelGroupDefPtr groupDef; | 
 |  | 
 | 	/* | 
 | 	* URGENT TODO: Test this. | 
 | 	*/ | 
 | 	WXS_TYPE_PARTICLE_TERM(typeDef) = NULL; | 
 | 	/* | 
 | 	* Resolve the MG definition reference. | 
 | 	*/ | 
 | 	groupDef = | 
 | 	    WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema, | 
 | 		ref->itemType, ref->name, ref->targetNamespace); | 
 | 	if (groupDef == NULL) { | 
 | 	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE, | 
 | 		NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), | 
 | 		"ref", ref->name, ref->targetNamespace, ref->itemType, | 
 | 		NULL); | 
 | 	    /* Remove the particle. */ | 
 | 	    WXS_TYPE_CONTENTTYPE(typeDef) = NULL; | 
 | 	} else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL) | 
 | 	    /* Remove the particle. */ | 
 | 	    WXS_TYPE_CONTENTTYPE(typeDef) = NULL; | 
 | 	else { | 
 | 	    /* | 
 | 	    * Assign the MG definition's {model group} to the | 
 | 	    * particle's {term}. | 
 | 	    */ | 
 | 	    WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef); | 
 |  | 
 | 	    if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) { | 
 | 		/* | 
 | 		* SPEC cos-all-limited (1.2) | 
 | 		* "1.2 the {term} property of a particle with | 
 | 		* {max occurs}=1 which is part of a pair which constitutes | 
 | 		* the {content type} of a complex type definition." | 
 | 		*/ | 
 | 		if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) { | 
 | 		    xmlSchemaCustomErr(ACTXT_CAST ctxt, | 
 | 			/* TODO: error code */ | 
 | 			XML_SCHEMAP_COS_ALL_LIMITED, | 
 | 			WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL, | 
 | 			"The particle's {max occurs} must be 1, since the " | 
 | 			"reference resolves to an 'all' model group", | 
 | 			NULL, NULL); | 
 | 		} | 
 | 	    } | 
 | 	} | 
 |     } | 
 | } | 
 |  | 
 |  | 
 |  | 
 | /** | 
 |  * xmlSchemaCheckSTPropsCorrect: | 
 |  * @ctxt:  the schema parser context | 
 |  * @type:  the simple type definition | 
 |  * | 
 |  * Checks st-props-correct. | 
 |  * | 
 |  * Returns 0 if the properties are correct, | 
 |  * if not, a positive error code and -1 on internal | 
 |  * errors. | 
 |  */ | 
 | static int | 
 | xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt, | 
 | 			     xmlSchemaTypePtr type) | 
 | { | 
 |     xmlSchemaTypePtr baseType = type->baseType; | 
 |     xmlChar *str = NULL; | 
 |  | 
 |     /* STATE: error funcs converted. */ | 
 |     /* | 
 |     * Schema Component Constraint: Simple Type Definition Properties Correct | 
 |     * | 
 |     * NOTE: This is somehow redundant, since we actually built a simple type | 
 |     * to have all the needed information; this acts as an self test. | 
 |     */ | 
 |     /* Base type: If the datatype has been �derived� by �restriction� | 
 |     * then the Simple Type Definition component from which it is �derived�, | 
 |     * otherwise the Simple Type Definition for anySimpleType (�4.1.6). | 
 |     */ | 
 |     if (baseType == NULL) { | 
 | 	/* | 
 | 	* TODO: Think about: "modulo the impact of Missing | 
 | 	* Sub-components (�5.3)." | 
 | 	*/ | 
 | 	xmlSchemaPCustomErr(ctxt, | 
 | 	    XML_SCHEMAP_ST_PROPS_CORRECT_1, | 
 | 	    WXS_BASIC_CAST type, NULL, | 
 | 	    "No base type existent", NULL); | 
 | 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1); | 
 |  | 
 |     } | 
 |     if (! WXS_IS_SIMPLE(baseType)) { | 
 | 	xmlSchemaPCustomErr(ctxt, | 
 | 	    XML_SCHEMAP_ST_PROPS_CORRECT_1, | 
 | 	    WXS_BASIC_CAST type, NULL, | 
 | 	    "The base type '%s' is not a simple type", | 
 | 	    xmlSchemaGetComponentQName(&str, baseType)); | 
 | 	FREE_AND_NULL(str) | 
 | 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1); | 
 |     } | 
 |     if ( (WXS_IS_LIST(type) || WXS_IS_UNION(type)) && | 
 | 	 (WXS_IS_RESTRICTION(type) == 0) && | 
 | 	 (! WXS_IS_ANY_SIMPLE_TYPE(baseType))) { | 
 | 	xmlSchemaPCustomErr(ctxt, | 
 | 	    XML_SCHEMAP_ST_PROPS_CORRECT_1, | 
 | 	    WXS_BASIC_CAST type, NULL, | 
 | 	    "A type, derived by list or union, must have " | 
 | 	    "the simple ur-type definition as base type, not '%s'", | 
 | 	    xmlSchemaGetComponentQName(&str, baseType)); | 
 | 	FREE_AND_NULL(str) | 
 | 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1); | 
 |     } | 
 |     /* | 
 |     * Variety: One of {atomic, list, union}. | 
 |     */ | 
 |     if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) && | 
 | 	(! WXS_IS_LIST(type))) { | 
 | 	xmlSchemaPCustomErr(ctxt, | 
 | 	    XML_SCHEMAP_ST_PROPS_CORRECT_1, | 
 | 	    WXS_BASIC_CAST type, NULL, | 
 | 	    "The variety is absent", NULL); | 
 | 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1); | 
 |     } | 
 |     /* TODO: Finish this. Hmm, is this finished? */ | 
 |  | 
 |     /* | 
 |     * 3 The {final} of the {base type definition} must not contain restriction. | 
 |     */ | 
 |     if (xmlSchemaTypeFinalContains(baseType, | 
 | 	XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) { | 
 | 	xmlSchemaPCustomErr(ctxt, | 
 | 	    XML_SCHEMAP_ST_PROPS_CORRECT_3, | 
 | 	    WXS_BASIC_CAST type, NULL, | 
 | 	    "The 'final' of its base type '%s' must not contain " | 
 | 	    "'restriction'", | 
 | 	    xmlSchemaGetComponentQName(&str, baseType)); | 
 | 	FREE_AND_NULL(str) | 
 | 	return (XML_SCHEMAP_ST_PROPS_CORRECT_3); | 
 |     } | 
 |  | 
 |     /* | 
 |     * 2 All simple type definitions must be derived ultimately from the �simple | 
 |     * ur-type definition (so� circular definitions are disallowed). That is, it | 
 |     * must be possible to reach a built-in primitive datatype or the �simple | 
 |     * ur-type definition� by repeatedly following the {base type definition}. | 
 |     * | 
 |     * NOTE: this is done in xmlSchemaCheckTypeDefCircular(). | 
 |     */ | 
 |     return (0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaCheckCOSSTRestricts: | 
 |  * @ctxt:  the schema parser context | 
 |  * @type:  the simple type definition | 
 |  * | 
 |  * Schema Component Constraint: | 
 |  * Derivation Valid (Restriction, Simple) (cos-st-restricts) | 
 |  | 
 |  * Checks if the given @type (simpleType) is derived validly by restriction. | 
 |  * STATUS: | 
 |  * | 
 |  * Returns -1 on internal errors, 0 if the type is validly derived, | 
 |  * a positive error code otherwise. | 
 |  */ | 
 | static int | 
 | xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt, | 
 | 			     xmlSchemaTypePtr type) | 
 | { | 
 |     xmlChar *str = NULL; | 
 |  | 
 |     if (type->type != XML_SCHEMA_TYPE_SIMPLE) { | 
 | 	PERROR_INT("xmlSchemaCheckCOSSTRestricts", | 
 | 	    "given type is not a user-derived simpleType"); | 
 | 	return (-1); | 
 |     } | 
 |  | 
 |     if (WXS_IS_ATOMIC(type)) { | 
 | 	xmlSchemaTypePtr primitive; | 
 | 	/* | 
 | 	* 1.1 The {base type definition} must be an atomic simple | 
 | 	* type definition or a built-in primitive datatype. | 
 | 	*/ | 
 | 	if (! WXS_IS_ATOMIC(type->baseType)) { | 
 | 	    xmlSchemaPCustomErr(pctxt, | 
 | 		XML_SCHEMAP_COS_ST_RESTRICTS_1_1, | 
 | 		WXS_BASIC_CAST type, NULL, | 
 | 		"The base type '%s' is not an atomic simple type", | 
 | 		xmlSchemaGetComponentQName(&str, type->baseType)); | 
 | 	    FREE_AND_NULL(str) | 
 | 	    return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1); | 
 | 	} | 
 | 	/* 1.2 The {final} of the {base type definition} must not contain | 
 | 	* restriction. | 
 | 	*/ | 
 | 	/* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */ | 
 | 	if (xmlSchemaTypeFinalContains(type->baseType, | 
 | 	    XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) { | 
 | 	    xmlSchemaPCustomErr(pctxt, | 
 | 		XML_SCHEMAP_COS_ST_RESTRICTS_1_2, | 
 | 		WXS_BASIC_CAST type, NULL, | 
 | 		"The final of its base type '%s' must not contain 'restriction'", | 
 | 		xmlSchemaGetComponentQName(&str, type->baseType)); | 
 | 	    FREE_AND_NULL(str) | 
 | 	    return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2); | 
 | 	} | 
 |  | 
 | 	/* | 
 | 	* 1.3.1 DF must be an allowed constraining facet for the {primitive | 
 | 	* type definition}, as specified in the appropriate subsection of 3.2 | 
 | 	* Primitive datatypes. | 
 | 	*/ | 
 | 	if (type->facets != NULL) { | 
 | 	    xmlSchemaFacetPtr facet; | 
 | 	    int ok = 1; | 
 |  | 
 | 	    primitive = xmlSchemaGetPrimitiveType(type); | 
 | 	    if (primitive == NULL) { | 
 | 		PERROR_INT("xmlSchemaCheckCOSSTRestricts", | 
 | 		    "failed to get primitive type"); | 
 | 		return (-1); | 
 | 	    } | 
 | 	    facet = type->facets; | 
 | 	    do { | 
 | 		if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) { | 
 | 		    ok = 0; | 
 | 		    xmlSchemaPIllegalFacetAtomicErr(pctxt, | 
 | 			XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1, | 
 | 			type, primitive, facet); | 
 | 		} | 
 | 		facet = facet->next; | 
 | 	    } while (facet != NULL); | 
 | 	    if (ok == 0) | 
 | 		return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1); | 
 | 	} | 
 | 	/* | 
 | 	* SPEC (1.3.2) "If there is a facet of the same kind in the {facets} | 
 | 	* of the {base type definition} (call this BF),then the DF's {value} | 
 | 	* must be a valid restriction of BF's {value} as defined in | 
 | 	* [XML Schemas: Datatypes]." | 
 | 	* | 
 | 	* NOTE (1.3.2) Facet derivation constraints are currently handled in | 
 | 	* xmlSchemaDeriveAndValidateFacets() | 
 | 	*/ | 
 |     } else if (WXS_IS_LIST(type)) { | 
 | 	xmlSchemaTypePtr itemType = NULL; | 
 |  | 
 | 	itemType = type->subtypes; | 
 | 	if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) { | 
 | 	    PERROR_INT("xmlSchemaCheckCOSSTRestricts", | 
 | 		"failed to evaluate the item type"); | 
 | 	    return (-1); | 
 | 	} | 
 | 	if (WXS_IS_TYPE_NOT_FIXED(itemType)) | 
 | 	    xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt); | 
 | 	/* | 
 | 	* 2.1 The {item type definition} must have a {variety} of atomic or | 
 | 	* union (in which case all the {member type definitions} | 
 | 	* must be atomic). | 
 | 	*/ | 
 | 	if ((! WXS_IS_ATOMIC(itemType)) && | 
 | 	    (! WXS_IS_UNION(itemType))) { | 
 | 	    xmlSchemaPCustomErr(pctxt, | 
 | 		XML_SCHEMAP_COS_ST_RESTRICTS_2_1, | 
 | 		WXS_BASIC_CAST type, NULL, | 
 | 		"The item type '%s' does not have a variety of atomic or union", | 
 | 		xmlSchemaGetComponentQName(&str, itemType)); | 
 | 	    FREE_AND_NULL(str) | 
 | 	    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1); | 
 | 	} else if (WXS_IS_UNION(itemType)) { | 
 | 	    xmlSchemaTypeLinkPtr member; | 
 |  | 
 | 	    member = itemType->memberTypes; | 
 | 	    while (member != NULL) { | 
 | 		if (! WXS_IS_ATOMIC(member->type)) { | 
 | 		    xmlSchemaPCustomErr(pctxt, | 
 | 			XML_SCHEMAP_COS_ST_RESTRICTS_2_1, | 
 | 			WXS_BASIC_CAST type, NULL, | 
 | 			"The item type is a union type, but the " | 
 | 			"member type '%s' of this item type is not atomic", | 
 | 			xmlSchemaGetComponentQName(&str, member->type)); | 
 | 		    FREE_AND_NULL(str) | 
 | 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1); | 
 | 		} | 
 | 		member = member->next; | 
 | 	    } | 
 | 	} | 
 |  | 
 | 	if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) { | 
 | 	    xmlSchemaFacetPtr facet; | 
 | 	    /* | 
 | 	    * This is the case if we have: <simpleType><list .. | 
 | 	    */ | 
 | 	    /* | 
 | 	    * 2.3.1 | 
 | 	    * 2.3.1.1 The {final} of the {item type definition} must not | 
 | 	    * contain list. | 
 | 	    */ | 
 | 	    if (xmlSchemaTypeFinalContains(itemType, | 
 | 		XML_SCHEMAS_TYPE_FINAL_LIST)) { | 
 | 		xmlSchemaPCustomErr(pctxt, | 
 | 		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1, | 
 | 		    WXS_BASIC_CAST type, NULL, | 
 | 		    "The final of its item type '%s' must not contain 'list'", | 
 | 		    xmlSchemaGetComponentQName(&str, itemType)); | 
 | 		FREE_AND_NULL(str) | 
 | 		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1); | 
 | 	    } | 
 | 	    /* | 
 | 	    * 2.3.1.2 The {facets} must only contain the whiteSpace | 
 | 	    * facet component. | 
 | 	    * OPTIMIZE TODO: the S4S already disallows any facet | 
 | 	    * to be specified. | 
 | 	    */ | 
 | 	    if (type->facets != NULL) { | 
 | 		facet = type->facets; | 
 | 		do { | 
 | 		    if (facet->type != XML_SCHEMA_FACET_WHITESPACE) { | 
 | 			xmlSchemaPIllegalFacetListUnionErr(pctxt, | 
 | 			    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2, | 
 | 			    type, facet); | 
 | 			return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2); | 
 | 		    } | 
 | 		    facet = facet->next; | 
 | 		} while (facet != NULL); | 
 | 	    } | 
 | 	    /* | 
 | 	    * MAYBE TODO: (Hmm, not really) Datatypes states: | 
 | 	    * A �list� datatype can be �derived� from an �atomic� datatype | 
 | 	    * whose �lexical space� allows space (such as string or anyURI)or | 
 | 	    * a �union� datatype any of whose {member type definitions}'s | 
 | 	    * �lexical space� allows space. | 
 | 	    */ | 
 | 	} else { | 
 | 	    /* | 
 | 	    * This is the case if we have: <simpleType><restriction ... | 
 | 	    * I.e. the variety of "list" is inherited. | 
 | 	    */ | 
 | 	    /* | 
 | 	    * 2.3.2 | 
 | 	    * 2.3.2.1 The {base type definition} must have a {variety} of list. | 
 | 	    */ | 
 | 	    if (! WXS_IS_LIST(type->baseType)) { | 
 | 		xmlSchemaPCustomErr(pctxt, | 
 | 		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1, | 
 | 		    WXS_BASIC_CAST type, NULL, | 
 | 		    "The base type '%s' must be a list type", | 
 | 		    xmlSchemaGetComponentQName(&str, type->baseType)); | 
 | 		FREE_AND_NULL(str) | 
 | 		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1); | 
 | 	    } | 
 | 	    /* | 
 | 	    * 2.3.2.2 The {final} of the {base type definition} must not | 
 | 	    * contain restriction. | 
 | 	    */ | 
 | 	    if (xmlSchemaTypeFinalContains(type->baseType, | 
 | 		XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) { | 
 | 		xmlSchemaPCustomErr(pctxt, | 
 | 		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2, | 
 | 		    WXS_BASIC_CAST type, NULL, | 
 | 		    "The 'final' of the base type '%s' must not contain 'restriction'", | 
 | 		    xmlSchemaGetComponentQName(&str, type->baseType)); | 
 | 		FREE_AND_NULL(str) | 
 | 		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2); | 
 | 	    } | 
 | 	    /* | 
 | 	    * 2.3.2.3 The {item type definition} must be validly derived | 
 | 	    * from the {base type definition}'s {item type definition} given | 
 | 	    * the empty set, as defined in Type Derivation OK (Simple) (�3.14.6). | 
 | 	    */ | 
 | 	    { | 
 | 		xmlSchemaTypePtr baseItemType; | 
 |  | 
 | 		baseItemType = type->baseType->subtypes; | 
 | 		if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) { | 
 | 		    PERROR_INT("xmlSchemaCheckCOSSTRestricts", | 
 | 			"failed to eval the item type of a base type"); | 
 | 		    return (-1); | 
 | 		} | 
 | 		if ((itemType != baseItemType) && | 
 | 		    (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType, | 
 | 			baseItemType, 0) != 0)) { | 
 | 		    xmlChar *strBIT = NULL, *strBT = NULL; | 
 | 		    xmlSchemaPCustomErrExt(pctxt, | 
 | 			XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3, | 
 | 			WXS_BASIC_CAST type, NULL, | 
 | 			"The item type '%s' is not validly derived from " | 
 | 			"the item type '%s' of the base type '%s'", | 
 | 			xmlSchemaGetComponentQName(&str, itemType), | 
 | 			xmlSchemaGetComponentQName(&strBIT, baseItemType), | 
 | 			xmlSchemaGetComponentQName(&strBT, type->baseType)); | 
 |  | 
 | 		    FREE_AND_NULL(str) | 
 | 		    FREE_AND_NULL(strBIT) | 
 | 		    FREE_AND_NULL(strBT) | 
 | 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3); | 
 | 		} | 
 | 	    } | 
 |  | 
 | 	    if (type->facets != NULL) { | 
 | 		xmlSchemaFacetPtr facet; | 
 | 		int ok = 1; | 
 | 		/* | 
 | 		* 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern | 
 | 		* and enumeration facet components are allowed among the {facets}. | 
 | 		*/ | 
 | 		facet = type->facets; | 
 | 		do { | 
 | 		    switch (facet->type) { | 
 | 			case XML_SCHEMA_FACET_LENGTH: | 
 | 			case XML_SCHEMA_FACET_MINLENGTH: | 
 | 			case XML_SCHEMA_FACET_MAXLENGTH: | 
 | 			case XML_SCHEMA_FACET_WHITESPACE: | 
 | 			    /* | 
 | 			    * TODO: 2.5.1.2 List datatypes | 
 | 			    * The value of �whiteSpace� is fixed to the value collapse. | 
 | 			    */ | 
 | 			case XML_SCHEMA_FACET_PATTERN: | 
 | 			case XML_SCHEMA_FACET_ENUMERATION: | 
 | 			    break; | 
 | 			default: { | 
 | 			    xmlSchemaPIllegalFacetListUnionErr(pctxt, | 
 | 				XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4, | 
 | 				type, facet); | 
 | 			    /* | 
 | 			    * We could return, but it's nicer to report all | 
 | 			    * invalid facets. | 
 | 			    */ | 
 | 			    ok = 0; | 
 | 			} | 
 | 		    } | 
 | 		    facet = facet->next; | 
 | 		} while (facet != NULL); | 
 | 		if (ok == 0) | 
 | 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4); | 
 | 		/* | 
 | 		* SPEC (2.3.2.5) (same as 1.3.2) | 
 | 		* | 
 | 		* NOTE (2.3.2.5) This is currently done in | 
 | 		* xmlSchemaDeriveAndValidateFacets() | 
 | 		*/ | 
 | 	    } | 
 | 	} | 
 |     } else if (WXS_IS_UNION(type)) { | 
 | 	/* | 
 | 	* 3.1 The {member type definitions} must all have {variety} of | 
 | 	* atomic or list. | 
 | 	*/ | 
 | 	xmlSchemaTypeLinkPtr member; | 
 |  | 
 | 	member = type->memberTypes; | 
 | 	while (member != NULL) { | 
 | 	    if (WXS_IS_TYPE_NOT_FIXED(member->type)) | 
 | 		xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt); | 
 |  | 
 | 	    if ((! WXS_IS_ATOMIC(member->type)) && | 
 | 		(! WXS_IS_LIST(member->type))) { | 
 | 		xmlSchemaPCustomErr(pctxt, | 
 | 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_1, | 
 | 		    WXS_BASIC_CAST type, NULL, | 
 | 		    "The member type '%s' is neither an atomic, nor a list type", | 
 | 		    xmlSchemaGetComponentQName(&str, member->type)); | 
 | 		FREE_AND_NULL(str) | 
 | 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1); | 
 | 	    } | 
 | 	    member = member->next; | 
 | 	} | 
 | 	/* | 
 | 	* 3.3.1 If the {base type definition} is the �simple ur-type | 
 | 	* definition� | 
 | 	*/ | 
 | 	if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) { | 
 | 	    /* | 
 | 	    * 3.3.1.1 All of the {member type definitions} must have a | 
 | 	    * {final} which does not contain union. | 
 | 	    */ | 
 | 	    member = type->memberTypes; | 
 | 	    while (member != NULL) { | 
 | 		if (xmlSchemaTypeFinalContains(member->type, | 
 | 		    XML_SCHEMAS_TYPE_FINAL_UNION)) { | 
 | 		    xmlSchemaPCustomErr(pctxt, | 
 | 			XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1, | 
 | 			WXS_BASIC_CAST type, NULL, | 
 | 			"The 'final' of member type '%s' contains 'union'", | 
 | 			xmlSchemaGetComponentQName(&str, member->type)); | 
 | 		    FREE_AND_NULL(str) | 
 | 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1); | 
 | 		} | 
 | 		member = member->next; | 
 | 	    } | 
 | 	    /* | 
 | 	    * 3.3.1.2 The {facets} must be empty. | 
 | 	    */ | 
 | 	    if (type->facetSet != NULL) { | 
 | 		xmlSchemaPCustomErr(pctxt, | 
 | 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2, | 
 | 		    WXS_BASIC_CAST type, NULL, | 
 | 		    "No facets allowed", NULL); | 
 | 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2); | 
 | 	    } | 
 | 	} else { | 
 | 	    /* | 
 | 	    * 3.3.2.1 The {base type definition} must have a {variety} of union. | 
 | 	    * I.e. the variety of "list" is inherited. | 
 | 	    */ | 
 | 	    if (! WXS_IS_UNION(type->baseType)) { | 
 | 		xmlSchemaPCustomErr(pctxt, | 
 | 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1, | 
 | 		    WXS_BASIC_CAST type, NULL, | 
 | 		    "The base type '%s' is not a union type", | 
 | 		    xmlSchemaGetComponentQName(&str, type->baseType)); | 
 | 		FREE_AND_NULL(str) | 
 | 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1); | 
 | 	    } | 
 | 	    /* | 
 | 	    * 3.3.2.2 The {final} of the {base type definition} must not contain restriction. | 
 | 	    */ | 
 | 	    if (xmlSchemaTypeFinalContains(type->baseType, | 
 | 		XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) { | 
 | 		xmlSchemaPCustomErr(pctxt, | 
 | 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2, | 
 | 		    WXS_BASIC_CAST type, NULL, | 
 | 		    "The 'final' of its base type '%s' must not contain 'restriction'", | 
 | 		    xmlSchemaGetComponentQName(&str, type->baseType)); | 
 | 		FREE_AND_NULL(str) | 
 | 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2); | 
 | 	    } | 
 | 	    /* | 
 | 	    * 3.3.2.3 The {member type definitions}, in order, must be validly | 
 | 	    * derived from the corresponding type definitions in the {base | 
 | 	    * type definition}'s {member type definitions} given the empty set, | 
 | 	    * as defined in Type Derivation OK (Simple) (�3.14.6). | 
 | 	    */ | 
 | 	    { | 
 | 		xmlSchemaTypeLinkPtr baseMember; | 
 |  | 
 | 		/* | 
 | 		* OPTIMIZE: if the type is restricting, it has no local defined | 
 | 		* member types and inherits the member types of the base type; | 
 | 		* thus a check for equality can be skipped. | 
 | 		*/ | 
 | 		/* | 
 | 		* Even worse: I cannot see a scenario where a restricting | 
 | 		* union simple type can have other member types as the member | 
 | 		* types of it's base type. This check seems not necessary with | 
 | 		* respect to the derivation process in libxml2. | 
 | 		* But necessary if constructing types with an API. | 
 | 		*/ | 
 | 		if (type->memberTypes != NULL) { | 
 | 		    member = type->memberTypes; | 
 | 		    baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType); | 
 | 		    if ((member == NULL) && (baseMember != NULL)) { | 
 | 			PERROR_INT("xmlSchemaCheckCOSSTRestricts", | 
 | 			    "different number of member types in base"); | 
 | 		    } | 
 | 		    while (member != NULL) { | 
 | 			if (baseMember == NULL) { | 
 | 			    PERROR_INT("xmlSchemaCheckCOSSTRestricts", | 
 | 			    "different number of member types in base"); | 
 | 			} else if ((member->type != baseMember->type) && | 
 | 			    (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, | 
 | 				member->type, baseMember->type, 0) != 0)) { | 
 | 			    xmlChar *strBMT = NULL, *strBT = NULL; | 
 |  | 
 | 			    xmlSchemaPCustomErrExt(pctxt, | 
 | 				XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3, | 
 | 				WXS_BASIC_CAST type, NULL, | 
 | 				"The member type %s is not validly " | 
 | 				"derived from its corresponding member " | 
 | 				"type %s of the base type %s", | 
 | 				xmlSchemaGetComponentQName(&str, member->type), | 
 | 				xmlSchemaGetComponentQName(&strBMT, baseMember->type), | 
 | 				xmlSchemaGetComponentQName(&strBT, type->baseType)); | 
 | 			    FREE_AND_NULL(str) | 
 | 			    FREE_AND_NULL(strBMT) | 
 | 			    FREE_AND_NULL(strBT) | 
 | 			    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3); | 
 | 			} | 
 | 			member = member->next; | 
 |                         if (baseMember != NULL) | 
 |                             baseMember = baseMember->next; | 
 | 		    } | 
 | 		} | 
 | 	    } | 
 | 	    /* | 
 | 	    * 3.3.2.4 Only pattern and enumeration facet components are | 
 | 	    * allowed among the {facets}. | 
 | 	    */ | 
 | 	    if (type->facets != NULL) { | 
 | 		xmlSchemaFacetPtr facet; | 
 | 		int ok = 1; | 
 |  | 
 | 		facet = type->facets; | 
 | 		do { | 
 | 		    if ((facet->type != XML_SCHEMA_FACET_PATTERN) && | 
 | 			(facet->type != XML_SCHEMA_FACET_ENUMERATION)) { | 
 | 			xmlSchemaPIllegalFacetListUnionErr(pctxt, | 
 | 				XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4, | 
 | 				type, facet); | 
 | 			ok = 0; | 
 | 		    } | 
 | 		    facet = facet->next; | 
 | 		} while (facet != NULL); | 
 | 		if (ok == 0) | 
 | 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4); | 
 |  | 
 | 	    } | 
 | 	    /* | 
 | 	    * SPEC (3.3.2.5) (same as 1.3.2) | 
 | 	    * | 
 | 	    * NOTE (3.3.2.5) This is currently done in | 
 | 	    * xmlSchemaDeriveAndValidateFacets() | 
 | 	    */ | 
 | 	} | 
 |     } | 
 |  | 
 |     return (0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaCheckSRCSimpleType: | 
 |  * @ctxt:  the schema parser context | 
 |  * @type:  the simple type definition | 
 |  * | 
 |  * Checks crc-simple-type constraints. | 
 |  * | 
 |  * Returns 0 if the constraints are satisfied, | 
 |  * if not a positive error code and -1 on internal | 
 |  * errors. | 
 |  */ | 
 | #if 0 | 
 | static int | 
 | xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt, | 
 | 			    xmlSchemaTypePtr type) | 
 | { | 
 |     /* | 
 |     * src-simple-type.1 The corresponding simple type definition, if any, | 
 |     * must satisfy the conditions set out in Constraints on Simple Type | 
 |     * Definition Schema Components (�3.14.6). | 
 |     */ | 
 |     if (WXS_IS_RESTRICTION(type)) { | 
 | 	/* | 
 | 	* src-simple-type.2 "If the <restriction> alternative is chosen, | 
 | 	* either it must have a base [attribute] or a <simpleType> among its | 
 | 	* [children], but not both." | 
 | 	* NOTE: This is checked in the parse function of <restriction>. | 
 | 	*/ | 
 | 	/* | 
 | 	* | 
 | 	*/ | 
 |     } else if (WXS_IS_LIST(type)) { | 
 | 	/* src-simple-type.3 "If the <list> alternative is chosen, either it must have | 
 | 	* an itemType [attribute] or a <simpleType> among its [children], | 
 | 	* but not both." | 
 | 	* | 
 | 	* NOTE: This is checked in the parse function of <list>. | 
 | 	*/ | 
 |     } else if (WXS_IS_UNION(type)) { | 
 | 	/* | 
 | 	* src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular(). | 
 | 	*/ | 
 |     } | 
 |     return (0); | 
 | } | 
 | #endif | 
 |  | 
 | static int | 
 | xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt) | 
 | { | 
 |    if (ctxt->vctxt == NULL) { | 
 | 	ctxt->vctxt = xmlSchemaNewValidCtxt(NULL); | 
 | 	if (ctxt->vctxt == NULL) { | 
 | 	    xmlSchemaPErr(ctxt, NULL, | 
 | 		XML_SCHEMAP_INTERNAL, | 
 | 		"Internal error: xmlSchemaCreateVCtxtOnPCtxt, " | 
 | 		"failed to create a temp. validation context.\n", | 
 | 		NULL, NULL); | 
 | 	    return (-1); | 
 | 	} | 
 | 	/* TODO: Pass user data. */ | 
 | 	xmlSchemaSetValidErrors(ctxt->vctxt, | 
 | 	    ctxt->error, ctxt->warning, ctxt->errCtxt); | 
 | 	xmlSchemaSetValidStructuredErrors(ctxt->vctxt, | 
 | 	    ctxt->serror, ctxt->errCtxt); | 
 |     } | 
 |     return (0); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt, | 
 | 			     xmlNodePtr node, | 
 | 			     xmlSchemaTypePtr type, | 
 | 			     const xmlChar *value, | 
 | 			     xmlSchemaValPtr *retVal, | 
 | 			     int fireErrors, | 
 | 			     int normalize, | 
 | 			     int isNormalized); | 
 |  | 
 | /** | 
 |  * xmlSchemaParseCheckCOSValidDefault: | 
 |  * @pctxt:  the schema parser context | 
 |  * @type:  the simple type definition | 
 |  * @value: the default value | 
 |  * @node: an optional node (the holder of the value) | 
 |  * | 
 |  * Schema Component Constraint: Element Default Valid (Immediate) | 
 |  * (cos-valid-default) | 
 |  * This will be used by the parser only. For the validator there's | 
 |  * an other version. | 
 |  * | 
 |  * Returns 0 if the constraints are satisfied, | 
 |  * if not, a positive error code and -1 on internal | 
 |  * errors. | 
 |  */ | 
 | static int | 
 | xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt, | 
 | 				   xmlNodePtr node, | 
 | 				   xmlSchemaTypePtr type, | 
 | 				   const xmlChar *value, | 
 | 				   xmlSchemaValPtr *val) | 
 | { | 
 |     int ret = 0; | 
 |  | 
 |     /* | 
 |     * cos-valid-default: | 
 |     * Schema Component Constraint: Element Default Valid (Immediate) | 
 |     * For a string to be a valid default with respect to a type | 
 |     * definition the appropriate case among the following must be true: | 
 |     */ | 
 |     if WXS_IS_COMPLEX(type) { | 
 | 	/* | 
 | 	* Complex type. | 
 | 	* | 
 | 	* SPEC (2.1) "its {content type} must be a simple type definition | 
 | 	* or mixed." | 
 | 	* SPEC (2.2.2) "If the {content type} is mixed, then the {content | 
 | 	* type}'s particle must be �emptiable� as defined by | 
 | 	* Particle Emptiable (�3.9.6)." | 
 | 	*/ | 
 | 	if ((! WXS_HAS_SIMPLE_CONTENT(type)) && | 
 | 	    ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) { | 
 | 	    /* NOTE that this covers (2.2.2) as well. */ | 
 | 	    xmlSchemaPCustomErr(pctxt, | 
 | 		XML_SCHEMAP_COS_VALID_DEFAULT_2_1, | 
 | 		WXS_BASIC_CAST type, type->node, | 
 | 		"For a string to be a valid default, the type definition " | 
 | 		"must be a simple type or a complex type with mixed content " | 
 | 		"and a particle emptiable", NULL); | 
 | 	    return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1); | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * 1 If the type definition is a simple type definition, then the string | 
 |     * must be �valid� with respect to that definition as defined by String | 
 |     * Valid (�3.14.4). | 
 |     * | 
 |     * AND | 
 |     * | 
 |     * 2.2.1 If the {content type} is a simple type definition, then the | 
 |     * string must be �valid� with respect to that simple type definition | 
 |     * as defined by String Valid (�3.14.4). | 
 |     */ | 
 |     if (WXS_IS_SIMPLE(type)) | 
 | 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node, | 
 | 	    type, value, val, 1, 1, 0); | 
 |     else if (WXS_HAS_SIMPLE_CONTENT(type)) | 
 | 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node, | 
 | 	    type->contentTypeDef, value, val, 1, 1, 0); | 
 |     else | 
 | 	return (ret); | 
 |  | 
 |     if (ret < 0) { | 
 | 	PERROR_INT("xmlSchemaParseCheckCOSValidDefault", | 
 | 	    "calling xmlSchemaVCheckCVCSimpleType()"); | 
 |     } | 
 |  | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaCheckCTPropsCorrect: | 
 |  * @ctxt:  the schema parser context | 
 |  * @type:  the complex type definition | 
 |  * | 
 |  *.(4.6) Constraints on Complex Type Definition Schema Components | 
 |  * Schema Component Constraint: | 
 |  * Complex Type Definition Properties Correct (ct-props-correct) | 
 |  * STATUS: (seems) complete | 
 |  * | 
 |  * Returns 0 if the constraints are satisfied, a positive | 
 |  * error code if not and -1 if an internal error occured. | 
 |  */ | 
 | static int | 
 | xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt, | 
 | 			     xmlSchemaTypePtr type) | 
 | { | 
 |     /* | 
 |     * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily. | 
 |     * | 
 |     * SPEC (1) "The values of the properties of a complex type definition must | 
 |     * be as described in the property tableau in The Complex Type Definition | 
 |     * Schema Component (�3.4.1), modulo the impact of Missing | 
 |     * Sub-components (�5.3)." | 
 |     */ | 
 |     if ((type->baseType != NULL) && | 
 | 	(WXS_IS_SIMPLE(type->baseType)) && | 
 | 	(WXS_IS_EXTENSION(type) == 0)) { | 
 | 	/* | 
 | 	* SPEC (2) "If the {base type definition} is a simple type definition, | 
 | 	* the {derivation method} must be extension." | 
 | 	*/ | 
 | 	xmlSchemaCustomErr(ACTXT_CAST pctxt, | 
 | 	    XML_SCHEMAP_SRC_CT_1, | 
 | 	    NULL, WXS_BASIC_CAST type, | 
 | 	    "If the base type is a simple type, the derivation method must be " | 
 | 	    "'extension'", NULL, NULL); | 
 | 	return (XML_SCHEMAP_SRC_CT_1); | 
 |     } | 
 |     /* | 
 |     * SPEC (3) "Circular definitions are disallowed, except for the �ur-type | 
 |     * definition�. That is, it must be possible to reach the �ur-type | 
 |     * definition by repeatedly following the {base type definition}." | 
 |     * | 
 |     * NOTE (3) is done in xmlSchemaCheckTypeDefCircular(). | 
 |     */ | 
 |     /* | 
 |     * NOTE that (4) and (5) need the following: | 
 |     *   - attribute uses need to be already inherited (apply attr. prohibitions) | 
 |     *   - attribute group references need to be expanded already | 
 |     *   - simple types need to be typefixed already | 
 |     */ | 
 |     if (type->attrUses && | 
 | 	(((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1)) | 
 |     { | 
 | 	xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses; | 
 | 	xmlSchemaAttributeUsePtr use, tmp; | 
 | 	int i, j, hasId = 0; | 
 |  | 
 | 	for (i = uses->nbItems -1; i >= 0; i--) { | 
 | 	    use = uses->items[i]; | 
 |  | 
 | 	    /* | 
 | 	    * SPEC ct-props-correct | 
 | 	    * (4) "Two distinct attribute declarations in the | 
 | 	    * {attribute uses} must not have identical {name}s and | 
 | 	    * {target namespace}s." | 
 | 	    */ | 
 | 	    if (i > 0) { | 
 | 		for (j = i -1; j >= 0; j--) { | 
 | 		    tmp = uses->items[j]; | 
 | 		    if ((WXS_ATTRUSE_DECL_NAME(use) == | 
 | 			WXS_ATTRUSE_DECL_NAME(tmp)) && | 
 | 			(WXS_ATTRUSE_DECL_TNS(use) == | 
 | 			WXS_ATTRUSE_DECL_TNS(tmp))) | 
 | 		    { | 
 | 			xmlChar *str = NULL; | 
 |  | 
 | 			xmlSchemaCustomErr(ACTXT_CAST pctxt, | 
 | 			    XML_SCHEMAP_AG_PROPS_CORRECT, | 
 | 			    NULL, WXS_BASIC_CAST type, | 
 | 			    "Duplicate %s", | 
 | 			    xmlSchemaGetComponentDesignation(&str, use), | 
 | 			    NULL); | 
 | 			FREE_AND_NULL(str); | 
 | 			/* | 
 | 			* Remove the duplicate. | 
 | 			*/ | 
 | 			if (xmlSchemaItemListRemove(uses, i) == -1) | 
 | 			    goto exit_failure; | 
 | 			goto next_use; | 
 | 		    } | 
 | 		} | 
 | 	    } | 
 | 	    /* | 
 | 	    * SPEC ct-props-correct | 
 | 	    * (5) "Two distinct attribute declarations in the | 
 | 	    * {attribute uses} must not have {type definition}s which | 
 | 	    * are or are derived from ID." | 
 | 	    */ | 
 | 	    if (WXS_ATTRUSE_TYPEDEF(use) != NULL) { | 
 | 		if (xmlSchemaIsDerivedFromBuiltInType( | 
 | 		    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID)) | 
 | 		{ | 
 | 		    if (hasId) { | 
 | 			xmlChar *str = NULL; | 
 |  | 
 | 			xmlSchemaCustomErr(ACTXT_CAST pctxt, | 
 | 			    XML_SCHEMAP_AG_PROPS_CORRECT, | 
 | 			    NULL, WXS_BASIC_CAST type, | 
 | 			    "There must not exist more than one attribute " | 
 | 			    "declaration of type 'xs:ID' " | 
 | 			    "(or derived from 'xs:ID'). The %s violates this " | 
 | 			    "constraint", | 
 | 			    xmlSchemaGetComponentDesignation(&str, use), | 
 | 			    NULL); | 
 | 			FREE_AND_NULL(str); | 
 | 			if (xmlSchemaItemListRemove(uses, i) == -1) | 
 | 			    goto exit_failure; | 
 | 		    } | 
 |  | 
 | 		    hasId = 1; | 
 | 		} | 
 | 	    } | 
 | next_use: {} | 
 | 	} | 
 |     } | 
 |     return (0); | 
 | exit_failure: | 
 |     return(-1); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA, | 
 | 		       xmlSchemaTypePtr typeB) | 
 | { | 
 |     /* | 
 |     * TODO: This should implement component-identity | 
 |     * in the future. | 
 |     */ | 
 |     if ((typeA == NULL) || (typeB == NULL)) | 
 | 	return (0); | 
 |     return (typeA == typeB); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaCheckCOSCTDerivedOK: | 
 |  * @ctxt:  the schema parser context | 
 |  * @type:  the to-be derived complex type definition | 
 |  * @baseType:  the base complex type definition | 
 |  * @set: the given set | 
 |  * | 
 |  * Schema Component Constraint: | 
 |  * Type Derivation OK (Complex) (cos-ct-derived-ok) | 
 |  * | 
 |  * STATUS: completed | 
 |  * | 
 |  * Returns 0 if the constraints are satisfied, or 1 | 
 |  * if not. | 
 |  */ | 
 | static int | 
 | xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt, | 
 | 			     xmlSchemaTypePtr type, | 
 | 			     xmlSchemaTypePtr baseType, | 
 | 			     int set) | 
 | { | 
 |     int equal = xmlSchemaAreEqualTypes(type, baseType); | 
 |     /* TODO: Error codes. */ | 
 |     /* | 
 |     * SPEC "For a complex type definition (call it D, for derived) | 
 |     * to be validly derived from a type definition (call this | 
 |     * B, for base) given a subset of {extension, restriction} | 
 |     * all of the following must be true:" | 
 |     */ | 
 |     if (! equal) { | 
 | 	/* | 
 | 	* SPEC (1) "If B and D are not the same type definition, then the | 
 | 	* {derivation method} of D must not be in the subset." | 
 | 	*/ | 
 | 	if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) || | 
 | 	    ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type)))) | 
 | 	    return (1); | 
 |     } else { | 
 | 	/* | 
 | 	* SPEC (2.1) "B and D must be the same type definition." | 
 | 	*/ | 
 | 	return (0); | 
 |     } | 
 |     /* | 
 |     * SPEC (2.2) "B must be D's {base type definition}." | 
 |     */ | 
 |     if (type->baseType == baseType) | 
 | 	return (0); | 
 |     /* | 
 |     * SPEC (2.3.1) "D's {base type definition} must not be the �ur-type | 
 |     * definition�." | 
 |     */ | 
 |     if (WXS_IS_ANYTYPE(type->baseType)) | 
 | 	return (1); | 
 |  | 
 |     if (WXS_IS_COMPLEX(type->baseType)) { | 
 | 	/* | 
 | 	* SPEC (2.3.2.1) "If D's {base type definition} is complex, then it | 
 | 	* must be validly derived from B given the subset as defined by this | 
 | 	* constraint." | 
 | 	*/ | 
 | 	return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType, | 
 | 	    baseType, set)); | 
 |     } else { | 
 | 	/* | 
 | 	* SPEC (2.3.2.2) "If D's {base type definition} is simple, then it | 
 | 	* must be validly derived from B given the subset as defined in Type | 
 | 	* Derivation OK (Simple) (�3.14.6). | 
 | 	*/ | 
 | 	return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType, | 
 | 	    baseType, set)); | 
 |     } | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaCheckCOSDerivedOK: | 
 |  * @type:  the derived simple type definition | 
 |  * @baseType:  the base type definition | 
 |  * | 
 |  * Calls: | 
 |  * Type Derivation OK (Simple) AND Type Derivation OK (Complex) | 
 |  * | 
 |  * Checks wheter @type can be validly derived from @baseType. | 
 |  * | 
 |  * Returns 0 on success, an positive error code otherwise. | 
 |  */ | 
 | static int | 
 | xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt, | 
 | 			   xmlSchemaTypePtr type, | 
 | 			   xmlSchemaTypePtr baseType, | 
 | 			   int set) | 
 | { | 
 |     if (WXS_IS_SIMPLE(type)) | 
 | 	return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set)); | 
 |     else | 
 | 	return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set)); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaCheckCOSCTExtends: | 
 |  * @ctxt:  the schema parser context | 
 |  * @type:  the complex type definition | 
 |  * | 
 |  * (3.4.6) Constraints on Complex Type Definition Schema Components | 
 |  * Schema Component Constraint: | 
 |  * Derivation Valid (Extension) (cos-ct-extends) | 
 |  * | 
 |  * STATUS: | 
 |  *   missing: | 
 |  *     (1.5) | 
 |  *     (1.4.3.2.2.2) "Particle Valid (Extension)" | 
 |  * | 
 |  * Returns 0 if the constraints are satisfied, a positive | 
 |  * error code if not and -1 if an internal error occured. | 
 |  */ | 
 | static int | 
 | xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt, | 
 | 			   xmlSchemaTypePtr type) | 
 | { | 
 |     xmlSchemaTypePtr base = type->baseType; | 
 |     /* | 
 |     * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used | 
 |     * temporarily only. | 
 |     */ | 
 |     /* | 
 |     * SPEC (1) "If the {base type definition} is a complex type definition, | 
 |     * then all of the following must be true:" | 
 |     */ | 
 |     if (WXS_IS_COMPLEX(base)) { | 
 | 	/* | 
 | 	* SPEC (1.1) "The {final} of the {base type definition} must not | 
 | 	* contain extension." | 
 | 	*/ | 
 | 	if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) { | 
 | 	    xmlSchemaPCustomErr(ctxt, | 
 | 		XML_SCHEMAP_COS_CT_EXTENDS_1_1, | 
 | 		WXS_BASIC_CAST type, NULL, | 
 | 		"The 'final' of the base type definition " | 
 | 		"contains 'extension'", NULL); | 
 | 	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1); | 
 | 	} | 
 |  | 
 | 	/* | 
 | 	* ATTENTION: The constrains (1.2) and (1.3) are not applied, | 
 | 	* since they are automatically satisfied through the | 
 | 	* inheriting mechanism. | 
 | 	* Note that even if redefining components, the inheriting mechanism | 
 | 	* is used. | 
 | 	*/ | 
 | #if 0 | 
 | 	/* | 
 | 	* SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute | 
 | 	* uses} | 
 | 	* of the complex type definition itself, that is, for every attribute | 
 | 	* use in the {attribute uses} of the {base type definition}, there | 
 | 	* must be an attribute use in the {attribute uses} of the complex | 
 | 	* type definition itself whose {attribute declaration} has the same | 
 | 	* {name}, {target namespace} and {type definition} as its attribute | 
 | 	* declaration" | 
 | 	*/ | 
 | 	if (base->attrUses != NULL) { | 
 | 	    int i, j, found; | 
 | 	    xmlSchemaAttributeUsePtr use, buse; | 
 |  | 
 | 	    for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) { | 
 | 		buse = (WXS_LIST_CAST base->attrUses)->items[i]; | 
 | 		found = 0; | 
 | 		if (type->attrUses != NULL) { | 
 | 		    use = (WXS_LIST_CAST type->attrUses)->items[j]; | 
 | 		    for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++) | 
 | 		    { | 
 | 			if ((WXS_ATTRUSE_DECL_NAME(use) == | 
 | 				WXS_ATTRUSE_DECL_NAME(buse)) && | 
 | 			    (WXS_ATTRUSE_DECL_TNS(use) == | 
 | 				WXS_ATTRUSE_DECL_TNS(buse)) && | 
 | 			    (WXS_ATTRUSE_TYPEDEF(use) == | 
 | 				WXS_ATTRUSE_TYPEDEF(buse)) | 
 | 			{ | 
 | 			    found = 1; | 
 | 			    break; | 
 | 			} | 
 | 		    } | 
 | 		} | 
 | 		if (! found) { | 
 | 		    xmlChar *str = NULL; | 
 |  | 
 | 		    xmlSchemaCustomErr(ACTXT_CAST ctxt, | 
 | 			XML_SCHEMAP_COS_CT_EXTENDS_1_2, | 
 | 			NULL, WXS_BASIC_CAST type, | 
 | 			/* | 
 | 			* TODO: The report does not indicate that also the | 
 | 			* type needs to be the same. | 
 | 			*/ | 
 | 			"This type is missing a matching correspondent " | 
 | 			"for its {base type}'s %s in its {attribute uses}", | 
 | 			xmlSchemaGetComponentDesignation(&str, | 
 | 			    buse->children), | 
 | 			NULL); | 
 | 		    FREE_AND_NULL(str) | 
 | 		} | 
 | 	    } | 
 | 	} | 
 | 	/* | 
 | 	* SPEC (1.3) "If it has an {attribute wildcard}, the complex type | 
 | 	* definition must also have one, and the base type definition's | 
 | 	* {attribute  wildcard}'s {namespace constraint} must be a subset | 
 | 	* of the complex  type definition's {attribute wildcard}'s {namespace | 
 | 	* constraint}, as defined by Wildcard Subset (�3.10.6)." | 
 | 	*/ | 
 |  | 
 | 	/* | 
 | 	* MAYBE TODO: Enable if ever needed. But this will be needed only | 
 | 	* if created the type via a schema construction API. | 
 | 	*/ | 
 | 	if (base->attributeWildcard != NULL) { | 
 | 	    if (type->attributeWilcard == NULL) { | 
 | 		xmlChar *str = NULL; | 
 |  | 
 | 		xmlSchemaCustomErr(ACTXT_CAST pctxt, | 
 | 		    XML_SCHEMAP_COS_CT_EXTENDS_1_3, | 
 | 		    NULL, type, | 
 | 		    "The base %s has an attribute wildcard, " | 
 | 		    "but this type is missing an attribute wildcard", | 
 | 		    xmlSchemaGetComponentDesignation(&str, base)); | 
 | 		FREE_AND_NULL(str) | 
 |  | 
 | 	    } else if (xmlSchemaCheckCOSNSSubset( | 
 | 		base->attributeWildcard, type->attributeWildcard)) | 
 | 	    { | 
 | 		xmlChar *str = NULL; | 
 |  | 
 | 		xmlSchemaCustomErr(ACTXT_CAST pctxt, | 
 | 		    XML_SCHEMAP_COS_CT_EXTENDS_1_3, | 
 | 		    NULL, type, | 
 | 		    "The attribute wildcard is not a valid " | 
 | 		    "superset of the one in the base %s", | 
 | 		    xmlSchemaGetComponentDesignation(&str, base)); | 
 | 		FREE_AND_NULL(str) | 
 | 	    } | 
 | 	} | 
 | #endif | 
 | 	/* | 
 | 	* SPEC (1.4) "One of the following must be true:" | 
 | 	*/ | 
 | 	if ((type->contentTypeDef != NULL) && | 
 | 	    (type->contentTypeDef == base->contentTypeDef)) { | 
 | 	    /* | 
 | 	    * SPEC (1.4.1) "The {content type} of the {base type definition} | 
 | 	    * and the {content type} of the complex type definition itself | 
 | 	    * must be the same simple type definition" | 
 | 	    * PASS | 
 | 	    */ | 
 | 	} else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) && | 
 | 	    (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) { | 
 | 	    /* | 
 | 	    * SPEC (1.4.2) "The {content type} of both the {base type | 
 | 	    * definition} and the complex type definition itself must | 
 | 	    * be empty." | 
 | 	    * PASS | 
 | 	    */ | 
 | 	} else { | 
 | 	    /* | 
 | 	    * SPEC (1.4.3) "All of the following must be true:" | 
 | 	    */ | 
 | 	    if (type->subtypes == NULL) { | 
 | 		/* | 
 | 		* SPEC 1.4.3.1 The {content type} of the complex type | 
 | 		* definition itself must specify a particle. | 
 | 		*/ | 
 | 		xmlSchemaPCustomErr(ctxt, | 
 | 		    XML_SCHEMAP_COS_CT_EXTENDS_1_1, | 
 | 		    WXS_BASIC_CAST type, NULL, | 
 | 		    "The content type must specify a particle", NULL); | 
 | 		return (XML_SCHEMAP_COS_CT_EXTENDS_1_1); | 
 | 	    } | 
 | 	    /* | 
 | 	    * SPEC (1.4.3.2) "One of the following must be true:" | 
 | 	    */ | 
 | 	    if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) { | 
 | 		/* | 
 | 		* SPEC (1.4.3.2.1) "The {content type} of the {base type | 
 | 		* definition} must be empty. | 
 | 		* PASS | 
 | 		*/ | 
 | 	    } else { | 
 | 		/* | 
 | 		* SPEC (1.4.3.2.2) "All of the following must be true:" | 
 | 		*/ | 
 | 		if ((type->contentType != base->contentType) || | 
 | 		    ((type->contentType != XML_SCHEMA_CONTENT_MIXED) && | 
 | 		    (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) { | 
 | 		    /* | 
 | 		    * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed | 
 | 		    * or both must be element-only." | 
 | 		    */ | 
 | 		    xmlSchemaPCustomErr(ctxt, | 
 | 			XML_SCHEMAP_COS_CT_EXTENDS_1_1, | 
 | 			WXS_BASIC_CAST type, NULL, | 
 | 			"The content type of both, the type and its base " | 
 | 			"type, must either 'mixed' or 'element-only'", NULL); | 
 | 		    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1); | 
 | 		} | 
 | 		/* | 
 | 		* URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the | 
 | 		* complex type definition must be a �valid extension� | 
 | 		* of the {base type definition}'s particle, as defined | 
 | 		* in Particle Valid (Extension) (�3.9.6)." | 
 | 		* | 
 | 		* NOTE that we won't check "Particle Valid (Extension)", | 
 | 		* since it is ensured by the derivation process in | 
 | 		* xmlSchemaTypeFixup(). We need to implement this when heading | 
 | 		* for a construction API | 
 | 		* TODO: !! This is needed to be checked if redefining a type !! | 
 | 		*/ | 
 | 	    } | 
 | 	    /* | 
 | 	    * URGENT TODO (1.5) | 
 | 	    */ | 
 | 	} | 
 |     } else { | 
 | 	/* | 
 | 	* SPEC (2) "If the {base type definition} is a simple type definition, | 
 | 	* then all of the following must be true:" | 
 | 	*/ | 
 | 	if (type->contentTypeDef != base) { | 
 | 	    /* | 
 | 	    * SPEC (2.1) "The {content type} must be the same simple type | 
 | 	    * definition." | 
 | 	    */ | 
 | 	    xmlSchemaPCustomErr(ctxt, | 
 | 		XML_SCHEMAP_COS_CT_EXTENDS_1_1, | 
 | 		WXS_BASIC_CAST type, NULL, | 
 | 		"The content type must be the simple base type", NULL); | 
 | 	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1); | 
 | 	} | 
 | 	if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) { | 
 | 	    /* | 
 | 	    * SPEC (2.2) "The {final} of the {base type definition} must not | 
 | 	    * contain extension" | 
 | 	    * NOTE that this is the same as (1.1). | 
 | 	    */ | 
 | 	    xmlSchemaPCustomErr(ctxt, | 
 | 		XML_SCHEMAP_COS_CT_EXTENDS_1_1, | 
 | 		WXS_BASIC_CAST type, NULL, | 
 | 		"The 'final' of the base type definition " | 
 | 		"contains 'extension'", NULL); | 
 | 	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1); | 
 | 	} | 
 |     } | 
 |     return (0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaCheckDerivationOKRestriction: | 
 |  * @ctxt:  the schema parser context | 
 |  * @type:  the complex type definition | 
 |  * | 
 |  * (3.4.6) Constraints on Complex Type Definition Schema Components | 
 |  * Schema Component Constraint: | 
 |  * Derivation Valid (Restriction, Complex) (derivation-ok-restriction) | 
 |  * | 
 |  * STATUS: | 
 |  *   missing: | 
 |  *     (5.4.2) ??? | 
 |  * | 
 |  * ATTENTION: | 
 |  * In XML Schema 1.1 this will be: | 
 |  * Validation Rule: Checking complex type subsumption | 
 |  * | 
 |  * Returns 0 if the constraints are satisfied, a positive | 
 |  * error code if not and -1 if an internal error occured. | 
 |  */ | 
 | static int | 
 | xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt, | 
 | 				      xmlSchemaTypePtr type) | 
 | { | 
 |     xmlSchemaTypePtr base; | 
 |  | 
 |     /* | 
 |     * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used | 
 |     * temporarily only. | 
 |     */ | 
 |     base = type->baseType; | 
 |     if (! WXS_IS_COMPLEX(base)) { | 
 | 	xmlSchemaCustomErr(ACTXT_CAST ctxt, | 
 | 	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1, | 
 | 	    type->node, WXS_BASIC_CAST type, | 
 | 	    "The base type must be a complex type", NULL, NULL); | 
 | 	return(ctxt->err); | 
 |     } | 
 |     if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) { | 
 | 	/* | 
 | 	* SPEC (1) "The {base type definition} must be a complex type | 
 | 	* definition whose {final} does not contain restriction." | 
 | 	*/ | 
 | 	xmlSchemaCustomErr(ACTXT_CAST ctxt, | 
 | 	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1, | 
 | 	    type->node, WXS_BASIC_CAST type, | 
 | 	    "The 'final' of the base type definition " | 
 | 	    "contains 'restriction'", NULL, NULL); | 
 | 	return (ctxt->err); | 
 |     } | 
 |     /* | 
 |     * SPEC (2), (3) and (4) | 
 |     * Those are handled in a separate function, since the | 
 |     * same constraints are needed for redefinition of | 
 |     * attribute groups as well. | 
 |     */ | 
 |     if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt, | 
 | 	XML_SCHEMA_ACTION_DERIVE, | 
 | 	WXS_BASIC_CAST type, WXS_BASIC_CAST base, | 
 | 	type->attrUses, base->attrUses, | 
 | 	type->attributeWildcard, | 
 | 	base->attributeWildcard) == -1) | 
 |     { | 
 | 	return(-1); | 
 |     } | 
 |     /* | 
 |     * SPEC (5) "One of the following must be true:" | 
 |     */ | 
 |     if (base->builtInType == XML_SCHEMAS_ANYTYPE) { | 
 | 	/* | 
 | 	* SPEC (5.1) "The {base type definition} must be the | 
 | 	* �ur-type definition�." | 
 | 	* PASS | 
 | 	*/ | 
 |     } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) || | 
 | 	    (type->contentType == XML_SCHEMA_CONTENT_BASIC)) { | 
 | 	/* | 
 | 	* SPEC (5.2.1) "The {content type} of the complex type definition | 
 | 	* must be a simple type definition" | 
 | 	* | 
 | 	* SPEC (5.2.2) "One of the following must be true:" | 
 | 	*/ | 
 | 	if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) || | 
 | 	    (base->contentType == XML_SCHEMA_CONTENT_BASIC)) | 
 | 	{ | 
 | 	    int err; | 
 | 	    /* | 
 | 	    * SPEC (5.2.2.1) "The {content type} of the {base type | 
 | 	    * definition} must be a simple type definition from which | 
 | 	    * the {content type} is validly derived given the empty | 
 | 	    * set as defined in Type Derivation OK (Simple) (�3.14.6)." | 
 | 	    * | 
 | 	    * ATTENTION TODO: This seems not needed if the type implicitely | 
 | 	    * derived from the base type. | 
 | 	    * | 
 | 	    */ | 
 | 	    err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt, | 
 | 		type->contentTypeDef, base->contentTypeDef, 0); | 
 | 	    if (err != 0) { | 
 | 		xmlChar *strA = NULL, *strB = NULL; | 
 |  | 
 | 		if (err == -1) | 
 | 		    return(-1); | 
 | 		xmlSchemaCustomErr(ACTXT_CAST ctxt, | 
 | 		    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1, | 
 | 		    NULL, WXS_BASIC_CAST type, | 
 | 		    "The {content type} %s is not validly derived from the " | 
 | 		    "base type's {content type} %s", | 
 | 		    xmlSchemaGetComponentDesignation(&strA, | 
 | 			type->contentTypeDef), | 
 | 		    xmlSchemaGetComponentDesignation(&strB, | 
 | 			base->contentTypeDef)); | 
 | 		FREE_AND_NULL(strA); | 
 | 		FREE_AND_NULL(strB); | 
 | 		return(ctxt->err); | 
 | 	    } | 
 | 	} else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) && | 
 | 	    (xmlSchemaIsParticleEmptiable( | 
 | 		(xmlSchemaParticlePtr) base->subtypes))) { | 
 | 	    /* | 
 | 	    * SPEC (5.2.2.2) "The {base type definition} must be mixed | 
 | 	    * and have a particle which is �emptiable� as defined in | 
 | 	    * Particle Emptiable (�3.9.6)." | 
 | 	    * PASS | 
 | 	    */ | 
 | 	} else { | 
 | 	    xmlSchemaPCustomErr(ctxt, | 
 | 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1, | 
 | 		WXS_BASIC_CAST type, NULL, | 
 | 		"The content type of the base type must be either " | 
 | 		"a simple type or 'mixed' and an emptiable particle", NULL); | 
 | 	    return (ctxt->err); | 
 | 	} | 
 |     } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) { | 
 | 	/* | 
 | 	* SPEC (5.3.1) "The {content type} of the complex type itself must | 
 | 	* be empty" | 
 | 	*/ | 
 | 	if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) { | 
 | 	    /* | 
 | 	    * SPEC (5.3.2.1) "The {content type} of the {base type | 
 | 	    * definition} must also be empty." | 
 | 	    * PASS | 
 | 	    */ | 
 | 	} else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) || | 
 | 	    (base->contentType == XML_SCHEMA_CONTENT_MIXED)) && | 
 | 	    xmlSchemaIsParticleEmptiable( | 
 | 		(xmlSchemaParticlePtr) base->subtypes)) { | 
 | 	    /* | 
 | 	    * SPEC (5.3.2.2) "The {content type} of the {base type | 
 | 	    * definition} must be elementOnly or mixed and have a particle | 
 | 	    * which is �emptiable� as defined in Particle Emptiable (�3.9.6)." | 
 | 	    * PASS | 
 | 	    */ | 
 | 	} else { | 
 | 	    xmlSchemaPCustomErr(ctxt, | 
 | 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1, | 
 | 		WXS_BASIC_CAST type, NULL, | 
 | 		"The content type of the base type must be either " | 
 | 		"empty or 'mixed' (or 'elements-only') and an emptiable " | 
 | 		"particle", NULL); | 
 | 	    return (ctxt->err); | 
 | 	} | 
 |     } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) || | 
 | 	WXS_HAS_MIXED_CONTENT(type)) { | 
 | 	/* | 
 | 	* SPEC (5.4.1.1) "The {content type} of the complex type definition | 
 | 	* itself must be element-only" | 
 | 	*/ | 
 | 	if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) { | 
 | 	    /* | 
 | 	    * SPEC (5.4.1.2) "The {content type} of the complex type | 
 | 	    * definition itself and of the {base type definition} must be | 
 | 	    * mixed" | 
 | 	    */ | 
 | 	    xmlSchemaPCustomErr(ctxt, | 
 | 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1, | 
 | 		WXS_BASIC_CAST type, NULL, | 
 | 		"If the content type is 'mixed', then the content type of the " | 
 | 		"base type must also be 'mixed'", NULL); | 
 | 	    return (ctxt->err); | 
 | 	} | 
 | 	/* | 
 | 	* SPEC (5.4.2) "The particle of the complex type definition itself | 
 | 	* must be a �valid restriction� of the particle of the {content | 
 | 	* type} of the {base type definition} as defined in Particle Valid | 
 | 	* (Restriction) (�3.9.6). | 
 | 	* | 
 | 	* URGENT TODO: (5.4.2) | 
 | 	*/ | 
 |     } else { | 
 | 	xmlSchemaPCustomErr(ctxt, | 
 | 	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1, | 
 | 	    WXS_BASIC_CAST type, NULL, | 
 | 	    "The type is not a valid restriction of its base type", NULL); | 
 | 	return (ctxt->err); | 
 |     } | 
 |     return (0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaCheckCTComponent: | 
 |  * @ctxt:  the schema parser context | 
 |  * @type:  the complex type definition | 
 |  * | 
 |  * (3.4.6) Constraints on Complex Type Definition Schema Components | 
 |  * | 
 |  * Returns 0 if the constraints are satisfied, a positive | 
 |  * error code if not and -1 if an internal error occured. | 
 |  */ | 
 | static int | 
 | xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt, | 
 | 			  xmlSchemaTypePtr type) | 
 | { | 
 |     int ret; | 
 |     /* | 
 |     * Complex Type Definition Properties Correct | 
 |     */ | 
 |     ret = xmlSchemaCheckCTPropsCorrect(ctxt, type); | 
 |     if (ret != 0) | 
 | 	return (ret); | 
 |     if (WXS_IS_EXTENSION(type)) | 
 | 	ret = xmlSchemaCheckCOSCTExtends(ctxt, type); | 
 |     else | 
 | 	ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type); | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaCheckSRCCT: | 
 |  * @ctxt:  the schema parser context | 
 |  * @type:  the complex type definition | 
 |  * | 
 |  * (3.4.3) Constraints on XML Representations of Complex Type Definitions: | 
 |  * Schema Representation Constraint: | 
 |  * Complex Type Definition Representation OK (src-ct) | 
 |  * | 
 |  * Returns 0 if the constraints are satisfied, a positive | 
 |  * error code if not and -1 if an internal error occured. | 
 |  */ | 
 | static int | 
 | xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt, | 
 | 		    xmlSchemaTypePtr type) | 
 | { | 
 |     xmlSchemaTypePtr base; | 
 |     int ret = 0; | 
 |  | 
 |     /* | 
 |     * TODO: Adjust the error codes here, as I used | 
 |     * XML_SCHEMAP_SRC_CT_1 only yet. | 
 |     */ | 
 |     base = type->baseType; | 
 |     if (! WXS_HAS_SIMPLE_CONTENT(type)) { | 
 | 	/* | 
 | 	* 1 If the <complexContent> alternative is chosen, the type definition | 
 | 	* �resolved� to by the �actual value� of the base [attribute] | 
 | 	* must be a complex type definition; | 
 | 	*/ | 
 | 	if (! WXS_IS_COMPLEX(base)) { | 
 | 	    xmlChar *str = NULL; | 
 | 	    xmlSchemaPCustomErr(ctxt, | 
 | 		XML_SCHEMAP_SRC_CT_1, | 
 | 		WXS_BASIC_CAST type, type->node, | 
 | 		"If using <complexContent>, the base type is expected to be " | 
 | 		"a complex type. The base type '%s' is a simple type", | 
 | 		xmlSchemaFormatQName(&str, base->targetNamespace, | 
 | 		base->name)); | 
 | 	    FREE_AND_NULL(str) | 
 | 	    return (XML_SCHEMAP_SRC_CT_1); | 
 | 	} | 
 |     } else { | 
 | 	/* | 
 | 	* SPEC | 
 | 	* 2 If the <simpleContent> alternative is chosen, all of the | 
 | 	* following must be true: | 
 | 	* 2.1 The type definition �resolved� to by the �actual value� of the | 
 | 	* base [attribute] must be one of the following: | 
 | 	*/ | 
 | 	if (WXS_IS_SIMPLE(base)) { | 
 | 	    if (WXS_IS_EXTENSION(type) == 0) { | 
 | 		xmlChar *str = NULL; | 
 | 		/* | 
 | 		* 2.1.3 only if the <extension> alternative is also | 
 | 		* chosen, a simple type definition. | 
 | 		*/ | 
 | 		/* TODO: Change error code to ..._SRC_CT_2_1_3. */ | 
 | 		xmlSchemaPCustomErr(ctxt, | 
 | 		    XML_SCHEMAP_SRC_CT_1, | 
 | 		    WXS_BASIC_CAST type, NULL, | 
 | 		    "If using <simpleContent> and <restriction>, the base " | 
 | 		    "type must be a complex type. The base type '%s' is " | 
 | 		    "a simple type", | 
 | 		    xmlSchemaFormatQName(&str, base->targetNamespace, | 
 | 			base->name)); | 
 | 		FREE_AND_NULL(str) | 
 | 		return (XML_SCHEMAP_SRC_CT_1); | 
 | 	    } | 
 | 	} else { | 
 | 	    /* Base type is a complex type. */ | 
 | 	    if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) || | 
 | 		(base->contentType == XML_SCHEMA_CONTENT_BASIC)) { | 
 | 		/* | 
 | 		* 2.1.1 a complex type definition whose {content type} is a | 
 | 		* simple type definition; | 
 | 		* PASS | 
 | 		*/ | 
 | 		if (base->contentTypeDef == NULL) { | 
 | 		    xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, | 
 | 			WXS_BASIC_CAST type, NULL, | 
 | 			"Internal error: xmlSchemaCheckSRCCT, " | 
 | 			"'%s', base type has no content type", | 
 | 			type->name); | 
 | 		    return (-1); | 
 | 		} | 
 | 	    } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) && | 
 | 		(WXS_IS_RESTRICTION(type))) { | 
 |  | 
 | 		/* | 
 | 		* 2.1.2 only if the <restriction> alternative is also | 
 | 		* chosen, a complex type definition whose {content type} | 
 | 		* is mixed and a particle emptiable. | 
 | 		*/ | 
 | 		if (! xmlSchemaIsParticleEmptiable( | 
 | 		    (xmlSchemaParticlePtr) base->subtypes)) { | 
 | 		    ret = XML_SCHEMAP_SRC_CT_1; | 
 | 		} else | 
 | 		    /* | 
 | 		    * Attention: at this point the <simpleType> child is in | 
 | 		    * ->contentTypeDef (put there during parsing). | 
 | 		    */ | 
 | 		    if (type->contentTypeDef == NULL) { | 
 | 		    xmlChar *str = NULL; | 
 | 		    /* | 
 | 		    * 2.2 If clause 2.1.2 above is satisfied, then there | 
 | 		    * must be a <simpleType> among the [children] of | 
 | 		    * <restriction>. | 
 | 		    */ | 
 | 		    /* TODO: Change error code to ..._SRC_CT_2_2. */ | 
 | 		    xmlSchemaPCustomErr(ctxt, | 
 | 			XML_SCHEMAP_SRC_CT_1, | 
 | 			WXS_BASIC_CAST type, NULL, | 
 | 			"A <simpleType> is expected among the children " | 
 | 			"of <restriction>, if <simpleContent> is used and " | 
 | 			"the base type '%s' is a complex type", | 
 | 			xmlSchemaFormatQName(&str, base->targetNamespace, | 
 | 			base->name)); | 
 | 		    FREE_AND_NULL(str) | 
 | 		    return (XML_SCHEMAP_SRC_CT_1); | 
 | 		} | 
 | 	    } else { | 
 | 		ret = XML_SCHEMAP_SRC_CT_1; | 
 | 	    } | 
 | 	} | 
 | 	if (ret > 0) { | 
 | 	    xmlChar *str = NULL; | 
 | 	    if (WXS_IS_RESTRICTION(type)) { | 
 | 		xmlSchemaPCustomErr(ctxt, | 
 | 		    XML_SCHEMAP_SRC_CT_1, | 
 | 		    WXS_BASIC_CAST type, NULL, | 
 | 		    "If <simpleContent> and <restriction> is used, the " | 
 | 		    "base type must be a simple type or a complex type with " | 
 | 		    "mixed content and particle emptiable. The base type " | 
 | 		    "'%s' is none of those", | 
 | 		    xmlSchemaFormatQName(&str, base->targetNamespace, | 
 | 		    base->name)); | 
 | 	    } else { | 
 | 		xmlSchemaPCustomErr(ctxt, | 
 | 		    XML_SCHEMAP_SRC_CT_1, | 
 | 		    WXS_BASIC_CAST type, NULL, | 
 | 		    "If <simpleContent> and <extension> is used, the " | 
 | 		    "base type must be a simple type. The base type '%s' " | 
 | 		    "is a complex type", | 
 | 		    xmlSchemaFormatQName(&str, base->targetNamespace, | 
 | 		    base->name)); | 
 | 	    } | 
 | 	    FREE_AND_NULL(str) | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * SPEC (3) "The corresponding complex type definition component must | 
 |     * satisfy the conditions set out in Constraints on Complex Type | 
 |     * Definition Schema Components (�3.4.6);" | 
 |     * NOTE (3) will be done in xmlSchemaTypeFixup(). | 
 |     */ | 
 |     /* | 
 |     * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification | 
 |     * above for {attribute wildcard} is satisfied, the intensional | 
 |     * intersection must be expressible, as defined in Attribute Wildcard | 
 |     * Intersection (�3.10.6). | 
 |     * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses(). | 
 |     */ | 
 |     return (ret); | 
 | } | 
 |  | 
 | #ifdef ENABLE_PARTICLE_RESTRICTION | 
 | /** | 
 |  * xmlSchemaCheckParticleRangeOK: | 
 |  * @ctxt:  the schema parser context | 
 |  * @type:  the complex type definition | 
 |  * | 
 |  * (3.9.6) Constraints on Particle Schema Components | 
 |  * Schema Component Constraint: | 
 |  * Occurrence Range OK (range-ok) | 
 |  * | 
 |  * STATUS: complete | 
 |  * | 
 |  * Returns 0 if the constraints are satisfied, a positive | 
 |  * error code if not and -1 if an internal error occured. | 
 |  */ | 
 | static int | 
 | xmlSchemaCheckParticleRangeOK(int rmin, int rmax, | 
 | 			      int bmin, int bmax) | 
 | { | 
 |     if (rmin < bmin) | 
 | 	return (1); | 
 |     if ((bmax != UNBOUNDED) && | 
 | 	(rmax > bmax)) | 
 | 	return (1); | 
 |     return (0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaCheckRCaseNameAndTypeOK: | 
 |  * @ctxt:  the schema parser context | 
 |  * @r: the restricting element declaration particle | 
 |  * @b: the base element declaration particle | 
 |  * | 
 |  * (3.9.6) Constraints on Particle Schema Components | 
 |  * Schema Component Constraint: | 
 |  * Particle Restriction OK (Elt:Elt -- NameAndTypeOK) | 
 |  * (rcase-NameAndTypeOK) | 
 |  * | 
 |  * STATUS: | 
 |  *   MISSING (3.2.3) | 
 |  *   CLARIFY: (3.2.2) | 
 |  * | 
 |  * Returns 0 if the constraints are satisfied, a positive | 
 |  * error code if not and -1 if an internal error occured. | 
 |  */ | 
 | static int | 
 | xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt, | 
 | 				 xmlSchemaParticlePtr r, | 
 | 				 xmlSchemaParticlePtr b) | 
 | { | 
 |     xmlSchemaElementPtr elemR, elemB; | 
 |  | 
 |     /* TODO: Error codes (rcase-NameAndTypeOK). */ | 
 |     elemR = (xmlSchemaElementPtr) r->children; | 
 |     elemB = (xmlSchemaElementPtr) b->children; | 
 |     /* | 
 |     * SPEC (1) "The declarations' {name}s and {target namespace}s are | 
 |     * the same." | 
 |     */ | 
 |     if ((elemR != elemB) && | 
 | 	((! xmlStrEqual(elemR->name, elemB->name)) || | 
 | 	(! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace)))) | 
 | 	return (1); | 
 |     /* | 
 |     * SPEC (2) "R's occurrence range is a valid restriction of B's | 
 |     * occurrence range as defined by Occurrence Range OK (�3.9.6)." | 
 |     */ | 
 |     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs, | 
 | 	    b->minOccurs, b->maxOccurs) != 0) | 
 | 	return (1); | 
 |     /* | 
 |     * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's | 
 |     * {scope} are global." | 
 |     */ | 
 |     if (elemR == elemB) | 
 | 	return (0); | 
 |     /* | 
 |     * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false." | 
 |     */ | 
 |     if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) && | 
 | 	(elemR->flags & XML_SCHEMAS_ELEM_NILLABLE)) | 
 | 	 return (1); | 
 |     /* | 
 |     * SPEC (3.2.2) "either B's declaration's {value constraint} is absent, | 
 |     * or is not fixed, or R's declaration's {value constraint} is fixed | 
 |     * with the same value." | 
 |     */ | 
 |     if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) && | 
 | 	((elemR->value == NULL) || | 
 | 	 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) || | 
 | 	 /* TODO: Equality of the initial value or normalized or canonical? */ | 
 | 	 (! xmlStrEqual(elemR->value, elemB->value)))) | 
 | 	 return (1); | 
 |     /* | 
 |     * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint | 
 |     * definitions} is a subset of B's declaration's {identity-constraint | 
 |     * definitions}, if any." | 
 |     */ | 
 |     if (elemB->idcs != NULL) { | 
 | 	/* TODO */ | 
 |     } | 
 |     /* | 
 |     * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a | 
 |     * superset of B's declaration's {disallowed substitutions}." | 
 |     */ | 
 |     if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) && | 
 | 	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) || | 
 | 	((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) && | 
 | 	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) || | 
 | 	((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) && | 
 | 	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0))) | 
 | 	 return (1); | 
 |     /* | 
 |     * SPEC (3.2.5) "R's {type definition} is validly derived given | 
 |     * {extension, list, union} from B's {type definition}" | 
 |     * | 
 |     * BADSPEC TODO: What's the point of adding "list" and "union" to the | 
 |     * set, if the corresponding constraints handle "restriction" and | 
 |     * "extension" only? | 
 |     * | 
 |     */ | 
 |     { | 
 | 	int set = 0; | 
 |  | 
 | 	set |= SUBSET_EXTENSION; | 
 | 	set |= SUBSET_LIST; | 
 | 	set |= SUBSET_UNION; | 
 | 	if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes, | 
 | 	    elemB->subtypes, set) != 0) | 
 | 	    return (1); | 
 |     } | 
 |     return (0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaCheckRCaseNSCompat: | 
 |  * @ctxt:  the schema parser context | 
 |  * @r: the restricting element declaration particle | 
 |  * @b: the base wildcard particle | 
 |  * | 
 |  * (3.9.6) Constraints on Particle Schema Components | 
 |  * Schema Component Constraint: | 
 |  * Particle Derivation OK (Elt:Any -- NSCompat) | 
 |  * (rcase-NSCompat) | 
 |  * | 
 |  * STATUS: complete | 
 |  * | 
 |  * Returns 0 if the constraints are satisfied, a positive | 
 |  * error code if not and -1 if an internal error occured. | 
 |  */ | 
 | static int | 
 | xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt, | 
 | 			    xmlSchemaParticlePtr r, | 
 | 			    xmlSchemaParticlePtr b) | 
 | { | 
 |     /* TODO:Error codes (rcase-NSCompat). */ | 
 |     /* | 
 |     * SPEC "For an element declaration particle to be a �valid restriction� | 
 |     * of a wildcard particle all of the following must be true:" | 
 |     * | 
 |     * SPEC (1) "The element declaration's {target namespace} is �valid� | 
 |     * with respect to the wildcard's {namespace constraint} as defined by | 
 |     * Wildcard allows Namespace Name (�3.10.4)." | 
 |     */ | 
 |     if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children, | 
 | 	((xmlSchemaElementPtr) r->children)->targetNamespace) != 0) | 
 | 	return (1); | 
 |     /* | 
 |     * SPEC (2) "R's occurrence range is a valid restriction of B's | 
 |     * occurrence range as defined by Occurrence Range OK (�3.9.6)." | 
 |     */ | 
 |     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs, | 
 | 	    b->minOccurs, b->maxOccurs) != 0) | 
 | 	return (1); | 
 |  | 
 |     return (0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaCheckRCaseRecurseAsIfGroup: | 
 |  * @ctxt:  the schema parser context | 
 |  * @r: the restricting element declaration particle | 
 |  * @b: the base model group particle | 
 |  * | 
 |  * (3.9.6) Constraints on Particle Schema Components | 
 |  * Schema Component Constraint: | 
 |  * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup) | 
 |  * (rcase-RecurseAsIfGroup) | 
 |  * | 
 |  * STATUS: TODO | 
 |  * | 
 |  * Returns 0 if the constraints are satisfied, a positive | 
 |  * error code if not and -1 if an internal error occured. | 
 |  */ | 
 | static int | 
 | xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt, | 
 | 				    xmlSchemaParticlePtr r, | 
 | 				    xmlSchemaParticlePtr b) | 
 | { | 
 |     /* TODO: Error codes (rcase-RecurseAsIfGroup). */ | 
 |     TODO | 
 |     return (0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaCheckRCaseNSSubset: | 
 |  * @ctxt:  the schema parser context | 
 |  * @r: the restricting wildcard particle | 
 |  * @b: the base wildcard particle | 
 |  * | 
 |  * (3.9.6) Constraints on Particle Schema Components | 
 |  * Schema Component Constraint: | 
 |  * Particle Derivation OK (Any:Any -- NSSubset) | 
 |  * (rcase-NSSubset) | 
 |  * | 
 |  * STATUS: complete | 
 |  * | 
 |  * Returns 0 if the constraints are satisfied, a positive | 
 |  * error code if not and -1 if an internal error occured. | 
 |  */ | 
 | static int | 
 | xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt, | 
 | 				    xmlSchemaParticlePtr r, | 
 | 				    xmlSchemaParticlePtr b, | 
 | 				    int isAnyTypeBase) | 
 | { | 
 |     /* TODO: Error codes (rcase-NSSubset). */ | 
 |     /* | 
 |     * SPEC (1) "R's occurrence range is a valid restriction of B's | 
 |     * occurrence range as defined by Occurrence Range OK (�3.9.6)." | 
 |     */ | 
 |     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs, | 
 | 	    b->minOccurs, b->maxOccurs)) | 
 | 	return (1); | 
 |     /* | 
 |     * SPEC (2) "R's {namespace constraint} must be an intensional subset | 
 |     * of B's {namespace constraint} as defined by Wildcard Subset (�3.10.6)." | 
 |     */ | 
 |     if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children, | 
 | 	(xmlSchemaWildcardPtr) b->children)) | 
 | 	return (1); | 
 |     /* | 
 |     * SPEC (3) "Unless B is the content model wildcard of the �ur-type | 
 |     * definition�, R's {process contents} must be identical to or stronger | 
 |     * than B's {process contents}, where strict is stronger than lax is | 
 |     * stronger than skip." | 
 |     */ | 
 |     if (! isAnyTypeBase) { | 
 | 	if ( ((xmlSchemaWildcardPtr) r->children)->processContents < | 
 | 	    ((xmlSchemaWildcardPtr) b->children)->processContents) | 
 | 	    return (1); | 
 |     } | 
 |  | 
 |     return (0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaCheckCOSParticleRestrict: | 
 |  * @ctxt:  the schema parser context | 
 |  * @type:  the complex type definition | 
 |  * | 
 |  * (3.9.6) Constraints on Particle Schema Components | 
 |  * Schema Component Constraint: | 
 |  * Particle Valid (Restriction) (cos-particle-restrict) | 
 |  * | 
 |  * STATUS: TODO | 
 |  * | 
 |  * Returns 0 if the constraints are satisfied, a positive | 
 |  * error code if not and -1 if an internal error occured. | 
 |  */ | 
 | static int | 
 | xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt, | 
 | 				  xmlSchemaParticlePtr r, | 
 | 				  xmlSchemaParticlePtr b) | 
 | { | 
 |     int ret = 0; | 
 |  | 
 |     /*part = WXS_TYPE_PARTICLE(type); | 
 |     basePart = WXS_TYPE_PARTICLE(base); | 
 |     */ | 
 |  | 
 |     TODO | 
 |  | 
 |     /* | 
 |     * SPEC (1) "They are the same particle." | 
 |     */ | 
 |     if (r == b) | 
 | 	return (0); | 
 |  | 
 |  | 
 |     return (0); | 
 | } | 
 |  | 
 | #if 0 | 
 | /** | 
 |  * xmlSchemaCheckRCaseNSRecurseCheckCardinality: | 
 |  * @ctxt:  the schema parser context | 
 |  * @r: the model group particle | 
 |  * @b: the base wildcard particle | 
 |  * | 
 |  * (3.9.6) Constraints on Particle Schema Components | 
 |  * Schema Component Constraint: | 
 |  * Particle Derivation OK (All/Choice/Sequence:Any -- | 
 |  *                         NSRecurseCheckCardinality) | 
 |  * (rcase-NSRecurseCheckCardinality) | 
 |  * | 
 |  * STATUS: TODO: subst-groups | 
 |  * | 
 |  * Returns 0 if the constraints are satisfied, a positive | 
 |  * error code if not and -1 if an internal error occured. | 
 |  */ | 
 | static int | 
 | xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt, | 
 | 					     xmlSchemaParticlePtr r, | 
 | 					     xmlSchemaParticlePtr b) | 
 | { | 
 |     xmlSchemaParticlePtr part; | 
 |     /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */ | 
 |     if ((r->children == NULL) || (r->children->children == NULL)) | 
 | 	return (-1); | 
 |     /* | 
 |     * SPEC "For a group particle to be a �valid restriction� of a | 
 |     * wildcard particle..." | 
 |     * | 
 |     * SPEC (1) "Every member of the {particles} of the group is a �valid | 
 |     * restriction� of the wildcard as defined by | 
 |     * Particle Valid (Restriction) (�3.9.6)." | 
 |     */ | 
 |     part = (xmlSchemaParticlePtr) r->children->children; | 
 |     do { | 
 | 	if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b)) | 
 | 	    return (1); | 
 | 	part = (xmlSchemaParticlePtr) part->next; | 
 |     } while (part != NULL); | 
 |     /* | 
 |     * SPEC (2) "The effective total range of the group [...] is a | 
 |     * valid restriction of B's occurrence range as defined by | 
 |     * Occurrence Range OK (�3.9.6)." | 
 |     */ | 
 |     if (xmlSchemaCheckParticleRangeOK( | 
 | 	    xmlSchemaGetParticleTotalRangeMin(r), | 
 | 	    xmlSchemaGetParticleTotalRangeMax(r), | 
 | 	    b->minOccurs, b->maxOccurs) != 0) | 
 | 	return (1); | 
 |     return (0); | 
 | } | 
 | #endif | 
 |  | 
 | /** | 
 |  * xmlSchemaCheckRCaseRecurse: | 
 |  * @ctxt:  the schema parser context | 
 |  * @r: the <all> or <sequence> model group particle | 
 |  * @b: the base <all> or <sequence> model group particle | 
 |  * | 
 |  * (3.9.6) Constraints on Particle Schema Components | 
 |  * Schema Component Constraint: | 
 |  * Particle Derivation OK (All:All,Sequence:Sequence -- | 
 |                            Recurse) | 
 |  * (rcase-Recurse) | 
 |  * | 
 |  * STATUS:  ? | 
 |  * TODO: subst-groups | 
 |  * | 
 |  * Returns 0 if the constraints are satisfied, a positive | 
 |  * error code if not and -1 if an internal error occured. | 
 |  */ | 
 | static int | 
 | xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt, | 
 | 			   xmlSchemaParticlePtr r, | 
 | 			   xmlSchemaParticlePtr b) | 
 | { | 
 |     /* xmlSchemaParticlePtr part; */ | 
 |     /* TODO: Error codes (rcase-Recurse). */ | 
 |     if ((r->children == NULL) || (b->children == NULL) || | 
 | 	(r->children->type != b->children->type)) | 
 | 	return (-1); | 
 |     /* | 
 |     * SPEC "For an all or sequence group particle to be a �valid | 
 |     * restriction� of another group particle with the same {compositor}..." | 
 |     * | 
 |     * SPEC (1) "R's occurrence range is a valid restriction of B's | 
 |     * occurrence range as defined by Occurrence Range OK (�3.9.6)." | 
 |     */ | 
 |     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs, | 
 | 	    b->minOccurs, b->maxOccurs)) | 
 | 	return (1); | 
 |  | 
 |  | 
 |     return (0); | 
 | } | 
 |  | 
 | #endif | 
 |  | 
 | #define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \ | 
 |     xmlSchemaPCustomErrExt(pctxt,      \ | 
 | 	XML_SCHEMAP_INVALID_FACET_VALUE, \ | 
 | 	WXS_BASIC_CAST fac1, fac1->node, \ | 
 | 	"It is an error for both '%s' and '%s' to be specified on the "\ | 
 | 	"same type definition", \ | 
 | 	BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \ | 
 | 	BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL); | 
 |  | 
 | #define FACET_RESTR_ERR(fac1, msg) \ | 
 |     xmlSchemaPCustomErr(pctxt,      \ | 
 | 	XML_SCHEMAP_INVALID_FACET_VALUE, \ | 
 | 	WXS_BASIC_CAST fac1, fac1->node, \ | 
 | 	msg, NULL); | 
 |  | 
 | #define FACET_RESTR_FIXED_ERR(fac) \ | 
 |     xmlSchemaPCustomErr(pctxt, \ | 
 | 	XML_SCHEMAP_INVALID_FACET_VALUE, \ | 
 | 	WXS_BASIC_CAST fac, fac->node, \ | 
 | 	"The base type's facet is 'fixed', thus the value must not " \ | 
 | 	"differ", NULL); | 
 |  | 
 | static void | 
 | xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt, | 
 | 			xmlSchemaFacetPtr facet1, | 
 | 			xmlSchemaFacetPtr facet2, | 
 | 			int lessGreater, | 
 | 			int orEqual, | 
 | 			int ofBase) | 
 | { | 
 |     xmlChar *msg = NULL; | 
 |  | 
 |     msg = xmlStrdup(BAD_CAST "'"); | 
 |     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type)); | 
 |     msg = xmlStrcat(msg, BAD_CAST "' has to be"); | 
 |     if (lessGreater == 0) | 
 | 	msg = xmlStrcat(msg, BAD_CAST " equal to"); | 
 |     if (lessGreater == 1) | 
 | 	msg = xmlStrcat(msg, BAD_CAST " greater than"); | 
 |     else | 
 | 	msg = xmlStrcat(msg, BAD_CAST " less than"); | 
 |  | 
 |     if (orEqual) | 
 | 	msg = xmlStrcat(msg, BAD_CAST " or equal to"); | 
 |     msg = xmlStrcat(msg, BAD_CAST " '"); | 
 |     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type)); | 
 |     if (ofBase) | 
 | 	msg = xmlStrcat(msg, BAD_CAST "' of the base type"); | 
 |     else | 
 | 	msg = xmlStrcat(msg, BAD_CAST "'"); | 
 |  | 
 |     xmlSchemaPCustomErr(pctxt, | 
 | 	XML_SCHEMAP_INVALID_FACET_VALUE, | 
 | 	WXS_BASIC_CAST facet1, NULL, | 
 | 	(const char *) msg, NULL); | 
 |  | 
 |     if (msg != NULL) | 
 | 	xmlFree(msg); | 
 | } | 
 |  | 
 | /* | 
 | * xmlSchemaDeriveAndValidateFacets: | 
 | * | 
 | * Schema Component Constraint: Simple Type Restriction (Facets) | 
 | * (st-restrict-facets) | 
 | */ | 
 | static int | 
 | xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt, | 
 | 				 xmlSchemaTypePtr type) | 
 | { | 
 |     xmlSchemaTypePtr base = type->baseType; | 
 |     xmlSchemaFacetLinkPtr link, cur, last = NULL; | 
 |     xmlSchemaFacetPtr facet, bfacet, | 
 | 	flength = NULL, ftotdig = NULL, ffracdig = NULL, | 
 | 	fmaxlen = NULL, fminlen = NULL, /* facets of the current type */ | 
 | 	fmininc = NULL, fmaxinc = NULL, | 
 | 	fminexc = NULL, fmaxexc = NULL, | 
 | 	bflength = NULL, bftotdig = NULL, bffracdig = NULL, | 
 | 	bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */ | 
 | 	bfmininc = NULL, bfmaxinc = NULL, | 
 | 	bfminexc = NULL, bfmaxexc = NULL; | 
 |     int res; /* err = 0, fixedErr; */ | 
 |  | 
 |     /* | 
 |     * SPEC st-restrict-facets 1: | 
 |     * "The {variety} of R is the same as that of B." | 
 |     */ | 
 |     /* | 
 |     * SPEC st-restrict-facets 2: | 
 |     * "If {variety} is atomic, the {primitive type definition} | 
 |     * of R is the same as that of B." | 
 |     * | 
 |     * NOTE: we leave 1 & 2 out for now, since this will be | 
 |     * satisfied by the derivation process. | 
 |     * CONSTRUCTION TODO: Maybe needed if using a construction API. | 
 |     */ | 
 |     /* | 
 |     * SPEC st-restrict-facets 3: | 
 |     * "The {facets} of R are the union of S and the {facets} | 
 |     * of B, eliminating duplicates. To eliminate duplicates, | 
 |     * when a facet of the same kind occurs in both S and the | 
 |     * {facets} of B, the one in the {facets} of B is not | 
 |     * included, with the exception of enumeration and pattern | 
 |     * facets, for which multiple occurrences with distinct values | 
 |     * are allowed." | 
 |     */ | 
 |  | 
 |     if ((type->facetSet == NULL) && (base->facetSet == NULL)) | 
 | 	return (0); | 
 |  | 
 |     last = type->facetSet; | 
 |     if (last != NULL) | 
 | 	while (last->next != NULL) | 
 | 	    last = last->next; | 
 |  | 
 |     for (cur = type->facetSet; cur != NULL; cur = cur->next) { | 
 | 	facet = cur->facet; | 
 | 	switch (facet->type) { | 
 | 	    case XML_SCHEMA_FACET_LENGTH: | 
 | 		flength = facet; break; | 
 | 	    case XML_SCHEMA_FACET_MINLENGTH: | 
 | 		fminlen = facet; break; | 
 | 	    case XML_SCHEMA_FACET_MININCLUSIVE: | 
 | 		fmininc = facet; break; | 
 | 	    case XML_SCHEMA_FACET_MINEXCLUSIVE: | 
 | 		fminexc = facet; break; | 
 | 	    case XML_SCHEMA_FACET_MAXLENGTH: | 
 | 		fmaxlen = facet; break; | 
 | 	    case XML_SCHEMA_FACET_MAXINCLUSIVE: | 
 | 		fmaxinc = facet; break; | 
 | 	    case XML_SCHEMA_FACET_MAXEXCLUSIVE: | 
 | 		fmaxexc = facet; break; | 
 | 	    case XML_SCHEMA_FACET_TOTALDIGITS: | 
 | 		ftotdig = facet; break; | 
 | 	    case XML_SCHEMA_FACET_FRACTIONDIGITS: | 
 | 		ffracdig = facet; break; | 
 | 	    default: | 
 | 		break; | 
 | 	} | 
 |     } | 
 |     for (cur = base->facetSet; cur != NULL; cur = cur->next) { | 
 | 	facet = cur->facet; | 
 | 	switch (facet->type) { | 
 | 	    case XML_SCHEMA_FACET_LENGTH: | 
 | 		bflength = facet; break; | 
 | 	    case XML_SCHEMA_FACET_MINLENGTH: | 
 | 		bfminlen = facet; break; | 
 | 	    case XML_SCHEMA_FACET_MININCLUSIVE: | 
 | 		bfmininc = facet; break; | 
 | 	    case XML_SCHEMA_FACET_MINEXCLUSIVE: | 
 | 		bfminexc = facet; break; | 
 | 	    case XML_SCHEMA_FACET_MAXLENGTH: | 
 | 		bfmaxlen = facet; break; | 
 | 	    case XML_SCHEMA_FACET_MAXINCLUSIVE: | 
 | 		bfmaxinc = facet; break; | 
 | 	    case XML_SCHEMA_FACET_MAXEXCLUSIVE: | 
 | 		bfmaxexc = facet; break; | 
 | 	    case XML_SCHEMA_FACET_TOTALDIGITS: | 
 | 		bftotdig = facet; break; | 
 | 	    case XML_SCHEMA_FACET_FRACTIONDIGITS: | 
 | 		bffracdig = facet; break; | 
 | 	    default: | 
 | 		break; | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * length and minLength or maxLength (2.2) + (3.2) | 
 |     */ | 
 |     if (flength && (fminlen || fmaxlen)) { | 
 | 	FACET_RESTR_ERR(flength, "It is an error for both 'length' and " | 
 | 	    "either of 'minLength' or 'maxLength' to be specified on " | 
 | 	    "the same type definition") | 
 |     } | 
 |     /* | 
 |     * Mutual exclusions in the same derivation step. | 
 |     */ | 
 |     if ((fmaxinc) && (fmaxexc)) { | 
 | 	/* | 
 | 	* SCC "maxInclusive and maxExclusive" | 
 | 	*/ | 
 | 	FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc) | 
 |     } | 
 |     if ((fmininc) && (fminexc)) { | 
 | 	/* | 
 | 	* SCC "minInclusive and minExclusive" | 
 | 	*/ | 
 | 	FACET_RESTR_MUTUAL_ERR(fmininc, fminexc) | 
 |     } | 
 |  | 
 |     if (flength && bflength) { | 
 | 	/* | 
 | 	* SCC "length valid restriction" | 
 | 	* The values have to be equal. | 
 | 	*/ | 
 | 	res = xmlSchemaCompareValues(flength->val, bflength->val); | 
 | 	if (res == -2) | 
 | 	    goto internal_error; | 
 | 	if (res != 0) | 
 | 	    xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1); | 
 | 	if ((res != 0) && (bflength->fixed)) { | 
 | 	    FACET_RESTR_FIXED_ERR(flength) | 
 | 	} | 
 |  | 
 |     } | 
 |     if (fminlen && bfminlen) { | 
 | 	/* | 
 | 	* SCC "minLength valid restriction" | 
 | 	* minLength >= BASE minLength | 
 | 	*/ | 
 | 	res = xmlSchemaCompareValues(fminlen->val, bfminlen->val); | 
 | 	if (res == -2) | 
 | 	    goto internal_error; | 
 | 	if (res == -1) | 
 | 	    xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1); | 
 | 	if ((res != 0) && (bfminlen->fixed)) { | 
 | 	    FACET_RESTR_FIXED_ERR(fminlen) | 
 | 	} | 
 |     } | 
 |     if (fmaxlen && bfmaxlen) { | 
 | 	/* | 
 | 	* SCC "maxLength valid restriction" | 
 | 	* maxLength <= BASE minLength | 
 | 	*/ | 
 | 	res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val); | 
 | 	if (res == -2) | 
 | 	    goto internal_error; | 
 | 	if (res == 1) | 
 | 	    xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1); | 
 | 	if ((res != 0) && (bfmaxlen->fixed)) { | 
 | 	    FACET_RESTR_FIXED_ERR(fmaxlen) | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * SCC "length and minLength or maxLength" | 
 |     */ | 
 |     if (! flength) | 
 | 	flength = bflength; | 
 |     if (flength) { | 
 | 	if (! fminlen) | 
 | 	    fminlen = bfminlen; | 
 | 	if (fminlen) { | 
 | 	    /* (1.1) length >= minLength */ | 
 | 	    res = xmlSchemaCompareValues(flength->val, fminlen->val); | 
 | 	    if (res == -2) | 
 | 		goto internal_error; | 
 | 	    if (res == -1) | 
 | 		xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0); | 
 | 	} | 
 | 	if (! fmaxlen) | 
 | 	    fmaxlen = bfmaxlen; | 
 | 	if (fmaxlen) { | 
 | 	    /* (2.1) length <= maxLength */ | 
 | 	    res = xmlSchemaCompareValues(flength->val, fmaxlen->val); | 
 | 	    if (res == -2) | 
 | 		goto internal_error; | 
 | 	    if (res == 1) | 
 | 		xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0); | 
 | 	} | 
 |     } | 
 |     if (fmaxinc) { | 
 | 	/* | 
 | 	* "maxInclusive" | 
 | 	*/ | 
 | 	if (fmininc) { | 
 | 	    /* SCC "maxInclusive >= minInclusive" */ | 
 | 	    res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val); | 
 | 	    if (res == -2) | 
 | 		goto internal_error; | 
 | 	    if (res == -1) { | 
 | 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0); | 
 | 	    } | 
 | 	} | 
 | 	/* | 
 | 	* SCC "maxInclusive valid restriction" | 
 | 	*/ | 
 | 	if (bfmaxinc) { | 
 | 	    /* maxInclusive <= BASE maxInclusive */ | 
 | 	    res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val); | 
 | 	    if (res == -2) | 
 | 		goto internal_error; | 
 | 	    if (res == 1) | 
 | 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1); | 
 | 	    if ((res != 0) && (bfmaxinc->fixed)) { | 
 | 		FACET_RESTR_FIXED_ERR(fmaxinc) | 
 | 	    } | 
 | 	} | 
 | 	if (bfmaxexc) { | 
 | 	    /* maxInclusive < BASE maxExclusive */ | 
 | 	    res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val); | 
 | 	    if (res == -2) | 
 | 		goto internal_error; | 
 | 	    if (res != -1) { | 
 | 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1); | 
 | 	    } | 
 | 	} | 
 | 	if (bfmininc) { | 
 | 	    /* maxInclusive >= BASE minInclusive */ | 
 | 	    res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val); | 
 | 	    if (res == -2) | 
 | 		goto internal_error; | 
 | 	    if (res == -1) { | 
 | 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1); | 
 | 	    } | 
 | 	} | 
 | 	if (bfminexc) { | 
 | 	    /* maxInclusive > BASE minExclusive */ | 
 | 	    res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val); | 
 | 	    if (res == -2) | 
 | 		goto internal_error; | 
 | 	    if (res != 1) { | 
 | 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1); | 
 | 	    } | 
 | 	} | 
 |     } | 
 |     if (fmaxexc) { | 
 | 	/* | 
 | 	* "maxExclusive >= minExclusive" | 
 | 	*/ | 
 | 	if (fminexc) { | 
 | 	    res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val); | 
 | 	    if (res == -2) | 
 | 		goto internal_error; | 
 | 	    if (res == -1) { | 
 | 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0); | 
 | 	    } | 
 | 	} | 
 | 	/* | 
 | 	* "maxExclusive valid restriction" | 
 | 	*/ | 
 | 	if (bfmaxexc) { | 
 | 	    /* maxExclusive <= BASE maxExclusive */ | 
 | 	    res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val); | 
 | 	    if (res == -2) | 
 | 		goto internal_error; | 
 | 	    if (res == 1) { | 
 | 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1); | 
 | 	    } | 
 | 	    if ((res != 0) && (bfmaxexc->fixed)) { | 
 | 		FACET_RESTR_FIXED_ERR(fmaxexc) | 
 | 	    } | 
 | 	} | 
 | 	if (bfmaxinc) { | 
 | 	    /* maxExclusive <= BASE maxInclusive */ | 
 | 	    res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val); | 
 | 	    if (res == -2) | 
 | 		goto internal_error; | 
 | 	    if (res == 1) { | 
 | 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1); | 
 | 	    } | 
 | 	} | 
 | 	if (bfmininc) { | 
 | 	    /* maxExclusive > BASE minInclusive */ | 
 | 	    res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val); | 
 | 	    if (res == -2) | 
 | 		goto internal_error; | 
 | 	    if (res != 1) { | 
 | 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1); | 
 | 	    } | 
 | 	} | 
 | 	if (bfminexc) { | 
 | 	    /* maxExclusive > BASE minExclusive */ | 
 | 	    res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val); | 
 | 	    if (res == -2) | 
 | 		goto internal_error; | 
 | 	    if (res != 1) { | 
 | 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1); | 
 | 	    } | 
 | 	} | 
 |     } | 
 |     if (fminexc) { | 
 | 	/* | 
 | 	* "minExclusive < maxInclusive" | 
 | 	*/ | 
 | 	if (fmaxinc) { | 
 | 	    res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val); | 
 | 	    if (res == -2) | 
 | 		goto internal_error; | 
 | 	    if (res != -1) { | 
 | 		xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0); | 
 | 	    } | 
 | 	} | 
 | 	/* | 
 | 	* "minExclusive valid restriction" | 
 | 	*/ | 
 | 	if (bfminexc) { | 
 | 	    /* minExclusive >= BASE minExclusive */ | 
 | 	    res = xmlSchemaCompareValues(fminexc->val, bfminexc->val); | 
 | 	    if (res == -2) | 
 | 		goto internal_error; | 
 | 	    if (res == -1) { | 
 | 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1); | 
 | 	    } | 
 | 	    if ((res != 0) && (bfminexc->fixed)) { | 
 | 		FACET_RESTR_FIXED_ERR(fminexc) | 
 | 	    } | 
 | 	} | 
 | 	if (bfmaxinc) { | 
 | 	    /* minExclusive <= BASE maxInclusive */ | 
 | 	    res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val); | 
 | 	    if (res == -2) | 
 | 		goto internal_error; | 
 | 	    if (res == 1) { | 
 | 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1); | 
 | 	    } | 
 | 	} | 
 | 	if (bfmininc) { | 
 | 	    /* minExclusive >= BASE minInclusive */ | 
 | 	    res = xmlSchemaCompareValues(fminexc->val, bfmininc->val); | 
 | 	    if (res == -2) | 
 | 		goto internal_error; | 
 | 	    if (res == -1) { | 
 | 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1); | 
 | 	    } | 
 | 	} | 
 | 	if (bfmaxexc) { | 
 | 	    /* minExclusive < BASE maxExclusive */ | 
 | 	    res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val); | 
 | 	    if (res == -2) | 
 | 		goto internal_error; | 
 | 	    if (res != -1) { | 
 | 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1); | 
 | 	    } | 
 | 	} | 
 |     } | 
 |     if (fmininc) { | 
 | 	/* | 
 | 	* "minInclusive < maxExclusive" | 
 | 	*/ | 
 | 	if (fmaxexc) { | 
 | 	    res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val); | 
 | 	    if (res == -2) | 
 | 		goto internal_error; | 
 | 	    if (res != -1) { | 
 | 		xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0); | 
 | 	    } | 
 | 	} | 
 | 	/* | 
 | 	* "minExclusive valid restriction" | 
 | 	*/ | 
 | 	if (bfmininc) { | 
 | 	    /* minInclusive >= BASE minInclusive */ | 
 | 	    res = xmlSchemaCompareValues(fmininc->val, bfmininc->val); | 
 | 	    if (res == -2) | 
 | 		goto internal_error; | 
 | 	    if (res == -1) { | 
 | 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1); | 
 | 	    } | 
 | 	    if ((res != 0) && (bfmininc->fixed)) { | 
 | 		FACET_RESTR_FIXED_ERR(fmininc) | 
 | 	    } | 
 | 	} | 
 | 	if (bfmaxinc) { | 
 | 	    /* minInclusive <= BASE maxInclusive */ | 
 | 	    res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val); | 
 | 	    if (res == -2) | 
 | 		goto internal_error; | 
 | 	    if (res == 1) { | 
 | 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1); | 
 | 	    } | 
 | 	} | 
 | 	if (bfminexc) { | 
 | 	    /* minInclusive > BASE minExclusive */ | 
 | 	    res = xmlSchemaCompareValues(fmininc->val, bfminexc->val); | 
 | 	    if (res == -2) | 
 | 		goto internal_error; | 
 | 	    if (res != 1) | 
 | 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1); | 
 | 	} | 
 | 	if (bfmaxexc) { | 
 | 	    /* minInclusive < BASE maxExclusive */ | 
 | 	    res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val); | 
 | 	    if (res == -2) | 
 | 		goto internal_error; | 
 | 	    if (res != -1) | 
 | 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1); | 
 | 	} | 
 |     } | 
 |     if (ftotdig && bftotdig) { | 
 | 	/* | 
 | 	* SCC " totalDigits valid restriction" | 
 | 	* totalDigits <= BASE totalDigits | 
 | 	*/ | 
 | 	res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val); | 
 | 	if (res == -2) | 
 | 	    goto internal_error; | 
 | 	if (res == 1) | 
 | 	    xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig, | 
 | 	    -1, 1, 1); | 
 | 	if ((res != 0) && (bftotdig->fixed)) { | 
 | 	    FACET_RESTR_FIXED_ERR(ftotdig) | 
 | 	} | 
 |     } | 
 |     if (ffracdig && bffracdig) { | 
 | 	/* | 
 | 	* SCC  "fractionDigits valid restriction" | 
 | 	* fractionDigits <= BASE fractionDigits | 
 | 	*/ | 
 | 	res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val); | 
 | 	if (res == -2) | 
 | 	    goto internal_error; | 
 | 	if (res == 1) | 
 | 	    xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig, | 
 | 	    -1, 1, 1); | 
 | 	if ((res != 0) && (bffracdig->fixed)) { | 
 | 	    FACET_RESTR_FIXED_ERR(ffracdig) | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * SCC "fractionDigits less than or equal to totalDigits" | 
 |     */ | 
 |     if (! ftotdig) | 
 | 	ftotdig = bftotdig; | 
 |     if (! ffracdig) | 
 | 	ffracdig = bffracdig; | 
 |     if (ftotdig && ffracdig) { | 
 | 	res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val); | 
 | 	if (res == -2) | 
 | 	    goto internal_error; | 
 | 	if (res == 1) | 
 | 	    xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig, | 
 | 		-1, 1, 0); | 
 |     } | 
 |     /* | 
 |     * *Enumerations* won' be added here, since only the first set | 
 |     * of enumerations in the ancestor-or-self axis is used | 
 |     * for validation, plus we need to use the base type of those | 
 |     * enumerations for whitespace. | 
 |     * | 
 |     * *Patterns*: won't be add here, since they are ORed at | 
 |     * type level and ANDed at ancestor level. This will | 
 |     * happed during validation by walking the base axis | 
 |     * of the type. | 
 |     */ | 
 |     for (cur = base->facetSet; cur != NULL; cur = cur->next) { | 
 | 	bfacet = cur->facet; | 
 | 	/* | 
 | 	* Special handling of enumerations and patterns. | 
 | 	* TODO: hmm, they should not appear in the set, so remove this. | 
 | 	*/ | 
 | 	if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) || | 
 | 	    (bfacet->type == XML_SCHEMA_FACET_ENUMERATION)) | 
 | 	    continue; | 
 | 	/* | 
 | 	* Search for a duplicate facet in the current type. | 
 | 	*/ | 
 | 	link = type->facetSet; | 
 | 	/* err = 0; */ | 
 | 	/* fixedErr = 0; */ | 
 | 	while (link != NULL) { | 
 | 	    facet = link->facet; | 
 | 	    if (facet->type == bfacet->type) { | 
 | 		switch (facet->type) { | 
 | 		    case XML_SCHEMA_FACET_WHITESPACE: | 
 | 			/* | 
 | 			* The whitespace must be stronger. | 
 | 			*/ | 
 | 			if (facet->whitespace < bfacet->whitespace) { | 
 | 			    FACET_RESTR_ERR(facet, | 
 | 				"The 'whitespace' value has to be equal to " | 
 | 				"or stronger than the 'whitespace' value of " | 
 | 				"the base type") | 
 | 			} | 
 | 			if ((bfacet->fixed) && | 
 | 			    (facet->whitespace != bfacet->whitespace)) { | 
 | 			    FACET_RESTR_FIXED_ERR(facet) | 
 | 			} | 
 | 			break; | 
 | 		    default: | 
 | 			break; | 
 | 		} | 
 | 		/* Duplicate found. */ | 
 | 		break; | 
 | 	    } | 
 | 	    link = link->next; | 
 | 	} | 
 | 	/* | 
 | 	* If no duplicate was found: add the base types's facet | 
 | 	* to the set. | 
 | 	*/ | 
 | 	if (link == NULL) { | 
 | 	    link = (xmlSchemaFacetLinkPtr) | 
 | 		xmlMalloc(sizeof(xmlSchemaFacetLink)); | 
 | 	    if (link == NULL) { | 
 | 		xmlSchemaPErrMemory(pctxt, | 
 | 		    "deriving facets, creating a facet link", NULL); | 
 | 		return (-1); | 
 | 	    } | 
 | 	    link->facet = cur->facet; | 
 | 	    link->next = NULL; | 
 | 	    if (last == NULL) | 
 | 		type->facetSet = link; | 
 | 	    else | 
 | 		last->next = link; | 
 | 	    last = link; | 
 | 	} | 
 |  | 
 |     } | 
 |  | 
 |     return (0); | 
 | internal_error: | 
 |     PERROR_INT("xmlSchemaDeriveAndValidateFacets", | 
 | 	"an error occured"); | 
 |     return (-1); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt, | 
 | 					     xmlSchemaTypePtr type) | 
 | { | 
 |     xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink; | 
 |     /* | 
 |     * The actual value is then formed by replacing any union type | 
 |     * definition in the �explicit members� with the members of their | 
 |     * {member type definitions}, in order. | 
 |     * | 
 |     * TODO: There's a bug entry at | 
 |     * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html" | 
 |     * which indicates that we'll keep the union types the future. | 
 |     */ | 
 |     link = type->memberTypes; | 
 |     while (link != NULL) { | 
 |  | 
 | 	if (WXS_IS_TYPE_NOT_FIXED(link->type)) | 
 | 	    xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt); | 
 |  | 
 | 	if (WXS_IS_UNION(link->type)) { | 
 | 	    subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type); | 
 | 	    if (subLink != NULL) { | 
 | 		link->type = subLink->type; | 
 | 		if (subLink->next != NULL) { | 
 | 		    lastLink = link->next; | 
 | 		    subLink = subLink->next; | 
 | 		    prevLink = link; | 
 | 		    while (subLink != NULL) { | 
 | 			newLink = (xmlSchemaTypeLinkPtr) | 
 | 			    xmlMalloc(sizeof(xmlSchemaTypeLink)); | 
 | 			if (newLink == NULL) { | 
 | 			    xmlSchemaPErrMemory(pctxt, "allocating a type link", | 
 | 				NULL); | 
 | 			    return (-1); | 
 | 			} | 
 | 			newLink->type = subLink->type; | 
 | 			prevLink->next = newLink; | 
 | 			prevLink = newLink; | 
 | 			newLink->next = lastLink; | 
 |  | 
 | 			subLink = subLink->next; | 
 | 		    } | 
 | 		} | 
 | 	    } | 
 | 	} | 
 | 	link = link->next; | 
 |     } | 
 |     return (0); | 
 | } | 
 |  | 
 | static void | 
 | xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type) | 
 | { | 
 |     int has = 0, needVal = 0, normVal = 0; | 
 |  | 
 |     has	= (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0; | 
 |     if (has) { | 
 | 	needVal = (type->baseType->flags & | 
 | 	    XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0; | 
 | 	normVal = (type->baseType->flags & | 
 | 	    XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0; | 
 |     } | 
 |     if (type->facets != NULL) { | 
 | 	xmlSchemaFacetPtr fac; | 
 |  | 
 | 	for (fac = type->facets; fac != NULL; fac = fac->next) { | 
 | 	    switch (fac->type) { | 
 | 		case XML_SCHEMA_FACET_WHITESPACE: | 
 | 		    break; | 
 | 		case XML_SCHEMA_FACET_PATTERN: | 
 | 		    normVal = 1; | 
 | 		    has = 1; | 
 | 		    break; | 
 | 		case XML_SCHEMA_FACET_ENUMERATION: | 
 | 		    needVal = 1; | 
 | 		    normVal = 1; | 
 | 		    has = 1; | 
 | 		    break; | 
 | 		default: | 
 | 		    has = 1; | 
 | 		    break; | 
 | 	    } | 
 | 	} | 
 |     } | 
 |     if (normVal) | 
 | 	type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED; | 
 |     if (needVal) | 
 | 	type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE; | 
 |     if (has) | 
 | 	type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS; | 
 |  | 
 |     if (has && (! needVal) && WXS_IS_ATOMIC(type)) { | 
 | 	xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type); | 
 | 	/* | 
 | 	* OPTIMIZE VAL TODO: Some facets need a computed value. | 
 | 	*/ | 
 | 	if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) && | 
 | 	    (prim->builtInType != XML_SCHEMAS_STRING)) { | 
 | 	    type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE; | 
 | 	} | 
 |     } | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type) | 
 | { | 
 |  | 
 |  | 
 |     /* | 
 |     * Evaluate the whitespace-facet value. | 
 |     */ | 
 |     if (WXS_IS_LIST(type)) { | 
 | 	type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE; | 
 | 	return (0); | 
 |     } else if (WXS_IS_UNION(type)) | 
 | 	return (0); | 
 |  | 
 |     if (type->facetSet != NULL) { | 
 | 	xmlSchemaFacetLinkPtr lin; | 
 |  | 
 | 	for (lin = type->facetSet; lin != NULL; lin = lin->next) { | 
 | 	    if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) { | 
 | 		switch (lin->facet->whitespace) { | 
 | 		case XML_SCHEMAS_FACET_PRESERVE: | 
 | 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE; | 
 | 		    break; | 
 | 		case XML_SCHEMAS_FACET_REPLACE: | 
 | 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE; | 
 | 		    break; | 
 | 		case XML_SCHEMAS_FACET_COLLAPSE: | 
 | 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE; | 
 | 		    break; | 
 | 		default: | 
 | 		    return (-1); | 
 | 		} | 
 | 		return (0); | 
 | 	    } | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * For all �atomic� datatypes other than string (and types �derived� | 
 |     * by �restriction� from it) the value of whiteSpace is fixed to | 
 |     * collapse | 
 |     */ | 
 |     { | 
 | 	xmlSchemaTypePtr anc; | 
 |  | 
 | 	for (anc = type->baseType; anc != NULL && | 
 | 		anc->builtInType != XML_SCHEMAS_ANYTYPE; | 
 | 		anc = anc->baseType) { | 
 |  | 
 | 	    if (anc->type == XML_SCHEMA_TYPE_BASIC) { | 
 | 		if (anc->builtInType == XML_SCHEMAS_NORMSTRING) { | 
 | 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE; | 
 |  | 
 | 		} else if ((anc->builtInType == XML_SCHEMAS_STRING) || | 
 | 		    (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) { | 
 | 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE; | 
 |  | 
 | 		} else | 
 | 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE; | 
 | 		break; | 
 | 	    } | 
 | 	} | 
 |     } | 
 |     return (0); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt, | 
 | 			  xmlSchemaTypePtr type) | 
 | { | 
 |     if (type->type != XML_SCHEMA_TYPE_SIMPLE) | 
 | 	return(0); | 
 |     if (! WXS_IS_TYPE_NOT_FIXED_1(type)) | 
 | 	return(0); | 
 |     type->flags |= XML_SCHEMAS_TYPE_FIXUP_1; | 
 |  | 
 |     if (WXS_IS_LIST(type)) { | 
 | 	/* | 
 | 	* Corresponds to <simpleType><list>... | 
 | 	*/ | 
 | 	if (type->subtypes == NULL) { | 
 | 	    /* | 
 | 	    * This one is really needed, so get out. | 
 | 	    */ | 
 | 	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne", | 
 | 		"list type has no item-type assigned"); | 
 | 	    return(-1); | 
 | 	} | 
 |     } else if (WXS_IS_UNION(type)) { | 
 | 	/* | 
 | 	* Corresponds to <simpleType><union>... | 
 | 	*/ | 
 | 	if (type->memberTypes == NULL) { | 
 | 	    /* | 
 | 	    * This one is really needed, so get out. | 
 | 	    */ | 
 | 	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne", | 
 | 		"union type has no member-types assigned"); | 
 | 	    return(-1); | 
 | 	} | 
 |     } else { | 
 | 	/* | 
 | 	* Corresponds to <simpleType><restriction>... | 
 | 	*/ | 
 | 	if (type->baseType == NULL) { | 
 | 	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne", | 
 | 		"type has no base-type assigned"); | 
 | 	    return(-1); | 
 | 	} | 
 | 	if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType)) | 
 | 	    if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1) | 
 | 		return(-1); | 
 | 	/* | 
 | 	* Variety | 
 | 	* If the <restriction> alternative is chosen, then the | 
 | 	* {variety} of the {base type definition}. | 
 | 	*/ | 
 | 	if (WXS_IS_ATOMIC(type->baseType)) | 
 | 	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC; | 
 | 	else if (WXS_IS_LIST(type->baseType)) { | 
 | 	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST; | 
 | 	    /* | 
 | 	    * Inherit the itemType. | 
 | 	    */ | 
 | 	    type->subtypes = type->baseType->subtypes; | 
 | 	} else if (WXS_IS_UNION(type->baseType)) { | 
 | 	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION; | 
 | 	    /* | 
 | 	    * NOTE that we won't assign the memberTypes of the base, | 
 | 	    * since this will make trouble when freeing them; we will | 
 | 	    * use a lookup function to access them instead. | 
 | 	    */ | 
 | 	} | 
 |     } | 
 |     return(0); | 
 | } | 
 |  | 
 | #ifdef DEBUG_TYPE | 
 | static void | 
 | xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt, | 
 | 		       xmlSchemaTypePtr type) | 
 | { | 
 |     if (type->node != NULL) { | 
 |         xmlGenericError(xmlGenericErrorContext, | 
 |                         "Type of %s : %s:%d :", name, | 
 |                         type->node->doc->URL, | 
 |                         xmlGetLineNo(type->node)); | 
 |     } else { | 
 |         xmlGenericError(xmlGenericErrorContext, "Type of %s :", name); | 
 |     } | 
 |     if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) { | 
 | 	switch (type->contentType) { | 
 | 	    case XML_SCHEMA_CONTENT_SIMPLE: | 
 | 		xmlGenericError(xmlGenericErrorContext, "simple\n"); | 
 | 		break; | 
 | 	    case XML_SCHEMA_CONTENT_ELEMENTS: | 
 | 		xmlGenericError(xmlGenericErrorContext, "elements\n"); | 
 | 		break; | 
 | 	    case XML_SCHEMA_CONTENT_UNKNOWN: | 
 | 		xmlGenericError(xmlGenericErrorContext, "unknown !!!\n"); | 
 | 		break; | 
 | 	    case XML_SCHEMA_CONTENT_EMPTY: | 
 | 		xmlGenericError(xmlGenericErrorContext, "empty\n"); | 
 | 		break; | 
 | 	    case XML_SCHEMA_CONTENT_MIXED: | 
 | 		if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr) | 
 | 		    type->subtypes)) | 
 | 		    xmlGenericError(xmlGenericErrorContext, | 
 | 			"mixed as emptiable particle\n"); | 
 | 		else | 
 | 		    xmlGenericError(xmlGenericErrorContext, "mixed\n"); | 
 | 		break; | 
 | 		/* Removed, since not used. */ | 
 | 		/* | 
 | 		case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS: | 
 | 		xmlGenericError(xmlGenericErrorContext, "mixed or elems\n"); | 
 | 		break; | 
 | 		*/ | 
 | 	    case XML_SCHEMA_CONTENT_BASIC: | 
 | 		xmlGenericError(xmlGenericErrorContext, "basic\n"); | 
 | 		break; | 
 | 	    default: | 
 | 		xmlGenericError(xmlGenericErrorContext, | 
 | 		    "not registered !!!\n"); | 
 | 		break; | 
 | 	} | 
 |     } | 
 | } | 
 | #endif | 
 |  | 
 | /* | 
 | * 3.14.6 Constraints on Simple Type Definition Schema Components | 
 | */ | 
 | static int | 
 | xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt, | 
 | 				 xmlSchemaTypePtr type) | 
 | { | 
 |     int res, olderrs = pctxt->nberrors; | 
 |  | 
 |     if (type->type != XML_SCHEMA_TYPE_SIMPLE) | 
 | 	return(-1); | 
 |  | 
 |     if (! WXS_IS_TYPE_NOT_FIXED(type)) | 
 | 	return(0); | 
 |  | 
 |     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED; | 
 |     type->contentType = XML_SCHEMA_CONTENT_SIMPLE; | 
 |  | 
 |     if (type->baseType == NULL) { | 
 | 	PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo", | 
 | 	    "missing baseType"); | 
 | 	goto exit_failure; | 
 |     } | 
 |     if (WXS_IS_TYPE_NOT_FIXED(type->baseType)) | 
 | 	xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt); | 
 |     /* | 
 |     * If a member type of a union is a union itself, we need to substitute | 
 |     * that member type for its member types. | 
 |     * NOTE that this might change in WXS 1.1; i.e. we will keep the union | 
 |     * types in WXS 1.1. | 
 |     */ | 
 |     if ((type->memberTypes != NULL) && | 
 | 	(xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1)) | 
 | 	return(-1); | 
 |     /* | 
 |     * SPEC src-simple-type 1 | 
 |     * "The corresponding simple type definition, if any, must satisfy | 
 |     * the conditions set out in Constraints on Simple Type Definition | 
 |     * Schema Components (�3.14.6)." | 
 |     */ | 
 |     /* | 
 |     * Schema Component Constraint: Simple Type Definition Properties Correct | 
 |     * (st-props-correct) | 
 |     */ | 
 |     res = xmlSchemaCheckSTPropsCorrect(pctxt, type); | 
 |     HFAILURE HERROR | 
 |     /* | 
 |     * Schema Component Constraint: Derivation Valid (Restriction, Simple) | 
 |     * (cos-st-restricts) | 
 |     */ | 
 |     res = xmlSchemaCheckCOSSTRestricts(pctxt, type); | 
 |     HFAILURE HERROR | 
 |     /* | 
 |     * TODO: Removed the error report, since it got annoying to get an | 
 |     * extra error report, if anything failed until now. | 
 |     * Enable this if needed. | 
 |     * | 
 |     * xmlSchemaPErr(ctxt, type->node, | 
 |     *    XML_SCHEMAP_SRC_SIMPLE_TYPE_1, | 
 |     *    "Simple type '%s' does not satisfy the constraints " | 
 |     *    "on simple type definitions.\n", | 
 |     *    type->name, NULL); | 
 |     */ | 
 |     /* | 
 |     * Schema Component Constraint: Simple Type Restriction (Facets) | 
 |     * (st-restrict-facets) | 
 |     */ | 
 |     res = xmlSchemaCheckFacetValues(type, pctxt); | 
 |     HFAILURE HERROR | 
 |     if ((type->facetSet != NULL) || | 
 | 	(type->baseType->facetSet != NULL)) { | 
 | 	res = xmlSchemaDeriveAndValidateFacets(pctxt, type); | 
 | 	HFAILURE HERROR | 
 |     } | 
 |     /* | 
 |     * Whitespace value. | 
 |     */ | 
 |     res = xmlSchemaTypeFixupWhitespace(type); | 
 |     HFAILURE HERROR | 
 |     xmlSchemaTypeFixupOptimFacets(type); | 
 |  | 
 | exit_error: | 
 | #ifdef DEBUG_TYPE | 
 |     xmlSchemaDebugFixedType(pctxt, type); | 
 | #endif | 
 |     if (olderrs != pctxt->nberrors) | 
 | 	return(pctxt->err); | 
 |     return(0); | 
 |  | 
 | exit_failure: | 
 | #ifdef DEBUG_TYPE | 
 |     xmlSchemaDebugFixedType(pctxt, type); | 
 | #endif | 
 |     return(-1); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt, | 
 | 			  xmlSchemaTypePtr type) | 
 | { | 
 |     int res = 0, olderrs = pctxt->nberrors; | 
 |     xmlSchemaTypePtr baseType = type->baseType; | 
 |  | 
 |     if (! WXS_IS_TYPE_NOT_FIXED(type)) | 
 | 	return(0); | 
 |     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED; | 
 |     if (baseType == NULL) { | 
 | 	PERROR_INT("xmlSchemaFixupComplexType", | 
 | 	    "missing baseType"); | 
 | 	goto exit_failure; | 
 |     } | 
 |     /* | 
 |     * Fixup the base type. | 
 |     */ | 
 |     if (WXS_IS_TYPE_NOT_FIXED(baseType)) | 
 | 	xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt); | 
 |     if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) { | 
 | 	/* | 
 | 	* Skip fixup if the base type is invalid. | 
 | 	* TODO: Generate a warning! | 
 | 	*/ | 
 | 	return(0); | 
 |     } | 
 |     /* | 
 |     * This basically checks if the base type can be derived. | 
 |     */ | 
 |     res = xmlSchemaCheckSRCCT(pctxt, type); | 
 |     HFAILURE HERROR | 
 |     /* | 
 |     * Fixup the content type. | 
 |     */ | 
 |     if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) { | 
 | 	/* | 
 | 	* Corresponds to <complexType><simpleContent>... | 
 | 	*/ | 
 | 	if ((WXS_IS_COMPLEX(baseType)) && | 
 | 	    (baseType->contentTypeDef != NULL) && | 
 | 	    (WXS_IS_RESTRICTION(type))) { | 
 | 	    xmlSchemaTypePtr contentBase, content; | 
 | #ifdef ENABLE_NAMED_LOCALS | 
 | 	    char buf[30]; | 
 | 	    const xmlChar *tmpname; | 
 | #endif | 
 | 	    /* | 
 | 	    * SPEC (1) If <restriction> + base type is <complexType>, | 
 | 	    * "whose own {content type} is a simple type..." | 
 | 	    */ | 
 | 	    if (type->contentTypeDef != NULL) { | 
 | 		/* | 
 | 		* SPEC (1.1) "the simple type definition corresponding to the | 
 | 		* <simpleType> among the [children] of <restriction> if there | 
 | 		* is one;" | 
 | 		* Note that this "<simpleType> among the [children]" was put | 
 | 		* into ->contentTypeDef during parsing. | 
 | 		*/ | 
 | 		contentBase = type->contentTypeDef; | 
 | 		type->contentTypeDef = NULL; | 
 | 	    } else { | 
 | 		/* | 
 | 		* (1.2) "...otherwise (<restriction> has no <simpleType> | 
 | 		* among its [children]), the simple type definition which | 
 | 		* is the {content type} of the ... base type." | 
 | 		*/ | 
 | 		contentBase = baseType->contentTypeDef; | 
 | 	    } | 
 | 	    /* | 
 | 	    * SPEC | 
 | 	    * "... a simple type definition which restricts the simple | 
 | 	    * type definition identified in clause 1.1 or clause 1.2 | 
 | 	    * with a set of facet components" | 
 | 	    * | 
 | 	    * Create the anonymous simple type, which will be the content | 
 | 	    * type of the complex type. | 
 | 	    */ | 
 | #ifdef ENABLE_NAMED_LOCALS | 
 | 	    snprintf(buf, 29, "#scST%d", ++(pctxt->counter)); | 
 | 	    tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1); | 
 | 	    content = xmlSchemaAddType(pctxt, pctxt->schema, | 
 | 		XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace, | 
 | 		type->node, 0); | 
 | #else | 
 | 	    content = xmlSchemaAddType(pctxt, pctxt->schema, | 
 | 		XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace, | 
 | 		type->node, 0); | 
 | #endif | 
 | 	    if (content == NULL) | 
 | 		goto exit_failure; | 
 | 	    /* | 
 | 	    * We will use the same node as for the <complexType> | 
 | 	    * to have it somehow anchored in the schema doc. | 
 | 	    */ | 
 | 	    content->type = XML_SCHEMA_TYPE_SIMPLE; | 
 | 	    content->baseType = contentBase; | 
 | 	    /* | 
 | 	    * Move the facets, previously anchored on the | 
 | 	    * complexType during parsing. | 
 | 	    */ | 
 | 	    content->facets = type->facets; | 
 | 	    type->facets = NULL; | 
 | 	    content->facetSet = type->facetSet; | 
 | 	    type->facetSet = NULL; | 
 |  | 
 | 	    type->contentTypeDef = content; | 
 | 	    if (WXS_IS_TYPE_NOT_FIXED(contentBase)) | 
 | 		xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt); | 
 | 	    /* | 
 | 	    * Fixup the newly created type. We don't need to check | 
 | 	    * for circularity here. | 
 | 	    */ | 
 | 	    res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content); | 
 | 	    HFAILURE HERROR | 
 | 	    res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content); | 
 | 	    HFAILURE HERROR | 
 |  | 
 | 	} else if ((WXS_IS_COMPLEX(baseType)) && | 
 | 	    (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) && | 
 | 	    (WXS_IS_RESTRICTION(type))) { | 
 | 	    /* | 
 | 	    * SPEC (2) If <restriction> + base is a mixed <complexType> with | 
 | 	    * an emptiable particle, then a simple type definition which | 
 | 	    * restricts the <restriction>'s <simpleType> child. | 
 | 	    */ | 
 | 	    if ((type->contentTypeDef == NULL) || | 
 | 		(type->contentTypeDef->baseType == NULL)) { | 
 | 		/* | 
 | 		* TODO: Check if this ever happens. | 
 | 		*/ | 
 | 		xmlSchemaPCustomErr(pctxt, | 
 | 		    XML_SCHEMAP_INTERNAL, | 
 | 		    WXS_BASIC_CAST type, NULL, | 
 | 		    "Internal error: xmlSchemaTypeFixup, " | 
 | 		    "complex type '%s': the <simpleContent><restriction> " | 
 | 		    "is missing a <simpleType> child, but was not catched " | 
 | 		    "by xmlSchemaCheckSRCCT()", type->name); | 
 | 		goto exit_failure; | 
 | 	    } | 
 | 	} else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) { | 
 | 	    /* | 
 | 	    * SPEC (3) If <extension> + base is <complexType> with | 
 | 	    * <simpleType> content, "...then the {content type} of that | 
 | 	    * complex type definition" | 
 | 	    */ | 
 | 	    if (baseType->contentTypeDef == NULL) { | 
 | 		/* | 
 | 		* TODO: Check if this ever happens. xmlSchemaCheckSRCCT | 
 | 		* should have catched this already. | 
 | 		*/ | 
 | 		xmlSchemaPCustomErr(pctxt, | 
 | 		    XML_SCHEMAP_INTERNAL, | 
 | 		    WXS_BASIC_CAST type, NULL, | 
 | 		    "Internal error: xmlSchemaTypeFixup, " | 
 | 		    "complex type '%s': the <extension>ed base type is " | 
 | 		    "a complex type with no simple content type", | 
 | 		    type->name); | 
 | 		goto exit_failure; | 
 | 	    } | 
 | 	    type->contentTypeDef = baseType->contentTypeDef; | 
 | 	} else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) { | 
 | 	    /* | 
 | 	    * SPEC (4) <extension> + base is <simpleType> | 
 | 	    * "... then that simple type definition" | 
 | 	    */ | 
 | 	    type->contentTypeDef = baseType; | 
 | 	} else { | 
 | 	    /* | 
 | 	    * TODO: Check if this ever happens. | 
 | 	    */ | 
 | 	    xmlSchemaPCustomErr(pctxt, | 
 | 		XML_SCHEMAP_INTERNAL, | 
 | 		WXS_BASIC_CAST type, NULL, | 
 | 		"Internal error: xmlSchemaTypeFixup, " | 
 | 		"complex type '%s' with <simpleContent>: unhandled " | 
 | 		"derivation case", type->name); | 
 | 	    goto exit_failure; | 
 | 	} | 
 |     } else { | 
 | 	int dummySequence = 0; | 
 | 	xmlSchemaParticlePtr particle = | 
 | 	    (xmlSchemaParticlePtr) type->subtypes; | 
 | 	/* | 
 | 	* Corresponds to <complexType><complexContent>... | 
 | 	* | 
 | 	* NOTE that the effective mixed was already set during parsing of | 
 | 	* <complexType> and <complexContent>; its flag value is | 
 | 	* XML_SCHEMAS_TYPE_MIXED. | 
 | 	* | 
 | 	* Compute the "effective content": | 
 | 	* (2.1.1) + (2.1.2) + (2.1.3) | 
 | 	*/ | 
 | 	if ((particle == NULL) || | 
 | 	    ((particle->type == XML_SCHEMA_TYPE_PARTICLE) && | 
 | 	    ((particle->children->type == XML_SCHEMA_TYPE_ALL) || | 
 | 	    (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) || | 
 | 	    ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) && | 
 | 	    (particle->minOccurs == 0))) && | 
 | 	    ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) { | 
 | 	    if (type->flags & XML_SCHEMAS_TYPE_MIXED) { | 
 | 		/* | 
 | 		* SPEC (2.1.4) "If the �effective mixed� is true, then | 
 | 		* a particle whose properties are as follows:..." | 
 | 		* | 
 | 		* Empty sequence model group with | 
 | 		* minOccurs/maxOccurs = 1 (i.e. a "particle emptiable"). | 
 | 		* NOTE that we sill assign it the <complexType> node to | 
 | 		* somehow anchor it in the doc. | 
 | 		*/ | 
 | 		if ((particle == NULL) || | 
 | 		    (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) { | 
 | 		    /* | 
 | 		    * Create the particle. | 
 | 		    */ | 
 | 		    particle = xmlSchemaAddParticle(pctxt, | 
 | 			type->node, 1, 1); | 
 | 		    if (particle == NULL) | 
 | 			goto exit_failure; | 
 | 		    /* | 
 | 		    * Create the model group. | 
 | 		    */ /* URGENT TODO: avoid adding to pending items. */ | 
 | 		    particle->children = (xmlSchemaTreeItemPtr) | 
 | 			xmlSchemaAddModelGroup(pctxt, pctxt->schema, | 
 | 			XML_SCHEMA_TYPE_SEQUENCE, type->node); | 
 | 		    if (particle->children == NULL) | 
 | 			goto exit_failure; | 
 |  | 
 | 		    type->subtypes = (xmlSchemaTypePtr) particle; | 
 | 		} | 
 | 		dummySequence = 1; | 
 | 		type->contentType = XML_SCHEMA_CONTENT_ELEMENTS; | 
 | 	    } else { | 
 | 		/* | 
 | 		* SPEC (2.1.5) "otherwise empty" | 
 | 		*/ | 
 | 		type->contentType = XML_SCHEMA_CONTENT_EMPTY; | 
 | 	    } | 
 | 	} else { | 
 | 	    /* | 
 | 	    * SPEC (2.2) "otherwise the particle corresponding to the | 
 | 	    * <all>, <choice>, <group> or <sequence> among the | 
 | 	    * [children]." | 
 | 	    */ | 
 | 	    type->contentType = XML_SCHEMA_CONTENT_ELEMENTS; | 
 | 	} | 
 | 	/* | 
 | 	* Compute the "content type". | 
 | 	*/ | 
 | 	if (WXS_IS_RESTRICTION(type)) { | 
 | 	    /* | 
 | 	    * SPEC (3.1) "If <restriction>..." | 
 | 	    * (3.1.1) + (3.1.2) */ | 
 | 	    if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) { | 
 | 		if (type->flags & XML_SCHEMAS_TYPE_MIXED) | 
 | 		    type->contentType = XML_SCHEMA_CONTENT_MIXED; | 
 | 	    } | 
 | 	} else { | 
 | 	    /* | 
 | 	    * SPEC (3.2) "If <extension>..." | 
 | 	    */ | 
 | 	    if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) { | 
 | 		/* | 
 | 		* SPEC (3.2.1) | 
 | 		* "If the �effective content� is empty, then the | 
 | 		*  {content type} of the [...] base ..." | 
 | 		*/ | 
 | 		type->contentType = baseType->contentType; | 
 | 		type->subtypes = baseType->subtypes; | 
 | 		/* | 
 | 		* Fixes bug #347316: | 
 | 		* This is the case when the base type has a simple | 
 | 		* type definition as content. | 
 | 		*/ | 
 | 		type->contentTypeDef = baseType->contentTypeDef; | 
 | 		/* | 
 | 		* NOTE that the effective mixed is ignored here. | 
 | 		*/ | 
 | 	    } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) { | 
 | 		/* | 
 | 		* SPEC (3.2.2) | 
 | 		*/ | 
 | 		if (type->flags & XML_SCHEMAS_TYPE_MIXED) | 
 | 		    type->contentType = XML_SCHEMA_CONTENT_MIXED; | 
 | 	    } else { | 
 | 		/* | 
 | 		* SPEC (3.2.3) | 
 | 		*/ | 
 | 		if (type->flags & XML_SCHEMAS_TYPE_MIXED) | 
 | 		    type->contentType = XML_SCHEMA_CONTENT_MIXED; | 
 | 		    /* | 
 | 		    * "A model group whose {compositor} is sequence and whose | 
 | 		    * {particles} are..." | 
 | 		    */ | 
 | 		if ((WXS_TYPE_PARTICLE(type) != NULL) && | 
 | 		    (WXS_TYPE_PARTICLE_TERM(type) != NULL) && | 
 | 		    ((WXS_TYPE_PARTICLE_TERM(type))->type == | 
 | 			XML_SCHEMA_TYPE_ALL)) | 
 | 		{ | 
 | 		    /* | 
 | 		    * SPEC cos-all-limited (1) | 
 | 		    */ | 
 | 		    xmlSchemaCustomErr(ACTXT_CAST pctxt, | 
 | 			/* TODO: error code */ | 
 | 			XML_SCHEMAP_COS_ALL_LIMITED, | 
 | 			WXS_ITEM_NODE(type), NULL, | 
 | 			"The type has an 'all' model group in its " | 
 | 			"{content type} and thus cannot be derived from " | 
 | 			"a non-empty type, since this would produce a " | 
 | 			"'sequence' model group containing the 'all' " | 
 | 			"model group; 'all' model groups are not " | 
 | 			"allowed to appear inside other model groups", | 
 | 			NULL, NULL); | 
 |  | 
 | 		} else if ((WXS_TYPE_PARTICLE(baseType) != NULL) && | 
 | 		    (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) && | 
 | 		    ((WXS_TYPE_PARTICLE_TERM(baseType))->type == | 
 | 			XML_SCHEMA_TYPE_ALL)) | 
 | 		{ | 
 | 		    /* | 
 | 		    * SPEC cos-all-limited (1) | 
 | 		    */ | 
 | 		    xmlSchemaCustomErr(ACTXT_CAST pctxt, | 
 | 			/* TODO: error code */ | 
 | 			XML_SCHEMAP_COS_ALL_LIMITED, | 
 | 			WXS_ITEM_NODE(type), NULL, | 
 | 			"A type cannot be derived by extension from a type " | 
 | 			"which has an 'all' model group in its " | 
 | 			"{content type}, since this would produce a " | 
 | 			"'sequence' model group containing the 'all' " | 
 | 			"model group; 'all' model groups are not " | 
 | 			"allowed to appear inside other model groups", | 
 | 			NULL, NULL); | 
 |  | 
 | 		} else if (! dummySequence) { | 
 | 		    xmlSchemaTreeItemPtr effectiveContent = | 
 | 			(xmlSchemaTreeItemPtr) type->subtypes; | 
 | 		    /* | 
 | 		    * Create the particle. | 
 | 		    */ | 
 | 		    particle = xmlSchemaAddParticle(pctxt, | 
 | 			type->node, 1, 1); | 
 | 		    if (particle == NULL) | 
 | 			goto exit_failure; | 
 | 		    /* | 
 | 		    * Create the "sequence" model group. | 
 | 		    */ | 
 | 		    particle->children = (xmlSchemaTreeItemPtr) | 
 | 			xmlSchemaAddModelGroup(pctxt, pctxt->schema, | 
 | 			XML_SCHEMA_TYPE_SEQUENCE, type->node); | 
 | 		    if (particle->children == NULL) | 
 | 			goto exit_failure; | 
 | 		    WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle; | 
 | 		    /* | 
 | 		    * SPEC "the particle of the {content type} of | 
 | 		    * the ... base ..." | 
 | 		    * Create a duplicate of the base type's particle | 
 | 		    * and assign its "term" to it. | 
 | 		    */ | 
 | 		    particle->children->children = | 
 | 			(xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt, | 
 | 			type->node, | 
 | 			((xmlSchemaParticlePtr) type->subtypes)->minOccurs, | 
 | 			((xmlSchemaParticlePtr) type->subtypes)->maxOccurs); | 
 | 		    if (particle->children->children == NULL) | 
 | 			goto exit_failure; | 
 | 		    particle = (xmlSchemaParticlePtr) | 
 | 			particle->children->children; | 
 | 		    particle->children = | 
 | 			((xmlSchemaParticlePtr) baseType->subtypes)->children; | 
 | 		    /* | 
 | 		    * SPEC "followed by the �effective content�." | 
 | 		    */ | 
 | 		    particle->next = effectiveContent; | 
 | 		    /* | 
 | 		    * This all will result in: | 
 | 		    * new-particle | 
 | 		    *   --> new-sequence( | 
 | 		    *         new-particle | 
 | 		    *           --> base-model, | 
 | 		    *         this-particle | 
 | 		    *	        --> this-model | 
 | 		    *	    ) | 
 | 		    */ | 
 | 		} else { | 
 | 		    /* | 
 | 		    * This is the case when there is already an empty | 
 | 		    * <sequence> with minOccurs==maxOccurs==1. | 
 | 		    * Just add the base types's content type. | 
 | 		    * NOTE that, although we miss to add an intermediate | 
 | 		    * <sequence>, this should produce no difference to | 
 | 		    * neither the regex compilation of the content model, | 
 | 		    * nor to the complex type contraints. | 
 | 		    */ | 
 | 		    particle->children->children = | 
 | 			(xmlSchemaTreeItemPtr) baseType->subtypes; | 
 | 		} | 
 | 	    } | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * Now fixup attribute uses: | 
 |     *   - expand attr. group references | 
 |     *     - intersect attribute wildcards | 
 |     *   - inherit attribute uses of the base type | 
 |     *   - inherit or union attr. wildcards if extending | 
 |     *   - apply attr. use prohibitions if restricting | 
 |     */ | 
 |     res = xmlSchemaFixupTypeAttributeUses(pctxt, type); | 
 |     HFAILURE HERROR | 
 |     /* | 
 |     * Apply the complex type component constraints; this will not | 
 |     * check attributes, since this is done in | 
 |     * xmlSchemaFixupTypeAttributeUses(). | 
 |     */ | 
 |     res = xmlSchemaCheckCTComponent(pctxt, type); | 
 |     HFAILURE HERROR | 
 |  | 
 | #ifdef DEBUG_TYPE | 
 |     xmlSchemaDebugFixedType(pctxt, type); | 
 | #endif | 
 |     if (olderrs != pctxt->nberrors) | 
 | 	return(pctxt->err); | 
 |     else | 
 | 	return(0); | 
 |  | 
 | exit_error: | 
 |     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID; | 
 | #ifdef DEBUG_TYPE | 
 |     xmlSchemaDebugFixedType(pctxt, type); | 
 | #endif | 
 |     return(pctxt->err); | 
 |  | 
 | exit_failure: | 
 |     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID; | 
 | #ifdef DEBUG_TYPE | 
 |     xmlSchemaDebugFixedType(pctxt, type); | 
 | #endif | 
 |     return(-1); | 
 | } | 
 |  | 
 |  | 
 | /** | 
 |  * xmlSchemaTypeFixup: | 
 |  * @typeDecl:  the schema type definition | 
 |  * @ctxt:  the schema parser context | 
 |  * | 
 |  * Fixes the content model of the type. | 
 |  * URGENT TODO: We need an int result! | 
 |  */ | 
 | static int | 
 | xmlSchemaTypeFixup(xmlSchemaTypePtr type, | 
 |                    xmlSchemaAbstractCtxtPtr actxt) | 
 | { | 
 |     if (type == NULL) | 
 |         return(0); | 
 |     if (actxt->type != XML_SCHEMA_CTXT_PARSER) { | 
 | 	AERROR_INT("xmlSchemaTypeFixup", | 
 | 	    "this function needs a parser context"); | 
 | 	return(-1); | 
 |     } | 
 |     if (! WXS_IS_TYPE_NOT_FIXED(type)) | 
 | 	return(0); | 
 |     if (type->type == XML_SCHEMA_TYPE_COMPLEX) | 
 | 	return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type)); | 
 |     else if (type->type == XML_SCHEMA_TYPE_SIMPLE) | 
 | 	return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type)); | 
 |     return(0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaCheckFacet: | 
 |  * @facet:  the facet | 
 |  * @typeDecl:  the schema type definition | 
 |  * @pctxt:  the schema parser context or NULL | 
 |  * @name: the optional name of the type | 
 |  * | 
 |  * Checks and computes the values of facets. | 
 |  * | 
 |  * Returns 0 if valid, a positive error code if not valid and | 
 |  *         -1 in case of an internal or API error. | 
 |  */ | 
 | int | 
 | xmlSchemaCheckFacet(xmlSchemaFacetPtr facet, | 
 |                     xmlSchemaTypePtr typeDecl, | 
 |                     xmlSchemaParserCtxtPtr pctxt, | 
 | 		    const xmlChar * name ATTRIBUTE_UNUSED) | 
 | { | 
 |     int ret = 0, ctxtGiven; | 
 |  | 
 |     if ((facet == NULL) || (typeDecl == NULL)) | 
 |         return(-1); | 
 |     /* | 
 |     * TODO: will the parser context be given if used from | 
 |     * the relaxNG module? | 
 |     */ | 
 |     if (pctxt == NULL) | 
 | 	ctxtGiven = 0; | 
 |     else | 
 | 	ctxtGiven = 1; | 
 |  | 
 |     switch (facet->type) { | 
 |         case XML_SCHEMA_FACET_MININCLUSIVE: | 
 |         case XML_SCHEMA_FACET_MINEXCLUSIVE: | 
 |         case XML_SCHEMA_FACET_MAXINCLUSIVE: | 
 |         case XML_SCHEMA_FACET_MAXEXCLUSIVE: | 
 | 	case XML_SCHEMA_FACET_ENUMERATION: { | 
 |                 /* | 
 |                  * Okay we need to validate the value | 
 |                  * at that point. | 
 |                  */ | 
 | 		xmlSchemaTypePtr base; | 
 |  | 
 | 		/* 4.3.5.5 Constraints on enumeration Schema Components | 
 | 		* Schema Component Constraint: enumeration valid restriction | 
 | 		* It is an �error� if any member of {value} is not in the | 
 | 		* �value space� of {base type definition}. | 
 | 		* | 
 | 		* minInclusive, maxInclusive, minExclusive, maxExclusive: | 
 | 		* The value �must� be in the | 
 | 		* �value space� of the �base type�. | 
 | 		*/ | 
 | 		/* | 
 | 		* This function is intended to deliver a compiled value | 
 | 		* on the facet. In this implementation of XML Schemata the | 
 | 		* type holding a facet, won't be a built-in type. | 
 | 		* Thus to ensure that other API | 
 | 		* calls (relaxng) do work, if the given type is a built-in | 
 | 		* type, we will assume that the given built-in type *is | 
 | 		* already* the base type. | 
 | 		*/ | 
 | 		if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) { | 
 | 		    base = typeDecl->baseType; | 
 | 		    if (base == NULL) { | 
 | 			PERROR_INT("xmlSchemaCheckFacet", | 
 | 			    "a type user derived type has no base type"); | 
 | 			return (-1); | 
 | 		    } | 
 | 		} else | 
 | 		    base = typeDecl; | 
 |  | 
 | 		if (! ctxtGiven) { | 
 | 		    /* | 
 | 		    * A context is needed if called from RelaxNG. | 
 | 		    */ | 
 | 		    pctxt = xmlSchemaNewParserCtxt("*"); | 
 | 		    if (pctxt == NULL) | 
 | 			return (-1); | 
 | 		} | 
 | 		/* | 
 | 		* NOTE: This call does not check the content nodes, | 
 | 		* since they are not available: | 
 | 		* facet->node is just the node holding the facet | 
 | 		* definition, *not* the attribute holding the *value* | 
 | 		* of the facet. | 
 | 		*/ | 
 | 		ret = xmlSchemaVCheckCVCSimpleType( | 
 | 		    ACTXT_CAST pctxt, facet->node, base, | 
 | 		    facet->value, &(facet->val), 1, 1, 0); | 
 |                 if (ret != 0) { | 
 | 		    if (ret < 0) { | 
 | 			/* No error message for RelaxNG. */ | 
 | 			if (ctxtGiven) { | 
 | 			    xmlSchemaCustomErr(ACTXT_CAST pctxt, | 
 | 				XML_SCHEMAP_INTERNAL, facet->node, NULL, | 
 | 				"Internal error: xmlSchemaCheckFacet, " | 
 | 				"failed to validate the value '%s' of the " | 
 | 				"facet '%s' against the base type", | 
 | 				facet->value, xmlSchemaFacetTypeToString(facet->type)); | 
 | 			} | 
 | 			goto internal_error; | 
 | 		    } | 
 | 		    ret = XML_SCHEMAP_INVALID_FACET_VALUE; | 
 | 		    /* No error message for RelaxNG. */ | 
 | 		    if (ctxtGiven) { | 
 | 			xmlChar *str = NULL; | 
 |  | 
 | 			xmlSchemaCustomErr(ACTXT_CAST pctxt, | 
 | 			    ret, facet->node, WXS_BASIC_CAST facet, | 
 | 			    "The value '%s' of the facet does not validate " | 
 | 			    "against the base type '%s'", | 
 | 			    facet->value, | 
 | 			    xmlSchemaFormatQName(&str, | 
 | 				base->targetNamespace, base->name)); | 
 | 			FREE_AND_NULL(str); | 
 | 		    } | 
 | 		    goto exit; | 
 |                 } else if (facet->val == NULL) { | 
 | 		    if (ctxtGiven) { | 
 | 			PERROR_INT("xmlSchemaCheckFacet", | 
 | 			    "value was not computed"); | 
 | 		    } | 
 | 		    TODO | 
 | 		} | 
 |                 break; | 
 |             } | 
 |         case XML_SCHEMA_FACET_PATTERN: | 
 |             facet->regexp = xmlRegexpCompile(facet->value); | 
 |             if (facet->regexp == NULL) { | 
 | 		ret = XML_SCHEMAP_REGEXP_INVALID; | 
 | 		/* No error message for RelaxNG. */ | 
 | 		if (ctxtGiven) { | 
 | 		    xmlSchemaCustomErr(ACTXT_CAST pctxt, | 
 | 			ret, facet->node, WXS_BASIC_CAST typeDecl, | 
 | 			"The value '%s' of the facet 'pattern' is not a " | 
 | 			"valid regular expression", | 
 | 			facet->value, NULL); | 
 | 		} | 
 |             } | 
 |             break; | 
 |         case XML_SCHEMA_FACET_TOTALDIGITS: | 
 |         case XML_SCHEMA_FACET_FRACTIONDIGITS: | 
 |         case XML_SCHEMA_FACET_LENGTH: | 
 |         case XML_SCHEMA_FACET_MAXLENGTH: | 
 |         case XML_SCHEMA_FACET_MINLENGTH: | 
 |  | 
 | 	    if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) { | 
 | 		ret = xmlSchemaValidatePredefinedType( | 
 | 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER), | 
 | 		    facet->value, &(facet->val)); | 
 | 	    } else { | 
 | 		ret = xmlSchemaValidatePredefinedType( | 
 | 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER), | 
 | 		    facet->value, &(facet->val)); | 
 | 	    } | 
 | 	    if (ret != 0) { | 
 | 		if (ret < 0) { | 
 | 		    /* No error message for RelaxNG. */ | 
 | 		    if (ctxtGiven) { | 
 | 			PERROR_INT("xmlSchemaCheckFacet", | 
 | 			    "validating facet value"); | 
 | 		    } | 
 | 		    goto internal_error; | 
 | 		} | 
 | 		ret = XML_SCHEMAP_INVALID_FACET_VALUE; | 
 | 		/* No error message for RelaxNG. */ | 
 | 		if (ctxtGiven) { | 
 | 		    /* error code */ | 
 | 		    xmlSchemaCustomErr4(ACTXT_CAST pctxt, | 
 | 			ret, facet->node, WXS_BASIC_CAST typeDecl, | 
 | 			"The value '%s' of the facet '%s' is not a valid '%s'", | 
 | 			facet->value, | 
 | 			xmlSchemaFacetTypeToString(facet->type), | 
 | 			(facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ? | 
 | 			    BAD_CAST "nonNegativeInteger" : | 
 | 			    BAD_CAST "positiveInteger", | 
 | 			NULL); | 
 | 		} | 
 | 	    } | 
 | 	    break; | 
 |  | 
 |         case XML_SCHEMA_FACET_WHITESPACE:{ | 
 |                 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) { | 
 |                     facet->whitespace = XML_SCHEMAS_FACET_PRESERVE; | 
 |                 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) { | 
 |                     facet->whitespace = XML_SCHEMAS_FACET_REPLACE; | 
 |                 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) { | 
 |                     facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE; | 
 |                 } else { | 
 | 		    ret = XML_SCHEMAP_INVALID_FACET_VALUE; | 
 |                     /* No error message for RelaxNG. */ | 
 | 		    if (ctxtGiven) { | 
 | 			/* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */ | 
 | 			xmlSchemaCustomErr(ACTXT_CAST pctxt, | 
 | 			    ret, facet->node, WXS_BASIC_CAST typeDecl, | 
 | 			    "The value '%s' of the facet 'whitespace' is not " | 
 | 			    "valid", facet->value, NULL); | 
 |                     } | 
 |                 } | 
 |             } | 
 |         default: | 
 |             break; | 
 |     } | 
 | exit: | 
 |     if ((! ctxtGiven) && (pctxt != NULL)) | 
 | 	xmlSchemaFreeParserCtxt(pctxt); | 
 |     return (ret); | 
 | internal_error: | 
 |     if ((! ctxtGiven) && (pctxt != NULL)) | 
 | 	xmlSchemaFreeParserCtxt(pctxt); | 
 |     return (-1); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaCheckFacetValues: | 
 |  * @typeDecl:  the schema type definition | 
 |  * @ctxt:  the schema parser context | 
 |  * | 
 |  * Checks the default values types, especially for facets | 
 |  */ | 
 | static int | 
 | xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl, | 
 | 			  xmlSchemaParserCtxtPtr pctxt) | 
 | { | 
 |     int res, olderrs = pctxt->nberrors; | 
 |     const xmlChar *name = typeDecl->name; | 
 |     /* | 
 |     * NOTE: It is intended to use the facets list, instead | 
 |     * of facetSet. | 
 |     */ | 
 |     if (typeDecl->facets != NULL) { | 
 | 	xmlSchemaFacetPtr facet = typeDecl->facets; | 
 |  | 
 | 	/* | 
 | 	* Temporarily assign the "schema" to the validation context | 
 | 	* of the parser context. This is needed for NOTATION validation. | 
 | 	*/ | 
 | 	if (pctxt->vctxt == NULL) { | 
 | 	    if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1) | 
 | 		return(-1); | 
 | 	} | 
 | 	pctxt->vctxt->schema = pctxt->schema; | 
 | 	while (facet != NULL) { | 
 | 	    res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name); | 
 | 	    HFAILURE | 
 | 	    facet = facet->next; | 
 | 	} | 
 | 	pctxt->vctxt->schema = NULL; | 
 |     } | 
 |     if (olderrs != pctxt->nberrors) | 
 | 	return(pctxt->err); | 
 |     return(0); | 
 | exit_failure: | 
 |     return(-1); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaGetCircModelGrDefRef: | 
 |  * @ctxtMGroup: the searched model group | 
 |  * @selfMGroup: the second searched model group | 
 |  * @particle: the first particle | 
 |  * | 
 |  * This one is intended to be used by | 
 |  * xmlSchemaCheckGroupDefCircular only. | 
 |  * | 
 |  * Returns the particle with the circular model group definition reference, | 
 |  * otherwise NULL. | 
 |  */ | 
 | static xmlSchemaTreeItemPtr | 
 | xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef, | 
 | 			      xmlSchemaTreeItemPtr particle) | 
 | { | 
 |     xmlSchemaTreeItemPtr circ = NULL; | 
 |     xmlSchemaTreeItemPtr term; | 
 |     xmlSchemaModelGroupDefPtr gdef; | 
 |  | 
 |     for (; particle != NULL; particle = particle->next) { | 
 | 	term = particle->children; | 
 | 	if (term == NULL) | 
 | 	    continue; | 
 | 	switch (term->type) { | 
 | 	    case XML_SCHEMA_TYPE_GROUP: | 
 | 		gdef = (xmlSchemaModelGroupDefPtr) term; | 
 | 		if (gdef == groupDef) | 
 | 		    return (particle); | 
 | 		/* | 
 | 		* Mark this model group definition to avoid infinite | 
 | 		* recursion on circular references not yet examined. | 
 | 		*/ | 
 | 		if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED) | 
 | 		    continue; | 
 | 		if (gdef->children != NULL) { | 
 | 		    gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED; | 
 | 		    circ = xmlSchemaGetCircModelGrDefRef(groupDef, | 
 | 			gdef->children->children); | 
 | 		    gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED; | 
 | 		    if (circ != NULL) | 
 | 			return (circ); | 
 | 		} | 
 | 		break; | 
 | 	    case XML_SCHEMA_TYPE_SEQUENCE: | 
 | 	    case XML_SCHEMA_TYPE_CHOICE: | 
 | 	    case XML_SCHEMA_TYPE_ALL: | 
 | 		circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children); | 
 | 		if (circ != NULL) | 
 | 		    return (circ); | 
 | 		break; | 
 | 	    default: | 
 | 		break; | 
 | 	} | 
 |     } | 
 |     return (NULL); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaCheckGroupDefCircular: | 
 |  * @item:  the model group definition | 
 |  * @ctxt:  the parser context | 
 |  * @name:  the name | 
 |  * | 
 |  * Checks for circular references to model group definitions. | 
 |  */ | 
 | static void | 
 | xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item, | 
 | 			       xmlSchemaParserCtxtPtr ctxt) | 
 | { | 
 |     /* | 
 |     * Schema Component Constraint: Model Group Correct | 
 |     * 2 Circular groups are disallowed. That is, within the {particles} | 
 |     * of a group there must not be at any depth a particle whose {term} | 
 |     * is the group itself. | 
 |     */ | 
 |     if ((item == NULL) || | 
 | 	(item->type != XML_SCHEMA_TYPE_GROUP) || | 
 | 	(item->children == NULL)) | 
 | 	return; | 
 |     { | 
 | 	xmlSchemaTreeItemPtr circ; | 
 |  | 
 | 	circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children); | 
 | 	if (circ != NULL) { | 
 | 	    xmlChar *str = NULL; | 
 | 	    /* | 
 | 	    * TODO: The error report is not adequate: this constraint | 
 | 	    * is defined for model groups but not definitions, but since | 
 | 	    * there cannot be any circular model groups without a model group | 
 | 	    * definition (if not using a construction API), we check those | 
 | 	    * defintions only. | 
 | 	    */ | 
 | 	    xmlSchemaPCustomErr(ctxt, | 
 | 		XML_SCHEMAP_MG_PROPS_CORRECT_2, | 
 | 		NULL, WXS_ITEM_NODE(circ), | 
 | 		"Circular reference to the model group definition '%s' " | 
 | 		"defined", xmlSchemaFormatQName(&str, | 
 | 		    item->targetNamespace, item->name)); | 
 | 	    FREE_AND_NULL(str) | 
 | 	    /* | 
 | 	    * NOTE: We will cut the reference to avoid further | 
 | 	    * confusion of the processor. This is a fatal error. | 
 | 	    */ | 
 | 	    circ->children = NULL; | 
 | 	} | 
 |     } | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaModelGroupToModelGroupDefFixup: | 
 |  * @ctxt:  the parser context | 
 |  * @mg:  the model group | 
 |  * | 
 |  * Assigns the model group of model group definitions to the "term" | 
 |  * of the referencing particle. | 
 |  * In xmlSchemaResolveModelGroupParticleReferences the model group | 
 |  * definitions were assigned to the "term", since needed for the | 
 |  * circularity check. | 
 |  * | 
 |  * Schema Component Constraint: | 
 |  *     All Group Limited (cos-all-limited) (1.2) | 
 |  */ | 
 | static void | 
 | xmlSchemaModelGroupToModelGroupDefFixup( | 
 |     xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED, | 
 |     xmlSchemaModelGroupPtr mg) | 
 | { | 
 |     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg); | 
 |  | 
 |     while (particle != NULL) { | 
 | 	if ((WXS_PARTICLE_TERM(particle) == NULL) || | 
 | 	    ((WXS_PARTICLE_TERM(particle))->type != | 
 | 		XML_SCHEMA_TYPE_GROUP)) | 
 | 	{ | 
 | 	    particle = WXS_PTC_CAST particle->next; | 
 | 	    continue; | 
 | 	} | 
 | 	if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) { | 
 | 	    /* | 
 | 	    * TODO: Remove the particle. | 
 | 	    */ | 
 | 	    WXS_PARTICLE_TERM(particle) = NULL; | 
 | 	    particle = WXS_PTC_CAST particle->next; | 
 | 	    continue; | 
 | 	} | 
 | 	/* | 
 | 	* Assign the model group to the {term} of the particle. | 
 | 	*/ | 
 | 	WXS_PARTICLE_TERM(particle) = | 
 | 	    WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)); | 
 |  | 
 | 	particle = WXS_PTC_CAST particle->next; | 
 |     } | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaCheckAttrGroupCircularRecur: | 
 |  * @ctxtGr: the searched attribute group | 
 |  * @attr: the current attribute list to be processed | 
 |  * | 
 |  * This one is intended to be used by | 
 |  * xmlSchemaCheckAttrGroupCircular only. | 
 |  * | 
 |  * Returns the circular attribute grou reference, otherwise NULL. | 
 |  */ | 
 | static xmlSchemaQNameRefPtr | 
 | xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr, | 
 | 				     xmlSchemaItemListPtr list) | 
 | { | 
 |     xmlSchemaAttributeGroupPtr gr; | 
 |     xmlSchemaQNameRefPtr ref, circ; | 
 |     int i; | 
 |     /* | 
 |     * We will search for an attribute group reference which | 
 |     * references the context attribute group. | 
 |     */ | 
 |     for (i = 0; i < list->nbItems; i++) { | 
 | 	ref = list->items[i]; | 
 | 	if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) && | 
 | 	    (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) && | 
 | 	    (ref->item != NULL)) | 
 | 	{ | 
 | 	    gr = WXS_ATTR_GROUP_CAST ref->item; | 
 | 	    if (gr == ctxtGr) | 
 | 		return(ref); | 
 | 	    if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED) | 
 | 		continue; | 
 | 	    /* | 
 | 	    * Mark as visited to avoid infinite recursion on | 
 | 	    * circular references not yet examined. | 
 | 	    */ | 
 | 	    if ((gr->attrUses) && | 
 | 		(gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS)) | 
 | 	    { | 
 | 		gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED; | 
 | 		circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr, | 
 | 		    (xmlSchemaItemListPtr) gr->attrUses); | 
 | 		gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED; | 
 | 		if (circ != NULL) | 
 | 		    return (circ); | 
 | 	    } | 
 |  | 
 | 	} | 
 |     } | 
 |     return (NULL); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaCheckAttrGroupCircular: | 
 |  * attrGr:  the attribute group definition | 
 |  * @ctxt:  the parser context | 
 |  * @name:  the name | 
 |  * | 
 |  * Checks for circular references of attribute groups. | 
 |  */ | 
 | static int | 
 | xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr, | 
 | 				xmlSchemaParserCtxtPtr ctxt) | 
 | { | 
 |     /* | 
 |     * Schema Representation Constraint: | 
 |     * Attribute Group Definition Representation OK | 
 |     * 3 Circular group reference is disallowed outside <redefine>. | 
 |     * That is, unless this element information item's parent is | 
 |     * <redefine>, then among the [children], if any, there must | 
 |     * not be an <attributeGroup> with ref [attribute] which resolves | 
 |     * to the component corresponding to this <attributeGroup>. Indirect | 
 |     * circularity is also ruled out. That is, when QName resolution | 
 |     * (Schema Document) (�3.15.3) is applied to a �QName� arising from | 
 |     * any <attributeGroup>s with a ref [attribute] among the [children], | 
 |     * it must not be the case that a �QName� is encountered at any depth | 
 |     * which resolves to the component corresponding to this <attributeGroup>. | 
 |     */ | 
 |     if (attrGr->attrUses == NULL) | 
 | 	return(0); | 
 |     else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0) | 
 | 	return(0); | 
 |     else { | 
 | 	xmlSchemaQNameRefPtr circ; | 
 |  | 
 | 	circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr, | 
 | 	    (xmlSchemaItemListPtr) attrGr->attrUses); | 
 | 	if (circ != NULL) { | 
 | 	    xmlChar *str = NULL; | 
 | 	    /* | 
 | 	    * TODO: Report the referenced attr group as QName. | 
 | 	    */ | 
 | 	    xmlSchemaPCustomErr(ctxt, | 
 | 		XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3, | 
 | 		NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ), | 
 | 		"Circular reference to the attribute group '%s' " | 
 | 		"defined", xmlSchemaGetComponentQName(&str, attrGr)); | 
 | 	    FREE_AND_NULL(str); | 
 | 	    /* | 
 | 	    * NOTE: We will cut the reference to avoid further | 
 | 	    * confusion of the processor. | 
 | 	    * BADSPEC TODO: The spec should define how to process in this case. | 
 | 	    */ | 
 | 	    circ->item = NULL; | 
 | 	    return(ctxt->err); | 
 | 	} | 
 |     } | 
 |     return(0); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt, | 
 | 				  xmlSchemaAttributeGroupPtr attrGr); | 
 |  | 
 | /** | 
 |  * xmlSchemaExpandAttributeGroupRefs: | 
 |  * @pctxt: the parser context | 
 |  * @node: the node of the component holding the attribute uses | 
 |  * @completeWild: the intersected wildcard to be returned | 
 |  * @list: the attribute uses | 
 |  * | 
 |  * Substitutes contained attribute group references | 
 |  * for their attribute uses. Wilcards are intersected. | 
 |  * Attribute use prohibitions are removed from the list | 
 |  * and returned via the @prohibs list. | 
 |  * Pointlessness of attr. prohibs, if a matching attr. decl | 
 |  * is existent a well, are checked. | 
 |  */ | 
 | static int | 
 | xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt, | 
 | 				  xmlSchemaBasicItemPtr item, | 
 | 				  xmlSchemaWildcardPtr *completeWild, | 
 | 				  xmlSchemaItemListPtr list, | 
 | 				  xmlSchemaItemListPtr prohibs) | 
 | { | 
 |     xmlSchemaAttributeGroupPtr gr; | 
 |     xmlSchemaAttributeUsePtr use; | 
 |     xmlSchemaItemListPtr sublist; | 
 |     int i, j; | 
 |     int created = (*completeWild == NULL) ? 0 : 1; | 
 |  | 
 |     if (prohibs) | 
 | 	prohibs->nbItems = 0; | 
 |  | 
 |     for (i = 0; i < list->nbItems; i++) { | 
 | 	use = list->items[i]; | 
 |  | 
 | 	if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) { | 
 | 	    if (prohibs == NULL) { | 
 | 		PERROR_INT("xmlSchemaExpandAttributeGroupRefs", | 
 | 		    "unexpected attr prohibition found"); | 
 | 		return(-1); | 
 | 	    } | 
 | 	    /* | 
 | 	    * Remove from attribute uses. | 
 | 	    */ | 
 | 	    if (xmlSchemaItemListRemove(list, i) == -1) | 
 | 		return(-1); | 
 | 	    i--; | 
 | 	    /* | 
 | 	    * Note that duplicate prohibitions were already | 
 | 	    * handled at parsing time. | 
 | 	    */ | 
 | 	    /* | 
 | 	    * Add to list of prohibitions. | 
 | 	    */ | 
 | 	    xmlSchemaItemListAddSize(prohibs, 2, use); | 
 | 	    continue; | 
 | 	} | 
 | 	if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) && | 
 | 	    ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)) | 
 | 	{ | 
 | 	    if ((WXS_QNAME_CAST use)->item == NULL) | 
 | 		return(-1); | 
 | 	    gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item; | 
 | 	    /* | 
 | 	    * Expand the referenced attr. group. | 
 | 	    * TODO: remove this, this is done in a previous step, so | 
 | 	    * already done here. | 
 | 	    */ | 
 | 	    if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) { | 
 | 		if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1) | 
 | 		    return(-1); | 
 | 	    } | 
 | 	    /* | 
 | 	    * Build the 'complete' wildcard; i.e. intersect multiple | 
 | 	    * wildcards. | 
 | 	    */ | 
 | 	    if (gr->attributeWildcard != NULL) { | 
 | 		if (*completeWild == NULL) { | 
 | 		    *completeWild = gr->attributeWildcard; | 
 | 		} else { | 
 | 		    if (! created) { | 
 | 			xmlSchemaWildcardPtr tmpWild; | 
 |  | 
 | 			 /* | 
 | 			* Copy the first encountered wildcard as context, | 
 | 			* except for the annotation. | 
 | 			* | 
 | 			* Although the complete wildcard might not correspond | 
 | 			* to any node in the schema, we will anchor it on | 
 | 			* the node of the owner component. | 
 | 			*/ | 
 | 			tmpWild =  xmlSchemaAddWildcard(pctxt, pctxt->schema, | 
 | 			    XML_SCHEMA_TYPE_ANY_ATTRIBUTE, | 
 | 			    WXS_ITEM_NODE(item)); | 
 | 			if (tmpWild == NULL) | 
 | 			    return(-1); | 
 | 			if (xmlSchemaCloneWildcardNsConstraints(pctxt, | 
 | 			    tmpWild, *completeWild) == -1) | 
 | 			    return (-1); | 
 | 			tmpWild->processContents = (*completeWild)->processContents; | 
 | 			*completeWild = tmpWild; | 
 | 			created = 1; | 
 | 		    } | 
 |  | 
 | 		    if (xmlSchemaIntersectWildcards(pctxt, *completeWild, | 
 | 			gr->attributeWildcard) == -1) | 
 | 			return(-1); | 
 | 		} | 
 | 	    } | 
 | 	    /* | 
 | 	    * Just remove the reference if the referenced group does not | 
 | 	    * contain any attribute uses. | 
 | 	    */ | 
 | 	    sublist = ((xmlSchemaItemListPtr) gr->attrUses); | 
 | 	    if ((sublist == NULL) || sublist->nbItems == 0) { | 
 | 		if (xmlSchemaItemListRemove(list, i) == -1) | 
 | 		    return(-1); | 
 | 		i--; | 
 | 		continue; | 
 | 	    } | 
 | 	    /* | 
 | 	    * Add the attribute uses. | 
 | 	    */ | 
 | 	    list->items[i] = sublist->items[0]; | 
 | 	    if (sublist->nbItems != 1) { | 
 | 		for (j = 1; j < sublist->nbItems; j++) { | 
 | 		    i++; | 
 | 		    if (xmlSchemaItemListInsert(list, | 
 | 			    sublist->items[j], i) == -1) | 
 | 			return(-1); | 
 | 		} | 
 | 	    } | 
 | 	} | 
 |  | 
 |     } | 
 |     /* | 
 |     * Handle pointless prohibitions of declared attributes. | 
 |     */ | 
 |     if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) { | 
 | 	xmlSchemaAttributeUseProhibPtr prohib; | 
 |  | 
 | 	for (i = prohibs->nbItems -1; i >= 0; i--) { | 
 | 	    prohib = prohibs->items[i]; | 
 | 	    for (j = 0; j < list->nbItems; j++) { | 
 | 		use = list->items[j]; | 
 |  | 
 | 		if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) && | 
 | 		    (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use))) | 
 | 		{ | 
 | 		    xmlChar *str = NULL; | 
 |  | 
 | 		    xmlSchemaCustomWarning(ACTXT_CAST pctxt, | 
 | 			XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH, | 
 | 			prohib->node, NULL, | 
 | 			"Skipping pointless attribute use prohibition " | 
 | 			"'%s', since a corresponding attribute use " | 
 | 			"exists already in the type definition", | 
 | 			xmlSchemaFormatQName(&str, | 
 | 			    prohib->targetNamespace, prohib->name), | 
 | 			NULL, NULL); | 
 | 		    FREE_AND_NULL(str); | 
 | 		    /* | 
 | 		    * Remove the prohibition. | 
 | 		    */ | 
 | 		    if (xmlSchemaItemListRemove(prohibs, i) == -1) | 
 | 			return(-1); | 
 | 		    break; | 
 | 		} | 
 | 	    } | 
 | 	} | 
 |     } | 
 |     return(0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaAttributeGroupExpandRefs: | 
 |  * @pctxt:  the parser context | 
 |  * @attrGr:  the attribute group definition | 
 |  * | 
 |  * Computation of: | 
 |  * {attribute uses} property | 
 |  * {attribute wildcard} property | 
 |  * | 
 |  * Substitutes contained attribute group references | 
 |  * for their attribute uses. Wilcards are intersected. | 
 |  */ | 
 | static int | 
 | xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt, | 
 | 				  xmlSchemaAttributeGroupPtr attrGr) | 
 | { | 
 |     if ((attrGr->attrUses == NULL) || | 
 | 	(attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED)) | 
 | 	return(0); | 
 |  | 
 |     attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED; | 
 |     if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr, | 
 | 	&(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1) | 
 | 	return(-1); | 
 |     return(0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaAttributeGroupExpandRefs: | 
 |  * @pctxt:  the parser context | 
 |  * @attrGr:  the attribute group definition | 
 |  * | 
 |  * Substitutes contained attribute group references | 
 |  * for their attribute uses. Wilcards are intersected. | 
 |  * | 
 |  * Schema Component Constraint: | 
 |  *    Attribute Group Definition Properties Correct (ag-props-correct) | 
 |  */ | 
 | static int | 
 | xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt, | 
 | 				  xmlSchemaAttributeGroupPtr attrGr) | 
 | { | 
 |     /* | 
 |     * SPEC ag-props-correct | 
 |     * (1) "The values of the properties of an attribute group definition | 
 |     * must be as described in the property tableau in The Attribute | 
 |     * Group Definition Schema Component (�3.6.1), modulo the impact of | 
 |     * Missing Sub-components (�5.3);" | 
 |     */ | 
 |  | 
 |     if ((attrGr->attrUses != NULL) && | 
 | 	(WXS_LIST_CAST attrGr->attrUses)->nbItems > 1) | 
 |     { | 
 | 	xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses; | 
 | 	xmlSchemaAttributeUsePtr use, tmp; | 
 | 	int i, j, hasId = 0; | 
 |  | 
 | 	for (i = uses->nbItems -1; i >= 0; i--) { | 
 | 	    use = uses->items[i]; | 
 | 	    /* | 
 | 	    * SPEC ag-props-correct | 
 | 	    * (2) "Two distinct members of the {attribute uses} must not have | 
 | 	    * {attribute declaration}s both of whose {name}s match and whose | 
 | 	    * {target namespace}s are identical." | 
 | 	    */ | 
 | 	    if (i > 0) { | 
 | 		for (j = i -1; j >= 0; j--) { | 
 | 		    tmp = uses->items[j]; | 
 | 		    if ((WXS_ATTRUSE_DECL_NAME(use) == | 
 | 			WXS_ATTRUSE_DECL_NAME(tmp)) && | 
 | 			(WXS_ATTRUSE_DECL_TNS(use) == | 
 | 			WXS_ATTRUSE_DECL_TNS(tmp))) | 
 | 		    { | 
 | 			xmlChar *str = NULL; | 
 |  | 
 | 			xmlSchemaCustomErr(ACTXT_CAST pctxt, | 
 | 			    XML_SCHEMAP_AG_PROPS_CORRECT, | 
 | 			    attrGr->node, WXS_BASIC_CAST attrGr, | 
 | 			    "Duplicate %s", | 
 | 			    xmlSchemaGetComponentDesignation(&str, use), | 
 | 			    NULL); | 
 | 			FREE_AND_NULL(str); | 
 | 			/* | 
 | 			* Remove the duplicate. | 
 | 			*/ | 
 | 			if (xmlSchemaItemListRemove(uses, i) == -1) | 
 | 			    return(-1); | 
 | 			goto next_use; | 
 | 		    } | 
 | 		} | 
 | 	    } | 
 | 	    /* | 
 | 	    * SPEC ag-props-correct | 
 | 	    * (3) "Two distinct members of the {attribute uses} must not have | 
 | 	    * {attribute declaration}s both of whose {type definition}s are or | 
 | 	    * are derived from ID." | 
 | 	    * TODO: Does 'derived' include member-types of unions? | 
 | 	    */ | 
 | 	    if (WXS_ATTRUSE_TYPEDEF(use) != NULL) { | 
 | 		if (xmlSchemaIsDerivedFromBuiltInType( | 
 | 		    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID)) | 
 | 		{ | 
 | 		    if (hasId) { | 
 | 			xmlChar *str = NULL; | 
 |  | 
 | 			xmlSchemaCustomErr(ACTXT_CAST pctxt, | 
 | 			    XML_SCHEMAP_AG_PROPS_CORRECT, | 
 | 			    attrGr->node, WXS_BASIC_CAST attrGr, | 
 | 			    "There must not exist more than one attribute " | 
 | 			    "declaration of type 'xs:ID' " | 
 | 			    "(or derived from 'xs:ID'). The %s violates this " | 
 | 			    "constraint", | 
 | 			    xmlSchemaGetComponentDesignation(&str, use), | 
 | 			    NULL); | 
 | 			FREE_AND_NULL(str); | 
 | 			if (xmlSchemaItemListRemove(uses, i) == -1) | 
 | 			    return(-1); | 
 | 		    } | 
 | 		    hasId = 1; | 
 | 		} | 
 | 	    } | 
 | next_use: {} | 
 | 	} | 
 |     } | 
 |     return(0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaResolveAttrGroupReferences: | 
 |  * @attrgrpDecl:  the schema attribute definition | 
 |  * @ctxt:  the schema parser context | 
 |  * @name:  the attribute name | 
 |  * | 
 |  * Resolves references to attribute group definitions. | 
 |  */ | 
 | static int | 
 | xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref, | 
 | 				    xmlSchemaParserCtxtPtr ctxt) | 
 | { | 
 |     xmlSchemaAttributeGroupPtr group; | 
 |  | 
 |     if (ref->item != NULL) | 
 |         return(0); | 
 |     group = xmlSchemaGetAttributeGroup(ctxt->schema, | 
 | 	ref->name, | 
 | 	ref->targetNamespace); | 
 |     if (group == NULL) { | 
 | 	xmlSchemaPResCompAttrErr(ctxt, | 
 | 	    XML_SCHEMAP_SRC_RESOLVE, | 
 | 	    NULL, ref->node, | 
 | 	    "ref", ref->name, ref->targetNamespace, | 
 | 	    ref->itemType, NULL); | 
 | 	return(ctxt->err); | 
 |     } | 
 |     ref->item = WXS_BASIC_CAST group; | 
 |     return(0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaCheckAttrPropsCorrect: | 
 |  * @item:  an schema attribute declaration/use | 
 |  * @ctxt:  a schema parser context | 
 |  * @name:  the name of the attribute | 
 |  * | 
 |  * | 
 |  * Schema Component Constraint: | 
 |  *    Attribute Declaration Properties Correct (a-props-correct) | 
 |  * | 
 |  * Validates the value constraints of an attribute declaration/use. | 
 |  * NOTE that this needs the simle type definitions to be already | 
 |  *   builded and checked. | 
 |  */ | 
 | static int | 
 | xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt, | 
 | 			       xmlSchemaAttributePtr attr) | 
 | { | 
 |  | 
 |     /* | 
 |     * SPEC a-props-correct (1) | 
 |     * "The values of the properties of an attribute declaration must | 
 |     * be as described in the property tableau in The Attribute | 
 |     * Declaration Schema Component (�3.2.1), modulo the impact of | 
 |     * Missing Sub-components (�5.3)." | 
 |     */ | 
 |  | 
 |     if (WXS_ATTR_TYPEDEF(attr) == NULL) | 
 | 	return(0); | 
 |  | 
 |     if (attr->defValue != NULL) { | 
 | 	int ret; | 
 |  | 
 | 	/* | 
 | 	* SPEC a-props-correct (3) | 
 | 	* "If the {type definition} is or is derived from ID then there | 
 | 	* must not be a {value constraint}." | 
 | 	*/ | 
 | 	if (xmlSchemaIsDerivedFromBuiltInType( | 
 | 	    WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID)) | 
 | 	{ | 
 | 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, | 
 | 		XML_SCHEMAP_A_PROPS_CORRECT_3, | 
 | 		NULL, WXS_BASIC_CAST attr, | 
 | 		"Value constraints are not allowed if the type definition " | 
 | 		"is or is derived from xs:ID", | 
 | 		NULL, NULL); | 
 | 	    return(pctxt->err); | 
 | 	} | 
 | 	/* | 
 | 	* SPEC a-props-correct (2) | 
 | 	* "if there is a {value constraint}, the canonical lexical | 
 | 	* representation of its value must be �valid� with respect | 
 | 	* to the {type definition} as defined in String Valid (�3.14.4)." | 
 | 	* TODO: Don't care about the *cononical* stuff here, this requirement | 
 | 	* will be removed in WXS 1.1 anyway. | 
 | 	*/ | 
 | 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, | 
 | 	    attr->node, WXS_ATTR_TYPEDEF(attr), | 
 | 	    attr->defValue, &(attr->defVal), | 
 | 	    1, 1, 0); | 
 | 	if (ret != 0) { | 
 | 	    if (ret < 0) { | 
 | 		PERROR_INT("xmlSchemaCheckAttrPropsCorrect", | 
 | 		    "calling xmlSchemaVCheckCVCSimpleType()"); | 
 | 		return(-1); | 
 | 	    } | 
 | 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, | 
 | 		XML_SCHEMAP_A_PROPS_CORRECT_2, | 
 | 		NULL, WXS_BASIC_CAST attr, | 
 | 		"The value of the value constraint is not valid", | 
 | 		NULL, NULL); | 
 | 	    return(pctxt->err); | 
 | 	} | 
 |     } | 
 |  | 
 |     return(0); | 
 | } | 
 |  | 
 | static xmlSchemaElementPtr | 
 | xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl, | 
 | 				 xmlSchemaElementPtr ancestor) | 
 | { | 
 |     xmlSchemaElementPtr ret; | 
 |  | 
 |     if (WXS_SUBST_HEAD(ancestor) == NULL) | 
 | 	return (NULL); | 
 |     if (WXS_SUBST_HEAD(ancestor) == elemDecl) | 
 | 	return (ancestor); | 
 |  | 
 |     if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR) | 
 | 	return (NULL); | 
 |     WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR; | 
 |     ret = xmlSchemaCheckSubstGroupCircular(elemDecl, | 
 | 	WXS_SUBST_HEAD(ancestor)); | 
 |     WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR; | 
 |  | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaCheckElemPropsCorrect: | 
 |  * @ctxt:  a schema parser context | 
 |  * @decl: the element declaration | 
 |  * @name:  the name of the attribute | 
 |  * | 
 |  * Schema Component Constraint: | 
 |  * Element Declaration Properties Correct (e-props-correct) | 
 |  * | 
 |  * STATUS: | 
 |  *   missing: (6) | 
 |  */ | 
 | static int | 
 | xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt, | 
 | 			       xmlSchemaElementPtr elemDecl) | 
 | { | 
 |     int ret = 0; | 
 |     xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl); | 
 |     /* | 
 |     * SPEC (1) "The values of the properties of an element declaration | 
 |     * must be as described in the property tableau in The Element | 
 |     * Declaration Schema Component (�3.3.1), modulo the impact of Missing | 
 |     * Sub-components (�5.3)." | 
 |     */ | 
 |     if (WXS_SUBST_HEAD(elemDecl) != NULL) { | 
 | 	xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ; | 
 |  | 
 | 	xmlSchemaCheckElementDeclComponent(head, pctxt); | 
 | 	/* | 
 | 	* SPEC (3) "If there is a non-�absent� {substitution group | 
 | 	* affiliation}, then {scope} must be global." | 
 | 	*/ | 
 | 	if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) { | 
 | 	    xmlSchemaPCustomErr(pctxt, | 
 | 		XML_SCHEMAP_E_PROPS_CORRECT_3, | 
 | 		WXS_BASIC_CAST elemDecl, NULL, | 
 | 		"Only global element declarations can have a " | 
 | 		"substitution group affiliation", NULL); | 
 | 	    ret = XML_SCHEMAP_E_PROPS_CORRECT_3; | 
 | 	} | 
 | 	/* | 
 | 	* TODO: SPEC (6) "Circular substitution groups are disallowed. | 
 | 	* That is, it must not be possible to return to an element declaration | 
 | 	* by repeatedly following the {substitution group affiliation} | 
 | 	* property." | 
 | 	*/ | 
 | 	if (head == elemDecl) | 
 | 	    circ = head; | 
 | 	else if (WXS_SUBST_HEAD(head) != NULL) | 
 | 	    circ = xmlSchemaCheckSubstGroupCircular(head, head); | 
 | 	else | 
 | 	    circ = NULL; | 
 | 	if (circ != NULL) { | 
 | 	    xmlChar *strA = NULL, *strB = NULL; | 
 |  | 
 | 	    xmlSchemaPCustomErrExt(pctxt, | 
 | 		XML_SCHEMAP_E_PROPS_CORRECT_6, | 
 | 		WXS_BASIC_CAST circ, NULL, | 
 | 		"The element declaration '%s' defines a circular " | 
 | 		"substitution group to element declaration '%s'", | 
 | 		xmlSchemaGetComponentQName(&strA, circ), | 
 | 		xmlSchemaGetComponentQName(&strB, head), | 
 | 		NULL); | 
 | 	    FREE_AND_NULL(strA) | 
 | 	    FREE_AND_NULL(strB) | 
 | 	    ret = XML_SCHEMAP_E_PROPS_CORRECT_6; | 
 | 	} | 
 | 	/* | 
 | 	* SPEC (4) "If there is a {substitution group affiliation}, | 
 | 	* the {type definition} | 
 | 	* of the element declaration must be validly derived from the {type | 
 | 	* definition} of the {substitution group affiliation}, given the value | 
 | 	* of the {substitution group exclusions} of the {substitution group | 
 | 	* affiliation}, as defined in Type Derivation OK (Complex) (�3.4.6) | 
 | 	* (if the {type definition} is complex) or as defined in | 
 | 	* Type Derivation OK (Simple) (�3.14.6) (if the {type definition} is | 
 | 	* simple)." | 
 | 	* | 
 | 	* NOTE: {substitution group exclusions} means the values of the | 
 | 	* attribute "final". | 
 | 	*/ | 
 |  | 
 | 	if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) { | 
 | 	    int set = 0; | 
 |  | 
 | 	    if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION) | 
 | 		set |= SUBSET_EXTENSION; | 
 | 	    if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION) | 
 | 		set |= SUBSET_RESTRICTION; | 
 |  | 
 | 	    if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef, | 
 | 		WXS_ELEM_TYPEDEF(head), set) != 0) { | 
 | 		xmlChar *strA = NULL, *strB = NULL, *strC = NULL; | 
 |  | 
 | 		ret = XML_SCHEMAP_E_PROPS_CORRECT_4; | 
 | 		xmlSchemaPCustomErrExt(pctxt, | 
 | 		    XML_SCHEMAP_E_PROPS_CORRECT_4, | 
 | 		    WXS_BASIC_CAST elemDecl, NULL, | 
 | 		    "The type definition '%s' was " | 
 | 		    "either rejected by the substitution group " | 
 | 		    "affiliation '%s', or not validly derived from its type " | 
 | 		    "definition '%s'", | 
 | 		    xmlSchemaGetComponentQName(&strA, typeDef), | 
 | 		    xmlSchemaGetComponentQName(&strB, head), | 
 | 		    xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head))); | 
 | 		FREE_AND_NULL(strA) | 
 | 		FREE_AND_NULL(strB) | 
 | 		FREE_AND_NULL(strC) | 
 | 	    } | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * SPEC (5) "If the {type definition} or {type definition}'s | 
 |     * {content type} | 
 |     * is or is derived from ID then there must not be a {value constraint}. | 
 |     * Note: The use of ID as a type definition for elements goes beyond | 
 |     * XML 1.0, and should be avoided if backwards compatibility is desired" | 
 |     */ | 
 |     if ((elemDecl->value != NULL) && | 
 | 	((WXS_IS_SIMPLE(typeDef) && | 
 | 	  xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) || | 
 | 	 (WXS_IS_COMPLEX(typeDef) && | 
 | 	  WXS_HAS_SIMPLE_CONTENT(typeDef) && | 
 | 	  xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef, | 
 | 	    XML_SCHEMAS_ID)))) { | 
 |  | 
 | 	ret = XML_SCHEMAP_E_PROPS_CORRECT_5; | 
 | 	xmlSchemaPCustomErr(pctxt, | 
 | 	    XML_SCHEMAP_E_PROPS_CORRECT_5, | 
 | 	    WXS_BASIC_CAST elemDecl, NULL, | 
 | 	    "The type definition (or type definition's content type) is or " | 
 | 	    "is derived from ID; value constraints are not allowed in " | 
 | 	    "conjunction with such a type definition", NULL); | 
 |     } else if (elemDecl->value != NULL) { | 
 | 	int vcret; | 
 | 	xmlNodePtr node = NULL; | 
 |  | 
 | 	/* | 
 | 	* SPEC (2) "If there is a {value constraint}, the canonical lexical | 
 | 	* representation of its value must be �valid� with respect to the | 
 | 	* {type definition} as defined in Element Default Valid (Immediate) | 
 | 	* (�3.3.6)." | 
 | 	*/ | 
 | 	if (typeDef == NULL) { | 
 | 	    xmlSchemaPErr(pctxt, elemDecl->node, | 
 | 		XML_SCHEMAP_INTERNAL, | 
 | 		"Internal error: xmlSchemaCheckElemPropsCorrect, " | 
 | 		"type is missing... skipping validation of " | 
 | 		"the value constraint", NULL, NULL); | 
 | 	    return (-1); | 
 | 	} | 
 | 	if (elemDecl->node != NULL) { | 
 | 	    if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) | 
 | 		node = (xmlNodePtr) xmlHasProp(elemDecl->node, | 
 | 		    BAD_CAST "fixed"); | 
 | 	    else | 
 | 		node = (xmlNodePtr) xmlHasProp(elemDecl->node, | 
 | 		    BAD_CAST "default"); | 
 | 	} | 
 | 	vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node, | 
 | 	    typeDef, elemDecl->value, &(elemDecl->defVal)); | 
 | 	if (vcret != 0) { | 
 | 	    if (vcret < 0) { | 
 | 		PERROR_INT("xmlSchemaElemCheckValConstr", | 
 | 		    "failed to validate the value constraint of an " | 
 | 		    "element declaration"); | 
 | 		return (-1); | 
 | 	    } | 
 | 	    return (vcret); | 
 | 	} | 
 |     } | 
 |  | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaCheckElemSubstGroup: | 
 |  * @ctxt:  a schema parser context | 
 |  * @decl: the element declaration | 
 |  * @name:  the name of the attribute | 
 |  * | 
 |  * Schema Component Constraint: | 
 |  * Substitution Group (cos-equiv-class) | 
 |  * | 
 |  * In Libxml2 the subst. groups will be precomputed, in terms of that | 
 |  * a list will be built for each subst. group head, holding all direct | 
 |  * referents to this head. | 
 |  * NOTE that this function needs: | 
 |  *   1. circular subst. groups to be checked beforehand | 
 |  *   2. the declaration's type to be derived from the head's type | 
 |  * | 
 |  * STATUS: | 
 |  * | 
 |  */ | 
 | static void | 
 | xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt, | 
 | 			     xmlSchemaElementPtr elemDecl) | 
 | { | 
 |     if ((WXS_SUBST_HEAD(elemDecl) == NULL) || | 
 | 	/* SPEC (1) "Its {abstract} is false." */ | 
 | 	(elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)) | 
 | 	return; | 
 |     { | 
 | 	xmlSchemaElementPtr head; | 
 | 	xmlSchemaTypePtr headType, type; | 
 | 	int set, methSet; | 
 | 	/* | 
 | 	* SPEC (2) "It is validly substitutable for HEAD subject to HEAD's | 
 | 	* {disallowed substitutions} as the blocking constraint, as defined in | 
 | 	* Substitution Group OK (Transitive) (�3.3.6)." | 
 | 	*/ | 
 | 	for (head = WXS_SUBST_HEAD(elemDecl); head != NULL; | 
 | 	    head = WXS_SUBST_HEAD(head)) { | 
 | 	    set = 0; | 
 | 	    methSet = 0; | 
 | 	    /* | 
 | 	    * The blocking constraints. | 
 | 	    */ | 
 | 	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) | 
 | 		continue; | 
 | 	    headType = head->subtypes; | 
 | 	    type = elemDecl->subtypes; | 
 | 	    if (headType == type) | 
 | 		goto add_member; | 
 | 	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) | 
 | 		set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION; | 
 | 	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) | 
 | 		set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION; | 
 | 	    /* | 
 | 	    * SPEC: Substitution Group OK (Transitive) (2.3) | 
 | 	    * "The set of all {derivation method}s involved in the | 
 | 	    * derivation of D's {type definition} from C's {type definition} | 
 | 	    * does not intersect with the union of the blocking constraint, | 
 | 	    * C's {prohibited substitutions} (if C is complex, otherwise the | 
 | 	    * empty set) and the {prohibited substitutions} (respectively the | 
 | 	    * empty set) of any intermediate {type definition}s in the | 
 | 	    * derivation of D's {type definition} from C's {type definition}." | 
 | 	    */ | 
 | 	    /* | 
 | 	    * OPTIMIZE TODO: Optimize this a bit, since, if traversing the | 
 | 	    * subst.head axis, the methSet does not need to be computed for | 
 | 	    * the full depth over and over. | 
 | 	    */ | 
 | 	    /* | 
 | 	    * The set of all {derivation method}s involved in the derivation | 
 | 	    */ | 
 | 	    while ((type != NULL) && (type != headType)) { | 
 | 		if ((WXS_IS_EXTENSION(type)) && | 
 | 		    ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0)) | 
 | 		    methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION; | 
 |  | 
 | 		if (WXS_IS_RESTRICTION(type) && | 
 | 		    ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0)) | 
 | 		    methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION; | 
 |  | 
 | 		type = type->baseType; | 
 | 	    } | 
 | 	    /* | 
 | 	    * The {prohibited substitutions} of all intermediate types + | 
 | 	    * the head's type. | 
 | 	    */ | 
 | 	    type = elemDecl->subtypes->baseType; | 
 | 	    while (type != NULL) { | 
 | 		if (WXS_IS_COMPLEX(type)) { | 
 | 		    if ((type->flags & | 
 | 			    XML_SCHEMAS_TYPE_BLOCK_EXTENSION) && | 
 | 			((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0)) | 
 | 		    set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION; | 
 | 		    if ((type->flags & | 
 | 			    XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) && | 
 | 			((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0)) | 
 | 		    set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION; | 
 | 		} else | 
 | 		    break; | 
 | 		if (type == headType) | 
 | 		    break; | 
 | 		type = type->baseType; | 
 | 	    } | 
 | 	    if ((set != 0) && | 
 | 		(((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) && | 
 | 		(methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) || | 
 | 		((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) && | 
 | 		(methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) { | 
 | 		continue; | 
 | 	    } | 
 | add_member: | 
 | 	    xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl); | 
 | 	    if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0) | 
 | 		head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD; | 
 | 	} | 
 |     } | 
 | } | 
 |  | 
 | #ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */ | 
 | /** | 
 |  * xmlSchemaCheckElementDeclComponent | 
 |  * @pctxt: the schema parser context | 
 |  * @ctxtComponent: the context component (an element declaration) | 
 |  * @ctxtParticle: the first particle of the context component | 
 |  * @searchParticle: the element declaration particle to be analysed | 
 |  * | 
 |  * Schema Component Constraint: Element Declarations Consistent | 
 |  */ | 
 | static int | 
 | xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt, | 
 | 				    xmlSchemaBasicItemPtr ctxtComponent, | 
 | 				    xmlSchemaParticlePtr ctxtParticle, | 
 | 				    xmlSchemaParticlePtr searchParticle, | 
 | 				    xmlSchemaParticlePtr curParticle, | 
 | 				    int search) | 
 | { | 
 |     return(0); | 
 |  | 
 |     int ret = 0; | 
 |     xmlSchemaParticlePtr cur = curParticle; | 
 |     if (curParticle == NULL) { | 
 | 	return(0); | 
 |     } | 
 |     if (WXS_PARTICLE_TERM(curParticle) == NULL) { | 
 | 	/* | 
 | 	* Just return in this case. A missing "term" of the particle | 
 | 	* might arise due to an invalid "term" component. | 
 | 	*/ | 
 | 	return(0); | 
 |     } | 
 |     while (cur != NULL) { | 
 | 	switch (WXS_PARTICLE_TERM(cur)->type) { | 
 | 	    case XML_SCHEMA_TYPE_ANY: | 
 | 		break; | 
 | 	    case XML_SCHEMA_TYPE_ELEMENT: | 
 | 		if (search == 0) { | 
 | 		    ret = xmlSchemaCheckElementDeclConsistent(pctxt, | 
 | 			ctxtComponent, ctxtParticle, cur, ctxtParticle, 1); | 
 | 		    if (ret != 0) | 
 | 			return(ret); | 
 | 		} else { | 
 | 		    xmlSchemaElementPtr elem = | 
 | 			WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur)); | 
 | 		    /* | 
 | 		    * SPEC Element Declarations Consistent: | 
 | 		    * "If the {particles} contains, either directly, | 
 | 		    * indirectly (that is, within the {particles} of a | 
 | 		    * contained model group, recursively) or �implicitly� | 
 | 		    * two or more element declaration particles with | 
 | 		    * the same {name} and {target namespace}, then | 
 | 		    * all their type definitions must be the same | 
 | 		    * top-level definition [...]" | 
 | 		    */ | 
 | 		    if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name, | 
 | 			    WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) && | 
 | 			xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace, | 
 | 			    WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace)) | 
 | 		    { | 
 | 			xmlChar *strA = NULL, *strB = NULL; | 
 |  | 
 | 			xmlSchemaCustomErr(ACTXT_CAST pctxt, | 
 | 			    /* TODO: error code */ | 
 | 			    XML_SCHEMAP_COS_NONAMBIG, | 
 | 			    WXS_ITEM_NODE(cur), NULL, | 
 | 			    "In the content model of %s, there are multiple " | 
 | 			    "element declarations for '%s' with different " | 
 | 			    "type definitions", | 
 | 			    xmlSchemaGetComponentDesignation(&strA, | 
 | 				ctxtComponent), | 
 | 			    xmlSchemaFormatQName(&strB, | 
 | 				WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace, | 
 | 				WXS_PARTICLE_TERM_AS_ELEM(cur)->name)); | 
 | 			FREE_AND_NULL(strA); | 
 | 			FREE_AND_NULL(strB); | 
 | 			return(XML_SCHEMAP_COS_NONAMBIG); | 
 | 		    } | 
 | 		} | 
 | 		break; | 
 | 	    case XML_SCHEMA_TYPE_SEQUENCE: { | 
 | 		break; | 
 | 		} | 
 | 	    case XML_SCHEMA_TYPE_CHOICE:{ | 
 | 		/* | 
 | 		xmlSchemaTreeItemPtr sub; | 
 |  | 
 | 		sub = WXS_PARTICLE_TERM(particle)->children;  (xmlSchemaParticlePtr) | 
 | 		while (sub != NULL) { | 
 | 		    ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent, | 
 | 			ctxtParticle, ctxtElem); | 
 | 		    if (ret != 0) | 
 | 			return(ret); | 
 | 		    sub = sub->next; | 
 | 		} | 
 | 		*/ | 
 | 		break; | 
 | 		} | 
 | 	    case XML_SCHEMA_TYPE_ALL: | 
 | 		break; | 
 | 	    case XML_SCHEMA_TYPE_GROUP: | 
 | 		break; | 
 | 	    default: | 
 | 		xmlSchemaInternalErr2(ACTXT_CAST pctxt, | 
 | 		    "xmlSchemaCheckElementDeclConsistent", | 
 | 		    "found unexpected term of type '%s' in content model", | 
 | 		    WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL); | 
 | 		return(-1); | 
 | 	} | 
 | 	cur = (xmlSchemaParticlePtr) cur->next; | 
 |     } | 
 |  | 
 | exit: | 
 |     return(ret); | 
 | } | 
 | #endif | 
 |  | 
 | /** | 
 |  * xmlSchemaCheckElementDeclComponent | 
 |  * @item:  an schema element declaration/particle | 
 |  * @ctxt:  a schema parser context | 
 |  * @name:  the name of the attribute | 
 |  * | 
 |  * Validates the value constraints of an element declaration. | 
 |  * Adds substitution group members. | 
 |  */ | 
 | static void | 
 | xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl, | 
 | 				   xmlSchemaParserCtxtPtr ctxt) | 
 | { | 
 |     if (elemDecl == NULL) | 
 | 	return; | 
 |     if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) | 
 | 	return; | 
 |     elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED; | 
 |     if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) { | 
 | 	/* | 
 | 	* Adds substitution group members. | 
 | 	*/ | 
 | 	xmlSchemaCheckElemSubstGroup(ctxt, elemDecl); | 
 |     } | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaResolveModelGroupParticleReferences: | 
 |  * @particle:  a particle component | 
 |  * @ctxt:  a parser context | 
 |  * | 
 |  * Resolves references of a model group's {particles} to | 
 |  * model group definitions and to element declarations. | 
 |  */ | 
 | static void | 
 | xmlSchemaResolveModelGroupParticleReferences( | 
 |     xmlSchemaParserCtxtPtr ctxt, | 
 |     xmlSchemaModelGroupPtr mg) | 
 | { | 
 |     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg); | 
 |     xmlSchemaQNameRefPtr ref; | 
 |     xmlSchemaBasicItemPtr refItem; | 
 |  | 
 |     /* | 
 |     * URGENT TODO: Test this. | 
 |     */ | 
 |     while (particle != NULL) { | 
 | 	if ((WXS_PARTICLE_TERM(particle) == NULL) || | 
 | 	    ((WXS_PARTICLE_TERM(particle))->type != | 
 | 		XML_SCHEMA_EXTRA_QNAMEREF)) | 
 | 	{ | 
 | 	    goto next_particle; | 
 | 	} | 
 | 	ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle); | 
 | 	/* | 
 | 	* Resolve the reference. | 
 | 	* NULL the {term} by default. | 
 | 	*/ | 
 | 	particle->children = NULL; | 
 |  | 
 | 	refItem = xmlSchemaGetNamedComponent(ctxt->schema, | 
 | 	    ref->itemType, ref->name, ref->targetNamespace); | 
 | 	if (refItem == NULL) { | 
 | 	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE, | 
 | 		NULL, WXS_ITEM_NODE(particle), "ref", ref->name, | 
 | 		ref->targetNamespace, ref->itemType, NULL); | 
 | 	    /* TODO: remove the particle. */ | 
 | 	    goto next_particle; | 
 | 	} | 
 | 	if (refItem->type == XML_SCHEMA_TYPE_GROUP) { | 
 | 	    if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL) | 
 | 		/* TODO: remove the particle. */ | 
 | 		goto next_particle; | 
 | 	    /* | 
 | 	    * NOTE that we will assign the model group definition | 
 | 	    * itself to the "term" of the particle. This will ease | 
 | 	    * the check for circular model group definitions. After | 
 | 	    * that the "term" will be assigned the model group of the | 
 | 	    * model group definition. | 
 | 	    */ | 
 | 	    if ((WXS_MODELGROUPDEF_MODEL(refItem))->type == | 
 | 		    XML_SCHEMA_TYPE_ALL) { | 
 | 		/* | 
 | 		* SPEC cos-all-limited (1) | 
 | 		* SPEC cos-all-limited (1.2) | 
 | 		* "It appears only as the value of one or both of the | 
 | 		* following properties:" | 
 | 		* (1.1) "the {model group} property of a model group | 
 | 		*        definition." | 
 | 		* (1.2) "the {term} property of a particle [... of] the " | 
 | 		* {content type} of a complex type definition." | 
 | 		*/ | 
 | 		xmlSchemaCustomErr(ACTXT_CAST ctxt, | 
 | 		    /* TODO: error code */ | 
 | 		    XML_SCHEMAP_COS_ALL_LIMITED, | 
 | 		    WXS_ITEM_NODE(particle), NULL, | 
 | 		    "A model group definition is referenced, but " | 
 | 		    "it contains an 'all' model group, which " | 
 | 		    "cannot be contained by model groups", | 
 | 		    NULL, NULL); | 
 | 		/* TODO: remove the particle. */ | 
 | 		goto next_particle; | 
 | 	    } | 
 | 	    particle->children = (xmlSchemaTreeItemPtr) refItem; | 
 | 	} else { | 
 | 	    /* | 
 | 	    * TODO: Are referenced element declarations the only | 
 | 	    * other components we expect here? | 
 | 	    */ | 
 | 	    particle->children = (xmlSchemaTreeItemPtr) refItem; | 
 | 	} | 
 | next_particle: | 
 | 	particle = WXS_PTC_CAST particle->next; | 
 |     } | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaAreValuesEqual(xmlSchemaValPtr x, | 
 | 		       xmlSchemaValPtr y) | 
 | { | 
 |     xmlSchemaTypePtr tx, ty, ptx, pty; | 
 |     int ret; | 
 |  | 
 |     while (x != NULL) { | 
 | 	/* Same types. */ | 
 | 	tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x)); | 
 | 	ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y)); | 
 | 	ptx = xmlSchemaGetPrimitiveType(tx); | 
 | 	pty = xmlSchemaGetPrimitiveType(ty); | 
 | 	/* | 
 | 	* (1) if a datatype T' is �derived� by �restriction� from an | 
 | 	* atomic datatype T then the �value space� of T' is a subset of | 
 | 	* the �value space� of T. */ | 
 | 	/* | 
 | 	* (2) if datatypes T' and T'' are �derived� by �restriction� | 
 | 	* from a common atomic ancestor T then the �value space�s of T' | 
 | 	* and T'' may overlap. | 
 | 	*/ | 
 | 	if (ptx != pty) | 
 | 	    return(0); | 
 | 	/* | 
 | 	* We assume computed values to be normalized, so do a fast | 
 | 	* string comparison for string based types. | 
 | 	*/ | 
 | 	if ((ptx->builtInType == XML_SCHEMAS_STRING) || | 
 | 	    WXS_IS_ANY_SIMPLE_TYPE(ptx)) { | 
 | 	    if (! xmlStrEqual( | 
 | 		xmlSchemaValueGetAsString(x), | 
 | 		xmlSchemaValueGetAsString(y))) | 
 | 		return (0); | 
 | 	} else { | 
 | 	    ret = xmlSchemaCompareValuesWhtsp( | 
 | 		x, XML_SCHEMA_WHITESPACE_PRESERVE, | 
 | 		y, XML_SCHEMA_WHITESPACE_PRESERVE); | 
 | 	    if (ret == -2) | 
 | 		return(-1); | 
 | 	    if (ret != 0) | 
 | 		return(0); | 
 | 	} | 
 | 	/* | 
 | 	* Lists. | 
 | 	*/ | 
 | 	x = xmlSchemaValueGetNext(x); | 
 | 	if (x != NULL) { | 
 | 	    y = xmlSchemaValueGetNext(y); | 
 | 	    if (y == NULL) | 
 | 		return (0); | 
 | 	} else if (xmlSchemaValueGetNext(y) != NULL) | 
 | 	    return (0); | 
 | 	else | 
 | 	    return (1); | 
 |     } | 
 |     return (0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaResolveAttrUseReferences: | 
 |  * @item:  an attribute use | 
 |  * @ctxt:  a parser context | 
 |  * | 
 |  * Resolves the referenced attribute declaration. | 
 |  */ | 
 | static int | 
 | xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause, | 
 | 				  xmlSchemaParserCtxtPtr ctxt) | 
 | { | 
 |     if ((ctxt == NULL) || (ause == NULL)) | 
 | 	return(-1); | 
 |     if ((ause->attrDecl == NULL) || | 
 | 	(ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF)) | 
 | 	return(0); | 
 |  | 
 |     { | 
 | 	xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl; | 
 |  | 
 | 	/* | 
 | 	* TODO: Evaluate, what errors could occur if the declaration is not | 
 | 	* found. | 
 | 	*/ | 
 | 	ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema, | 
 | 	    ref->name, ref->targetNamespace); | 
 |         if (ause->attrDecl == NULL) { | 
 | 	    xmlSchemaPResCompAttrErr(ctxt, | 
 | 	    	XML_SCHEMAP_SRC_RESOLVE, | 
 | 		WXS_BASIC_CAST ause, ause->node, | 
 | 		"ref", ref->name, ref->targetNamespace, | 
 | 		XML_SCHEMA_TYPE_ATTRIBUTE, NULL); | 
 |             return(ctxt->err);; | 
 |         } | 
 |     } | 
 |     return(0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaCheckAttrUsePropsCorrect: | 
 |  * @ctxt:  a parser context | 
 |  * @use:  an attribute use | 
 |  * | 
 |  * Schema Component Constraint: | 
 |  * Attribute Use Correct (au-props-correct) | 
 |  * | 
 |  */ | 
 | static int | 
 | xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt, | 
 | 			     xmlSchemaAttributeUsePtr use) | 
 | { | 
 |     if ((ctxt == NULL) || (use == NULL)) | 
 | 	return(-1); | 
 |     if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) || | 
 | 	((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE)) | 
 | 	return(0); | 
 |  | 
 |     /* | 
 |     * SPEC au-props-correct (1) | 
 |     * "The values of the properties of an attribute use must be as | 
 |     * described in the property tableau in The Attribute Use Schema | 
 |     * Component (�3.5.1), modulo the impact of Missing | 
 |     * Sub-components (�5.3)." | 
 |     */ | 
 |  | 
 |     if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) && | 
 | 	((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) && | 
 |         ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0)) | 
 |     { | 
 | 	xmlSchemaPCustomErr(ctxt, | 
 | 	    XML_SCHEMAP_AU_PROPS_CORRECT_2, | 
 | 	    WXS_BASIC_CAST use, NULL, | 
 | 	    "The attribute declaration has a 'fixed' value constraint " | 
 | 	    ", thus the attribute use must also have a 'fixed' value " | 
 | 	    "constraint", | 
 | 	    NULL); | 
 | 	return(ctxt->err); | 
 |     } | 
 |     /* | 
 |     * Compute and check the value constraint's value. | 
 |     */ | 
 |     if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) { | 
 | 	int ret; | 
 | 	/* | 
 | 	* TODO: The spec seems to be missing a check of the | 
 | 	* value constraint of the attribute use. We will do it here. | 
 | 	*/ | 
 | 	/* | 
 | 	* SPEC a-props-correct (3) | 
 | 	*/ | 
 | 	if (xmlSchemaIsDerivedFromBuiltInType( | 
 | 	    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID)) | 
 | 	{ | 
 | 	    xmlSchemaCustomErr(ACTXT_CAST ctxt, | 
 | 		XML_SCHEMAP_AU_PROPS_CORRECT, | 
 | 		NULL, WXS_BASIC_CAST use, | 
 | 		"Value constraints are not allowed if the type definition " | 
 | 		"is or is derived from xs:ID", | 
 | 		NULL, NULL); | 
 | 	    return(ctxt->err); | 
 | 	} | 
 |  | 
 | 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt, | 
 | 	    use->node, WXS_ATTRUSE_TYPEDEF(use), | 
 | 	    use->defValue, &(use->defVal), | 
 | 	    1, 1, 0); | 
 | 	if (ret != 0) { | 
 | 	    if (ret < 0) { | 
 | 		PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect", | 
 | 		    "calling xmlSchemaVCheckCVCSimpleType()"); | 
 | 		return(-1); | 
 | 	    } | 
 | 	    xmlSchemaCustomErr(ACTXT_CAST ctxt, | 
 | 		XML_SCHEMAP_AU_PROPS_CORRECT, | 
 | 		NULL, WXS_BASIC_CAST use, | 
 | 		"The value of the value constraint is not valid", | 
 | 		NULL, NULL); | 
 | 	    return(ctxt->err); | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * SPEC au-props-correct (2) | 
 |     * "If the {attribute declaration} has a fixed | 
 |     * {value constraint}, then if the attribute use itself has a | 
 |     * {value constraint}, it must also be fixed and its value must match | 
 |     * that of the {attribute declaration}'s {value constraint}." | 
 |     */ | 
 |     if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) && | 
 | 	(((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0)) | 
 |     { | 
 | 	if (! xmlSchemaAreValuesEqual(use->defVal, | 
 | 		(WXS_ATTRUSE_DECL(use))->defVal)) | 
 | 	{ | 
 | 	    xmlSchemaPCustomErr(ctxt, | 
 | 		XML_SCHEMAP_AU_PROPS_CORRECT_2, | 
 | 		WXS_BASIC_CAST use, NULL, | 
 | 		"The 'fixed' value constraint of the attribute use " | 
 | 		"must match the attribute declaration's value " | 
 | 		"constraint '%s'", | 
 | 		(WXS_ATTRUSE_DECL(use))->defValue); | 
 | 	} | 
 | 	return(ctxt->err); | 
 |     } | 
 |     return(0); | 
 | } | 
 |  | 
 |  | 
 |  | 
 |  | 
 | /** | 
 |  * xmlSchemaResolveAttrTypeReferences: | 
 |  * @item:  an attribute declaration | 
 |  * @ctxt:  a parser context | 
 |  * | 
 |  * Resolves the referenced type definition component. | 
 |  */ | 
 | static int | 
 | xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item, | 
 | 				   xmlSchemaParserCtxtPtr ctxt) | 
 | { | 
 |     /* | 
 |     * The simple type definition corresponding to the <simpleType> element | 
 |     * information item in the [children], if present, otherwise the simple | 
 |     * type definition �resolved� to by the �actual value� of the type | 
 |     * [attribute], if present, otherwise the �simple ur-type definition�. | 
 |     */ | 
 |     if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED) | 
 | 	return(0); | 
 |     item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED; | 
 |     if (item->subtypes != NULL) | 
 |         return(0); | 
 |     if (item->typeName != NULL) { | 
 |         xmlSchemaTypePtr type; | 
 |  | 
 | 	type = xmlSchemaGetType(ctxt->schema, item->typeName, | 
 | 	    item->typeNs); | 
 | 	if ((type == NULL) || (! WXS_IS_SIMPLE(type))) { | 
 | 	    xmlSchemaPResCompAttrErr(ctxt, | 
 | 		XML_SCHEMAP_SRC_RESOLVE, | 
 | 		WXS_BASIC_CAST item, item->node, | 
 | 		"type", item->typeName, item->typeNs, | 
 | 		XML_SCHEMA_TYPE_SIMPLE, NULL); | 
 | 	    return(ctxt->err); | 
 | 	} else | 
 | 	    item->subtypes = type; | 
 |  | 
 |     } else { | 
 | 	/* | 
 | 	* The type defaults to the xs:anySimpleType. | 
 | 	*/ | 
 | 	item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE); | 
 |     } | 
 |     return(0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaResolveIDCKeyReferences: | 
 |  * @idc:  the identity-constraint definition | 
 |  * @ctxt:  the schema parser context | 
 |  * @name:  the attribute name | 
 |  * | 
 |  * Resolve keyRef references to key/unique IDCs. | 
 |  * Schema Component Constraint: | 
 |  *   Identity-constraint Definition Properties Correct (c-props-correct) | 
 |  */ | 
 | static int | 
 | xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc, | 
 | 			  xmlSchemaParserCtxtPtr pctxt) | 
 | { | 
 |     if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) | 
 |         return(0); | 
 |     if (idc->ref->name != NULL) { | 
 | 	idc->ref->item = (xmlSchemaBasicItemPtr) | 
 | 	    xmlSchemaGetIDC(pctxt->schema, idc->ref->name, | 
 | 		idc->ref->targetNamespace); | 
 |         if (idc->ref->item == NULL) { | 
 | 	    /* | 
 | 	    * TODO: It is actually not an error to fail to resolve | 
 | 	    * at this stage. BUT we need to be that strict! | 
 | 	    */ | 
 | 	    xmlSchemaPResCompAttrErr(pctxt, | 
 | 		XML_SCHEMAP_SRC_RESOLVE, | 
 | 		WXS_BASIC_CAST idc, idc->node, | 
 | 		"refer", idc->ref->name, | 
 | 		idc->ref->targetNamespace, | 
 | 		XML_SCHEMA_TYPE_IDC_KEY, NULL); | 
 |             return(pctxt->err); | 
 | 	} else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) { | 
 | 	    /* | 
 | 	    * SPEC c-props-correct (1) | 
 | 	    */ | 
 | 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, | 
 | 		XML_SCHEMAP_C_PROPS_CORRECT, | 
 | 		NULL, WXS_BASIC_CAST idc, | 
 | 		"The keyref references a keyref", | 
 | 		NULL, NULL); | 
 | 	    idc->ref->item = NULL; | 
 | 	    return(pctxt->err); | 
 | 	} else { | 
 | 	    if (idc->nbFields != | 
 | 		((xmlSchemaIDCPtr) idc->ref->item)->nbFields) { | 
 | 		xmlChar *str = NULL; | 
 | 		xmlSchemaIDCPtr refer; | 
 |  | 
 | 		refer = (xmlSchemaIDCPtr) idc->ref->item; | 
 | 		/* | 
 | 		* SPEC c-props-correct(2) | 
 | 		* "If the {identity-constraint category} is keyref, | 
 | 		* the cardinality of the {fields} must equal that of | 
 | 		* the {fields} of the {referenced key}. | 
 | 		*/ | 
 | 		xmlSchemaCustomErr(ACTXT_CAST pctxt, | 
 | 		    XML_SCHEMAP_C_PROPS_CORRECT, | 
 | 		    NULL, WXS_BASIC_CAST idc, | 
 | 		    "The cardinality of the keyref differs from the " | 
 | 		    "cardinality of the referenced key/unique '%s'", | 
 | 		    xmlSchemaFormatQName(&str, refer->targetNamespace, | 
 | 			refer->name), | 
 | 		    NULL); | 
 | 		FREE_AND_NULL(str) | 
 | 		return(pctxt->err); | 
 | 	    } | 
 | 	} | 
 |     } | 
 |     return(0); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib, | 
 | 				       xmlSchemaParserCtxtPtr pctxt) | 
 | { | 
 |     if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name, | 
 | 	prohib->targetNamespace) == NULL) { | 
 |  | 
 | 	xmlSchemaPResCompAttrErr(pctxt, | 
 | 	    XML_SCHEMAP_SRC_RESOLVE, | 
 | 	    NULL, prohib->node, | 
 | 	    "ref", prohib->name, prohib->targetNamespace, | 
 | 	    XML_SCHEMA_TYPE_ATTRIBUTE, NULL); | 
 | 	return(XML_SCHEMAP_SRC_RESOLVE); | 
 |     } | 
 |     return(0); | 
 | } | 
 |  | 
 | #define WXS_REDEFINED_TYPE(c) \ | 
 | (((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED) | 
 |  | 
 | #define WXS_REDEFINED_MODEL_GROUP_DEF(c) \ | 
 | (((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED) | 
 |  | 
 | #define WXS_REDEFINED_ATTR_GROUP(c) \ | 
 | (((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED) | 
 |  | 
 | static int | 
 | xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt) | 
 | { | 
 |     int err = 0; | 
 |     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs; | 
 |     xmlSchemaBasicItemPtr prev, item; | 
 |     int wasRedefined; | 
 |  | 
 |     if (redef == NULL) | 
 | 	return(0); | 
 |  | 
 |     do { | 
 | 	item = redef->item; | 
 | 	/* | 
 | 	* First try to locate the redefined component in the | 
 | 	* schema graph starting with the redefined schema. | 
 | 	* NOTE: According to this schema bug entry: | 
 | 	*   http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html | 
 | 	*   it's not clear if the referenced component needs to originate | 
 | 	*   from the <redefine>d schema _document_ or the schema; the latter | 
 | 	*   would include all imported and included sub-schemas of the | 
 | 	*   <redefine>d schema. Currenlty we latter approach is used. | 
 | 	*   SUPPLEMENT: It seems that the WG moves towards the latter | 
 | 	*   approach, so we are doing it right. | 
 | 	* | 
 | 	*/ | 
 | 	prev = xmlSchemaFindRedefCompInGraph( | 
 | 	    redef->targetBucket, item->type, | 
 | 	    redef->refName, redef->refTargetNs); | 
 | 	if (prev == NULL) { | 
 | 	    xmlChar *str = NULL; | 
 | 	    xmlNodePtr node; | 
 |  | 
 | 	    /* | 
 | 	    * SPEC src-redefine: | 
 | 	    * (6.2.1) "The �actual value� of its own name attribute plus | 
 | 	    * target namespace must successfully �resolve� to a model | 
 | 	    * group definition in I." | 
 | 	    * (7.2.1) "The �actual value� of its own name attribute plus | 
 | 	    * target namespace must successfully �resolve� to an attribute | 
 | 	    * group definition in I." | 
 |  | 
 | 	    * | 
 | 	    * Note that, if we are redefining with the use of references | 
 | 	    * to components, the spec assumes the src-resolve to be used; | 
 | 	    * but this won't assure that we search only *inside* the | 
 | 	    * redefined schema. | 
 | 	    */ | 
 | 	    if (redef->reference) | 
 | 		node = WXS_ITEM_NODE(redef->reference); | 
 | 	    else | 
 | 		node = WXS_ITEM_NODE(item); | 
 | 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, | 
 | 		/* | 
 | 		* TODO: error code. | 
 | 		* Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the | 
 | 		* reference kind. | 
 | 		*/ | 
 | 		XML_SCHEMAP_SRC_REDEFINE, node, NULL, | 
 | 		"The %s '%s' to be redefined could not be found in " | 
 | 		"the redefined schema", | 
 | 		WXS_ITEM_TYPE_NAME(item), | 
 | 		xmlSchemaFormatQName(&str, redef->refTargetNs, | 
 | 		    redef->refName)); | 
 | 	    FREE_AND_NULL(str); | 
 | 	    err = pctxt->err; | 
 | 	    redef = redef->next; | 
 | 	    continue; | 
 | 	} | 
 | 	/* | 
 | 	* TODO: Obtaining and setting the redefinition state is really | 
 | 	* clumsy. | 
 | 	*/ | 
 | 	wasRedefined = 0; | 
 | 	switch (item->type) { | 
 | 	    case XML_SCHEMA_TYPE_COMPLEX: | 
 | 	    case XML_SCHEMA_TYPE_SIMPLE: | 
 | 		if ((WXS_TYPE_CAST prev)->flags & | 
 | 		    XML_SCHEMAS_TYPE_REDEFINED) | 
 | 		{ | 
 | 		    wasRedefined = 1; | 
 | 		    break; | 
 | 		} | 
 | 		/* Mark it as redefined. */ | 
 | 		(WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED; | 
 | 		/* | 
 | 		* Assign the redefined type to the | 
 | 		* base type of the redefining type. | 
 | 		* TODO: How | 
 | 		*/ | 
 | 		((xmlSchemaTypePtr) item)->baseType = | 
 | 		    (xmlSchemaTypePtr) prev; | 
 | 		break; | 
 | 	    case XML_SCHEMA_TYPE_GROUP: | 
 | 		if ((WXS_MODEL_GROUPDEF_CAST prev)->flags & | 
 | 		    XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED) | 
 | 		{ | 
 | 		    wasRedefined = 1; | 
 | 		    break; | 
 | 		} | 
 | 		/* Mark it as redefined. */ | 
 | 		(WXS_MODEL_GROUPDEF_CAST prev)->flags |= | 
 | 		    XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED; | 
 | 		if (redef->reference != NULL) { | 
 | 		    /* | 
 | 		    * Overwrite the QName-reference with the | 
 | 		    * referenced model group def. | 
 | 		    */ | 
 | 		    (WXS_PTC_CAST redef->reference)->children = | 
 | 			WXS_TREE_CAST prev; | 
 | 		} | 
 | 		redef->target = prev; | 
 | 		break; | 
 | 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: | 
 | 		if ((WXS_ATTR_GROUP_CAST prev)->flags & | 
 | 		    XML_SCHEMAS_ATTRGROUP_REDEFINED) | 
 | 		{ | 
 | 		    wasRedefined = 1; | 
 | 		    break; | 
 | 		} | 
 | 		(WXS_ATTR_GROUP_CAST prev)->flags |= | 
 | 		    XML_SCHEMAS_ATTRGROUP_REDEFINED; | 
 | 		if (redef->reference != NULL) { | 
 | 		    /* | 
 | 		    * Assign the redefined attribute group to the | 
 | 		    * QName-reference component. | 
 | 		    * This is the easy case, since we will just | 
 | 		    * expand the redefined group. | 
 | 		    */ | 
 | 		    (WXS_QNAME_CAST redef->reference)->item = prev; | 
 | 		    redef->target = NULL; | 
 | 		} else { | 
 | 		    /* | 
 | 		    * This is the complicated case: we need | 
 | 		    * to apply src-redefine (7.2.2) at a later | 
 | 		    * stage, i.e. when attribute group references | 
 | 		    * have beed expanded and simple types have | 
 | 		    * beed fixed. | 
 | 		    */ | 
 | 		    redef->target = prev; | 
 | 		} | 
 | 		break; | 
 | 	    default: | 
 | 		PERROR_INT("xmlSchemaResolveRedefReferences", | 
 | 		    "Unexpected redefined component type"); | 
 | 		return(-1); | 
 | 	} | 
 | 	if (wasRedefined) { | 
 | 	    xmlChar *str = NULL; | 
 | 	    xmlNodePtr node; | 
 |  | 
 | 	    if (redef->reference) | 
 | 		node = WXS_ITEM_NODE(redef->reference); | 
 | 	    else | 
 | 		node = WXS_ITEM_NODE(redef->item); | 
 |  | 
 | 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, | 
 | 		/* TODO: error code. */ | 
 | 		XML_SCHEMAP_SRC_REDEFINE, | 
 | 		node, NULL, | 
 | 		"The referenced %s was already redefined. Multiple " | 
 | 		"redefinition of the same component is not supported", | 
 | 		xmlSchemaGetComponentDesignation(&str, prev), | 
 | 		NULL); | 
 | 	    FREE_AND_NULL(str) | 
 | 	    err = pctxt->err; | 
 | 	    redef = redef->next; | 
 | 	    continue; | 
 | 	} | 
 | 	redef = redef->next; | 
 |     } while (redef != NULL); | 
 |  | 
 |     return(err); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt) | 
 | { | 
 |     int err = 0; | 
 |     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs; | 
 |     xmlSchemaBasicItemPtr item; | 
 |  | 
 |     if (redef == NULL) | 
 | 	return(0); | 
 |  | 
 |     do { | 
 | 	if (redef->target == NULL) { | 
 | 	    redef = redef->next; | 
 | 	    continue; | 
 | 	} | 
 | 	item = redef->item; | 
 |  | 
 | 	switch (item->type) { | 
 | 	    case XML_SCHEMA_TYPE_SIMPLE: | 
 | 	    case XML_SCHEMA_TYPE_COMPLEX: | 
 | 		/* | 
 | 		* Since the spec wants the {name} of the redefined | 
 | 		* type to be 'absent', we'll NULL it. | 
 | 		*/ | 
 | 		(WXS_TYPE_CAST redef->target)->name = NULL; | 
 |  | 
 | 		/* | 
 | 		* TODO: Seems like there's nothing more to do. The normal | 
 | 		* inheritance mechanism is used. But not 100% sure. | 
 | 		*/ | 
 | 		break; | 
 | 	    case XML_SCHEMA_TYPE_GROUP: | 
 | 		/* | 
 | 		* URGENT TODO: | 
 | 		* SPEC src-redefine: | 
 | 		* (6.2.2) "The {model group} of the model group definition | 
 | 		* which corresponds to it per XML Representation of Model | 
 | 		* Group Definition Schema Components (�3.7.2) must be a | 
 | 		* �valid restriction� of the {model group} of that model | 
 | 		* group definition in I, as defined in Particle Valid | 
 | 		* (Restriction) (�3.9.6)." | 
 | 		*/ | 
 | 		break; | 
 | 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: | 
 | 		/* | 
 | 		* SPEC src-redefine: | 
 | 		* (7.2.2) "The {attribute uses} and {attribute wildcard} of | 
 | 		* the attribute group definition which corresponds to it | 
 | 		* per XML Representation of Attribute Group Definition Schema | 
 | 		* Components (�3.6.2) must be �valid restrictions� of the | 
 | 		* {attribute uses} and {attribute wildcard} of that attribute | 
 | 		* group definition in I, as defined in clause 2, clause 3 and | 
 | 		* clause 4 of Derivation Valid (Restriction, Complex) | 
 | 		* (�3.4.6) (where references to the base type definition are | 
 | 		* understood as references to the attribute group definition | 
 | 		* in I)." | 
 | 		*/ | 
 | 		err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt, | 
 | 		    XML_SCHEMA_ACTION_REDEFINE, | 
 | 		    item, redef->target, | 
 | 		    (WXS_ATTR_GROUP_CAST item)->attrUses, | 
 | 		    (WXS_ATTR_GROUP_CAST redef->target)->attrUses, | 
 | 		    (WXS_ATTR_GROUP_CAST item)->attributeWildcard, | 
 | 		    (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard); | 
 | 		if (err == -1) | 
 | 		    return(-1); | 
 | 		break; | 
 | 	    default: | 
 | 		break; | 
 | 	} | 
 | 	redef = redef->next; | 
 |     } while (redef != NULL); | 
 |     return(0); | 
 | } | 
 |  | 
 |  | 
 | static int | 
 | xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt, | 
 | 		       xmlSchemaBucketPtr bucket) | 
 | { | 
 |     xmlSchemaBasicItemPtr item; | 
 |     int err; | 
 |     xmlHashTablePtr *table; | 
 |     const xmlChar *name; | 
 |     int i; | 
 |  | 
 | #define WXS_GET_GLOBAL_HASH(c, slot) { \ | 
 |     if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \ | 
 | 	table = &(WXS_IMPBUCKET((c))->schema->slot); \ | 
 |     else \ | 
 | 	table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); } | 
 |  | 
 |     /* | 
 |     * Add global components to the schema's hash tables. | 
 |     * This is the place where duplicate components will be | 
 |     * detected. | 
 |     * TODO: I think normally we should support imports of the | 
 |     *   same namespace from multiple locations. We don't do currently, | 
 |     *   but if we do then according to: | 
 |     *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224 | 
 |     *   we would need, if imported directly, to import redefined | 
 |     *   components as well to be able to catch clashing components. | 
 |     *   (I hope I'll still know what this means after some months :-() | 
 |     */ | 
 |     if (bucket == NULL) | 
 | 	return(-1); | 
 |     if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) | 
 | 	return(0); | 
 |     bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED; | 
 |  | 
 |     for (i = 0; i < bucket->globals->nbItems; i++) { | 
 | 	item = bucket->globals->items[i]; | 
 | 	table = NULL; | 
 | 	switch (item->type) { | 
 | 	    case XML_SCHEMA_TYPE_COMPLEX: | 
 | 	    case XML_SCHEMA_TYPE_SIMPLE: | 
 | 		if (WXS_REDEFINED_TYPE(item)) | 
 | 		    continue; | 
 | 		name = (WXS_TYPE_CAST item)->name; | 
 | 		WXS_GET_GLOBAL_HASH(bucket, typeDecl) | 
 | 		break; | 
 | 	    case XML_SCHEMA_TYPE_ELEMENT: | 
 | 		name = (WXS_ELEM_CAST item)->name; | 
 | 		WXS_GET_GLOBAL_HASH(bucket, elemDecl) | 
 | 		break; | 
 | 	    case XML_SCHEMA_TYPE_ATTRIBUTE: | 
 | 		name = (WXS_ATTR_CAST item)->name; | 
 | 		WXS_GET_GLOBAL_HASH(bucket, attrDecl) | 
 | 		break; | 
 | 	    case XML_SCHEMA_TYPE_GROUP: | 
 | 		if (WXS_REDEFINED_MODEL_GROUP_DEF(item)) | 
 | 		    continue; | 
 | 		name = (WXS_MODEL_GROUPDEF_CAST item)->name; | 
 | 		WXS_GET_GLOBAL_HASH(bucket, groupDecl) | 
 | 		break; | 
 | 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: | 
 | 		if (WXS_REDEFINED_ATTR_GROUP(item)) | 
 | 		    continue; | 
 | 		name = (WXS_ATTR_GROUP_CAST item)->name; | 
 | 		WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl) | 
 | 		break; | 
 | 	    case XML_SCHEMA_TYPE_IDC_KEY: | 
 | 	    case XML_SCHEMA_TYPE_IDC_UNIQUE: | 
 | 	    case XML_SCHEMA_TYPE_IDC_KEYREF: | 
 | 		name = (WXS_IDC_CAST item)->name; | 
 | 		WXS_GET_GLOBAL_HASH(bucket, idcDef) | 
 | 		break; | 
 | 	    case XML_SCHEMA_TYPE_NOTATION: | 
 | 		name = ((xmlSchemaNotationPtr) item)->name; | 
 | 		WXS_GET_GLOBAL_HASH(bucket, notaDecl) | 
 | 		break; | 
 | 	    default: | 
 | 		PERROR_INT("xmlSchemaAddComponents", | 
 | 		    "Unexpected global component type"); | 
 | 		continue; | 
 | 	} | 
 | 	if (*table == NULL) { | 
 | 	    *table = xmlHashCreateDict(10, pctxt->dict); | 
 | 	    if (*table == NULL) { | 
 | 		PERROR_INT("xmlSchemaAddComponents", | 
 | 		    "failed to create a component hash table"); | 
 | 		return(-1); | 
 | 	    } | 
 | 	} | 
 | 	err = xmlHashAddEntry(*table, name, item); | 
 | 	if (err != 0) { | 
 | 	    xmlChar *str = NULL; | 
 |  | 
 | 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, | 
 | 		XML_SCHEMAP_REDEFINED_TYPE, | 
 | 		WXS_ITEM_NODE(item), | 
 | 		WXS_BASIC_CAST item, | 
 | 		"A global %s '%s' does already exist", | 
 | 		WXS_ITEM_TYPE_NAME(item), | 
 | 		xmlSchemaGetComponentQName(&str, item)); | 
 | 	    FREE_AND_NULL(str); | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * Process imported/included schemas. | 
 |     */ | 
 |     if (bucket->relations != NULL) { | 
 | 	xmlSchemaSchemaRelationPtr rel = bucket->relations; | 
 | 	do { | 
 | 	    if ((rel->bucket != NULL) && | 
 | 		((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) { | 
 | 		if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1) | 
 | 		    return(-1); | 
 | 	    } | 
 | 	    rel = rel->next; | 
 | 	} while (rel != NULL); | 
 |     } | 
 |     return(0); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt, | 
 | 			 xmlSchemaBucketPtr rootBucket) | 
 | { | 
 |     xmlSchemaConstructionCtxtPtr con = pctxt->constructor; | 
 |     xmlSchemaTreeItemPtr item, *items; | 
 |     int nbItems, i, ret = 0; | 
 |     xmlSchemaBucketPtr oldbucket = con->bucket; | 
 |     xmlSchemaElementPtr elemDecl; | 
 |  | 
 | #define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure; | 
 |  | 
 |     if ((con->pending == NULL) || | 
 | 	(con->pending->nbItems == 0)) | 
 | 	return(0); | 
 |  | 
 |     /* | 
 |     * Since xmlSchemaFixupComplexType() will create new particles | 
 |     * (local components), and those particle components need a bucket | 
 |     * on the constructor, we'll assure here that the constructor has | 
 |     * a bucket. | 
 |     * TODO: Think about storing locals _only_ on the main bucket. | 
 |     */ | 
 |     if (con->bucket == NULL) | 
 | 	con->bucket = rootBucket; | 
 |  | 
 |     /* TODO: | 
 |     * SPEC (src-redefine): | 
 |     * (6.2) "If it has no such self-reference, then all of the | 
 |     * following must be true:" | 
 |  | 
 |     * (6.2.2) The {model group} of the model group definition which | 
 |     * corresponds to it per XML Representation of Model Group | 
 |     * Definition Schema Components (�3.7.2) must be a �valid | 
 |     * restriction� of the {model group} of that model group definition | 
 |     * in I, as defined in Particle Valid (Restriction) (�3.9.6)." | 
 |     */ | 
 |     xmlSchemaCheckSRCRedefineFirst(pctxt); | 
 |  | 
 |     /* | 
 |     * Add global components to the schemata's hash tables. | 
 |     */ | 
 |     xmlSchemaAddComponents(pctxt, rootBucket); | 
 |  | 
 |     pctxt->ctxtType = NULL; | 
 |     items = (xmlSchemaTreeItemPtr *) con->pending->items; | 
 |     nbItems = con->pending->nbItems; | 
 |     /* | 
 |     * Now that we have parsed *all* the schema document(s) and converted | 
 |     * them to schema components, we can resolve references, apply component | 
 |     * constraints, create the FSA from the content model, etc. | 
 |     */ | 
 |     /* | 
 |     * Resolve references of.. | 
 |     * | 
 |     * 1. element declarations: | 
 |     *   - the type definition | 
 |     *   - the substitution group affiliation | 
 |     * 2. simple/complex types: | 
 |     *   - the base type definition | 
 |     *   - the memberTypes of union types | 
 |     *   - the itemType of list types | 
 |     * 3. attributes declarations and attribute uses: | 
 |     *   - the type definition | 
 |     *   - if an attribute use, then the attribute declaration | 
 |     * 4. attribute group references: | 
 |     *   - the attribute group definition | 
 |     * 5. particles: | 
 |     *   - the term of the particle (e.g. a model group) | 
 |     * 6. IDC key-references: | 
 |     *   - the referenced IDC 'key' or 'unique' definition | 
 |     * 7. Attribute prohibitions which had a "ref" attribute. | 
 |     */ | 
 |     for (i = 0; i < nbItems; i++) { | 
 | 	item = items[i]; | 
 | 	switch (item->type) { | 
 | 	    case XML_SCHEMA_TYPE_ELEMENT: | 
 | 		xmlSchemaResolveElementReferences( | 
 | 		    (xmlSchemaElementPtr) item, pctxt); | 
 | 		FIXHFAILURE; | 
 | 		break; | 
 | 	    case XML_SCHEMA_TYPE_COMPLEX: | 
 | 	    case XML_SCHEMA_TYPE_SIMPLE: | 
 | 		xmlSchemaResolveTypeReferences( | 
 | 		    (xmlSchemaTypePtr) item, pctxt); | 
 | 		FIXHFAILURE; | 
 | 		break; | 
 | 	    case XML_SCHEMA_TYPE_ATTRIBUTE: | 
 | 		xmlSchemaResolveAttrTypeReferences( | 
 | 		    (xmlSchemaAttributePtr) item, pctxt); | 
 | 		FIXHFAILURE; | 
 | 		break; | 
 | 	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE: | 
 | 		xmlSchemaResolveAttrUseReferences( | 
 | 		    (xmlSchemaAttributeUsePtr) item, pctxt); | 
 | 		FIXHFAILURE; | 
 | 		break; | 
 | 	    case XML_SCHEMA_EXTRA_QNAMEREF: | 
 | 		if ((WXS_QNAME_CAST item)->itemType == | 
 | 		    XML_SCHEMA_TYPE_ATTRIBUTEGROUP) | 
 | 		{ | 
 | 		    xmlSchemaResolveAttrGroupReferences( | 
 | 			WXS_QNAME_CAST item, pctxt); | 
 | 		} | 
 | 		FIXHFAILURE; | 
 | 		break; | 
 | 	    case XML_SCHEMA_TYPE_SEQUENCE: | 
 | 	    case XML_SCHEMA_TYPE_CHOICE: | 
 | 	    case XML_SCHEMA_TYPE_ALL: | 
 | 		xmlSchemaResolveModelGroupParticleReferences(pctxt, | 
 | 		    WXS_MODEL_GROUP_CAST item); | 
 | 		FIXHFAILURE; | 
 | 		break; | 
 | 	    case XML_SCHEMA_TYPE_IDC_KEY: | 
 | 	    case XML_SCHEMA_TYPE_IDC_UNIQUE: | 
 | 	    case XML_SCHEMA_TYPE_IDC_KEYREF: | 
 | 		xmlSchemaResolveIDCKeyReferences( | 
 | 		    (xmlSchemaIDCPtr) item, pctxt); | 
 | 		FIXHFAILURE; | 
 | 		break; | 
 | 	    case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB: | 
 | 		/* | 
 | 		* Handle attribue prohibition which had a | 
 | 		* "ref" attribute. | 
 | 		*/ | 
 | 		xmlSchemaResolveAttrUseProhibReferences( | 
 | 		    WXS_ATTR_PROHIB_CAST item, pctxt); | 
 | 		FIXHFAILURE; | 
 | 		break; | 
 | 	    default: | 
 | 		break; | 
 | 	} | 
 |     } | 
 |     if (pctxt->nberrors != 0) | 
 | 	goto exit_error; | 
 |  | 
 |     /* | 
 |     * Now that all references are resolved we | 
 |     * can check for circularity of... | 
 |     * 1. the base axis of type definitions | 
 |     * 2. nested model group definitions | 
 |     * 3. nested attribute group definitions | 
 |     * TODO: check for circual substitution groups. | 
 |     */ | 
 |     for (i = 0; i < nbItems; i++) { | 
 | 	item = items[i]; | 
 | 	/* | 
 | 	* Let's better stop on the first error here. | 
 | 	*/ | 
 | 	switch (item->type) { | 
 | 	    case XML_SCHEMA_TYPE_COMPLEX: | 
 | 	    case XML_SCHEMA_TYPE_SIMPLE: | 
 | 		xmlSchemaCheckTypeDefCircular( | 
 | 		    (xmlSchemaTypePtr) item, pctxt); | 
 | 		FIXHFAILURE; | 
 | 		if (pctxt->nberrors != 0) | 
 | 		    goto exit_error; | 
 | 		break; | 
 | 	    case XML_SCHEMA_TYPE_GROUP: | 
 | 		xmlSchemaCheckGroupDefCircular( | 
 | 		    (xmlSchemaModelGroupDefPtr) item, pctxt); | 
 | 		FIXHFAILURE; | 
 | 		if (pctxt->nberrors != 0) | 
 | 		    goto exit_error; | 
 | 		break; | 
 | 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: | 
 | 		xmlSchemaCheckAttrGroupCircular( | 
 | 		    (xmlSchemaAttributeGroupPtr) item, pctxt); | 
 | 		FIXHFAILURE; | 
 | 		if (pctxt->nberrors != 0) | 
 | 		    goto exit_error; | 
 | 		break; | 
 | 	    default: | 
 | 		break; | 
 | 	} | 
 |     } | 
 |     if (pctxt->nberrors != 0) | 
 | 	goto exit_error; | 
 |     /* | 
 |     * Model group definition references: | 
 |     * Such a reference is reflected by a particle at the component | 
 |     * level. Until now the 'term' of such particles pointed | 
 |     * to the model group definition; this was done, in order to | 
 |     * ease circularity checks. Now we need to set the 'term' of | 
 |     * such particles to the model group of the model group definition. | 
 |     */ | 
 |     for (i = 0; i < nbItems; i++) { | 
 | 	item = items[i]; | 
 | 	switch (item->type) { | 
 | 	    case XML_SCHEMA_TYPE_SEQUENCE: | 
 | 	    case XML_SCHEMA_TYPE_CHOICE: | 
 | 		xmlSchemaModelGroupToModelGroupDefFixup(pctxt, | 
 | 		    WXS_MODEL_GROUP_CAST item); | 
 | 		break; | 
 | 	    default: | 
 | 		break; | 
 | 	} | 
 |     } | 
 |     if (pctxt->nberrors != 0) | 
 | 	goto exit_error; | 
 |     /* | 
 |     * Expand attribute group references of attribute group definitions. | 
 |     */ | 
 |     for (i = 0; i < nbItems; i++) { | 
 | 	item = items[i]; | 
 | 	switch (item->type) { | 
 |             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: | 
 | 		if ((! WXS_ATTR_GROUP_EXPANDED(item)) && | 
 | 		    WXS_ATTR_GROUP_HAS_REFS(item)) | 
 | 		{ | 
 | 		    xmlSchemaAttributeGroupExpandRefs(pctxt, | 
 | 			WXS_ATTR_GROUP_CAST item); | 
 | 		    FIXHFAILURE; | 
 | 		} | 
 | 		break; | 
 | 	    default: | 
 | 		break; | 
 | 	} | 
 |     } | 
 |     if (pctxt->nberrors != 0) | 
 | 	goto exit_error; | 
 |     /* | 
 |     * First compute the variety of simple types. This is needed as | 
 |     * a seperate step, since otherwise we won't be able to detect | 
 |     * circular union types in all cases. | 
 |     */ | 
 |     for (i = 0; i < nbItems; i++) { | 
 | 	item = items[i]; | 
 | 	switch (item->type) { | 
 |             case XML_SCHEMA_TYPE_SIMPLE: | 
 | 		if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) { | 
 | 		    xmlSchemaFixupSimpleTypeStageOne(pctxt, | 
 | 			(xmlSchemaTypePtr) item); | 
 | 		    FIXHFAILURE; | 
 | 		} | 
 | 		break; | 
 | 	    default: | 
 | 		break; | 
 | 	} | 
 |     } | 
 |     if (pctxt->nberrors != 0) | 
 | 	goto exit_error; | 
 |     /* | 
 |     * Detect circular union types. Note that this needs the variety to | 
 |     * be already computed. | 
 |     */ | 
 |     for (i = 0; i < nbItems; i++) { | 
 | 	item = items[i]; | 
 | 	switch (item->type) { | 
 |             case XML_SCHEMA_TYPE_SIMPLE: | 
 | 		if (((xmlSchemaTypePtr) item)->memberTypes != NULL) { | 
 | 		    xmlSchemaCheckUnionTypeDefCircular(pctxt, | 
 | 			(xmlSchemaTypePtr) item); | 
 | 		    FIXHFAILURE; | 
 | 		} | 
 | 		break; | 
 | 	    default: | 
 | 		break; | 
 | 	} | 
 |     } | 
 |     if (pctxt->nberrors != 0) | 
 | 	goto exit_error; | 
 |  | 
 |     /* | 
 |     * Do the complete type fixup for simple types. | 
 |     */ | 
 |     for (i = 0; i < nbItems; i++) { | 
 | 	item = items[i]; | 
 | 	switch (item->type) { | 
 |             case XML_SCHEMA_TYPE_SIMPLE: | 
 | 		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) { | 
 | 		    xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item); | 
 | 		    FIXHFAILURE; | 
 | 		} | 
 | 		break; | 
 | 	    default: | 
 | 		break; | 
 | 	} | 
 |     } | 
 |     if (pctxt->nberrors != 0) | 
 | 	goto exit_error; | 
 |     /* | 
 |     * At this point we need build and check all simple types. | 
 |     */ | 
 |     /* | 
 |     * Apply contraints for attribute declarations. | 
 |     */ | 
 |     for (i = 0; i < nbItems; i++) { | 
 | 	item = items[i]; | 
 | 	switch (item->type) { | 
 | 	    case XML_SCHEMA_TYPE_ATTRIBUTE: | 
 | 		xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item); | 
 | 		FIXHFAILURE; | 
 | 		break; | 
 | 	    default: | 
 | 		break; | 
 | 	} | 
 |     } | 
 |     if (pctxt->nberrors != 0) | 
 | 	goto exit_error; | 
 |     /* | 
 |     * Apply constraints for attribute uses. | 
 |     */ | 
 |     for (i = 0; i < nbItems; i++) { | 
 | 	item = items[i]; | 
 | 	switch (item->type) { | 
 | 	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE: | 
 | 		if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) { | 
 | 		    xmlSchemaCheckAttrUsePropsCorrect(pctxt, | 
 | 			WXS_ATTR_USE_CAST item); | 
 | 		    FIXHFAILURE; | 
 | 		} | 
 | 		break; | 
 | 	    default: | 
 | 		break; | 
 | 	} | 
 |     } | 
 |     if (pctxt->nberrors != 0) | 
 | 	goto exit_error; | 
 |  | 
 |     /* | 
 |     * Apply constraints for attribute group definitions. | 
 |     */ | 
 |     for (i = 0; i < nbItems; i++) { | 
 | 	item = items[i]; | 
 | 	switch (item->type) { | 
 | 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: | 
 | 	    if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) && | 
 | 		( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1)) | 
 | 	    { | 
 | 		xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item); | 
 | 		FIXHFAILURE; | 
 | 	    } | 
 | 	    break; | 
 | 	default: | 
 | 	    break; | 
 | 	} | 
 |     } | 
 |     if (pctxt->nberrors != 0) | 
 | 	goto exit_error; | 
 |  | 
 |     /* | 
 |     * Apply constraints for redefinitions. | 
 |     */ | 
 |     if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL) | 
 | 	xmlSchemaCheckSRCRedefineSecond(pctxt); | 
 |     if (pctxt->nberrors != 0) | 
 | 	goto exit_error; | 
 |  | 
 |     /* | 
 |     * Complex types are builded and checked. | 
 |     */ | 
 |     for (i = 0; i < nbItems; i++) { | 
 | 	item = con->pending->items[i]; | 
 | 	switch (item->type) { | 
 | 	    case XML_SCHEMA_TYPE_COMPLEX: | 
 | 		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) { | 
 | 		    xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item); | 
 | 		    FIXHFAILURE; | 
 | 		} | 
 | 		break; | 
 | 	    default: | 
 | 		break; | 
 | 	} | 
 |     } | 
 |     if (pctxt->nberrors != 0) | 
 | 	goto exit_error; | 
 |  | 
 |     /* | 
 |     * The list could have changed, since xmlSchemaFixupComplexType() | 
 |     * will create particles and model groups in some cases. | 
 |     */ | 
 |     items = (xmlSchemaTreeItemPtr *) con->pending->items; | 
 |     nbItems = con->pending->nbItems; | 
 |  | 
 |     /* | 
 |     * Apply some constraints for element declarations. | 
 |     */ | 
 |     for (i = 0; i < nbItems; i++) { | 
 | 	item = items[i]; | 
 | 	switch (item->type) { | 
 | 	    case XML_SCHEMA_TYPE_ELEMENT: | 
 | 		elemDecl = (xmlSchemaElementPtr) item; | 
 |  | 
 | 		if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0) | 
 | 		{ | 
 | 		    xmlSchemaCheckElementDeclComponent( | 
 | 			(xmlSchemaElementPtr) elemDecl, pctxt); | 
 | 		    FIXHFAILURE; | 
 | 		} | 
 |  | 
 | #ifdef WXS_ELEM_DECL_CONS_ENABLED | 
 | 		/* | 
 | 		* Schema Component Constraint: Element Declarations Consistent | 
 | 		* Apply this constraint to local types of element declarations. | 
 | 		*/ | 
 | 		if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) && | 
 | 		    (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) && | 
 | 		    (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl)))) | 
 | 		{ | 
 | 		    xmlSchemaCheckElementDeclConsistent(pctxt, | 
 | 			WXS_BASIC_CAST elemDecl, | 
 | 			WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)), | 
 | 			NULL, NULL, 0); | 
 | 		} | 
 | #endif | 
 | 		break; | 
 | 	    default: | 
 | 		break; | 
 | 	} | 
 |     } | 
 |     if (pctxt->nberrors != 0) | 
 | 	goto exit_error; | 
 |  | 
 |     /* | 
 |     * Finally we can build the automaton from the content model of | 
 |     * complex types. | 
 |     */ | 
 |  | 
 |     for (i = 0; i < nbItems; i++) { | 
 | 	item = items[i]; | 
 | 	switch (item->type) { | 
 | 	    case XML_SCHEMA_TYPE_COMPLEX: | 
 | 		xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt); | 
 | 		/* FIXHFAILURE; */ | 
 | 		break; | 
 | 	    default: | 
 | 		break; | 
 | 	} | 
 |     } | 
 |     if (pctxt->nberrors != 0) | 
 | 	goto exit_error; | 
 |     /* | 
 |     * URGENT TODO: cos-element-consistent | 
 |     */ | 
 |     goto exit; | 
 |  | 
 | exit_error: | 
 |     ret = pctxt->err; | 
 |     goto exit; | 
 |  | 
 | exit_failure: | 
 |     ret = -1; | 
 |  | 
 | exit: | 
 |     /* | 
 |     * Reset the constructor. This is needed for XSI acquisition, since | 
 |     * those items will be processed over and over again for every XSI | 
 |     * if not cleared here. | 
 |     */ | 
 |     con->bucket = oldbucket; | 
 |     con->pending->nbItems = 0; | 
 |     if (con->substGroups != NULL) { | 
 | 	xmlHashFree(con->substGroups, | 
 | 	    (xmlHashDeallocator) xmlSchemaSubstGroupFree); | 
 | 	con->substGroups = NULL; | 
 |     } | 
 |     if (con->redefs != NULL) { | 
 | 	xmlSchemaRedefListFree(con->redefs); | 
 | 	con->redefs = NULL; | 
 |     } | 
 |     return(ret); | 
 | } | 
 | /** | 
 |  * xmlSchemaParse: | 
 |  * @ctxt:  a schema validation context | 
 |  * | 
 |  * parse a schema definition resource and build an internal | 
 |  * XML Shema struture which can be used to validate instances. | 
 |  * | 
 |  * Returns the internal XML Schema structure built from the resource or | 
 |  *         NULL in case of error | 
 |  */ | 
 | xmlSchemaPtr | 
 | xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt) | 
 | { | 
 |     xmlSchemaPtr mainSchema = NULL; | 
 |     xmlSchemaBucketPtr bucket = NULL; | 
 |     int res; | 
 |  | 
 |     /* | 
 |     * This one is used if the schema to be parsed was specified via | 
 |     * the API; i.e. not automatically by the validated instance document. | 
 |     */ | 
 |  | 
 |     xmlSchemaInitTypes(); | 
 |  | 
 |     if (ctxt == NULL) | 
 |         return (NULL); | 
 |  | 
 |     /* TODO: Init the context. Is this all we need?*/ | 
 |     ctxt->nberrors = 0; | 
 |     ctxt->err = 0; | 
 |     ctxt->counter = 0; | 
 |  | 
 |     /* Create the *main* schema. */ | 
 |     mainSchema = xmlSchemaNewSchema(ctxt); | 
 |     if (mainSchema == NULL) | 
 | 	goto exit_failure; | 
 |     /* | 
 |     * Create the schema constructor. | 
 |     */ | 
 |     if (ctxt->constructor == NULL) { | 
 | 	ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict); | 
 | 	if (ctxt->constructor == NULL) | 
 | 	    return(NULL); | 
 | 	/* Take ownership of the constructor to be able to free it. */ | 
 | 	ctxt->ownsConstructor = 1; | 
 |     } | 
 |     ctxt->constructor->mainSchema = mainSchema; | 
 |     /* | 
 |     * Locate and add the schema document. | 
 |     */ | 
 |     res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN, | 
 | 	ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL, | 
 | 	NULL, NULL, &bucket); | 
 |     if (res == -1) | 
 | 	goto exit_failure; | 
 |     if (res != 0) | 
 | 	goto exit; | 
 |  | 
 |     if (bucket == NULL) { | 
 | 	/* TODO: Error code, actually we failed to *locate* the schema. */ | 
 | 	if (ctxt->URL) | 
 | 	    xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD, | 
 | 		NULL, NULL, | 
 | 		"Failed to locate the main schema resource at '%s'", | 
 | 		ctxt->URL, NULL); | 
 | 	else | 
 | 	    xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD, | 
 | 		NULL, NULL, | 
 | 		"Failed to locate the main schema resource", | 
 | 		    NULL, NULL); | 
 | 	goto exit; | 
 |     } | 
 |     /* Then do the parsing for good. */ | 
 |     if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1) | 
 | 	goto exit_failure; | 
 |     if (ctxt->nberrors != 0) | 
 | 	goto exit; | 
 |  | 
 |     mainSchema->doc = bucket->doc; | 
 |     mainSchema->preserve = ctxt->preserve; | 
 |  | 
 |     ctxt->schema = mainSchema; | 
 |  | 
 |     if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1) | 
 | 	goto exit_failure; | 
 |  | 
 |     /* | 
 |     * TODO: This is not nice, since we cannot distinguish from the | 
 |     * result if there was an internal error or not. | 
 |     */ | 
 | exit: | 
 |     if (ctxt->nberrors != 0) { | 
 | 	if (mainSchema) { | 
 | 	    xmlSchemaFree(mainSchema); | 
 | 	    mainSchema = NULL; | 
 | 	} | 
 | 	if (ctxt->constructor) { | 
 | 	    xmlSchemaConstructionCtxtFree(ctxt->constructor); | 
 | 	    ctxt->constructor = NULL; | 
 | 	    ctxt->ownsConstructor = 0; | 
 | 	} | 
 |     } | 
 |     ctxt->schema = NULL; | 
 |     return(mainSchema); | 
 | exit_failure: | 
 |     /* | 
 |     * Quite verbose, but should catch internal errors, which were | 
 |     * not communitated. | 
 |     */ | 
 |     if (mainSchema) { | 
 |         xmlSchemaFree(mainSchema); | 
 | 	mainSchema = NULL; | 
 |     } | 
 |     if (ctxt->constructor) { | 
 | 	xmlSchemaConstructionCtxtFree(ctxt->constructor); | 
 | 	ctxt->constructor = NULL; | 
 | 	ctxt->ownsConstructor = 0; | 
 |     } | 
 |     PERROR_INT2("xmlSchemaParse", | 
 | 	"An internal error occured"); | 
 |     ctxt->schema = NULL; | 
 |     return(NULL); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaSetParserErrors: | 
 |  * @ctxt:  a schema validation context | 
 |  * @err:  the error callback | 
 |  * @warn:  the warning callback | 
 |  * @ctx:  contextual data for the callbacks | 
 |  * | 
 |  * Set the callback functions used to handle errors for a validation context | 
 |  */ | 
 | void | 
 | xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt, | 
 |                          xmlSchemaValidityErrorFunc err, | 
 |                          xmlSchemaValidityWarningFunc warn, void *ctx) | 
 | { | 
 |     if (ctxt == NULL) | 
 |         return; | 
 |     ctxt->error = err; | 
 |     ctxt->warning = warn; | 
 |     ctxt->errCtxt = ctx; | 
 |     if (ctxt->vctxt != NULL) | 
 | 	xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaSetParserStructuredErrors: | 
 |  * @ctxt:  a schema parser context | 
 |  * @serror:  the structured error function | 
 |  * @ctx: the functions context | 
 |  * | 
 |  * Set the structured error callback | 
 |  */ | 
 | void | 
 | xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt, | 
 | 				   xmlStructuredErrorFunc serror, | 
 | 				   void *ctx) | 
 | { | 
 |     if (ctxt == NULL) | 
 | 	return; | 
 |     ctxt->serror = serror; | 
 |     ctxt->errCtxt = ctx; | 
 |     if (ctxt->vctxt != NULL) | 
 | 	xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaGetParserErrors: | 
 |  * @ctxt:  a XMl-Schema parser context | 
 |  * @err: the error callback result | 
 |  * @warn: the warning callback result | 
 |  * @ctx: contextual data for the callbacks result | 
 |  * | 
 |  * Get the callback information used to handle errors for a parser context | 
 |  * | 
 |  * Returns -1 in case of failure, 0 otherwise | 
 |  */ | 
 | int | 
 | xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt, | 
 | 			 xmlSchemaValidityErrorFunc * err, | 
 | 			 xmlSchemaValidityWarningFunc * warn, void **ctx) | 
 | { | 
 | 	if (ctxt == NULL) | 
 | 		return(-1); | 
 | 	if (err != NULL) | 
 | 		*err = ctxt->error; | 
 | 	if (warn != NULL) | 
 | 		*warn = ctxt->warning; | 
 | 	if (ctx != NULL) | 
 | 		*ctx = ctxt->errCtxt; | 
 | 	return(0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaFacetTypeToString: | 
 |  * @type:  the facet type | 
 |  * | 
 |  * Convert the xmlSchemaTypeType to a char string. | 
 |  * | 
 |  * Returns the char string representation of the facet type if the | 
 |  *     type is a facet and an "Internal Error" string otherwise. | 
 |  */ | 
 | static const xmlChar * | 
 | xmlSchemaFacetTypeToString(xmlSchemaTypeType type) | 
 | { | 
 |     switch (type) { | 
 |         case XML_SCHEMA_FACET_PATTERN: | 
 |             return (BAD_CAST "pattern"); | 
 |         case XML_SCHEMA_FACET_MAXEXCLUSIVE: | 
 |             return (BAD_CAST "maxExclusive"); | 
 |         case XML_SCHEMA_FACET_MAXINCLUSIVE: | 
 |             return (BAD_CAST "maxInclusive"); | 
 |         case XML_SCHEMA_FACET_MINEXCLUSIVE: | 
 |             return (BAD_CAST "minExclusive"); | 
 |         case XML_SCHEMA_FACET_MININCLUSIVE: | 
 |             return (BAD_CAST "minInclusive"); | 
 |         case XML_SCHEMA_FACET_WHITESPACE: | 
 |             return (BAD_CAST "whiteSpace"); | 
 |         case XML_SCHEMA_FACET_ENUMERATION: | 
 |             return (BAD_CAST "enumeration"); | 
 |         case XML_SCHEMA_FACET_LENGTH: | 
 |             return (BAD_CAST "length"); | 
 |         case XML_SCHEMA_FACET_MAXLENGTH: | 
 |             return (BAD_CAST "maxLength"); | 
 |         case XML_SCHEMA_FACET_MINLENGTH: | 
 |             return (BAD_CAST "minLength"); | 
 |         case XML_SCHEMA_FACET_TOTALDIGITS: | 
 |             return (BAD_CAST "totalDigits"); | 
 |         case XML_SCHEMA_FACET_FRACTIONDIGITS: | 
 |             return (BAD_CAST "fractionDigits"); | 
 |         default: | 
 |             break; | 
 |     } | 
 |     return (BAD_CAST "Internal Error"); | 
 | } | 
 |  | 
 | static xmlSchemaWhitespaceValueType | 
 | xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type) | 
 | { | 
 |     /* | 
 |     * The normalization type can be changed only for types which are derived | 
 |     * from xsd:string. | 
 |     */ | 
 |     if (type->type == XML_SCHEMA_TYPE_BASIC) { | 
 | 	/* | 
 | 	* Note that we assume a whitespace of preserve for anySimpleType. | 
 | 	*/ | 
 | 	if ((type->builtInType == XML_SCHEMAS_STRING) || | 
 | 	    (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) | 
 | 	    return(XML_SCHEMA_WHITESPACE_PRESERVE); | 
 | 	else if (type->builtInType == XML_SCHEMAS_NORMSTRING) | 
 | 	    return(XML_SCHEMA_WHITESPACE_REPLACE); | 
 | 	else { | 
 | 	    /* | 
 | 	    * For all �atomic� datatypes other than string (and types �derived� | 
 | 	    * by �restriction� from it) the value of whiteSpace is fixed to | 
 | 	    * collapse | 
 | 	    * Note that this includes built-in list datatypes. | 
 | 	    */ | 
 | 	    return(XML_SCHEMA_WHITESPACE_COLLAPSE); | 
 | 	} | 
 |     } else if (WXS_IS_LIST(type)) { | 
 | 	/* | 
 | 	* For list types the facet "whiteSpace" is fixed to "collapse". | 
 | 	*/ | 
 | 	return (XML_SCHEMA_WHITESPACE_COLLAPSE); | 
 |     } else if (WXS_IS_UNION(type)) { | 
 | 	return (XML_SCHEMA_WHITESPACE_UNKNOWN); | 
 |     } else if (WXS_IS_ATOMIC(type)) { | 
 | 	if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE) | 
 | 	    return (XML_SCHEMA_WHITESPACE_PRESERVE); | 
 | 	else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE) | 
 | 	    return (XML_SCHEMA_WHITESPACE_REPLACE); | 
 | 	else | 
 | 	    return (XML_SCHEMA_WHITESPACE_COLLAPSE); | 
 |     } | 
 |     return (-1); | 
 | } | 
 |  | 
 | /************************************************************************ | 
 |  * 									* | 
 |  * 			Simple type validation				* | 
 |  * 									* | 
 |  ************************************************************************/ | 
 |  | 
 |  | 
 | /************************************************************************ | 
 |  * 									* | 
 |  * 			DOM Validation code				* | 
 |  * 									* | 
 |  ************************************************************************/ | 
 |  | 
 | /** | 
 |  * xmlSchemaAssembleByLocation: | 
 |  * @pctxt:  a schema parser context | 
 |  * @vctxt:  a schema validation context | 
 |  * @schema: the existing schema | 
 |  * @node: the node that fired the assembling | 
 |  * @nsName: the namespace name of the new schema | 
 |  * @location: the location of the schema | 
 |  * | 
 |  * Expands an existing schema by an additional schema. | 
 |  * | 
 |  * Returns 0 if the new schema is correct, a positive error code | 
 |  * number otherwise and -1 in case of an internal or API error. | 
 |  */ | 
 | static int | 
 | xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt, | 
 | 			    xmlSchemaPtr schema, | 
 | 			    xmlNodePtr node, | 
 | 			    const xmlChar *nsName, | 
 | 			    const xmlChar *location) | 
 | { | 
 |     int ret = 0; | 
 |     xmlSchemaParserCtxtPtr pctxt; | 
 |     xmlSchemaBucketPtr bucket = NULL; | 
 |  | 
 |     if ((vctxt == NULL) || (schema == NULL)) | 
 | 	return (-1); | 
 |  | 
 |     if (vctxt->pctxt == NULL) { | 
 | 	VERROR_INT("xmlSchemaAssembleByLocation", | 
 | 	    "no parser context available"); | 
 | 	return(-1); | 
 |     } | 
 |     pctxt = vctxt->pctxt; | 
 |     if (pctxt->constructor == NULL) { | 
 | 	PERROR_INT("xmlSchemaAssembleByLocation", | 
 | 	    "no constructor"); | 
 | 	return(-1); | 
 |     } | 
 |     /* | 
 |     * Acquire the schema document. | 
 |     */ | 
 |     location = xmlSchemaBuildAbsoluteURI(pctxt->dict, | 
 | 	location, node); | 
 |     /* | 
 |     * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here; | 
 |     * the process will automatically change this to | 
 |     * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document. | 
 |     */ | 
 |     ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT, | 
 | 	location, NULL, NULL, 0, node, NULL, nsName, | 
 | 	&bucket); | 
 |     if (ret != 0) | 
 | 	return(ret); | 
 |     if (bucket == NULL) { | 
 | 	/* | 
 | 	* Generate a warning that the document could not be located. | 
 | 	*/ | 
 | 	xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC, | 
 | 	    node, NULL, | 
 | 	    "The document at location '%s' could not be acquired", | 
 | 	    location, NULL, NULL); | 
 | 	return(ret); | 
 |     } | 
 |     /* | 
 |     * The first located schema will be handled as if all other | 
 |     * schemas imported by XSI were imported by this first schema. | 
 |     */ | 
 |     if ((bucket != NULL) && | 
 | 	(WXS_CONSTRUCTOR(pctxt)->bucket == NULL)) | 
 | 	WXS_CONSTRUCTOR(pctxt)->bucket = bucket; | 
 |     /* | 
 |     * TODO: Is this handled like an import? I.e. is it not an error | 
 |     * if the schema cannot be located? | 
 |     */ | 
 |     if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket))) | 
 | 	return(0); | 
 |     /* | 
 |     * We will reuse the parser context for every schema imported | 
 |     * directly via XSI. So reset the context. | 
 |     */ | 
 |     pctxt->nberrors = 0; | 
 |     pctxt->err = 0; | 
 |     pctxt->doc = bucket->doc; | 
 |  | 
 |     ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket); | 
 |     if (ret == -1) { | 
 | 	pctxt->doc = NULL; | 
 | 	goto exit_failure; | 
 |     } | 
 |     /* Paranoid error channelling. */ | 
 |     if ((ret == 0) && (pctxt->nberrors != 0)) | 
 | 	ret = pctxt->err; | 
 |     if (pctxt->nberrors == 0) { | 
 | 	/* | 
 | 	* Only bother to fixup pending components, if there was | 
 | 	* no error yet. | 
 | 	* For every XSI acquired schema (and its sub-schemata) we will | 
 | 	* fixup the components. | 
 | 	*/ | 
 | 	xmlSchemaFixupComponents(pctxt, bucket); | 
 | 	ret = pctxt->err; | 
 | 	/* | 
 | 	* Not nice, but we need somehow to channel the schema parser | 
 | 	* error to the validation context. | 
 | 	*/ | 
 | 	if ((ret != 0) && (vctxt->err == 0)) | 
 | 	    vctxt->err = ret; | 
 | 	vctxt->nberrors += pctxt->nberrors; | 
 |     } else { | 
 | 	/* Add to validation error sum. */ | 
 | 	vctxt->nberrors += pctxt->nberrors; | 
 |     } | 
 |     pctxt->doc = NULL; | 
 |     return(ret); | 
 | exit_failure: | 
 |     pctxt->doc = NULL; | 
 |     return (-1); | 
 | } | 
 |  | 
 | static xmlSchemaAttrInfoPtr | 
 | xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt, | 
 | 			 int metaType) | 
 | { | 
 |     if (vctxt->nbAttrInfos == 0) | 
 | 	return (NULL); | 
 |     { | 
 | 	int i; | 
 | 	xmlSchemaAttrInfoPtr iattr; | 
 |  | 
 | 	for (i = 0; i < vctxt->nbAttrInfos; i++) { | 
 | 	    iattr = vctxt->attrInfos[i]; | 
 | 	    if (iattr->metaType == metaType) | 
 | 		return (iattr); | 
 | 	} | 
 |  | 
 |     } | 
 |     return (NULL); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaAssembleByXSI: | 
 |  * @vctxt:  a schema validation context | 
 |  * | 
 |  * Expands an existing schema by an additional schema using | 
 |  * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute | 
 |  * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace | 
 |  * must be set to 1. | 
 |  * | 
 |  * Returns 0 if the new schema is correct, a positive error code | 
 |  * number otherwise and -1 in case of an internal or API error. | 
 |  */ | 
 | static int | 
 | xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt) | 
 | { | 
 |     const xmlChar *cur, *end; | 
 |     const xmlChar *nsname = NULL, *location; | 
 |     int count = 0; | 
 |     int ret = 0; | 
 |     xmlSchemaAttrInfoPtr iattr; | 
 |  | 
 |     /* | 
 |     * Parse the value; we will assume an even number of values | 
 |     * to be given (this is how Xerces and XSV work). | 
 |     * | 
 |     * URGENT TODO: !! This needs to work for both | 
 |     * @noNamespaceSchemaLocation AND @schemaLocation on the same | 
 |     * element !! | 
 |     */ | 
 |     iattr = xmlSchemaGetMetaAttrInfo(vctxt, | 
 | 	XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC); | 
 |     if (iattr == NULL) | 
 | 	iattr = xmlSchemaGetMetaAttrInfo(vctxt, | 
 | 	XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC); | 
 |     if (iattr == NULL) | 
 | 	return (0); | 
 |     cur = iattr->value; | 
 |     do { | 
 | 	/* | 
 | 	* TODO: Move the string parsing mechanism away from here. | 
 | 	*/ | 
 | 	if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) { | 
 | 	    /* | 
 | 	    * Get the namespace name. | 
 | 	    */ | 
 | 	    while (IS_BLANK_CH(*cur)) | 
 | 		cur++; | 
 | 	    end = cur; | 
 | 	    while ((*end != 0) && (!(IS_BLANK_CH(*end)))) | 
 | 		end++; | 
 | 	    if (end == cur) | 
 | 		break; | 
 | 	    count++; /* TODO: Don't use the schema's dict. */ | 
 | 	    nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur); | 
 | 	    cur = end; | 
 | 	} | 
 | 	/* | 
 | 	* Get the URI. | 
 | 	*/ | 
 | 	while (IS_BLANK_CH(*cur)) | 
 | 	    cur++; | 
 | 	end = cur; | 
 | 	while ((*end != 0) && (!(IS_BLANK_CH(*end)))) | 
 | 	    end++; | 
 | 	if (end == cur) { | 
 | 	    if (iattr->metaType == | 
 | 		XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) | 
 | 	    { | 
 | 		/* | 
 | 		* If using @schemaLocation then tuples are expected. | 
 | 		* I.e. the namespace name *and* the document's URI. | 
 | 		*/ | 
 | 		xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC, | 
 | 		    iattr->node, NULL, | 
 | 		    "The value must consist of tuples: the target namespace " | 
 | 		    "name and the document's URI", NULL, NULL, NULL); | 
 | 	    } | 
 | 	    break; | 
 | 	} | 
 | 	count++; /* TODO: Don't use the schema's dict. */ | 
 | 	location = xmlDictLookup(vctxt->schema->dict, cur, end - cur); | 
 | 	cur = end; | 
 | 	ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema, | 
 | 	    iattr->node, nsname, location); | 
 | 	if (ret == -1) { | 
 | 	    VERROR_INT("xmlSchemaAssembleByXSI", | 
 | 		"assembling schemata"); | 
 | 	    return (-1); | 
 | 	} | 
 |     } while (*cur != 0); | 
 |     return (ret); | 
 | } | 
 |  | 
 | static const xmlChar * | 
 | xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt, | 
 | 			 const xmlChar *prefix) | 
 | { | 
 |     if (vctxt->sax != NULL) { | 
 | 	int i, j; | 
 | 	xmlSchemaNodeInfoPtr inode; | 
 |  | 
 | 	for (i = vctxt->depth; i >= 0; i--) { | 
 | 	    if (vctxt->elemInfos[i]->nbNsBindings != 0) { | 
 | 		inode = vctxt->elemInfos[i]; | 
 | 		for (j = 0; j < inode->nbNsBindings * 2; j += 2) { | 
 | 		    if (((prefix == NULL) && | 
 | 			    (inode->nsBindings[j] == NULL)) || | 
 | 			((prefix != NULL) && xmlStrEqual(prefix, | 
 | 			    inode->nsBindings[j]))) { | 
 |  | 
 | 			/* | 
 | 			* Note that the namespace bindings are already | 
 | 			* in a string dict. | 
 | 			*/ | 
 | 			return (inode->nsBindings[j+1]); | 
 | 		    } | 
 | 		} | 
 | 	    } | 
 | 	} | 
 | 	return (NULL); | 
 | #ifdef LIBXML_READER_ENABLED | 
 |     } else if (vctxt->reader != NULL) { | 
 | 	xmlChar *nsName; | 
 |  | 
 | 	nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix); | 
 | 	if (nsName != NULL) { | 
 | 	    const xmlChar *ret; | 
 |  | 
 | 	    ret = xmlDictLookup(vctxt->dict, nsName, -1); | 
 | 	    xmlFree(nsName); | 
 | 	    return (ret); | 
 | 	} else | 
 | 	    return (NULL); | 
 | #endif | 
 |     } else { | 
 | 	xmlNsPtr ns; | 
 |  | 
 | 	if ((vctxt->inode->node == NULL) || | 
 | 	    (vctxt->inode->node->doc == NULL)) { | 
 | 	    VERROR_INT("xmlSchemaLookupNamespace", | 
 | 		"no node or node's doc avaliable"); | 
 | 	    return (NULL); | 
 | 	} | 
 | 	ns = xmlSearchNs(vctxt->inode->node->doc, | 
 | 	    vctxt->inode->node, prefix); | 
 | 	if (ns != NULL) | 
 | 	    return (ns->href); | 
 | 	return (NULL); | 
 |     } | 
 | } | 
 |  | 
 | /* | 
 | * This one works on the schema of the validation context. | 
 | */ | 
 | static int | 
 | xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt, | 
 | 			  xmlSchemaPtr schema, | 
 | 			  xmlNodePtr node, | 
 | 			  const xmlChar *value, | 
 | 			  xmlSchemaValPtr *val, | 
 | 			  int valNeeded) | 
 | { | 
 |     int ret; | 
 |  | 
 |     if (vctxt && (vctxt->schema == NULL)) { | 
 | 	VERROR_INT("xmlSchemaValidateNotation", | 
 | 	    "a schema is needed on the validation context"); | 
 | 	return (-1); | 
 |     } | 
 |     ret = xmlValidateQName(value, 1); | 
 |     if (ret != 0) | 
 | 	return (ret); | 
 |     { | 
 | 	xmlChar *localName = NULL; | 
 | 	xmlChar *prefix = NULL; | 
 |  | 
 | 	localName = xmlSplitQName2(value, &prefix); | 
 | 	if (prefix != NULL) { | 
 | 	    const xmlChar *nsName = NULL; | 
 |  | 
 | 	    if (vctxt != NULL) | 
 | 		nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix); | 
 | 	    else if (node != NULL) { | 
 | 		xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix); | 
 | 		if (ns != NULL) | 
 | 		    nsName = ns->href; | 
 | 	    } else { | 
 | 		xmlFree(prefix); | 
 | 		xmlFree(localName); | 
 | 		return (1); | 
 | 	    } | 
 | 	    if (nsName == NULL) { | 
 | 		xmlFree(prefix); | 
 | 		xmlFree(localName); | 
 | 		return (1); | 
 | 	    } | 
 | 	    if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) { | 
 | 		if ((valNeeded) && (val != NULL)) { | 
 | 		    (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName), | 
 | 						       xmlStrdup(nsName)); | 
 | 		    if (*val == NULL) | 
 | 			ret = -1; | 
 | 		} | 
 | 	    } else | 
 | 		ret = 1; | 
 | 	    xmlFree(prefix); | 
 | 	    xmlFree(localName); | 
 | 	} else { | 
 | 	    if (xmlSchemaGetNotation(schema, value, NULL) != NULL) { | 
 | 		if (valNeeded && (val != NULL)) { | 
 | 		    (*val) = xmlSchemaNewNOTATIONValue( | 
 | 			BAD_CAST xmlStrdup(value), NULL); | 
 | 		    if (*val == NULL) | 
 | 			ret = -1; | 
 | 		} | 
 | 	    } else | 
 | 		return (1); | 
 | 	} | 
 |     } | 
 |     return (ret); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt, | 
 | 		       const xmlChar* lname, | 
 | 		       const xmlChar* nsname) | 
 | { | 
 |     int i; | 
 |  | 
 |     lname = xmlDictLookup(vctxt->dict, lname, -1); | 
 |     if (lname == NULL) | 
 | 	return(-1); | 
 |     if (nsname != NULL) { | 
 | 	nsname = xmlDictLookup(vctxt->dict, nsname, -1); | 
 | 	if (nsname == NULL) | 
 | 	    return(-1); | 
 |     } | 
 |     for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) { | 
 | 	if ((vctxt->nodeQNames->items [i] == lname) && | 
 | 	    (vctxt->nodeQNames->items[i +1] == nsname)) | 
 | 	    /* Already there */ | 
 | 	    return(i); | 
 |     } | 
 |     /* Add new entry. */ | 
 |     i = vctxt->nodeQNames->nbItems; | 
 |     xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname); | 
 |     xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname); | 
 |     return(i); | 
 | } | 
 |  | 
 | /************************************************************************ | 
 |  * 									* | 
 |  *  Validation of identity-constraints (IDC)                            * | 
 |  * 									* | 
 |  ************************************************************************/ | 
 |  | 
 | /** | 
 |  * xmlSchemaAugmentIDC: | 
 |  * @idcDef: the IDC definition | 
 |  * | 
 |  * Creates an augmented IDC definition item. | 
 |  * | 
 |  * Returns the item, or NULL on internal errors. | 
 |  */ | 
 | static void | 
 | xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef, | 
 | 		    xmlSchemaValidCtxtPtr vctxt) | 
 | { | 
 |     xmlSchemaIDCAugPtr aidc; | 
 |  | 
 |     aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug)); | 
 |     if (aidc == NULL) { | 
 | 	xmlSchemaVErrMemory(vctxt, | 
 | 	    "xmlSchemaAugmentIDC: allocating an augmented IDC definition", | 
 | 	    NULL); | 
 | 	return; | 
 |     } | 
 |     aidc->keyrefDepth = -1; | 
 |     aidc->def = idcDef; | 
 |     aidc->next = NULL; | 
 |     if (vctxt->aidcs == NULL) | 
 | 	vctxt->aidcs = aidc; | 
 |     else { | 
 | 	aidc->next = vctxt->aidcs; | 
 | 	vctxt->aidcs = aidc; | 
 |     } | 
 |     /* | 
 |     * Save if we have keyrefs at all. | 
 |     */ | 
 |     if ((vctxt->hasKeyrefs == 0) && | 
 | 	(idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF)) | 
 | 	vctxt->hasKeyrefs = 1; | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaAugmentImportedIDC: | 
 |  * @imported: the imported schema | 
 |  * | 
 |  * Creates an augmented IDC definition for the imported schema. | 
 |  */ | 
 | static void | 
 | xmlSchemaAugmentImportedIDC(xmlSchemaImportPtr imported, xmlSchemaValidCtxtPtr vctxt) { | 
 |     if (imported->schema->idcDef != NULL) { | 
 | 	    xmlHashScan(imported->schema->idcDef , | 
 | 	    (xmlHashScanner) xmlSchemaAugmentIDC, vctxt); | 
 |     } | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaIDCNewBinding: | 
 |  * @idcDef: the IDC definition of this binding | 
 |  * | 
 |  * Creates a new IDC binding. | 
 |  * | 
 |  * Returns the new IDC binding, NULL on internal errors. | 
 |  */ | 
 | static xmlSchemaPSVIIDCBindingPtr | 
 | xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef) | 
 | { | 
 |     xmlSchemaPSVIIDCBindingPtr ret; | 
 |  | 
 |     ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc( | 
 | 	    sizeof(xmlSchemaPSVIIDCBinding)); | 
 |     if (ret == NULL) { | 
 | 	xmlSchemaVErrMemory(NULL, | 
 | 	    "allocating a PSVI IDC binding item", NULL); | 
 | 	return (NULL); | 
 |     } | 
 |     memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding)); | 
 |     ret->definition = idcDef; | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaIDCStoreNodeTableItem: | 
 |  * @vctxt: the WXS validation context | 
 |  * @item: the IDC node table item | 
 |  * | 
 |  * The validation context is used to store IDC node table items. | 
 |  * They are stored to avoid copying them if IDC node-tables are merged | 
 |  * with corresponding parent IDC node-tables (bubbling). | 
 |  * | 
 |  * Returns 0 if succeeded, -1 on internal errors. | 
 |  */ | 
 | static int | 
 | xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt, | 
 | 			       xmlSchemaPSVIIDCNodePtr item) | 
 | { | 
 |     /* | 
 |     * Add to gobal list. | 
 |     */ | 
 |     if (vctxt->idcNodes == NULL) { | 
 | 	vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *) | 
 | 	    xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr)); | 
 | 	if (vctxt->idcNodes == NULL) { | 
 | 	    xmlSchemaVErrMemory(vctxt, | 
 | 		"allocating the IDC node table item list", NULL); | 
 | 	    return (-1); | 
 | 	} | 
 | 	vctxt->sizeIdcNodes = 20; | 
 |     } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) { | 
 | 	vctxt->sizeIdcNodes *= 2; | 
 | 	vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *) | 
 | 	    xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes * | 
 | 	    sizeof(xmlSchemaPSVIIDCNodePtr)); | 
 | 	if (vctxt->idcNodes == NULL) { | 
 | 	    xmlSchemaVErrMemory(vctxt, | 
 | 		"re-allocating the IDC node table item list", NULL); | 
 | 	    return (-1); | 
 | 	} | 
 |     } | 
 |     vctxt->idcNodes[vctxt->nbIdcNodes++] = item; | 
 |  | 
 |     return (0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaIDCStoreKey: | 
 |  * @vctxt: the WXS validation context | 
 |  * @item: the IDC key | 
 |  * | 
 |  * The validation context is used to store an IDC key. | 
 |  * | 
 |  * Returns 0 if succeeded, -1 on internal errors. | 
 |  */ | 
 | static int | 
 | xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt, | 
 | 		     xmlSchemaPSVIIDCKeyPtr key) | 
 | { | 
 |     /* | 
 |     * Add to gobal list. | 
 |     */ | 
 |     if (vctxt->idcKeys == NULL) { | 
 | 	vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *) | 
 | 	    xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr)); | 
 | 	if (vctxt->idcKeys == NULL) { | 
 | 	    xmlSchemaVErrMemory(vctxt, | 
 | 		"allocating the IDC key storage list", NULL); | 
 | 	    return (-1); | 
 | 	} | 
 | 	vctxt->sizeIdcKeys = 40; | 
 |     } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) { | 
 | 	vctxt->sizeIdcKeys *= 2; | 
 | 	vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *) | 
 | 	    xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys * | 
 | 	    sizeof(xmlSchemaPSVIIDCKeyPtr)); | 
 | 	if (vctxt->idcKeys == NULL) { | 
 | 	    xmlSchemaVErrMemory(vctxt, | 
 | 		"re-allocating the IDC key storage list", NULL); | 
 | 	    return (-1); | 
 | 	} | 
 |     } | 
 |     vctxt->idcKeys[vctxt->nbIdcKeys++] = key; | 
 |  | 
 |     return (0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaIDCAppendNodeTableItem: | 
 |  * @bind: the IDC binding | 
 |  * @ntItem: the node-table item | 
 |  * | 
 |  * Appends the IDC node-table item to the binding. | 
 |  * | 
 |  * Returns 0 on success and -1 on internal errors. | 
 |  */ | 
 | static int | 
 | xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind, | 
 | 				xmlSchemaPSVIIDCNodePtr ntItem) | 
 | { | 
 |     if (bind->nodeTable == NULL) { | 
 | 	bind->sizeNodes = 10; | 
 | 	bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *) | 
 | 	    xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr)); | 
 | 	if (bind->nodeTable == NULL) { | 
 | 	    xmlSchemaVErrMemory(NULL, | 
 | 		"allocating an array of IDC node-table items", NULL); | 
 | 	    return(-1); | 
 | 	} | 
 |     } else if (bind->sizeNodes <= bind->nbNodes) { | 
 | 	bind->sizeNodes *= 2; | 
 | 	bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *) | 
 | 	    xmlRealloc(bind->nodeTable, bind->sizeNodes * | 
 | 		sizeof(xmlSchemaPSVIIDCNodePtr)); | 
 | 	if (bind->nodeTable == NULL) { | 
 | 	    xmlSchemaVErrMemory(NULL, | 
 | 		"re-allocating an array of IDC node-table items", NULL); | 
 | 	    return(-1); | 
 | 	} | 
 |     } | 
 |     bind->nodeTable[bind->nbNodes++] = ntItem; | 
 |     return(0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaIDCAcquireBinding: | 
 |  * @vctxt: the WXS validation context | 
 |  * @matcher: the IDC matcher | 
 |  * | 
 |  * Looks up an PSVI IDC binding, for the IDC definition and | 
 |  * of the given matcher. If none found, a new one is created | 
 |  * and added to the IDC table. | 
 |  * | 
 |  * Returns an IDC binding or NULL on internal errors. | 
 |  */ | 
 | static xmlSchemaPSVIIDCBindingPtr | 
 | xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt, | 
 | 			  xmlSchemaIDCMatcherPtr matcher) | 
 | { | 
 |     xmlSchemaNodeInfoPtr ielem; | 
 |  | 
 |     ielem = vctxt->elemInfos[matcher->depth]; | 
 |  | 
 |     if (ielem->idcTable == NULL) { | 
 | 	ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def); | 
 | 	if (ielem->idcTable == NULL) | 
 | 	    return (NULL); | 
 | 	return(ielem->idcTable); | 
 |     } else { | 
 | 	xmlSchemaPSVIIDCBindingPtr bind = NULL; | 
 |  | 
 | 	bind = ielem->idcTable; | 
 | 	do { | 
 | 	    if (bind->definition == matcher->aidc->def) | 
 | 		return(bind); | 
 | 	    if (bind->next == NULL) { | 
 | 		bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def); | 
 | 		if (bind->next == NULL) | 
 | 		    return (NULL); | 
 | 		return(bind->next); | 
 | 	    } | 
 | 	    bind = bind->next; | 
 | 	} while (bind != NULL); | 
 |     } | 
 |     return (NULL); | 
 | } | 
 |  | 
 | static xmlSchemaItemListPtr | 
 | xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED, | 
 | 			     xmlSchemaIDCMatcherPtr matcher) | 
 | { | 
 |     if (matcher->targets == NULL) | 
 | 	matcher->targets = xmlSchemaItemListCreate(); | 
 |     return(matcher->targets); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaIDCFreeKey: | 
 |  * @key: the IDC key | 
 |  * | 
 |  * Frees an IDC key together with its compiled value. | 
 |  */ | 
 | static void | 
 | xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key) | 
 | { | 
 |     if (key->val != NULL) | 
 | 	xmlSchemaFreeValue(key->val); | 
 |     xmlFree(key); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaIDCFreeBinding: | 
 |  * | 
 |  * Frees an IDC binding. Note that the node table-items | 
 |  * are not freed. | 
 |  */ | 
 | static void | 
 | xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind) | 
 | { | 
 |     if (bind->nodeTable != NULL) | 
 | 	xmlFree(bind->nodeTable); | 
 |     if (bind->dupls != NULL) | 
 | 	xmlSchemaItemListFree(bind->dupls); | 
 |     xmlFree(bind); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaIDCFreeIDCTable: | 
 |  * @bind: the first IDC binding in the list | 
 |  * | 
 |  * Frees an IDC table, i.e. all the IDC bindings in the list. | 
 |  */ | 
 | static void | 
 | xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind) | 
 | { | 
 |     xmlSchemaPSVIIDCBindingPtr prev; | 
 |  | 
 |     while (bind != NULL) { | 
 | 	prev = bind; | 
 | 	bind = bind->next; | 
 | 	xmlSchemaIDCFreeBinding(prev); | 
 |     } | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaIDCFreeMatcherList: | 
 |  * @matcher: the first IDC matcher in the list | 
 |  * | 
 |  * Frees a list of IDC matchers. | 
 |  */ | 
 | static void | 
 | xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher) | 
 | { | 
 |     xmlSchemaIDCMatcherPtr next; | 
 |  | 
 |     while (matcher != NULL) { | 
 | 	next = matcher->next; | 
 | 	if (matcher->keySeqs != NULL) { | 
 | 	    int i; | 
 | 	    for (i = 0; i < matcher->sizeKeySeqs; i++) | 
 | 		if (matcher->keySeqs[i] != NULL) | 
 | 		    xmlFree(matcher->keySeqs[i]); | 
 | 	    xmlFree(matcher->keySeqs); | 
 | 	} | 
 | 	if (matcher->targets != NULL) { | 
 | 	    if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) { | 
 | 		int i; | 
 | 		xmlSchemaPSVIIDCNodePtr idcNode; | 
 | 		/* | 
 | 		* Node-table items for keyrefs are not stored globally | 
 | 		* to the validation context, since they are not bubbled. | 
 | 		* We need to free them here. | 
 | 		*/ | 
 | 		for (i = 0; i < matcher->targets->nbItems; i++) { | 
 | 		    idcNode = | 
 | 			(xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i]; | 
 | 		    xmlFree(idcNode->keys); | 
 | 		    xmlFree(idcNode); | 
 | 		} | 
 | 	    } | 
 | 	    xmlSchemaItemListFree(matcher->targets); | 
 | 	} | 
 | 	xmlFree(matcher); | 
 | 	matcher = next; | 
 |     } | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaIDCReleaseMatcherList: | 
 |  * @vctxt: the WXS validation context | 
 |  * @matcher: the first IDC matcher in the list | 
 |  * | 
 |  * Caches a list of IDC matchers for reuse. | 
 |  */ | 
 | static void | 
 | xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt, | 
 | 			       xmlSchemaIDCMatcherPtr matcher) | 
 | { | 
 |     xmlSchemaIDCMatcherPtr next; | 
 |  | 
 |     while (matcher != NULL) { | 
 | 	next = matcher->next; | 
 | 	if (matcher->keySeqs != NULL) { | 
 | 	    int i; | 
 | 	    /* | 
 | 	    * Don't free the array, but only the content. | 
 | 	    */ | 
 | 	    for (i = 0; i < matcher->sizeKeySeqs; i++) | 
 | 		if (matcher->keySeqs[i] != NULL) { | 
 | 		    xmlFree(matcher->keySeqs[i]); | 
 | 		    matcher->keySeqs[i] = NULL; | 
 | 		} | 
 | 	} | 
 | 	if (matcher->targets) { | 
 | 	    if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) { | 
 | 		int i; | 
 | 		xmlSchemaPSVIIDCNodePtr idcNode; | 
 | 		/* | 
 | 		* Node-table items for keyrefs are not stored globally | 
 | 		* to the validation context, since they are not bubbled. | 
 | 		* We need to free them here. | 
 | 		*/ | 
 | 		for (i = 0; i < matcher->targets->nbItems; i++) { | 
 | 		    idcNode = | 
 | 			(xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i]; | 
 | 		    xmlFree(idcNode->keys); | 
 | 		    xmlFree(idcNode); | 
 | 		} | 
 | 	    } | 
 | 	    xmlSchemaItemListFree(matcher->targets); | 
 | 	    matcher->targets = NULL; | 
 | 	} | 
 | 	matcher->next = NULL; | 
 | 	/* | 
 | 	* Cache the matcher. | 
 | 	*/ | 
 | 	if (vctxt->idcMatcherCache != NULL) | 
 | 	    matcher->nextCached = vctxt->idcMatcherCache; | 
 | 	vctxt->idcMatcherCache = matcher; | 
 |  | 
 | 	matcher = next; | 
 |     } | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaIDCAddStateObject: | 
 |  * @vctxt: the WXS validation context | 
 |  * @matcher: the IDC matcher | 
 |  * @sel: the XPath information | 
 |  * @parent: the parent "selector" state object if any | 
 |  * @type: "selector" or "field" | 
 |  * | 
 |  * Creates/reuses and activates state objects for the given | 
 |  * XPath information; if the XPath expression consists of unions, | 
 |  * multiple state objects are created for every unioned expression. | 
 |  * | 
 |  * Returns 0 on success and -1 on internal errors. | 
 |  */ | 
 | static int | 
 | xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt, | 
 | 			xmlSchemaIDCMatcherPtr matcher, | 
 | 			xmlSchemaIDCSelectPtr sel, | 
 | 			int type) | 
 | { | 
 |     xmlSchemaIDCStateObjPtr sto; | 
 |  | 
 |     /* | 
 |     * Reuse the state objects from the pool. | 
 |     */ | 
 |     if (vctxt->xpathStatePool != NULL) { | 
 | 	sto = vctxt->xpathStatePool; | 
 | 	vctxt->xpathStatePool = sto->next; | 
 | 	sto->next = NULL; | 
 |     } else { | 
 | 	/* | 
 | 	* Create a new state object. | 
 | 	*/ | 
 | 	sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj)); | 
 | 	if (sto == NULL) { | 
 | 	    xmlSchemaVErrMemory(NULL, | 
 | 		"allocating an IDC state object", NULL); | 
 | 	    return (-1); | 
 | 	} | 
 | 	memset(sto, 0, sizeof(xmlSchemaIDCStateObj)); | 
 |     } | 
 |     /* | 
 |     * Add to global list. | 
 |     */ | 
 |     if (vctxt->xpathStates != NULL) | 
 | 	sto->next = vctxt->xpathStates; | 
 |     vctxt->xpathStates = sto; | 
 |  | 
 |     /* | 
 |     * Free the old xpath validation context. | 
 |     */ | 
 |     if (sto->xpathCtxt != NULL) | 
 | 	xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt); | 
 |  | 
 |     /* | 
 |     * Create a new XPath (pattern) validation context. | 
 |     */ | 
 |     sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt( | 
 | 	(xmlPatternPtr) sel->xpathComp); | 
 |     if (sto->xpathCtxt == NULL) { | 
 | 	VERROR_INT("xmlSchemaIDCAddStateObject", | 
 | 	    "failed to create an XPath validation context"); | 
 | 	return (-1); | 
 |     } | 
 |     sto->type = type; | 
 |     sto->depth = vctxt->depth; | 
 |     sto->matcher = matcher; | 
 |     sto->sel = sel; | 
 |     sto->nbHistory = 0; | 
 |  | 
 | #ifdef DEBUG_IDC | 
 |     xmlGenericError(xmlGenericErrorContext, "IDC:   STO push '%s'\n", | 
 | 	sto->sel->xpath); | 
 | #endif | 
 |     return (0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaXPathEvaluate: | 
 |  * @vctxt: the WXS validation context | 
 |  * @nodeType: the nodeType of the current node | 
 |  * | 
 |  * Evaluates all active XPath state objects. | 
 |  * | 
 |  * Returns the number of IC "field" state objects which resolved to | 
 |  * this node, 0 if none resolved and -1 on internal errors. | 
 |  */ | 
 | static int | 
 | xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt, | 
 | 		       xmlElementType nodeType) | 
 | { | 
 |     xmlSchemaIDCStateObjPtr sto, head = NULL, first; | 
 |     int res, resolved = 0, depth = vctxt->depth; | 
 |  | 
 |     if (vctxt->xpathStates == NULL) | 
 | 	return (0); | 
 |  | 
 |     if (nodeType == XML_ATTRIBUTE_NODE) | 
 | 	depth++; | 
 | #ifdef DEBUG_IDC | 
 |     { | 
 | 	xmlChar *str = NULL; | 
 | 	xmlGenericError(xmlGenericErrorContext, | 
 | 	    "IDC: EVAL on %s, depth %d, type %d\n", | 
 | 	    xmlSchemaFormatQName(&str, vctxt->inode->nsName, | 
 | 		vctxt->inode->localName), depth, nodeType); | 
 | 	FREE_AND_NULL(str) | 
 |     } | 
 | #endif | 
 |     /* | 
 |     * Process all active XPath state objects. | 
 |     */ | 
 |     first = vctxt->xpathStates; | 
 |     sto = first; | 
 |     while (sto != head) { | 
 | #ifdef DEBUG_IDC | 
 | 	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) | 
 | 	    xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] selector '%s'\n", | 
 | 		sto->matcher->aidc->def->name, sto->sel->xpath); | 
 | 	else | 
 | 	    xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] field '%s'\n", | 
 | 		sto->matcher->aidc->def->name, sto->sel->xpath); | 
 | #endif | 
 | 	if (nodeType == XML_ELEMENT_NODE) | 
 | 	    res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt, | 
 | 		vctxt->inode->localName, vctxt->inode->nsName); | 
 | 	else | 
 | 	    res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt, | 
 | 		vctxt->inode->localName, vctxt->inode->nsName); | 
 |  | 
 | 	if (res == -1) { | 
 | 	    VERROR_INT("xmlSchemaXPathEvaluate", | 
 | 		"calling xmlStreamPush()"); | 
 | 	    return (-1); | 
 | 	} | 
 | 	if (res == 0) | 
 | 	    goto next_sto; | 
 | 	/* | 
 | 	* Full match. | 
 | 	*/ | 
 | #ifdef DEBUG_IDC | 
 | 	xmlGenericError(xmlGenericErrorContext, "IDC:     " | 
 | 	    "MATCH\n"); | 
 | #endif | 
 | 	/* | 
 | 	* Register a match in the state object history. | 
 | 	*/ | 
 | 	if (sto->history == NULL) { | 
 | 	    sto->history = (int *) xmlMalloc(5 * sizeof(int)); | 
 | 	    if (sto->history == NULL) { | 
 | 		xmlSchemaVErrMemory(NULL, | 
 | 		    "allocating the state object history", NULL); | 
 | 		return(-1); | 
 | 	    } | 
 | 	    sto->sizeHistory = 5; | 
 | 	} else if (sto->sizeHistory <= sto->nbHistory) { | 
 | 	    sto->sizeHistory *= 2; | 
 | 	    sto->history = (int *) xmlRealloc(sto->history, | 
 | 		sto->sizeHistory * sizeof(int)); | 
 | 	    if (sto->history == NULL) { | 
 | 		xmlSchemaVErrMemory(NULL, | 
 | 		    "re-allocating the state object history", NULL); | 
 | 		return(-1); | 
 | 	    } | 
 | 	} | 
 | 	sto->history[sto->nbHistory++] = depth; | 
 |  | 
 | #ifdef DEBUG_IDC | 
 | 	xmlGenericError(xmlGenericErrorContext, "IDC:       push match '%d'\n", | 
 | 	    vctxt->depth); | 
 | #endif | 
 |  | 
 | 	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) { | 
 | 	    xmlSchemaIDCSelectPtr sel; | 
 | 	    /* | 
 | 	    * Activate state objects for the IDC fields of | 
 | 	    * the IDC selector. | 
 | 	    */ | 
 | #ifdef DEBUG_IDC | 
 | 	    xmlGenericError(xmlGenericErrorContext, "IDC:     " | 
 | 		"activating field states\n"); | 
 | #endif | 
 | 	    sel = sto->matcher->aidc->def->fields; | 
 | 	    while (sel != NULL) { | 
 | 		if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher, | 
 | 		    sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1) | 
 | 		    return (-1); | 
 | 		sel = sel->next; | 
 | 	    } | 
 | 	} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) { | 
 | 	    /* | 
 | 	    * An IDC key node was found by the IDC field. | 
 | 	    */ | 
 | #ifdef DEBUG_IDC | 
 | 	    xmlGenericError(xmlGenericErrorContext, | 
 | 		"IDC:     key found\n"); | 
 | #endif | 
 | 	    /* | 
 | 	    * Notify that the character value of this node is | 
 | 	    * needed. | 
 | 	    */ | 
 | 	    if (resolved == 0) { | 
 | 		if ((vctxt->inode->flags & | 
 | 		    XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0) | 
 | 		vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED; | 
 | 	    } | 
 | 	    resolved++; | 
 | 	} | 
 | next_sto: | 
 | 	if (sto->next == NULL) { | 
 | 	    /* | 
 | 	    * Evaluate field state objects created on this node as well. | 
 | 	    */ | 
 | 	    head = first; | 
 | 	    sto = vctxt->xpathStates; | 
 | 	} else | 
 | 	    sto = sto->next; | 
 |     } | 
 |     return (resolved); | 
 | } | 
 |  | 
 | static const xmlChar * | 
 | xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt, | 
 | 			      xmlChar **buf, | 
 | 			      xmlSchemaPSVIIDCKeyPtr *seq, | 
 | 			      int count) | 
 | { | 
 |     int i, res; | 
 |     xmlChar *value = NULL; | 
 |  | 
 |     *buf = xmlStrdup(BAD_CAST "["); | 
 |     for (i = 0; i < count; i++) { | 
 | 	*buf = xmlStrcat(*buf, BAD_CAST "'"); | 
 | 	res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val, | 
 | 	    xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type), | 
 | 	    &value); | 
 | 	if (res == 0) | 
 | 	    *buf = xmlStrcat(*buf, BAD_CAST value); | 
 | 	else { | 
 | 	    VERROR_INT("xmlSchemaFormatIDCKeySequence", | 
 | 		"failed to compute a canonical value"); | 
 | 	    *buf = xmlStrcat(*buf, BAD_CAST "???"); | 
 | 	} | 
 | 	if (i < count -1) | 
 | 	    *buf = xmlStrcat(*buf, BAD_CAST "', "); | 
 | 	else | 
 | 	    *buf = xmlStrcat(*buf, BAD_CAST "'"); | 
 | 	if (value != NULL) { | 
 | 	    xmlFree(value); | 
 | 	    value = NULL; | 
 | 	} | 
 |     } | 
 |     *buf = xmlStrcat(*buf, BAD_CAST "]"); | 
 |  | 
 |     return (BAD_CAST *buf); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaXPathPop: | 
 |  * @vctxt: the WXS validation context | 
 |  * | 
 |  * Pops all XPath states. | 
 |  * | 
 |  * Returns 0 on success and -1 on internal errors. | 
 |  */ | 
 | static int | 
 | xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt) | 
 | { | 
 |     xmlSchemaIDCStateObjPtr sto; | 
 |     int res; | 
 |  | 
 |     if (vctxt->xpathStates == NULL) | 
 | 	return(0); | 
 |     sto = vctxt->xpathStates; | 
 |     do { | 
 | 	res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt); | 
 | 	if (res == -1) | 
 | 	    return (-1); | 
 | 	sto = sto->next; | 
 |     } while (sto != NULL); | 
 |     return(0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaXPathProcessHistory: | 
 |  * @vctxt: the WXS validation context | 
 |  * @type: the simple/complex type of the current node if any at all | 
 |  * @val: the precompiled value | 
 |  * | 
 |  * Processes and pops the history items of the IDC state objects. | 
 |  * IDC key-sequences are validated/created on IDC bindings. | 
 |  * | 
 |  * Returns 0 on success and -1 on internal errors. | 
 |  */ | 
 | static int | 
 | xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt, | 
 | 			     int depth) | 
 | { | 
 |     xmlSchemaIDCStateObjPtr sto, nextsto; | 
 |     int res, matchDepth; | 
 |     xmlSchemaPSVIIDCKeyPtr key = NULL; | 
 |     xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL; | 
 |  | 
 |     if (vctxt->xpathStates == NULL) | 
 | 	return (0); | 
 |     sto = vctxt->xpathStates; | 
 |  | 
 | #ifdef DEBUG_IDC | 
 |     { | 
 | 	xmlChar *str = NULL; | 
 | 	xmlGenericError(xmlGenericErrorContext, | 
 | 	    "IDC: BACK on %s, depth %d\n", | 
 | 	    xmlSchemaFormatQName(&str, vctxt->inode->nsName, | 
 | 		vctxt->inode->localName), vctxt->depth); | 
 | 	FREE_AND_NULL(str) | 
 |     } | 
 | #endif | 
 |     /* | 
 |     * Evaluate the state objects. | 
 |     */ | 
 |     while (sto != NULL) { | 
 | 	res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt); | 
 | 	if (res == -1) { | 
 | 	    VERROR_INT("xmlSchemaXPathProcessHistory", | 
 | 		"calling xmlStreamPop()"); | 
 | 	    return (-1); | 
 | 	} | 
 | #ifdef DEBUG_IDC | 
 | 	xmlGenericError(xmlGenericErrorContext, "IDC:   stream pop '%s'\n", | 
 | 	    sto->sel->xpath); | 
 | #endif | 
 | 	if (sto->nbHistory == 0) | 
 | 	    goto deregister_check; | 
 |  | 
 | 	matchDepth = sto->history[sto->nbHistory -1]; | 
 |  | 
 | 	/* | 
 | 	* Only matches at the current depth are of interest. | 
 | 	*/ | 
 | 	if (matchDepth != depth) { | 
 | 	    sto = sto->next; | 
 | 	    continue; | 
 | 	} | 
 | 	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) { | 
 | 	    /* | 
 | 	    * NOTE: According to | 
 | 	    *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198 | 
 | 	    *   ... the simple-content of complex types is also allowed. | 
 | 	    */ | 
 |  | 
 | 	    if (WXS_IS_COMPLEX(type)) { | 
 | 		if (WXS_HAS_SIMPLE_CONTENT(type)) { | 
 | 		    /* | 
 | 		    * Sanity check for complex types with simple content. | 
 | 		    */ | 
 | 		    simpleType = type->contentTypeDef; | 
 | 		    if (simpleType == NULL) { | 
 | 			VERROR_INT("xmlSchemaXPathProcessHistory", | 
 | 			    "field resolves to a CT with simple content " | 
 | 			    "but the CT is missing the ST definition"); | 
 | 			return (-1); | 
 | 		    } | 
 | 		} else | 
 | 		    simpleType = NULL; | 
 | 	    } else | 
 | 		simpleType = type; | 
 | 	    if (simpleType == NULL) { | 
 | 		xmlChar *str = NULL; | 
 |  | 
 | 		/* | 
 | 		* Not qualified if the field resolves to a node of non | 
 | 		* simple type. | 
 | 		*/ | 
 | 		xmlSchemaCustomErr(ACTXT_CAST vctxt, | 
 | 		    XML_SCHEMAV_CVC_IDC, NULL, | 
 | 		    WXS_BASIC_CAST sto->matcher->aidc->def, | 
 | 		    "The XPath '%s' of a field of %s does evaluate to a node of " | 
 | 		    "non-simple type", | 
 | 		    sto->sel->xpath, | 
 | 		    xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def)); | 
 | 		FREE_AND_NULL(str); | 
 | 		sto->nbHistory--; | 
 | 		goto deregister_check; | 
 | 	    } | 
 |  | 
 | 	    if ((key == NULL) && (vctxt->inode->val == NULL)) { | 
 | 		/* | 
 | 		* Failed to provide the normalized value; maybe | 
 | 		* the value was invalid. | 
 | 		*/ | 
 | 		VERROR(XML_SCHEMAV_CVC_IDC, | 
 | 		    WXS_BASIC_CAST sto->matcher->aidc->def, | 
 | 		    "Warning: No precomputed value available, the value " | 
 | 		    "was either invalid or something strange happend"); | 
 | 		sto->nbHistory--; | 
 | 		goto deregister_check; | 
 | 	    } else { | 
 | 		xmlSchemaIDCMatcherPtr matcher = sto->matcher; | 
 | 		xmlSchemaPSVIIDCKeyPtr *keySeq; | 
 | 		int pos, idx; | 
 |  | 
 | 		/* | 
 | 		* The key will be anchored on the matcher's list of | 
 | 		* key-sequences. The position in this list is determined | 
 | 		* by the target node's depth relative to the matcher's | 
 | 		* depth of creation (i.e. the depth of the scope element). | 
 | 		* | 
 | 		* Element        Depth    Pos   List-entries | 
 | 		* <scope>          0              NULL | 
 | 		*   <bar>          1              NULL | 
 | 		*     <target/>    2       2      target | 
 | 		*   <bar> | 
 |                 * </scope> | 
 | 		* | 
 | 		* The size of the list is only dependant on the depth of | 
 | 		* the tree. | 
 | 		* An entry will be NULLed in selector_leave, i.e. when | 
 | 		* we hit the target's | 
 | 		*/ | 
 | 		pos = sto->depth - matcher->depth; | 
 | 		idx = sto->sel->index; | 
 |  | 
 | 		/* | 
 | 		* Create/grow the array of key-sequences. | 
 | 		*/ | 
 | 		if (matcher->keySeqs == NULL) { | 
 | 		    if (pos > 9) | 
 | 			matcher->sizeKeySeqs = pos * 2; | 
 | 		    else | 
 | 			matcher->sizeKeySeqs = 10; | 
 | 		    matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **) | 
 | 			xmlMalloc(matcher->sizeKeySeqs * | 
 | 			sizeof(xmlSchemaPSVIIDCKeyPtr *)); | 
 | 		    if (matcher->keySeqs == NULL) { | 
 | 			xmlSchemaVErrMemory(NULL, | 
 | 			    "allocating an array of key-sequences", | 
 | 			    NULL); | 
 | 			return(-1); | 
 | 		    } | 
 | 		    memset(matcher->keySeqs, 0, | 
 | 			matcher->sizeKeySeqs * | 
 | 			sizeof(xmlSchemaPSVIIDCKeyPtr *)); | 
 | 		} else if (pos >= matcher->sizeKeySeqs) { | 
 | 		    int i = matcher->sizeKeySeqs; | 
 |  | 
 | 		    matcher->sizeKeySeqs *= 2; | 
 | 		    matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **) | 
 | 			xmlRealloc(matcher->keySeqs, | 
 | 			matcher->sizeKeySeqs * | 
 | 			sizeof(xmlSchemaPSVIIDCKeyPtr *)); | 
 | 		    if (matcher->keySeqs == NULL) { | 
 | 			xmlSchemaVErrMemory(NULL, | 
 | 			    "reallocating an array of key-sequences", | 
 | 			    NULL); | 
 | 			return (-1); | 
 | 		    } | 
 | 		    /* | 
 | 		    * The array needs to be NULLed. | 
 | 		    * TODO: Use memset? | 
 | 		    */ | 
 | 		    for (; i < matcher->sizeKeySeqs; i++) | 
 | 			matcher->keySeqs[i] = NULL; | 
 | 		} | 
 |  | 
 | 		/* | 
 | 		* Get/create the key-sequence. | 
 | 		*/ | 
 | 		keySeq = matcher->keySeqs[pos]; | 
 | 		if (keySeq == NULL) { | 
 | 		    goto create_sequence; | 
 | 		} else if (keySeq[idx] != NULL) { | 
 | 		    xmlChar *str = NULL; | 
 | 		    /* | 
 | 		    * cvc-identity-constraint: | 
 | 		    * 3 For each node in the �target node set� all | 
 | 		    * of the {fields}, with that node as the context | 
 | 		    * node, evaluate to either an empty node-set or | 
 | 		    * a node-set with exactly one member, which must | 
 | 		    * have a simple type. | 
 | 		    * | 
 | 		    * The key was already set; report an error. | 
 | 		    */ | 
 | 		    xmlSchemaCustomErr(ACTXT_CAST vctxt, | 
 | 			XML_SCHEMAV_CVC_IDC, NULL, | 
 | 			WXS_BASIC_CAST matcher->aidc->def, | 
 | 			"The XPath '%s' of a field of %s evaluates to a " | 
 | 			"node-set with more than one member", | 
 | 			sto->sel->xpath, | 
 | 			xmlSchemaGetIDCDesignation(&str, matcher->aidc->def)); | 
 | 		    FREE_AND_NULL(str); | 
 | 		    sto->nbHistory--; | 
 | 		    goto deregister_check; | 
 | 		} else | 
 | 		    goto create_key; | 
 |  | 
 | create_sequence: | 
 | 		/* | 
 | 		* Create a key-sequence. | 
 | 		*/ | 
 | 		keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc( | 
 | 		    matcher->aidc->def->nbFields * | 
 | 		    sizeof(xmlSchemaPSVIIDCKeyPtr)); | 
 | 		if (keySeq == NULL) { | 
 | 		    xmlSchemaVErrMemory(NULL, | 
 | 			"allocating an IDC key-sequence", NULL); | 
 | 		    return(-1); | 
 | 		} | 
 | 		memset(keySeq, 0, matcher->aidc->def->nbFields * | 
 | 		    sizeof(xmlSchemaPSVIIDCKeyPtr)); | 
 | 		matcher->keySeqs[pos] = keySeq; | 
 | create_key: | 
 | 		/* | 
 | 		* Create a key once per node only. | 
 | 		*/ | 
 | 		if (key == NULL) { | 
 | 		    key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc( | 
 | 			sizeof(xmlSchemaPSVIIDCKey)); | 
 | 		    if (key == NULL) { | 
 | 			xmlSchemaVErrMemory(NULL, | 
 | 			    "allocating a IDC key", NULL); | 
 | 			xmlFree(keySeq); | 
 | 			matcher->keySeqs[pos] = NULL; | 
 | 			return(-1); | 
 | 		    } | 
 | 		    /* | 
 | 		    * Consume the compiled value. | 
 | 		    */ | 
 | 		    key->type = simpleType; | 
 | 		    key->val = vctxt->inode->val; | 
 | 		    vctxt->inode->val = NULL; | 
 | 		    /* | 
 | 		    * Store the key in a global list. | 
 | 		    */ | 
 | 		    if (xmlSchemaIDCStoreKey(vctxt, key) == -1) { | 
 | 			xmlSchemaIDCFreeKey(key); | 
 | 			return (-1); | 
 | 		    } | 
 | 		} | 
 | 		keySeq[idx] = key; | 
 | 	    } | 
 | 	} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) { | 
 |  | 
 | 	    xmlSchemaPSVIIDCKeyPtr **keySeq = NULL; | 
 | 	    /* xmlSchemaPSVIIDCBindingPtr bind; */ | 
 | 	    xmlSchemaPSVIIDCNodePtr ntItem; | 
 | 	    xmlSchemaIDCMatcherPtr matcher; | 
 | 	    xmlSchemaIDCPtr idc; | 
 | 	    xmlSchemaItemListPtr targets; | 
 | 	    int pos, i, j, nbKeys; | 
 | 	    /* | 
 | 	    * Here we have the following scenario: | 
 | 	    * An IDC 'selector' state object resolved to a target node, | 
 | 	    * during the time this target node was in the | 
 | 	    * ancestor-or-self axis, the 'field' state object(s) looked | 
 | 	    * out for matching nodes to create a key-sequence for this | 
 | 	    * target node. Now we are back to this target node and need | 
 | 	    * to put the key-sequence, together with the target node | 
 | 	    * itself, into the node-table of the corresponding IDC | 
 | 	    * binding. | 
 | 	    */ | 
 | 	    matcher = sto->matcher; | 
 | 	    idc = matcher->aidc->def; | 
 | 	    nbKeys = idc->nbFields; | 
 | 	    pos = depth - matcher->depth; | 
 | 	    /* | 
 | 	    * Check if the matcher has any key-sequences at all, plus | 
 | 	    * if it has a key-sequence for the current target node. | 
 | 	    */ | 
 | 	    if ((matcher->keySeqs == NULL) || | 
 | 		(matcher->sizeKeySeqs <= pos)) { | 
 | 		if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) | 
 | 		    goto selector_key_error; | 
 | 		else | 
 | 		    goto selector_leave; | 
 | 	    } | 
 |  | 
 | 	    keySeq = &(matcher->keySeqs[pos]); | 
 | 	    if (*keySeq == NULL) { | 
 | 		if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) | 
 | 		    goto selector_key_error; | 
 | 		else | 
 | 		    goto selector_leave; | 
 | 	    } | 
 |  | 
 | 	    for (i = 0; i < nbKeys; i++) { | 
 | 		if ((*keySeq)[i] == NULL) { | 
 | 		    /* | 
 | 		    * Not qualified, if not all fields did resolve. | 
 | 		    */ | 
 | 		    if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) { | 
 | 			/* | 
 | 			* All fields of a "key" IDC must resolve. | 
 | 			*/ | 
 | 			goto selector_key_error; | 
 | 		    } | 
 | 		    goto selector_leave; | 
 | 		} | 
 | 	    } | 
 | 	    /* | 
 | 	    * All fields did resolve. | 
 | 	    */ | 
 |  | 
 | 	    /* | 
 | 	    * 4.1 If the {identity-constraint category} is unique(/key), | 
 | 	    * then no two members of the �qualified node set� have | 
 | 	    * �key-sequences� whose members are pairwise equal, as | 
 | 	    * defined by Equal in [XML Schemas: Datatypes]. | 
 | 	    * | 
 | 	    * Get the IDC binding from the matcher and check for | 
 | 	    * duplicate key-sequences. | 
 | 	    */ | 
 | #if 0 | 
 | 	    bind = xmlSchemaIDCAcquireBinding(vctxt, matcher); | 
 | #endif | 
 | 	    targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher); | 
 | 	    if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) && | 
 | 		(targets->nbItems != 0)) { | 
 | 		xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq; | 
 |  | 
 | 		i = 0; | 
 | 		res = 0; | 
 | 		/* | 
 | 		* Compare the key-sequences, key by key. | 
 | 		*/ | 
 | 		do { | 
 | 		    bkeySeq = | 
 | 			((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys; | 
 | 		    for (j = 0; j < nbKeys; j++) { | 
 | 			ckey = (*keySeq)[j]; | 
 | 			bkey = bkeySeq[j]; | 
 | 			res = xmlSchemaAreValuesEqual(ckey->val, bkey->val); | 
 | 			if (res == -1) { | 
 | 			    return (-1); | 
 | 			} else if (res == 0) { | 
 | 			    /* | 
 | 			    * One of the keys differs, so the key-sequence | 
 | 			    * won't be equal; get out. | 
 | 			    */ | 
 | 			    break; | 
 | 			} | 
 | 		    } | 
 | 		    if (res == 1) { | 
 | 			/* | 
 | 			* Duplicate key-sequence found. | 
 | 			*/ | 
 | 			break; | 
 | 		    } | 
 | 		    i++; | 
 | 		} while (i < targets->nbItems); | 
 | 		if (i != targets->nbItems) { | 
 | 		    xmlChar *str = NULL, *strB = NULL; | 
 | 		    /* | 
 | 		    * TODO: Try to report the key-sequence. | 
 | 		    */ | 
 | 		    xmlSchemaCustomErr(ACTXT_CAST vctxt, | 
 | 			XML_SCHEMAV_CVC_IDC, NULL, | 
 | 			WXS_BASIC_CAST idc, | 
 | 			"Duplicate key-sequence %s in %s", | 
 | 			xmlSchemaFormatIDCKeySequence(vctxt, &str, | 
 | 			    (*keySeq), nbKeys), | 
 | 			xmlSchemaGetIDCDesignation(&strB, idc)); | 
 | 		    FREE_AND_NULL(str); | 
 | 		    FREE_AND_NULL(strB); | 
 | 		    goto selector_leave; | 
 | 		} | 
 | 	    } | 
 | 	    /* | 
 | 	    * Add a node-table item to the IDC binding. | 
 | 	    */ | 
 | 	    ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc( | 
 | 		sizeof(xmlSchemaPSVIIDCNode)); | 
 | 	    if (ntItem == NULL) { | 
 | 		xmlSchemaVErrMemory(NULL, | 
 | 		    "allocating an IDC node-table item", NULL); | 
 | 		xmlFree(*keySeq); | 
 | 		*keySeq = NULL; | 
 | 		return(-1); | 
 | 	    } | 
 | 	    memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode)); | 
 |  | 
 | 	    /* | 
 | 	    * Store the node-table item in a global list. | 
 | 	    */ | 
 | 	    if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) { | 
 | 		if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) { | 
 | 		    xmlFree(ntItem); | 
 | 		    xmlFree(*keySeq); | 
 | 		    *keySeq = NULL; | 
 | 		    return (-1); | 
 | 		} | 
 | 		ntItem->nodeQNameID = -1; | 
 | 	    } else { | 
 | 		/* | 
 | 		* Save a cached QName for this node on the IDC node, to be | 
 | 		* able to report it, even if the node is not saved. | 
 | 		*/ | 
 | 		ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt, | 
 | 		    vctxt->inode->localName, vctxt->inode->nsName); | 
 | 		if (ntItem->nodeQNameID == -1) { | 
 | 		    xmlFree(ntItem); | 
 | 		    xmlFree(*keySeq); | 
 | 		    *keySeq = NULL; | 
 | 		    return (-1); | 
 | 		} | 
 | 	    } | 
 | 	    /* | 
 | 	    * Init the node-table item: Save the node, position and | 
 | 	    * consume the key-sequence. | 
 | 	    */ | 
 | 	    ntItem->node = vctxt->node; | 
 | 	    ntItem->nodeLine = vctxt->inode->nodeLine; | 
 | 	    ntItem->keys = *keySeq; | 
 | 	    *keySeq = NULL; | 
 | #if 0 | 
 | 	    if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) | 
 | #endif | 
 | 	    if (xmlSchemaItemListAdd(targets, ntItem) == -1) { | 
 | 		if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) { | 
 | 		    /* | 
 | 		    * Free the item, since keyref items won't be | 
 | 		    * put on a global list. | 
 | 		    */ | 
 | 		    xmlFree(ntItem->keys); | 
 | 		    xmlFree(ntItem); | 
 | 		} | 
 | 		return (-1); | 
 | 	    } | 
 |  | 
 | 	    goto selector_leave; | 
 | selector_key_error: | 
 | 	    { | 
 | 		xmlChar *str = NULL; | 
 | 		/* | 
 | 		* 4.2.1 (KEY) The �target node set� and the | 
 | 		* �qualified node set� are equal, that is, every | 
 | 		* member of the �target node set� is also a member | 
 | 		* of the �qualified node set� and vice versa. | 
 | 		*/ | 
 | 		xmlSchemaCustomErr(ACTXT_CAST vctxt, | 
 | 		    XML_SCHEMAV_CVC_IDC, NULL, | 
 | 		    WXS_BASIC_CAST idc, | 
 | 		    "Not all fields of %s evaluate to a node", | 
 | 		    xmlSchemaGetIDCDesignation(&str, idc), NULL); | 
 | 		FREE_AND_NULL(str); | 
 | 	    } | 
 | selector_leave: | 
 | 	    /* | 
 | 	    * Free the key-sequence if not added to the IDC table. | 
 | 	    */ | 
 | 	    if ((keySeq != NULL) && (*keySeq != NULL)) { | 
 | 		xmlFree(*keySeq); | 
 | 		*keySeq = NULL; | 
 | 	    } | 
 | 	} /* if selector */ | 
 |  | 
 | 	sto->nbHistory--; | 
 |  | 
 | deregister_check: | 
 | 	/* | 
 | 	* Deregister state objects if they reach the depth of creation. | 
 | 	*/ | 
 | 	if ((sto->nbHistory == 0) && (sto->depth == depth)) { | 
 | #ifdef DEBUG_IDC | 
 | 	    xmlGenericError(xmlGenericErrorContext, "IDC:   STO pop '%s'\n", | 
 | 		sto->sel->xpath); | 
 | #endif | 
 | 	    if (vctxt->xpathStates != sto) { | 
 | 		VERROR_INT("xmlSchemaXPathProcessHistory", | 
 | 		    "The state object to be removed is not the first " | 
 | 		    "in the list"); | 
 | 	    } | 
 | 	    nextsto = sto->next; | 
 | 	    /* | 
 | 	    * Unlink from the list of active XPath state objects. | 
 | 	    */ | 
 | 	    vctxt->xpathStates = sto->next; | 
 | 	    sto->next = vctxt->xpathStatePool; | 
 | 	    /* | 
 | 	    * Link it to the pool of reusable state objects. | 
 | 	    */ | 
 | 	    vctxt->xpathStatePool = sto; | 
 | 	    sto = nextsto; | 
 | 	} else | 
 | 	    sto = sto->next; | 
 |     } /* while (sto != NULL) */ | 
 |     return (0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaIDCRegisterMatchers: | 
 |  * @vctxt: the WXS validation context | 
 |  * @elemDecl: the element declaration | 
 |  * | 
 |  * Creates helper objects to evaluate IDC selectors/fields | 
 |  * successively. | 
 |  * | 
 |  * Returns 0 if OK and -1 on internal errors. | 
 |  */ | 
 | static int | 
 | xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt, | 
 | 			     xmlSchemaElementPtr elemDecl) | 
 | { | 
 |     xmlSchemaIDCMatcherPtr matcher, last = NULL; | 
 |     xmlSchemaIDCPtr idc, refIdc; | 
 |     xmlSchemaIDCAugPtr aidc; | 
 |  | 
 |     idc = (xmlSchemaIDCPtr) elemDecl->idcs; | 
 |     if (idc == NULL) | 
 | 	return (0); | 
 |  | 
 | #ifdef DEBUG_IDC | 
 |     { | 
 | 	xmlChar *str = NULL; | 
 | 	xmlGenericError(xmlGenericErrorContext, | 
 | 	    "IDC: REGISTER on %s, depth %d\n", | 
 | 	    (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName, | 
 | 		vctxt->inode->localName), vctxt->depth); | 
 | 	FREE_AND_NULL(str) | 
 |     } | 
 | #endif | 
 |     if (vctxt->inode->idcMatchers != NULL) { | 
 | 	VERROR_INT("xmlSchemaIDCRegisterMatchers", | 
 | 	    "The chain of IDC matchers is expected to be empty"); | 
 | 	return (-1); | 
 |     } | 
 |     do { | 
 | 	if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) { | 
 | 	    /* | 
 | 	    * Since IDCs bubbles are expensive we need to know the | 
 | 	    * depth at which the bubbles should stop; this will be | 
 | 	    * the depth of the top-most keyref IDC. If no keyref | 
 | 	    * references a key/unique IDC, the keyrefDepth will | 
 | 	    * be -1, indicating that no bubbles are needed. | 
 | 	    */ | 
 | 	    refIdc = (xmlSchemaIDCPtr) idc->ref->item; | 
 | 	    if (refIdc != NULL) { | 
 | 		/* | 
 | 		* Remember that we have keyrefs on this node. | 
 | 		*/ | 
 | 		vctxt->inode->hasKeyrefs = 1; | 
 | 		/* | 
 | 		* Lookup the referenced augmented IDC info. | 
 | 		*/ | 
 | 		aidc = vctxt->aidcs; | 
 | 		while (aidc != NULL) { | 
 | 		    if (aidc->def == refIdc) | 
 | 			break; | 
 | 		    aidc = aidc->next; | 
 | 		} | 
 | 		if (aidc == NULL) { | 
 | 		    VERROR_INT("xmlSchemaIDCRegisterMatchers", | 
 | 			"Could not find an augmented IDC item for an IDC " | 
 | 			"definition"); | 
 | 		    return (-1); | 
 | 		} | 
 | 		if ((aidc->keyrefDepth == -1) || | 
 | 		    (vctxt->depth < aidc->keyrefDepth)) | 
 | 		    aidc->keyrefDepth = vctxt->depth; | 
 | 	    } | 
 | 	} | 
 | 	/* | 
 | 	* Lookup the augmented IDC item for the IDC definition. | 
 | 	*/ | 
 | 	aidc = vctxt->aidcs; | 
 | 	while (aidc != NULL) { | 
 | 	    if (aidc->def == idc) | 
 | 		break; | 
 | 	    aidc = aidc->next; | 
 | 	} | 
 | 	if (aidc == NULL) { | 
 | 	    VERROR_INT("xmlSchemaIDCRegisterMatchers", | 
 | 		"Could not find an augmented IDC item for an IDC definition"); | 
 | 	    return (-1); | 
 | 	} | 
 | 	/* | 
 | 	* Create an IDC matcher for every IDC definition. | 
 | 	*/ | 
 | 	if (vctxt->idcMatcherCache != NULL) { | 
 | 	    /* | 
 | 	    * Reuse a cached matcher. | 
 | 	    */ | 
 | 	    matcher = vctxt->idcMatcherCache; | 
 | 	    vctxt->idcMatcherCache = matcher->nextCached; | 
 | 	    matcher->nextCached = NULL; | 
 | 	} else { | 
 | 	    matcher = (xmlSchemaIDCMatcherPtr) | 
 | 		xmlMalloc(sizeof(xmlSchemaIDCMatcher)); | 
 | 	    if (matcher == NULL) { | 
 | 		xmlSchemaVErrMemory(vctxt, | 
 | 		    "allocating an IDC matcher", NULL); | 
 | 		return (-1); | 
 | 	    } | 
 | 	    memset(matcher, 0, sizeof(xmlSchemaIDCMatcher)); | 
 | 	} | 
 | 	if (last == NULL) | 
 | 	    vctxt->inode->idcMatchers = matcher; | 
 | 	else | 
 | 	    last->next = matcher; | 
 | 	last = matcher; | 
 |  | 
 | 	matcher->type = IDC_MATCHER; | 
 | 	matcher->depth = vctxt->depth; | 
 | 	matcher->aidc = aidc; | 
 | 	matcher->idcType = aidc->def->type; | 
 | #ifdef DEBUG_IDC | 
 | 	xmlGenericError(xmlGenericErrorContext, "IDC:   register matcher\n"); | 
 | #endif | 
 | 	/* | 
 | 	* Init the automaton state object. | 
 | 	*/ | 
 | 	if (xmlSchemaIDCAddStateObject(vctxt, matcher, | 
 | 	    idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1) | 
 | 	    return (-1); | 
 |  | 
 | 	idc = idc->next; | 
 |     } while (idc != NULL); | 
 |     return (0); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt, | 
 | 			   xmlSchemaNodeInfoPtr ielem) | 
 | { | 
 |     xmlSchemaPSVIIDCBindingPtr bind; | 
 |     int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable; | 
 |     xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys; | 
 |     xmlSchemaPSVIIDCNodePtr *targets, *dupls; | 
 |  | 
 |     xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers; | 
 |     /* vctxt->createIDCNodeTables */ | 
 |     while (matcher != NULL) { | 
 | 	/* | 
 | 	* Skip keyref IDCs and empty IDC target-lists. | 
 | 	*/ | 
 | 	if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) || | 
 | 	    WXS_ILIST_IS_EMPTY(matcher->targets)) | 
 | 	{ | 
 | 	    matcher = matcher->next; | 
 | 	    continue; | 
 | 	} | 
 | 	/* | 
 | 	* If we _want_ the IDC node-table to be created in any case | 
 | 	* then do so. Otherwise create them only if keyrefs need them. | 
 | 	*/ | 
 | 	if ((! vctxt->createIDCNodeTables) && | 
 | 	    ((matcher->aidc->keyrefDepth == -1) || | 
 | 	     (matcher->aidc->keyrefDepth > vctxt->depth))) | 
 | 	{ | 
 | 	    matcher = matcher->next; | 
 | 	    continue; | 
 | 	} | 
 | 	/* | 
 | 	* Get/create the IDC binding on this element for the IDC definition. | 
 | 	*/ | 
 | 	bind = xmlSchemaIDCAcquireBinding(vctxt, matcher); | 
 |  | 
 | 	if (! WXS_ILIST_IS_EMPTY(bind->dupls)) { | 
 | 	    dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items; | 
 | 	    nbDupls = bind->dupls->nbItems; | 
 | 	} else { | 
 | 	    dupls = NULL; | 
 | 	    nbDupls = 0; | 
 | 	} | 
 | 	if (bind->nodeTable != NULL) { | 
 | 	    nbNodeTable = bind->nbNodes; | 
 | 	} else { | 
 | 	    nbNodeTable = 0; | 
 | 	} | 
 |  | 
 | 	if ((nbNodeTable == 0) && (nbDupls == 0)) { | 
 | 	    /* | 
 | 	    * Transfer all IDC target-nodes to the IDC node-table. | 
 | 	    */ | 
 | 	    bind->nodeTable = | 
 | 		(xmlSchemaPSVIIDCNodePtr *) matcher->targets->items; | 
 | 	    bind->sizeNodes = matcher->targets->sizeItems; | 
 | 	    bind->nbNodes = matcher->targets->nbItems; | 
 |  | 
 | 	    matcher->targets->items = NULL; | 
 | 	    matcher->targets->sizeItems = 0; | 
 | 	    matcher->targets->nbItems = 0; | 
 | 	} else { | 
 | 	    /* | 
 | 	    * Compare the key-sequences and add to the IDC node-table. | 
 | 	    */ | 
 | 	    nbTargets = matcher->targets->nbItems; | 
 | 	    targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items; | 
 | 	    nbFields = matcher->aidc->def->nbFields; | 
 | 	    i = 0; | 
 | 	    do { | 
 | 		keys = targets[i]->keys; | 
 | 		if (nbDupls) { | 
 | 		    /* | 
 | 		    * Search in already found duplicates first. | 
 | 		    */ | 
 | 		    j = 0; | 
 | 		    do { | 
 | 			if (nbFields == 1) { | 
 | 			    res = xmlSchemaAreValuesEqual(keys[0]->val, | 
 | 				dupls[j]->keys[0]->val); | 
 | 			    if (res == -1) | 
 | 				goto internal_error; | 
 | 			    if (res == 1) { | 
 | 				/* | 
 | 				* Equal key-sequence. | 
 | 				*/ | 
 | 				goto next_target; | 
 | 			    } | 
 | 			} else { | 
 | 			    res = 0; | 
 | 			    ntkeys = dupls[j]->keys; | 
 | 			    for (k = 0; k < nbFields; k++) { | 
 | 				res = xmlSchemaAreValuesEqual(keys[k]->val, | 
 | 				    ntkeys[k]->val); | 
 | 				if (res == -1) | 
 | 				    goto internal_error; | 
 | 				if (res == 0) { | 
 | 				    /* | 
 | 				    * One of the keys differs. | 
 | 				    */ | 
 | 				    break; | 
 | 				} | 
 | 			    } | 
 | 			    if (res == 1) { | 
 | 				/* | 
 | 				* Equal key-sequence found. | 
 | 				*/ | 
 | 				goto next_target; | 
 | 			    } | 
 | 			} | 
 | 			j++; | 
 | 		    } while (j < nbDupls); | 
 | 		} | 
 | 		if (nbNodeTable) { | 
 | 		    j = 0; | 
 | 		    do { | 
 | 			if (nbFields == 1) { | 
 | 			    res = xmlSchemaAreValuesEqual(keys[0]->val, | 
 | 				bind->nodeTable[j]->keys[0]->val); | 
 | 			    if (res == -1) | 
 | 				goto internal_error; | 
 | 			    if (res == 0) { | 
 | 				/* | 
 | 				* The key-sequence differs. | 
 | 				*/ | 
 | 				goto next_node_table_entry; | 
 | 			    } | 
 | 			} else { | 
 | 			    res = 0; | 
 | 			    ntkeys = bind->nodeTable[j]->keys; | 
 | 			    for (k = 0; k < nbFields; k++) { | 
 | 				res = xmlSchemaAreValuesEqual(keys[k]->val, | 
 | 				    ntkeys[k]->val); | 
 | 				if (res == -1) | 
 | 				    goto internal_error; | 
 | 				if (res == 0) { | 
 | 				    /* | 
 | 				    * One of the keys differs. | 
 | 				    */ | 
 | 				    goto next_node_table_entry; | 
 | 				} | 
 | 			    } | 
 | 			} | 
 | 			/* | 
 | 			* Add the duplicate to the list of duplicates. | 
 | 			*/ | 
 | 			if (bind->dupls == NULL) { | 
 | 			    bind->dupls = xmlSchemaItemListCreate(); | 
 | 			    if (bind->dupls == NULL) | 
 | 				goto internal_error; | 
 | 			} | 
 | 			if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1) | 
 | 			    goto internal_error; | 
 | 			/* | 
 | 			* Remove the duplicate entry from the IDC node-table. | 
 | 			*/ | 
 | 			bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1]; | 
 | 			bind->nbNodes--; | 
 |  | 
 | 			goto next_target; | 
 |  | 
 | next_node_table_entry: | 
 | 			j++; | 
 | 		    } while (j < nbNodeTable); | 
 | 		} | 
 | 		/* | 
 | 		* If everything is fine, then add the IDC target-node to | 
 | 		* the IDC node-table. | 
 | 		*/ | 
 | 		if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1) | 
 | 		    goto internal_error; | 
 |  | 
 | next_target: | 
 | 		i++; | 
 | 	    } while (i < nbTargets); | 
 | 	} | 
 | 	matcher = matcher->next; | 
 |     } | 
 |     return(0); | 
 |  | 
 | internal_error: | 
 |     return(-1); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaBubbleIDCNodeTables: | 
 |  * @depth: the current tree depth | 
 |  * | 
 |  * Merges IDC bindings of an element at @depth into the corresponding IDC | 
 |  * bindings of its parent element. If a duplicate note-table entry is found, | 
 |  * both, the parent node-table entry and child entry are discarded from the | 
 |  * node-table of the parent. | 
 |  * | 
 |  * Returns 0 if OK and -1 on internal errors. | 
 |  */ | 
 | static int | 
 | xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt) | 
 | { | 
 |     xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */ | 
 |     xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */ | 
 |     xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */ | 
 |     xmlSchemaIDCAugPtr aidc; | 
 |     int i, j, k, ret = 0, nbFields, oldNum, oldDupls; | 
 |  | 
 |     bind = vctxt->inode->idcTable; | 
 |     if (bind == NULL) { | 
 | 	/* Fine, no table, no bubbles. */ | 
 | 	return (0); | 
 |     } | 
 |  | 
 |     parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable); | 
 |     /* | 
 |     * Walk all bindings; create new or add to existing bindings. | 
 |     * Remove duplicate key-sequences. | 
 |     */ | 
 |     while (bind != NULL) { | 
 |  | 
 | 	if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls)) | 
 | 	    goto next_binding; | 
 | 	/* | 
 | 	* Check if the key/unique IDC table needs to be bubbled. | 
 | 	*/ | 
 | 	if (! vctxt->createIDCNodeTables) { | 
 | 	    aidc = vctxt->aidcs; | 
 | 	    do { | 
 | 		if (aidc->def == bind->definition) { | 
 | 		    if ((aidc->keyrefDepth == -1) || | 
 | 			(aidc->keyrefDepth >= vctxt->depth)) { | 
 | 			goto next_binding; | 
 | 		    } | 
 | 		    break; | 
 | 		} | 
 | 		aidc = aidc->next; | 
 | 	    } while (aidc != NULL); | 
 | 	} | 
 |  | 
 | 	if (parTable != NULL) | 
 | 	    parBind = *parTable; | 
 | 	/* | 
 | 	* Search a matching parent binding for the | 
 | 	* IDC definition. | 
 | 	*/ | 
 | 	while (parBind != NULL) { | 
 | 	    if (parBind->definition == bind->definition) | 
 | 		break; | 
 | 	    parBind = parBind->next; | 
 | 	} | 
 |  | 
 | 	if (parBind != NULL) { | 
 | 	    /* | 
 | 	    * Compare every node-table entry of the child node, | 
 | 	    * i.e. the key-sequence within, ... | 
 | 	    */ | 
 | 	    oldNum = parBind->nbNodes; /* Skip newly added items. */ | 
 |  | 
 | 	    if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) { | 
 | 		oldDupls = parBind->dupls->nbItems; | 
 | 		dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items; | 
 | 	    } else { | 
 | 		dupls = NULL; | 
 | 		oldDupls = 0; | 
 | 	    } | 
 |  | 
 | 	    parNodes = parBind->nodeTable; | 
 | 	    nbFields = bind->definition->nbFields; | 
 |  | 
 | 	    for (i = 0; i < bind->nbNodes; i++) { | 
 | 		node = bind->nodeTable[i]; | 
 | 		if (node == NULL) | 
 | 		    continue; | 
 | 		/* | 
 | 		* ...with every key-sequence of the parent node, already | 
 | 		* evaluated to be a duplicate key-sequence. | 
 | 		*/ | 
 | 		if (oldDupls) { | 
 | 		    j = 0; | 
 | 		    while (j < oldDupls) { | 
 | 			if (nbFields == 1) { | 
 | 			    ret = xmlSchemaAreValuesEqual( | 
 | 				node->keys[0]->val, | 
 | 				dupls[j]->keys[0]->val); | 
 | 			    if (ret == -1) | 
 | 				goto internal_error; | 
 | 			    if (ret == 0) { | 
 | 				j++; | 
 | 				continue; | 
 | 			    } | 
 | 			} else { | 
 | 			    parNode = dupls[j]; | 
 | 			    for (k = 0; k < nbFields; k++) { | 
 | 				ret = xmlSchemaAreValuesEqual( | 
 | 				    node->keys[k]->val, | 
 | 				    parNode->keys[k]->val); | 
 | 				if (ret == -1) | 
 | 				    goto internal_error; | 
 | 				if (ret == 0) | 
 | 				    break; | 
 | 			    } | 
 | 			} | 
 | 			if (ret == 1) | 
 | 			    /* Duplicate found. */ | 
 | 			    break; | 
 | 			j++; | 
 | 		    } | 
 | 		    if (j != oldDupls) { | 
 | 			/* Duplicate found. Skip this entry. */ | 
 | 			continue; | 
 | 		    } | 
 | 		} | 
 | 		/* | 
 | 		* ... and with every key-sequence of the parent node. | 
 | 		*/ | 
 | 		if (oldNum) { | 
 | 		    j = 0; | 
 | 		    while (j < oldNum) { | 
 | 			parNode = parNodes[j]; | 
 | 			if (nbFields == 1) { | 
 | 			    ret = xmlSchemaAreValuesEqual( | 
 | 				node->keys[0]->val, | 
 | 				parNode->keys[0]->val); | 
 | 			    if (ret == -1) | 
 | 				goto internal_error; | 
 | 			    if (ret == 0) { | 
 | 				j++; | 
 | 				continue; | 
 | 			    } | 
 | 			} else { | 
 | 			    for (k = 0; k < nbFields; k++) { | 
 | 				ret = xmlSchemaAreValuesEqual( | 
 | 				    node->keys[k]->val, | 
 | 				    parNode->keys[k]->val); | 
 | 				if (ret == -1) | 
 | 				    goto internal_error; | 
 | 				if (ret == 0) | 
 | 				    break; | 
 | 			    } | 
 | 			} | 
 | 			if (ret == 1) | 
 | 			    /* Duplicate found. */ | 
 | 			    break; | 
 | 			j++; | 
 | 		    } | 
 | 		    if (j != oldNum) { | 
 | 			/* | 
 | 			* Handle duplicates. Move the duplicate in | 
 | 			* the parent's node-table to the list of | 
 | 			* duplicates. | 
 | 			*/ | 
 | 			oldNum--; | 
 | 			parBind->nbNodes--; | 
 | 			/* | 
 | 			* Move last old item to pos of duplicate. | 
 | 			*/ | 
 | 			parNodes[j] = parNodes[oldNum]; | 
 |  | 
 | 			if (parBind->nbNodes != oldNum) { | 
 | 			    /* | 
 | 			    * If new items exist, move last new item to | 
 | 			    * last of old items. | 
 | 			    */ | 
 | 			    parNodes[oldNum] = | 
 | 				parNodes[parBind->nbNodes]; | 
 | 			} | 
 | 			if (parBind->dupls == NULL) { | 
 | 			    parBind->dupls = xmlSchemaItemListCreate(); | 
 | 			    if (parBind->dupls == NULL) | 
 | 				goto internal_error; | 
 | 			} | 
 | 			xmlSchemaItemListAdd(parBind->dupls, parNode); | 
 | 		    } else { | 
 | 			/* | 
 | 			* Add the node-table entry (node and key-sequence) of | 
 | 			* the child node to the node table of the parent node. | 
 | 			*/ | 
 | 			if (parBind->nodeTable == NULL) { | 
 | 			    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *) | 
 | 				xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr)); | 
 | 			    if (parBind->nodeTable == NULL) { | 
 | 				xmlSchemaVErrMemory(NULL, | 
 | 				    "allocating IDC list of node-table items", NULL); | 
 | 				goto internal_error; | 
 | 			    } | 
 | 			    parBind->sizeNodes = 1; | 
 | 			} else if (parBind->nbNodes >= parBind->sizeNodes) { | 
 | 			    parBind->sizeNodes *= 2; | 
 | 			    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *) | 
 | 				xmlRealloc(parBind->nodeTable, parBind->sizeNodes * | 
 | 				sizeof(xmlSchemaPSVIIDCNodePtr)); | 
 | 			    if (parBind->nodeTable == NULL) { | 
 | 				xmlSchemaVErrMemory(NULL, | 
 | 				    "re-allocating IDC list of node-table items", NULL); | 
 | 				goto internal_error; | 
 | 			    } | 
 | 			} | 
 | 			parNodes = parBind->nodeTable; | 
 | 			/* | 
 | 			* Append the new node-table entry to the 'new node-table | 
 | 			* entries' section. | 
 | 			*/ | 
 | 			parNodes[parBind->nbNodes++] = node; | 
 | 		    } | 
 |  | 
 | 		} | 
 |  | 
 | 	    } | 
 | 	} else { | 
 | 	    /* | 
 | 	    * No binding for the IDC was found: create a new one and | 
 | 	    * copy all node-tables. | 
 | 	    */ | 
 | 	    parBind = xmlSchemaIDCNewBinding(bind->definition); | 
 | 	    if (parBind == NULL) | 
 | 		goto internal_error; | 
 |  | 
 | 	    /* | 
 | 	    * TODO: Hmm, how to optimize the initial number of | 
 | 	    * allocated entries? | 
 | 	    */ | 
 | 	    if (bind->nbNodes != 0) { | 
 | 		/* | 
 | 		* Add all IDC node-table entries. | 
 | 		*/ | 
 | 		if (! vctxt->psviExposeIDCNodeTables) { | 
 | 		    /* | 
 | 		    * Just move the entries. | 
 | 		    * NOTE: this is quite save here, since | 
 | 		    * all the keyref lookups have already been | 
 | 		    * performed. | 
 | 		    */ | 
 | 		    parBind->nodeTable = bind->nodeTable; | 
 | 		    bind->nodeTable = NULL; | 
 | 		    parBind->sizeNodes = bind->sizeNodes; | 
 | 		    bind->sizeNodes = 0; | 
 | 		    parBind->nbNodes = bind->nbNodes; | 
 | 		    bind->nbNodes = 0; | 
 | 		} else { | 
 | 		    /* | 
 | 		    * Copy the entries. | 
 | 		    */ | 
 | 		    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *) | 
 | 			xmlMalloc(bind->nbNodes * | 
 | 			sizeof(xmlSchemaPSVIIDCNodePtr)); | 
 | 		    if (parBind->nodeTable == NULL) { | 
 | 			xmlSchemaVErrMemory(NULL, | 
 | 			    "allocating an array of IDC node-table " | 
 | 			    "items", NULL); | 
 | 			xmlSchemaIDCFreeBinding(parBind); | 
 | 			goto internal_error; | 
 | 		    } | 
 | 		    parBind->sizeNodes = bind->nbNodes; | 
 | 		    parBind->nbNodes = bind->nbNodes; | 
 | 		    memcpy(parBind->nodeTable, bind->nodeTable, | 
 | 			bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr)); | 
 | 		} | 
 | 	    } | 
 | 	    if (bind->dupls) { | 
 | 		/* | 
 | 		* Move the duplicates. | 
 | 		*/ | 
 | 		if (parBind->dupls != NULL) | 
 | 		    xmlSchemaItemListFree(parBind->dupls); | 
 | 		parBind->dupls = bind->dupls; | 
 | 		bind->dupls = NULL; | 
 | 	    } | 
 |             if (parTable != NULL) { | 
 |                 if (*parTable == NULL) | 
 |                     *parTable = parBind; | 
 |                 else { | 
 |                     parBind->next = *parTable; | 
 |                     *parTable = parBind; | 
 |                 } | 
 |             } | 
 | 	} | 
 |  | 
 | next_binding: | 
 | 	bind = bind->next; | 
 |     } | 
 |     return (0); | 
 |  | 
 | internal_error: | 
 |     return(-1); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaCheckCVCIDCKeyRef: | 
 |  * @vctxt: the WXS validation context | 
 |  * @elemDecl: the element declaration | 
 |  * | 
 |  * Check the cvc-idc-keyref constraints. | 
 |  */ | 
 | static int | 
 | xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt) | 
 | { | 
 |     xmlSchemaIDCMatcherPtr matcher; | 
 |     xmlSchemaPSVIIDCBindingPtr bind; | 
 |  | 
 |     matcher = vctxt->inode->idcMatchers; | 
 |     /* | 
 |     * Find a keyref. | 
 |     */ | 
 |     while (matcher != NULL) { | 
 | 	if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) && | 
 | 	    matcher->targets && | 
 | 	    matcher->targets->nbItems) | 
 | 	{ | 
 | 	    int i, j, k, res, nbFields, hasDupls; | 
 | 	    xmlSchemaPSVIIDCKeyPtr *refKeys, *keys; | 
 | 	    xmlSchemaPSVIIDCNodePtr refNode = NULL; | 
 |  | 
 | 	    nbFields = matcher->aidc->def->nbFields; | 
 |  | 
 | 	    /* | 
 | 	    * Find the IDC node-table for the referenced IDC key/unique. | 
 | 	    */ | 
 | 	    bind = vctxt->inode->idcTable; | 
 | 	    while (bind != NULL) { | 
 | 		if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item == | 
 | 		    bind->definition) | 
 | 		    break; | 
 | 		bind = bind->next; | 
 | 	    } | 
 | 	    hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0; | 
 | 	    /* | 
 | 	    * Search for a matching key-sequences. | 
 | 	    */ | 
 | 	    for (i = 0; i < matcher->targets->nbItems; i++) { | 
 | 		res = 0; | 
 | 		refNode = matcher->targets->items[i]; | 
 | 		if (bind != NULL) { | 
 | 		    refKeys = refNode->keys; | 
 | 		    for (j = 0; j < bind->nbNodes; j++) { | 
 | 			keys = bind->nodeTable[j]->keys; | 
 | 			for (k = 0; k < nbFields; k++) { | 
 | 			    res = xmlSchemaAreValuesEqual(keys[k]->val, | 
 | 				refKeys[k]->val); | 
 | 			    if (res == 0) | 
 | 				break; | 
 | 			    else if (res == -1) { | 
 | 				return (-1); | 
 | 			    } | 
 | 			} | 
 | 			if (res == 1) { | 
 | 			    /* | 
 | 			    * Match found. | 
 | 			    */ | 
 | 			    break; | 
 | 			} | 
 | 		    } | 
 | 		    if ((res == 0) && hasDupls) { | 
 | 			/* | 
 | 			* Search in duplicates | 
 | 			*/ | 
 | 			for (j = 0; j < bind->dupls->nbItems; j++) { | 
 | 			    keys = ((xmlSchemaPSVIIDCNodePtr) | 
 | 				bind->dupls->items[j])->keys; | 
 | 			    for (k = 0; k < nbFields; k++) { | 
 | 				res = xmlSchemaAreValuesEqual(keys[k]->val, | 
 | 				    refKeys[k]->val); | 
 | 				if (res == 0) | 
 | 				    break; | 
 | 				else if (res == -1) { | 
 | 				    return (-1); | 
 | 				} | 
 | 			    } | 
 | 			    if (res == 1) { | 
 | 				/* | 
 | 				* Match in duplicates found. | 
 | 				*/ | 
 | 				xmlChar *str = NULL, *strB = NULL; | 
 | 				xmlSchemaKeyrefErr(vctxt, | 
 | 				    XML_SCHEMAV_CVC_IDC, refNode, | 
 | 				    (xmlSchemaTypePtr) matcher->aidc->def, | 
 | 				    "More than one match found for " | 
 | 				    "key-sequence %s of keyref '%s'", | 
 | 				    xmlSchemaFormatIDCKeySequence(vctxt, &str, | 
 | 					refNode->keys, nbFields), | 
 | 				    xmlSchemaGetComponentQName(&strB, | 
 | 					matcher->aidc->def)); | 
 | 				FREE_AND_NULL(str); | 
 | 				FREE_AND_NULL(strB); | 
 | 				break; | 
 | 			    } | 
 | 			} | 
 | 		    } | 
 | 		} | 
 |  | 
 | 		if (res == 0) { | 
 | 		    xmlChar *str = NULL, *strB = NULL; | 
 | 		    xmlSchemaKeyrefErr(vctxt, | 
 | 			XML_SCHEMAV_CVC_IDC, refNode, | 
 | 			(xmlSchemaTypePtr) matcher->aidc->def, | 
 | 			"No match found for key-sequence %s of keyref '%s'", | 
 | 			xmlSchemaFormatIDCKeySequence(vctxt, &str, | 
 | 			    refNode->keys, nbFields), | 
 | 			xmlSchemaGetComponentQName(&strB, matcher->aidc->def)); | 
 | 		    FREE_AND_NULL(str); | 
 | 		    FREE_AND_NULL(strB); | 
 | 		} | 
 | 	    } | 
 | 	} | 
 | 	matcher = matcher->next; | 
 |     } | 
 |     /* TODO: Return an error if any error encountered. */ | 
 |     return (0); | 
 | } | 
 |  | 
 | /************************************************************************ | 
 |  * 									* | 
 |  * 			XML Reader validation code                      * | 
 |  * 									* | 
 |  ************************************************************************/ | 
 |  | 
 | static xmlSchemaAttrInfoPtr | 
 | xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt) | 
 | { | 
 |     xmlSchemaAttrInfoPtr iattr; | 
 |     /* | 
 |     * Grow/create list of attribute infos. | 
 |     */ | 
 |     if (vctxt->attrInfos == NULL) { | 
 | 	vctxt->attrInfos = (xmlSchemaAttrInfoPtr *) | 
 | 	    xmlMalloc(sizeof(xmlSchemaAttrInfoPtr)); | 
 | 	vctxt->sizeAttrInfos = 1; | 
 | 	if (vctxt->attrInfos == NULL) { | 
 | 	    xmlSchemaVErrMemory(vctxt, | 
 | 		"allocating attribute info list", NULL); | 
 | 	    return (NULL); | 
 | 	} | 
 |     } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) { | 
 | 	vctxt->sizeAttrInfos++; | 
 | 	vctxt->attrInfos = (xmlSchemaAttrInfoPtr *) | 
 | 	    xmlRealloc(vctxt->attrInfos, | 
 | 		vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr)); | 
 | 	if (vctxt->attrInfos == NULL) { | 
 | 	    xmlSchemaVErrMemory(vctxt, | 
 | 		"re-allocating attribute info list", NULL); | 
 | 	    return (NULL); | 
 | 	} | 
 |     } else { | 
 | 	iattr = vctxt->attrInfos[vctxt->nbAttrInfos++]; | 
 | 	if (iattr->localName != NULL) { | 
 | 	    VERROR_INT("xmlSchemaGetFreshAttrInfo", | 
 | 		"attr info not cleared"); | 
 | 	    return (NULL); | 
 | 	} | 
 | 	iattr->nodeType = XML_ATTRIBUTE_NODE; | 
 | 	return (iattr); | 
 |     } | 
 |     /* | 
 |     * Create an attribute info. | 
 |     */ | 
 |     iattr = (xmlSchemaAttrInfoPtr) | 
 | 	xmlMalloc(sizeof(xmlSchemaAttrInfo)); | 
 |     if (iattr == NULL) { | 
 | 	xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL); | 
 | 	return (NULL); | 
 |     } | 
 |     memset(iattr, 0, sizeof(xmlSchemaAttrInfo)); | 
 |     iattr->nodeType = XML_ATTRIBUTE_NODE; | 
 |     vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr; | 
 |  | 
 |     return (iattr); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt, | 
 | 			xmlNodePtr attrNode, | 
 | 			int nodeLine, | 
 | 			const xmlChar *localName, | 
 | 			const xmlChar *nsName, | 
 | 			int ownedNames, | 
 | 			xmlChar *value, | 
 | 			int ownedValue) | 
 | { | 
 |     xmlSchemaAttrInfoPtr attr; | 
 |  | 
 |     attr = xmlSchemaGetFreshAttrInfo(vctxt); | 
 |     if (attr == NULL) { | 
 | 	VERROR_INT("xmlSchemaPushAttribute", | 
 | 	    "calling xmlSchemaGetFreshAttrInfo()"); | 
 | 	return (-1); | 
 |     } | 
 |     attr->node = attrNode; | 
 |     attr->nodeLine = nodeLine; | 
 |     attr->state = XML_SCHEMAS_ATTR_UNKNOWN; | 
 |     attr->localName = localName; | 
 |     attr->nsName = nsName; | 
 |     if (ownedNames) | 
 | 	attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES; | 
 |     /* | 
 |     * Evaluate if it's an XSI attribute. | 
 |     */ | 
 |     if (nsName != NULL) { | 
 | 	if (xmlStrEqual(localName, BAD_CAST "nil")) { | 
 | 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) { | 
 | 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL; | 
 | 	    } | 
 | 	} else if (xmlStrEqual(localName, BAD_CAST "type")) { | 
 | 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) { | 
 | 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE; | 
 | 	    } | 
 | 	} else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) { | 
 | 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) { | 
 | 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC; | 
 | 	    } | 
 | 	} else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) { | 
 | 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) { | 
 | 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC; | 
 | 	    } | 
 | 	} else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) { | 
 | 	    attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS; | 
 | 	} | 
 |     } | 
 |     attr->value = value; | 
 |     if (ownedValue) | 
 | 	attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES; | 
 |     if (attr->metaType != 0) | 
 | 	attr->state = XML_SCHEMAS_ATTR_META; | 
 |     return (0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaClearElemInfo: | 
 |  * @vctxt: the WXS validation context | 
 |  * @ielem: the element information item | 
 |  */ | 
 | static void | 
 | xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt, | 
 | 		       xmlSchemaNodeInfoPtr ielem) | 
 | { | 
 |     ielem->hasKeyrefs = 0; | 
 |     ielem->appliedXPath = 0; | 
 |     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) { | 
 | 	FREE_AND_NULL(ielem->localName); | 
 | 	FREE_AND_NULL(ielem->nsName); | 
 |     } else { | 
 | 	ielem->localName = NULL; | 
 | 	ielem->nsName = NULL; | 
 |     } | 
 |     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) { | 
 | 	FREE_AND_NULL(ielem->value); | 
 |     } else { | 
 | 	ielem->value = NULL; | 
 |     } | 
 |     if (ielem->val != NULL) { | 
 | 	/* | 
 | 	* PSVI TODO: Be careful not to free it when the value is | 
 | 	* exposed via PSVI. | 
 | 	*/ | 
 | 	xmlSchemaFreeValue(ielem->val); | 
 | 	ielem->val = NULL; | 
 |     } | 
 |     if (ielem->idcMatchers != NULL) { | 
 | 	/* | 
 | 	* REVISIT OPTIMIZE TODO: Use a pool of IDC matchers. | 
 | 	*   Does it work? | 
 | 	*/ | 
 | 	xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers); | 
 | #if 0 | 
 | 	xmlSchemaIDCFreeMatcherList(ielem->idcMatchers); | 
 | #endif | 
 | 	ielem->idcMatchers = NULL; | 
 |     } | 
 |     if (ielem->idcTable != NULL) { | 
 | 	/* | 
 | 	* OPTIMIZE TODO: Use a pool of IDC tables??. | 
 | 	*/ | 
 | 	xmlSchemaIDCFreeIDCTable(ielem->idcTable); | 
 | 	ielem->idcTable = NULL; | 
 |     } | 
 |     if (ielem->regexCtxt != NULL) { | 
 | 	xmlRegFreeExecCtxt(ielem->regexCtxt); | 
 | 	ielem->regexCtxt = NULL; | 
 |     } | 
 |     if (ielem->nsBindings != NULL) { | 
 | 	xmlFree((xmlChar **)ielem->nsBindings); | 
 | 	ielem->nsBindings = NULL; | 
 | 	ielem->nbNsBindings = 0; | 
 | 	ielem->sizeNsBindings = 0; | 
 |     } | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaGetFreshElemInfo: | 
 |  * @vctxt: the schema validation context | 
 |  * | 
 |  * Creates/reuses and initializes the element info item for | 
 |  * the currect tree depth. | 
 |  * | 
 |  * Returns the element info item or NULL on API or internal errors. | 
 |  */ | 
 | static xmlSchemaNodeInfoPtr | 
 | xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt) | 
 | { | 
 |     xmlSchemaNodeInfoPtr info = NULL; | 
 |  | 
 |     if (vctxt->depth > vctxt->sizeElemInfos) { | 
 | 	VERROR_INT("xmlSchemaGetFreshElemInfo", | 
 | 	    "inconsistent depth encountered"); | 
 | 	return (NULL); | 
 |     } | 
 |     if (vctxt->elemInfos == NULL) { | 
 | 	vctxt->elemInfos = (xmlSchemaNodeInfoPtr *) | 
 | 	    xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr)); | 
 | 	if (vctxt->elemInfos == NULL) { | 
 | 	    xmlSchemaVErrMemory(vctxt, | 
 | 		"allocating the element info array", NULL); | 
 | 	    return (NULL); | 
 | 	} | 
 | 	memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr)); | 
 | 	vctxt->sizeElemInfos = 10; | 
 |     } else if (vctxt->sizeElemInfos <= vctxt->depth) { | 
 | 	int i = vctxt->sizeElemInfos; | 
 |  | 
 | 	vctxt->sizeElemInfos *= 2; | 
 | 	vctxt->elemInfos = (xmlSchemaNodeInfoPtr *) | 
 | 	    xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos * | 
 | 	    sizeof(xmlSchemaNodeInfoPtr)); | 
 | 	if (vctxt->elemInfos == NULL) { | 
 | 	    xmlSchemaVErrMemory(vctxt, | 
 | 		"re-allocating the element info array", NULL); | 
 | 	    return (NULL); | 
 | 	} | 
 | 	/* | 
 | 	* We need the new memory to be NULLed. | 
 | 	* TODO: Use memset instead? | 
 | 	*/ | 
 | 	for (; i < vctxt->sizeElemInfos; i++) | 
 | 	    vctxt->elemInfos[i] = NULL; | 
 |     } else | 
 | 	info = vctxt->elemInfos[vctxt->depth]; | 
 |  | 
 |     if (info == NULL) { | 
 | 	info = (xmlSchemaNodeInfoPtr) | 
 | 	    xmlMalloc(sizeof(xmlSchemaNodeInfo)); | 
 | 	if (info == NULL) { | 
 | 	    xmlSchemaVErrMemory(vctxt, | 
 | 		"allocating an element info", NULL); | 
 | 	    return (NULL); | 
 | 	} | 
 | 	vctxt->elemInfos[vctxt->depth] = info; | 
 |     } else { | 
 | 	if (info->localName != NULL) { | 
 | 	    VERROR_INT("xmlSchemaGetFreshElemInfo", | 
 | 		"elem info has not been cleared"); | 
 | 	    return (NULL); | 
 | 	} | 
 |     } | 
 |     memset(info, 0, sizeof(xmlSchemaNodeInfo)); | 
 |     info->nodeType = XML_ELEMENT_NODE; | 
 |     info->depth = vctxt->depth; | 
 |  | 
 |     return (info); | 
 | } | 
 |  | 
 | #define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item; | 
 | #define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth]; | 
 | #define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1]; | 
 |  | 
 | static int | 
 | xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt, | 
 | 			xmlNodePtr node, | 
 | 			xmlSchemaTypePtr type, | 
 | 			xmlSchemaValType valType, | 
 | 			const xmlChar * value, | 
 | 			xmlSchemaValPtr val, | 
 | 			unsigned long length, | 
 | 			int fireErrors) | 
 | { | 
 |     int ret, error = 0; | 
 |  | 
 |     xmlSchemaTypePtr tmpType; | 
 |     xmlSchemaFacetLinkPtr facetLink; | 
 |     xmlSchemaFacetPtr facet; | 
 |     unsigned long len = 0; | 
 |     xmlSchemaWhitespaceValueType ws; | 
 |  | 
 |     /* | 
 |     * In Libxml2, derived built-in types have currently no explicit facets. | 
 |     */ | 
 |     if (type->type == XML_SCHEMA_TYPE_BASIC) | 
 | 	return (0); | 
 |  | 
 |     /* | 
 |     * NOTE: Do not jump away, if the facetSet of the given type is | 
 |     * empty: until now, "pattern" and "enumeration" facets of the | 
 |     * *base types* need to be checked as well. | 
 |     */ | 
 |     if (type->facetSet == NULL) | 
 | 	goto pattern_and_enum; | 
 |  | 
 |     if (! WXS_IS_ATOMIC(type)) { | 
 | 	if (WXS_IS_LIST(type)) | 
 | 	    goto WXS_IS_LIST; | 
 | 	else | 
 | 	    goto pattern_and_enum; | 
 |     } | 
 |     /* | 
 |     * Whitespace handling is only of importance for string-based | 
 |     * types. | 
 |     */ | 
 |     tmpType = xmlSchemaGetPrimitiveType(type); | 
 |     if ((tmpType->builtInType == XML_SCHEMAS_STRING) || | 
 | 	WXS_IS_ANY_SIMPLE_TYPE(tmpType)) { | 
 | 	ws = xmlSchemaGetWhiteSpaceFacetValue(type); | 
 |     } else | 
 | 	ws = XML_SCHEMA_WHITESPACE_COLLAPSE; | 
 |     /* | 
 |     * If the value was not computed (for string or | 
 |     * anySimpleType based types), then use the provided | 
 |     * type. | 
 |     */ | 
 |     if (val == NULL) | 
 | 	valType = valType; | 
 |     else | 
 | 	valType = xmlSchemaGetValType(val); | 
 |  | 
 |     ret = 0; | 
 |     for (facetLink = type->facetSet; facetLink != NULL; | 
 | 	facetLink = facetLink->next) { | 
 | 	/* | 
 | 	* Skip the pattern "whiteSpace": it is used to | 
 | 	* format the character content beforehand. | 
 | 	*/ | 
 | 	switch (facetLink->facet->type) { | 
 | 	    case XML_SCHEMA_FACET_WHITESPACE: | 
 | 	    case XML_SCHEMA_FACET_PATTERN: | 
 | 	    case XML_SCHEMA_FACET_ENUMERATION: | 
 | 		continue; | 
 | 	    case XML_SCHEMA_FACET_LENGTH: | 
 | 	    case XML_SCHEMA_FACET_MINLENGTH: | 
 | 	    case XML_SCHEMA_FACET_MAXLENGTH: | 
 | 		ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet, | 
 | 		    valType, value, val, &len, ws); | 
 | 		break; | 
 | 	    default: | 
 | 		ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws, | 
 | 		    valType, value, val, ws); | 
 | 		break; | 
 | 	} | 
 | 	if (ret < 0) { | 
 | 	    AERROR_INT("xmlSchemaValidateFacets", | 
 | 		"validating against a atomic type facet"); | 
 | 	    return (-1); | 
 | 	} else if (ret > 0) { | 
 | 	    if (fireErrors) | 
 | 		xmlSchemaFacetErr(actxt, ret, node, | 
 | 		value, len, type, facetLink->facet, NULL, NULL, NULL); | 
 | 	    else | 
 | 		return (ret); | 
 | 	    if (error == 0) | 
 | 		error = ret; | 
 | 	} | 
 | 	ret = 0; | 
 |     } | 
 |  | 
 | WXS_IS_LIST: | 
 |     if (! WXS_IS_LIST(type)) | 
 | 	goto pattern_and_enum; | 
 |     /* | 
 |     * "length", "minLength" and "maxLength" of list types. | 
 |     */ | 
 |     ret = 0; | 
 |     for (facetLink = type->facetSet; facetLink != NULL; | 
 | 	facetLink = facetLink->next) { | 
 |  | 
 | 	switch (facetLink->facet->type) { | 
 | 	    case XML_SCHEMA_FACET_LENGTH: | 
 | 	    case XML_SCHEMA_FACET_MINLENGTH: | 
 | 	    case XML_SCHEMA_FACET_MAXLENGTH: | 
 | 		ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet, | 
 | 		    value, length, NULL); | 
 | 		break; | 
 | 	    default: | 
 | 		continue; | 
 | 	} | 
 | 	if (ret < 0) { | 
 | 	    AERROR_INT("xmlSchemaValidateFacets", | 
 | 		"validating against a list type facet"); | 
 | 	    return (-1); | 
 | 	} else if (ret > 0) { | 
 | 	    if (fireErrors) | 
 | 		xmlSchemaFacetErr(actxt, ret, node, | 
 | 		value, length, type, facetLink->facet, NULL, NULL, NULL); | 
 | 	    else | 
 | 		return (ret); | 
 | 	    if (error == 0) | 
 | 		error = ret; | 
 | 	} | 
 | 	ret = 0; | 
 |     } | 
 |  | 
 | pattern_and_enum: | 
 |     if (error >= 0) { | 
 | 	int found = 0; | 
 | 	/* | 
 | 	* Process enumerations. Facet values are in the value space | 
 | 	* of the defining type's base type. This seems to be a bug in the | 
 | 	* XML Schema 1.0 spec. Use the whitespace type of the base type. | 
 | 	* Only the first set of enumerations in the ancestor-or-self axis | 
 | 	* is used for validation. | 
 | 	*/ | 
 | 	ret = 0; | 
 | 	tmpType = type; | 
 | 	do { | 
 | 	    for (facet = tmpType->facets; facet != NULL; facet = facet->next) { | 
 | 		if (facet->type != XML_SCHEMA_FACET_ENUMERATION) | 
 | 		    continue; | 
 | 		found = 1; | 
 | 		ret = xmlSchemaAreValuesEqual(facet->val, val); | 
 | 		if (ret == 1) | 
 | 		    break; | 
 | 		else if (ret < 0) { | 
 | 		    AERROR_INT("xmlSchemaValidateFacets", | 
 | 			"validating against an enumeration facet"); | 
 | 		    return (-1); | 
 | 		} | 
 | 	    } | 
 | 	    if (ret != 0) | 
 | 		break; | 
 | 	    /* | 
 | 	    * Break on the first set of enumerations. Any additional | 
 | 	    *  enumerations which might be existent on the ancestors | 
 | 	    *  of the current type are restricted by this set; thus | 
 | 	    *  *must* *not* be taken into account. | 
 | 	    */ | 
 | 	    if (found) | 
 | 		break; | 
 | 	    tmpType = tmpType->baseType; | 
 | 	} while ((tmpType != NULL) && | 
 | 	    (tmpType->type != XML_SCHEMA_TYPE_BASIC)); | 
 | 	if (found && (ret == 0)) { | 
 | 	    ret = XML_SCHEMAV_CVC_ENUMERATION_VALID; | 
 | 	    if (fireErrors) { | 
 | 		xmlSchemaFacetErr(actxt, ret, node, | 
 | 		    value, 0, type, NULL, NULL, NULL, NULL); | 
 | 	    } else | 
 | 		return (ret); | 
 | 	    if (error == 0) | 
 | 		error = ret; | 
 | 	} | 
 |     } | 
 |  | 
 |     if (error >= 0) { | 
 | 	int found; | 
 | 	/* | 
 | 	* Process patters. Pattern facets are ORed at type level | 
 | 	* and ANDed if derived. Walk the base type axis. | 
 | 	*/ | 
 | 	tmpType = type; | 
 | 	facet = NULL; | 
 | 	do { | 
 | 	    found = 0; | 
 | 	    for (facetLink = tmpType->facetSet; facetLink != NULL; | 
 | 		facetLink = facetLink->next) { | 
 | 		if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN) | 
 | 		    continue; | 
 | 		found = 1; | 
 | 		/* | 
 | 		* NOTE that for patterns, @value needs to be the | 
 | 		* normalized vaule. | 
 | 		*/ | 
 | 		ret = xmlRegexpExec(facetLink->facet->regexp, value); | 
 | 		if (ret == 1) | 
 | 		    break; | 
 | 		else if (ret < 0) { | 
 | 		    AERROR_INT("xmlSchemaValidateFacets", | 
 | 			"validating against a pattern facet"); | 
 | 		    return (-1); | 
 | 		} else { | 
 | 		    /* | 
 | 		    * Save the last non-validating facet. | 
 | 		    */ | 
 | 		    facet = facetLink->facet; | 
 | 		} | 
 | 	    } | 
 | 	    if (found && (ret != 1)) { | 
 | 		ret = XML_SCHEMAV_CVC_PATTERN_VALID; | 
 | 		if (fireErrors) { | 
 | 		    xmlSchemaFacetErr(actxt, ret, node, | 
 | 			value, 0, type, facet, NULL, NULL, NULL); | 
 | 		} else | 
 | 		    return (ret); | 
 | 		if (error == 0) | 
 | 		    error = ret; | 
 | 		break; | 
 | 	    } | 
 | 	    tmpType = tmpType->baseType; | 
 | 	} while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC)); | 
 |     } | 
 |  | 
 |     return (error); | 
 | } | 
 |  | 
 | static xmlChar * | 
 | xmlSchemaNormalizeValue(xmlSchemaTypePtr type, | 
 | 			const xmlChar *value) | 
 | { | 
 |     switch (xmlSchemaGetWhiteSpaceFacetValue(type)) { | 
 | 	case XML_SCHEMA_WHITESPACE_COLLAPSE: | 
 | 	    return (xmlSchemaCollapseString(value)); | 
 | 	case XML_SCHEMA_WHITESPACE_REPLACE: | 
 | 	    return (xmlSchemaWhiteSpaceReplace(value)); | 
 | 	default: | 
 | 	    return (NULL); | 
 |     } | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt, | 
 | 		       const xmlChar *value, | 
 | 		       xmlSchemaValPtr *val, | 
 | 		       int valNeeded) | 
 | { | 
 |     int ret; | 
 |     const xmlChar *nsName; | 
 |     xmlChar *local, *prefix = NULL; | 
 |  | 
 |     ret = xmlValidateQName(value, 1); | 
 |     if (ret != 0) { | 
 | 	if (ret == -1) { | 
 | 	    VERROR_INT("xmlSchemaValidateQName", | 
 | 		"calling xmlValidateQName()"); | 
 | 	    return (-1); | 
 | 	} | 
 | 	return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1); | 
 |     } | 
 |     /* | 
 |     * NOTE: xmlSplitQName2 will always return a duplicated | 
 |     * strings. | 
 |     */ | 
 |     local = xmlSplitQName2(value, &prefix); | 
 |     if (local == NULL) | 
 | 	local = xmlStrdup(value); | 
 |     /* | 
 |     * OPTIMIZE TODO: Use flags for: | 
 |     *  - is there any namespace binding? | 
 |     *  - is there a default namespace? | 
 |     */ | 
 |     nsName = xmlSchemaLookupNamespace(vctxt, prefix); | 
 |  | 
 |     if (prefix != NULL) { | 
 | 	xmlFree(prefix); | 
 | 	/* | 
 | 	* A namespace must be found if the prefix is | 
 | 	* NOT NULL. | 
 | 	*/ | 
 | 	if (nsName == NULL) { | 
 | 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1; | 
 | 	    xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL, | 
 | 		WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), | 
 | 		"The QName value '%s' has no " | 
 | 		"corresponding namespace declaration in " | 
 | 		"scope", value, NULL); | 
 | 	    if (local != NULL) | 
 | 		xmlFree(local); | 
 | 	    return (ret); | 
 | 	} | 
 |     } | 
 |     if (valNeeded && val) { | 
 | 	if (nsName != NULL) | 
 | 	    *val = xmlSchemaNewQNameValue( | 
 | 		BAD_CAST xmlStrdup(nsName), BAD_CAST local); | 
 | 	else | 
 | 	    *val = xmlSchemaNewQNameValue(NULL, | 
 | 		BAD_CAST local); | 
 |     } else | 
 | 	xmlFree(local); | 
 |     return (0); | 
 | } | 
 |  | 
 | /* | 
 | * cvc-simple-type | 
 | */ | 
 | static int | 
 | xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt, | 
 | 			     xmlNodePtr node, | 
 | 			     xmlSchemaTypePtr type, | 
 | 			     const xmlChar *value, | 
 | 			     xmlSchemaValPtr *retVal, | 
 | 			     int fireErrors, | 
 | 			     int normalize, | 
 | 			     int isNormalized) | 
 | { | 
 |     int ret = 0, valNeeded = (retVal) ? 1 : 0; | 
 |     xmlSchemaValPtr val = NULL; | 
 |     /* xmlSchemaWhitespaceValueType ws; */ | 
 |     xmlChar *normValue = NULL; | 
 |  | 
 | #define NORMALIZE(atype) \ | 
 |     if ((! isNormalized) && \ | 
 |     (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \ | 
 | 	normValue = xmlSchemaNormalizeValue(atype, value); \ | 
 | 	if (normValue != NULL) \ | 
 | 	    value = normValue; \ | 
 | 	isNormalized = 1; \ | 
 |     } | 
 |  | 
 |     if ((retVal != NULL) && (*retVal != NULL)) { | 
 | 	xmlSchemaFreeValue(*retVal); | 
 | 	*retVal = NULL; | 
 |     } | 
 |     /* | 
 |     * 3.14.4 Simple Type Definition Validation Rules | 
 |     * Validation Rule: String Valid | 
 |     */ | 
 |     /* | 
 |     * 1 It is schema-valid with respect to that definition as defined | 
 |     * by Datatype Valid in [XML Schemas: Datatypes]. | 
 |     */ | 
 |     /* | 
 |     * 2.1 If The definition is ENTITY or is validly derived from ENTITY given | 
 |     * the empty set, as defined in Type Derivation OK (Simple) (�3.14.6), then | 
 |     * the string must be a �declared entity name�. | 
 |     */ | 
 |     /* | 
 |     * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES | 
 |     * given the empty set, as defined in Type Derivation OK (Simple) (�3.14.6), | 
 |     * then every whitespace-delimited substring of the string must be a �declared | 
 |     * entity name�. | 
 |     */ | 
 |     /* | 
 |     * 2.3 otherwise no further condition applies. | 
 |     */ | 
 |     if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE)) | 
 | 	valNeeded = 1; | 
 |     if (value == NULL) | 
 | 	value = BAD_CAST ""; | 
 |     if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) { | 
 | 	xmlSchemaTypePtr biType; /* The built-in type. */ | 
 | 	/* | 
 | 	* SPEC (1.2.1) "if {variety} is �atomic� then the string must �match� | 
 | 	* a literal in the �lexical space� of {base type definition}" | 
 | 	*/ | 
 | 	/* | 
 | 	* Whitespace-normalize. | 
 | 	*/ | 
 | 	NORMALIZE(type); | 
 | 	if (type->type != XML_SCHEMA_TYPE_BASIC) { | 
 | 	    /* | 
 | 	    * Get the built-in type. | 
 | 	    */ | 
 | 	    biType = type->baseType; | 
 | 	    while ((biType != NULL) && | 
 | 		(biType->type != XML_SCHEMA_TYPE_BASIC)) | 
 | 		biType = biType->baseType; | 
 |  | 
 | 	    if (biType == NULL) { | 
 | 		AERROR_INT("xmlSchemaVCheckCVCSimpleType", | 
 | 		    "could not get the built-in type"); | 
 | 		goto internal_error; | 
 | 	    } | 
 | 	} else | 
 | 	    biType = type; | 
 | 	/* | 
 | 	* NOTATIONs need to be processed here, since they need | 
 | 	* to lookup in the hashtable of NOTATION declarations of the schema. | 
 | 	*/ | 
 | 	if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) { | 
 | 	    switch (biType->builtInType) { | 
 | 		case XML_SCHEMAS_NOTATION: | 
 | 		    ret = xmlSchemaValidateNotation( | 
 | 			(xmlSchemaValidCtxtPtr) actxt, | 
 | 			((xmlSchemaValidCtxtPtr) actxt)->schema, | 
 | 			NULL, value, &val, valNeeded); | 
 | 		    break; | 
 | 		case XML_SCHEMAS_QNAME: | 
 | 		    ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt, | 
 | 			value, &val, valNeeded); | 
 | 		    break; | 
 | 		default: | 
 | 		    /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */ | 
 | 		    if (valNeeded) | 
 | 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType, | 
 | 			    value, &val, node); | 
 | 		    else | 
 | 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType, | 
 | 			    value, NULL, node); | 
 | 		    break; | 
 | 	    } | 
 | 	} else if (actxt->type == XML_SCHEMA_CTXT_PARSER) { | 
 | 	    switch (biType->builtInType) { | 
 | 		case XML_SCHEMAS_NOTATION: | 
 | 		    ret = xmlSchemaValidateNotation(NULL, | 
 | 			((xmlSchemaParserCtxtPtr) actxt)->schema, node, | 
 | 			value, &val, valNeeded); | 
 | 		    break; | 
 | 		default: | 
 | 		    /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */ | 
 | 		    if (valNeeded) | 
 | 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType, | 
 | 			    value, &val, node); | 
 | 		    else | 
 | 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType, | 
 | 			    value, NULL, node); | 
 | 		    break; | 
 | 	    } | 
 | 	} else { | 
 | 	    /* | 
 | 	    * Validation via a public API is not implemented yet. | 
 | 	    */ | 
 | 	    TODO | 
 | 	    goto internal_error; | 
 | 	} | 
 | 	if (ret != 0) { | 
 | 	    if (ret < 0) { | 
 | 		AERROR_INT("xmlSchemaVCheckCVCSimpleType", | 
 | 		    "validating against a built-in type"); | 
 | 		goto internal_error; | 
 | 	    } | 
 | 	    if (WXS_IS_LIST(type)) | 
 | 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2; | 
 | 	    else | 
 | 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1; | 
 | 	} | 
 | 	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) { | 
 | 	    /* | 
 | 	    * Check facets. | 
 | 	    */ | 
 | 	    ret = xmlSchemaValidateFacets(actxt, node, type, | 
 | 		(xmlSchemaValType) biType->builtInType, value, val, | 
 | 		0, fireErrors); | 
 | 	    if (ret != 0) { | 
 | 		if (ret < 0) { | 
 | 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType", | 
 | 			"validating facets of atomic simple type"); | 
 | 		    goto internal_error; | 
 | 		} | 
 | 		if (WXS_IS_LIST(type)) | 
 | 		    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2; | 
 | 		else | 
 | 		    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1; | 
 | 	    } | 
 | 	} | 
 | 	if (fireErrors && (ret > 0)) | 
 | 	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1); | 
 |     } else if (WXS_IS_LIST(type)) { | 
 |  | 
 | 	xmlSchemaTypePtr itemType; | 
 | 	const xmlChar *cur, *end; | 
 | 	xmlChar *tmpValue = NULL; | 
 | 	unsigned long len = 0; | 
 | 	xmlSchemaValPtr prevVal = NULL, curVal = NULL; | 
 | 	/* 1.2.2 if {variety} is �list� then the string must be a sequence | 
 | 	* of white space separated tokens, each of which �match�es a literal | 
 | 	* in the �lexical space� of {item type definition} | 
 | 	*/ | 
 | 	/* | 
 | 	* Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if | 
 | 	* the list type has an enum or pattern facet. | 
 | 	*/ | 
 | 	NORMALIZE(type); | 
 | 	/* | 
 | 	* VAL TODO: Optimize validation of empty values. | 
 | 	* VAL TODO: We do not have computed values for lists. | 
 | 	*/ | 
 | 	itemType = WXS_LIST_ITEMTYPE(type); | 
 | 	cur = value; | 
 | 	do { | 
 | 	    while (IS_BLANK_CH(*cur)) | 
 | 		cur++; | 
 | 	    end = cur; | 
 | 	    while ((*end != 0) && (!(IS_BLANK_CH(*end)))) | 
 | 		end++; | 
 | 	    if (end == cur) | 
 | 		break; | 
 | 	    tmpValue = xmlStrndup(cur, end - cur); | 
 | 	    len++; | 
 |  | 
 | 	    if (valNeeded) | 
 | 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType, | 
 | 		    tmpValue, &curVal, fireErrors, 0, 1); | 
 | 	    else | 
 | 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType, | 
 | 		    tmpValue, NULL, fireErrors, 0, 1); | 
 | 	    FREE_AND_NULL(tmpValue); | 
 | 	    if (curVal != NULL) { | 
 | 		/* | 
 | 		* Add to list of computed values. | 
 | 		*/ | 
 | 		if (val == NULL) | 
 | 		    val = curVal; | 
 | 		else | 
 | 		    xmlSchemaValueAppend(prevVal, curVal); | 
 | 		prevVal = curVal; | 
 | 		curVal = NULL; | 
 | 	    } | 
 | 	    if (ret != 0) { | 
 | 		if (ret < 0) { | 
 | 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType", | 
 | 			"validating an item of list simple type"); | 
 | 		    goto internal_error; | 
 | 		} | 
 | 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2; | 
 | 		break; | 
 | 	    } | 
 | 	    cur = end; | 
 | 	} while (*cur != 0); | 
 | 	FREE_AND_NULL(tmpValue); | 
 | 	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) { | 
 | 	    /* | 
 | 	    * Apply facets (pattern, enumeration). | 
 | 	    */ | 
 | 	    ret = xmlSchemaValidateFacets(actxt, node, type, | 
 | 		XML_SCHEMAS_UNKNOWN, value, val, | 
 | 		len, fireErrors); | 
 | 	    if (ret != 0) { | 
 | 		if (ret < 0) { | 
 | 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType", | 
 | 			"validating facets of list simple type"); | 
 | 		    goto internal_error; | 
 | 		} | 
 | 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2; | 
 | 	    } | 
 | 	} | 
 | 	if (fireErrors && (ret > 0)) { | 
 | 	    /* | 
 | 	    * Report the normalized value. | 
 | 	    */ | 
 | 	    normalize = 1; | 
 | 	    NORMALIZE(type); | 
 | 	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1); | 
 | 	} | 
 |     } else if (WXS_IS_UNION(type)) { | 
 | 	xmlSchemaTypeLinkPtr memberLink; | 
 | 	/* | 
 | 	* TODO: For all datatypes �derived� by �union�  whiteSpace does | 
 | 	* not apply directly; however, the normalization behavior of �union� | 
 | 	* types is controlled by the value of whiteSpace on that one of the | 
 | 	* �memberTypes� against which the �union� is successfully validated. | 
 | 	* | 
 | 	* This means that the value is normalized by the first validating | 
 | 	* member type, then the facets of the union type are applied. This | 
 | 	* needs changing of the value! | 
 | 	*/ | 
 |  | 
 | 	/* | 
 | 	* 1.2.3 if {variety} is �union� then the string must �match� a | 
 | 	* literal in the �lexical space� of at least one member of | 
 | 	* {member type definitions} | 
 | 	*/ | 
 | 	memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type); | 
 | 	if (memberLink == NULL) { | 
 | 	    AERROR_INT("xmlSchemaVCheckCVCSimpleType", | 
 | 		"union simple type has no member types"); | 
 | 	    goto internal_error; | 
 | 	} | 
 | 	/* | 
 | 	* Always normalize union type values, since we currently | 
 | 	* cannot store the whitespace information with the value | 
 | 	* itself; otherwise a later value-comparison would be | 
 | 	* not possible. | 
 | 	*/ | 
 | 	while (memberLink != NULL) { | 
 | 	    if (valNeeded) | 
 | 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, | 
 | 		    memberLink->type, value, &val, 0, 1, 0); | 
 | 	    else | 
 | 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, | 
 | 		    memberLink->type, value, NULL, 0, 1, 0); | 
 | 	    if (ret <= 0) | 
 | 		break; | 
 | 	    memberLink = memberLink->next; | 
 | 	} | 
 | 	if (ret != 0) { | 
 | 	    if (ret < 0) { | 
 | 		AERROR_INT("xmlSchemaVCheckCVCSimpleType", | 
 | 		    "validating members of union simple type"); | 
 | 		goto internal_error; | 
 | 	    } | 
 | 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3; | 
 | 	} | 
 | 	/* | 
 | 	* Apply facets (pattern, enumeration). | 
 | 	*/ | 
 | 	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) { | 
 | 	    /* | 
 | 	    * The normalization behavior of �union� types is controlled by | 
 | 	    * the value of whiteSpace on that one of the �memberTypes� | 
 | 	    * against which the �union� is successfully validated. | 
 | 	    */ | 
 | 	    NORMALIZE(memberLink->type); | 
 | 	    ret = xmlSchemaValidateFacets(actxt, node, type, | 
 | 		XML_SCHEMAS_UNKNOWN, value, val, | 
 | 		0, fireErrors); | 
 | 	    if (ret != 0) { | 
 | 		if (ret < 0) { | 
 | 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType", | 
 | 			"validating facets of union simple type"); | 
 | 		    goto internal_error; | 
 | 		} | 
 | 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3; | 
 | 	    } | 
 | 	} | 
 | 	if (fireErrors && (ret > 0)) | 
 | 	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1); | 
 |     } | 
 |  | 
 |     if (normValue != NULL) | 
 | 	xmlFree(normValue); | 
 |     if (ret == 0) { | 
 | 	if (retVal != NULL) | 
 | 	    *retVal = val; | 
 | 	else if (val != NULL) | 
 | 	    xmlSchemaFreeValue(val); | 
 |     } else if (val != NULL) | 
 | 	xmlSchemaFreeValue(val); | 
 |     return (ret); | 
 | internal_error: | 
 |     if (normValue != NULL) | 
 | 	xmlFree(normValue); | 
 |     if (val != NULL) | 
 | 	xmlSchemaFreeValue(val); | 
 |     return (-1); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt, | 
 | 			   const xmlChar *value, | 
 | 			   const xmlChar **nsName, | 
 | 			   const xmlChar **localName) | 
 | { | 
 |     int ret = 0; | 
 |  | 
 |     if ((nsName == NULL) || (localName == NULL)) | 
 | 	return (-1); | 
 |     *nsName = NULL; | 
 |     *localName = NULL; | 
 |  | 
 |     ret = xmlValidateQName(value, 1); | 
 |     if (ret == -1) | 
 | 	return (-1); | 
 |     if (ret > 0) { | 
 | 	xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt, | 
 | 	    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL, | 
 | 	    value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1); | 
 | 	return (1); | 
 |     } | 
 |     { | 
 | 	xmlChar *local = NULL; | 
 | 	xmlChar *prefix; | 
 |  | 
 | 	/* | 
 | 	* NOTE: xmlSplitQName2 will return a duplicated | 
 | 	* string. | 
 | 	*/ | 
 | 	local = xmlSplitQName2(value, &prefix); | 
 | 	if (local == NULL) | 
 | 	    *localName = xmlDictLookup(vctxt->dict, value, -1); | 
 | 	else { | 
 | 	    *localName = xmlDictLookup(vctxt->dict, local, -1); | 
 | 	    xmlFree(local); | 
 | 	} | 
 |  | 
 | 	*nsName = xmlSchemaLookupNamespace(vctxt, prefix); | 
 |  | 
 | 	if (prefix != NULL) { | 
 | 	    xmlFree(prefix); | 
 | 	    /* | 
 | 	    * A namespace must be found if the prefix is NOT NULL. | 
 | 	    */ | 
 | 	    if (*nsName == NULL) { | 
 | 		xmlSchemaCustomErr(ACTXT_CAST vctxt, | 
 | 		    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL, | 
 | 		    WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), | 
 | 		    "The QName value '%s' has no " | 
 | 		    "corresponding namespace declaration in scope", | 
 | 		    value, NULL); | 
 | 		return (2); | 
 | 	    } | 
 | 	} | 
 |     } | 
 |     return (0); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt, | 
 | 			xmlSchemaAttrInfoPtr iattr, | 
 | 			xmlSchemaTypePtr *localType, | 
 | 			xmlSchemaElementPtr elemDecl) | 
 | { | 
 |     int ret = 0; | 
 |     /* | 
 |     * cvc-elt (3.3.4) : (4) | 
 |     * AND | 
 |     * Schema-Validity Assessment (Element) (cvc-assess-elt) | 
 |     *   (1.2.1.2.1) - (1.2.1.2.4) | 
 |     * Handle 'xsi:type'. | 
 |     */ | 
 |     if (localType == NULL) | 
 | 	return (-1); | 
 |     *localType = NULL; | 
 |     if (iattr == NULL) | 
 | 	return (0); | 
 |     else { | 
 | 	const xmlChar *nsName = NULL, *local = NULL; | 
 | 	/* | 
 | 	* TODO: We should report a *warning* that the type was overriden | 
 | 	* by the instance. | 
 | 	*/ | 
 | 	ACTIVATE_ATTRIBUTE(iattr); | 
 | 	/* | 
 | 	* (cvc-elt) (3.3.4) : (4.1) | 
 | 	* (cvc-assess-elt) (1.2.1.2.2) | 
 | 	*/ | 
 | 	ret = xmlSchemaVExpandQName(vctxt, iattr->value, | 
 | 	    &nsName, &local); | 
 | 	if (ret != 0) { | 
 | 	    if (ret < 0) { | 
 | 		VERROR_INT("xmlSchemaValidateElementByDeclaration", | 
 | 		    "calling xmlSchemaQNameExpand() to validate the " | 
 | 		    "attribute 'xsi:type'"); | 
 | 		goto internal_error; | 
 | 	    } | 
 | 	    goto exit; | 
 | 	} | 
 | 	/* | 
 | 	* (cvc-elt) (3.3.4) : (4.2) | 
 | 	* (cvc-assess-elt) (1.2.1.2.3) | 
 | 	*/ | 
 | 	*localType = xmlSchemaGetType(vctxt->schema, local, nsName); | 
 | 	if (*localType == NULL) { | 
 | 	    xmlChar *str = NULL; | 
 |  | 
 | 	    xmlSchemaCustomErr(ACTXT_CAST vctxt, | 
 | 		XML_SCHEMAV_CVC_ELT_4_2, NULL, | 
 | 		WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), | 
 | 		"The QName value '%s' of the xsi:type attribute does not " | 
 | 		"resolve to a type definition", | 
 | 		xmlSchemaFormatQName(&str, nsName, local), NULL); | 
 | 	    FREE_AND_NULL(str); | 
 | 	    ret = vctxt->err; | 
 | 	    goto exit; | 
 | 	} | 
 | 	if (elemDecl != NULL) { | 
 | 	    int set = 0; | 
 |  | 
 | 	    /* | 
 | 	    * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK) | 
 | 	    * "The �local type definition� must be validly | 
 | 	    * derived from the {type definition} given the union of | 
 | 	    * the {disallowed substitutions} and the {type definition}'s | 
 | 	    * {prohibited substitutions}, as defined in | 
 | 	    * Type Derivation OK (Complex) (�3.4.6) | 
 | 	    * (if it is a complex type definition), | 
 | 	    * or given {disallowed substitutions} as defined in Type | 
 | 	    * Derivation OK (Simple) (�3.14.6) (if it is a simple type | 
 | 	    * definition)." | 
 | 	    * | 
 | 	    * {disallowed substitutions}: the "block" on the element decl. | 
 | 	    * {prohibited substitutions}: the "block" on the type def. | 
 | 	    */ | 
 | 	    /* | 
 | 	    * OPTIMIZE TODO: We could map types already evaluated | 
 | 	    * to be validly derived from other types to avoid checking | 
 | 	    * this over and over for the same types. | 
 | 	    */ | 
 | 	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) || | 
 | 		(elemDecl->subtypes->flags & | 
 | 		    XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) | 
 | 		set |= SUBSET_EXTENSION; | 
 |  | 
 | 	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) || | 
 | 		(elemDecl->subtypes->flags & | 
 | 		    XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)) | 
 | 		set |= SUBSET_RESTRICTION; | 
 |  | 
 | 	    /* | 
 | 	    * REMOVED and CHANGED since this produced a parser context | 
 | 	    * which adds to the string dict of the schema. So this would | 
 | 	    * change the schema and we don't want this. We don't need | 
 | 	    * the parser context anymore. | 
 | 	    * | 
 | 	    * if ((vctxt->pctxt == NULL) && | 
 | 	    *	(xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) | 
 | 	    *	    return (-1); | 
 | 	    */ | 
 |  | 
 | 	    if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType, | 
 | 		elemDecl->subtypes, set) != 0) { | 
 | 		xmlChar *str = NULL; | 
 |  | 
 | 		xmlSchemaCustomErr(ACTXT_CAST vctxt, | 
 | 		    XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL, | 
 | 		    "The type definition '%s', specified by xsi:type, is " | 
 | 		    "blocked or not validly derived from the type definition " | 
 | 		    "of the element declaration", | 
 | 		    xmlSchemaFormatQName(&str, | 
 | 			(*localType)->targetNamespace, | 
 | 			(*localType)->name), | 
 | 		    NULL); | 
 | 		FREE_AND_NULL(str); | 
 | 		ret = vctxt->err; | 
 | 		*localType = NULL; | 
 | 	    } | 
 | 	} | 
 |     } | 
 | exit: | 
 |     ACTIVATE_ELEM; | 
 |     return (ret); | 
 | internal_error: | 
 |     ACTIVATE_ELEM; | 
 |     return (-1); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt) | 
 | { | 
 |     xmlSchemaElementPtr elemDecl = vctxt->inode->decl; | 
 |     xmlSchemaTypePtr actualType; | 
 |  | 
 |     /* | 
 |     * cvc-elt (3.3.4) : 1 | 
 |     */ | 
 |     if (elemDecl == NULL) { | 
 | 	VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, | 
 | 	    "No matching declaration available"); | 
 |         return (vctxt->err); | 
 |     } | 
 |     actualType = WXS_ELEM_TYPEDEF(elemDecl); | 
 |     /* | 
 |     * cvc-elt (3.3.4) : 2 | 
 |     */ | 
 |     if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) { | 
 | 	VERROR(XML_SCHEMAV_CVC_ELT_2, NULL, | 
 | 	    "The element declaration is abstract"); | 
 |         return (vctxt->err); | 
 |     } | 
 |     if (actualType == NULL) { | 
 |     	VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL, | 
 |     	    "The type definition is absent"); | 
 |     	return (XML_SCHEMAV_CVC_TYPE_1); | 
 |     } | 
 |     if (vctxt->nbAttrInfos != 0) { | 
 | 	int ret; | 
 | 	xmlSchemaAttrInfoPtr iattr; | 
 | 	/* | 
 | 	* cvc-elt (3.3.4) : 3 | 
 | 	* Handle 'xsi:nil'. | 
 | 	*/ | 
 | 	iattr = xmlSchemaGetMetaAttrInfo(vctxt, | 
 | 	    XML_SCHEMA_ATTR_INFO_META_XSI_NIL); | 
 | 	if (iattr) { | 
 | 	    ACTIVATE_ATTRIBUTE(iattr); | 
 | 	    /* | 
 | 	    * Validate the value. | 
 | 	    */ | 
 | 	    ret = xmlSchemaVCheckCVCSimpleType( | 
 | 		ACTXT_CAST vctxt, NULL, | 
 | 		xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN), | 
 | 		iattr->value, &(iattr->val), 1, 0, 0); | 
 | 	    ACTIVATE_ELEM; | 
 | 	    if (ret < 0) { | 
 | 		VERROR_INT("xmlSchemaValidateElemDecl", | 
 | 		    "calling xmlSchemaVCheckCVCSimpleType() to " | 
 | 		    "validate the attribute 'xsi:nil'"); | 
 | 		return (-1); | 
 | 	    } | 
 | 	    if (ret == 0) { | 
 | 		if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) { | 
 | 		    /* | 
 | 		    * cvc-elt (3.3.4) : 3.1 | 
 | 		    */ | 
 | 		    VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL, | 
 | 			"The element is not 'nillable'"); | 
 | 		    /* Does not return an error on purpose. */ | 
 | 		} else { | 
 | 		    if (xmlSchemaValueGetAsBoolean(iattr->val)) { | 
 | 			/* | 
 | 			* cvc-elt (3.3.4) : 3.2.2 | 
 | 			*/ | 
 | 			if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) && | 
 | 			    (elemDecl->value != NULL)) { | 
 | 			    VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL, | 
 | 				"The element cannot be 'nilled' because " | 
 | 				"there is a fixed value constraint defined " | 
 | 				"for it"); | 
 | 			     /* Does not return an error on purpose. */ | 
 | 			} else | 
 | 			    vctxt->inode->flags |= | 
 | 				XML_SCHEMA_ELEM_INFO_NILLED; | 
 | 		    } | 
 | 		} | 
 | 	    } | 
 | 	} | 
 | 	/* | 
 | 	* cvc-elt (3.3.4) : 4 | 
 | 	* Handle 'xsi:type'. | 
 | 	*/ | 
 | 	iattr = xmlSchemaGetMetaAttrInfo(vctxt, | 
 | 	    XML_SCHEMA_ATTR_INFO_META_XSI_TYPE); | 
 | 	if (iattr) { | 
 | 	    xmlSchemaTypePtr localType = NULL; | 
 |  | 
 | 	    ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType, | 
 | 		elemDecl); | 
 | 	    if (ret != 0) { | 
 | 		if (ret == -1) { | 
 | 		    VERROR_INT("xmlSchemaValidateElemDecl", | 
 | 			"calling xmlSchemaProcessXSIType() to " | 
 | 			"process the attribute 'xsi:type'"); | 
 | 		    return (-1); | 
 | 		} | 
 | 		/* Does not return an error on purpose. */ | 
 | 	    } | 
 | 	    if (localType != NULL) { | 
 | 		vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE; | 
 | 		actualType = localType; | 
 | 	    } | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * IDC: Register identity-constraint XPath matchers. | 
 |     */ | 
 |     if ((elemDecl->idcs != NULL) && | 
 | 	(xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1)) | 
 | 	    return (-1); | 
 |     /* | 
 |     * No actual type definition. | 
 |     */ | 
 |     if (actualType == NULL) { | 
 |     	VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL, | 
 |     	    "The type definition is absent"); | 
 |     	return (XML_SCHEMAV_CVC_TYPE_1); | 
 |     } | 
 |     /* | 
 |     * Remember the actual type definition. | 
 |     */ | 
 |     vctxt->inode->typeDef = actualType; | 
 |  | 
 |     return (0); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt) | 
 | { | 
 |     xmlSchemaAttrInfoPtr iattr; | 
 |     int ret = 0, i; | 
 |  | 
 |     /* | 
 |     * SPEC cvc-type (3.1.1) | 
 |     * "The attributes of must be empty, excepting those whose namespace | 
 |     * name is identical to http://www.w3.org/2001/XMLSchema-instance and | 
 |     * whose local name is one of type, nil, schemaLocation or | 
 |     * noNamespaceSchemaLocation." | 
 |     */ | 
 |     if (vctxt->nbAttrInfos == 0) | 
 | 	return (0); | 
 |     for (i = 0; i < vctxt->nbAttrInfos; i++) { | 
 | 	iattr = vctxt->attrInfos[i]; | 
 | 	if (! iattr->metaType) { | 
 | 	    ACTIVATE_ATTRIBUTE(iattr) | 
 | 	    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt, | 
 | 		XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL); | 
 | 	    ret = XML_SCHEMAV_CVC_TYPE_3_1_1; | 
 |         } | 
 |     } | 
 |     ACTIVATE_ELEM | 
 |     return (ret); | 
 | } | 
 |  | 
 | /* | 
 | * Cleanup currently used attribute infos. | 
 | */ | 
 | static void | 
 | xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt) | 
 | { | 
 |     int i; | 
 |     xmlSchemaAttrInfoPtr attr; | 
 |  | 
 |     if (vctxt->nbAttrInfos == 0) | 
 | 	return; | 
 |     for (i = 0; i < vctxt->nbAttrInfos; i++) { | 
 | 	attr = vctxt->attrInfos[i]; | 
 | 	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) { | 
 | 	    if (attr->localName != NULL) | 
 | 		xmlFree((xmlChar *) attr->localName); | 
 | 	    if (attr->nsName != NULL) | 
 | 		xmlFree((xmlChar *) attr->nsName); | 
 | 	} | 
 | 	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) { | 
 | 	    if (attr->value != NULL) | 
 | 		xmlFree((xmlChar *) attr->value); | 
 | 	} | 
 | 	if (attr->val != NULL) { | 
 | 	    xmlSchemaFreeValue(attr->val); | 
 | 	    attr->val = NULL; | 
 | 	} | 
 | 	memset(attr, 0, sizeof(xmlSchemaAttrInfo)); | 
 |     } | 
 |     vctxt->nbAttrInfos = 0; | 
 | } | 
 |  | 
 | /* | 
 | * 3.4.4 Complex Type Definition Validation Rules | 
 | *   Element Locally Valid (Complex Type) (cvc-complex-type) | 
 | * 3.2.4 Attribute Declaration Validation Rules | 
 | *   Validation Rule: Attribute Locally Valid (cvc-attribute) | 
 | *   Attribute Locally Valid (Use) (cvc-au) | 
 | * | 
 | * Only "assessed" attribute information items will be visible to | 
 | * IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes. | 
 | */ | 
 | static int | 
 | xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt) | 
 | { | 
 |     xmlSchemaTypePtr type = vctxt->inode->typeDef; | 
 |     xmlSchemaItemListPtr attrUseList; | 
 |     xmlSchemaAttributeUsePtr attrUse = NULL; | 
 |     xmlSchemaAttributePtr attrDecl = NULL; | 
 |     xmlSchemaAttrInfoPtr iattr, tmpiattr; | 
 |     int i, j, found, nbAttrs, nbUses; | 
 |     int xpathRes = 0, res, wildIDs = 0, fixed; | 
 |     xmlNodePtr defAttrOwnerElem = NULL; | 
 |  | 
 |     /* | 
 |     * SPEC (cvc-attribute) | 
 |     * (1) "The declaration must not be �absent� (see Missing | 
 |     * Sub-components (�5.3) for how this can fail to be | 
 |     * the case)." | 
 |     * (2) "Its {type definition} must not be absent." | 
 |     * | 
 |     * NOTE (1) + (2): This is not handled here, since we currently do not | 
 |     * allow validation against schemas which have missing sub-components. | 
 |     * | 
 |     * SPEC (cvc-complex-type) | 
 |     * (3) "For each attribute information item in the element information | 
 |     * item's [attributes] excepting those whose [namespace name] is | 
 |     * identical to http://www.w3.org/2001/XMLSchema-instance and whose | 
 |     * [local name] is one of type, nil, schemaLocation or | 
 |     * noNamespaceSchemaLocation, the appropriate case among the following | 
 |     * must be true: | 
 |     * | 
 |     */ | 
 |     attrUseList = (xmlSchemaItemListPtr) type->attrUses; | 
 |     /* | 
 |     * @nbAttrs is the number of attributes present in the instance. | 
 |     */ | 
 |     nbAttrs = vctxt->nbAttrInfos; | 
 |     if (attrUseList != NULL) | 
 | 	nbUses = attrUseList->nbItems; | 
 |     else | 
 | 	nbUses = 0; | 
 |     for (i = 0; i < nbUses; i++) { | 
 |         found = 0; | 
 | 	attrUse = attrUseList->items[i]; | 
 | 	attrDecl = WXS_ATTRUSE_DECL(attrUse); | 
 |         for (j = 0; j < nbAttrs; j++) { | 
 | 	    iattr = vctxt->attrInfos[j]; | 
 | 	    /* | 
 | 	    * SPEC (cvc-complex-type) (3) | 
 | 	    * Skip meta attributes. | 
 | 	    */ | 
 | 	    if (iattr->metaType) | 
 | 		continue; | 
 | 	    if (iattr->localName[0] != attrDecl->name[0]) | 
 | 		continue; | 
 | 	    if (!xmlStrEqual(iattr->localName, attrDecl->name)) | 
 | 		continue; | 
 | 	    if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace)) | 
 | 		continue; | 
 | 	    found = 1; | 
 | 	    /* | 
 | 	    * SPEC (cvc-complex-type) | 
 | 	    * (3.1) "If there is among the {attribute uses} an attribute | 
 | 	    * use with an {attribute declaration} whose {name} matches | 
 | 	    * the attribute information item's [local name] and whose | 
 | 	    * {target namespace} is identical to the attribute information | 
 | 	    * item's [namespace name] (where an �absent� {target namespace} | 
 | 	    * is taken to be identical to a [namespace name] with no value), | 
 | 	    * then the attribute information must be �valid� with respect | 
 | 	    * to that attribute use as per Attribute Locally Valid (Use) | 
 | 	    * (�3.5.4). In this case the {attribute declaration} of that | 
 | 	    * attribute use is the �context-determined declaration� for the | 
 | 	    * attribute information item with respect to Schema-Validity | 
 | 	    * Assessment (Attribute) (�3.2.4) and | 
 | 	    * Assessment Outcome (Attribute) (�3.2.5). | 
 | 	    */ | 
 | 	    iattr->state = XML_SCHEMAS_ATTR_ASSESSED; | 
 | 	    iattr->use = attrUse; | 
 | 	    /* | 
 | 	    * Context-determined declaration. | 
 | 	    */ | 
 | 	    iattr->decl = attrDecl; | 
 | 	    iattr->typeDef = attrDecl->subtypes; | 
 | 	    break; | 
 | 	} | 
 |  | 
 | 	if (found) | 
 | 	    continue; | 
 |  | 
 | 	if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) { | 
 | 	    /* | 
 | 	    * Handle non-existent, required attributes. | 
 | 	    * | 
 | 	    * SPEC (cvc-complex-type) | 
 | 	    * (4) "The {attribute declaration} of each attribute use in | 
 | 	    * the {attribute uses} whose {required} is true matches one | 
 | 	    * of the attribute information items in the element information | 
 | 	    * item's [attributes] as per clause 3.1 above." | 
 | 	    */ | 
 | 	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt); | 
 | 	    if (tmpiattr == NULL) { | 
 | 		VERROR_INT( | 
 | 		    "xmlSchemaVAttributesComplex", | 
 | 		    "calling xmlSchemaGetFreshAttrInfo()"); | 
 | 		return (-1); | 
 | 	    } | 
 | 	    tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING; | 
 | 	    tmpiattr->use = attrUse; | 
 | 	    tmpiattr->decl = attrDecl; | 
 | 	} else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) && | 
 | 	    ((attrUse->defValue != NULL) || | 
 | 	     (attrDecl->defValue != NULL))) { | 
 | 	    /* | 
 | 	    * Handle non-existent, optional, default/fixed attributes. | 
 | 	    */ | 
 | 	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt); | 
 | 	    if (tmpiattr == NULL) { | 
 | 		VERROR_INT( | 
 | 		    "xmlSchemaVAttributesComplex", | 
 | 		    "calling xmlSchemaGetFreshAttrInfo()"); | 
 | 		return (-1); | 
 | 	    } | 
 | 	    tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT; | 
 | 	    tmpiattr->use = attrUse; | 
 | 	    tmpiattr->decl = attrDecl; | 
 | 	    tmpiattr->typeDef = attrDecl->subtypes; | 
 | 	    tmpiattr->localName = attrDecl->name; | 
 | 	    tmpiattr->nsName = attrDecl->targetNamespace; | 
 | 	} | 
 |     } | 
 |  | 
 |     if (vctxt->nbAttrInfos == 0) | 
 | 	return (0); | 
 |     /* | 
 |     * Validate against the wildcard. | 
 |     */ | 
 |     if (type->attributeWildcard != NULL) { | 
 | 	/* | 
 | 	* SPEC (cvc-complex-type) | 
 | 	* (3.2.1) "There must be an {attribute wildcard}." | 
 | 	*/ | 
 | 	for (i = 0; i < nbAttrs; i++) { | 
 | 	    iattr = vctxt->attrInfos[i]; | 
 | 	    /* | 
 | 	    * SPEC (cvc-complex-type) (3) | 
 | 	    * Skip meta attributes. | 
 | 	    */ | 
 | 	    if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN) | 
 | 		continue; | 
 | 	    /* | 
 | 	    * SPEC (cvc-complex-type) | 
 | 	    * (3.2.2) "The attribute information item must be �valid� with | 
 | 	    * respect to it as defined in Item Valid (Wildcard) (�3.10.4)." | 
 | 	    * | 
 | 	    * SPEC Item Valid (Wildcard) (cvc-wildcard) | 
 | 	    * "... its [namespace name] must be �valid� with respect to | 
 | 	    * the wildcard constraint, as defined in Wildcard allows | 
 | 	    * Namespace Name (�3.10.4)." | 
 | 	    */ | 
 | 	    if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard, | 
 | 		    iattr->nsName) == 0) { | 
 | 		/* | 
 | 		* Handle processContents. | 
 | 		* | 
 | 		* SPEC (cvc-wildcard): | 
 | 		* processContents | context-determined declaration: | 
 | 		* "strict"          "mustFind" | 
 | 		* "lax"             "none" | 
 | 		* "skip"            "skip" | 
 | 		*/ | 
 | 		if (type->attributeWildcard->processContents == | 
 | 		    XML_SCHEMAS_ANY_SKIP) { | 
 | 		     /* | 
 | 		    * context-determined declaration = "skip" | 
 | 		    * | 
 | 		    * SPEC PSVI Assessment Outcome (Attribute) | 
 | 		    * [validity] = "notKnown" | 
 | 		    * [validation attempted] = "none" | 
 | 		    */ | 
 | 		    iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP; | 
 | 		    continue; | 
 | 		} | 
 | 		/* | 
 | 		* Find an attribute declaration. | 
 | 		*/ | 
 | 		iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema, | 
 | 		    iattr->localName, iattr->nsName); | 
 | 		if (iattr->decl != NULL) { | 
 | 		    iattr->state = XML_SCHEMAS_ATTR_ASSESSED; | 
 | 		    /* | 
 | 		    * SPEC (cvc-complex-type) | 
 | 		    * (5) "Let [Definition:]  the wild IDs be the set of | 
 | 		    * all attribute information item to which clause 3.2 | 
 | 		    * applied and whose �validation� resulted in a | 
 | 		    * �context-determined declaration� of mustFind or no | 
 | 		    * �context-determined declaration� at all, and whose | 
 | 		    * [local name] and [namespace name] resolve (as | 
 | 		    * defined by QName resolution (Instance) (�3.15.4)) to | 
 | 		    * an attribute declaration whose {type definition} is | 
 | 		    * or is derived from ID. Then all of the following | 
 | 		    * must be true:" | 
 | 		    */ | 
 | 		    iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl); | 
 | 		    if (xmlSchemaIsDerivedFromBuiltInType( | 
 | 			iattr->typeDef, XML_SCHEMAS_ID)) { | 
 | 			/* | 
 | 			* SPEC (5.1) "There must be no more than one | 
 | 			* item in �wild IDs�." | 
 | 			*/ | 
 | 			if (wildIDs != 0) { | 
 | 			    /* VAL TODO */ | 
 | 			    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID; | 
 | 			    TODO | 
 | 			    continue; | 
 | 			} | 
 | 			wildIDs++; | 
 | 			/* | 
 | 			* SPEC (cvc-complex-type) | 
 | 			* (5.2) "If �wild IDs� is non-empty, there must not | 
 | 			* be any attribute uses among the {attribute uses} | 
 | 			* whose {attribute declaration}'s {type definition} | 
 | 			* is or is derived from ID." | 
 | 			*/ | 
 |                         if (attrUseList != NULL) { | 
 |                             for (j = 0; j < attrUseList->nbItems; j++) { | 
 |                                 if (xmlSchemaIsDerivedFromBuiltInType( | 
 |                                     WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]), | 
 |                                     XML_SCHEMAS_ID)) { | 
 |                                     /* URGENT VAL TODO: implement */ | 
 |                             iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID; | 
 |                                     TODO | 
 |                                     break; | 
 |                                 } | 
 |                             } | 
 |                         } | 
 | 		    } | 
 | 		} else if (type->attributeWildcard->processContents == | 
 | 		    XML_SCHEMAS_ANY_LAX) { | 
 | 		    iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL; | 
 | 		    /* | 
 | 		    * SPEC PSVI Assessment Outcome (Attribute) | 
 | 		    * [validity] = "notKnown" | 
 | 		    * [validation attempted] = "none" | 
 | 		    */ | 
 | 		} else { | 
 | 		    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL; | 
 | 		} | 
 | 	    } | 
 | 	} | 
 |     } | 
 |  | 
 |     if (vctxt->nbAttrInfos == 0) | 
 | 	return (0); | 
 |  | 
 |     /* | 
 |     * Get the owner element; needed for creation of default attributes. | 
 |     * This fixes bug #341337, reported by David Grohmann. | 
 |     */ | 
 |     if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) { | 
 | 	xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth]; | 
 | 	if (ielem && ielem->node && ielem->node->doc) | 
 | 	    defAttrOwnerElem = ielem->node; | 
 |     } | 
 |     /* | 
 |     * Validate values, create default attributes, evaluate IDCs. | 
 |     */ | 
 |     for (i = 0; i < vctxt->nbAttrInfos; i++) { | 
 | 	iattr = vctxt->attrInfos[i]; | 
 | 	/* | 
 | 	* VAL TODO: Note that we won't try to resolve IDCs to | 
 | 	* "lax" and "skip" validated attributes. Check what to | 
 | 	* do in this case. | 
 | 	*/ | 
 | 	if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) && | 
 | 	    (iattr->state != XML_SCHEMAS_ATTR_DEFAULT)) | 
 | 	    continue; | 
 | 	/* | 
 | 	* VAL TODO: What to do if the type definition is missing? | 
 | 	*/ | 
 | 	if (iattr->typeDef == NULL) { | 
 | 	    iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE; | 
 | 	    continue; | 
 | 	} | 
 |  | 
 | 	ACTIVATE_ATTRIBUTE(iattr); | 
 | 	fixed = 0; | 
 | 	xpathRes = 0; | 
 |  | 
 | 	if (vctxt->xpathStates != NULL) { | 
 | 	    /* | 
 | 	    * Evaluate IDCs. | 
 | 	    */ | 
 | 	    xpathRes = xmlSchemaXPathEvaluate(vctxt, | 
 | 		XML_ATTRIBUTE_NODE); | 
 | 	    if (xpathRes == -1) { | 
 | 		VERROR_INT("xmlSchemaVAttributesComplex", | 
 | 		    "calling xmlSchemaXPathEvaluate()"); | 
 | 		goto internal_error; | 
 | 	    } | 
 | 	} | 
 |  | 
 | 	if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) { | 
 | 	    /* | 
 | 	    * Default/fixed attributes. | 
 | 	    * We need the value only if we need to resolve IDCs or | 
 | 	    * will create default attributes. | 
 | 	    */ | 
 | 	    if ((xpathRes) || (defAttrOwnerElem)) { | 
 | 		if (iattr->use->defValue != NULL) { | 
 | 		    iattr->value = (xmlChar *) iattr->use->defValue; | 
 | 		    iattr->val = iattr->use->defVal; | 
 | 		} else { | 
 | 		    iattr->value = (xmlChar *) iattr->decl->defValue; | 
 | 		    iattr->val = iattr->decl->defVal; | 
 | 		} | 
 | 		/* | 
 | 		* IDCs will consume the precomputed default value, | 
 | 		* so we need to clone it. | 
 | 		*/ | 
 | 		if (iattr->val == NULL) { | 
 | 		    VERROR_INT("xmlSchemaVAttributesComplex", | 
 | 			"default/fixed value on an attribute use was " | 
 | 			"not precomputed"); | 
 | 		    goto internal_error; | 
 | 		} | 
 | 		iattr->val = xmlSchemaCopyValue(iattr->val); | 
 | 		if (iattr->val == NULL) { | 
 | 		    VERROR_INT("xmlSchemaVAttributesComplex", | 
 | 			"calling xmlSchemaCopyValue()"); | 
 | 		    goto internal_error; | 
 | 		} | 
 | 	    } | 
 | 	    /* | 
 | 	    * PSVI: Add the default attribute to the current element. | 
 | 	    * VAL TODO: Should we use the *normalized* value? This currently | 
 | 	    *   uses the *initial* value. | 
 | 	    */ | 
 |  | 
 | 	    if (defAttrOwnerElem) { | 
 | 		xmlChar *normValue; | 
 | 		const xmlChar *value; | 
 |  | 
 | 		value = iattr->value; | 
 | 		/* | 
 | 		* Normalize the value. | 
 | 		*/ | 
 | 		normValue = xmlSchemaNormalizeValue(iattr->typeDef, | 
 | 		    iattr->value); | 
 | 		if (normValue != NULL) | 
 | 		    value = BAD_CAST normValue; | 
 |  | 
 | 		if (iattr->nsName == NULL) { | 
 | 		    if (xmlNewProp(defAttrOwnerElem, | 
 | 			iattr->localName, value) == NULL) { | 
 | 			VERROR_INT("xmlSchemaVAttributesComplex", | 
 | 			    "callling xmlNewProp()"); | 
 | 			if (normValue != NULL) | 
 | 			    xmlFree(normValue); | 
 | 			goto internal_error; | 
 | 		    } | 
 | 		} else { | 
 | 		    xmlNsPtr ns; | 
 |  | 
 | 		    ns = xmlSearchNsByHref(defAttrOwnerElem->doc, | 
 | 			defAttrOwnerElem, iattr->nsName); | 
 | 		    if (ns == NULL) { | 
 | 			xmlChar prefix[12]; | 
 | 			int counter = 0; | 
 |  | 
 | 			/* | 
 | 			* Create a namespace declaration on the validation | 
 | 			* root node if no namespace declaration is in scope. | 
 | 			*/ | 
 | 			do { | 
 | 			    snprintf((char *) prefix, 12, "p%d", counter++); | 
 | 			    ns = xmlSearchNs(defAttrOwnerElem->doc, | 
 | 				defAttrOwnerElem, BAD_CAST prefix); | 
 | 			    if (counter > 1000) { | 
 | 				VERROR_INT( | 
 | 				    "xmlSchemaVAttributesComplex", | 
 | 				    "could not compute a ns prefix for a " | 
 | 				    "default/fixed attribute"); | 
 | 				if (normValue != NULL) | 
 | 				    xmlFree(normValue); | 
 | 				goto internal_error; | 
 | 			    } | 
 | 			} while (ns != NULL); | 
 | 			ns = xmlNewNs(vctxt->validationRoot, | 
 | 			    iattr->nsName, BAD_CAST prefix); | 
 | 		    } | 
 | 		    /* | 
 | 		    * TODO: | 
 | 		    * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html | 
 | 		    * If we have QNames: do we need to ensure there's a | 
 | 		    * prefix defined for the QName? | 
 | 		    */ | 
 | 		    xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value); | 
 | 		} | 
 | 		if (normValue != NULL) | 
 | 		    xmlFree(normValue); | 
 | 	    } | 
 | 	    /* | 
 | 	    * Go directly to IDC evaluation. | 
 | 	    */ | 
 | 	    goto eval_idcs; | 
 | 	} | 
 | 	/* | 
 | 	* Validate the value. | 
 | 	*/ | 
 | 	if (vctxt->value != NULL) { | 
 | 	    /* | 
 | 	    * Free last computed value; just for safety reasons. | 
 | 	    */ | 
 | 	    xmlSchemaFreeValue(vctxt->value); | 
 | 	    vctxt->value = NULL; | 
 | 	} | 
 | 	/* | 
 | 	* Note that the attribute *use* can be unavailable, if | 
 | 	* the attribute was a wild attribute. | 
 | 	*/ | 
 | 	if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) || | 
 | 	    ((iattr->use != NULL) && | 
 | 	     (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED))) | 
 | 	    fixed = 1; | 
 | 	else | 
 | 	    fixed = 0; | 
 | 	/* | 
 | 	* SPEC (cvc-attribute) | 
 | 	* (3) "The item's �normalized value� must be locally �valid� | 
 | 	* with respect to that {type definition} as per | 
 | 	* String Valid (�3.14.4)." | 
 | 	* | 
 | 	* VAL TODO: Do we already have the | 
 | 	* "normalized attribute value" here? | 
 | 	*/ | 
 | 	if (xpathRes || fixed) { | 
 | 	    iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED; | 
 | 	    /* | 
 | 	    * Request a computed value. | 
 | 	    */ | 
 | 	    res = xmlSchemaVCheckCVCSimpleType( | 
 | 		ACTXT_CAST vctxt, | 
 | 		iattr->node, iattr->typeDef, iattr->value, &(iattr->val), | 
 | 		1, 1, 0); | 
 | 	} else { | 
 | 	    res = xmlSchemaVCheckCVCSimpleType( | 
 | 		ACTXT_CAST vctxt, | 
 | 		iattr->node, iattr->typeDef, iattr->value, NULL, | 
 | 		1, 0, 0); | 
 | 	} | 
 |  | 
 | 	if (res != 0) { | 
 | 	    if (res == -1) { | 
 | 		VERROR_INT("xmlSchemaVAttributesComplex", | 
 | 		    "calling xmlSchemaStreamValidateSimpleTypeValue()"); | 
 | 		goto internal_error; | 
 | 	    } | 
 | 	    iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE; | 
 | 	    /* | 
 | 	    * SPEC PSVI Assessment Outcome (Attribute) | 
 | 	    * [validity] = "invalid" | 
 | 	    */ | 
 | 	    goto eval_idcs; | 
 | 	} | 
 |  | 
 | 	if (fixed) { | 
 | 	    /* | 
 | 	    * SPEC Attribute Locally Valid (Use) (cvc-au) | 
 | 	    * "For an attribute information item to be�valid� | 
 | 	    * with respect to an attribute use its *normalized* | 
 | 	    * value� must match the *canonical* lexical | 
 | 	    * representation of the attribute use's {value | 
 | 	    * constraint}value, if it is present and fixed." | 
 | 	    * | 
 | 	    * VAL TODO: The requirement for the *canonical* value | 
 | 	    * will be removed in XML Schema 1.1. | 
 | 	    */ | 
 | 	    /* | 
 | 	    * SPEC Attribute Locally Valid (cvc-attribute) | 
 | 	    * (4) "The item's *actual* value� must match the *value* of | 
 | 	    * the {value constraint}, if it is present and fixed." | 
 | 	    */ | 
 | 	    if (iattr->val == NULL) { | 
 | 		/* VAL TODO: A value was not precomputed. */ | 
 | 		TODO | 
 | 		goto eval_idcs; | 
 | 	    } | 
 | 	    if ((iattr->use != NULL) && | 
 | 		(iattr->use->defValue != NULL)) { | 
 | 		if (iattr->use->defVal == NULL) { | 
 | 		    /* VAL TODO: A default value was not precomputed. */ | 
 | 		    TODO | 
 | 		    goto eval_idcs; | 
 | 		} | 
 | 		iattr->vcValue = iattr->use->defValue; | 
 | 		/* | 
 | 		if (xmlSchemaCompareValuesWhtsp(attr->val, | 
 | 		    (xmlSchemaWhitespaceValueType) ws, | 
 | 		    attr->use->defVal, | 
 | 		    (xmlSchemaWhitespaceValueType) ws) != 0) { | 
 | 		*/ | 
 | 		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal)) | 
 | 		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE; | 
 | 	    } else { | 
 | 		if (iattr->decl->defVal == NULL) { | 
 | 		    /* VAL TODO: A default value was not precomputed. */ | 
 | 		    TODO | 
 | 		    goto eval_idcs; | 
 | 		} | 
 | 		iattr->vcValue = iattr->decl->defValue; | 
 | 		/* | 
 | 		if (xmlSchemaCompareValuesWhtsp(attr->val, | 
 | 		    (xmlSchemaWhitespaceValueType) ws, | 
 | 		    attrDecl->defVal, | 
 | 		    (xmlSchemaWhitespaceValueType) ws) != 0) { | 
 | 		*/ | 
 | 		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal)) | 
 | 		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE; | 
 | 	    } | 
 | 	    /* | 
 | 	    * [validity] = "valid" | 
 | 	    */ | 
 | 	} | 
 | eval_idcs: | 
 | 	/* | 
 | 	* Evaluate IDCs. | 
 | 	*/ | 
 | 	if (xpathRes) { | 
 | 	    if (xmlSchemaXPathProcessHistory(vctxt, | 
 | 		vctxt->depth +1) == -1) { | 
 | 		VERROR_INT("xmlSchemaVAttributesComplex", | 
 | 		    "calling xmlSchemaXPathEvaluate()"); | 
 | 		goto internal_error; | 
 | 	    } | 
 | 	} else if (vctxt->xpathStates != NULL) | 
 | 	    xmlSchemaXPathPop(vctxt); | 
 |     } | 
 |  | 
 |     /* | 
 |     * Report errors. | 
 |     */ | 
 |     for (i = 0; i < vctxt->nbAttrInfos; i++) { | 
 | 	iattr = vctxt->attrInfos[i]; | 
 | 	if ((iattr->state == XML_SCHEMAS_ATTR_META) || | 
 | 	    (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) || | 
 | 	    (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) || | 
 | 	    (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL)) | 
 | 	    continue; | 
 | 	ACTIVATE_ATTRIBUTE(iattr); | 
 | 	switch (iattr->state) { | 
 | 	    case XML_SCHEMAS_ATTR_ERR_MISSING: { | 
 | 		    xmlChar *str = NULL; | 
 | 		    ACTIVATE_ELEM; | 
 | 		    xmlSchemaCustomErr(ACTXT_CAST vctxt, | 
 | 			XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL, | 
 | 			"The attribute '%s' is required but missing", | 
 | 			xmlSchemaFormatQName(&str, | 
 | 			    iattr->decl->targetNamespace, | 
 | 			    iattr->decl->name), | 
 | 			NULL); | 
 | 		    FREE_AND_NULL(str) | 
 | 		    break; | 
 | 		} | 
 | 	    case XML_SCHEMAS_ATTR_ERR_NO_TYPE: | 
 | 		VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL, | 
 | 		    "The type definition is absent"); | 
 | 		break; | 
 | 	    case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE: | 
 | 		xmlSchemaCustomErr(ACTXT_CAST vctxt, | 
 | 		    XML_SCHEMAV_CVC_AU, NULL, NULL, | 
 | 		    "The value '%s' does not match the fixed " | 
 | 		    "value constraint '%s'", | 
 | 		    iattr->value, iattr->vcValue); | 
 | 		break; | 
 | 	    case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL: | 
 | 		VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL, | 
 | 		    "No matching global attribute declaration available, but " | 
 | 		    "demanded by the strict wildcard"); | 
 | 		break; | 
 | 	    case XML_SCHEMAS_ATTR_UNKNOWN: | 
 | 		if (iattr->metaType) | 
 | 		    break; | 
 | 		/* | 
 | 		* MAYBE VAL TODO: One might report different error messages | 
 | 		* for the following errors. | 
 | 		*/ | 
 | 		if (type->attributeWildcard == NULL) { | 
 | 		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt, | 
 | 			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL); | 
 | 		} else { | 
 | 		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt, | 
 | 			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL); | 
 | 		} | 
 | 		break; | 
 | 	    default: | 
 | 		break; | 
 | 	} | 
 |     } | 
 |  | 
 |     ACTIVATE_ELEM; | 
 |     return (0); | 
 | internal_error: | 
 |     ACTIVATE_ELEM; | 
 |     return (-1); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt, | 
 | 			      int *skip) | 
 | { | 
 |     xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl; | 
 |     /* | 
 |     * The namespace of the element was already identified to be | 
 |     * matching the wildcard. | 
 |     */ | 
 |     if ((skip == NULL) || (wild == NULL) || | 
 | 	(wild->type != XML_SCHEMA_TYPE_ANY)) { | 
 | 	VERROR_INT("xmlSchemaValidateElemWildcard", | 
 | 	    "bad arguments"); | 
 | 	return (-1); | 
 |     } | 
 |     *skip = 0; | 
 |     if (wild->processContents == XML_SCHEMAS_ANY_SKIP) { | 
 | 	/* | 
 | 	* URGENT VAL TODO: Either we need to position the stream to the | 
 | 	* next sibling, or walk the whole subtree. | 
 | 	*/ | 
 | 	*skip = 1; | 
 | 	return (0); | 
 |     } | 
 |     { | 
 | 	xmlSchemaElementPtr decl = NULL; | 
 |  | 
 | 	decl = xmlSchemaGetElem(vctxt->schema, | 
 | 	    vctxt->inode->localName, vctxt->inode->nsName); | 
 | 	if (decl != NULL) { | 
 | 	    vctxt->inode->decl = decl; | 
 | 	    return (0); | 
 | 	} | 
 |     } | 
 |     if (wild->processContents == XML_SCHEMAS_ANY_STRICT) { | 
 | 	/* VAL TODO: Change to proper error code. */ | 
 | 	VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */ | 
 | 	    "No matching global element declaration available, but " | 
 | 	    "demanded by the strict wildcard"); | 
 | 	return (vctxt->err); | 
 |     } | 
 |     if (vctxt->nbAttrInfos != 0) { | 
 | 	xmlSchemaAttrInfoPtr iattr; | 
 | 	/* | 
 | 	* SPEC Validation Rule: Schema-Validity Assessment (Element) | 
 | 	* (1.2.1.2.1) - (1.2.1.2.3 ) | 
 | 	* | 
 | 	* Use the xsi:type attribute for the type definition. | 
 | 	*/ | 
 | 	iattr = xmlSchemaGetMetaAttrInfo(vctxt, | 
 | 	    XML_SCHEMA_ATTR_INFO_META_XSI_TYPE); | 
 | 	if (iattr != NULL) { | 
 | 	    if (xmlSchemaProcessXSIType(vctxt, iattr, | 
 | 		&(vctxt->inode->typeDef), NULL) == -1) { | 
 | 		VERROR_INT("xmlSchemaValidateElemWildcard", | 
 | 		    "calling xmlSchemaProcessXSIType() to " | 
 | 		    "process the attribute 'xsi:nil'"); | 
 | 		return (-1); | 
 | 	    } | 
 | 	    /* | 
 | 	    * Don't return an error on purpose. | 
 | 	    */ | 
 | 	    return (0); | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * SPEC Validation Rule: Schema-Validity Assessment (Element) | 
 |     * | 
 |     * Fallback to "anyType". | 
 |     */ | 
 |     vctxt->inode->typeDef = | 
 | 	xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE); | 
 |     return (0); | 
 | } | 
 |  | 
 | /* | 
 | * xmlSchemaCheckCOSValidDefault: | 
 | * | 
 | * This will be called if: not nilled, no content and a default/fixed | 
 | * value is provided. | 
 | */ | 
 |  | 
 | static int | 
 | xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt, | 
 | 			      const xmlChar *value, | 
 | 			      xmlSchemaValPtr *val) | 
 | { | 
 |     int ret = 0; | 
 |     xmlSchemaNodeInfoPtr inode = vctxt->inode; | 
 |  | 
 |     /* | 
 |     * cos-valid-default: | 
 |     * Schema Component Constraint: Element Default Valid (Immediate) | 
 |     * For a string to be a valid default with respect to a type | 
 |     * definition the appropriate case among the following must be true: | 
 |     */ | 
 |     if WXS_IS_COMPLEX(inode->typeDef) { | 
 | 	/* | 
 | 	* Complex type. | 
 | 	* | 
 | 	* SPEC (2.1) "its {content type} must be a simple type definition | 
 | 	* or mixed." | 
 | 	* SPEC (2.2.2) "If the {content type} is mixed, then the {content | 
 | 	* type}'s particle must be �emptiable� as defined by | 
 | 	* Particle Emptiable (�3.9.6)." | 
 | 	*/ | 
 | 	if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) && | 
 | 	    ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) || | 
 | 	     (! WXS_EMPTIABLE(inode->typeDef)))) { | 
 | 	    ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1; | 
 | 	    /* NOTE that this covers (2.2.2) as well. */ | 
 | 	    VERROR(ret, NULL, | 
 | 		"For a string to be a valid default, the type definition " | 
 | 		"must be a simple type or a complex type with simple content " | 
 | 		"or mixed content and a particle emptiable"); | 
 | 	    return(ret); | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * 1 If the type definition is a simple type definition, then the string | 
 |     * must be �valid� with respect to that definition as defined by String | 
 |     * Valid (�3.14.4). | 
 |     * | 
 |     * AND | 
 |     * | 
 |     * 2.2.1 If the {content type} is a simple type definition, then the | 
 |     * string must be �valid� with respect to that simple type definition | 
 |     * as defined by String Valid (�3.14.4). | 
 |     */ | 
 |     if (WXS_IS_SIMPLE(inode->typeDef)) { | 
 |  | 
 | 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt, | 
 | 	    NULL, inode->typeDef, value, val, 1, 1, 0); | 
 |  | 
 |     } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) { | 
 |  | 
 | 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt, | 
 | 	    NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0); | 
 |     } | 
 |     if (ret < 0) { | 
 | 	VERROR_INT("xmlSchemaCheckCOSValidDefault", | 
 | 	    "calling xmlSchemaVCheckCVCSimpleType()"); | 
 |     } | 
 |     return (ret); | 
 | } | 
 |  | 
 | static void | 
 | xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED, | 
 | 			       const xmlChar * name ATTRIBUTE_UNUSED, | 
 | 			       xmlSchemaElementPtr item, | 
 | 			       xmlSchemaNodeInfoPtr inode) | 
 | { | 
 |     inode->decl = item; | 
 | #ifdef DEBUG_CONTENT | 
 |     { | 
 | 	xmlChar *str = NULL; | 
 |  | 
 | 	if (item->type == XML_SCHEMA_TYPE_ELEMENT) { | 
 | 	    xmlGenericError(xmlGenericErrorContext, | 
 | 		"AUTOMATON callback for '%s' [declaration]\n", | 
 | 		xmlSchemaFormatQName(&str, | 
 | 		inode->localName, inode->nsName)); | 
 | 	} else { | 
 | 	    xmlGenericError(xmlGenericErrorContext, | 
 | 		    "AUTOMATON callback for '%s' [wildcard]\n", | 
 | 		    xmlSchemaFormatQName(&str, | 
 | 		    inode->localName, inode->nsName)); | 
 |  | 
 | 	} | 
 | 	FREE_AND_NULL(str) | 
 |     } | 
 | #endif | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt) | 
 | { | 
 |     vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt); | 
 |     if (vctxt->inode == NULL) { | 
 | 	VERROR_INT("xmlSchemaValidatorPushElem", | 
 | 	    "calling xmlSchemaGetFreshElemInfo()"); | 
 | 	return (-1); | 
 |     } | 
 |     vctxt->nbAttrInfos = 0; | 
 |     return (0); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt, | 
 | 			     xmlSchemaNodeInfoPtr inode, | 
 | 			     xmlSchemaTypePtr type, | 
 | 			     const xmlChar *value) | 
 | { | 
 |     if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED) | 
 | 	return (xmlSchemaVCheckCVCSimpleType( | 
 | 	    ACTXT_CAST vctxt, NULL, | 
 | 	    type, value, &(inode->val), 1, 1, 0)); | 
 |     else | 
 | 	return (xmlSchemaVCheckCVCSimpleType( | 
 | 	    ACTXT_CAST vctxt, NULL, | 
 | 	    type, value, NULL, 1, 0, 0)); | 
 | } | 
 |  | 
 |  | 
 |  | 
 | /* | 
 | * Process END of element. | 
 | */ | 
 | static int | 
 | xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt) | 
 | { | 
 |     int ret = 0; | 
 |     xmlSchemaNodeInfoPtr inode = vctxt->inode; | 
 |  | 
 |     if (vctxt->nbAttrInfos != 0) | 
 | 	xmlSchemaClearAttrInfos(vctxt); | 
 |     if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) { | 
 | 	/* | 
 | 	* This element was not expected; | 
 | 	* we will not validate child elements of broken parents. | 
 | 	* Skip validation of all content of the parent. | 
 | 	*/ | 
 | 	vctxt->skipDepth = vctxt->depth -1; | 
 | 	goto end_elem; | 
 |     } | 
 |     if ((inode->typeDef == NULL) || | 
 | 	(inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) { | 
 | 	/* | 
 | 	* 1. the type definition might be missing if the element was | 
 | 	*    error prone | 
 | 	* 2. it might be abstract. | 
 | 	*/ | 
 | 	goto end_elem; | 
 |     } | 
 |     /* | 
 |     * Check the content model. | 
 |     */ | 
 |     if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) || | 
 | 	(inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) { | 
 |  | 
 | 	/* | 
 | 	* Workaround for "anyType". | 
 | 	*/ | 
 | 	if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE) | 
 | 	    goto character_content; | 
 |  | 
 | 	if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) { | 
 | 	    xmlChar *values[10]; | 
 | 	    int terminal, nbval = 10, nbneg; | 
 |  | 
 | 	    if (inode->regexCtxt == NULL) { | 
 | 		/* | 
 | 		* Create the regex context. | 
 | 		*/ | 
 | 		inode->regexCtxt = | 
 | 		    xmlRegNewExecCtxt(inode->typeDef->contModel, | 
 | 		    (xmlRegExecCallbacks) xmlSchemaVContentModelCallback, | 
 | 		    vctxt); | 
 | 		if (inode->regexCtxt == NULL) { | 
 | 		    VERROR_INT("xmlSchemaValidatorPopElem", | 
 | 			"failed to create a regex context"); | 
 | 		    goto internal_error; | 
 | 		} | 
 | #ifdef DEBUG_AUTOMATA | 
 | 		xmlGenericError(xmlGenericErrorContext, | 
 | 		    "AUTOMATON create on '%s'\n", inode->localName); | 
 | #endif | 
 | 	    } | 
 | 	    /* | 
 | 	    * Get hold of the still expected content, since a further | 
 | 	    * call to xmlRegExecPushString() will loose this information. | 
 | 	    */ | 
 | 	    xmlRegExecNextValues(inode->regexCtxt, | 
 | 		&nbval, &nbneg, &values[0], &terminal); | 
 | 	    ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL); | 
 | 	    if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) { | 
 | 		/* | 
 | 		* Still missing something. | 
 | 		*/ | 
 | 		ret = 1; | 
 | 		inode->flags |= | 
 | 		    XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT; | 
 | 		xmlSchemaComplexTypeErr(ACTXT_CAST vctxt, | 
 | 		    XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL, | 
 | 		    "Missing child element(s)", | 
 | 		    nbval, nbneg, values); | 
 | #ifdef DEBUG_AUTOMATA | 
 | 		xmlGenericError(xmlGenericErrorContext, | 
 | 		    "AUTOMATON missing ERROR on '%s'\n", | 
 | 		    inode->localName); | 
 | #endif | 
 | 	    } else { | 
 | 		/* | 
 | 		* Content model is satisfied. | 
 | 		*/ | 
 | 		ret = 0; | 
 | #ifdef DEBUG_AUTOMATA | 
 | 		xmlGenericError(xmlGenericErrorContext, | 
 | 		    "AUTOMATON succeeded on '%s'\n", | 
 | 		    inode->localName); | 
 | #endif | 
 | 	    } | 
 |  | 
 | 	} | 
 |     } | 
 |     if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS) | 
 | 	goto end_elem; | 
 |  | 
 | character_content: | 
 |  | 
 |     if (vctxt->value != NULL) { | 
 | 	xmlSchemaFreeValue(vctxt->value); | 
 | 	vctxt->value = NULL; | 
 |     } | 
 |     /* | 
 |     * Check character content. | 
 |     */ | 
 |     if (inode->decl == NULL) { | 
 | 	/* | 
 | 	* Speedup if no declaration exists. | 
 | 	*/ | 
 | 	if (WXS_IS_SIMPLE(inode->typeDef)) { | 
 | 	    ret = xmlSchemaVCheckINodeDataType(vctxt, | 
 | 		inode, inode->typeDef, inode->value); | 
 | 	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) { | 
 | 	    ret = xmlSchemaVCheckINodeDataType(vctxt, | 
 | 		inode, inode->typeDef->contentTypeDef, | 
 | 		inode->value); | 
 | 	} | 
 | 	if (ret < 0) { | 
 | 	    VERROR_INT("xmlSchemaValidatorPopElem", | 
 | 		"calling xmlSchemaVCheckCVCSimpleType()"); | 
 | 	    goto internal_error; | 
 | 	} | 
 | 	goto end_elem; | 
 |     } | 
 |     /* | 
 |     * cvc-elt (3.3.4) : 5 | 
 |     * The appropriate case among the following must be true: | 
 |     */ | 
 |     /* | 
 |     * cvc-elt (3.3.4) : 5.1 | 
 |     * If the declaration has a {value constraint}, | 
 |     * the item has neither element nor character [children] and | 
 |     * clause 3.2 has not applied, then all of the following must be true: | 
 |     */ | 
 |     if ((inode->decl->value != NULL) && | 
 | 	(inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) && | 
 | 	(! INODE_NILLED(inode))) { | 
 | 	/* | 
 | 	* cvc-elt (3.3.4) : 5.1.1 | 
 | 	* If the �actual type definition� is a �local type definition� | 
 | 	* then the canonical lexical representation of the {value constraint} | 
 | 	* value must be a valid default for the �actual type definition� as | 
 | 	* defined in Element Default Valid (Immediate) (�3.3.6). | 
 | 	*/ | 
 | 	/* | 
 | 	* NOTE: 'local' above means types acquired by xsi:type. | 
 | 	* NOTE: Although the *canonical* value is stated, it is not | 
 | 	* relevant if canonical or not. Additionally XML Schema 1.1 | 
 | 	* will removed this requirement as well. | 
 | 	*/ | 
 | 	if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) { | 
 |  | 
 | 	    ret = xmlSchemaCheckCOSValidDefault(vctxt, | 
 | 		inode->decl->value, &(inode->val)); | 
 | 	    if (ret != 0) { | 
 | 		if (ret < 0) { | 
 | 		    VERROR_INT("xmlSchemaValidatorPopElem", | 
 | 			"calling xmlSchemaCheckCOSValidDefault()"); | 
 | 		    goto internal_error; | 
 | 		} | 
 | 		goto end_elem; | 
 | 	    } | 
 | 	    /* | 
 | 	    * Stop here, to avoid redundant validation of the value | 
 | 	    * (see following). | 
 | 	    */ | 
 | 	    goto default_psvi; | 
 | 	} | 
 | 	/* | 
 | 	* cvc-elt (3.3.4) : 5.1.2 | 
 | 	* The element information item with the canonical lexical | 
 | 	* representation of the {value constraint} value used as its | 
 | 	* �normalized value� must be �valid� with respect to the | 
 | 	* �actual type definition� as defined by Element Locally Valid (Type) | 
 | 	* (�3.3.4). | 
 | 	*/ | 
 | 	if (WXS_IS_SIMPLE(inode->typeDef)) { | 
 | 	    ret = xmlSchemaVCheckINodeDataType(vctxt, | 
 | 		inode, inode->typeDef, inode->decl->value); | 
 | 	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) { | 
 | 	    ret = xmlSchemaVCheckINodeDataType(vctxt, | 
 | 		inode, inode->typeDef->contentTypeDef, | 
 | 		inode->decl->value); | 
 | 	} | 
 | 	if (ret != 0) { | 
 | 	    if (ret < 0) { | 
 | 		VERROR_INT("xmlSchemaValidatorPopElem", | 
 | 		    "calling xmlSchemaVCheckCVCSimpleType()"); | 
 | 		goto internal_error; | 
 | 	    } | 
 | 	    goto end_elem; | 
 | 	} | 
 |  | 
 | default_psvi: | 
 | 	/* | 
 | 	* PSVI: Create a text node on the instance element. | 
 | 	*/ | 
 | 	if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) && | 
 | 	    (inode->node != NULL)) { | 
 | 	    xmlNodePtr textChild; | 
 | 	    xmlChar *normValue; | 
 | 	    /* | 
 | 	    * VAL TODO: Normalize the value. | 
 | 	    */ | 
 | 	    normValue = xmlSchemaNormalizeValue(inode->typeDef, | 
 | 		inode->decl->value); | 
 | 	    if (normValue != NULL) { | 
 | 		textChild = xmlNewText(BAD_CAST normValue); | 
 | 		xmlFree(normValue); | 
 | 	    } else | 
 | 		textChild = xmlNewText(inode->decl->value); | 
 | 	    if (textChild == NULL) { | 
 | 		VERROR_INT("xmlSchemaValidatorPopElem", | 
 | 		    "calling xmlNewText()"); | 
 | 		goto internal_error; | 
 | 	    } else | 
 | 		xmlAddChild(inode->node, textChild); | 
 | 	} | 
 |  | 
 |     } else if (! INODE_NILLED(inode)) { | 
 | 	/* | 
 | 	* 5.2.1 The element information item must be �valid� with respect | 
 | 	* to the �actual type definition� as defined by Element Locally | 
 | 	* Valid (Type) (�3.3.4). | 
 | 	*/ | 
 | 	if (WXS_IS_SIMPLE(inode->typeDef)) { | 
 | 	     /* | 
 | 	    * SPEC (cvc-type) (3.1) | 
 | 	    * "If the type definition is a simple type definition, ..." | 
 | 	    * (3.1.3) "If clause 3.2 of Element Locally Valid | 
 | 	    * (Element) (�3.3.4) did not apply, then the �normalized value� | 
 | 	    * must be �valid� with respect to the type definition as defined | 
 | 	    * by String Valid (�3.14.4). | 
 | 	    */ | 
 | 	    ret = xmlSchemaVCheckINodeDataType(vctxt, | 
 | 		    inode, inode->typeDef, inode->value); | 
 | 	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) { | 
 | 	    /* | 
 | 	    * SPEC (cvc-type) (3.2) "If the type definition is a complex type | 
 | 	    * definition, then the element information item must be | 
 | 	    * �valid� with respect to the type definition as per | 
 | 	    * Element Locally Valid (Complex Type) (�3.4.4);" | 
 | 	    * | 
 | 	    * SPEC (cvc-complex-type) (2.2) | 
 | 	    * "If the {content type} is a simple type definition, ... | 
 | 	    * the �normalized value� of the element information item is | 
 | 	    * �valid� with respect to that simple type definition as | 
 | 	    * defined by String Valid (�3.14.4)." | 
 | 	    */ | 
 | 	    ret = xmlSchemaVCheckINodeDataType(vctxt, | 
 | 		inode, inode->typeDef->contentTypeDef, inode->value); | 
 | 	} | 
 | 	if (ret != 0) { | 
 | 	    if (ret < 0) { | 
 | 		VERROR_INT("xmlSchemaValidatorPopElem", | 
 | 		    "calling xmlSchemaVCheckCVCSimpleType()"); | 
 | 		goto internal_error; | 
 | 	    } | 
 | 	    goto end_elem; | 
 | 	} | 
 | 	/* | 
 | 	* 5.2.2 If there is a fixed {value constraint} and clause 3.2 has | 
 | 	* not applied, all of the following must be true: | 
 | 	*/ | 
 | 	if ((inode->decl->value != NULL) && | 
 | 	    (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) { | 
 |  | 
 | 	    /* | 
 | 	    * TODO: We will need a computed value, when comparison is | 
 | 	    * done on computed values. | 
 | 	    */ | 
 | 	    /* | 
 | 	    * 5.2.2.1 The element information item must have no element | 
 | 	    * information item [children]. | 
 | 	    */ | 
 | 	    if (inode->flags & | 
 | 		    XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) { | 
 | 		ret = XML_SCHEMAV_CVC_ELT_5_2_2_1; | 
 | 		VERROR(ret, NULL, | 
 | 		    "The content must not containt element nodes since " | 
 | 		    "there is a fixed value constraint"); | 
 | 		goto end_elem; | 
 | 	    } else { | 
 | 		/* | 
 | 		* 5.2.2.2 The appropriate case among the following must | 
 | 		* be true: | 
 | 		*/ | 
 | 		if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) { | 
 | 		    /* | 
 | 		    * 5.2.2.2.1 If the {content type} of the �actual type | 
 | 		    * definition� is mixed, then the *initial value* of the | 
 | 		    * item must match the canonical lexical representation | 
 | 		    * of the {value constraint} value. | 
 | 		    * | 
 | 		    * ... the *initial value* of an element information | 
 | 		    * item is the string composed of, in order, the | 
 | 		    * [character code] of each character information item in | 
 | 		    * the [children] of that element information item. | 
 | 		    */ | 
 | 		    if (! xmlStrEqual(inode->value, inode->decl->value)){ | 
 | 			/* | 
 | 			* VAL TODO: Report invalid & expected values as well. | 
 | 			* VAL TODO: Implement the canonical stuff. | 
 | 			*/ | 
 | 			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1; | 
 | 			xmlSchemaCustomErr(ACTXT_CAST vctxt, | 
 | 			    ret, NULL, NULL, | 
 | 			    "The initial value '%s' does not match the fixed " | 
 | 			    "value constraint '%s'", | 
 | 			    inode->value, inode->decl->value); | 
 | 			goto end_elem; | 
 | 		    } | 
 | 		} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) { | 
 | 		    /* | 
 | 		    * 5.2.2.2.2 If the {content type} of the �actual type | 
 | 		    * definition� is a simple type definition, then the | 
 | 		    * *actual value* of the item must match the canonical | 
 | 		    * lexical representation of the {value constraint} value. | 
 | 		    */ | 
 | 		    /* | 
 | 		    * VAL TODO: *actual value* is the normalized value, impl. | 
 | 		    *           this. | 
 | 		    * VAL TODO: Report invalid & expected values as well. | 
 | 		    * VAL TODO: Implement a comparison with the computed values. | 
 | 		    */ | 
 | 		    if (! xmlStrEqual(inode->value, | 
 | 			    inode->decl->value)) { | 
 | 			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2; | 
 | 			xmlSchemaCustomErr(ACTXT_CAST vctxt, | 
 | 			    ret, NULL, NULL, | 
 | 			    "The actual value '%s' does not match the fixed " | 
 | 			    "value constraint '%s'", | 
 | 			    inode->value, | 
 | 			    inode->decl->value); | 
 | 			goto end_elem; | 
 | 		    } | 
 | 		} | 
 | 	    } | 
 | 	} | 
 |     } | 
 |  | 
 | end_elem: | 
 |     if (vctxt->depth < 0) { | 
 | 	/* TODO: raise error? */ | 
 | 	return (0); | 
 |     } | 
 |     if (vctxt->depth == vctxt->skipDepth) | 
 | 	vctxt->skipDepth = -1; | 
 |     /* | 
 |     * Evaluate the history of XPath state objects. | 
 |     */ | 
 |     if (inode->appliedXPath && | 
 | 	(xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)) | 
 | 	goto internal_error; | 
 |     /* | 
 |     * MAYBE TODO: | 
 |     * SPEC (6) "The element information item must be �valid� with | 
 |     * respect to each of the {identity-constraint definitions} as per | 
 |     * Identity-constraint Satisfied (�3.11.4)." | 
 |     */ | 
 |     /* | 
 |     * PSVI TODO: If we expose IDC node-tables via PSVI then the tables | 
 |     *   need to be built in any case. | 
 |     *   We will currently build IDC node-tables and bubble them only if | 
 |     *   keyrefs do exist. | 
 |     */ | 
 |  | 
 |     /* | 
 |     * Add the current IDC target-nodes to the IDC node-tables. | 
 |     */ | 
 |     if ((inode->idcMatchers != NULL) && | 
 | 	(vctxt->hasKeyrefs || vctxt->createIDCNodeTables)) | 
 |     { | 
 | 	if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1) | 
 | 	    goto internal_error; | 
 |     } | 
 |     /* | 
 |     * Validate IDC keyrefs. | 
 |     */ | 
 |     if (vctxt->inode->hasKeyrefs) | 
 | 	if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1) | 
 | 	    goto internal_error; | 
 |     /* | 
 |     * Merge/free the IDC table. | 
 |     */ | 
 |     if (inode->idcTable != NULL) { | 
 | #ifdef DEBUG_IDC_NODE_TABLE | 
 | 	xmlSchemaDebugDumpIDCTable(stdout, | 
 | 	    inode->nsName, | 
 | 	    inode->localName, | 
 | 	    inode->idcTable); | 
 | #endif | 
 | 	if ((vctxt->depth > 0) && | 
 | 	    (vctxt->hasKeyrefs || vctxt->createIDCNodeTables)) | 
 | 	{ | 
 | 	    /* | 
 | 	    * Merge the IDC node table with the table of the parent node. | 
 | 	    */ | 
 | 	    if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1) | 
 | 		goto internal_error; | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * Clear the current ielem. | 
 |     * VAL TODO: Don't free the PSVI IDC tables if they are | 
 |     * requested for the PSVI. | 
 |     */ | 
 |     xmlSchemaClearElemInfo(vctxt, inode); | 
 |     /* | 
 |     * Skip further processing if we are on the validation root. | 
 |     */ | 
 |     if (vctxt->depth == 0) { | 
 | 	vctxt->depth--; | 
 | 	vctxt->inode = NULL; | 
 | 	return (0); | 
 |     } | 
 |     /* | 
 |     * Reset the keyrefDepth if needed. | 
 |     */ | 
 |     if (vctxt->aidcs != NULL) { | 
 | 	xmlSchemaIDCAugPtr aidc = vctxt->aidcs; | 
 | 	do { | 
 | 	    if (aidc->keyrefDepth == vctxt->depth) { | 
 | 		/* | 
 | 		* A 'keyrefDepth' of a key/unique IDC matches the current | 
 | 		* depth, this means that we are leaving the scope of the | 
 | 		* top-most keyref IDC which refers to this IDC. | 
 | 		*/ | 
 | 		aidc->keyrefDepth = -1; | 
 | 	    } | 
 | 	    aidc = aidc->next; | 
 | 	} while (aidc != NULL); | 
 |     } | 
 |     vctxt->depth--; | 
 |     vctxt->inode = vctxt->elemInfos[vctxt->depth]; | 
 |     /* | 
 |     * VAL TODO: 7 If the element information item is the �validation root�, it must be | 
 |     * �valid� per Validation Root Valid (ID/IDREF) (�3.3.4). | 
 |     */ | 
 |     return (ret); | 
 |  | 
 | internal_error: | 
 |     vctxt->err = -1; | 
 |     return (-1); | 
 | } | 
 |  | 
 | /* | 
 | * 3.4.4 Complex Type Definition Validation Rules | 
 | * Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type) | 
 | */ | 
 | static int | 
 | xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt) | 
 | { | 
 |     xmlSchemaNodeInfoPtr pielem; | 
 |     xmlSchemaTypePtr ptype; | 
 |     int ret = 0; | 
 |  | 
 |     if (vctxt->depth <= 0) { | 
 | 	VERROR_INT("xmlSchemaValidateChildElem", | 
 | 	    "not intended for the validation root"); | 
 | 	return (-1); | 
 |     } | 
 |     pielem = vctxt->elemInfos[vctxt->depth -1]; | 
 |     if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) | 
 | 	pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY; | 
 |     /* | 
 |     * Handle 'nilled' elements. | 
 |     */ | 
 |     if (INODE_NILLED(pielem)) { | 
 | 	/* | 
 | 	* SPEC (cvc-elt) (3.3.4) : (3.2.1) | 
 | 	*/ | 
 | 	ACTIVATE_PARENT_ELEM; | 
 | 	ret = XML_SCHEMAV_CVC_ELT_3_2_1; | 
 | 	VERROR(ret, NULL, | 
 | 	    "Neither character nor element content is allowed, " | 
 | 	    "because the element was 'nilled'"); | 
 | 	ACTIVATE_ELEM; | 
 | 	goto unexpected_elem; | 
 |     } | 
 |  | 
 |     ptype = pielem->typeDef; | 
 |  | 
 |     if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) { | 
 | 	/* | 
 | 	* Workaround for "anyType": we have currently no content model | 
 | 	* assigned for "anyType", so handle it explicitely. | 
 | 	* "anyType" has an unbounded, lax "any" wildcard. | 
 | 	*/ | 
 | 	vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema, | 
 | 	    vctxt->inode->localName, | 
 | 	    vctxt->inode->nsName); | 
 |  | 
 | 	if (vctxt->inode->decl == NULL) { | 
 | 	    xmlSchemaAttrInfoPtr iattr; | 
 | 	    /* | 
 | 	    * Process "xsi:type". | 
 | 	    * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3) | 
 | 	    */ | 
 | 	    iattr = xmlSchemaGetMetaAttrInfo(vctxt, | 
 | 		XML_SCHEMA_ATTR_INFO_META_XSI_TYPE); | 
 | 	    if (iattr != NULL) { | 
 | 		ret = xmlSchemaProcessXSIType(vctxt, iattr, | 
 | 		    &(vctxt->inode->typeDef), NULL); | 
 | 		if (ret != 0) { | 
 | 		    if (ret == -1) { | 
 | 			VERROR_INT("xmlSchemaValidateChildElem", | 
 | 			    "calling xmlSchemaProcessXSIType() to " | 
 | 			    "process the attribute 'xsi:nil'"); | 
 | 			return (-1); | 
 | 		    } | 
 | 		    return (ret); | 
 | 		} | 
 | 	    } else { | 
 | 		 /* | 
 | 		 * Fallback to "anyType". | 
 | 		 * | 
 | 		 * SPEC (cvc-assess-elt) | 
 | 		 * "If the item cannot be �strictly assessed�, [...] | 
 | 		 * an element information item's schema validity may be laxly | 
 | 		 * assessed if its �context-determined declaration� is not | 
 | 		 * skip by �validating� with respect to the �ur-type | 
 | 		 * definition� as per Element Locally Valid (Type) (�3.3.4)." | 
 | 		*/ | 
 | 		vctxt->inode->typeDef = | 
 | 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE); | 
 | 	    } | 
 | 	} | 
 | 	return (0); | 
 |     } | 
 |  | 
 |     switch (ptype->contentType) { | 
 | 	case XML_SCHEMA_CONTENT_EMPTY: | 
 | 	    /* | 
 | 	    * SPEC (2.1) "If the {content type} is empty, then the | 
 | 	    * element information item has no character or element | 
 | 	    * information item [children]." | 
 | 	    */ | 
 | 	    ACTIVATE_PARENT_ELEM | 
 | 	    ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1; | 
 | 	    VERROR(ret, NULL, | 
 | 		"Element content is not allowed, " | 
 | 		"because the content type is empty"); | 
 | 	    ACTIVATE_ELEM | 
 | 	    goto unexpected_elem; | 
 | 	    break; | 
 |  | 
 | 	case XML_SCHEMA_CONTENT_MIXED: | 
 |         case XML_SCHEMA_CONTENT_ELEMENTS: { | 
 | 	    xmlRegExecCtxtPtr regexCtxt; | 
 | 	    xmlChar *values[10]; | 
 | 	    int terminal, nbval = 10, nbneg; | 
 |  | 
 | 	    /* VAL TODO: Optimized "anyType" validation.*/ | 
 |  | 
 | 	    if (ptype->contModel == NULL) { | 
 | 		VERROR_INT("xmlSchemaValidateChildElem", | 
 | 		    "type has elem content but no content model"); | 
 | 		return (-1); | 
 | 	    } | 
 | 	    /* | 
 | 	    * Safety belf for evaluation if the cont. model was already | 
 | 	    * examined to be invalid. | 
 | 	    */ | 
 | 	    if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) { | 
 | 		VERROR_INT("xmlSchemaValidateChildElem", | 
 | 		    "validating elem, but elem content is already invalid"); | 
 | 		return (-1); | 
 | 	    } | 
 |  | 
 | 	    regexCtxt = pielem->regexCtxt; | 
 | 	    if (regexCtxt == NULL) { | 
 | 		/* | 
 | 		* Create the regex context. | 
 | 		*/ | 
 | 		regexCtxt = xmlRegNewExecCtxt(ptype->contModel, | 
 | 		    (xmlRegExecCallbacks) xmlSchemaVContentModelCallback, | 
 | 		    vctxt); | 
 | 		if (regexCtxt == NULL) { | 
 | 		    VERROR_INT("xmlSchemaValidateChildElem", | 
 | 			"failed to create a regex context"); | 
 | 		    return (-1); | 
 | 		} | 
 | 		pielem->regexCtxt = regexCtxt; | 
 | #ifdef DEBUG_AUTOMATA | 
 | 		xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n", | 
 | 		    pielem->localName); | 
 | #endif | 
 | 	    } | 
 |  | 
 | 	    /* | 
 | 	    * SPEC (2.4) "If the {content type} is element-only or mixed, | 
 | 	    * then the sequence of the element information item's | 
 | 	    * element information item [children], if any, taken in | 
 | 	    * order, is �valid� with respect to the {content type}'s | 
 | 	    * particle, as defined in Element Sequence Locally Valid | 
 | 	    * (Particle) (�3.9.4)." | 
 | 	    */ | 
 | 	    ret = xmlRegExecPushString2(regexCtxt, | 
 | 		vctxt->inode->localName, | 
 | 		vctxt->inode->nsName, | 
 | 		vctxt->inode); | 
 | #ifdef DEBUG_AUTOMATA | 
 | 	    if (ret < 0) | 
 | 		xmlGenericError(xmlGenericErrorContext, | 
 | 		"AUTOMATON push ERROR for '%s' on '%s'\n", | 
 | 		vctxt->inode->localName, pielem->localName); | 
 | 	    else | 
 | 		xmlGenericError(xmlGenericErrorContext, | 
 | 		"AUTOMATON push OK for '%s' on '%s'\n", | 
 | 		vctxt->inode->localName, pielem->localName); | 
 | #endif | 
 | 	    if (vctxt->err == XML_SCHEMAV_INTERNAL) { | 
 | 		VERROR_INT("xmlSchemaValidateChildElem", | 
 | 		    "calling xmlRegExecPushString2()"); | 
 | 		return (-1); | 
 | 	    } | 
 | 	    if (ret < 0) { | 
 | 		xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg, | 
 | 		    &values[0], &terminal); | 
 | 		xmlSchemaComplexTypeErr(ACTXT_CAST vctxt, | 
 | 		    XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL, | 
 | 		    "This element is not expected", | 
 | 		    nbval, nbneg, values); | 
 | 		ret = vctxt->err; | 
 | 		goto unexpected_elem; | 
 | 	    } else | 
 | 		ret = 0; | 
 | 	} | 
 | 	    break; | 
 | 	case XML_SCHEMA_CONTENT_SIMPLE: | 
 | 	case XML_SCHEMA_CONTENT_BASIC: | 
 | 	    ACTIVATE_PARENT_ELEM | 
 | 	    if (WXS_IS_COMPLEX(ptype)) { | 
 | 		/* | 
 | 		* SPEC (cvc-complex-type) (2.2) | 
 | 		* "If the {content type} is a simple type definition, then | 
 | 		* the element information item has no element information | 
 | 		* item [children], ..." | 
 | 		*/ | 
 | 		ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2; | 
 | 		VERROR(ret, NULL, "Element content is not allowed, " | 
 | 		    "because the content type is a simple type definition"); | 
 | 	    } else { | 
 | 		/* | 
 | 		* SPEC (cvc-type) (3.1.2) "The element information item must | 
 | 		* have no element information item [children]." | 
 | 		*/ | 
 | 		ret = XML_SCHEMAV_CVC_TYPE_3_1_2; | 
 | 		VERROR(ret, NULL, "Element content is not allowed, " | 
 | 		    "because the type definition is simple"); | 
 | 	    } | 
 | 	    ACTIVATE_ELEM | 
 | 	    ret = vctxt->err; | 
 | 	    goto unexpected_elem; | 
 | 	    break; | 
 |  | 
 | 	default: | 
 | 	    break; | 
 |     } | 
 |     return (ret); | 
 | unexpected_elem: | 
 |     /* | 
 |     * Pop this element and set the skipDepth to skip | 
 |     * all further content of the parent element. | 
 |     */ | 
 |     vctxt->skipDepth = vctxt->depth; | 
 |     vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED; | 
 |     pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT; | 
 |     return (ret); | 
 | } | 
 |  | 
 | #define XML_SCHEMA_PUSH_TEXT_PERSIST 1 | 
 | #define XML_SCHEMA_PUSH_TEXT_CREATED 2 | 
 | #define XML_SCHEMA_PUSH_TEXT_VOLATILE 3 | 
 |  | 
 | static int | 
 | xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt, | 
 | 		  int nodeType, const xmlChar *value, int len, | 
 | 		  int mode, int *consumed) | 
 | { | 
 |     /* | 
 |     * Unfortunately we have to duplicate the text sometimes. | 
 |     * OPTIMIZE: Maybe we could skip it, if: | 
 |     *   1. content type is simple | 
 |     *   2. whitespace is "collapse" | 
 |     *   3. it consists of whitespace only | 
 |     * | 
 |     * Process character content. | 
 |     */ | 
 |     if (consumed != NULL) | 
 | 	*consumed = 0; | 
 |     if (INODE_NILLED(vctxt->inode)) { | 
 | 	/* | 
 | 	* SPEC cvc-elt (3.3.4 - 3.2.1) | 
 | 	* "The element information item must have no character or | 
 | 	* element information item [children]." | 
 | 	*/ | 
 | 	VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL, | 
 | 	    "Neither character nor element content is allowed " | 
 | 	    "because the element is 'nilled'"); | 
 | 	return (vctxt->err); | 
 |     } | 
 |     /* | 
 |     * SPEC (2.1) "If the {content type} is empty, then the | 
 |     * element information item has no character or element | 
 |     * information item [children]." | 
 |     */ | 
 |     if (vctxt->inode->typeDef->contentType == | 
 | 	    XML_SCHEMA_CONTENT_EMPTY) { | 
 | 	VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL, | 
 | 	    "Character content is not allowed, " | 
 | 	    "because the content type is empty"); | 
 | 	return (vctxt->err); | 
 |     } | 
 |  | 
 |     if (vctxt->inode->typeDef->contentType == | 
 | 	    XML_SCHEMA_CONTENT_ELEMENTS) { | 
 | 	if ((nodeType != XML_TEXT_NODE) || | 
 | 	    (! xmlSchemaIsBlank((xmlChar *) value, len))) { | 
 | 	    /* | 
 | 	    * SPEC cvc-complex-type (2.3) | 
 | 	    * "If the {content type} is element-only, then the | 
 | 	    * element information item has no character information | 
 | 	    * item [children] other than those whose [character | 
 | 	    * code] is defined as a white space in [XML 1.0 (Second | 
 | 	    * Edition)]." | 
 | 	    */ | 
 | 	    VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL, | 
 | 		"Character content other than whitespace is not allowed " | 
 | 		"because the content type is 'element-only'"); | 
 | 	    return (vctxt->err); | 
 | 	} | 
 | 	return (0); | 
 |     } | 
 |  | 
 |     if ((value == NULL) || (value[0] == 0)) | 
 | 	return (0); | 
 |     /* | 
 |     * Save the value. | 
 |     * NOTE that even if the content type is *mixed*, we need the | 
 |     * *initial value* for default/fixed value constraints. | 
 |     */ | 
 |     if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) && | 
 | 	((vctxt->inode->decl == NULL) || | 
 | 	(vctxt->inode->decl->value == NULL))) | 
 | 	return (0); | 
 |  | 
 |     if (vctxt->inode->value == NULL) { | 
 | 	/* | 
 | 	* Set the value. | 
 | 	*/ | 
 | 	switch (mode) { | 
 | 	    case XML_SCHEMA_PUSH_TEXT_PERSIST: | 
 | 		/* | 
 | 		* When working on a tree. | 
 | 		*/ | 
 | 		vctxt->inode->value = value; | 
 | 		break; | 
 | 	    case XML_SCHEMA_PUSH_TEXT_CREATED: | 
 | 		/* | 
 | 		* When working with the reader. | 
 | 		* The value will be freed by the element info. | 
 | 		*/ | 
 | 		vctxt->inode->value = value; | 
 | 		if (consumed != NULL) | 
 | 		    *consumed = 1; | 
 | 		vctxt->inode->flags |= | 
 | 		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES; | 
 | 		break; | 
 | 	    case XML_SCHEMA_PUSH_TEXT_VOLATILE: | 
 | 		/* | 
 | 		* When working with SAX. | 
 | 		* The value will be freed by the element info. | 
 | 		*/ | 
 | 		if (len != -1) | 
 | 		    vctxt->inode->value = BAD_CAST xmlStrndup(value, len); | 
 | 		else | 
 | 		    vctxt->inode->value = BAD_CAST xmlStrdup(value); | 
 | 		vctxt->inode->flags |= | 
 | 		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES; | 
 | 		break; | 
 | 	    default: | 
 | 		break; | 
 | 	} | 
 |     } else { | 
 | 	if (len < 0) | 
 | 	    len = xmlStrlen(value); | 
 | 	/* | 
 | 	* Concat the value. | 
 | 	*/ | 
 | 	if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) { | 
 | 	    vctxt->inode->value = BAD_CAST xmlStrncat( | 
 | 		(xmlChar *) vctxt->inode->value, value, len); | 
 | 	} else { | 
 | 	    vctxt->inode->value = | 
 | 		BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len); | 
 | 	    vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES; | 
 | 	} | 
 |     } | 
 |  | 
 |     return (0); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt) | 
 | { | 
 |     int ret = 0; | 
 |  | 
 |     if ((vctxt->skipDepth != -1) && | 
 | 	(vctxt->depth >= vctxt->skipDepth)) { | 
 | 	VERROR_INT("xmlSchemaValidateElem", | 
 | 	    "in skip-state"); | 
 | 	goto internal_error; | 
 |     } | 
 |     if (vctxt->xsiAssemble) { | 
 | 	/* | 
 | 	* We will stop validation if there was an error during | 
 | 	* dynamic schema construction. | 
 | 	* Note that we simply set @skipDepth to 0, this could | 
 | 	* mean that a streaming document via SAX would be | 
 | 	* still read to the end but it won't be validated any more. | 
 | 	* TODO: If we are sure how to stop the validation at once | 
 | 	*   for all input scenarios, then this should be changed to | 
 | 	*   instantly stop the validation. | 
 | 	*/ | 
 | 	ret = xmlSchemaAssembleByXSI(vctxt); | 
 | 	if (ret != 0) { | 
 | 	    if (ret == -1) | 
 | 		goto internal_error; | 
 | 	    vctxt->skipDepth = 0; | 
 | 	    return(ret); | 
 | 	} | 
 |     } | 
 |     if (vctxt->depth > 0) { | 
 | 	/* | 
 | 	* Validate this element against the content model | 
 | 	* of the parent. | 
 | 	*/ | 
 | 	ret = xmlSchemaValidateChildElem(vctxt); | 
 | 	if (ret != 0) { | 
 | 	    if (ret < 0) { | 
 | 		VERROR_INT("xmlSchemaValidateElem", | 
 | 		    "calling xmlSchemaStreamValidateChildElement()"); | 
 | 		goto internal_error; | 
 | 	    } | 
 | 	    goto exit; | 
 | 	} | 
 | 	if (vctxt->depth == vctxt->skipDepth) | 
 | 	    goto exit; | 
 | 	if ((vctxt->inode->decl == NULL) && | 
 | 	    (vctxt->inode->typeDef == NULL)) { | 
 | 	    VERROR_INT("xmlSchemaValidateElem", | 
 | 		"the child element was valid but neither the " | 
 | 		"declaration nor the type was set"); | 
 | 	    goto internal_error; | 
 | 	} | 
 |     } else { | 
 | 	/* | 
 | 	* Get the declaration of the validation root. | 
 | 	*/ | 
 | 	vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema, | 
 | 	    vctxt->inode->localName, | 
 | 	    vctxt->inode->nsName); | 
 | 	if (vctxt->inode->decl == NULL) { | 
 | 	    ret = XML_SCHEMAV_CVC_ELT_1; | 
 | 	    VERROR(ret, NULL, | 
 | 		"No matching global declaration available " | 
 | 		"for the validation root"); | 
 | 	    goto exit; | 
 | 	} | 
 |     } | 
 |  | 
 |     if (vctxt->inode->decl == NULL) | 
 | 	goto type_validation; | 
 |  | 
 |     if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) { | 
 | 	int skip; | 
 | 	/* | 
 | 	* Wildcards. | 
 | 	*/ | 
 | 	ret = xmlSchemaValidateElemWildcard(vctxt, &skip); | 
 | 	if (ret != 0) { | 
 | 	    if (ret < 0) { | 
 | 		VERROR_INT("xmlSchemaValidateElem", | 
 | 		    "calling xmlSchemaValidateElemWildcard()"); | 
 | 		goto internal_error; | 
 | 	    } | 
 | 	    goto exit; | 
 | 	} | 
 | 	if (skip) { | 
 | 	    vctxt->skipDepth = vctxt->depth; | 
 | 	    goto exit; | 
 | 	} | 
 | 	/* | 
 | 	* The declaration might be set by the wildcard validation, | 
 | 	* when the processContents is "lax" or "strict". | 
 | 	*/ | 
 | 	if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) { | 
 | 	    /* | 
 | 	    * Clear the "decl" field to not confuse further processing. | 
 | 	    */ | 
 | 	    vctxt->inode->decl = NULL; | 
 | 	    goto type_validation; | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * Validate against the declaration. | 
 |     */ | 
 |     ret = xmlSchemaValidateElemDecl(vctxt); | 
 |     if (ret != 0) { | 
 | 	if (ret < 0) { | 
 | 	    VERROR_INT("xmlSchemaValidateElem", | 
 | 		"calling xmlSchemaValidateElemDecl()"); | 
 | 	    goto internal_error; | 
 | 	} | 
 | 	goto exit; | 
 |     } | 
 |     /* | 
 |     * Validate against the type definition. | 
 |     */ | 
 | type_validation: | 
 |  | 
 |     if (vctxt->inode->typeDef == NULL) { | 
 | 	vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE; | 
 | 	ret = XML_SCHEMAV_CVC_TYPE_1; | 
 |     	VERROR(ret, NULL, | 
 |     	    "The type definition is absent"); | 
 | 	goto exit; | 
 |     } | 
 |     if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) { | 
 | 	vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE; | 
 | 	ret = XML_SCHEMAV_CVC_TYPE_2; | 
 |     	    VERROR(ret, NULL, | 
 |     	    "The type definition is abstract"); | 
 | 	goto exit; | 
 |     } | 
 |     /* | 
 |     * Evaluate IDCs. Do it here, since new IDC matchers are registered | 
 |     * during validation against the declaration. This must be done | 
 |     * _before_ attribute validation. | 
 |     */ | 
 |     if (vctxt->xpathStates != NULL) { | 
 | 	ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE); | 
 | 	vctxt->inode->appliedXPath = 1; | 
 | 	if (ret == -1) { | 
 | 	    VERROR_INT("xmlSchemaValidateElem", | 
 | 		"calling xmlSchemaXPathEvaluate()"); | 
 | 	    goto internal_error; | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * Validate attributes. | 
 |     */ | 
 |     if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) { | 
 | 	if ((vctxt->nbAttrInfos != 0) || | 
 | 	    (vctxt->inode->typeDef->attrUses != NULL)) { | 
 |  | 
 | 	    ret = xmlSchemaVAttributesComplex(vctxt); | 
 | 	} | 
 |     } else if (vctxt->nbAttrInfos != 0) { | 
 |  | 
 | 	ret = xmlSchemaVAttributesSimple(vctxt); | 
 |     } | 
 |     /* | 
 |     * Clear registered attributes. | 
 |     */ | 
 |     if (vctxt->nbAttrInfos != 0) | 
 | 	xmlSchemaClearAttrInfos(vctxt); | 
 |     if (ret == -1) { | 
 | 	VERROR_INT("xmlSchemaValidateElem", | 
 | 	    "calling attributes validation"); | 
 | 	goto internal_error; | 
 |     } | 
 |     /* | 
 |     * Don't return an error if attributes are invalid on purpose. | 
 |     */ | 
 |     ret = 0; | 
 |  | 
 | exit: | 
 |     if (ret != 0) | 
 | 	vctxt->skipDepth = vctxt->depth; | 
 |     return (ret); | 
 | internal_error: | 
 |     return (-1); | 
 | } | 
 |  | 
 | #ifdef XML_SCHEMA_READER_ENABLED | 
 | static int | 
 | xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt) | 
 | { | 
 |     const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15; | 
 |     int depth, nodeType, ret = 0, consumed; | 
 |     xmlSchemaNodeInfoPtr ielem; | 
 |  | 
 |     vctxt->depth = -1; | 
 |     ret = xmlTextReaderRead(vctxt->reader); | 
 |     /* | 
 |     * Move to the document element. | 
 |     */ | 
 |     while (ret == 1) { | 
 | 	nodeType = xmlTextReaderNodeType(vctxt->reader); | 
 | 	if (nodeType == XML_ELEMENT_NODE) | 
 | 	    goto root_found; | 
 | 	ret = xmlTextReaderRead(vctxt->reader); | 
 |     } | 
 |     goto exit; | 
 |  | 
 | root_found: | 
 |  | 
 |     do { | 
 | 	depth = xmlTextReaderDepth(vctxt->reader); | 
 | 	nodeType = xmlTextReaderNodeType(vctxt->reader); | 
 |  | 
 | 	if (nodeType == XML_ELEMENT_NODE) { | 
 |  | 
 | 	    vctxt->depth++; | 
 | 	    if (xmlSchemaValidatorPushElem(vctxt) == -1) { | 
 | 		VERROR_INT("xmlSchemaVReaderWalk", | 
 | 		    "calling xmlSchemaValidatorPushElem()"); | 
 | 		goto internal_error; | 
 | 	    } | 
 | 	    ielem = vctxt->inode; | 
 | 	    ielem->localName = xmlTextReaderLocalName(vctxt->reader); | 
 | 	    ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader); | 
 | 	    ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES; | 
 | 	    /* | 
 | 	    * Is the element empty? | 
 | 	    */ | 
 | 	    ret = xmlTextReaderIsEmptyElement(vctxt->reader); | 
 | 	    if (ret == -1) { | 
 | 		VERROR_INT("xmlSchemaVReaderWalk", | 
 | 		    "calling xmlTextReaderIsEmptyElement()"); | 
 | 		goto internal_error; | 
 | 	    } | 
 | 	    if (ret) { | 
 | 		ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY; | 
 | 	    } | 
 | 	    /* | 
 | 	    * Register attributes. | 
 | 	    */ | 
 | 	    vctxt->nbAttrInfos = 0; | 
 | 	    ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader); | 
 | 	    if (ret == -1) { | 
 | 		VERROR_INT("xmlSchemaVReaderWalk", | 
 | 		    "calling xmlTextReaderMoveToFirstAttribute()"); | 
 | 		goto internal_error; | 
 | 	    } | 
 | 	    if (ret == 1) { | 
 | 		do { | 
 | 		    /* | 
 | 		    * VAL TODO: How do we know that the reader works on a | 
 | 		    * node tree, to be able to pass a node here? | 
 | 		    */ | 
 | 		    if (xmlSchemaValidatorPushAttribute(vctxt, NULL, | 
 | 			(const xmlChar *) xmlTextReaderLocalName(vctxt->reader), | 
 | 			xmlTextReaderNamespaceUri(vctxt->reader), 1, | 
 | 			xmlTextReaderValue(vctxt->reader), 1) == -1) { | 
 |  | 
 | 			VERROR_INT("xmlSchemaVReaderWalk", | 
 | 			    "calling xmlSchemaValidatorPushAttribute()"); | 
 | 			goto internal_error; | 
 | 		    } | 
 | 		    ret = xmlTextReaderMoveToNextAttribute(vctxt->reader); | 
 | 		    if (ret == -1) { | 
 | 			VERROR_INT("xmlSchemaVReaderWalk", | 
 | 			    "calling xmlTextReaderMoveToFirstAttribute()"); | 
 | 			goto internal_error; | 
 | 		    } | 
 | 		} while (ret == 1); | 
 | 		/* | 
 | 		* Back to element position. | 
 | 		*/ | 
 | 		ret = xmlTextReaderMoveToElement(vctxt->reader); | 
 | 		if (ret == -1) { | 
 | 		    VERROR_INT("xmlSchemaVReaderWalk", | 
 | 			"calling xmlTextReaderMoveToElement()"); | 
 | 		    goto internal_error; | 
 | 		} | 
 | 	    } | 
 | 	    /* | 
 | 	    * Validate the element. | 
 | 	    */ | 
 | 	    ret= xmlSchemaValidateElem(vctxt); | 
 | 	    if (ret != 0) { | 
 | 		if (ret == -1) { | 
 | 		    VERROR_INT("xmlSchemaVReaderWalk", | 
 | 			"calling xmlSchemaValidateElem()"); | 
 | 		    goto internal_error; | 
 | 		} | 
 | 		goto exit; | 
 | 	    } | 
 | 	    if (vctxt->depth == vctxt->skipDepth) { | 
 | 		int curDepth; | 
 | 		/* | 
 | 		* Skip all content. | 
 | 		*/ | 
 | 		if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) { | 
 | 		    ret = xmlTextReaderRead(vctxt->reader); | 
 | 		    curDepth = xmlTextReaderDepth(vctxt->reader); | 
 | 		    while ((ret == 1) && (curDepth != depth)) { | 
 | 			ret = xmlTextReaderRead(vctxt->reader); | 
 | 			curDepth = xmlTextReaderDepth(vctxt->reader); | 
 | 		    } | 
 | 		    if (ret < 0) { | 
 | 			/* | 
 | 			* VAL TODO: A reader error occured; what to do here? | 
 | 			*/ | 
 | 			ret = 1; | 
 | 			goto exit; | 
 | 		    } | 
 | 		} | 
 | 		goto leave_elem; | 
 | 	    } | 
 | 	    /* | 
 | 	    * READER VAL TODO: Is an END_ELEM really never called | 
 | 	    * if the elem is empty? | 
 | 	    */ | 
 | 	    if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) | 
 | 		goto leave_elem; | 
 | 	} else if (nodeType == END_ELEM) { | 
 | 	    /* | 
 | 	    * Process END of element. | 
 | 	    */ | 
 | leave_elem: | 
 | 	    ret = xmlSchemaValidatorPopElem(vctxt); | 
 | 	    if (ret != 0) { | 
 | 		if (ret < 0) { | 
 | 		    VERROR_INT("xmlSchemaVReaderWalk", | 
 | 			"calling xmlSchemaValidatorPopElem()"); | 
 | 		    goto internal_error; | 
 | 		} | 
 | 		goto exit; | 
 | 	    } | 
 | 	    if (vctxt->depth >= 0) | 
 | 		ielem = vctxt->inode; | 
 | 	    else | 
 | 		ielem = NULL; | 
 | 	} else if ((nodeType == XML_TEXT_NODE) || | 
 | 	    (nodeType == XML_CDATA_SECTION_NODE) || | 
 | 	    (nodeType == WHTSP) || | 
 | 	    (nodeType == SIGN_WHTSP)) { | 
 | 	    /* | 
 | 	    * Process character content. | 
 | 	    */ | 
 | 	    xmlChar *value; | 
 |  | 
 | 	    if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP)) | 
 | 		nodeType = XML_TEXT_NODE; | 
 |  | 
 | 	    value = xmlTextReaderValue(vctxt->reader); | 
 | 	    ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value, | 
 | 		-1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed); | 
 | 	    if (! consumed) | 
 | 		xmlFree(value); | 
 | 	    if (ret == -1) { | 
 | 		VERROR_INT("xmlSchemaVReaderWalk", | 
 | 		    "calling xmlSchemaVPushText()"); | 
 | 		goto internal_error; | 
 | 	    } | 
 | 	} else if ((nodeType == XML_ENTITY_NODE) || | 
 | 	    (nodeType == XML_ENTITY_REF_NODE)) { | 
 | 	    /* | 
 | 	    * VAL TODO: What to do with entities? | 
 | 	    */ | 
 | 	    TODO | 
 | 	} | 
 | 	/* | 
 | 	* Read next node. | 
 | 	*/ | 
 | 	ret = xmlTextReaderRead(vctxt->reader); | 
 |     } while (ret == 1); | 
 |  | 
 | exit: | 
 |     return (ret); | 
 | internal_error: | 
 |     return (-1); | 
 | } | 
 | #endif | 
 |  | 
 | /************************************************************************ | 
 |  * 									* | 
 |  * 			SAX validation handlers				* | 
 |  * 									* | 
 |  ************************************************************************/ | 
 |  | 
 | /* | 
 | * Process text content. | 
 | */ | 
 | static void | 
 | xmlSchemaSAXHandleText(void *ctx, | 
 | 		       const xmlChar * ch, | 
 | 		       int len) | 
 | { | 
 |     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx; | 
 |  | 
 |     if (vctxt->depth < 0) | 
 | 	return; | 
 |     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth)) | 
 | 	return; | 
 |     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) | 
 | 	vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY; | 
 |     if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len, | 
 | 	XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) { | 
 | 	VERROR_INT("xmlSchemaSAXHandleCDataSection", | 
 | 	    "calling xmlSchemaVPushText()"); | 
 | 	vctxt->err = -1; | 
 | 	xmlStopParser(vctxt->parserCtxt); | 
 |     } | 
 | } | 
 |  | 
 | /* | 
 | * Process CDATA content. | 
 | */ | 
 | static void | 
 | xmlSchemaSAXHandleCDataSection(void *ctx, | 
 | 			     const xmlChar * ch, | 
 | 			     int len) | 
 | { | 
 |     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx; | 
 |  | 
 |     if (vctxt->depth < 0) | 
 | 	return; | 
 |     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth)) | 
 | 	return; | 
 |     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) | 
 | 	vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY; | 
 |     if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len, | 
 | 	XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) { | 
 | 	VERROR_INT("xmlSchemaSAXHandleCDataSection", | 
 | 	    "calling xmlSchemaVPushText()"); | 
 | 	vctxt->err = -1; | 
 | 	xmlStopParser(vctxt->parserCtxt); | 
 |     } | 
 | } | 
 |  | 
 | static void | 
 | xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED, | 
 | 			    const xmlChar * name ATTRIBUTE_UNUSED) | 
 | { | 
 |     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx; | 
 |  | 
 |     if (vctxt->depth < 0) | 
 | 	return; | 
 |     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth)) | 
 | 	return; | 
 |     /* SAX VAL TODO: What to do here? */ | 
 |     TODO | 
 | } | 
 |  | 
 | static void | 
 | xmlSchemaSAXHandleStartElementNs(void *ctx, | 
 | 				 const xmlChar * localname, | 
 | 				 const xmlChar * prefix ATTRIBUTE_UNUSED, | 
 | 				 const xmlChar * URI, | 
 | 				 int nb_namespaces, | 
 | 				 const xmlChar ** namespaces, | 
 | 				 int nb_attributes, | 
 | 				 int nb_defaulted ATTRIBUTE_UNUSED, | 
 | 				 const xmlChar ** attributes) | 
 | { | 
 |     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx; | 
 |     int ret; | 
 |     xmlSchemaNodeInfoPtr ielem; | 
 |     int i, j; | 
 |  | 
 |     /* | 
 |     * SAX VAL TODO: What to do with nb_defaulted? | 
 |     */ | 
 |     /* | 
 |     * Skip elements if inside a "skip" wildcard or invalid. | 
 |     */ | 
 |     vctxt->depth++; | 
 |     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth)) | 
 | 	return; | 
 |     /* | 
 |     * Push the element. | 
 |     */ | 
 |     if (xmlSchemaValidatorPushElem(vctxt) == -1) { | 
 | 	VERROR_INT("xmlSchemaSAXHandleStartElementNs", | 
 | 	    "calling xmlSchemaValidatorPushElem()"); | 
 | 	goto internal_error; | 
 |     } | 
 |     ielem = vctxt->inode; | 
 |     /* | 
 |     * TODO: Is this OK? | 
 |     */ | 
 |     ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt); | 
 |     ielem->localName = localname; | 
 |     ielem->nsName = URI; | 
 |     ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY; | 
 |     /* | 
 |     * Register namespaces on the elem info. | 
 |     */ | 
 |     if (nb_namespaces != 0) { | 
 | 	/* | 
 | 	* Although the parser builds its own namespace list, | 
 | 	* we have no access to it, so we'll use an own one. | 
 | 	*/ | 
 |         for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) { | 
 | 	    /* | 
 | 	    * Store prefix and namespace name. | 
 | 	    */ | 
 | 	    if (ielem->nsBindings == NULL) { | 
 | 		ielem->nsBindings = | 
 | 		    (const xmlChar **) xmlMalloc(10 * | 
 | 			sizeof(const xmlChar *)); | 
 | 		if (ielem->nsBindings == NULL) { | 
 | 		    xmlSchemaVErrMemory(vctxt, | 
 | 			"allocating namespace bindings for SAX validation", | 
 | 			NULL); | 
 | 		    goto internal_error; | 
 | 		} | 
 | 		ielem->nbNsBindings = 0; | 
 | 		ielem->sizeNsBindings = 5; | 
 | 	    } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) { | 
 | 		ielem->sizeNsBindings *= 2; | 
 | 		ielem->nsBindings = | 
 | 		    (const xmlChar **) xmlRealloc( | 
 | 			(void *) ielem->nsBindings, | 
 | 			ielem->sizeNsBindings * 2 * sizeof(const xmlChar *)); | 
 | 		if (ielem->nsBindings == NULL) { | 
 | 		    xmlSchemaVErrMemory(vctxt, | 
 | 			"re-allocating namespace bindings for SAX validation", | 
 | 			NULL); | 
 | 		    goto internal_error; | 
 | 		} | 
 | 	    } | 
 |  | 
 | 	    ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j]; | 
 | 	    if (namespaces[j+1][0] == 0) { | 
 | 		/* | 
 | 		* Handle xmlns="". | 
 | 		*/ | 
 | 		ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL; | 
 | 	    } else | 
 | 		ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = | 
 | 		    namespaces[j+1]; | 
 | 	    ielem->nbNsBindings++; | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * Register attributes. | 
 |     * SAX VAL TODO: We are not adding namespace declaration | 
 |     * attributes yet. | 
 |     */ | 
 |     if (nb_attributes != 0) { | 
 | 	xmlChar *value; | 
 |  | 
 |         for (j = 0, i = 0; i < nb_attributes; i++, j += 5) { | 
 | 	    /* | 
 | 	    * Duplicate the value. | 
 | 	    */ | 
 | 	    value = xmlStrndup(attributes[j+3], | 
 | 		attributes[j+4] - attributes[j+3]); | 
 | 	    /* | 
 | 	    * TODO: Set the node line. | 
 | 	    */ | 
 | 	    ret = xmlSchemaValidatorPushAttribute(vctxt, | 
 | 		NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0, | 
 | 		value, 1); | 
 | 	    if (ret == -1) { | 
 | 		VERROR_INT("xmlSchemaSAXHandleStartElementNs", | 
 | 		    "calling xmlSchemaValidatorPushAttribute()"); | 
 | 		goto internal_error; | 
 | 	    } | 
 | 	} | 
 |     } | 
 |     /* | 
 |     * Validate the element. | 
 |     */ | 
 |     ret = xmlSchemaValidateElem(vctxt); | 
 |     if (ret != 0) { | 
 | 	if (ret == -1) { | 
 | 	    VERROR_INT("xmlSchemaSAXHandleStartElementNs", | 
 | 		"calling xmlSchemaValidateElem()"); | 
 | 	    goto internal_error; | 
 | 	} | 
 | 	goto exit; | 
 |     } | 
 |  | 
 | exit: | 
 |     return; | 
 | internal_error: | 
 |     vctxt->err = -1; | 
 |     xmlStopParser(vctxt->parserCtxt); | 
 |     return; | 
 | } | 
 |  | 
 | static void | 
 | xmlSchemaSAXHandleEndElementNs(void *ctx, | 
 | 			       const xmlChar * localname ATTRIBUTE_UNUSED, | 
 | 			       const xmlChar * prefix ATTRIBUTE_UNUSED, | 
 | 			       const xmlChar * URI ATTRIBUTE_UNUSED) | 
 | { | 
 |     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx; | 
 |     int res; | 
 |  | 
 |     /* | 
 |     * Skip elements if inside a "skip" wildcard or if invalid. | 
 |     */ | 
 |     if (vctxt->skipDepth != -1) { | 
 | 	if (vctxt->depth > vctxt->skipDepth) { | 
 | 	    vctxt->depth--; | 
 | 	    return; | 
 | 	} else | 
 | 	    vctxt->skipDepth = -1; | 
 |     } | 
 |     /* | 
 |     * SAX VAL TODO: Just a temporary check. | 
 |     */ | 
 |     if ((!xmlStrEqual(vctxt->inode->localName, localname)) || | 
 | 	(!xmlStrEqual(vctxt->inode->nsName, URI))) { | 
 | 	VERROR_INT("xmlSchemaSAXHandleEndElementNs", | 
 | 	    "elem pop mismatch"); | 
 |     } | 
 |     res = xmlSchemaValidatorPopElem(vctxt); | 
 |     if (res != 0) { | 
 | 	if (res < 0) { | 
 | 	    VERROR_INT("xmlSchemaSAXHandleEndElementNs", | 
 | 		"calling xmlSchemaValidatorPopElem()"); | 
 | 	    goto internal_error; | 
 | 	} | 
 | 	goto exit; | 
 |     } | 
 | exit: | 
 |     return; | 
 | internal_error: | 
 |     vctxt->err = -1; | 
 |     xmlStopParser(vctxt->parserCtxt); | 
 |     return; | 
 | } | 
 |  | 
 | /************************************************************************ | 
 |  * 									* | 
 |  * 			Validation interfaces				* | 
 |  * 									* | 
 |  ************************************************************************/ | 
 |  | 
 | /** | 
 |  * xmlSchemaNewValidCtxt: | 
 |  * @schema:  a precompiled XML Schemas | 
 |  * | 
 |  * Create an XML Schemas validation context based on the given schema. | 
 |  * | 
 |  * Returns the validation context or NULL in case of error | 
 |  */ | 
 | xmlSchemaValidCtxtPtr | 
 | xmlSchemaNewValidCtxt(xmlSchemaPtr schema) | 
 | { | 
 |     xmlSchemaValidCtxtPtr ret; | 
 |  | 
 |     ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt)); | 
 |     if (ret == NULL) { | 
 |         xmlSchemaVErrMemory(NULL, "allocating validation context", NULL); | 
 |         return (NULL); | 
 |     } | 
 |     memset(ret, 0, sizeof(xmlSchemaValidCtxt)); | 
 |     ret->type = XML_SCHEMA_CTXT_VALIDATOR; | 
 |     ret->dict = xmlDictCreate(); | 
 |     ret->nodeQNames = xmlSchemaItemListCreate(); | 
 |     ret->schema = schema; | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaClearValidCtxt: | 
 |  * @ctxt: the schema validation context | 
 |  * | 
 |  * Free the resources associated to the schema validation context; | 
 |  * leaves some fields alive intended for reuse of the context. | 
 |  */ | 
 | static void | 
 | xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt) | 
 | { | 
 |     if (vctxt == NULL) | 
 |         return; | 
 |  | 
 |     /* | 
 |     * TODO: Should we clear the flags? | 
 |     *   Might be problematic if one reuses the context | 
 |     *   and assumes that the options remain the same. | 
 |     */ | 
 |     vctxt->flags = 0; | 
 |     vctxt->validationRoot = NULL; | 
 |     vctxt->doc = NULL; | 
 | #ifdef LIBXML_READER_ENABLED | 
 |     vctxt->reader = NULL; | 
 | #endif | 
 |     vctxt->hasKeyrefs = 0; | 
 |  | 
 |     if (vctxt->value != NULL) { | 
 |         xmlSchemaFreeValue(vctxt->value); | 
 | 	vctxt->value = NULL; | 
 |     } | 
 |     /* | 
 |     * Augmented IDC information. | 
 |     */ | 
 |     if (vctxt->aidcs != NULL) { | 
 | 	xmlSchemaIDCAugPtr cur = vctxt->aidcs, next; | 
 | 	do { | 
 | 	    next = cur->next; | 
 | 	    xmlFree(cur); | 
 | 	    cur = next; | 
 | 	} while (cur != NULL); | 
 | 	vctxt->aidcs = NULL; | 
 |     } | 
 |     if (vctxt->idcMatcherCache != NULL) { | 
 | 	xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp; | 
 |  | 
 | 	while (matcher) { | 
 | 	    tmp = matcher; | 
 | 	    matcher = matcher->nextCached; | 
 | 	    xmlSchemaIDCFreeMatcherList(tmp); | 
 | 	} | 
 | 	vctxt->idcMatcherCache = NULL; | 
 |     } | 
 |  | 
 |  | 
 |     if (vctxt->idcNodes != NULL) { | 
 | 	int i; | 
 | 	xmlSchemaPSVIIDCNodePtr item; | 
 |  | 
 | 	for (i = 0; i < vctxt->nbIdcNodes; i++) { | 
 | 	    item = vctxt->idcNodes[i]; | 
 | 	    xmlFree(item->keys); | 
 | 	    xmlFree(item); | 
 | 	} | 
 | 	xmlFree(vctxt->idcNodes); | 
 | 	vctxt->idcNodes = NULL; | 
 | 	vctxt->nbIdcNodes = 0; | 
 | 	vctxt->sizeIdcNodes = 0; | 
 |     } | 
 |     /* | 
 |     * Note that we won't delete the XPath state pool here. | 
 |     */ | 
 |     if (vctxt->xpathStates != NULL) { | 
 | 	xmlSchemaFreeIDCStateObjList(vctxt->xpathStates); | 
 | 	vctxt->xpathStates = NULL; | 
 |     } | 
 |     /* | 
 |     * Attribute info. | 
 |     */ | 
 |     if (vctxt->nbAttrInfos != 0) { | 
 | 	xmlSchemaClearAttrInfos(vctxt); | 
 |     } | 
 |     /* | 
 |     * Element info. | 
 |     */ | 
 |     if (vctxt->elemInfos != NULL) { | 
 | 	int i; | 
 | 	xmlSchemaNodeInfoPtr ei; | 
 |  | 
 | 	for (i = 0; i < vctxt->sizeElemInfos; i++) { | 
 | 	    ei = vctxt->elemInfos[i]; | 
 | 	    if (ei == NULL) | 
 | 		break; | 
 | 	    xmlSchemaClearElemInfo(vctxt, ei); | 
 | 	} | 
 |     } | 
 |     xmlSchemaItemListClear(vctxt->nodeQNames); | 
 |     /* Recreate the dict. */ | 
 |     xmlDictFree(vctxt->dict); | 
 |     /* | 
 |     * TODO: Is is save to recreate it? Do we have a scenario | 
 |     * where the user provides the dict? | 
 |     */ | 
 |     vctxt->dict = xmlDictCreate(); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaFreeValidCtxt: | 
 |  * @ctxt:  the schema validation context | 
 |  * | 
 |  * Free the resources associated to the schema validation context | 
 |  */ | 
 | void | 
 | xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt) | 
 | { | 
 |     if (ctxt == NULL) | 
 |         return; | 
 |     if (ctxt->value != NULL) | 
 |         xmlSchemaFreeValue(ctxt->value); | 
 |     if (ctxt->pctxt != NULL) | 
 | 	xmlSchemaFreeParserCtxt(ctxt->pctxt); | 
 |     if (ctxt->idcNodes != NULL) { | 
 | 	int i; | 
 | 	xmlSchemaPSVIIDCNodePtr item; | 
 |  | 
 | 	for (i = 0; i < ctxt->nbIdcNodes; i++) { | 
 | 	    item = ctxt->idcNodes[i]; | 
 | 	    xmlFree(item->keys); | 
 | 	    xmlFree(item); | 
 | 	} | 
 | 	xmlFree(ctxt->idcNodes); | 
 |     } | 
 |     if (ctxt->idcKeys != NULL) { | 
 | 	int i; | 
 | 	for (i = 0; i < ctxt->nbIdcKeys; i++) | 
 | 	    xmlSchemaIDCFreeKey(ctxt->idcKeys[i]); | 
 | 	xmlFree(ctxt->idcKeys); | 
 |     } | 
 |  | 
 |     if (ctxt->xpathStates != NULL) { | 
 | 	xmlSchemaFreeIDCStateObjList(ctxt->xpathStates); | 
 | 	ctxt->xpathStates = NULL; | 
 |     } | 
 |     if (ctxt->xpathStatePool != NULL) { | 
 | 	xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool); | 
 | 	ctxt->xpathStatePool = NULL; | 
 |     } | 
 |  | 
 |     /* | 
 |     * Augmented IDC information. | 
 |     */ | 
 |     if (ctxt->aidcs != NULL) { | 
 | 	xmlSchemaIDCAugPtr cur = ctxt->aidcs, next; | 
 | 	do { | 
 | 	    next = cur->next; | 
 | 	    xmlFree(cur); | 
 | 	    cur = next; | 
 | 	} while (cur != NULL); | 
 |     } | 
 |     if (ctxt->attrInfos != NULL) { | 
 | 	int i; | 
 | 	xmlSchemaAttrInfoPtr attr; | 
 |  | 
 | 	/* Just a paranoid call to the cleanup. */ | 
 | 	if (ctxt->nbAttrInfos != 0) | 
 | 	    xmlSchemaClearAttrInfos(ctxt); | 
 | 	for (i = 0; i < ctxt->sizeAttrInfos; i++) { | 
 | 	    attr = ctxt->attrInfos[i]; | 
 | 	    xmlFree(attr); | 
 | 	} | 
 | 	xmlFree(ctxt->attrInfos); | 
 |     } | 
 |     if (ctxt->elemInfos != NULL) { | 
 | 	int i; | 
 | 	xmlSchemaNodeInfoPtr ei; | 
 |  | 
 | 	for (i = 0; i < ctxt->sizeElemInfos; i++) { | 
 | 	    ei = ctxt->elemInfos[i]; | 
 | 	    if (ei == NULL) | 
 | 		break; | 
 | 	    xmlSchemaClearElemInfo(ctxt, ei); | 
 | 	    xmlFree(ei); | 
 | 	} | 
 | 	xmlFree(ctxt->elemInfos); | 
 |     } | 
 |     if (ctxt->nodeQNames != NULL) | 
 | 	xmlSchemaItemListFree(ctxt->nodeQNames); | 
 |     if (ctxt->dict != NULL) | 
 | 	xmlDictFree(ctxt->dict); | 
 |     xmlFree(ctxt); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaIsValid: | 
 |  * @ctxt: the schema validation context | 
 |  * | 
 |  * Check if any error was detected during validation. | 
 |  * | 
 |  * Returns 1 if valid so far, 0 if errors were detected, and -1 in case | 
 |  *         of internal error. | 
 |  */ | 
 | int | 
 | xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt) | 
 | { | 
 |     if (ctxt == NULL) | 
 |         return(-1); | 
 |     return(ctxt->err == 0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaSetValidErrors: | 
 |  * @ctxt:  a schema validation context | 
 |  * @err:  the error function | 
 |  * @warn: the warning function | 
 |  * @ctx: the functions context | 
 |  * | 
 |  * Set the error and warning callback informations | 
 |  */ | 
 | void | 
 | xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt, | 
 |                         xmlSchemaValidityErrorFunc err, | 
 |                         xmlSchemaValidityWarningFunc warn, void *ctx) | 
 | { | 
 |     if (ctxt == NULL) | 
 |         return; | 
 |     ctxt->error = err; | 
 |     ctxt->warning = warn; | 
 |     ctxt->errCtxt = ctx; | 
 |     if (ctxt->pctxt != NULL) | 
 | 	xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaSetValidStructuredErrors: | 
 |  * @ctxt:  a schema validation context | 
 |  * @serror:  the structured error function | 
 |  * @ctx: the functions context | 
 |  * | 
 |  * Set the structured error callback | 
 |  */ | 
 | void | 
 | xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt, | 
 | 				  xmlStructuredErrorFunc serror, void *ctx) | 
 | { | 
 |     if (ctxt == NULL) | 
 |         return; | 
 | 	ctxt->serror = serror; | 
 |     ctxt->error = NULL; | 
 |     ctxt->warning = NULL; | 
 |     ctxt->errCtxt = ctx; | 
 |     if (ctxt->pctxt != NULL) | 
 | 	xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaGetValidErrors: | 
 |  * @ctxt: a XML-Schema validation context | 
 |  * @err: the error function result | 
 |  * @warn: the warning function result | 
 |  * @ctx: the functions context result | 
 |  * | 
 |  * Get the error and warning callback informations | 
 |  * | 
 |  * Returns -1 in case of error and 0 otherwise | 
 |  */ | 
 | int | 
 | xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt, | 
 | 			xmlSchemaValidityErrorFunc * err, | 
 | 			xmlSchemaValidityWarningFunc * warn, void **ctx) | 
 | { | 
 | 	if (ctxt == NULL) | 
 | 		return (-1); | 
 | 	if (err != NULL) | 
 | 		*err = ctxt->error; | 
 | 	if (warn != NULL) | 
 | 		*warn = ctxt->warning; | 
 | 	if (ctx != NULL) | 
 | 		*ctx = ctxt->errCtxt; | 
 | 	return (0); | 
 | } | 
 |  | 
 |  | 
 | /** | 
 |  * xmlSchemaSetValidOptions: | 
 |  * @ctxt:	a schema validation context | 
 |  * @options: a combination of xmlSchemaValidOption | 
 |  * | 
 |  * Sets the options to be used during the validation. | 
 |  * | 
 |  * Returns 0 in case of success, -1 in case of an | 
 |  * API error. | 
 |  */ | 
 | int | 
 | xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt, | 
 | 			 int options) | 
 |  | 
 | { | 
 |     int i; | 
 |  | 
 |     if (ctxt == NULL) | 
 | 	return (-1); | 
 |     /* | 
 |     * WARNING: Change the start value if adding to the | 
 |     * xmlSchemaValidOption. | 
 |     * TODO: Is there an other, more easy to maintain, | 
 |     * way? | 
 |     */ | 
 |     for (i = 1; i < (int) sizeof(int) * 8; i++) { | 
 |         if (options & 1<<i) | 
 | 	    return (-1); | 
 |     } | 
 |     ctxt->options = options; | 
 |     return (0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaValidCtxtGetOptions: | 
 |  * @ctxt: a schema validation context | 
 |  * | 
 |  * Get the validation context options. | 
 |  * | 
 |  * Returns the option combination or -1 on error. | 
 |  */ | 
 | int | 
 | xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt) | 
 |  | 
 | { | 
 |     if (ctxt == NULL) | 
 | 	return (-1); | 
 |     else | 
 | 	return (ctxt->options); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt) | 
 | { | 
 |     xmlAttrPtr attr; | 
 |     int ret = 0; | 
 |     xmlSchemaNodeInfoPtr ielem = NULL; | 
 |     xmlNodePtr node, valRoot; | 
 |     const xmlChar *nsName; | 
 |  | 
 |     /* DOC VAL TODO: Move this to the start function. */ | 
 |     valRoot = xmlDocGetRootElement(vctxt->doc); | 
 |     if (valRoot == NULL) { | 
 | 	/* VAL TODO: Error code? */ | 
 | 	VERROR(1, NULL, "The document has no document element"); | 
 | 	return (1); | 
 |     } | 
 |     vctxt->depth = -1; | 
 |     vctxt->validationRoot = valRoot; | 
 |     node = valRoot; | 
 |     while (node != NULL) { | 
 | 	if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth)) | 
 | 	    goto next_sibling; | 
 | 	if (node->type == XML_ELEMENT_NODE) { | 
 |  | 
 | 	    /* | 
 | 	    * Init the node-info. | 
 | 	    */ | 
 | 	    vctxt->depth++; | 
 | 	    if (xmlSchemaValidatorPushElem(vctxt) == -1) | 
 | 		goto internal_error; | 
 | 	    ielem = vctxt->inode; | 
 | 	    ielem->node = node; | 
 | 	    ielem->nodeLine = node->line; | 
 | 	    ielem->localName = node->name; | 
 | 	    if (node->ns != NULL) | 
 | 		ielem->nsName = node->ns->href; | 
 | 	    ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY; | 
 | 	    /* | 
 | 	    * Register attributes. | 
 | 	    * DOC VAL TODO: We do not register namespace declaration | 
 | 	    * attributes yet. | 
 | 	    */ | 
 | 	    vctxt->nbAttrInfos = 0; | 
 | 	    if (node->properties != NULL) { | 
 | 		attr = node->properties; | 
 | 		do { | 
 | 		    if (attr->ns != NULL) | 
 | 			nsName = attr->ns->href; | 
 | 		    else | 
 | 			nsName = NULL; | 
 | 		    ret = xmlSchemaValidatorPushAttribute(vctxt, | 
 | 			(xmlNodePtr) attr, | 
 | 			/* | 
 | 			* Note that we give it the line number of the | 
 | 			* parent element. | 
 | 			*/ | 
 | 			ielem->nodeLine, | 
 | 			attr->name, nsName, 0, | 
 | 			xmlNodeListGetString(attr->doc, attr->children, 1), 1); | 
 | 		    if (ret == -1) { | 
 | 			VERROR_INT("xmlSchemaDocWalk", | 
 | 			    "calling xmlSchemaValidatorPushAttribute()"); | 
 | 			goto internal_error; | 
 | 		    } | 
 | 		    attr = attr->next; | 
 | 		} while (attr); | 
 | 	    } | 
 | 	    /* | 
 | 	    * Validate the element. | 
 | 	    */ | 
 | 	    ret = xmlSchemaValidateElem(vctxt); | 
 | 	    if (ret != 0) { | 
 | 		if (ret == -1) { | 
 | 		    VERROR_INT("xmlSchemaDocWalk", | 
 | 			"calling xmlSchemaValidateElem()"); | 
 | 		    goto internal_error; | 
 | 		} | 
 | 		/* | 
 | 		* Don't stop validation; just skip the content | 
 | 		* of this element. | 
 | 		*/ | 
 | 		goto leave_node; | 
 | 	    } | 
 | 	    if ((vctxt->skipDepth != -1) && | 
 | 		(vctxt->depth >= vctxt->skipDepth)) | 
 | 		goto leave_node; | 
 | 	} else if ((node->type == XML_TEXT_NODE) || | 
 | 	    (node->type == XML_CDATA_SECTION_NODE)) { | 
 | 	    /* | 
 | 	    * Process character content. | 
 | 	    */ | 
 | 	    if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)) | 
 | 		ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY; | 
 | 	    ret = xmlSchemaVPushText(vctxt, node->type, node->content, | 
 | 		-1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL); | 
 | 	    if (ret < 0) { | 
 | 		VERROR_INT("xmlSchemaVDocWalk", | 
 | 		    "calling xmlSchemaVPushText()"); | 
 | 		goto internal_error; | 
 | 	    } | 
 | 	    /* | 
 | 	    * DOC VAL TODO: Should we skip further validation of the | 
 | 	    * element content here? | 
 | 	    */ | 
 | 	} else if ((node->type == XML_ENTITY_NODE) || | 
 | 	    (node->type == XML_ENTITY_REF_NODE)) { | 
 | 	    /* | 
 | 	    * DOC VAL TODO: What to do with entities? | 
 | 	    */ | 
 | 	    VERROR_INT("xmlSchemaVDocWalk", | 
 | 		"there is at least one entity reference in the node-tree " | 
 | 		"currently being validated. Processing of entities with " | 
 | 		"this XML Schema processor is not supported (yet). Please " | 
 | 		"substitute entities before validation."); | 
 | 	    goto internal_error; | 
 | 	} else { | 
 | 	    goto leave_node; | 
 | 	    /* | 
 | 	    * DOC VAL TODO: XInclude nodes, etc. | 
 | 	    */ | 
 | 	} | 
 | 	/* | 
 | 	* Walk the doc. | 
 | 	*/ | 
 | 	if (node->children != NULL) { | 
 | 	    node = node->children; | 
 | 	    continue; | 
 | 	} | 
 | leave_node: | 
 | 	if (node->type == XML_ELEMENT_NODE) { | 
 | 	    /* | 
 | 	    * Leaving the scope of an element. | 
 | 	    */ | 
 | 	    if (node != vctxt->inode->node) { | 
 | 		VERROR_INT("xmlSchemaVDocWalk", | 
 | 		    "element position mismatch"); | 
 | 		goto internal_error; | 
 | 	    } | 
 | 	    ret = xmlSchemaValidatorPopElem(vctxt); | 
 | 	    if (ret != 0) { | 
 | 		if (ret < 0) { | 
 | 		    VERROR_INT("xmlSchemaVDocWalk", | 
 | 			"calling xmlSchemaValidatorPopElem()"); | 
 | 		    goto internal_error; | 
 | 		} | 
 | 	    } | 
 | 	    if (node == valRoot) | 
 | 		goto exit; | 
 | 	} | 
 | next_sibling: | 
 | 	if (node->next != NULL) | 
 | 	    node = node->next; | 
 | 	else { | 
 | 	    node = node->parent; | 
 | 	    goto leave_node; | 
 | 	} | 
 |     } | 
 |  | 
 | exit: | 
 |     return (ret); | 
 | internal_error: | 
 |     return (-1); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) { | 
 |     /* | 
 |     * Some initialization. | 
 |     */ | 
 |     vctxt->err = 0; | 
 |     vctxt->nberrors = 0; | 
 |     vctxt->depth = -1; | 
 |     vctxt->skipDepth = -1; | 
 |     vctxt->xsiAssemble = 0; | 
 |     vctxt->hasKeyrefs = 0; | 
 | #ifdef ENABLE_IDC_NODE_TABLES_TEST | 
 |     vctxt->createIDCNodeTables = 1; | 
 | #else | 
 |     vctxt->createIDCNodeTables = 0; | 
 | #endif | 
 |     /* | 
 |     * Create a schema + parser if necessary. | 
 |     */ | 
 |     if (vctxt->schema == NULL) { | 
 | 	xmlSchemaParserCtxtPtr pctxt; | 
 |  | 
 | 	vctxt->xsiAssemble = 1; | 
 | 	/* | 
 | 	* If not schema was given then we will create a schema | 
 | 	* dynamically using XSI schema locations. | 
 | 	* | 
 | 	* Create the schema parser context. | 
 | 	*/ | 
 | 	if ((vctxt->pctxt == NULL) && | 
 | 	   (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) | 
 | 	   return (-1); | 
 | 	pctxt = vctxt->pctxt; | 
 | 	pctxt->xsiAssemble = 1; | 
 | 	/* | 
 | 	* Create the schema. | 
 | 	*/ | 
 | 	vctxt->schema = xmlSchemaNewSchema(pctxt); | 
 | 	if (vctxt->schema == NULL) | 
 | 	    return (-1); | 
 | 	/* | 
 | 	* Create the schema construction context. | 
 | 	*/ | 
 | 	pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict); | 
 | 	if (pctxt->constructor == NULL) | 
 | 	    return(-1); | 
 | 	pctxt->constructor->mainSchema = vctxt->schema; | 
 | 	/* | 
 | 	* Take ownership of the constructor to be able to free it. | 
 | 	*/ | 
 | 	pctxt->ownsConstructor = 1; | 
 |     } | 
 |     /* | 
 |     * Augment the IDC definitions for the main schema and all imported ones | 
 |     * NOTE: main schema if the first in the imported list | 
 |     */ | 
 |     xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt); | 
 |  | 
 |     return(0); | 
 | } | 
 |  | 
 | static void | 
 | xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) { | 
 |     if (vctxt->xsiAssemble) { | 
 | 	if (vctxt->schema != NULL) { | 
 | 	    xmlSchemaFree(vctxt->schema); | 
 | 	    vctxt->schema = NULL; | 
 | 	} | 
 |     } | 
 |     xmlSchemaClearValidCtxt(vctxt); | 
 | } | 
 |  | 
 | static int | 
 | xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt) | 
 | { | 
 |     int ret = 0; | 
 |  | 
 |     if (xmlSchemaPreRun(vctxt) < 0) | 
 |         return(-1); | 
 |  | 
 |     if (vctxt->doc != NULL) { | 
 | 	/* | 
 | 	 * Tree validation. | 
 | 	 */ | 
 | 	ret = xmlSchemaVDocWalk(vctxt); | 
 | #ifdef LIBXML_READER_ENABLED | 
 |     } else if (vctxt->reader != NULL) { | 
 | 	/* | 
 | 	 * XML Reader validation. | 
 | 	 */ | 
 | #ifdef XML_SCHEMA_READER_ENABLED | 
 | 	ret = xmlSchemaVReaderWalk(vctxt); | 
 | #endif | 
 | #endif | 
 |     } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) { | 
 | 	/* | 
 | 	 * SAX validation. | 
 | 	 */ | 
 | 	ret = xmlParseDocument(vctxt->parserCtxt); | 
 |     } else { | 
 | 	VERROR_INT("xmlSchemaVStart", | 
 | 	    "no instance to validate"); | 
 | 	ret = -1; | 
 |     } | 
 |  | 
 |     xmlSchemaPostRun(vctxt); | 
 |     if (ret == 0) | 
 | 	ret = vctxt->err; | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaValidateOneElement: | 
 |  * @ctxt:  a schema validation context | 
 |  * @elem:  an element node | 
 |  * | 
 |  * Validate a branch of a tree, starting with the given @elem. | 
 |  * | 
 |  * Returns 0 if the element and its subtree is valid, a positive error | 
 |  * code number otherwise and -1 in case of an internal or API error. | 
 |  */ | 
 | int | 
 | xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem) | 
 | { | 
 |     if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE)) | 
 | 	return (-1); | 
 |  | 
 |     if (ctxt->schema == NULL) | 
 | 	return (-1); | 
 |  | 
 |     ctxt->doc = elem->doc; | 
 |     ctxt->node = elem; | 
 |     ctxt->validationRoot = elem; | 
 |     return(xmlSchemaVStart(ctxt)); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaValidateDoc: | 
 |  * @ctxt:  a schema validation context | 
 |  * @doc:  a parsed document tree | 
 |  * | 
 |  * Validate a document tree in memory. | 
 |  * | 
 |  * Returns 0 if the document is schemas valid, a positive error code | 
 |  *     number otherwise and -1 in case of internal or API error. | 
 |  */ | 
 | int | 
 | xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc) | 
 | { | 
 |     if ((ctxt == NULL) || (doc == NULL)) | 
 |         return (-1); | 
 |  | 
 |     ctxt->doc = doc; | 
 |     ctxt->node = xmlDocGetRootElement(doc); | 
 |     if (ctxt->node == NULL) { | 
 |         xmlSchemaCustomErr(ACTXT_CAST ctxt, | 
 | 	    XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING, | 
 | 	    (xmlNodePtr) doc, NULL, | 
 | 	    "The document has no document element", NULL, NULL); | 
 |         return (ctxt->err); | 
 |     } | 
 |     ctxt->validationRoot = ctxt->node; | 
 |     return (xmlSchemaVStart(ctxt)); | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************ | 
 |  * 									* | 
 |  * 		Function and data for SAX streaming API			* | 
 |  * 									* | 
 |  ************************************************************************/ | 
 | typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData; | 
 | typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr; | 
 |  | 
 | struct _xmlSchemaSplitSAXData { | 
 |     xmlSAXHandlerPtr      user_sax; | 
 |     void                 *user_data; | 
 |     xmlSchemaValidCtxtPtr ctxt; | 
 |     xmlSAXHandlerPtr      schemas_sax; | 
 | }; | 
 |  | 
 | #define XML_SAX_PLUG_MAGIC 0xdc43ba21 | 
 |  | 
 | struct _xmlSchemaSAXPlug { | 
 |     unsigned int magic; | 
 |  | 
 |     /* the original callbacks informations */ | 
 |     xmlSAXHandlerPtr     *user_sax_ptr; | 
 |     xmlSAXHandlerPtr      user_sax; | 
 |     void                **user_data_ptr; | 
 |     void                 *user_data; | 
 |  | 
 |     /* the block plugged back and validation informations */ | 
 |     xmlSAXHandler         schemas_sax; | 
 |     xmlSchemaValidCtxtPtr ctxt; | 
 | }; | 
 |  | 
 | /* All those functions just bounces to the user provided SAX handlers */ | 
 | static void | 
 | internalSubsetSplit(void *ctx, const xmlChar *name, | 
 | 	       const xmlChar *ExternalID, const xmlChar *SystemID) | 
 | { | 
 |     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | 
 |     if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | 
 |         (ctxt->user_sax->internalSubset != NULL)) | 
 | 	ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID, | 
 | 	                               SystemID); | 
 | } | 
 |  | 
 | static int | 
 | isStandaloneSplit(void *ctx) | 
 | { | 
 |     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | 
 |     if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | 
 |         (ctxt->user_sax->isStandalone != NULL)) | 
 | 	return(ctxt->user_sax->isStandalone(ctxt->user_data)); | 
 |     return(0); | 
 | } | 
 |  | 
 | static int | 
 | hasInternalSubsetSplit(void *ctx) | 
 | { | 
 |     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | 
 |     if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | 
 |         (ctxt->user_sax->hasInternalSubset != NULL)) | 
 | 	return(ctxt->user_sax->hasInternalSubset(ctxt->user_data)); | 
 |     return(0); | 
 | } | 
 |  | 
 | static int | 
 | hasExternalSubsetSplit(void *ctx) | 
 | { | 
 |     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | 
 |     if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | 
 |         (ctxt->user_sax->hasExternalSubset != NULL)) | 
 | 	return(ctxt->user_sax->hasExternalSubset(ctxt->user_data)); | 
 |     return(0); | 
 | } | 
 |  | 
 | static void | 
 | externalSubsetSplit(void *ctx, const xmlChar *name, | 
 | 	       const xmlChar *ExternalID, const xmlChar *SystemID) | 
 | { | 
 |     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | 
 |     if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | 
 |         (ctxt->user_sax->externalSubset != NULL)) | 
 | 	ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID, | 
 | 	                               SystemID); | 
 | } | 
 |  | 
 | static xmlParserInputPtr | 
 | resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId) | 
 | { | 
 |     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | 
 |     if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | 
 |         (ctxt->user_sax->resolveEntity != NULL)) | 
 | 	return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId, | 
 | 	                                     systemId)); | 
 |     return(NULL); | 
 | } | 
 |  | 
 | static xmlEntityPtr | 
 | getEntitySplit(void *ctx, const xmlChar *name) | 
 | { | 
 |     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | 
 |     if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | 
 |         (ctxt->user_sax->getEntity != NULL)) | 
 | 	return(ctxt->user_sax->getEntity(ctxt->user_data, name)); | 
 |     return(NULL); | 
 | } | 
 |  | 
 | static xmlEntityPtr | 
 | getParameterEntitySplit(void *ctx, const xmlChar *name) | 
 | { | 
 |     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | 
 |     if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | 
 |         (ctxt->user_sax->getParameterEntity != NULL)) | 
 | 	return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name)); | 
 |     return(NULL); | 
 | } | 
 |  | 
 |  | 
 | static void | 
 | entityDeclSplit(void *ctx, const xmlChar *name, int type, | 
 |           const xmlChar *publicId, const xmlChar *systemId, xmlChar *content) | 
 | { | 
 |     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | 
 |     if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | 
 |         (ctxt->user_sax->entityDecl != NULL)) | 
 | 	ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId, | 
 | 	                           systemId, content); | 
 | } | 
 |  | 
 | static void | 
 | attributeDeclSplit(void *ctx, const xmlChar * elem, | 
 |                    const xmlChar * name, int type, int def, | 
 |                    const xmlChar * defaultValue, xmlEnumerationPtr tree) | 
 | { | 
 |     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | 
 |     if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | 
 |         (ctxt->user_sax->attributeDecl != NULL)) { | 
 | 	ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type, | 
 | 	                              def, defaultValue, tree); | 
 |     } else { | 
 | 	xmlFreeEnumeration(tree); | 
 |     } | 
 | } | 
 |  | 
 | static void | 
 | elementDeclSplit(void *ctx, const xmlChar *name, int type, | 
 | 	    xmlElementContentPtr content) | 
 | { | 
 |     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | 
 |     if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | 
 |         (ctxt->user_sax->elementDecl != NULL)) | 
 | 	ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content); | 
 | } | 
 |  | 
 | static void | 
 | notationDeclSplit(void *ctx, const xmlChar *name, | 
 | 	     const xmlChar *publicId, const xmlChar *systemId) | 
 | { | 
 |     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | 
 |     if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | 
 |         (ctxt->user_sax->notationDecl != NULL)) | 
 | 	ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId, | 
 | 	                             systemId); | 
 | } | 
 |  | 
 | static void | 
 | unparsedEntityDeclSplit(void *ctx, const xmlChar *name, | 
 | 		   const xmlChar *publicId, const xmlChar *systemId, | 
 | 		   const xmlChar *notationName) | 
 | { | 
 |     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | 
 |     if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | 
 |         (ctxt->user_sax->unparsedEntityDecl != NULL)) | 
 | 	ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId, | 
 | 	                                   systemId, notationName); | 
 | } | 
 |  | 
 | static void | 
 | setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc) | 
 | { | 
 |     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | 
 |     if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | 
 |         (ctxt->user_sax->setDocumentLocator != NULL)) | 
 | 	ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc); | 
 | } | 
 |  | 
 | static void | 
 | startDocumentSplit(void *ctx) | 
 | { | 
 |     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | 
 |     if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | 
 |         (ctxt->user_sax->startDocument != NULL)) | 
 | 	ctxt->user_sax->startDocument(ctxt->user_data); | 
 | } | 
 |  | 
 | static void | 
 | endDocumentSplit(void *ctx) | 
 | { | 
 |     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | 
 |     if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | 
 |         (ctxt->user_sax->endDocument != NULL)) | 
 | 	ctxt->user_sax->endDocument(ctxt->user_data); | 
 | } | 
 |  | 
 | static void | 
 | processingInstructionSplit(void *ctx, const xmlChar *target, | 
 |                       const xmlChar *data) | 
 | { | 
 |     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | 
 |     if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | 
 |         (ctxt->user_sax->processingInstruction != NULL)) | 
 | 	ctxt->user_sax->processingInstruction(ctxt->user_data, target, data); | 
 | } | 
 |  | 
 | static void | 
 | commentSplit(void *ctx, const xmlChar *value) | 
 | { | 
 |     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | 
 |     if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | 
 |         (ctxt->user_sax->comment != NULL)) | 
 | 	ctxt->user_sax->comment(ctxt->user_data, value); | 
 | } | 
 |  | 
 | /* | 
 |  * Varargs error callbacks to the user application, harder ... | 
 |  */ | 
 |  | 
 | static void XMLCDECL | 
 | warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) { | 
 |     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | 
 |     if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | 
 |         (ctxt->user_sax->warning != NULL)) { | 
 | 	TODO | 
 |     } | 
 | } | 
 | static void XMLCDECL | 
 | errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) { | 
 |     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | 
 |     if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | 
 |         (ctxt->user_sax->error != NULL)) { | 
 | 	TODO | 
 |     } | 
 | } | 
 | static void XMLCDECL | 
 | fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) { | 
 |     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | 
 |     if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | 
 |         (ctxt->user_sax->fatalError != NULL)) { | 
 | 	TODO | 
 |     } | 
 | } | 
 |  | 
 | /* | 
 |  * Those are function where both the user handler and the schemas handler | 
 |  * need to be called. | 
 |  */ | 
 | static void | 
 | charactersSplit(void *ctx, const xmlChar *ch, int len) | 
 | { | 
 |     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | 
 |     if (ctxt == NULL) | 
 |         return; | 
 |     if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL)) | 
 | 	ctxt->user_sax->characters(ctxt->user_data, ch, len); | 
 |     if (ctxt->ctxt != NULL) | 
 | 	xmlSchemaSAXHandleText(ctxt->ctxt, ch, len); | 
 | } | 
 |  | 
 | static void | 
 | ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len) | 
 | { | 
 |     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | 
 |     if (ctxt == NULL) | 
 |         return; | 
 |     if ((ctxt->user_sax != NULL) && | 
 |         (ctxt->user_sax->ignorableWhitespace != NULL)) | 
 | 	ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len); | 
 |     if (ctxt->ctxt != NULL) | 
 | 	xmlSchemaSAXHandleText(ctxt->ctxt, ch, len); | 
 | } | 
 |  | 
 | static void | 
 | cdataBlockSplit(void *ctx, const xmlChar *value, int len) | 
 | { | 
 |     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | 
 |     if (ctxt == NULL) | 
 |         return; | 
 |     if ((ctxt->user_sax != NULL) && | 
 |         (ctxt->user_sax->cdataBlock != NULL)) | 
 | 	ctxt->user_sax->cdataBlock(ctxt->user_data, value, len); | 
 |     if (ctxt->ctxt != NULL) | 
 | 	xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len); | 
 | } | 
 |  | 
 | static void | 
 | referenceSplit(void *ctx, const xmlChar *name) | 
 | { | 
 |     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | 
 |     if (ctxt == NULL) | 
 |         return; | 
 |     if ((ctxt != NULL) && (ctxt->user_sax != NULL) && | 
 |         (ctxt->user_sax->reference != NULL)) | 
 | 	ctxt->user_sax->reference(ctxt->user_data, name); | 
 |     if (ctxt->ctxt != NULL) | 
 |         xmlSchemaSAXHandleReference(ctxt->user_data, name); | 
 | } | 
 |  | 
 | static void | 
 | startElementNsSplit(void *ctx, const xmlChar * localname, | 
 | 		    const xmlChar * prefix, const xmlChar * URI, | 
 | 		    int nb_namespaces, const xmlChar ** namespaces, | 
 | 		    int nb_attributes, int nb_defaulted, | 
 | 		    const xmlChar ** attributes) { | 
 |     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | 
 |     if (ctxt == NULL) | 
 |         return; | 
 |     if ((ctxt->user_sax != NULL) && | 
 |         (ctxt->user_sax->startElementNs != NULL)) | 
 | 	ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix, | 
 | 	                               URI, nb_namespaces, namespaces, | 
 | 				       nb_attributes, nb_defaulted, | 
 | 				       attributes); | 
 |     if (ctxt->ctxt != NULL) | 
 | 	xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix, | 
 | 	                                 URI, nb_namespaces, namespaces, | 
 | 					 nb_attributes, nb_defaulted, | 
 | 					 attributes); | 
 | } | 
 |  | 
 | static void | 
 | endElementNsSplit(void *ctx, const xmlChar * localname, | 
 | 		    const xmlChar * prefix, const xmlChar * URI) { | 
 |     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx; | 
 |     if (ctxt == NULL) | 
 |         return; | 
 |     if ((ctxt->user_sax != NULL) && | 
 |         (ctxt->user_sax->endElementNs != NULL)) | 
 | 	ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI); | 
 |     if (ctxt->ctxt != NULL) | 
 | 	xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaSAXPlug: | 
 |  * @ctxt:  a schema validation context | 
 |  * @sax:  a pointer to the original xmlSAXHandlerPtr | 
 |  * @user_data:  a pointer to the original SAX user data pointer | 
 |  * | 
 |  * Plug a SAX based validation layer in a SAX parsing event flow. | 
 |  * The original @saxptr and @dataptr data are replaced by new pointers | 
 |  * but the calls to the original will be maintained. | 
 |  * | 
 |  * Returns a pointer to a data structure needed to unplug the validation layer | 
 |  *         or NULL in case of errors. | 
 |  */ | 
 | xmlSchemaSAXPlugPtr | 
 | xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt, | 
 | 		 xmlSAXHandlerPtr *sax, void **user_data) | 
 | { | 
 |     xmlSchemaSAXPlugPtr ret; | 
 |     xmlSAXHandlerPtr old_sax; | 
 |  | 
 |     if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL)) | 
 |         return(NULL); | 
 |  | 
 |     /* | 
 |      * We only allow to plug into SAX2 event streams | 
 |      */ | 
 |     old_sax = *sax; | 
 |     if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC)) | 
 |         return(NULL); | 
 |     if ((old_sax != NULL) && | 
 |         (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) && | 
 |         ((old_sax->startElement != NULL) || (old_sax->endElement != NULL))) | 
 |         return(NULL); | 
 |  | 
 |     /* | 
 |      * everything seems right allocate the local data needed for that layer | 
 |      */ | 
 |     ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct)); | 
 |     if (ret == NULL) { | 
 |         return(NULL); | 
 |     } | 
 |     memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct)); | 
 |     ret->magic = XML_SAX_PLUG_MAGIC; | 
 |     ret->schemas_sax.initialized = XML_SAX2_MAGIC; | 
 |     ret->ctxt = ctxt; | 
 |     ret->user_sax_ptr = sax; | 
 |     ret->user_sax = old_sax; | 
 |     if (old_sax == NULL) { | 
 |         /* | 
 | 	 * go direct, no need for the split block and functions. | 
 | 	 */ | 
 | 	ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs; | 
 | 	ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs; | 
 | 	/* | 
 | 	 * Note that we use the same text-function for both, to prevent | 
 | 	 * the parser from testing for ignorable whitespace. | 
 | 	 */ | 
 | 	ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText; | 
 | 	ret->schemas_sax.characters = xmlSchemaSAXHandleText; | 
 |  | 
 | 	ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection; | 
 | 	ret->schemas_sax.reference = xmlSchemaSAXHandleReference; | 
 |  | 
 | 	ret->user_data = ctxt; | 
 | 	*user_data = ctxt; | 
 |     } else { | 
 |        /* | 
 |         * for each callback unused by Schemas initialize it to the Split | 
 | 	* routine only if non NULL in the user block, this can speed up | 
 | 	* things at the SAX level. | 
 | 	*/ | 
 |         if (old_sax->internalSubset != NULL) | 
 |             ret->schemas_sax.internalSubset = internalSubsetSplit; | 
 |         if (old_sax->isStandalone != NULL) | 
 |             ret->schemas_sax.isStandalone = isStandaloneSplit; | 
 |         if (old_sax->hasInternalSubset != NULL) | 
 |             ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit; | 
 |         if (old_sax->hasExternalSubset != NULL) | 
 |             ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit; | 
 |         if (old_sax->resolveEntity != NULL) | 
 |             ret->schemas_sax.resolveEntity = resolveEntitySplit; | 
 |         if (old_sax->getEntity != NULL) | 
 |             ret->schemas_sax.getEntity = getEntitySplit; | 
 |         if (old_sax->entityDecl != NULL) | 
 |             ret->schemas_sax.entityDecl = entityDeclSplit; | 
 |         if (old_sax->notationDecl != NULL) | 
 |             ret->schemas_sax.notationDecl = notationDeclSplit; | 
 |         if (old_sax->attributeDecl != NULL) | 
 |             ret->schemas_sax.attributeDecl = attributeDeclSplit; | 
 |         if (old_sax->elementDecl != NULL) | 
 |             ret->schemas_sax.elementDecl = elementDeclSplit; | 
 |         if (old_sax->unparsedEntityDecl != NULL) | 
 |             ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit; | 
 |         if (old_sax->setDocumentLocator != NULL) | 
 |             ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit; | 
 |         if (old_sax->startDocument != NULL) | 
 |             ret->schemas_sax.startDocument = startDocumentSplit; | 
 |         if (old_sax->endDocument != NULL) | 
 |             ret->schemas_sax.endDocument = endDocumentSplit; | 
 |         if (old_sax->processingInstruction != NULL) | 
 |             ret->schemas_sax.processingInstruction = processingInstructionSplit; | 
 |         if (old_sax->comment != NULL) | 
 |             ret->schemas_sax.comment = commentSplit; | 
 |         if (old_sax->warning != NULL) | 
 |             ret->schemas_sax.warning = warningSplit; | 
 |         if (old_sax->error != NULL) | 
 |             ret->schemas_sax.error = errorSplit; | 
 |         if (old_sax->fatalError != NULL) | 
 |             ret->schemas_sax.fatalError = fatalErrorSplit; | 
 |         if (old_sax->getParameterEntity != NULL) | 
 |             ret->schemas_sax.getParameterEntity = getParameterEntitySplit; | 
 |         if (old_sax->externalSubset != NULL) | 
 |             ret->schemas_sax.externalSubset = externalSubsetSplit; | 
 |  | 
 | 	/* | 
 | 	 * the 6 schemas callback have to go to the splitter functions | 
 | 	 * Note that we use the same text-function for ignorableWhitespace | 
 | 	 * if possible, to prevent the parser from testing for ignorable | 
 | 	 * whitespace. | 
 | 	 */ | 
 |         ret->schemas_sax.characters = charactersSplit; | 
 | 	if ((old_sax->ignorableWhitespace != NULL) && | 
 | 	    (old_sax->ignorableWhitespace != old_sax->characters)) | 
 | 	    ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit; | 
 | 	else | 
 | 	    ret->schemas_sax.ignorableWhitespace = charactersSplit; | 
 |         ret->schemas_sax.cdataBlock = cdataBlockSplit; | 
 |         ret->schemas_sax.reference = referenceSplit; | 
 |         ret->schemas_sax.startElementNs = startElementNsSplit; | 
 |         ret->schemas_sax.endElementNs = endElementNsSplit; | 
 |  | 
 | 	ret->user_data_ptr = user_data; | 
 | 	ret->user_data = *user_data; | 
 | 	*user_data = ret; | 
 |     } | 
 |  | 
 |     /* | 
 |      * plug the pointers back. | 
 |      */ | 
 |     *sax = &(ret->schemas_sax); | 
 |     ctxt->sax = *sax; | 
 |     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM; | 
 |     xmlSchemaPreRun(ctxt); | 
 |     return(ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaSAXUnplug: | 
 |  * @plug:  a data structure returned by xmlSchemaSAXPlug | 
 |  * | 
 |  * Unplug a SAX based validation layer in a SAX parsing event flow. | 
 |  * The original pointers used in the call are restored. | 
 |  * | 
 |  * Returns 0 in case of success and -1 in case of failure. | 
 |  */ | 
 | int | 
 | xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug) | 
 | { | 
 |     xmlSAXHandlerPtr *sax; | 
 |     void **user_data; | 
 |  | 
 |     if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC)) | 
 |         return(-1); | 
 |     plug->magic = 0; | 
 |  | 
 |     xmlSchemaPostRun(plug->ctxt); | 
 |     /* restore the data */ | 
 |     sax = plug->user_sax_ptr; | 
 |     *sax = plug->user_sax; | 
 |     if (plug->user_sax != NULL) { | 
 | 	user_data = plug->user_data_ptr; | 
 | 	*user_data = plug->user_data; | 
 |     } | 
 |  | 
 |     /* free and return */ | 
 |     xmlFree(plug); | 
 |     return(0); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaValidateStream: | 
 |  * @ctxt:  a schema validation context | 
 |  * @input:  the input to use for reading the data | 
 |  * @enc:  an optional encoding information | 
 |  * @sax:  a SAX handler for the resulting events | 
 |  * @user_data:  the context to provide to the SAX handler. | 
 |  * | 
 |  * Validate an input based on a flow of SAX event from the parser | 
 |  * and forward the events to the @sax handler with the provided @user_data | 
 |  * the user provided @sax handler must be a SAX2 one. | 
 |  * | 
 |  * Returns 0 if the document is schemas valid, a positive error code | 
 |  *     number otherwise and -1 in case of internal or API error. | 
 |  */ | 
 | int | 
 | xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt, | 
 |                         xmlParserInputBufferPtr input, xmlCharEncoding enc, | 
 |                         xmlSAXHandlerPtr sax, void *user_data) | 
 | { | 
 |     xmlSchemaSAXPlugPtr plug = NULL; | 
 |     xmlSAXHandlerPtr old_sax = NULL; | 
 |     xmlParserCtxtPtr pctxt = NULL; | 
 |     xmlParserInputPtr inputStream = NULL; | 
 |     int ret; | 
 |  | 
 |     if ((ctxt == NULL) || (input == NULL)) | 
 |         return (-1); | 
 |  | 
 |     /* | 
 |      * prepare the parser | 
 |      */ | 
 |     pctxt = xmlNewParserCtxt(); | 
 |     if (pctxt == NULL) | 
 |         return (-1); | 
 |     old_sax = pctxt->sax; | 
 |     pctxt->sax = sax; | 
 |     pctxt->userData = user_data; | 
 | #if 0 | 
 |     if (options) | 
 |         xmlCtxtUseOptions(pctxt, options); | 
 | #endif | 
 |     pctxt->linenumbers = 1; | 
 |  | 
 |     inputStream = xmlNewIOInputStream(pctxt, input, enc);; | 
 |     if (inputStream == NULL) { | 
 |         ret = -1; | 
 | 	goto done; | 
 |     } | 
 |     inputPush(pctxt, inputStream); | 
 |     ctxt->parserCtxt = pctxt; | 
 |     ctxt->input = input; | 
 |  | 
 |     /* | 
 |      * Plug the validation and launch the parsing | 
 |      */ | 
 |     plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData)); | 
 |     if (plug == NULL) { | 
 |         ret = -1; | 
 | 	goto done; | 
 |     } | 
 |     ctxt->input = input; | 
 |     ctxt->enc = enc; | 
 |     ctxt->sax = pctxt->sax; | 
 |     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM; | 
 |     ret = xmlSchemaVStart(ctxt); | 
 |  | 
 |     if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) { | 
 | 	ret = ctxt->parserCtxt->errNo; | 
 | 	if (ret == 0) | 
 | 	    ret = 1; | 
 |     } | 
 |  | 
 | done: | 
 |     ctxt->parserCtxt = NULL; | 
 |     ctxt->sax = NULL; | 
 |     ctxt->input = NULL; | 
 |     if (plug != NULL) { | 
 |         xmlSchemaSAXUnplug(plug); | 
 |     } | 
 |     /* cleanup */ | 
 |     if (pctxt != NULL) { | 
 | 	pctxt->sax = old_sax; | 
 | 	xmlFreeParserCtxt(pctxt); | 
 |     } | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaValidateFile: | 
 |  * @ctxt: a schema validation context | 
 |  * @filename: the URI of the instance | 
 |  * @options: a future set of options, currently unused | 
 |  * | 
 |  * Do a schemas validation of the given resource, it will use the | 
 |  * SAX streamable validation internally. | 
 |  * | 
 |  * Returns 0 if the document is valid, a positive error code | 
 |  *     number otherwise and -1 in case of an internal or API error. | 
 |  */ | 
 | int | 
 | xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt, | 
 |                       const char * filename, | 
 | 		      int options ATTRIBUTE_UNUSED) | 
 | { | 
 |     int ret; | 
 |     xmlParserInputBufferPtr input; | 
 |  | 
 |     if ((ctxt == NULL) || (filename == NULL)) | 
 |         return (-1); | 
 |  | 
 |     input = xmlParserInputBufferCreateFilename(filename, | 
 | 	XML_CHAR_ENCODING_NONE); | 
 |     if (input == NULL) | 
 | 	return (-1); | 
 |     ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE, | 
 | 	NULL, NULL); | 
 |     return (ret); | 
 | } | 
 |  | 
 | /** | 
 |  * xmlSchemaValidCtxtGetParserCtxt: | 
 |  * @ctxt: a schema validation context | 
 |  * | 
 |  * allow access to the parser context of the schema validation context | 
 |  * | 
 |  * Returns the parser context of the schema validation context or NULL | 
 |  *         in case of error. | 
 |  */ | 
 | xmlParserCtxtPtr | 
 | xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt) | 
 | { | 
 |     if (ctxt == NULL) | 
 |         return(NULL); | 
 |     return (ctxt->parserCtxt); | 
 | } | 
 |  | 
 | #define bottom_xmlschemas | 
 | #include "elfgcchack.h" | 
 | #endif /* LIBXML_SCHEMAS_ENABLED */ |