ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

xmlschemas.c
Go to the documentation of this file.
00001 /*
00002  * schemas.c : implementation of the XML Schema handling and
00003  *             schema validity checking
00004  *
00005  * See Copyright for the status of this software.
00006  *
00007  * Daniel Veillard <veillard@redhat.com>
00008  */
00009 
00010 /*
00011  * TODO:
00012  *   - when types are redefined in includes, check that all
00013  *     types in the redef list are equal
00014  *     -> need a type equality operation.
00015  *   - if we don't intend to use the schema for schemas, we
00016  *     need to validate all schema attributes (ref, type, name)
00017  *     against their types.
00018  *   - Eliminate item creation for: ??
00019  *
00020  * URGENT TODO:
00021  *   - For xsi-driven schema acquisition, augment the IDCs after every
00022  *     acquisition episode (xmlSchemaAugmentIDC).
00023  *
00024  * NOTES:
00025  *   - Elimated item creation for: <restriction>, <extension>,
00026  *     <simpleContent>, <complexContent>, <list>, <union>
00027  *
00028  * PROBLEMS:
00029  *   - http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0337.html
00030  *     IDC XPath expression and chameleon includes: the targetNamespace is changed, so
00031  *     XPath will have trouble to resolve to this namespace, since not known.
00032  *
00033  *
00034  * CONSTRAINTS:
00035  *
00036  * Schema Component Constraint:
00037  *   All Group Limited (cos-all-limited)
00038  *   Status: complete
00039  *   (1.2)
00040  *     In xmlSchemaGroupDefReferenceTermFixup() and
00041  *   (2)
00042  *     In xmlSchemaParseModelGroup()
00043  *     TODO: Actually this should go to component-level checks,
00044  *     but is done here due to performance. Move it to an other layer
00045  *     is schema construction via an API is implemented.
00046  */
00047 #define IN_LIBXML
00048 #include "libxml.h"
00049 
00050 #ifdef LIBXML_SCHEMAS_ENABLED
00051 
00052 #include <string.h>
00053 #include <libxml/xmlmemory.h>
00054 #include <libxml/parser.h>
00055 #include <libxml/parserInternals.h>
00056 #include <libxml/hash.h>
00057 #include <libxml/uri.h>
00058 #include <libxml/xmlschemas.h>
00059 #include <libxml/schemasInternals.h>
00060 #include <libxml/xmlschemastypes.h>
00061 #include <libxml/xmlautomata.h>
00062 #include <libxml/xmlregexp.h>
00063 #include <libxml/dict.h>
00064 #include <libxml/encoding.h>
00065 #include <libxml/xmlIO.h>
00066 #ifdef LIBXML_PATTERN_ENABLED
00067 #include <libxml/pattern.h>
00068 #endif
00069 #ifdef LIBXML_READER_ENABLED
00070 #include <libxml/xmlreader.h>
00071 #endif
00072 
00073 /* #define DEBUG 1 */
00074 
00075 /* #define DEBUG_CONTENT 1 */
00076 
00077 /* #define DEBUG_TYPE 1 */
00078 
00079 /* #define DEBUG_CONTENT_REGEXP 1 */
00080 
00081 /* #define DEBUG_AUTOMATA 1 */
00082 
00083 /* #define DEBUG_IDC */
00084 
00085 /* #define DEBUG_IDC_NODE_TABLE */
00086 
00087 /* #define WXS_ELEM_DECL_CONS_ENABLED */
00088 
00089 #ifdef DEBUG_IDC
00090  #ifndef DEBUG_IDC_NODE_TABLE
00091   #define DEBUG_IDC_NODE_TABLE
00092  #endif
00093 #endif
00094 
00095 /* #define ENABLE_PARTICLE_RESTRICTION 1 */
00096 
00097 #define ENABLE_REDEFINE
00098 
00099 /* #define ENABLE_NAMED_LOCALS */
00100 
00101 /* #define ENABLE_IDC_NODE_TABLES_TEST */
00102 
00103 #define DUMP_CONTENT_MODEL
00104 
00105 #ifdef LIBXML_READER_ENABLED
00106 /* #define XML_SCHEMA_READER_ENABLED */
00107 #endif
00108 
00109 #define UNBOUNDED (1 << 30)
00110 #define TODO                                \
00111     xmlGenericError(xmlGenericErrorContext,             \
00112         "Unimplemented block at %s:%d\n",               \
00113             __FILE__, __LINE__);
00114 
00115 #define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
00116 
00117 /*
00118  * The XML Schemas namespaces
00119  */
00120 static const xmlChar *xmlSchemaNs = (const xmlChar *)
00121     "http://www.w3.org/2001/XMLSchema";
00122 
00123 static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
00124     "http://www.w3.org/2001/XMLSchema-instance";
00125 
00126 static const xmlChar *xmlNamespaceNs = (const xmlChar *)
00127     "http://www.w3.org/2000/xmlns/";
00128 
00129 /*
00130 * Come casting macros.
00131 */
00132 #define ACTXT_CAST (xmlSchemaAbstractCtxtPtr)
00133 #define PCTXT_CAST (xmlSchemaParserCtxtPtr)
00134 #define VCTXT_CAST (xmlSchemaValidCtxtPtr)
00135 #define WXS_BASIC_CAST (xmlSchemaBasicItemPtr)
00136 #define WXS_TREE_CAST (xmlSchemaTreeItemPtr)
00137 #define WXS_PTC_CAST (xmlSchemaParticlePtr)
00138 #define WXS_TYPE_CAST (xmlSchemaTypePtr)
00139 #define WXS_ELEM_CAST (xmlSchemaElementPtr)
00140 #define WXS_ATTR_GROUP_CAST (xmlSchemaAttributeGroupPtr)
00141 #define WXS_ATTR_CAST (xmlSchemaAttributePtr)
00142 #define WXS_ATTR_USE_CAST (xmlSchemaAttributeUsePtr)
00143 #define WXS_ATTR_PROHIB_CAST (xmlSchemaAttributeUseProhibPtr)
00144 #define WXS_MODEL_GROUPDEF_CAST (xmlSchemaModelGroupDefPtr)
00145 #define WXS_MODEL_GROUP_CAST (xmlSchemaModelGroupPtr)
00146 #define WXS_IDC_CAST (xmlSchemaIDCPtr)
00147 #define WXS_QNAME_CAST (xmlSchemaQNameRefPtr)
00148 #define WXS_LIST_CAST (xmlSchemaItemListPtr)
00149 
00150 /*
00151 * Macros to query common properties of components.
00152 */
00153 #define WXS_ITEM_NODE(i) xmlSchemaGetComponentNode(WXS_BASIC_CAST (i))
00154 
00155 #define WXS_ITEM_TYPE_NAME(i) xmlSchemaGetComponentTypeStr(WXS_BASIC_CAST (i))
00156 /*
00157 * Macros for element declarations.
00158 */
00159 #define WXS_ELEM_TYPEDEF(e) (e)->subtypes
00160 
00161 #define WXS_SUBST_HEAD(item) (item)->refDecl
00162 /*
00163 * Macros for attribute declarations.
00164 */
00165 #define WXS_ATTR_TYPEDEF(a) (a)->subtypes
00166 /*
00167 * Macros for attribute uses.
00168 */
00169 #define WXS_ATTRUSE_DECL(au) WXS_ATTR_CAST (WXS_ATTR_USE_CAST (au))->attrDecl
00170 
00171 #define WXS_ATTRUSE_TYPEDEF(au) WXS_ATTR_TYPEDEF(WXS_ATTRUSE_DECL( WXS_ATTR_USE_CAST au))
00172 
00173 #define WXS_ATTRUSE_DECL_NAME(au) (WXS_ATTRUSE_DECL(au))->name
00174 
00175 #define WXS_ATTRUSE_DECL_TNS(au) (WXS_ATTRUSE_DECL(au))->targetNamespace
00176 /*
00177 * Macros for attribute groups.
00178 */
00179 #define WXS_ATTR_GROUP_HAS_REFS(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS)
00180 #define WXS_ATTR_GROUP_EXPANDED(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED)
00181 /*
00182 * Macros for particles.
00183 */
00184 #define WXS_PARTICLE(p) WXS_PTC_CAST (p)
00185 
00186 #define WXS_PARTICLE_TERM(p) (WXS_PARTICLE(p))->children
00187 
00188 #define WXS_PARTICLE_TERM_AS_ELEM(p) (WXS_ELEM_CAST WXS_PARTICLE_TERM(p))
00189 
00190 #define WXS_PARTICLE_MODEL(p) WXS_MODEL_GROUP_CAST WXS_PARTICLE(p)->children
00191 /*
00192 * Macros for model groups definitions.
00193 */
00194 #define WXS_MODELGROUPDEF_MODEL(mgd) (WXS_MODEL_GROUP_CAST (mgd))->children
00195 /*
00196 * Macros for model groups.
00197 */
00198 #define WXS_IS_MODEL_GROUP(i) \
00199     (((i)->type == XML_SCHEMA_TYPE_SEQUENCE) || \
00200      ((i)->type == XML_SCHEMA_TYPE_CHOICE) || \
00201      ((i)->type == XML_SCHEMA_TYPE_ALL))
00202 
00203 #define WXS_MODELGROUP_PARTICLE(mg) WXS_PTC_CAST (mg)->children
00204 /*
00205 * Macros for schema buckets.
00206 */
00207 #define WXS_IS_BUCKET_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \
00208     ((t) == XML_SCHEMA_SCHEMA_REDEFINE))
00209 
00210 #define WXS_IS_BUCKET_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \
00211     ((t) == XML_SCHEMA_SCHEMA_IMPORT))
00212 
00213 #define WXS_IMPBUCKET(b) ((xmlSchemaImportPtr) (b))
00214 
00215 #define WXS_INCBUCKET(b) ((xmlSchemaIncludePtr) (b))
00216 /*
00217 * Macros for complex/simple types.
00218 */
00219 #define WXS_IS_ANYTYPE(i) \
00220      (( (i)->type == XML_SCHEMA_TYPE_BASIC) && \
00221       ( (WXS_TYPE_CAST (i))->builtInType == XML_SCHEMAS_ANYTYPE))
00222 
00223 #define WXS_IS_COMPLEX(i) \
00224     (((i)->type == XML_SCHEMA_TYPE_COMPLEX) || \
00225      ((i)->builtInType == XML_SCHEMAS_ANYTYPE))
00226 
00227 #define WXS_IS_SIMPLE(item) \
00228     ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
00229      ((item->type == XML_SCHEMA_TYPE_BASIC) && \
00230       (item->builtInType != XML_SCHEMAS_ANYTYPE)))
00231 
00232 #define WXS_IS_ANY_SIMPLE_TYPE(i) \
00233     (((i)->type == XML_SCHEMA_TYPE_BASIC) && \
00234       ((i)->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
00235 
00236 #define WXS_IS_RESTRICTION(t) \
00237     ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)
00238 
00239 #define WXS_IS_EXTENSION(t) \
00240     ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
00241 
00242 #define WXS_IS_TYPE_NOT_FIXED(i) \
00243     (((i)->type != XML_SCHEMA_TYPE_BASIC) && \
00244      (((i)->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
00245 
00246 #define WXS_IS_TYPE_NOT_FIXED_1(item) \
00247     (((item)->type != XML_SCHEMA_TYPE_BASIC) && \
00248      (((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0))
00249 
00250 #define WXS_TYPE_IS_GLOBAL(t) ((t)->flags & XML_SCHEMAS_TYPE_GLOBAL)
00251 
00252 #define WXS_TYPE_IS_LOCAL(t) (((t)->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0)
00253 /*
00254 * Macros for exclusively for complex types.
00255 */
00256 #define WXS_HAS_COMPLEX_CONTENT(item) \
00257     ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
00258      (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
00259      (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
00260 
00261 #define WXS_HAS_SIMPLE_CONTENT(item) \
00262     ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
00263      (item->contentType == XML_SCHEMA_CONTENT_BASIC))
00264 
00265 #define WXS_HAS_MIXED_CONTENT(item) \
00266     (item->contentType == XML_SCHEMA_CONTENT_MIXED)
00267 
00268 #define WXS_EMPTIABLE(t) \
00269     (xmlSchemaIsParticleEmptiable(WXS_PTC_CAST (t)->subtypes))
00270 
00271 #define WXS_TYPE_CONTENTTYPE(t) (t)->subtypes
00272 
00273 #define WXS_TYPE_PARTICLE(t) WXS_PTC_CAST (t)->subtypes
00274 
00275 #define WXS_TYPE_PARTICLE_TERM(t) WXS_PARTICLE_TERM(WXS_TYPE_PARTICLE(t))
00276 /*
00277 * Macros for exclusively for simple types.
00278 */
00279 #define WXS_LIST_ITEMTYPE(t) (t)->subtypes
00280 
00281 #define WXS_IS_ATOMIC(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
00282 
00283 #define WXS_IS_LIST(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
00284 
00285 #define WXS_IS_UNION(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
00286 /*
00287 * Misc parser context macros.
00288 */
00289 #define WXS_CONSTRUCTOR(ctx) (ctx)->constructor
00290 
00291 #define WXS_HAS_BUCKETS(ctx) \
00292 ( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \
00293 (WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) )
00294 
00295 #define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups
00296 
00297 #define WXS_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket
00298 
00299 #define WXS_SCHEMA(ctx) (ctx)->schema
00300 
00301 #define WXS_ADD_LOCAL(ctx, item) \
00302     xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, item)
00303 
00304 #define WXS_ADD_GLOBAL(ctx, item) \
00305     xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, item)
00306 
00307 #define WXS_ADD_PENDING(ctx, item) \
00308     xmlSchemaAddItemSize(&((ctx)->constructor->pending), 10, item)
00309 /*
00310 * xmlSchemaItemList macros.
00311 */
00312 #define WXS_ILIST_IS_EMPTY(l) ((l == NULL) || ((l)->nbItems == 0))
00313 /*
00314 * Misc macros.
00315 */
00316 #define IS_SCHEMA(node, type) \
00317    ((node != NULL) && (node->ns != NULL) && \
00318     (xmlStrEqual(node->name, (const xmlChar *) type)) && \
00319     (xmlStrEqual(node->ns->href, xmlSchemaNs)))
00320 
00321 #define FREE_AND_NULL(str) if ((str) != NULL) { xmlFree((xmlChar *) (str)); str = NULL; }
00322 
00323 /*
00324 * Since we put the default/fixed values into the dict, we can
00325 * use pointer comparison for those values.
00326 * REMOVED: (xmlStrEqual((v1), (v2)))
00327 */
00328 #define WXS_ARE_DEFAULT_STR_EQUAL(v1, v2) ((v1) == (v2))
00329 
00330 #define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
00331 
00332 #define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0))
00333 
00334 #define HFAILURE if (res == -1) goto exit_failure;
00335 
00336 #define HERROR if (res != 0) goto exit_error;
00337 
00338 #define HSTOP(ctx) if ((ctx)->stop) goto exit;
00339 /*
00340 * Some flags used for various schema constraints.
00341 */
00342 #define SUBSET_RESTRICTION  1<<0
00343 #define SUBSET_EXTENSION    1<<1
00344 #define SUBSET_SUBSTITUTION 1<<2
00345 #define SUBSET_LIST         1<<3
00346 #define SUBSET_UNION        1<<4
00347 
00348 typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
00349 typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
00350 
00351 typedef struct _xmlSchemaItemList xmlSchemaItemList;
00352 typedef xmlSchemaItemList *xmlSchemaItemListPtr;
00353 struct _xmlSchemaItemList {
00354     void **items;  /* used for dynamic addition of schemata */
00355     int nbItems; /* used for dynamic addition of schemata */
00356     int sizeItems; /* used for dynamic addition of schemata */
00357 };
00358 
00359 #define XML_SCHEMA_CTXT_PARSER 1
00360 #define XML_SCHEMA_CTXT_VALIDATOR 2
00361 
00362 typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
00363 typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
00364 struct _xmlSchemaAbstractCtxt {
00365     int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */
00366 };
00367 
00368 typedef struct _xmlSchemaBucket xmlSchemaBucket;
00369 typedef xmlSchemaBucket *xmlSchemaBucketPtr;
00370 
00371 #define XML_SCHEMA_SCHEMA_MAIN 0
00372 #define XML_SCHEMA_SCHEMA_IMPORT 1
00373 #define XML_SCHEMA_SCHEMA_INCLUDE 2
00374 #define XML_SCHEMA_SCHEMA_REDEFINE 3
00375 
00381 typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation;
00382 typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr;
00383 struct _xmlSchemaSchemaRelation {
00384     xmlSchemaSchemaRelationPtr next;
00385     int type; /* E.g. XML_SCHEMA_SCHEMA_IMPORT */
00386     const xmlChar *importNamespace;
00387     xmlSchemaBucketPtr bucket;
00388 };
00389 
00390 #define XML_SCHEMA_BUCKET_MARKED 1<<0
00391 #define XML_SCHEMA_BUCKET_COMPS_ADDED 1<<1
00392 
00393 struct _xmlSchemaBucket {
00394     int type;
00395     int flags;
00396     const xmlChar *schemaLocation;
00397     const xmlChar *origTargetNamespace;
00398     const xmlChar *targetNamespace;
00399     xmlDocPtr doc;
00400     xmlSchemaSchemaRelationPtr relations;
00401     int located;
00402     int parsed;
00403     int imported;
00404     int preserveDoc;
00405     xmlSchemaItemListPtr globals; /* Global components. */
00406     xmlSchemaItemListPtr locals; /* Local components. */
00407 };
00408 
00417 typedef struct _xmlSchemaImport xmlSchemaImport;
00418 typedef xmlSchemaImport *xmlSchemaImportPtr;
00419 struct _xmlSchemaImport {
00420     int type; /* Main OR import OR include. */
00421     int flags;
00422     const xmlChar *schemaLocation; /* The URI of the schema document. */
00423     /* For chameleon includes, @origTargetNamespace will be NULL */
00424     const xmlChar *origTargetNamespace;
00425     /*
00426     * For chameleon includes, @targetNamespace will be the
00427     * targetNamespace of the including schema.
00428     */
00429     const xmlChar *targetNamespace;
00430     xmlDocPtr doc; /* The schema node-tree. */
00431     /* @relations will hold any included/imported/redefined schemas. */
00432     xmlSchemaSchemaRelationPtr relations;
00433     int located;
00434     int parsed;
00435     int imported;
00436     int preserveDoc;
00437     xmlSchemaItemListPtr globals;
00438     xmlSchemaItemListPtr locals;
00439     /* The imported schema. */
00440     xmlSchemaPtr schema;
00441 };
00442 
00443 /*
00444 * (extends xmlSchemaBucket)
00445 */
00446 typedef struct _xmlSchemaInclude xmlSchemaInclude;
00447 typedef xmlSchemaInclude *xmlSchemaIncludePtr;
00448 struct _xmlSchemaInclude {
00449     int type;
00450     int flags;
00451     const xmlChar *schemaLocation;
00452     const xmlChar *origTargetNamespace;
00453     const xmlChar *targetNamespace;
00454     xmlDocPtr doc;
00455     xmlSchemaSchemaRelationPtr relations;
00456     int located;
00457     int parsed;
00458     int imported;
00459     int preserveDoc;
00460     xmlSchemaItemListPtr globals; /* Global components. */
00461     xmlSchemaItemListPtr locals; /* Local components. */
00462 
00463     /* The owning main or import schema bucket. */
00464     xmlSchemaImportPtr ownerImport;
00465 };
00466 
00472 typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
00473 typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
00474 struct _xmlSchemaBasicItem {
00475     xmlSchemaTypeType type;
00476 };
00477 
00484 typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
00485 typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
00486 struct _xmlSchemaAnnotItem {
00487     xmlSchemaTypeType type;
00488     xmlSchemaAnnotPtr annot;
00489 };
00490 
00497 typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
00498 typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
00499 struct _xmlSchemaTreeItem {
00500     xmlSchemaTypeType type;
00501     xmlSchemaAnnotPtr annot;
00502     xmlSchemaTreeItemPtr next;
00503     xmlSchemaTreeItemPtr children;
00504 };
00505 
00506 
00507 #define XML_SCHEMA_ATTR_USE_FIXED 1<<0
00508 
00514 typedef struct _xmlSchemaAttributeUse xmlSchemaAttributeUse;
00515 typedef xmlSchemaAttributeUse *xmlSchemaAttributeUsePtr;
00516 struct _xmlSchemaAttributeUse {
00517     xmlSchemaTypeType type;
00518     xmlSchemaAnnotPtr annot;
00519     xmlSchemaAttributeUsePtr next; /* The next attr. use. */
00520     /*
00521     * The attr. decl. OR a QName-ref. to an attr. decl. OR
00522     * a QName-ref. to an attribute group definition.
00523     */
00524     xmlSchemaAttributePtr attrDecl;
00525 
00526     int flags;
00527     xmlNodePtr node;
00528     int occurs; /* required, optional */
00529     const xmlChar * defValue;
00530     xmlSchemaValPtr defVal;
00531 };
00532 
00539 typedef struct _xmlSchemaAttributeUseProhib xmlSchemaAttributeUseProhib;
00540 typedef xmlSchemaAttributeUseProhib *xmlSchemaAttributeUseProhibPtr;
00541 struct _xmlSchemaAttributeUseProhib {
00542     xmlSchemaTypeType type; /* == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB */
00543     xmlNodePtr node;
00544     const xmlChar *name;
00545     const xmlChar *targetNamespace;
00546     int isRef;
00547 };
00548 
00552 typedef struct _xmlSchemaRedef xmlSchemaRedef;
00553 typedef xmlSchemaRedef *xmlSchemaRedefPtr;
00554 struct _xmlSchemaRedef {
00555     xmlSchemaRedefPtr next;
00556     xmlSchemaBasicItemPtr item; /* The redefining component. */
00557     xmlSchemaBasicItemPtr reference; /* The referencing component. */
00558     xmlSchemaBasicItemPtr target; /* The to-be-redefined component. */
00559     const xmlChar *refName; /* The name of the to-be-redefined component. */
00560     const xmlChar *refTargetNs; /* The target namespace of the
00561                                    to-be-redefined comp. */
00562     xmlSchemaBucketPtr targetBucket; /* The redefined schema. */
00563 };
00564 
00568 typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt;
00569 typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr;
00570 struct _xmlSchemaConstructionCtxt {
00571     xmlSchemaPtr mainSchema; /* The main schema. */
00572     xmlSchemaBucketPtr mainBucket; /* The main schema bucket */
00573     xmlDictPtr dict;
00574     xmlSchemaItemListPtr buckets; /* List of schema buckets. */
00575     /* xmlSchemaItemListPtr relations; */ /* List of schema relations. */
00576     xmlSchemaBucketPtr bucket; /* The current schema bucket */
00577     xmlSchemaItemListPtr pending; /* All Components of all schemas that
00578                                      need to be fixed. */
00579     xmlHashTablePtr substGroups;
00580     xmlSchemaRedefPtr redefs;
00581     xmlSchemaRedefPtr lastRedef;
00582 };
00583 
00584 #define XML_SCHEMAS_PARSE_ERROR     1
00585 #define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
00586 
00587 struct _xmlSchemaParserCtxt {
00588     int type;
00589     void *errCtxt;             /* user specific error context */
00590     xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */
00591     xmlSchemaValidityWarningFunc warning;       /* the callback in case of warning */
00592     int err;
00593     int nberrors;
00594     xmlStructuredErrorFunc serror;
00595 
00596     xmlSchemaConstructionCtxtPtr constructor;
00597     int ownsConstructor; /* TODO: Move this to parser *flags*. */
00598 
00599     /* xmlSchemaPtr topschema;  */
00600     /* xmlHashTablePtr namespaces;  */
00601 
00602     xmlSchemaPtr schema;        /* The main schema in use */
00603     int counter;
00604 
00605     const xmlChar *URL;
00606     xmlDocPtr doc;
00607     int preserve;       /* Whether the doc should be freed  */
00608 
00609     const char *buffer;
00610     int size;
00611 
00612     /*
00613      * Used to build complex element content models
00614      */
00615     xmlAutomataPtr am;
00616     xmlAutomataStatePtr start;
00617     xmlAutomataStatePtr end;
00618     xmlAutomataStatePtr state;
00619 
00620     xmlDictPtr dict;        /* dictionnary for interned string names */
00621     xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
00622     int options;
00623     xmlSchemaValidCtxtPtr vctxt;
00624     int isS4S;
00625     int isRedefine;
00626     int xsiAssemble;
00627     int stop; /* If the parser should stop; i.e. a critical error. */
00628     const xmlChar *targetNamespace;
00629     xmlSchemaBucketPtr redefined; /* The schema to be redefined. */
00630 
00631     xmlSchemaRedefPtr redef; /* Used for redefinitions. */
00632     int redefCounter; /* Used for redefinitions. */
00633     xmlSchemaItemListPtr attrProhibs;
00634 };
00635 
00642 typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
00643 typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
00644 struct _xmlSchemaQNameRef {
00645     xmlSchemaTypeType type;
00646     xmlSchemaBasicItemPtr item; /* The resolved referenced item. */
00647     xmlSchemaTypeType itemType;
00648     const xmlChar *name;
00649     const xmlChar *targetNamespace;
00650     xmlNodePtr node;
00651 };
00652 
00659 typedef struct _xmlSchemaParticle xmlSchemaParticle;
00660 typedef xmlSchemaParticle *xmlSchemaParticlePtr;
00661 struct _xmlSchemaParticle {
00662     xmlSchemaTypeType type;
00663     xmlSchemaAnnotPtr annot;
00664     xmlSchemaTreeItemPtr next; /* next particle */
00665     xmlSchemaTreeItemPtr children; /* the "term" (e.g. a model group,
00666     a group definition, a XML_SCHEMA_EXTRA_QNAMEREF (if a reference),
00667         etc.) */
00668     int minOccurs;
00669     int maxOccurs;
00670     xmlNodePtr node;
00671 };
00672 
00679 typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
00680 typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
00681 struct _xmlSchemaModelGroup {
00682     xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
00683     xmlSchemaAnnotPtr annot;
00684     xmlSchemaTreeItemPtr next; /* not used */
00685     xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
00686     xmlNodePtr node;
00687 };
00688 
00689 #define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
00690 #define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1
00691 
00697 typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
00698 typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
00699 struct _xmlSchemaModelGroupDef {
00700     xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
00701     xmlSchemaAnnotPtr annot;
00702     xmlSchemaTreeItemPtr next; /* not used */
00703     xmlSchemaTreeItemPtr children; /* the "model group" */
00704     const xmlChar *name;
00705     const xmlChar *targetNamespace;
00706     xmlNodePtr node;
00707     int flags;
00708 };
00709 
00710 typedef struct _xmlSchemaIDC xmlSchemaIDC;
00711 typedef xmlSchemaIDC *xmlSchemaIDCPtr;
00712 
00719 typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
00720 typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
00721 struct _xmlSchemaIDCSelect {
00722     xmlSchemaIDCSelectPtr next;
00723     xmlSchemaIDCPtr idc;
00724     int index; /* an index position if significant for IDC key-sequences */
00725     const xmlChar *xpath; /* the XPath expression */
00726     void *xpathComp; /* the compiled XPath expression */
00727 };
00728 
00736 struct _xmlSchemaIDC {
00737     xmlSchemaTypeType type;
00738     xmlSchemaAnnotPtr annot;
00739     xmlSchemaIDCPtr next;
00740     xmlNodePtr node;
00741     const xmlChar *name;
00742     const xmlChar *targetNamespace;
00743     xmlSchemaIDCSelectPtr selector;
00744     xmlSchemaIDCSelectPtr fields;
00745     int nbFields;
00746     xmlSchemaQNameRefPtr ref;
00747 };
00748 
00754 typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
00755 typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
00756 struct _xmlSchemaIDCAug {
00757     xmlSchemaIDCAugPtr next; /* next in a list */
00758     xmlSchemaIDCPtr def; /* the IDC definition */
00759     int keyrefDepth; /* the lowest tree level to which IDC
00760                         tables need to be bubbled upwards */
00761 };
00762 
00768 typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
00769 typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
00770 struct _xmlSchemaPSVIIDCKey {
00771     xmlSchemaTypePtr type;
00772     xmlSchemaValPtr val;
00773 };
00774 
00780 typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
00781 typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
00782 struct _xmlSchemaPSVIIDCNode {
00783     xmlNodePtr node;
00784     xmlSchemaPSVIIDCKeyPtr *keys;
00785     int nodeLine;
00786     int nodeQNameID;
00787 
00788 };
00789 
00795 typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
00796 typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
00797 struct _xmlSchemaPSVIIDCBinding {
00798     xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
00799     xmlSchemaIDCPtr definition; /* the IDC definition */
00800     xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
00801     int nbNodes; /* number of entries in the node table */
00802     int sizeNodes; /* size of the node table */
00803     xmlSchemaItemListPtr dupls;
00804 };
00805 
00806 
00807 #define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
00808 #define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
00809 
00810 #define XPATH_STATE_OBJ_MATCHES -2
00811 #define XPATH_STATE_OBJ_BLOCKED -3
00812 
00813 typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
00814 typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
00815 
00821 typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
00822 typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
00823 struct _xmlSchemaIDCStateObj {
00824     int type;
00825     xmlSchemaIDCStateObjPtr next; /* next if in a list */
00826     int depth; /* depth of creation */
00827     int *history; /* list of (depth, state-id) tuples */
00828     int nbHistory;
00829     int sizeHistory;
00830     xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
00831                                        matcher */
00832     xmlSchemaIDCSelectPtr sel;
00833     void *xpathCtxt;
00834 };
00835 
00836 #define IDC_MATCHER 0
00837 
00843 struct _xmlSchemaIDCMatcher {
00844     int type;
00845     int depth; /* the tree depth at creation time */
00846     xmlSchemaIDCMatcherPtr next; /* next in the list */
00847     xmlSchemaIDCMatcherPtr nextCached; /* next in the cache list */
00848     xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
00849     int idcType;
00850     xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
00851                                          elements */
00852     int sizeKeySeqs;
00853     xmlSchemaItemListPtr targets; /* list of target-node
00854                                      (xmlSchemaPSVIIDCNodePtr) entries */
00855 };
00856 
00857 /*
00858 * Element info flags.
00859 */
00860 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES  1<<0
00861 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
00862 #define XML_SCHEMA_ELEM_INFO_NILLED        1<<2
00863 #define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE        1<<3
00864 
00865 #define XML_SCHEMA_NODE_INFO_VALUE_NEEDED      1<<4
00866 #define XML_SCHEMA_ELEM_INFO_EMPTY             1<<5
00867 #define XML_SCHEMA_ELEM_INFO_HAS_CONTENT       1<<6
00868 
00869 #define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT  1<<7
00870 #define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT  1<<8
00871 #define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED  1<<9
00872 #define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE  1<<10
00873 
00879 struct _xmlSchemaNodeInfo {
00880     int nodeType;
00881     xmlNodePtr node;
00882     int nodeLine;
00883     const xmlChar *localName;
00884     const xmlChar *nsName;
00885     const xmlChar *value;
00886     xmlSchemaValPtr val; /* the pre-computed value if any */
00887     xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
00888 
00889     int flags; /* combination of node info flags */
00890 
00891     int valNeeded;
00892     int normVal;
00893 
00894     xmlSchemaElementPtr decl; /* the element/attribute declaration */
00895     int depth;
00896     xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
00897                                             for the scope element*/
00898     xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
00899                                            element */
00900     xmlRegExecCtxtPtr regexCtxt;
00901 
00902     const xmlChar **nsBindings; /* Namespace bindings on this element */
00903     int nbNsBindings;
00904     int sizeNsBindings;
00905 
00906     int hasKeyrefs;
00907     int appliedXPath; /* Indicates that an XPath has been applied. */
00908 };
00909 
00910 #define XML_SCHEMAS_ATTR_UNKNOWN 1
00911 #define XML_SCHEMAS_ATTR_ASSESSED 2
00912 #define XML_SCHEMAS_ATTR_PROHIBITED 3
00913 #define XML_SCHEMAS_ATTR_ERR_MISSING 4
00914 #define XML_SCHEMAS_ATTR_INVALID_VALUE 5
00915 #define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
00916 #define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
00917 #define XML_SCHEMAS_ATTR_DEFAULT 8
00918 #define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
00919 #define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
00920 #define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
00921 #define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
00922 #define XML_SCHEMAS_ATTR_WILD_SKIP 13
00923 #define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
00924 #define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
00925 #define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
00926 #define XML_SCHEMAS_ATTR_META 17
00927 /*
00928 * @metaType values of xmlSchemaAttrInfo.
00929 */
00930 #define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
00931 #define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
00932 #define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
00933 #define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
00934 #define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
00935 
00936 typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
00937 typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
00938 struct _xmlSchemaAttrInfo {
00939     int nodeType;
00940     xmlNodePtr node;
00941     int nodeLine;
00942     const xmlChar *localName;
00943     const xmlChar *nsName;
00944     const xmlChar *value;
00945     xmlSchemaValPtr val; /* the pre-computed value if any */
00946     xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
00947     int flags; /* combination of node info flags */
00948 
00949     xmlSchemaAttributePtr decl; /* the attribute declaration */
00950     xmlSchemaAttributeUsePtr use;  /* the attribute use */
00951     int state;
00952     int metaType;
00953     const xmlChar *vcValue; /* the value constraint value */
00954     xmlSchemaNodeInfoPtr parent;
00955 };
00956 
00957 
00958 #define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
00959 
00964 struct _xmlSchemaValidCtxt {
00965     int type;
00966     void *errCtxt;             /* user specific data block */
00967     xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */
00968     xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
00969     xmlStructuredErrorFunc serror;
00970 
00971     xmlSchemaPtr schema;        /* The schema in use */
00972     xmlDocPtr doc;
00973     xmlParserInputBufferPtr input;
00974     xmlCharEncoding enc;
00975     xmlSAXHandlerPtr sax;
00976     xmlParserCtxtPtr parserCtxt;
00977     void *user_data; /* TODO: What is this for? */
00978 
00979     int err;
00980     int nberrors;
00981 
00982     xmlNodePtr node;
00983     xmlNodePtr cur;
00984     /* xmlSchemaTypePtr type; */
00985 
00986     xmlRegExecCtxtPtr regexp;
00987     xmlSchemaValPtr value;
00988 
00989     int valueWS;
00990     int options;
00991     xmlNodePtr validationRoot;
00992     xmlSchemaParserCtxtPtr pctxt;
00993     int xsiAssemble;
00994 
00995     int depth;
00996     xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
00997     int sizeElemInfos;
00998     xmlSchemaNodeInfoPtr inode; /* the current element information */
00999 
01000     xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
01001 
01002     xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
01003     xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
01004     xmlSchemaIDCMatcherPtr idcMatcherCache; /* Cache for IDC matcher objects. */
01005 
01006     xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
01007     int nbIdcNodes;
01008     int sizeIdcNodes;
01009 
01010     xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
01011     int nbIdcKeys;
01012     int sizeIdcKeys;
01013 
01014     int flags;
01015 
01016     xmlDictPtr dict;
01017 
01018 #ifdef LIBXML_READER_ENABLED
01019     xmlTextReaderPtr reader;
01020 #endif
01021 
01022     xmlSchemaAttrInfoPtr *attrInfos;
01023     int nbAttrInfos;
01024     int sizeAttrInfos;
01025 
01026     int skipDepth;
01027     xmlSchemaItemListPtr nodeQNames;
01028     int hasKeyrefs;
01029     int createIDCNodeTables;
01030     int psviExposeIDCNodeTables;
01031 };
01032 
01038 typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
01039 typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
01040 struct _xmlSchemaSubstGroup {
01041     xmlSchemaElementPtr head;
01042     xmlSchemaItemListPtr members;
01043 };
01044 
01045 /************************************************************************
01046  *                                  *
01047  *          Some predeclarations                *
01048  *                                  *
01049  ************************************************************************/
01050 
01051 static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
01052                                  xmlSchemaPtr schema,
01053                                  xmlNodePtr node);
01054 static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
01055                                  xmlSchemaPtr schema,
01056                                  xmlNodePtr node);
01057 static int
01058 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
01059                    xmlSchemaAbstractCtxtPtr ctxt);
01060 static const xmlChar *
01061 xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
01062 static int
01063 xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
01064                      xmlNodePtr node);
01065 static int
01066 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
01067                        xmlSchemaParserCtxtPtr ctxt);
01068 static void
01069 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
01070 static xmlSchemaWhitespaceValueType
01071 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
01072 static xmlSchemaTreeItemPtr
01073 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
01074              xmlNodePtr node, xmlSchemaTypeType type,
01075              int withParticle);
01076 static const xmlChar *
01077 xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item);
01078 static xmlSchemaTypeLinkPtr
01079 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
01080 static void
01081 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
01082              const char *funcName,
01083              const char *message);
01084 static int
01085 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt,
01086                  xmlSchemaTypePtr type,
01087                  xmlSchemaTypePtr baseType,
01088                  int subset);
01089 static void
01090 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
01091                    xmlSchemaParserCtxtPtr ctxt);
01092 static void
01093 xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
01094 static xmlSchemaQNameRefPtr
01095 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
01096                 xmlSchemaPtr schema,
01097                 xmlNodePtr node);
01098 
01099 /************************************************************************
01100  *                                  *
01101  *          Helper functions                    *
01102  *                                  *
01103  ************************************************************************/
01104 
01111 static const xmlChar *
01112 xmlSchemaItemTypeToStr(xmlSchemaTypeType type)
01113 {
01114     switch (type) {
01115     case XML_SCHEMA_TYPE_BASIC:
01116         return(BAD_CAST "simple type definition");
01117     case XML_SCHEMA_TYPE_SIMPLE:
01118         return(BAD_CAST "simple type definition");
01119     case XML_SCHEMA_TYPE_COMPLEX:
01120         return(BAD_CAST "complex type definition");
01121     case XML_SCHEMA_TYPE_ELEMENT:
01122         return(BAD_CAST "element declaration");
01123     case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
01124         return(BAD_CAST "attribute use");
01125     case XML_SCHEMA_TYPE_ATTRIBUTE:
01126         return(BAD_CAST "attribute declaration");
01127     case XML_SCHEMA_TYPE_GROUP:
01128         return(BAD_CAST "model group definition");
01129     case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
01130         return(BAD_CAST "attribute group definition");
01131     case XML_SCHEMA_TYPE_NOTATION:
01132         return(BAD_CAST "notation declaration");
01133     case XML_SCHEMA_TYPE_SEQUENCE:
01134         return(BAD_CAST "model group (sequence)");
01135     case XML_SCHEMA_TYPE_CHOICE:
01136         return(BAD_CAST "model group (choice)");
01137     case XML_SCHEMA_TYPE_ALL:
01138         return(BAD_CAST "model group (all)");
01139     case XML_SCHEMA_TYPE_PARTICLE:
01140         return(BAD_CAST "particle");
01141     case XML_SCHEMA_TYPE_IDC_UNIQUE:
01142         return(BAD_CAST "unique identity-constraint");
01143         /* return(BAD_CAST "IDC (unique)"); */
01144     case XML_SCHEMA_TYPE_IDC_KEY:
01145         return(BAD_CAST "key identity-constraint");
01146         /* return(BAD_CAST "IDC (key)"); */
01147     case XML_SCHEMA_TYPE_IDC_KEYREF:
01148         return(BAD_CAST "keyref identity-constraint");
01149         /* return(BAD_CAST "IDC (keyref)"); */
01150     case XML_SCHEMA_TYPE_ANY:
01151         return(BAD_CAST "wildcard (any)");
01152     case XML_SCHEMA_EXTRA_QNAMEREF:
01153         return(BAD_CAST "[helper component] QName reference");
01154     case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
01155         return(BAD_CAST "[helper component] attribute use prohibition");
01156     default:
01157         return(BAD_CAST "Not a schema component");
01158     }
01159 }
01160 
01167 static const xmlChar *
01168 xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)
01169 {
01170     switch (item->type) {
01171     case XML_SCHEMA_TYPE_BASIC:
01172         if (WXS_IS_COMPLEX(WXS_TYPE_CAST item))
01173         return(BAD_CAST "complex type definition");
01174         else
01175         return(BAD_CAST "simple type definition");
01176     default:
01177         return(xmlSchemaItemTypeToStr(item->type));
01178     }
01179 }
01180 
01191 static xmlNodePtr
01192 xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
01193 {
01194     switch (item->type) {
01195     case XML_SCHEMA_TYPE_ELEMENT:
01196         return (((xmlSchemaElementPtr) item)->node);
01197     case XML_SCHEMA_TYPE_ATTRIBUTE:
01198         return (((xmlSchemaAttributePtr) item)->node);
01199     case XML_SCHEMA_TYPE_COMPLEX:
01200     case XML_SCHEMA_TYPE_SIMPLE:
01201         return (((xmlSchemaTypePtr) item)->node);
01202     case XML_SCHEMA_TYPE_ANY:
01203     case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
01204         return (((xmlSchemaWildcardPtr) item)->node);
01205     case XML_SCHEMA_TYPE_PARTICLE:
01206         return (((xmlSchemaParticlePtr) item)->node);
01207     case XML_SCHEMA_TYPE_SEQUENCE:
01208     case XML_SCHEMA_TYPE_CHOICE:
01209     case XML_SCHEMA_TYPE_ALL:
01210         return (((xmlSchemaModelGroupPtr) item)->node);
01211     case XML_SCHEMA_TYPE_GROUP:
01212         return (((xmlSchemaModelGroupDefPtr) item)->node);
01213     case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
01214         return (((xmlSchemaAttributeGroupPtr) item)->node);
01215     case XML_SCHEMA_TYPE_IDC_UNIQUE:
01216     case XML_SCHEMA_TYPE_IDC_KEY:
01217     case XML_SCHEMA_TYPE_IDC_KEYREF:
01218         return (((xmlSchemaIDCPtr) item)->node);
01219     case XML_SCHEMA_EXTRA_QNAMEREF:
01220         return(((xmlSchemaQNameRefPtr) item)->node);
01221     /* TODO: What to do with NOTATIONs?
01222     case XML_SCHEMA_TYPE_NOTATION:
01223         return (((xmlSchemaNotationPtr) item)->node);
01224     */
01225     case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
01226         return (((xmlSchemaAttributeUsePtr) item)->node);
01227     default:
01228         return (NULL);
01229     }
01230 }
01231 
01232 #if 0
01233 
01239 static xmlSchemaBasicItemPtr
01240 xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
01241 {
01242     switch (item->type) {
01243     case XML_SCHEMA_TYPE_ELEMENT:
01244         return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
01245     case XML_SCHEMA_TYPE_ATTRIBUTE:
01246         return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
01247     case XML_SCHEMA_TYPE_COMPLEX:
01248     case XML_SCHEMA_TYPE_SIMPLE:
01249         return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
01250     case XML_SCHEMA_TYPE_ANY:
01251     case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
01252         return (NULL);
01253     case XML_SCHEMA_TYPE_PARTICLE:
01254         return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
01255     case XML_SCHEMA_TYPE_SEQUENCE:
01256     case XML_SCHEMA_TYPE_CHOICE:
01257     case XML_SCHEMA_TYPE_ALL:
01258         return (NULL);
01259     case XML_SCHEMA_TYPE_GROUP:
01260         return (NULL);
01261     case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
01262         return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
01263     case XML_SCHEMA_TYPE_IDC_UNIQUE:
01264     case XML_SCHEMA_TYPE_IDC_KEY:
01265     case XML_SCHEMA_TYPE_IDC_KEYREF:
01266         return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
01267     default:
01268         return (NULL);
01269     }
01270 }
01271 #endif
01272 
01273 
01286 static const xmlChar*
01287 xmlSchemaFormatQName(xmlChar **buf,
01288              const xmlChar *namespaceName,
01289              const xmlChar *localName)
01290 {
01291     FREE_AND_NULL(*buf)
01292     if (namespaceName != NULL) {
01293     *buf = xmlStrdup(BAD_CAST "{");
01294     *buf = xmlStrcat(*buf, namespaceName);
01295     *buf = xmlStrcat(*buf, BAD_CAST "}");
01296     }
01297     if (localName != NULL) {
01298     if (namespaceName == NULL)
01299         return(localName);
01300     *buf = xmlStrcat(*buf, localName);
01301     } else {
01302     *buf = xmlStrcat(*buf, BAD_CAST "(NULL)");
01303     }
01304     return ((const xmlChar *) *buf);
01305 }
01306 
01307 static const xmlChar*
01308 xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
01309 {
01310     if (ns != NULL)
01311     return (xmlSchemaFormatQName(buf, ns->href, localName));
01312     else
01313     return (xmlSchemaFormatQName(buf, NULL, localName));
01314 }
01315 
01316 static const xmlChar *
01317 xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
01318 {
01319     switch (item->type) {
01320     case XML_SCHEMA_TYPE_ELEMENT:
01321         return (((xmlSchemaElementPtr) item)->name);
01322     case XML_SCHEMA_TYPE_ATTRIBUTE:
01323         return (((xmlSchemaAttributePtr) item)->name);
01324     case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
01325         return (((xmlSchemaAttributeGroupPtr) item)->name);
01326     case XML_SCHEMA_TYPE_BASIC:
01327     case XML_SCHEMA_TYPE_SIMPLE:
01328     case XML_SCHEMA_TYPE_COMPLEX:
01329         return (((xmlSchemaTypePtr) item)->name);
01330     case XML_SCHEMA_TYPE_GROUP:
01331         return (((xmlSchemaModelGroupDefPtr) item)->name);
01332     case XML_SCHEMA_TYPE_IDC_KEY:
01333     case XML_SCHEMA_TYPE_IDC_UNIQUE:
01334     case XML_SCHEMA_TYPE_IDC_KEYREF:
01335         return (((xmlSchemaIDCPtr) item)->name);
01336     case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
01337         if (WXS_ATTRUSE_DECL(item) != NULL) {
01338         return(xmlSchemaGetComponentName(
01339             WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
01340         } else
01341         return(NULL);
01342     case XML_SCHEMA_EXTRA_QNAMEREF:
01343         return (((xmlSchemaQNameRefPtr) item)->name);
01344     case XML_SCHEMA_TYPE_NOTATION:
01345         return (((xmlSchemaNotationPtr) item)->name);
01346     default:
01347         /*
01348         * Other components cannot have names.
01349         */
01350         break;
01351     }
01352     return (NULL);
01353 }
01354 
01355 #define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
01356 #define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
01357 /*
01358 static const xmlChar *
01359 xmlSchemaGetQNameRefName(void *ref)
01360 {
01361     return(((xmlSchemaQNameRefPtr) ref)->name);
01362 }
01363 
01364 static const xmlChar *
01365 xmlSchemaGetQNameRefTargetNs(void *ref)
01366 {
01367     return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
01368 }
01369 */
01370 
01371 static const xmlChar *
01372 xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
01373 {
01374     switch (item->type) {
01375     case XML_SCHEMA_TYPE_ELEMENT:
01376         return (((xmlSchemaElementPtr) item)->targetNamespace);
01377     case XML_SCHEMA_TYPE_ATTRIBUTE:
01378         return (((xmlSchemaAttributePtr) item)->targetNamespace);
01379     case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
01380         return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
01381     case XML_SCHEMA_TYPE_BASIC:
01382         return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
01383     case XML_SCHEMA_TYPE_SIMPLE:
01384     case XML_SCHEMA_TYPE_COMPLEX:
01385         return (((xmlSchemaTypePtr) item)->targetNamespace);
01386     case XML_SCHEMA_TYPE_GROUP:
01387         return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
01388     case XML_SCHEMA_TYPE_IDC_KEY:
01389     case XML_SCHEMA_TYPE_IDC_UNIQUE:
01390     case XML_SCHEMA_TYPE_IDC_KEYREF:
01391         return (((xmlSchemaIDCPtr) item)->targetNamespace);
01392     case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
01393         if (WXS_ATTRUSE_DECL(item) != NULL) {
01394         return(xmlSchemaGetComponentTargetNs(
01395             WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
01396         }
01397         /* TODO: Will returning NULL break something? */
01398         break;
01399     case XML_SCHEMA_EXTRA_QNAMEREF:
01400         return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
01401     case XML_SCHEMA_TYPE_NOTATION:
01402         return (((xmlSchemaNotationPtr) item)->targetNamespace);
01403     default:
01404         /*
01405         * Other components cannot have names.
01406         */
01407         break;
01408     }
01409     return (NULL);
01410 }
01411 
01412 static const xmlChar*
01413 xmlSchemaGetComponentQName(xmlChar **buf,
01414                void *item)
01415 {
01416     return (xmlSchemaFormatQName(buf,
01417     xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
01418     xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
01419 }
01420 
01421 static const xmlChar*
01422 xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
01423 {
01424     xmlChar *str = NULL;
01425 
01426     *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
01427     *buf = xmlStrcat(*buf, BAD_CAST " '");
01428     *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
01429     (xmlSchemaBasicItemPtr) item));
01430     *buf = xmlStrcat(*buf, BAD_CAST "'");
01431     FREE_AND_NULL(str);
01432     return(*buf);
01433 }
01434 
01435 static const xmlChar*
01436 xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
01437 {
01438     return(xmlSchemaGetComponentDesignation(buf, idc));
01439 }
01440 
01448 static const xmlChar *
01449 xmlSchemaWildcardPCToString(int pc)
01450 {
01451     switch (pc) {
01452     case XML_SCHEMAS_ANY_SKIP:
01453         return (BAD_CAST "skip");
01454     case XML_SCHEMAS_ANY_LAX:
01455         return (BAD_CAST "lax");
01456     case XML_SCHEMAS_ANY_STRICT:
01457         return (BAD_CAST "strict");
01458     default:
01459         return (BAD_CAST "invalid process contents");
01460     }
01461 }
01462 
01475 static int
01476 xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
01477                    xmlSchemaWhitespaceValueType ws,
01478                    xmlChar **retValue)
01479 {
01480     int list;
01481     xmlSchemaValType valType;
01482     const xmlChar *value, *value2 = NULL;
01483 
01484 
01485     if ((retValue == NULL) || (val == NULL))
01486     return (-1);
01487     list = xmlSchemaValueGetNext(val) ? 1 : 0;
01488     *retValue = NULL;
01489     do {
01490     value = NULL;
01491     valType = xmlSchemaGetValType(val);
01492     switch (valType) {
01493         case XML_SCHEMAS_STRING:
01494         case XML_SCHEMAS_NORMSTRING:
01495         case XML_SCHEMAS_ANYSIMPLETYPE:
01496         value = xmlSchemaValueGetAsString(val);
01497         if (value != NULL) {
01498             if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
01499             value2 = xmlSchemaCollapseString(value);
01500             else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
01501             value2 = xmlSchemaWhiteSpaceReplace(value);
01502             if (value2 != NULL)
01503             value = value2;
01504         }
01505         break;
01506         default:
01507         if (xmlSchemaGetCanonValue(val, &value2) == -1) {
01508             if (value2 != NULL)
01509             xmlFree((xmlChar *) value2);
01510             goto internal_error;
01511         }
01512         value = value2;
01513     }
01514     if (*retValue == NULL)
01515         if (value == NULL) {
01516         if (! list)
01517             *retValue = xmlStrdup(BAD_CAST "");
01518         } else
01519         *retValue = xmlStrdup(value);
01520     else if (value != NULL) {
01521         /* List. */
01522         *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
01523         *retValue = xmlStrcat((xmlChar *) *retValue, value);
01524     }
01525     FREE_AND_NULL(value2)
01526     val = xmlSchemaValueGetNext(val);
01527     } while (val != NULL);
01528 
01529     return (0);
01530 internal_error:
01531     if (*retValue != NULL)
01532     xmlFree((xmlChar *) (*retValue));
01533     if (value2 != NULL)
01534     xmlFree((xmlChar *) value2);
01535     return (-1);
01536 }
01537 
01564 static xmlChar*
01565 xmlSchemaFormatItemForReport(xmlChar **buf,
01566              const xmlChar *itemDes,
01567              xmlSchemaBasicItemPtr item,
01568              xmlNodePtr itemNode)
01569 {
01570     xmlChar *str = NULL;
01571     int named = 1;
01572 
01573     if (*buf != NULL) {
01574     xmlFree(*buf);
01575     *buf = NULL;
01576     }
01577 
01578     if (itemDes != NULL) {
01579     *buf = xmlStrdup(itemDes);
01580     } else if (item != NULL) {
01581     switch (item->type) {
01582     case XML_SCHEMA_TYPE_BASIC: {
01583         xmlSchemaTypePtr type = WXS_TYPE_CAST item;
01584 
01585         if (WXS_IS_ATOMIC(type))
01586         *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
01587         else if (WXS_IS_LIST(type))
01588         *buf = xmlStrdup(BAD_CAST "list type 'xs:");
01589         else if (WXS_IS_UNION(type))
01590         *buf = xmlStrdup(BAD_CAST "union type 'xs:");
01591         else
01592         *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
01593         *buf = xmlStrcat(*buf, type->name);
01594         *buf = xmlStrcat(*buf, BAD_CAST "'");
01595         }
01596         break;
01597     case XML_SCHEMA_TYPE_SIMPLE: {
01598         xmlSchemaTypePtr type = WXS_TYPE_CAST item;
01599 
01600         if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
01601         *buf = xmlStrdup(BAD_CAST"");
01602         } else {
01603         *buf = xmlStrdup(BAD_CAST "local ");
01604         }
01605         if (WXS_IS_ATOMIC(type))
01606         *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
01607         else if (WXS_IS_LIST(type))
01608         *buf = xmlStrcat(*buf, BAD_CAST "list type");
01609         else if (WXS_IS_UNION(type))
01610         *buf = xmlStrcat(*buf, BAD_CAST "union type");
01611         else
01612         *buf = xmlStrcat(*buf, BAD_CAST "simple type");
01613         if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
01614         *buf = xmlStrcat(*buf, BAD_CAST " '");
01615         *buf = xmlStrcat(*buf, type->name);
01616         *buf = xmlStrcat(*buf, BAD_CAST "'");
01617         }
01618         }
01619         break;
01620     case XML_SCHEMA_TYPE_COMPLEX: {
01621         xmlSchemaTypePtr type = WXS_TYPE_CAST item;
01622 
01623         if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
01624         *buf = xmlStrdup(BAD_CAST "");
01625         else
01626         *buf = xmlStrdup(BAD_CAST "local ");
01627         *buf = xmlStrcat(*buf, BAD_CAST "complex type");
01628         if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
01629         *buf = xmlStrcat(*buf, BAD_CAST " '");
01630         *buf = xmlStrcat(*buf, type->name);
01631         *buf = xmlStrcat(*buf, BAD_CAST "'");
01632         }
01633         }
01634         break;
01635     case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
01636         xmlSchemaAttributeUsePtr ause;
01637 
01638         ause = WXS_ATTR_USE_CAST item;
01639         *buf = xmlStrdup(BAD_CAST "attribute use ");
01640         if (WXS_ATTRUSE_DECL(ause) != NULL) {
01641             *buf = xmlStrcat(*buf, BAD_CAST "'");
01642             *buf = xmlStrcat(*buf,
01643             xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
01644             FREE_AND_NULL(str)
01645             *buf = xmlStrcat(*buf, BAD_CAST "'");
01646         } else {
01647             *buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
01648         }
01649         }
01650         break;
01651     case XML_SCHEMA_TYPE_ATTRIBUTE: {
01652         xmlSchemaAttributePtr attr;
01653 
01654         attr = (xmlSchemaAttributePtr) item;
01655         *buf = xmlStrdup(BAD_CAST "attribute decl.");
01656         *buf = xmlStrcat(*buf, BAD_CAST " '");
01657         *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
01658             attr->targetNamespace, attr->name));
01659         FREE_AND_NULL(str)
01660             *buf = xmlStrcat(*buf, BAD_CAST "'");
01661         }
01662         break;
01663     case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
01664         xmlSchemaGetComponentDesignation(buf, item);
01665         break;
01666     case XML_SCHEMA_TYPE_ELEMENT: {
01667         xmlSchemaElementPtr elem;
01668 
01669         elem = (xmlSchemaElementPtr) item;
01670         *buf = xmlStrdup(BAD_CAST "element decl.");
01671         *buf = xmlStrcat(*buf, BAD_CAST " '");
01672         *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
01673             elem->targetNamespace, elem->name));
01674         *buf = xmlStrcat(*buf, BAD_CAST "'");
01675         }
01676         break;
01677     case XML_SCHEMA_TYPE_IDC_UNIQUE:
01678     case XML_SCHEMA_TYPE_IDC_KEY:
01679     case XML_SCHEMA_TYPE_IDC_KEYREF:
01680         if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
01681         *buf = xmlStrdup(BAD_CAST "unique '");
01682         else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
01683         *buf = xmlStrdup(BAD_CAST "key '");
01684         else
01685         *buf = xmlStrdup(BAD_CAST "keyRef '");
01686         *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
01687         *buf = xmlStrcat(*buf, BAD_CAST "'");
01688         break;
01689     case XML_SCHEMA_TYPE_ANY:
01690     case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
01691         *buf = xmlStrdup(xmlSchemaWildcardPCToString(
01692             ((xmlSchemaWildcardPtr) item)->processContents));
01693         *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
01694         break;
01695     case XML_SCHEMA_FACET_MININCLUSIVE:
01696     case XML_SCHEMA_FACET_MINEXCLUSIVE:
01697     case XML_SCHEMA_FACET_MAXINCLUSIVE:
01698     case XML_SCHEMA_FACET_MAXEXCLUSIVE:
01699     case XML_SCHEMA_FACET_TOTALDIGITS:
01700     case XML_SCHEMA_FACET_FRACTIONDIGITS:
01701     case XML_SCHEMA_FACET_PATTERN:
01702     case XML_SCHEMA_FACET_ENUMERATION:
01703     case XML_SCHEMA_FACET_WHITESPACE:
01704     case XML_SCHEMA_FACET_LENGTH:
01705     case XML_SCHEMA_FACET_MAXLENGTH:
01706     case XML_SCHEMA_FACET_MINLENGTH:
01707         *buf = xmlStrdup(BAD_CAST "facet '");
01708         *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
01709         *buf = xmlStrcat(*buf, BAD_CAST "'");
01710         break;
01711     case XML_SCHEMA_TYPE_GROUP: {
01712         *buf = xmlStrdup(BAD_CAST "model group def.");
01713         *buf = xmlStrcat(*buf, BAD_CAST " '");
01714         *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
01715         *buf = xmlStrcat(*buf, BAD_CAST "'");
01716         FREE_AND_NULL(str)
01717         }
01718         break;
01719     case XML_SCHEMA_TYPE_SEQUENCE:
01720     case XML_SCHEMA_TYPE_CHOICE:
01721     case XML_SCHEMA_TYPE_ALL:
01722     case XML_SCHEMA_TYPE_PARTICLE:
01723         *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
01724         break;
01725     case XML_SCHEMA_TYPE_NOTATION: {
01726         *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
01727         *buf = xmlStrcat(*buf, BAD_CAST " '");
01728         *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
01729         *buf = xmlStrcat(*buf, BAD_CAST "'");
01730         FREE_AND_NULL(str);
01731         }
01732     default:
01733         named = 0;
01734     }
01735     } else
01736     named = 0;
01737 
01738     if ((named == 0) && (itemNode != NULL)) {
01739     xmlNodePtr elem;
01740 
01741     if (itemNode->type == XML_ATTRIBUTE_NODE)
01742         elem = itemNode->parent;
01743     else
01744         elem = itemNode;
01745     *buf = xmlStrdup(BAD_CAST "Element '");
01746     if (elem->ns != NULL) {
01747         *buf = xmlStrcat(*buf,
01748         xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
01749         FREE_AND_NULL(str)
01750     } else
01751         *buf = xmlStrcat(*buf, elem->name);
01752     *buf = xmlStrcat(*buf, BAD_CAST "'");
01753 
01754     }
01755     if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
01756     *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
01757     if (itemNode->ns != NULL) {
01758         *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
01759         itemNode->ns->href, itemNode->name));
01760         FREE_AND_NULL(str)
01761     } else
01762         *buf = xmlStrcat(*buf, itemNode->name);
01763     *buf = xmlStrcat(*buf, BAD_CAST "'");
01764     }
01765     FREE_AND_NULL(str)
01766 
01767     return (*buf);
01768 }
01769 
01779 static const xmlChar *
01780 xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
01781                 xmlChar **buf, xmlSchemaTypePtr type)
01782 {
01783     xmlSchemaFacetPtr facet;
01784     xmlSchemaWhitespaceValueType ws;
01785     xmlChar *value = NULL;
01786     int res, found = 0;
01787 
01788     if (*buf != NULL)
01789     xmlFree(*buf);
01790     *buf = NULL;
01791 
01792     do {
01793     /*
01794     * Use the whitespace type of the base type.
01795     */
01796     ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
01797     for (facet = type->facets; facet != NULL; facet = facet->next) {
01798         if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
01799         continue;
01800         found = 1;
01801         res = xmlSchemaGetCanonValueWhtspExt(facet->val,
01802         ws, &value);
01803         if (res == -1) {
01804         xmlSchemaInternalErr(actxt,
01805             "xmlSchemaFormatFacetEnumSet",
01806             "compute the canonical lexical representation");
01807         if (*buf != NULL)
01808             xmlFree(*buf);
01809         *buf = NULL;
01810         return (NULL);
01811         }
01812         if (*buf == NULL)
01813         *buf = xmlStrdup(BAD_CAST "'");
01814         else
01815         *buf = xmlStrcat(*buf, BAD_CAST ", '");
01816         *buf = xmlStrcat(*buf, BAD_CAST value);
01817         *buf = xmlStrcat(*buf, BAD_CAST "'");
01818         if (value != NULL) {
01819         xmlFree((xmlChar *)value);
01820         value = NULL;
01821         }
01822     }
01823     /*
01824     * The enumeration facet of a type restricts the enumeration
01825     * facet of the ancestor type; i.e., such restricted enumerations
01826     * do not belong to the set of the given type. Thus we break
01827     * on the first found enumeration.
01828     */
01829     if (found)
01830         break;
01831     type = type->baseType;
01832     } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
01833 
01834     return ((const xmlChar *) *buf);
01835 }
01836 
01837 /************************************************************************
01838  *                                  *
01839  *          Error functions                     *
01840  *                                  *
01841  ************************************************************************/
01842 
01843 #if 0
01844 static void
01845 xmlSchemaErrMemory(const char *msg)
01846 {
01847     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
01848                      msg);
01849 }
01850 #endif
01851 
01852 static void
01853 xmlSchemaPSimpleErr(const char *msg)
01854 {
01855     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
01856                      msg);
01857 }
01858 
01866 static void
01867 xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
01868                     const char *extra, xmlNodePtr node)
01869 {
01870     if (ctxt != NULL)
01871         ctxt->nberrors++;
01872     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
01873                      extra);
01874 }
01875 
01887 static void
01888 xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
01889               const char *msg, const xmlChar * str1, const xmlChar * str2)
01890 {
01891     xmlGenericErrorFunc channel = NULL;
01892     xmlStructuredErrorFunc schannel = NULL;
01893     void *data = NULL;
01894 
01895     if (ctxt != NULL) {
01896         ctxt->nberrors++;
01897     ctxt->err = error;
01898         channel = ctxt->error;
01899         data = ctxt->errCtxt;
01900     schannel = ctxt->serror;
01901     }
01902     __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
01903                     error, XML_ERR_ERROR, NULL, 0,
01904                     (const char *) str1, (const char *) str2, NULL, 0, 0,
01905                     msg, str1, str2);
01906 }
01907 
01920 static void
01921 xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
01922                xmlNodePtr child, int error,
01923                const char *msg, const xmlChar * str1, const xmlChar * str2)
01924 {
01925     if (child != NULL)
01926         xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
01927     else
01928         xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
01929 }
01930 
01931 
01949 static void
01950 xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
01951         const xmlChar * strData1, const xmlChar * strData2,
01952         const xmlChar * strData3, const char *msg, const xmlChar * str1,
01953         const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
01954         const xmlChar * str5)
01955 {
01956 
01957     xmlGenericErrorFunc channel = NULL;
01958     xmlStructuredErrorFunc schannel = NULL;
01959     void *data = NULL;
01960 
01961     if (ctxt != NULL) {
01962         ctxt->nberrors++;
01963     ctxt->err = error;
01964         channel = ctxt->error;
01965         data = ctxt->errCtxt;
01966     schannel = ctxt->serror;
01967     }
01968     __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
01969                     error, XML_ERR_ERROR, NULL, 0,
01970                     (const char *) strData1, (const char *) strData2,
01971             (const char *) strData3, 0, 0, msg, str1, str2,
01972             str3, str4, str5);
01973 }
01974 
01975 /************************************************************************
01976  *                                  *
01977  *          Allround error functions            *
01978  *                                  *
01979  ************************************************************************/
01980 
01988 static void
01989 xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
01990                     const char *extra, xmlNodePtr node)
01991 {
01992     if (ctxt != NULL) {
01993         ctxt->nberrors++;
01994         ctxt->err = XML_SCHEMAV_INTERNAL;
01995     }
01996     __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
01997                      extra);
01998 }
01999 
02000 static void
02001 xmlSchemaPSimpleInternalErr(xmlNodePtr node,
02002                 const char *msg, const xmlChar *str)
02003 {
02004      __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node,
02005      msg, (const char *) str);
02006 }
02007 
02008 #define WXS_ERROR_TYPE_ERROR 1
02009 #define WXS_ERROR_TYPE_WARNING 2
02010 
02022 static void
02023 xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
02024           xmlErrorLevel errorLevel,
02025           int error, xmlNodePtr node, int line, const char *msg,
02026           const xmlChar *str1, const xmlChar *str2,
02027           const xmlChar *str3, const xmlChar *str4)
02028 {
02029     xmlStructuredErrorFunc schannel = NULL;
02030     xmlGenericErrorFunc channel = NULL;
02031     void *data = NULL;
02032 
02033     if (ctxt != NULL) {
02034     if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
02035         xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
02036         const char *file = NULL;
02037         if (errorLevel != XML_ERR_WARNING) {
02038         vctxt->nberrors++;
02039         vctxt->err = error;
02040         channel = vctxt->error;
02041         } else {
02042         channel = vctxt->warning;
02043         }
02044         schannel = vctxt->serror;
02045         data = vctxt->errCtxt;
02046 
02047         /*
02048         * Error node. If we specify a line number, then
02049         * do not channel any node to the error function.
02050         */
02051         if (line == 0) {
02052         if ((node == NULL) &&
02053             (vctxt->depth >= 0) &&
02054             (vctxt->inode != NULL)) {
02055             node = vctxt->inode->node;
02056         }
02057         /*
02058         * Get filename and line if no node-tree.
02059         */
02060         if ((node == NULL) &&
02061             (vctxt->parserCtxt != NULL) &&
02062             (vctxt->parserCtxt->input != NULL)) {
02063             file = vctxt->parserCtxt->input->filename;
02064             line = vctxt->parserCtxt->input->line;
02065         }
02066         } else {
02067         /*
02068         * Override the given node's (if any) position
02069         * and channel only the given line number.
02070         */
02071         node = NULL;
02072         /*
02073         * Get filename.
02074         */
02075         if (vctxt->doc != NULL)
02076             file = (const char *) vctxt->doc->URL;
02077         else if ((vctxt->parserCtxt != NULL) &&
02078             (vctxt->parserCtxt->input != NULL))
02079             file = vctxt->parserCtxt->input->filename;
02080         }
02081         __xmlRaiseError(schannel, channel, data, ctxt,
02082         node, XML_FROM_SCHEMASV,
02083         error, errorLevel, file, line,
02084         (const char *) str1, (const char *) str2,
02085         (const char *) str3, 0, 0, msg, str1, str2, str3, str4);
02086 
02087     } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
02088         xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
02089         if (errorLevel != XML_ERR_WARNING) {
02090         pctxt->nberrors++;
02091         pctxt->err = error;
02092         channel = pctxt->error;
02093         } else {
02094         channel = pctxt->warning;
02095         }
02096         schannel = pctxt->serror;
02097         data = pctxt->errCtxt;
02098         __xmlRaiseError(schannel, channel, data, ctxt,
02099         node, XML_FROM_SCHEMASP, error,
02100         errorLevel, NULL, 0,
02101         (const char *) str1, (const char *) str2,
02102         (const char *) str3, 0, 0, msg, str1, str2, str3, str4);
02103     } else {
02104         TODO
02105     }
02106     }
02107 }
02108 
02121 static void
02122 xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
02123           int error, xmlNodePtr node, const char *msg,
02124           const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
02125 {
02126     xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
02127     msg, str1, str2, str3, NULL);
02128 }
02129 
02130 static void
02131 xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
02132           int error, xmlNodePtr node, const char *msg,
02133           const xmlChar *str1, const xmlChar *str2,
02134           const xmlChar *str3, const xmlChar *str4)
02135 {
02136     xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
02137     msg, str1, str2, str3, str4);
02138 }
02139 
02140 static void
02141 xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
02142          int error, xmlNodePtr node, const char *msg,
02143          const xmlChar *str1, const xmlChar *str2)
02144 {
02145     xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
02146 }
02147 
02148 static xmlChar *
02149 xmlSchemaFormatNodeForError(xmlChar ** msg,
02150                 xmlSchemaAbstractCtxtPtr actxt,
02151                 xmlNodePtr node)
02152 {
02153     xmlChar *str = NULL;
02154 
02155     *msg = NULL;
02156     if ((node != NULL) &&
02157     (node->type != XML_ELEMENT_NODE) &&
02158     (node->type != XML_ATTRIBUTE_NODE))
02159     {
02160     /*
02161     * Don't try to format other nodes than element and
02162     * attribute nodes.
02163     * Play save and return an empty string.
02164     */
02165     *msg = xmlStrdup(BAD_CAST "");
02166     return(*msg);
02167     }
02168     if (node != NULL) {
02169     /*
02170     * Work on tree nodes.
02171     */
02172     if (node->type == XML_ATTRIBUTE_NODE) {
02173         xmlNodePtr elem = node->parent;
02174 
02175         *msg = xmlStrdup(BAD_CAST "Element '");
02176         if (elem->ns != NULL)
02177         *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
02178             elem->ns->href, elem->name));
02179         else
02180         *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
02181             NULL, elem->name));
02182         FREE_AND_NULL(str);
02183         *msg = xmlStrcat(*msg, BAD_CAST "', ");
02184         *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
02185     } else {
02186         *msg = xmlStrdup(BAD_CAST "Element '");
02187     }
02188     if (node->ns != NULL)
02189         *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
02190         node->ns->href, node->name));
02191     else
02192         *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
02193         NULL, node->name));
02194     FREE_AND_NULL(str);
02195     *msg = xmlStrcat(*msg, BAD_CAST "': ");
02196     } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
02197     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
02198     /*
02199     * Work on node infos.
02200     */
02201     if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
02202         xmlSchemaNodeInfoPtr ielem =
02203         vctxt->elemInfos[vctxt->depth];
02204 
02205         *msg = xmlStrdup(BAD_CAST "Element '");
02206         *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
02207         ielem->nsName, ielem->localName));
02208         FREE_AND_NULL(str);
02209         *msg = xmlStrcat(*msg, BAD_CAST "', ");
02210         *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
02211     } else {
02212         *msg = xmlStrdup(BAD_CAST "Element '");
02213     }
02214     *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
02215         vctxt->inode->nsName, vctxt->inode->localName));
02216     FREE_AND_NULL(str);
02217     *msg = xmlStrcat(*msg, BAD_CAST "': ");
02218     } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
02219     /*
02220     * Hmm, no node while parsing?
02221     * Return an empty string, in case NULL will break something.
02222     */
02223     *msg = xmlStrdup(BAD_CAST "");
02224     } else {
02225     TODO
02226     return (NULL);
02227     }
02228     /*
02229     * VAL TODO: The output of the given schema component is currently
02230     * disabled.
02231     */
02232 #if 0
02233     if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
02234     *msg = xmlStrcat(*msg, BAD_CAST " [");
02235     *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
02236         NULL, type, NULL, 0));
02237     FREE_AND_NULL(str)
02238     *msg = xmlStrcat(*msg, BAD_CAST "]");
02239     }
02240 #endif
02241     return (*msg);
02242 }
02243 
02244 static void
02245 xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
02246              const char *funcName,
02247              const char *message,
02248              const xmlChar *str1,
02249              const xmlChar *str2)
02250 {
02251     xmlChar *msg = NULL;
02252 
02253     if (actxt == NULL)
02254         return;
02255     msg = xmlStrdup(BAD_CAST "Internal error: ");
02256     msg = xmlStrcat(msg, BAD_CAST funcName);
02257     msg = xmlStrcat(msg, BAD_CAST ", ");
02258     msg = xmlStrcat(msg, BAD_CAST message);
02259     msg = xmlStrcat(msg, BAD_CAST ".\n");
02260 
02261     if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
02262     xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
02263         (const char *) msg, str1, str2);
02264 
02265     else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
02266     xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
02267         (const char *) msg, str1, str2);
02268 
02269     FREE_AND_NULL(msg)
02270 }
02271 
02272 static void
02273 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
02274              const char *funcName,
02275              const char *message)
02276 {
02277     xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
02278 }
02279 
02280 #if 0
02281 static void
02282 xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
02283              const char *funcName,
02284              const char *message,
02285              const xmlChar *str1,
02286              const xmlChar *str2)
02287 {
02288     xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
02289     str1, str2);
02290 }
02291 #endif
02292 
02293 static void
02294 xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
02295            xmlParserErrors error,
02296            xmlNodePtr node,
02297            xmlSchemaBasicItemPtr item,
02298            const char *message,
02299            const xmlChar *str1, const xmlChar *str2,
02300            const xmlChar *str3, const xmlChar *str4)
02301 {
02302     xmlChar *msg = NULL;
02303 
02304     if ((node == NULL) && (item != NULL) &&
02305     (actxt->type == XML_SCHEMA_CTXT_PARSER)) {
02306     node = WXS_ITEM_NODE(item);
02307     xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
02308     msg = xmlStrcat(msg, BAD_CAST ": ");
02309     } else
02310     xmlSchemaFormatNodeForError(&msg, actxt, node);
02311     msg = xmlStrcat(msg, (const xmlChar *) message);
02312     msg = xmlStrcat(msg, BAD_CAST ".\n");
02313     xmlSchemaErr4(actxt, error, node,
02314     (const char *) msg, str1, str2, str3, str4);
02315     FREE_AND_NULL(msg)
02316 }
02317 
02318 static void
02319 xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
02320            xmlParserErrors error,
02321            xmlNodePtr node,
02322            xmlSchemaBasicItemPtr item,
02323            const char *message,
02324            const xmlChar *str1,
02325            const xmlChar *str2)
02326 {
02327     xmlSchemaCustomErr4(actxt, error, node, item,
02328     message, str1, str2, NULL, NULL);
02329 }
02330 
02331 
02332 
02333 static void
02334 xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
02335            xmlParserErrors error,
02336            xmlNodePtr node,
02337            xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
02338            const char *message,
02339            const xmlChar *str1,
02340            const xmlChar *str2,
02341            const xmlChar *str3)
02342 {
02343     xmlChar *msg = NULL;
02344 
02345     xmlSchemaFormatNodeForError(&msg, actxt, node);
02346     msg = xmlStrcat(msg, (const xmlChar *) message);
02347     msg = xmlStrcat(msg, BAD_CAST ".\n");
02348 
02349     /* URGENT TODO: Set the error code to something sane. */
02350     xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
02351     (const char *) msg, str1, str2, str3, NULL);
02352 
02353     FREE_AND_NULL(msg)
02354 }
02355 
02356 
02357 
02358 static void
02359 xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
02360            xmlParserErrors error,
02361            xmlSchemaPSVIIDCNodePtr idcNode,
02362            xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
02363            const char *message,
02364            const xmlChar *str1,
02365            const xmlChar *str2)
02366 {
02367     xmlChar *msg = NULL, *qname = NULL;
02368 
02369     msg = xmlStrdup(BAD_CAST "Element '%s': ");
02370     msg = xmlStrcat(msg, (const xmlChar *) message);
02371     msg = xmlStrcat(msg, BAD_CAST ".\n");
02372     xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
02373     error, NULL, idcNode->nodeLine, (const char *) msg,
02374     xmlSchemaFormatQName(&qname,
02375         vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
02376         vctxt->nodeQNames->items[idcNode->nodeQNameID]),
02377     str1, str2, NULL);
02378     FREE_AND_NULL(qname);
02379     FREE_AND_NULL(msg);
02380 }
02381 
02382 static int
02383 xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
02384                xmlNodePtr node)
02385 {
02386     if (node != NULL)
02387     return (node->type);
02388     if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
02389     (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
02390     return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
02391     return (-1);
02392 }
02393 
02394 static int
02395 xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
02396 {
02397     switch (item->type) {
02398     case XML_SCHEMA_TYPE_COMPLEX:
02399     case XML_SCHEMA_TYPE_SIMPLE:
02400         if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
02401         return(1);
02402         break;
02403     case XML_SCHEMA_TYPE_GROUP:
02404         return (1);
02405     case XML_SCHEMA_TYPE_ELEMENT:
02406         if ( ((xmlSchemaElementPtr) item)->flags &
02407         XML_SCHEMAS_ELEM_GLOBAL)
02408         return(1);
02409         break;
02410     case XML_SCHEMA_TYPE_ATTRIBUTE:
02411         if ( ((xmlSchemaAttributePtr) item)->flags &
02412         XML_SCHEMAS_ATTR_GLOBAL)
02413         return(1);
02414         break;
02415     /* Note that attribute groups are always global. */
02416     default:
02417         return(1);
02418     }
02419     return (0);
02420 }
02421 
02422 static void
02423 xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
02424                xmlParserErrors error,
02425                xmlNodePtr node,
02426                const xmlChar *value,
02427                xmlSchemaTypePtr type,
02428                int displayValue)
02429 {
02430     xmlChar *msg = NULL;
02431 
02432     xmlSchemaFormatNodeForError(&msg, actxt, node);
02433 
02434     if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
02435         XML_ATTRIBUTE_NODE))
02436     msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
02437     else
02438     msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
02439         "value of ");
02440 
02441     if (! xmlSchemaIsGlobalItem(type))
02442     msg = xmlStrcat(msg, BAD_CAST "the local ");
02443     else
02444     msg = xmlStrcat(msg, BAD_CAST "the ");
02445 
02446     if (WXS_IS_ATOMIC(type))
02447     msg = xmlStrcat(msg, BAD_CAST "atomic type");
02448     else if (WXS_IS_LIST(type))
02449     msg = xmlStrcat(msg, BAD_CAST "list type");
02450     else if (WXS_IS_UNION(type))
02451     msg = xmlStrcat(msg, BAD_CAST "union type");
02452 
02453     if (xmlSchemaIsGlobalItem(type)) {
02454     xmlChar *str = NULL;
02455     msg = xmlStrcat(msg, BAD_CAST " '");
02456     if (type->builtInType != 0) {
02457         msg = xmlStrcat(msg, BAD_CAST "xs:");
02458         msg = xmlStrcat(msg, type->name);
02459     } else
02460         msg = xmlStrcat(msg,
02461         xmlSchemaFormatQName(&str,
02462             type->targetNamespace, type->name));
02463     msg = xmlStrcat(msg, BAD_CAST "'");
02464     FREE_AND_NULL(str);
02465     }
02466     msg = xmlStrcat(msg, BAD_CAST ".\n");
02467     if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
02468         XML_ATTRIBUTE_NODE))
02469     xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
02470     else
02471     xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
02472     FREE_AND_NULL(msg)
02473 }
02474 
02475 static const xmlChar *
02476 xmlSchemaFormatErrorNodeQName(xmlChar ** str,
02477                   xmlSchemaNodeInfoPtr ni,
02478                   xmlNodePtr node)
02479 {
02480     if (node != NULL) {
02481     if (node->ns != NULL)
02482         return (xmlSchemaFormatQName(str, node->ns->href, node->name));
02483     else
02484         return (xmlSchemaFormatQName(str, NULL, node->name));
02485     } else if (ni != NULL)
02486     return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
02487     return (NULL);
02488 }
02489 
02490 static void
02491 xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
02492             xmlParserErrors error,
02493             xmlSchemaAttrInfoPtr ni,
02494             xmlNodePtr node)
02495 {
02496     xmlChar *msg = NULL, *str = NULL;
02497 
02498     xmlSchemaFormatNodeForError(&msg, actxt, node);
02499     msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
02500     xmlSchemaErr(actxt, error, node, (const char *) msg,
02501     xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
02502     NULL);
02503     FREE_AND_NULL(str)
02504     FREE_AND_NULL(msg)
02505 }
02506 
02507 static void
02508 xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
02509                 xmlParserErrors error,
02510                 xmlNodePtr node,
02511             xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
02512             const char *message,
02513             int nbval,
02514             int nbneg,
02515             xmlChar **values)
02516 {
02517     xmlChar *str = NULL, *msg = NULL;
02518     xmlChar *localName, *nsName;
02519     const xmlChar *cur, *end;
02520     int i;
02521 
02522     xmlSchemaFormatNodeForError(&msg, actxt, node);
02523     msg = xmlStrcat(msg, (const xmlChar *) message);
02524     msg = xmlStrcat(msg, BAD_CAST ".");
02525     /*
02526     * Note that is does not make sense to report that we have a
02527     * wildcard here, since the wildcard might be unfolded into
02528     * multiple transitions.
02529     */
02530     if (nbval + nbneg > 0) {
02531     if (nbval + nbneg > 1) {
02532         str = xmlStrdup(BAD_CAST " Expected is one of ( ");
02533     } else
02534         str = xmlStrdup(BAD_CAST " Expected is ( ");
02535     nsName = NULL;
02536 
02537     for (i = 0; i < nbval + nbneg; i++) {
02538         cur = values[i];
02539         if (cur == NULL)
02540             continue;
02541         if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
02542             (cur[3] == ' ')) {
02543         cur += 4;
02544         str = xmlStrcat(str, BAD_CAST "##other");
02545         }
02546         /*
02547         * Get the local name.
02548         */
02549         localName = NULL;
02550 
02551         end = cur;
02552         if (*end == '*') {
02553         localName = xmlStrdup(BAD_CAST "*");
02554         end++;
02555         } else {
02556         while ((*end != 0) && (*end != '|'))
02557             end++;
02558         localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
02559         }
02560         if (*end != 0) {
02561         end++;
02562         /*
02563         * Skip "*|*" if they come with negated expressions, since
02564         * they represent the same negated wildcard.
02565         */
02566         if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
02567             /*
02568             * Get the namespace name.
02569             */
02570             cur = end;
02571             if (*end == '*') {
02572             nsName = xmlStrdup(BAD_CAST "{*}");
02573             } else {
02574             while (*end != 0)
02575                 end++;
02576 
02577             if (i >= nbval)
02578                 nsName = xmlStrdup(BAD_CAST "{##other:");
02579             else
02580                 nsName = xmlStrdup(BAD_CAST "{");
02581 
02582             nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
02583             nsName = xmlStrcat(nsName, BAD_CAST "}");
02584             }
02585             str = xmlStrcat(str, BAD_CAST nsName);
02586             FREE_AND_NULL(nsName)
02587         } else {
02588             FREE_AND_NULL(localName);
02589             continue;
02590         }
02591         }
02592         str = xmlStrcat(str, BAD_CAST localName);
02593         FREE_AND_NULL(localName);
02594 
02595         if (i < nbval + nbneg -1)
02596         str = xmlStrcat(str, BAD_CAST ", ");
02597     }
02598     str = xmlStrcat(str, BAD_CAST " ).\n");
02599     msg = xmlStrcat(msg, BAD_CAST str);
02600     FREE_AND_NULL(str)
02601     } else
02602       msg = xmlStrcat(msg, BAD_CAST "\n");
02603     xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
02604     xmlFree(msg);
02605 }
02606 
02607 static void
02608 xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
02609           xmlParserErrors error,
02610           xmlNodePtr node,
02611           const xmlChar *value,
02612           unsigned long length,
02613           xmlSchemaTypePtr type,
02614           xmlSchemaFacetPtr facet,
02615           const char *message,
02616           const xmlChar *str1,
02617           const xmlChar *str2)
02618 {
02619     xmlChar *str = NULL, *msg = NULL;
02620     xmlSchemaTypeType facetType;
02621     int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
02622 
02623     xmlSchemaFormatNodeForError(&msg, actxt, node);
02624     if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
02625     facetType = XML_SCHEMA_FACET_ENUMERATION;
02626     /*
02627     * If enumerations are validated, one must not expect the
02628     * facet to be given.
02629     */
02630     } else
02631     facetType = facet->type;
02632     msg = xmlStrcat(msg, BAD_CAST "[");
02633     msg = xmlStrcat(msg, BAD_CAST "facet '");
02634     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
02635     msg = xmlStrcat(msg, BAD_CAST "'] ");
02636     if (message == NULL) {
02637     /*
02638     * Use a default message.
02639     */
02640     if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
02641         (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
02642         (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
02643 
02644         char len[25], actLen[25];
02645 
02646         /* FIXME, TODO: What is the max expected string length of the
02647         * this value?
02648         */
02649         if (nodeType == XML_ATTRIBUTE_NODE)
02650         msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
02651         else
02652         msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
02653 
02654         snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
02655         snprintf(actLen, 24, "%lu", length);
02656 
02657         if (facetType == XML_SCHEMA_FACET_LENGTH)
02658         msg = xmlStrcat(msg,
02659         BAD_CAST "this differs from the allowed length of '%s'.\n");
02660         else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
02661         msg = xmlStrcat(msg,
02662         BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
02663         else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
02664         msg = xmlStrcat(msg,
02665         BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
02666 
02667         if (nodeType == XML_ATTRIBUTE_NODE)
02668         xmlSchemaErr3(actxt, error, node, (const char *) msg,
02669             value, (const xmlChar *) actLen, (const xmlChar *) len);
02670         else
02671         xmlSchemaErr(actxt, error, node, (const char *) msg,
02672             (const xmlChar *) actLen, (const xmlChar *) len);
02673 
02674     } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
02675         msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
02676         "of the set {%s}.\n");
02677         xmlSchemaErr(actxt, error, node, (const char *) msg, value,
02678         xmlSchemaFormatFacetEnumSet(actxt, &str, type));
02679     } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
02680         msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
02681         "by the pattern '%s'.\n");
02682         xmlSchemaErr(actxt, error, node, (const char *) msg, value,
02683         facet->value);
02684     } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
02685         msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
02686         "minimum value allowed ('%s').\n");
02687         xmlSchemaErr(actxt, error, node, (const char *) msg, value,
02688         facet->value);
02689     } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
02690         msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
02691         "maximum value allowed ('%s').\n");
02692         xmlSchemaErr(actxt, error, node, (const char *) msg, value,
02693         facet->value);
02694     } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
02695         msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
02696         "'%s'.\n");
02697         xmlSchemaErr(actxt, error, node, (const char *) msg, value,
02698         facet->value);
02699     } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
02700         msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
02701         "'%s'.\n");
02702         xmlSchemaErr(actxt, error, node, (const char *) msg, value,
02703         facet->value);
02704     } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
02705         msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
02706         "digits than are allowed ('%s').\n");
02707         xmlSchemaErr(actxt, error, node, (const char*) msg, value,
02708         facet->value);
02709     } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
02710         msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
02711         "digits than are allowed ('%s').\n");
02712         xmlSchemaErr(actxt, error, node, (const char*) msg, value,
02713         facet->value);
02714     } else if (nodeType == XML_ATTRIBUTE_NODE) {
02715         msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
02716         xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
02717     } else {
02718         msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
02719         xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
02720     }
02721     } else {
02722     msg = xmlStrcat(msg, (const xmlChar *) message);
02723     msg = xmlStrcat(msg, BAD_CAST ".\n");
02724     xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
02725     }
02726     FREE_AND_NULL(str)
02727     xmlFree(msg);
02728 }
02729 
02730 #define VERROR(err, type, msg) \
02731     xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
02732 
02733 #define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
02734 
02735 #define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
02736 #define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
02737 
02738 #define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
02739 
02740 
02753 static void
02754 xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
02755              xmlParserErrors error,
02756              xmlSchemaBasicItemPtr ownerItem,
02757              xmlNodePtr ownerElem,
02758              const char *name,
02759              const char *message)
02760 {
02761     xmlChar *des = NULL;
02762 
02763     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
02764 
02765     if (message != NULL)
02766     xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
02767     else
02768     xmlSchemaPErr(ctxt, ownerElem, error,
02769         "%s: The attribute '%s' is required but missing.\n",
02770         BAD_CAST des, BAD_CAST name);
02771     FREE_AND_NULL(des);
02772 }
02773 
02774 
02790 static void
02791 xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
02792              xmlParserErrors error,
02793              xmlSchemaBasicItemPtr ownerItem,
02794              xmlNodePtr ownerElem,
02795              const char *name,
02796              const xmlChar *refName,
02797              const xmlChar *refURI,
02798              xmlSchemaTypeType refType,
02799              const char *refTypeStr)
02800 {
02801     xmlChar *des = NULL, *strA = NULL;
02802 
02803     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
02804     if (refTypeStr == NULL)
02805     refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
02806     xmlSchemaPErrExt(ctxt, ownerElem, error,
02807         NULL, NULL, NULL,
02808         "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
02809         "%s.\n", BAD_CAST des, BAD_CAST name,
02810         xmlSchemaFormatQName(&strA, refURI, refName),
02811         BAD_CAST refTypeStr, NULL);
02812     FREE_AND_NULL(des)
02813     FREE_AND_NULL(strA)
02814 }
02815 
02826 static void
02827 xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
02828             xmlParserErrors error,
02829             xmlChar **ownerDes,
02830             xmlSchemaBasicItemPtr ownerItem,
02831             xmlAttrPtr attr,
02832             const char *msg)
02833 {
02834     xmlChar *des = NULL;
02835 
02836     if (ownerDes == NULL)
02837     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
02838     else if (*ownerDes == NULL) {
02839     xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
02840     des = *ownerDes;
02841     } else
02842     des = *ownerDes;
02843     if (attr == NULL) {
02844     xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL,
02845         "%s, attribute '%s': %s.\n",
02846         BAD_CAST des, (const xmlChar *) "Unknown",
02847         (const xmlChar *) msg, NULL, NULL);
02848     } else {
02849     xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
02850         "%s, attribute '%s': %s.\n",
02851         BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
02852     }
02853     if (ownerDes == NULL)
02854     FREE_AND_NULL(des);
02855 }
02856 
02867 static void
02868 xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
02869              xmlParserErrors error,
02870              xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
02871              xmlAttrPtr attr)
02872 {
02873     xmlChar *strA = NULL, *strB = NULL;
02874 
02875     xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
02876     xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
02877     "%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
02878     xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
02879     NULL, NULL);
02880     FREE_AND_NULL(strA);
02881     FREE_AND_NULL(strB);
02882 }
02883 
02898 static void
02899 xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
02900             xmlParserErrors error,
02901             xmlSchemaBasicItemPtr item,
02902             xmlNodePtr itemElem,
02903             const char *message,
02904             const xmlChar *str1,
02905             const xmlChar *str2,
02906             const xmlChar *str3)
02907 {
02908     xmlChar *des = NULL, *msg = NULL;
02909 
02910     xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
02911     msg = xmlStrdup(BAD_CAST "%s: ");
02912     msg = xmlStrcat(msg, (const xmlChar *) message);
02913     msg = xmlStrcat(msg, BAD_CAST ".\n");
02914     if ((itemElem == NULL) && (item != NULL))
02915     itemElem = WXS_ITEM_NODE(item);
02916     xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
02917     (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
02918     FREE_AND_NULL(des);
02919     FREE_AND_NULL(msg);
02920 }
02921 
02934 static void
02935 xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
02936             xmlParserErrors error,
02937             xmlSchemaBasicItemPtr item,
02938             xmlNodePtr itemElem,
02939             const char *message,
02940             const xmlChar *str1)
02941 {
02942     xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
02943     str1, NULL, NULL);
02944 }
02945 
02959 static void
02960 xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
02961             xmlParserErrors error,
02962             xmlNodePtr node,
02963             xmlSchemaBasicItemPtr ownerItem,
02964             const xmlSchemaAttributeUsePtr attruse,
02965             const char *message,
02966             const xmlChar *str1, const xmlChar *str2,
02967             const xmlChar *str3,const xmlChar *str4)
02968 {
02969     xmlChar *str = NULL, *msg = NULL;
02970 
02971     xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
02972     msg = xmlStrcat(msg, BAD_CAST ", ");
02973     msg = xmlStrcat(msg,
02974     BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
02975     WXS_BASIC_CAST attruse, NULL));
02976     FREE_AND_NULL(str);
02977     msg = xmlStrcat(msg, BAD_CAST ": ");
02978     msg = xmlStrcat(msg, (const xmlChar *) message);
02979     msg = xmlStrcat(msg, BAD_CAST ".\n");
02980     xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
02981     (const char *) msg, str1, str2, str3, str4);
02982     xmlFree(msg);
02983 }
02984 
02995 static void
02996 xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
02997               xmlParserErrors error,
02998               xmlSchemaTypePtr type,
02999               xmlSchemaTypePtr baseType,
03000               xmlSchemaFacetPtr facet)
03001 {
03002     xmlChar *des = NULL, *strT = NULL;
03003 
03004     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
03005     xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
03006     "%s: The facet '%s' is not allowed on types derived from the "
03007     "type %s.\n",
03008     BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
03009     xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
03010     NULL, NULL);
03011     FREE_AND_NULL(des);
03012     FREE_AND_NULL(strT);
03013 }
03014 
03025 static void
03026 xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
03027               xmlParserErrors error,
03028               xmlSchemaTypePtr type,
03029               xmlSchemaFacetPtr facet)
03030 {
03031     xmlChar *des = NULL;
03032 
03033     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
03034     type->node);
03035     xmlSchemaPErr(ctxt, type->node, error,
03036     "%s: The facet '%s' is not allowed.\n",
03037     BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
03038     FREE_AND_NULL(des);
03039 }
03040 
03051 static void
03052 xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
03053              xmlParserErrors error,
03054              xmlSchemaBasicItemPtr ownerItem,
03055              xmlAttrPtr attr,
03056              const char *name1,
03057              const char *name2)
03058 {
03059     xmlChar *des = NULL;
03060 
03061     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
03062     xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
03063     "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
03064     BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
03065     FREE_AND_NULL(des);
03066 }
03067 
03081 static void
03082 xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
03083             xmlParserErrors error,
03084             xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
03085             xmlNodePtr node,
03086             xmlSchemaTypePtr type,
03087             const char *expected,
03088             const xmlChar *value,
03089             const char *message,
03090             const xmlChar *str1,
03091             const xmlChar *str2)
03092 {
03093     xmlChar *msg = NULL;
03094 
03095     xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
03096     if (message == NULL) {
03097     /*
03098     * Use default messages.
03099     */
03100     if (type != NULL) {
03101         if (node->type == XML_ATTRIBUTE_NODE)
03102         msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
03103         else
03104         msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
03105         "valid value of ");
03106         if (! xmlSchemaIsGlobalItem(type))
03107         msg = xmlStrcat(msg, BAD_CAST "the local ");
03108         else
03109         msg = xmlStrcat(msg, BAD_CAST "the ");
03110 
03111         if (WXS_IS_ATOMIC(type))
03112         msg = xmlStrcat(msg, BAD_CAST "atomic type");
03113         else if (WXS_IS_LIST(type))
03114         msg = xmlStrcat(msg, BAD_CAST "list type");
03115         else if (WXS_IS_UNION(type))
03116         msg = xmlStrcat(msg, BAD_CAST "union type");
03117 
03118         if (xmlSchemaIsGlobalItem(type)) {
03119         xmlChar *str = NULL;
03120         msg = xmlStrcat(msg, BAD_CAST " '");
03121         if (type->builtInType != 0) {
03122             msg = xmlStrcat(msg, BAD_CAST "xs:");
03123             msg = xmlStrcat(msg, type->name);
03124         } else
03125             msg = xmlStrcat(msg,
03126             xmlSchemaFormatQName(&str,
03127                 type->targetNamespace, type->name));
03128         msg = xmlStrcat(msg, BAD_CAST "'.");
03129         FREE_AND_NULL(str);
03130         }
03131     } else {
03132         if (node->type == XML_ATTRIBUTE_NODE)
03133         msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
03134         else
03135         msg = xmlStrcat(msg, BAD_CAST "The character content is not "
03136         "valid.");
03137     }
03138     if (expected) {
03139         msg = xmlStrcat(msg, BAD_CAST " Expected is '");
03140         msg = xmlStrcat(msg, BAD_CAST expected);
03141         msg = xmlStrcat(msg, BAD_CAST "'.\n");
03142     } else
03143         msg = xmlStrcat(msg, BAD_CAST "\n");
03144     if (node->type == XML_ATTRIBUTE_NODE)
03145         xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
03146     else
03147         xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
03148     } else {
03149     msg = xmlStrcat(msg, BAD_CAST message);
03150     msg = xmlStrcat(msg, BAD_CAST ".\n");
03151     xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
03152          (const char*) msg, str1, str2, NULL, NULL, NULL);
03153     }
03154     /* Cleanup. */
03155     FREE_AND_NULL(msg)
03156 }
03157 
03171 static void
03172 xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
03173              xmlParserErrors error,
03174              xmlSchemaBasicItemPtr ownerItem,
03175              xmlNodePtr ownerElem,
03176              xmlNodePtr child,
03177              const char *message,
03178              const char *content)
03179 {
03180     xmlChar *des = NULL;
03181 
03182     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
03183     if (message != NULL)
03184     xmlSchemaPErr2(ctxt, ownerElem, child, error,
03185         "%s: %s.\n",
03186         BAD_CAST des, BAD_CAST message);
03187     else {
03188     if (content != NULL) {
03189         xmlSchemaPErr2(ctxt, ownerElem, child, error,
03190         "%s: The content is not valid. Expected is %s.\n",
03191         BAD_CAST des, BAD_CAST content);
03192     } else {
03193         xmlSchemaPErr2(ctxt, ownerElem, child, error,
03194         "%s: The content is not valid.\n",
03195         BAD_CAST des, NULL);
03196     }
03197     }
03198     FREE_AND_NULL(des)
03199 }
03200 
03201 /************************************************************************
03202  *                                  *
03203  *          Streamable error functions                      *
03204  *                                  *
03205  ************************************************************************/
03206 
03207 
03208 
03209 
03210 /************************************************************************
03211  *                                  *
03212  *          Validation helper functions         *
03213  *                                  *
03214  ************************************************************************/
03215 
03216 
03217 /************************************************************************
03218  *                                  *
03219  *          Allocation functions                *
03220  *                                  *
03221  ************************************************************************/
03222 
03231 static xmlSchemaPtr
03232 xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
03233 {
03234     xmlSchemaPtr ret;
03235 
03236     ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
03237     if (ret == NULL) {
03238         xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
03239         return (NULL);
03240     }
03241     memset(ret, 0, sizeof(xmlSchema));
03242     ret->dict = ctxt->dict;
03243     xmlDictReference(ret->dict);
03244 
03245     return (ret);
03246 }
03247 
03255 xmlSchemaFacetPtr
03256 xmlSchemaNewFacet(void)
03257 {
03258     xmlSchemaFacetPtr ret;
03259 
03260     ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
03261     if (ret == NULL) {
03262         return (NULL);
03263     }
03264     memset(ret, 0, sizeof(xmlSchemaFacet));
03265 
03266     return (ret);
03267 }
03268 
03278 static xmlSchemaAnnotPtr
03279 xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
03280 {
03281     xmlSchemaAnnotPtr ret;
03282 
03283     ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
03284     if (ret == NULL) {
03285         xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
03286         return (NULL);
03287     }
03288     memset(ret, 0, sizeof(xmlSchemaAnnot));
03289     ret->content = node;
03290     return (ret);
03291 }
03292 
03293 static xmlSchemaItemListPtr
03294 xmlSchemaItemListCreate(void)
03295 {
03296     xmlSchemaItemListPtr ret;
03297 
03298     ret = xmlMalloc(sizeof(xmlSchemaItemList));
03299     if (ret == NULL) {
03300     xmlSchemaPErrMemory(NULL,
03301         "allocating an item list structure", NULL);
03302     return (NULL);
03303     }
03304     memset(ret, 0, sizeof(xmlSchemaItemList));
03305     return (ret);
03306 }
03307 
03308 static void
03309 xmlSchemaItemListClear(xmlSchemaItemListPtr list)
03310 {
03311     if (list->items != NULL) {
03312     xmlFree(list->items);
03313     list->items = NULL;
03314     }
03315     list->nbItems = 0;
03316     list->sizeItems = 0;
03317 }
03318 
03319 static int
03320 xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
03321 {
03322     if (list->items == NULL) {
03323     list->items = (void **) xmlMalloc(
03324         20 * sizeof(void *));
03325     if (list->items == NULL) {
03326         xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
03327         return(-1);
03328     }
03329     list->sizeItems = 20;
03330     } else if (list->sizeItems <= list->nbItems) {
03331     list->sizeItems *= 2;
03332     list->items = (void **) xmlRealloc(list->items,
03333         list->sizeItems * sizeof(void *));
03334     if (list->items == NULL) {
03335         xmlSchemaPErrMemory(NULL, "growing item list", NULL);
03336         list->sizeItems = 0;
03337         return(-1);
03338     }
03339     }
03340     list->items[list->nbItems++] = item;
03341     return(0);
03342 }
03343 
03344 static int
03345 xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
03346              int initialSize,
03347              void *item)
03348 {
03349     if (list->items == NULL) {
03350     if (initialSize <= 0)
03351         initialSize = 1;
03352     list->items = (void **) xmlMalloc(
03353         initialSize * sizeof(void *));
03354     if (list->items == NULL) {
03355         xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
03356         return(-1);
03357     }
03358     list->sizeItems = initialSize;
03359     } else if (list->sizeItems <= list->nbItems) {
03360     list->sizeItems *= 2;
03361     list->items = (void **) xmlRealloc(list->items,
03362         list->sizeItems * sizeof(void *));
03363     if (list->items == NULL) {
03364         xmlSchemaPErrMemory(NULL, "growing item list", NULL);
03365         list->sizeItems = 0;
03366         return(-1);
03367     }
03368     }
03369     list->items[list->nbItems++] = item;
03370     return(0);
03371 }
03372 
03373 static int
03374 xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
03375 {
03376     if (list->items == NULL) {
03377     list->items = (void **) xmlMalloc(
03378         20 * sizeof(void *));
03379     if (list->items == NULL) {
03380         xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
03381         return(-1);
03382     }
03383     list->sizeItems = 20;
03384     } else if (list->sizeItems <= list->nbItems) {
03385     list->sizeItems *= 2;
03386     list->items = (void **) xmlRealloc(list->items,
03387         list->sizeItems * sizeof(void *));
03388     if (list->items == NULL) {
03389         xmlSchemaPErrMemory(NULL, "growing item list", NULL);
03390         list->sizeItems = 0;
03391         return(-1);
03392     }
03393     }
03394     /*
03395     * Just append if the index is greater/equal than the item count.
03396     */
03397     if (idx >= list->nbItems) {
03398     list->items[list->nbItems++] = item;
03399     } else {
03400     int i;
03401     for (i = list->nbItems; i > idx; i--)
03402         list->items[i] = list->items[i-1];
03403     list->items[idx] = item;
03404     list->nbItems++;
03405     }
03406     return(0);
03407 }
03408 
03409 #if 0 /* enable if ever needed */
03410 static int
03411 xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
03412                 int initialSize,
03413                 void *item,
03414                 int idx)
03415 {
03416     if (list->items == NULL) {
03417     if (initialSize <= 0)
03418         initialSize = 1;
03419     list->items = (void **) xmlMalloc(
03420         initialSize * sizeof(void *));
03421     if (list->items == NULL) {
03422         xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
03423         return(-1);
03424     }
03425     list->sizeItems = initialSize;
03426     } else if (list->sizeItems <= list->nbItems) {
03427     list->sizeItems *= 2;
03428     list->items = (void **) xmlRealloc(list->items,
03429         list->sizeItems * sizeof(void *));
03430     if (list->items == NULL) {
03431         xmlSchemaPErrMemory(NULL, "growing item list", NULL);
03432         list->sizeItems = 0;
03433         return(-1);
03434     }
03435     }
03436     /*
03437     * Just append if the index is greater/equal than the item count.
03438     */
03439     if (idx >= list->nbItems) {
03440     list->items[list->nbItems++] = item;
03441     } else {
03442     int i;
03443     for (i = list->nbItems; i > idx; i--)
03444         list->items[i] = list->items[i-1];
03445     list->items[idx] = item;
03446     list->nbItems++;
03447     }
03448     return(0);
03449 }
03450 #endif
03451 
03452 static int
03453 xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
03454 {
03455     int i;
03456     if ((list->items == NULL) || (idx >= list->nbItems)) {
03457     xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
03458         "index error.\n");
03459     return(-1);
03460     }
03461 
03462     if (list->nbItems == 1) {
03463     /* TODO: Really free the list? */
03464     xmlFree(list->items);
03465     list->items = NULL;
03466     list->nbItems = 0;
03467     list->sizeItems = 0;
03468     } else if (list->nbItems -1 == idx) {
03469     list->nbItems--;
03470     } else {
03471     for (i = idx; i < list->nbItems -1; i++)
03472         list->items[i] = list->items[i+1];
03473     list->nbItems--;
03474     }
03475     return(0);
03476 }
03477 
03484 static void
03485 xmlSchemaItemListFree(xmlSchemaItemListPtr list)
03486 {
03487     if (list == NULL)
03488     return;
03489     if (list->items != NULL)
03490     xmlFree(list->items);
03491     xmlFree(list);
03492 }
03493 
03494 static void
03495 xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
03496 {
03497     if (bucket == NULL)
03498     return;
03499     if (bucket->globals != NULL) {
03500     xmlSchemaComponentListFree(bucket->globals);
03501     xmlSchemaItemListFree(bucket->globals);
03502     }
03503     if (bucket->locals != NULL) {
03504     xmlSchemaComponentListFree(bucket->locals);
03505     xmlSchemaItemListFree(bucket->locals);
03506     }
03507     if (bucket->relations != NULL) {
03508     xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
03509     do {
03510         prev = cur;
03511         cur = cur->next;
03512         xmlFree(prev);
03513     } while (cur != NULL);
03514     }
03515     if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
03516     xmlFreeDoc(bucket->doc);
03517     }
03518     if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
03519     if (WXS_IMPBUCKET(bucket)->schema != NULL)
03520         xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
03521     }
03522     xmlFree(bucket);
03523 }
03524 
03525 static xmlSchemaBucketPtr
03526 xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
03527              int type, const xmlChar *targetNamespace)
03528 {
03529     xmlSchemaBucketPtr ret;
03530     int size;
03531     xmlSchemaPtr mainSchema;
03532 
03533     if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
03534     PERROR_INT("xmlSchemaBucketCreate",
03535         "no main schema on constructor");
03536     return(NULL);
03537     }
03538     mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
03539     /* Create the schema bucket. */
03540     if (WXS_IS_BUCKET_INCREDEF(type))
03541     size = sizeof(xmlSchemaInclude);
03542     else
03543     size = sizeof(xmlSchemaImport);
03544     ret = (xmlSchemaBucketPtr) xmlMalloc(size);
03545     if (ret == NULL) {
03546     xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
03547     return(NULL);
03548     }
03549     memset(ret, 0, size);
03550     ret->targetNamespace = targetNamespace;
03551     ret->type = type;
03552     ret->globals = xmlSchemaItemListCreate();
03553     if (ret->globals == NULL) {
03554     xmlFree(ret);
03555     return(NULL);
03556     }
03557     ret->locals = xmlSchemaItemListCreate();
03558     if (ret->locals == NULL) {
03559     xmlFree(ret);
03560     return(NULL);
03561     }
03562     /*
03563     * The following will assure that only the first bucket is marked as
03564     * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
03565     * For each following import buckets an xmlSchema will be created.
03566     * An xmlSchema will be created for every distinct targetNamespace.
03567     * We assign the targetNamespace to the schemata here.
03568     */
03569     if (! WXS_HAS_BUCKETS(pctxt)) {
03570     if (WXS_IS_BUCKET_INCREDEF(type)) {
03571         PERROR_INT("xmlSchemaBucketCreate",
03572         "first bucket but it's an include or redefine");
03573         xmlSchemaBucketFree(ret);
03574         return(NULL);
03575     }
03576     /* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
03577     ret->type = XML_SCHEMA_SCHEMA_MAIN;
03578     /* Point to the *main* schema. */
03579     WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
03580     WXS_IMPBUCKET(ret)->schema = mainSchema;
03581     /*
03582     * Ensure that the main schema gets a targetNamespace.
03583     */
03584     mainSchema->targetNamespace = targetNamespace;
03585     } else {
03586     if (type == XML_SCHEMA_SCHEMA_MAIN) {
03587         PERROR_INT("xmlSchemaBucketCreate",
03588         "main bucket but it's not the first one");
03589         xmlSchemaBucketFree(ret);
03590         return(NULL);
03591     } else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
03592         /*
03593         * Create a schema for imports and assign the
03594         * targetNamespace.
03595         */
03596         WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
03597         if (WXS_IMPBUCKET(ret)->schema == NULL) {
03598         xmlSchemaBucketFree(ret);
03599         return(NULL);
03600         }
03601         WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
03602     }
03603     }
03604     if (WXS_IS_BUCKET_IMPMAIN(type)) {
03605     int res;
03606     /*
03607     * Imports go into the "schemasImports" slot of the main *schema*.
03608     * Note that we create an import entry for the main schema as well; i.e.,
03609     * even if there's only one schema, we'll get an import.
03610     */
03611     if (mainSchema->schemasImports == NULL) {
03612         mainSchema->schemasImports = xmlHashCreateDict(5,
03613         WXS_CONSTRUCTOR(pctxt)->dict);
03614         if (mainSchema->schemasImports == NULL) {
03615         xmlSchemaBucketFree(ret);
03616         return(NULL);
03617         }
03618     }
03619     if (targetNamespace == NULL)
03620         res = xmlHashAddEntry(mainSchema->schemasImports,
03621         XML_SCHEMAS_NO_NAMESPACE, ret);
03622     else
03623         res = xmlHashAddEntry(mainSchema->schemasImports,
03624         targetNamespace, ret);
03625     if (res != 0) {
03626         PERROR_INT("xmlSchemaBucketCreate",
03627         "failed to add the schema bucket to the hash");
03628         xmlSchemaBucketFree(ret);
03629         return(NULL);
03630     }
03631     } else {
03632     /* Set the @ownerImport of an include bucket. */
03633     if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
03634         WXS_INCBUCKET(ret)->ownerImport =
03635         WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
03636     else
03637         WXS_INCBUCKET(ret)->ownerImport =
03638         WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
03639 
03640     /* Includes got into the "includes" slot of the *main* schema. */
03641     if (mainSchema->includes == NULL) {
03642         mainSchema->includes = xmlSchemaItemListCreate();
03643         if (mainSchema->includes == NULL) {
03644         xmlSchemaBucketFree(ret);
03645         return(NULL);
03646         }
03647     }
03648     xmlSchemaItemListAdd(mainSchema->includes, ret);
03649     }
03650     /*
03651     * Add to list of all buckets; this is used for lookup
03652     * during schema construction time only.
03653     */
03654     if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
03655     return(NULL);
03656     return(ret);
03657 }
03658 
03659 static int
03660 xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
03661 {
03662     if (*list == NULL) {
03663     *list = xmlSchemaItemListCreate();
03664     if (*list == NULL)
03665         return(-1);
03666     }
03667     xmlSchemaItemListAddSize(*list, initialSize, item);
03668     return(0);
03669 }
03670 
03677 static void
03678 xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
03679 {
03680     if (annot == NULL)
03681         return;
03682     if (annot->next == NULL) {
03683     xmlFree(annot);
03684     } else {
03685     xmlSchemaAnnotPtr prev;
03686 
03687     do {
03688         prev = annot;
03689         annot = annot->next;
03690         xmlFree(prev);
03691     } while (annot != NULL);
03692     }
03693 }
03694 
03701 static void
03702 xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
03703 {
03704     if (nota == NULL)
03705         return;
03706     xmlFree(nota);
03707 }
03708 
03715 static void
03716 xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
03717 {
03718     if (attr == NULL)
03719         return;
03720     if (attr->annot != NULL)
03721     xmlSchemaFreeAnnot(attr->annot);
03722     if (attr->defVal != NULL)
03723     xmlSchemaFreeValue(attr->defVal);
03724     xmlFree(attr);
03725 }
03726 
03733 static void
03734 xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
03735 {
03736     if (use == NULL)
03737         return;
03738     if (use->annot != NULL)
03739     xmlSchemaFreeAnnot(use->annot);
03740     if (use->defVal != NULL)
03741     xmlSchemaFreeValue(use->defVal);
03742     xmlFree(use);
03743 }
03744 
03751 static void
03752 xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
03753 {
03754     if (prohib == NULL)
03755         return;
03756     xmlFree(prohib);
03757 }
03758 
03765 static void
03766 xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
03767 {
03768     xmlSchemaWildcardNsPtr next;
03769 
03770     while (set != NULL) {
03771     next = set->next;
03772     xmlFree(set);
03773     set = next;
03774     }
03775 }
03776 
03783 void
03784 xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
03785 {
03786     if (wildcard == NULL)
03787         return;
03788     if (wildcard->annot != NULL)
03789         xmlSchemaFreeAnnot(wildcard->annot);
03790     if (wildcard->nsSet != NULL)
03791     xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
03792     if (wildcard->negNsSet != NULL)
03793     xmlFree(wildcard->negNsSet);
03794     xmlFree(wildcard);
03795 }
03796 
03803 static void
03804 xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
03805 {
03806     if (attrGr == NULL)
03807         return;
03808     if (attrGr->annot != NULL)
03809         xmlSchemaFreeAnnot(attrGr->annot);
03810     if (attrGr->attrUses != NULL)
03811     xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
03812     xmlFree(attrGr);
03813 }
03814 
03821 static void
03822 xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
03823 {
03824     xmlFree(item);
03825 }
03826 
03833 static void
03834 xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
03835 {
03836     xmlSchemaTypeLinkPtr next;
03837 
03838     while (link != NULL) {
03839     next = link->next;
03840     xmlFree(link);
03841     link = next;
03842     }
03843 }
03844 
03845 static void
03846 xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
03847 {
03848     xmlSchemaIDCStateObjPtr next;
03849     while (sto != NULL) {
03850     next = sto->next;
03851     if (sto->history != NULL)
03852         xmlFree(sto->history);
03853     if (sto->xpathCtxt != NULL)
03854         xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
03855     xmlFree(sto);
03856     sto = next;
03857     }
03858 }
03859 
03866 static void
03867 xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
03868 {
03869     xmlSchemaIDCSelectPtr cur, prev;
03870 
03871     if (idcDef == NULL)
03872     return;
03873     if (idcDef->annot != NULL)
03874         xmlSchemaFreeAnnot(idcDef->annot);
03875     /* Selector */
03876     if (idcDef->selector != NULL) {
03877     if (idcDef->selector->xpathComp != NULL)
03878         xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
03879     xmlFree(idcDef->selector);
03880     }
03881     /* Fields */
03882     if (idcDef->fields != NULL) {
03883     cur = idcDef->fields;
03884     do {
03885         prev = cur;
03886         cur = cur->next;
03887         if (prev->xpathComp != NULL)
03888         xmlFreePattern((xmlPatternPtr) prev->xpathComp);
03889         xmlFree(prev);
03890     } while (cur != NULL);
03891     }
03892     xmlFree(idcDef);
03893 }
03894 
03901 static void
03902 xmlSchemaFreeElement(xmlSchemaElementPtr elem)
03903 {
03904     if (elem == NULL)
03905         return;
03906     if (elem->annot != NULL)
03907         xmlSchemaFreeAnnot(elem->annot);
03908     if (elem->contModel != NULL)
03909         xmlRegFreeRegexp(elem->contModel);
03910     if (elem->defVal != NULL)
03911     xmlSchemaFreeValue(elem->defVal);
03912     xmlFree(elem);
03913 }
03914 
03921 void
03922 xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
03923 {
03924     if (facet == NULL)
03925         return;
03926     if (facet->val != NULL)
03927         xmlSchemaFreeValue(facet->val);
03928     if (facet->regexp != NULL)
03929         xmlRegFreeRegexp(facet->regexp);
03930     if (facet->annot != NULL)
03931         xmlSchemaFreeAnnot(facet->annot);
03932     xmlFree(facet);
03933 }
03934 
03941 void
03942 xmlSchemaFreeType(xmlSchemaTypePtr type)
03943 {
03944     if (type == NULL)
03945         return;
03946     if (type->annot != NULL)
03947         xmlSchemaFreeAnnot(type->annot);
03948     if (type->facets != NULL) {
03949         xmlSchemaFacetPtr facet, next;
03950 
03951         facet = type->facets;
03952         while (facet != NULL) {
03953             next = facet->next;
03954             xmlSchemaFreeFacet(facet);
03955             facet = next;
03956         }
03957     }
03958     if (type->attrUses != NULL)
03959     xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
03960     if (type->memberTypes != NULL)
03961     xmlSchemaFreeTypeLinkList(type->memberTypes);
03962     if (type->facetSet != NULL) {
03963     xmlSchemaFacetLinkPtr next, link;
03964 
03965     link = type->facetSet;
03966     do {
03967         next = link->next;
03968         xmlFree(link);
03969         link = next;
03970     } while (link != NULL);
03971     }
03972     if (type->contModel != NULL)
03973         xmlRegFreeRegexp(type->contModel);
03974     xmlFree(type);
03975 }
03976 
03983 static void
03984 xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
03985 {
03986     if (item->annot != NULL)
03987     xmlSchemaFreeAnnot(item->annot);
03988     xmlFree(item);
03989 }
03990 
03997 static void
03998 xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
03999 {
04000     if (item->annot != NULL)
04001     xmlSchemaFreeAnnot(item->annot);
04002     xmlFree(item);
04003 }
04004 
04005 static void
04006 xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
04007 {
04008     if ((list == NULL) || (list->nbItems == 0))
04009     return;
04010     {
04011     xmlSchemaTreeItemPtr item;
04012     xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
04013     int i;
04014 
04015     for (i = 0; i < list->nbItems; i++) {
04016         item = items[i];
04017         if (item == NULL)
04018         continue;
04019         switch (item->type) {
04020         case XML_SCHEMA_TYPE_SIMPLE:
04021         case XML_SCHEMA_TYPE_COMPLEX:
04022             xmlSchemaFreeType((xmlSchemaTypePtr) item);
04023             break;
04024         case XML_SCHEMA_TYPE_ATTRIBUTE:
04025             xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
04026             break;
04027         case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
04028             xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
04029             break;
04030         case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
04031             xmlSchemaFreeAttributeUseProhib(
04032             (xmlSchemaAttributeUseProhibPtr) item);
04033             break;
04034         case XML_SCHEMA_TYPE_ELEMENT:
04035             xmlSchemaFreeElement((xmlSchemaElementPtr) item);
04036             break;
04037         case XML_SCHEMA_TYPE_PARTICLE:
04038             if (item->annot != NULL)
04039             xmlSchemaFreeAnnot(item->annot);
04040             xmlFree(item);
04041             break;
04042         case XML_SCHEMA_TYPE_SEQUENCE:
04043         case XML_SCHEMA_TYPE_CHOICE:
04044         case XML_SCHEMA_TYPE_ALL:
04045             xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
04046             break;
04047         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
04048             xmlSchemaFreeAttributeGroup(
04049             (xmlSchemaAttributeGroupPtr) item);
04050             break;
04051         case XML_SCHEMA_TYPE_GROUP:
04052             xmlSchemaFreeModelGroupDef(
04053             (xmlSchemaModelGroupDefPtr) item);
04054             break;
04055         case XML_SCHEMA_TYPE_ANY:
04056         case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
04057             xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
04058             break;
04059         case XML_SCHEMA_TYPE_IDC_KEY:
04060         case XML_SCHEMA_TYPE_IDC_UNIQUE:
04061         case XML_SCHEMA_TYPE_IDC_KEYREF:
04062             xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
04063             break;
04064         case XML_SCHEMA_TYPE_NOTATION:
04065             xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
04066             break;
04067         case XML_SCHEMA_EXTRA_QNAMEREF:
04068             xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
04069             break;
04070         default: {
04071             /* TODO: This should never be hit. */
04072             xmlSchemaPSimpleInternalErr(NULL,
04073             "Internal error: xmlSchemaComponentListFree, "
04074             "unexpected component type '%s'\n",
04075             (const xmlChar *) WXS_ITEM_TYPE_NAME(item));
04076              }
04077             break;
04078         }
04079     }
04080     list->nbItems = 0;
04081     }
04082 }
04083 
04090 void
04091 xmlSchemaFree(xmlSchemaPtr schema)
04092 {
04093     if (schema == NULL)
04094         return;
04095     /* @volatiles is not used anymore :-/ */
04096     if (schema->volatiles != NULL)
04097     TODO
04098     /*
04099     * Note that those slots are not responsible for freeing
04100     * schema components anymore; this will now be done by
04101     * the schema buckets.
04102     */
04103     if (schema->notaDecl != NULL)
04104         xmlHashFree(schema->notaDecl, NULL);
04105     if (schema->attrDecl != NULL)
04106         xmlHashFree(schema->attrDecl, NULL);
04107     if (schema->attrgrpDecl != NULL)
04108         xmlHashFree(schema->attrgrpDecl, NULL);
04109     if (schema->elemDecl != NULL)
04110         xmlHashFree(schema->elemDecl, NULL);
04111     if (schema->typeDecl != NULL)
04112         xmlHashFree(schema->typeDecl, NULL);
04113     if (schema->groupDecl != NULL)
04114         xmlHashFree(schema->groupDecl, NULL);
04115     if (schema->idcDef != NULL)
04116         xmlHashFree(schema->idcDef, NULL);
04117 
04118     if (schema->schemasImports != NULL)
04119     xmlHashFree(schema->schemasImports,
04120             (xmlHashDeallocator) xmlSchemaBucketFree);
04121     if (schema->includes != NULL) {
04122     xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
04123     int i;
04124     for (i = 0; i < list->nbItems; i++) {
04125         xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
04126     }
04127     xmlSchemaItemListFree(list);
04128     }
04129     if (schema->annot != NULL)
04130         xmlSchemaFreeAnnot(schema->annot);
04131     /* Never free the doc here, since this will be done by the buckets. */
04132 
04133     xmlDictFree(schema->dict);
04134     xmlFree(schema);
04135 }
04136 
04137 /************************************************************************
04138  *                                  *
04139  *          Debug functions                 *
04140  *                                  *
04141  ************************************************************************/
04142 
04143 #ifdef LIBXML_OUTPUT_ENABLED
04144 
04145 static void
04146 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
04147 
04155 static void
04156 xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
04157                      const xmlChar * name ATTRIBUTE_UNUSED,
04158              const xmlChar * namespace ATTRIBUTE_UNUSED,
04159                      const xmlChar * context ATTRIBUTE_UNUSED)
04160 {
04161     if (elem == NULL)
04162         return;
04163 
04164 
04165     fprintf(output, "Element");
04166     if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
04167     fprintf(output, " (global)");
04168     fprintf(output, ": '%s' ", elem->name);
04169     if (namespace != NULL)
04170     fprintf(output, "ns '%s'", namespace);
04171     fprintf(output, "\n");
04172 #if 0
04173     if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
04174     fprintf(output, "  min %d ", elem->minOccurs);
04175         if (elem->maxOccurs >= UNBOUNDED)
04176             fprintf(output, "max: unbounded\n");
04177         else if (elem->maxOccurs != 1)
04178             fprintf(output, "max: %d\n", elem->maxOccurs);
04179         else
04180             fprintf(output, "\n");
04181     }
04182 #endif
04183     /*
04184     * Misc other properties.
04185     */
04186     if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
04187     (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
04188     (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
04189     (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
04190     fprintf(output, "  props: ");
04191     if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
04192         fprintf(output, "[fixed] ");
04193     if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
04194         fprintf(output, "[default] ");
04195     if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
04196         fprintf(output, "[abstract] ");
04197     if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
04198         fprintf(output, "[nillable] ");
04199     fprintf(output, "\n");
04200     }
04201     /*
04202     * Default/fixed value.
04203     */
04204     if (elem->value != NULL)
04205     fprintf(output, "  value: '%s'\n", elem->value);
04206     /*
04207     * Type.
04208     */
04209     if (elem->namedType != NULL) {
04210     fprintf(output, "  type: '%s' ", elem->namedType);
04211     if (elem->namedTypeNs != NULL)
04212         fprintf(output, "ns '%s'\n", elem->namedTypeNs);
04213     else
04214         fprintf(output, "\n");
04215     } else if (elem->subtypes != NULL) {
04216     /*
04217     * Dump local types.
04218     */
04219     xmlSchemaTypeDump(elem->subtypes, output);
04220     }
04221     /*
04222     * Substitution group.
04223     */
04224     if (elem->substGroup != NULL) {
04225     fprintf(output, "  substitutionGroup: '%s' ", elem->substGroup);
04226     if (elem->substGroupNs != NULL)
04227         fprintf(output, "ns '%s'\n", elem->substGroupNs);
04228     else
04229         fprintf(output, "\n");
04230     }
04231 }
04232 
04240 static void
04241 xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
04242 {
04243     xmlChar *content;
04244 
04245     if (annot == NULL)
04246         return;
04247 
04248     content = xmlNodeGetContent(annot->content);
04249     if (content != NULL) {
04250         fprintf(output, "  Annot: %s\n", content);
04251         xmlFree(content);
04252     } else
04253         fprintf(output, "  Annot: empty\n");
04254 }
04255 
04264 static void
04265 xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
04266 {
04267     xmlChar *str = NULL;
04268     xmlSchemaTreeItemPtr term;
04269     char shift[100];
04270     int i;
04271 
04272     if (particle == NULL)
04273     return;
04274     for (i = 0;((i < depth) && (i < 25));i++)
04275         shift[2 * i] = shift[2 * i + 1] = ' ';
04276     shift[2 * i] = shift[2 * i + 1] = 0;
04277     fprintf(output, "%s", shift);
04278     if (particle->children == NULL) {
04279     fprintf(output, "MISSING particle term\n");
04280     return;
04281     }
04282     term = particle->children;
04283     if (term == NULL) {
04284     fprintf(output, "(NULL)");
04285     } else {
04286     switch (term->type) {
04287         case XML_SCHEMA_TYPE_ELEMENT:
04288         fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
04289             ((xmlSchemaElementPtr)term)->targetNamespace,
04290             ((xmlSchemaElementPtr)term)->name));
04291         FREE_AND_NULL(str);
04292         break;
04293         case XML_SCHEMA_TYPE_SEQUENCE:
04294         fprintf(output, "SEQUENCE");
04295         break;
04296         case XML_SCHEMA_TYPE_CHOICE:
04297         fprintf(output, "CHOICE");
04298         break;
04299         case XML_SCHEMA_TYPE_ALL:
04300         fprintf(output, "ALL");
04301         break;
04302         case XML_SCHEMA_TYPE_ANY:
04303         fprintf(output, "ANY");
04304         break;
04305         default:
04306         fprintf(output, "UNKNOWN\n");
04307         return;
04308     }
04309     }
04310     if (particle->minOccurs != 1)
04311     fprintf(output, " min: %d", particle->minOccurs);
04312     if (particle->maxOccurs >= UNBOUNDED)
04313     fprintf(output, " max: unbounded");
04314     else if (particle->maxOccurs != 1)
04315     fprintf(output, " max: %d", particle->maxOccurs);
04316     fprintf(output, "\n");
04317     if (term &&
04318     ((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
04319      (term->type == XML_SCHEMA_TYPE_CHOICE) ||
04320      (term->type == XML_SCHEMA_TYPE_ALL)) &&
04321      (term->children != NULL)) {
04322     xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
04323         output, depth +1);
04324     }
04325     if (particle->next != NULL)
04326     xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
04327         output, depth);
04328 }
04329 
04337 static void
04338 xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
04339 {
04340     xmlSchemaAttributeUsePtr use;
04341     xmlSchemaAttributeUseProhibPtr prohib;
04342     xmlSchemaQNameRefPtr ref;
04343     const xmlChar *name, *tns;
04344     xmlChar *str = NULL;
04345     int i;
04346 
04347     if ((uses == NULL) || (uses->nbItems == 0))
04348         return;
04349 
04350     fprintf(output, "  attributes:\n");
04351     for (i = 0; i < uses->nbItems; i++) {
04352     use = uses->items[i];
04353     if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
04354         fprintf(output, "  [prohibition] ");
04355         prohib = (xmlSchemaAttributeUseProhibPtr) use;
04356         name = prohib->name;
04357         tns = prohib->targetNamespace;
04358     } else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
04359         fprintf(output, "  [reference] ");
04360         ref = (xmlSchemaQNameRefPtr) use;
04361         name = ref->name;
04362         tns = ref->targetNamespace;
04363     } else {
04364         fprintf(output, "  [use] ");
04365         name = WXS_ATTRUSE_DECL_NAME(use);
04366         tns = WXS_ATTRUSE_DECL_TNS(use);
04367     }
04368     fprintf(output, "'%s'\n",
04369         (const char *) xmlSchemaFormatQName(&str, tns, name));
04370     FREE_AND_NULL(str);
04371     }
04372 }
04373 
04381 static void
04382 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
04383 {
04384     if (type == NULL) {
04385         fprintf(output, "Type: NULL\n");
04386         return;
04387     }
04388     fprintf(output, "Type: ");
04389     if (type->name != NULL)
04390         fprintf(output, "'%s' ", type->name);
04391     else
04392         fprintf(output, "(no name) ");
04393     if (type->targetNamespace != NULL)
04394     fprintf(output, "ns '%s' ", type->targetNamespace);
04395     switch (type->type) {
04396         case XML_SCHEMA_TYPE_BASIC:
04397             fprintf(output, "[basic] ");
04398             break;
04399         case XML_SCHEMA_TYPE_SIMPLE:
04400             fprintf(output, "[simple] ");
04401             break;
04402         case XML_SCHEMA_TYPE_COMPLEX:
04403             fprintf(output, "[complex] ");
04404             break;
04405         case XML_SCHEMA_TYPE_SEQUENCE:
04406             fprintf(output, "[sequence] ");
04407             break;
04408         case XML_SCHEMA_TYPE_CHOICE:
04409             fprintf(output, "[choice] ");
04410             break;
04411         case XML_SCHEMA_TYPE_ALL:
04412             fprintf(output, "[all] ");
04413             break;
04414         case XML_SCHEMA_TYPE_UR:
04415             fprintf(output, "[ur] ");
04416             break;
04417         case XML_SCHEMA_TYPE_RESTRICTION:
04418             fprintf(output, "[restriction] ");
04419             break;
04420         case XML_SCHEMA_TYPE_EXTENSION:
04421             fprintf(output, "[extension] ");
04422             break;
04423         default:
04424             fprintf(output, "[unknown type %d] ", type->type);
04425             break;
04426     }
04427     fprintf(output, "content: ");
04428     switch (type->contentType) {
04429         case XML_SCHEMA_CONTENT_UNKNOWN:
04430             fprintf(output, "[unknown] ");
04431             break;
04432         case XML_SCHEMA_CONTENT_EMPTY:
04433             fprintf(output, "[empty] ");
04434             break;
04435         case XML_SCHEMA_CONTENT_ELEMENTS:
04436             fprintf(output, "[element] ");
04437             break;
04438         case XML_SCHEMA_CONTENT_MIXED:
04439             fprintf(output, "[mixed] ");
04440             break;
04441         case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
04442     /* not used. */
04443             break;
04444         case XML_SCHEMA_CONTENT_BASIC:
04445             fprintf(output, "[basic] ");
04446             break;
04447         case XML_SCHEMA_CONTENT_SIMPLE:
04448             fprintf(output, "[simple] ");
04449             break;
04450         case XML_SCHEMA_CONTENT_ANY:
04451             fprintf(output, "[any] ");
04452             break;
04453     }
04454     fprintf(output, "\n");
04455     if (type->base != NULL) {
04456         fprintf(output, "  base type: '%s'", type->base);
04457     if (type->baseNs != NULL)
04458         fprintf(output, " ns '%s'\n", type->baseNs);
04459     else
04460         fprintf(output, "\n");
04461     }
04462     if (type->attrUses != NULL)
04463     xmlSchemaAttrUsesDump(type->attrUses, output);
04464     if (type->annot != NULL)
04465         xmlSchemaAnnotDump(output, type->annot);
04466 #ifdef DUMP_CONTENT_MODEL
04467     if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
04468     (type->subtypes != NULL)) {
04469     xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
04470         output, 1);
04471     }
04472 #endif
04473 }
04474 
04482 void
04483 xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
04484 {
04485     if (output == NULL)
04486         return;
04487     if (schema == NULL) {
04488         fprintf(output, "Schemas: NULL\n");
04489         return;
04490     }
04491     fprintf(output, "Schemas: ");
04492     if (schema->name != NULL)
04493         fprintf(output, "%s, ", schema->name);
04494     else
04495         fprintf(output, "no name, ");
04496     if (schema->targetNamespace != NULL)
04497         fprintf(output, "%s", (const char *) schema->targetNamespace);
04498     else
04499         fprintf(output, "no target namespace");
04500     fprintf(output, "\n");
04501     if (schema->annot != NULL)
04502         xmlSchemaAnnotDump(output, schema->annot);
04503     xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
04504                 output);
04505     xmlHashScanFull(schema->elemDecl,
04506                     (xmlHashScannerFull) xmlSchemaElementDump, output);
04507 }
04508 
04509 #ifdef DEBUG_IDC_NODE_TABLE
04510 
04516 static void
04517 xmlSchemaDebugDumpIDCTable(FILE * output,
04518                const xmlChar *namespaceName,
04519                const xmlChar *localName,
04520                xmlSchemaPSVIIDCBindingPtr bind)
04521 {
04522     xmlChar *str = NULL;
04523     const xmlChar *value;
04524     xmlSchemaPSVIIDCNodePtr tab;
04525     xmlSchemaPSVIIDCKeyPtr key;
04526     int i, j, res;
04527 
04528     fprintf(output, "IDC: TABLES on '%s'\n",
04529     xmlSchemaFormatQName(&str, namespaceName, localName));
04530     FREE_AND_NULL(str)
04531 
04532     if (bind == NULL)
04533     return;
04534     do {
04535     fprintf(output, "IDC:   BINDING '%s' (%d)\n",
04536         xmlSchemaGetComponentQName(&str,
04537         bind->definition), bind->nbNodes);
04538     FREE_AND_NULL(str)
04539     for (i = 0; i < bind->nbNodes; i++) {
04540         tab = bind->nodeTable[i];
04541         fprintf(output, "         ( ");
04542         for (j = 0; j < bind->definition->nbFields; j++) {
04543         key = tab->keys[j];
04544         if ((key != NULL) && (key->val != NULL)) {
04545             res = xmlSchemaGetCanonValue(key->val, &value);
04546             if (res >= 0)
04547             fprintf(output, "'%s' ", value);
04548             else
04549             fprintf(output, "CANON-VALUE-FAILED ");
04550             if (res == 0)
04551             FREE_AND_NULL(value)
04552         } else if (key != NULL)
04553             fprintf(output, "(no val), ");
04554         else
04555             fprintf(output, "(key missing), ");
04556         }
04557         fprintf(output, ")\n");
04558     }
04559     if (bind->dupls && bind->dupls->nbItems) {
04560         fprintf(output, "IDC:     dupls (%d):\n", bind->dupls->nbItems);
04561         for (i = 0; i < bind->dupls->nbItems; i++) {
04562         tab = bind->dupls->items[i];
04563         fprintf(output, "         ( ");
04564         for (j = 0; j < bind->definition->nbFields; j++) {
04565             key = tab->keys[j];
04566             if ((key != NULL) && (key->val != NULL)) {
04567             res = xmlSchemaGetCanonValue(key->val, &value);
04568             if (res >= 0)
04569                 fprintf(output, "'%s' ", value);
04570             else
04571                 fprintf(output, "CANON-VALUE-FAILED ");
04572             if (res == 0)
04573                 FREE_AND_NULL(value)
04574             } else if (key != NULL)
04575             fprintf(output, "(no val), ");
04576             else
04577                 fprintf(output, "(key missing), ");
04578         }
04579         fprintf(output, ")\n");
04580         }
04581     }
04582     bind = bind->next;
04583     } while (bind != NULL);
04584 }
04585 #endif /* DEBUG_IDC */
04586 #endif /* LIBXML_OUTPUT_ENABLED */
04587 
04588 /************************************************************************
04589  *                                  *
04590  *          Utilities                   *
04591  *                                  *
04592  ************************************************************************/
04593 
04604 static xmlAttrPtr
04605 xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
04606 {
04607     xmlAttrPtr prop;
04608 
04609     if ((node == NULL) || (name == NULL))
04610     return(NULL);
04611     prop = node->properties;
04612     while (prop != NULL) {
04613         if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
04614         return(prop);
04615     prop = prop->next;
04616     }
04617     return (NULL);
04618 }
04619 
04631 static xmlAttrPtr
04632 xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
04633 {
04634     xmlAttrPtr prop;
04635 
04636     if ((node == NULL) || (name == NULL))
04637     return(NULL);
04638     prop = node->properties;
04639     while (prop != NULL) {
04640     if ((prop->ns != NULL) &&
04641         xmlStrEqual(prop->name, BAD_CAST name) &&
04642         xmlStrEqual(prop->ns->href, BAD_CAST uri))
04643         return(prop);
04644     prop = prop->next;
04645     }
04646     return (NULL);
04647 }
04648 
04649 static const xmlChar *
04650 xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
04651 {
04652     xmlChar *val;
04653     const xmlChar *ret;
04654 
04655     val = xmlNodeGetContent(node);
04656     if (val == NULL)
04657     val = xmlStrdup((xmlChar *)"");
04658     ret = xmlDictLookup(ctxt->dict, val, -1);
04659     xmlFree(val);
04660     return(ret);
04661 }
04662 
04663 static const xmlChar *
04664 xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
04665 {
04666     return((const xmlChar*) xmlNodeGetContent(node));
04667 }
04668 
04679 static const xmlChar *
04680 xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
04681                  const char *name)
04682 {
04683     xmlChar *val;
04684     const xmlChar *ret;
04685 
04686     val = xmlGetNoNsProp(node, BAD_CAST name);
04687     if (val == NULL)
04688         return(NULL);
04689     ret = xmlDictLookup(ctxt->dict, val, -1);
04690     xmlFree(val);
04691     return(ret);
04692 }
04693 
04694 /************************************************************************
04695  *                                  *
04696  *          Parsing functions               *
04697  *                                  *
04698  ************************************************************************/
04699 
04700 #define WXS_FIND_GLOBAL_ITEM(slot)          \
04701     if (xmlStrEqual(nsName, schema->targetNamespace)) { \
04702     ret = xmlHashLookup(schema->slot, name); \
04703     if (ret != NULL) goto exit; \
04704     } \
04705     if (xmlHashSize(schema->schemasImports) > 1) { \
04706     xmlSchemaImportPtr import; \
04707     if (nsName == NULL) \
04708         import = xmlHashLookup(schema->schemasImports, \
04709         XML_SCHEMAS_NO_NAMESPACE); \
04710     else \
04711         import = xmlHashLookup(schema->schemasImports, nsName); \
04712     if (import == NULL) \
04713         goto exit; \
04714     ret = xmlHashLookup(import->schema->slot, name); \
04715     }
04716 
04727 static xmlSchemaElementPtr
04728 xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
04729                  const xmlChar * nsName)
04730 {
04731     xmlSchemaElementPtr ret = NULL;
04732 
04733     if ((name == NULL) || (schema == NULL))
04734         return(NULL);
04735     if (schema != NULL) {
04736     WXS_FIND_GLOBAL_ITEM(elemDecl)
04737     }
04738 exit:
04739 #ifdef DEBUG
04740     if (ret == NULL) {
04741         if (nsName == NULL)
04742             fprintf(stderr, "Unable to lookup element decl. %s", name);
04743         else
04744             fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
04745                     nsName);
04746     }
04747 #endif
04748     return (ret);
04749 }
04750 
04761 static xmlSchemaTypePtr
04762 xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
04763                  const xmlChar * nsName)
04764 {
04765     xmlSchemaTypePtr ret = NULL;
04766 
04767     if (name == NULL)
04768         return (NULL);
04769     /* First try the built-in types. */
04770     if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
04771     ret = xmlSchemaGetPredefinedType(name, nsName);
04772     if (ret != NULL)
04773         goto exit;
04774     /*
04775     * Note that we try the parsed schemas as well here
04776     * since one might have parsed the S4S, which contain more
04777     * than the built-in types.
04778     * TODO: Can we optimize this?
04779     */
04780     }
04781     if (schema != NULL) {
04782     WXS_FIND_GLOBAL_ITEM(typeDecl)
04783     }
04784 exit:
04785 
04786 #ifdef DEBUG
04787     if (ret == NULL) {
04788         if (nsName == NULL)
04789             fprintf(stderr, "Unable to lookup type %s", name);
04790         else
04791             fprintf(stderr, "Unable to lookup type %s:%s", name,
04792                     nsName);
04793     }
04794 #endif
04795     return (ret);
04796 }
04797 
04808 static xmlSchemaAttributePtr
04809 xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
04810                  const xmlChar * nsName)
04811 {
04812     xmlSchemaAttributePtr ret = NULL;
04813 
04814     if ((name == NULL) || (schema == NULL))
04815         return (NULL);
04816     if (schema != NULL) {
04817     WXS_FIND_GLOBAL_ITEM(attrDecl)
04818     }
04819 exit:
04820 #ifdef DEBUG
04821     if (ret == NULL) {
04822         if (nsName == NULL)
04823             fprintf(stderr, "Unable to lookup attribute %s", name);
04824         else
04825             fprintf(stderr, "Unable to lookup attribute %s:%s", name,
04826                     nsName);
04827     }
04828 #endif
04829     return (ret);
04830 }
04831 
04842 static xmlSchemaAttributeGroupPtr
04843 xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
04844                  const xmlChar * nsName)
04845 {
04846     xmlSchemaAttributeGroupPtr ret = NULL;
04847 
04848     if ((name == NULL) || (schema == NULL))
04849         return (NULL);
04850     if (schema != NULL) {
04851     WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
04852     }
04853 exit:
04854     /* TODO:
04855     if ((ret != NULL) && (ret->redef != NULL)) {
04856     * Return the last redefinition. *
04857     ret = ret->redef;
04858     }
04859     */
04860 #ifdef DEBUG
04861     if (ret == NULL) {
04862         if (nsName == NULL)
04863             fprintf(stderr, "Unable to lookup attribute group %s", name);
04864         else
04865             fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
04866                     nsName);
04867     }
04868 #endif
04869     return (ret);
04870 }
04871 
04882 static xmlSchemaModelGroupDefPtr
04883 xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
04884                  const xmlChar * nsName)
04885 {
04886     xmlSchemaModelGroupDefPtr ret = NULL;
04887 
04888     if ((name == NULL) || (schema == NULL))
04889         return (NULL);
04890     if (schema != NULL) {
04891     WXS_FIND_GLOBAL_ITEM(groupDecl)
04892     }
04893 exit:
04894 
04895 #ifdef DEBUG
04896     if (ret == NULL) {
04897         if (nsName == NULL)
04898             fprintf(stderr, "Unable to lookup group %s", name);
04899         else
04900             fprintf(stderr, "Unable to lookup group %s:%s", name,
04901                     nsName);
04902     }
04903 #endif
04904     return (ret);
04905 }
04906 
04907 static xmlSchemaNotationPtr
04908 xmlSchemaGetNotation(xmlSchemaPtr schema,
04909              const xmlChar *name,
04910              const xmlChar *nsName)
04911 {
04912     xmlSchemaNotationPtr ret = NULL;
04913 
04914     if ((name == NULL) || (schema == NULL))
04915         return (NULL);
04916     if (schema != NULL) {
04917     WXS_FIND_GLOBAL_ITEM(notaDecl)
04918     }
04919 exit:
04920     return (ret);
04921 }
04922 
04923 static xmlSchemaIDCPtr
04924 xmlSchemaGetIDC(xmlSchemaPtr schema,
04925         const xmlChar *name,
04926         const xmlChar *nsName)
04927 {
04928     xmlSchemaIDCPtr ret = NULL;
04929 
04930     if ((name == NULL) || (schema == NULL))
04931         return (NULL);
04932     if (schema != NULL) {
04933     WXS_FIND_GLOBAL_ITEM(idcDef)
04934     }
04935 exit:
04936     return (ret);
04937 }
04938 
04949 static xmlSchemaBasicItemPtr
04950 xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
04951                xmlSchemaTypeType itemType,
04952                const xmlChar *name,
04953                const xmlChar *targetNs)
04954 {
04955     switch (itemType) {
04956     case XML_SCHEMA_TYPE_GROUP:
04957         return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
04958         name, targetNs));
04959     case XML_SCHEMA_TYPE_ELEMENT:
04960         return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
04961         name, targetNs));
04962     default:
04963         TODO
04964         return (NULL);
04965     }
04966 }
04967 
04968 /************************************************************************
04969  *                                  *
04970  *          Parsing functions               *
04971  *                                  *
04972  ************************************************************************/
04973 
04974 #define IS_BLANK_NODE(n)                        \
04975     (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
04976 
04986 static int
04987 xmlSchemaIsBlank(xmlChar * str, int len)
04988 {
04989     if (str == NULL)
04990         return (1);
04991     if (len < 0) {
04992     while (*str != 0) {
04993         if (!(IS_BLANK_CH(*str)))
04994         return (0);
04995         str++;
04996     }
04997     } else while ((*str != 0) && (len != 0)) {
04998     if (!(IS_BLANK_CH(*str)))
04999         return (0);
05000     str++;
05001     len--;
05002     }
05003 
05004     return (1);
05005 }
05006 
05007 #define WXS_COMP_NAME(c, t) ((t) (c))->name
05008 #define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
05009 /*
05010 * xmlSchemaFindRedefCompInGraph:
05011 * ATTENTION TODO: This uses pointer comp. for strings.
05012 */
05013 static xmlSchemaBasicItemPtr
05014 xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
05015                   xmlSchemaTypeType type,
05016                   const xmlChar *name,
05017                   const xmlChar *nsName)
05018 {
05019     xmlSchemaBasicItemPtr ret;
05020     int i;
05021 
05022     if ((bucket == NULL) || (name == NULL))
05023     return(NULL);
05024     if ((bucket->globals == NULL) ||
05025     (bucket->globals->nbItems == 0))
05026     goto subschemas;
05027     /*
05028     * Search in global components.
05029     */
05030     for (i = 0; i < bucket->globals->nbItems; i++) {
05031     ret = bucket->globals->items[i];
05032     if (ret->type == type) {
05033         switch (type) {
05034         case XML_SCHEMA_TYPE_COMPLEX:
05035         case XML_SCHEMA_TYPE_SIMPLE:
05036             if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
05037             (WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
05038             nsName))
05039             {
05040             return(ret);
05041             }
05042             break;
05043         case XML_SCHEMA_TYPE_GROUP:
05044             if ((WXS_COMP_NAME(ret,
05045                 xmlSchemaModelGroupDefPtr) == name) &&
05046             (WXS_COMP_TNS(ret,
05047                 xmlSchemaModelGroupDefPtr) == nsName))
05048             {
05049             return(ret);
05050             }
05051             break;
05052         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
05053             if ((WXS_COMP_NAME(ret,
05054                 xmlSchemaAttributeGroupPtr) == name) &&
05055             (WXS_COMP_TNS(ret,
05056                 xmlSchemaAttributeGroupPtr) == nsName))
05057             {
05058             return(ret);
05059             }
05060             break;
05061         default:
05062             /* Should not be hit. */
05063             return(NULL);
05064         }
05065     }
05066     }
05067 subschemas:
05068     /*
05069     * Process imported/included schemas.
05070     */
05071     if (bucket->relations != NULL) {
05072     xmlSchemaSchemaRelationPtr rel = bucket->relations;
05073 
05074     /*
05075     * TODO: Marking the bucket will not avoid multiple searches
05076     * in the same schema, but avoids at least circularity.
05077     */
05078     bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
05079     do {
05080         if ((rel->bucket != NULL) &&
05081         ((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
05082         ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
05083             type, name, nsName);
05084         if (ret != NULL)
05085             return(ret);
05086         }
05087         rel = rel->next;
05088     } while (rel != NULL);
05089      bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
05090     }
05091     return(NULL);
05092 }
05093 
05105 static xmlSchemaNotationPtr
05106 xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
05107                      const xmlChar *name, const xmlChar *nsName,
05108              xmlNodePtr node ATTRIBUTE_UNUSED)
05109 {
05110     xmlSchemaNotationPtr ret = NULL;
05111 
05112     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
05113         return (NULL);
05114 
05115     ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
05116     if (ret == NULL) {
05117         xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
05118         return (NULL);
05119     }
05120     memset(ret, 0, sizeof(xmlSchemaNotation));
05121     ret->type = XML_SCHEMA_TYPE_NOTATION;
05122     ret->name = name;
05123     ret->targetNamespace = nsName;
05124     /* TODO: do we need the node to be set?
05125     * ret->node = node;*/
05126     WXS_ADD_GLOBAL(ctxt, ret);
05127     return (ret);
05128 }
05129 
05142 static xmlSchemaAttributePtr
05143 xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
05144                       const xmlChar * name, const xmlChar * nsName,
05145               xmlNodePtr node, int topLevel)
05146 {
05147     xmlSchemaAttributePtr ret = NULL;
05148 
05149     if ((ctxt == NULL) || (schema == NULL))
05150         return (NULL);
05151 
05152     ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
05153     if (ret == NULL) {
05154         xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
05155         return (NULL);
05156     }
05157     memset(ret, 0, sizeof(xmlSchemaAttribute));
05158     ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
05159     ret->node = node;
05160     ret->name = name;
05161     ret->targetNamespace = nsName;
05162 
05163     if (topLevel)
05164     WXS_ADD_GLOBAL(ctxt, ret);
05165     else
05166     WXS_ADD_LOCAL(ctxt, ret);
05167     WXS_ADD_PENDING(ctxt, ret);
05168     return (ret);
05169 }
05170 
05183 static xmlSchemaAttributeUsePtr
05184 xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
05185              xmlNodePtr node)
05186 {
05187     xmlSchemaAttributeUsePtr ret = NULL;
05188 
05189     if (pctxt == NULL)
05190         return (NULL);
05191 
05192     ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
05193     if (ret == NULL) {
05194         xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
05195         return (NULL);
05196     }
05197     memset(ret, 0, sizeof(xmlSchemaAttributeUse));
05198     ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
05199     ret->node = node;
05200 
05201     WXS_ADD_LOCAL(pctxt, ret);
05202     return (ret);
05203 }
05204 
05205 /*
05206 * xmlSchemaAddRedef:
05207 *
05208 * Adds a redefinition information. This is used at a later stage to:
05209 * resolve references to the redefined components and to check constraints.
05210 */
05211 static xmlSchemaRedefPtr
05212 xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
05213           xmlSchemaBucketPtr targetBucket,
05214           void *item,
05215           const xmlChar *refName,
05216           const xmlChar *refTargetNs)
05217 {
05218     xmlSchemaRedefPtr ret;
05219 
05220     ret = (xmlSchemaRedefPtr)
05221     xmlMalloc(sizeof(xmlSchemaRedef));
05222     if (ret == NULL) {
05223     xmlSchemaPErrMemory(pctxt,
05224         "allocating redefinition info", NULL);
05225     return (NULL);
05226     }
05227     memset(ret, 0, sizeof(xmlSchemaRedef));
05228     ret->item = item;
05229     ret->targetBucket = targetBucket;
05230     ret->refName = refName;
05231     ret->refTargetNs = refTargetNs;
05232     if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
05233     WXS_CONSTRUCTOR(pctxt)->redefs = ret;
05234     else
05235     WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
05236     WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
05237 
05238     return (ret);
05239 }
05240 
05253 static xmlSchemaAttributeGroupPtr
05254 xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
05255                            xmlSchemaPtr schema ATTRIBUTE_UNUSED,
05256                const xmlChar *name,
05257                const xmlChar *nsName,
05258                xmlNodePtr node)
05259 {
05260     xmlSchemaAttributeGroupPtr ret = NULL;
05261 
05262     if ((pctxt == NULL) || (name == NULL))
05263         return (NULL);
05264 
05265     ret = (xmlSchemaAttributeGroupPtr)
05266         xmlMalloc(sizeof(xmlSchemaAttributeGroup));
05267     if (ret == NULL) {
05268     xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
05269     return (NULL);
05270     }
05271     memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
05272     ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
05273     ret->name = name;
05274     ret->targetNamespace = nsName;
05275     ret->node = node;
05276 
05277     /* TODO: Remove the flag. */
05278     ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
05279     if (pctxt->isRedefine) {
05280     pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
05281         ret, name, nsName);
05282     if (pctxt->redef == NULL) {
05283         xmlFree(ret);
05284         return(NULL);
05285     }
05286     pctxt->redefCounter = 0;
05287     }
05288     WXS_ADD_GLOBAL(pctxt, ret);
05289     WXS_ADD_PENDING(pctxt, ret);
05290     return (ret);
05291 }
05292 
05305 static xmlSchemaElementPtr
05306 xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
05307                     const xmlChar * name, const xmlChar * nsName,
05308             xmlNodePtr node, int topLevel)
05309 {
05310     xmlSchemaElementPtr ret = NULL;
05311 
05312     if ((ctxt == NULL) || (name == NULL))
05313         return (NULL);
05314 
05315     ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
05316     if (ret == NULL) {
05317         xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
05318         return (NULL);
05319     }
05320     memset(ret, 0, sizeof(xmlSchemaElement));
05321     ret->type = XML_SCHEMA_TYPE_ELEMENT;
05322     ret->name = name;
05323     ret->targetNamespace = nsName;
05324     ret->node = node;
05325 
05326     if (topLevel)
05327     WXS_ADD_GLOBAL(ctxt, ret);
05328     else
05329     WXS_ADD_LOCAL(ctxt, ret);
05330     WXS_ADD_PENDING(ctxt, ret);
05331     return (ret);
05332 }
05333 
05346 static xmlSchemaTypePtr
05347 xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
05348          xmlSchemaTypeType type,
05349                  const xmlChar * name, const xmlChar * nsName,
05350          xmlNodePtr node, int topLevel)
05351 {
05352     xmlSchemaTypePtr ret = NULL;
05353 
05354     if ((ctxt == NULL) || (schema == NULL))
05355         return (NULL);
05356 
05357     ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
05358     if (ret == NULL) {
05359         xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
05360         return (NULL);
05361     }
05362     memset(ret, 0, sizeof(xmlSchemaType));
05363     ret->type = type;
05364     ret->name = name;
05365     ret->targetNamespace = nsName;
05366     ret->node = node;
05367     if (topLevel) {
05368     if (ctxt->isRedefine) {
05369         ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
05370         ret, name, nsName);
05371         if (ctxt->redef == NULL) {
05372         xmlFree(ret);
05373         return(NULL);
05374         }
05375         ctxt->redefCounter = 0;
05376     }
05377     WXS_ADD_GLOBAL(ctxt, ret);
05378     } else
05379     WXS_ADD_LOCAL(ctxt, ret);
05380     WXS_ADD_PENDING(ctxt, ret);
05381     return (ret);
05382 }
05383 
05384 static xmlSchemaQNameRefPtr
05385 xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
05386              xmlSchemaTypeType refType,
05387              const xmlChar *refName,
05388              const xmlChar *refNs)
05389 {
05390     xmlSchemaQNameRefPtr ret;
05391 
05392     ret = (xmlSchemaQNameRefPtr)
05393     xmlMalloc(sizeof(xmlSchemaQNameRef));
05394     if (ret == NULL) {
05395     xmlSchemaPErrMemory(pctxt,
05396         "allocating QName reference item", NULL);
05397     return (NULL);
05398     }
05399     ret->node = NULL;
05400     ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
05401     ret->name = refName;
05402     ret->targetNamespace = refNs;
05403     ret->item = NULL;
05404     ret->itemType = refType;
05405     /*
05406     * Store the reference item in the schema.
05407     */
05408     WXS_ADD_LOCAL(pctxt, ret);
05409     return (ret);
05410 }
05411 
05412 static xmlSchemaAttributeUseProhibPtr
05413 xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
05414 {
05415     xmlSchemaAttributeUseProhibPtr ret;
05416 
05417     ret = (xmlSchemaAttributeUseProhibPtr)
05418     xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
05419     if (ret == NULL) {
05420     xmlSchemaPErrMemory(pctxt,
05421         "allocating attribute use prohibition", NULL);
05422     return (NULL);
05423     }
05424     memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
05425     ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
05426     WXS_ADD_LOCAL(pctxt, ret);
05427     return (ret);
05428 }
05429 
05430 
05443 static xmlSchemaModelGroupPtr
05444 xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
05445                xmlSchemaPtr schema,
05446                xmlSchemaTypeType type,
05447                xmlNodePtr node)
05448 {
05449     xmlSchemaModelGroupPtr ret = NULL;
05450 
05451     if ((ctxt == NULL) || (schema == NULL))
05452         return (NULL);
05453 
05454     ret = (xmlSchemaModelGroupPtr)
05455     xmlMalloc(sizeof(xmlSchemaModelGroup));
05456     if (ret == NULL) {
05457     xmlSchemaPErrMemory(ctxt, "allocating model group component",
05458         NULL);
05459     return (NULL);
05460     }
05461     memset(ret, 0, sizeof(xmlSchemaModelGroup));
05462     ret->type = type;
05463     ret->node = node;
05464     WXS_ADD_LOCAL(ctxt, ret);
05465     if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
05466     (type == XML_SCHEMA_TYPE_CHOICE))
05467     WXS_ADD_PENDING(ctxt, ret);
05468     return (ret);
05469 }
05470 
05471 
05485 static xmlSchemaParticlePtr
05486 xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
05487              xmlNodePtr node, int min, int max)
05488 {
05489     xmlSchemaParticlePtr ret = NULL;
05490     if (ctxt == NULL)
05491         return (NULL);
05492 
05493 #ifdef DEBUG
05494     fprintf(stderr, "Adding particle component\n");
05495 #endif
05496     ret = (xmlSchemaParticlePtr)
05497     xmlMalloc(sizeof(xmlSchemaParticle));
05498     if (ret == NULL) {
05499     xmlSchemaPErrMemory(ctxt, "allocating particle component",
05500         NULL);
05501     return (NULL);
05502     }
05503     ret->type = XML_SCHEMA_TYPE_PARTICLE;
05504     ret->annot = NULL;
05505     ret->node = node;
05506     ret->minOccurs = min;
05507     ret->maxOccurs = max;
05508     ret->next = NULL;
05509     ret->children = NULL;
05510 
05511     WXS_ADD_LOCAL(ctxt, ret);
05512     /*
05513     * Note that addition to pending components will be done locally
05514     * to the specific parsing function, since the most particles
05515     * need not to be fixed up (i.e. the reference to be resolved).
05516     * REMOVED: WXS_ADD_PENDING(ctxt, ret);
05517     */
05518     return (ret);
05519 }
05520 
05531 static xmlSchemaModelGroupDefPtr
05532 xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
05533                  xmlSchemaPtr schema,
05534                  const xmlChar *name,
05535                  const xmlChar *nsName,
05536                  xmlNodePtr node)
05537 {
05538     xmlSchemaModelGroupDefPtr ret = NULL;
05539 
05540     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
05541         return (NULL);
05542 
05543     ret = (xmlSchemaModelGroupDefPtr)
05544     xmlMalloc(sizeof(xmlSchemaModelGroupDef));
05545     if (ret == NULL) {
05546         xmlSchemaPErrMemory(ctxt, "adding group", NULL);
05547         return (NULL);
05548     }
05549     memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
05550     ret->name = name;
05551     ret->type = XML_SCHEMA_TYPE_GROUP;
05552     ret->node = node;
05553     ret->targetNamespace = nsName;
05554 
05555     if (ctxt->isRedefine) {
05556     ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
05557         ret, name, nsName);
05558     if (ctxt->redef == NULL) {
05559         xmlFree(ret);
05560         return(NULL);
05561     }
05562     ctxt->redefCounter = 0;
05563     }
05564     WXS_ADD_GLOBAL(ctxt, ret);
05565     WXS_ADD_PENDING(ctxt, ret);
05566     return (ret);
05567 }
05568 
05577 static xmlSchemaWildcardNsPtr
05578 xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
05579 {
05580     xmlSchemaWildcardNsPtr ret;
05581 
05582     ret = (xmlSchemaWildcardNsPtr)
05583     xmlMalloc(sizeof(xmlSchemaWildcardNs));
05584     if (ret == NULL) {
05585     xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
05586     return (NULL);
05587     }
05588     ret->value = NULL;
05589     ret->next = NULL;
05590     return (ret);
05591 }
05592 
05593 static xmlSchemaIDCPtr
05594 xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
05595                   const xmlChar *name, const xmlChar *nsName,
05596           int category, xmlNodePtr node)
05597 {
05598     xmlSchemaIDCPtr ret = NULL;
05599 
05600     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
05601         return (NULL);
05602 
05603     ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
05604     if (ret == NULL) {
05605         xmlSchemaPErrMemory(ctxt,
05606         "allocating an identity-constraint definition", NULL);
05607         return (NULL);
05608     }
05609     memset(ret, 0, sizeof(xmlSchemaIDC));
05610     /* The target namespace of the parent element declaration. */
05611     ret->targetNamespace = nsName;
05612     ret->name = name;
05613     ret->type = category;
05614     ret->node = node;
05615 
05616     WXS_ADD_GLOBAL(ctxt, ret);
05617     /*
05618     * Only keyrefs need to be fixup up.
05619     */
05620     if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
05621     WXS_ADD_PENDING(ctxt, ret);
05622     return (ret);
05623 }
05624 
05635 static xmlSchemaWildcardPtr
05636 xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
05637              xmlSchemaTypeType type, xmlNodePtr node)
05638 {
05639     xmlSchemaWildcardPtr ret = NULL;
05640 
05641     if ((ctxt == NULL) || (schema == NULL))
05642         return (NULL);
05643 
05644     ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
05645     if (ret == NULL) {
05646         xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
05647         return (NULL);
05648     }
05649     memset(ret, 0, sizeof(xmlSchemaWildcard));
05650     ret->type = type;
05651     ret->node = node;
05652     WXS_ADD_LOCAL(ctxt, ret);
05653     return (ret);
05654 }
05655 
05656 static void
05657 xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
05658 {
05659     if (group == NULL)
05660     return;
05661     if (group->members != NULL)
05662     xmlSchemaItemListFree(group->members);
05663     xmlFree(group);
05664 }
05665 
05666 static xmlSchemaSubstGroupPtr
05667 xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
05668                xmlSchemaElementPtr head)
05669 {
05670     xmlSchemaSubstGroupPtr ret;
05671 
05672     /* Init subst group hash. */
05673     if (WXS_SUBST_GROUPS(pctxt) == NULL) {
05674     WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
05675     if (WXS_SUBST_GROUPS(pctxt) == NULL)
05676         return(NULL);
05677     }
05678     /* Create a new substitution group. */
05679     ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
05680     if (ret == NULL) {
05681     xmlSchemaPErrMemory(NULL,
05682         "allocating a substitution group container", NULL);
05683     return(NULL);
05684     }
05685     memset(ret, 0, sizeof(xmlSchemaSubstGroup));
05686     ret->head = head;
05687     /* Create list of members. */
05688     ret->members = xmlSchemaItemListCreate();
05689     if (ret->members == NULL) {
05690     xmlSchemaSubstGroupFree(ret);
05691     return(NULL);
05692     }
05693     /* Add subst group to hash. */
05694     if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
05695     head->name, head->targetNamespace, ret) != 0) {
05696     PERROR_INT("xmlSchemaSubstGroupAdd",
05697         "failed to add a new substitution container");
05698     xmlSchemaSubstGroupFree(ret);
05699     return(NULL);
05700     }
05701     return(ret);
05702 }
05703 
05704 static xmlSchemaSubstGroupPtr
05705 xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
05706                xmlSchemaElementPtr head)
05707 {
05708     if (WXS_SUBST_GROUPS(pctxt) == NULL)
05709     return(NULL);
05710     return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
05711     head->name, head->targetNamespace));
05712 
05713 }
05714 
05725 static int
05726 xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
05727                       xmlSchemaElementPtr head,
05728                       xmlSchemaElementPtr member)
05729 {
05730     xmlSchemaSubstGroupPtr substGroup = NULL;
05731 
05732     if ((pctxt == NULL) || (head == NULL) || (member == NULL))
05733     return (-1);
05734 
05735     substGroup = xmlSchemaSubstGroupGet(pctxt, head);
05736     if (substGroup == NULL)
05737     substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
05738     if (substGroup == NULL)
05739     return(-1);
05740     if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
05741     return(-1);
05742     return(0);
05743 }
05744 
05745 /************************************************************************
05746  *                                  *
05747  *      Utilities for parsing                   *
05748  *                                  *
05749  ************************************************************************/
05750 
05768 static int
05769 xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
05770                        xmlSchemaPtr schema,
05771                        xmlSchemaBasicItemPtr ownerItem,
05772                        xmlAttrPtr attr,
05773                        const xmlChar *value,
05774                        const xmlChar **uri,
05775                        const xmlChar **local)
05776 {
05777     const xmlChar *pref;
05778     xmlNsPtr ns;
05779     int len, ret;
05780 
05781     *uri = NULL;
05782     *local = NULL;
05783     ret = xmlValidateQName(value, 1);
05784     if (ret > 0) {
05785     xmlSchemaPSimpleTypeErr(ctxt,
05786         XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
05787         ownerItem, (xmlNodePtr) attr,
05788         xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
05789         NULL, value, NULL, NULL, NULL);
05790     *local = value;
05791     return (ctxt->err);
05792     } else if (ret < 0)
05793     return (-1);
05794 
05795     if (!strchr((char *) value, ':')) {
05796     ns = xmlSearchNs(attr->doc, attr->parent, NULL);
05797     if (ns)
05798         *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
05799     else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
05800         /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
05801         * parser context. */
05802         /*
05803         * This one takes care of included schemas with no
05804         * target namespace.
05805         */
05806         *uri = ctxt->targetNamespace;
05807     }
05808     *local = xmlDictLookup(ctxt->dict, value, -1);
05809     return (0);
05810     }
05811     /*
05812     * At this point xmlSplitQName3 has to return a local name.
05813     */
05814     *local = xmlSplitQName3(value, &len);
05815     *local = xmlDictLookup(ctxt->dict, *local, -1);
05816     pref = xmlDictLookup(ctxt->dict, value, len);
05817     ns = xmlSearchNs(attr->doc, attr->parent, pref);
05818     if (ns == NULL) {
05819     xmlSchemaPSimpleTypeErr(ctxt,
05820         XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
05821         ownerItem, (xmlNodePtr) attr,
05822         xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
05823         "The value '%s' of simple type 'xs:QName' has no "
05824         "corresponding namespace declaration in scope", value, NULL);
05825     return (ctxt->err);
05826     } else {
05827         *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
05828     }
05829     return (0);
05830 }
05831 
05849 static int
05850 xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
05851                        xmlSchemaPtr schema,
05852                        xmlSchemaBasicItemPtr ownerItem,
05853                        xmlAttrPtr attr,
05854                        const xmlChar **uri,
05855                        const xmlChar **local)
05856 {
05857     const xmlChar *value;
05858 
05859     value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
05860     return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
05861     ownerItem, attr, value, uri, local));
05862 }
05863 
05880 static int
05881 xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
05882                    xmlSchemaPtr schema,
05883                    xmlSchemaBasicItemPtr ownerItem,
05884                    xmlNodePtr ownerElem,
05885                    const char *name,
05886                    const xmlChar **uri,
05887                    const xmlChar **local)
05888 {
05889     xmlAttrPtr attr;
05890 
05891     attr = xmlSchemaGetPropNode(ownerElem, name);
05892     if (attr == NULL) {
05893     *local = NULL;
05894     *uri = NULL;
05895     return (0);
05896     }
05897     return (xmlSchemaPValAttrNodeQName(ctxt, schema,
05898     ownerItem, attr, uri, local));
05899 }
05900 
05915 static int
05916 xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
05917 {
05918     int ret;
05919     const xmlChar *value;
05920 
05921     if (attr == NULL)
05922     return(0);
05923     value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
05924     ret = xmlValidateNCName(value, 1);
05925     if (ret == 0) {
05926     /*
05927     * NOTE: the IDness might have already be declared in the DTD
05928     */
05929     if (attr->atype != XML_ATTRIBUTE_ID) {
05930         xmlIDPtr res;
05931         xmlChar *strip;
05932 
05933         /*
05934         * TODO: Use xmlSchemaStrip here; it's not exported at this
05935         * moment.
05936         */
05937         strip = xmlSchemaCollapseString(value);
05938         if (strip != NULL) {
05939         xmlFree((xmlChar *) value);
05940         value = strip;
05941         }
05942             res = xmlAddID(NULL, attr->doc, value, attr);
05943         if (res == NULL) {
05944         ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
05945         xmlSchemaPSimpleTypeErr(ctxt,
05946             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
05947             NULL, (xmlNodePtr) attr,
05948             xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
05949             NULL, NULL, "Duplicate value '%s' of simple "
05950             "type 'xs:ID'", value, NULL);
05951         } else
05952         attr->atype = XML_ATTRIBUTE_ID;
05953     }
05954     } else if (ret > 0) {
05955     ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
05956     xmlSchemaPSimpleTypeErr(ctxt,
05957         XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
05958         NULL, (xmlNodePtr) attr,
05959         xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
05960         NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
05961         "not a valid 'xs:NCName'",
05962         value, NULL);
05963     }
05964     if (value != NULL)
05965     xmlFree((xmlChar *)value);
05966 
05967     return (ret);
05968 }
05969 
05970 static int
05971 xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
05972             xmlNodePtr ownerElem,
05973             const xmlChar *name)
05974 {
05975     xmlAttrPtr attr;
05976 
05977     attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
05978     if (attr == NULL)
05979     return(0);
05980     return(xmlSchemaPValAttrNodeID(ctxt, attr));
05981 
05982 }
05983 
05993 static int
05994 xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
05995         int min, int max, int def, const char *expected)
05996 {
05997     const xmlChar *val, *cur;
05998     int ret = 0;
05999     xmlAttrPtr attr;
06000 
06001     attr = xmlSchemaGetPropNode(node, "maxOccurs");
06002     if (attr == NULL)
06003     return (def);
06004     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
06005 
06006     if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
06007     if (max != UNBOUNDED) {
06008         xmlSchemaPSimpleTypeErr(ctxt,
06009         XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
06010         /* XML_SCHEMAP_INVALID_MINOCCURS, */
06011         NULL, (xmlNodePtr) attr, NULL, expected,
06012         val, NULL, NULL, NULL);
06013         return (def);
06014     } else
06015         return (UNBOUNDED);  /* encoding it with -1 might be another option */
06016     }
06017 
06018     cur = val;
06019     while (IS_BLANK_CH(*cur))
06020         cur++;
06021     if (*cur == 0) {
06022         xmlSchemaPSimpleTypeErr(ctxt,
06023         XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
06024         /* XML_SCHEMAP_INVALID_MINOCCURS, */
06025         NULL, (xmlNodePtr) attr, NULL, expected,
06026         val, NULL, NULL, NULL);
06027     return (def);
06028     }
06029     while ((*cur >= '0') && (*cur <= '9')) {
06030         ret = ret * 10 + (*cur - '0');
06031         cur++;
06032     }
06033     while (IS_BLANK_CH(*cur))
06034         cur++;
06035     /*
06036     * TODO: Restrict the maximal value to Integer.
06037     */
06038     if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
06039     xmlSchemaPSimpleTypeErr(ctxt,
06040         XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
06041         /* XML_SCHEMAP_INVALID_MINOCCURS, */
06042         NULL, (xmlNodePtr) attr, NULL, expected,
06043         val, NULL, NULL, NULL);
06044         return (def);
06045     }
06046     return (ret);
06047 }
06048 
06058 static int
06059 xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
06060         int min, int max, int def, const char *expected)
06061 {
06062     const xmlChar *val, *cur;
06063     int ret = 0;
06064     xmlAttrPtr attr;
06065 
06066     attr = xmlSchemaGetPropNode(node, "minOccurs");
06067     if (attr == NULL)
06068     return (def);
06069     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
06070     cur = val;
06071     while (IS_BLANK_CH(*cur))
06072         cur++;
06073     if (*cur == 0) {
06074         xmlSchemaPSimpleTypeErr(ctxt,
06075         XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
06076         /* XML_SCHEMAP_INVALID_MINOCCURS, */
06077         NULL, (xmlNodePtr) attr, NULL, expected,
06078         val, NULL, NULL, NULL);
06079         return (def);
06080     }
06081     while ((*cur >= '0') && (*cur <= '9')) {
06082         ret = ret * 10 + (*cur - '0');
06083         cur++;
06084     }
06085     while (IS_BLANK_CH(*cur))
06086         cur++;
06087     /*
06088     * TODO: Restrict the maximal value to Integer.
06089     */
06090     if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
06091     xmlSchemaPSimpleTypeErr(ctxt,
06092         XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
06093         /* XML_SCHEMAP_INVALID_MINOCCURS, */
06094         NULL, (xmlNodePtr) attr, NULL, expected,
06095         val, NULL, NULL, NULL);
06096         return (def);
06097     }
06098     return (ret);
06099 }
06100 
06112 static int
06113 xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
06114                xmlSchemaBasicItemPtr ownerItem,
06115                xmlNodePtr node)
06116 {
06117     xmlChar *value = NULL;
06118     int res = 0;
06119 
06120     value = xmlNodeGetContent(node);
06121     /*
06122     * 3.2.2.1 Lexical representation
06123     * An instance of a datatype that is defined as �boolean�
06124     * can have the following legal literals {true, false, 1, 0}.
06125     */
06126     if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
06127         res = 1;
06128     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
06129         res = 0;
06130     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
06131     res = 1;
06132     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
06133         res = 0;
06134     else {
06135         xmlSchemaPSimpleTypeErr(ctxt,
06136         XML_SCHEMAP_INVALID_BOOLEAN,
06137         ownerItem, node,
06138         xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
06139         NULL, BAD_CAST value,
06140         NULL, NULL, NULL);
06141     }
06142     if (value != NULL)
06143     xmlFree(value);
06144     return (res);
06145 }
06146 
06159 static int
06160 xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
06161           xmlNodePtr node,
06162                   const char *name, int def)
06163 {
06164     const xmlChar *val;
06165 
06166     val = xmlSchemaGetProp(ctxt, node, name);
06167     if (val == NULL)
06168         return (def);
06169     /*
06170     * 3.2.2.1 Lexical representation
06171     * An instance of a datatype that is defined as �boolean�
06172     * can have the following legal literals {true, false, 1, 0}.
06173     */
06174     if (xmlStrEqual(val, BAD_CAST "true"))
06175         def = 1;
06176     else if (xmlStrEqual(val, BAD_CAST "false"))
06177         def = 0;
06178     else if (xmlStrEqual(val, BAD_CAST "1"))
06179     def = 1;
06180     else if (xmlStrEqual(val, BAD_CAST "0"))
06181         def = 0;
06182     else {
06183         xmlSchemaPSimpleTypeErr(ctxt,
06184         XML_SCHEMAP_INVALID_BOOLEAN,
06185         NULL,
06186         (xmlNodePtr) xmlSchemaGetPropNode(node, name),
06187         xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
06188         NULL, val, NULL, NULL, NULL);
06189     }
06190     return (def);
06191 }
06192 
06193 /************************************************************************
06194  *                                  *
06195  *      Shema extraction from an Infoset            *
06196  *                                  *
06197  ************************************************************************/
06198 static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
06199                                                  ctxt, xmlSchemaPtr schema,
06200                                                  xmlNodePtr node,
06201                          int topLevel);
06202 static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
06203                                                   ctxt,
06204                                                   xmlSchemaPtr schema,
06205                                                   xmlNodePtr node,
06206                           int topLevel);
06207 static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
06208                                                   ctxt,
06209                                                   xmlSchemaPtr schema,
06210                                                   xmlNodePtr node,
06211                           xmlSchemaTypeType parentType);
06212 static xmlSchemaBasicItemPtr
06213 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
06214                  xmlSchemaPtr schema,
06215                  xmlNodePtr node,
06216                  xmlSchemaItemListPtr uses,
06217                  int parentType);
06218 static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
06219                                            xmlSchemaPtr schema,
06220                                            xmlNodePtr node);
06221 static xmlSchemaWildcardPtr
06222 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
06223                            xmlSchemaPtr schema, xmlNodePtr node);
06224 
06242 static int
06243 xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
06244                xmlSchemaBasicItemPtr ownerItem,
06245                xmlAttrPtr attr,
06246                const xmlChar *value,
06247                xmlSchemaTypePtr type)
06248 {
06249 
06250     int ret = 0;
06251 
06252     /*
06253     * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
06254     * one is really meant to be used internally, so better not.
06255     */
06256     if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
06257     return (-1);
06258     if (type->type != XML_SCHEMA_TYPE_BASIC) {
06259     PERROR_INT("xmlSchemaPValAttrNodeValue",
06260         "the given type is not a built-in type");
06261     return (-1);
06262     }
06263     switch (type->builtInType) {
06264     case XML_SCHEMAS_NCNAME:
06265     case XML_SCHEMAS_QNAME:
06266     case XML_SCHEMAS_ANYURI:
06267     case XML_SCHEMAS_TOKEN:
06268     case XML_SCHEMAS_LANGUAGE:
06269         ret = xmlSchemaValPredefTypeNode(type, value, NULL,
06270         (xmlNodePtr) attr);
06271         break;
06272     default: {
06273         PERROR_INT("xmlSchemaPValAttrNodeValue",
06274         "validation using the given type is not supported while "
06275         "parsing a schema");
06276         return (-1);
06277     }
06278     }
06279     /*
06280     * TODO: Should we use the S4S error codes instead?
06281     */
06282     if (ret < 0) {
06283     PERROR_INT("xmlSchemaPValAttrNodeValue",
06284         "failed to validate a schema attribute value");
06285     return (-1);
06286     } else if (ret > 0) {
06287     if (WXS_IS_LIST(type))
06288         ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
06289     else
06290         ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
06291     xmlSchemaPSimpleTypeErr(pctxt,
06292         ret, ownerItem, (xmlNodePtr) attr,
06293         type, NULL, value, NULL, NULL, NULL);
06294     }
06295     return (ret);
06296 }
06297 
06315 static int
06316 xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
06317                xmlSchemaBasicItemPtr ownerItem,
06318                xmlAttrPtr attr,
06319                xmlSchemaTypePtr type,
06320                const xmlChar **value)
06321 {
06322     const xmlChar *val;
06323 
06324     if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
06325     return (-1);
06326 
06327     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
06328     if (value != NULL)
06329     *value = val;
06330 
06331     return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
06332     val, type));
06333 }
06334 
06354 static int
06355 xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
06356                xmlSchemaBasicItemPtr ownerItem,
06357                xmlNodePtr ownerElem,
06358                const char *name,
06359                xmlSchemaTypePtr type,
06360                const xmlChar **value)
06361 {
06362     xmlAttrPtr attr;
06363 
06364     if ((ctxt == NULL) || (type == NULL)) {
06365     if (value != NULL)
06366         *value = NULL;
06367     return (-1);
06368     }
06369     if (type->type != XML_SCHEMA_TYPE_BASIC) {
06370     if (value != NULL)
06371         *value = NULL;
06372     xmlSchemaPErr(ctxt, ownerElem,
06373         XML_SCHEMAP_INTERNAL,
06374         "Internal error: xmlSchemaPValAttr, the given "
06375         "type '%s' is not a built-in type.\n",
06376         type->name, NULL);
06377     return (-1);
06378     }
06379     attr = xmlSchemaGetPropNode(ownerElem, name);
06380     if (attr == NULL) {
06381     if (value != NULL)
06382         *value = NULL;
06383     return (0);
06384     }
06385     return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
06386     type, value));
06387 }
06388 
06389 static int
06390 xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
06391           xmlSchemaPtr schema ATTRIBUTE_UNUSED,
06392           xmlNodePtr node,
06393           xmlAttrPtr attr,
06394           const xmlChar *namespaceName)
06395 {
06396     /* TODO: Pointer comparison instead? */
06397     if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
06398     return (0);
06399     if (xmlStrEqual(xmlSchemaNs, namespaceName))
06400     return (0);
06401     /*
06402     * Check if the referenced namespace was <import>ed.
06403     */
06404     if (WXS_BUCKET(pctxt)->relations != NULL) {
06405     xmlSchemaSchemaRelationPtr rel;
06406 
06407     rel = WXS_BUCKET(pctxt)->relations;
06408     do {
06409         if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
06410         xmlStrEqual(namespaceName, rel->importNamespace))
06411         return (0);
06412         rel = rel->next;
06413     } while (rel != NULL);
06414     }
06415     /*
06416     * No matching <import>ed namespace found.
06417     */
06418     {
06419     xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
06420 
06421     if (namespaceName == NULL)
06422         xmlSchemaCustomErr(ACTXT_CAST pctxt,
06423         XML_SCHEMAP_SRC_RESOLVE, n, NULL,
06424         "References from this schema to components in no "
06425         "namespace are not allowed, since not indicated by an "
06426         "import statement", NULL, NULL);
06427     else
06428         xmlSchemaCustomErr(ACTXT_CAST pctxt,
06429         XML_SCHEMAP_SRC_RESOLVE, n, NULL,
06430         "References from this schema to components in the "
06431         "namespace '%s' are not allowed, since not indicated by an "
06432         "import statement", namespaceName, NULL);
06433     }
06434     return (XML_SCHEMAP_SRC_RESOLVE);
06435 }
06436 
06447 static int
06448 xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
06449                         xmlNodePtr *child, xmlSchemaItemListPtr *list,
06450             int parentType, int *hasRefs)
06451 {
06452     void *item;
06453 
06454     while ((IS_SCHEMA((*child), "attribute")) ||
06455            (IS_SCHEMA((*child), "attributeGroup"))) {
06456         if (IS_SCHEMA((*child), "attribute")) {
06457         item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
06458         *list, parentType);
06459         } else {
06460             item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
06461         if ((item != NULL) && (hasRefs != NULL))
06462         *hasRefs = 1;
06463         }
06464     if (item != NULL) {
06465         if (*list == NULL) {
06466         /* TODO: Customize grow factor. */
06467         *list = xmlSchemaItemListCreate();
06468         if (*list == NULL)
06469             return(-1);
06470         }
06471         if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
06472         return(-1);
06473     }
06474         *child = (*child)->next;
06475     }
06476     return (0);
06477 }
06478 
06491 static xmlSchemaAnnotPtr
06492 xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed)
06493 {
06494     xmlSchemaAnnotPtr ret;
06495     xmlNodePtr child = NULL;
06496     xmlAttrPtr attr;
06497     int barked = 0;
06498 
06499     /*
06500     * INFO: S4S completed.
06501     */
06502     /*
06503     * id = ID
06504     * {any attributes with non-schema namespace . . .}>
06505     * Content: (appinfo | documentation)*
06506     */
06507     if ((ctxt == NULL) || (node == NULL))
06508         return (NULL);
06509     if (needed)
06510     ret = xmlSchemaNewAnnot(ctxt, node);
06511     else
06512     ret = NULL;
06513     attr = node->properties;
06514     while (attr != NULL) {
06515     if (((attr->ns == NULL) &&
06516         (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
06517         ((attr->ns != NULL) &&
06518         xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
06519 
06520         xmlSchemaPIllegalAttrErr(ctxt,
06521         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
06522     }
06523     attr = attr->next;
06524     }
06525     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
06526     /*
06527     * And now for the children...
06528     */
06529     child = node->children;
06530     while (child != NULL) {
06531     if (IS_SCHEMA(child, "appinfo")) {
06532         /* TODO: make available the content of "appinfo". */
06533         /*
06534         * source = anyURI
06535         * {any attributes with non-schema namespace . . .}>
06536         * Content: ({any})*
06537         */
06538         attr = child->properties;
06539         while (attr != NULL) {
06540         if (((attr->ns == NULL) &&
06541              (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
06542              ((attr->ns != NULL) &&
06543               xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
06544 
06545             xmlSchemaPIllegalAttrErr(ctxt,
06546             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
06547         }
06548         attr = attr->next;
06549         }
06550         xmlSchemaPValAttr(ctxt, NULL, child, "source",
06551         xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
06552         child = child->next;
06553     } else if (IS_SCHEMA(child, "documentation")) {
06554         /* TODO: make available the content of "documentation". */
06555         /*
06556         * source = anyURI
06557         * {any attributes with non-schema namespace . . .}>
06558         * Content: ({any})*
06559         */
06560         attr = child->properties;
06561         while (attr != NULL) {
06562         if (attr->ns == NULL) {
06563             if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
06564             xmlSchemaPIllegalAttrErr(ctxt,
06565                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
06566             }
06567         } else {
06568             if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
06569             (xmlStrEqual(attr->name, BAD_CAST "lang") &&
06570             (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
06571 
06572             xmlSchemaPIllegalAttrErr(ctxt,
06573                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
06574             }
06575         }
06576         attr = attr->next;
06577         }
06578         /*
06579         * Attribute "xml:lang".
06580         */
06581         attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
06582         if (attr != NULL)
06583         xmlSchemaPValAttrNode(ctxt, NULL, attr,
06584         xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
06585         child = child->next;
06586     } else {
06587         if (!barked)
06588         xmlSchemaPContentErr(ctxt,
06589             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
06590             NULL, node, child, NULL, "(appinfo | documentation)*");
06591         barked = 1;
06592         child = child->next;
06593     }
06594     }
06595 
06596     return (ret);
06597 }
06598 
06610 static xmlSchemaFacetPtr
06611 xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
06612                     xmlNodePtr node)
06613 {
06614     xmlSchemaFacetPtr facet;
06615     xmlNodePtr child = NULL;
06616     const xmlChar *value;
06617 
06618     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
06619         return (NULL);
06620 
06621     facet = xmlSchemaNewFacet();
06622     if (facet == NULL) {
06623         xmlSchemaPErrMemory(ctxt, "allocating facet", node);
06624         return (NULL);
06625     }
06626     facet->node = node;
06627     value = xmlSchemaGetProp(ctxt, node, "value");
06628     if (value == NULL) {
06629         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
06630                        "Facet %s has no value\n", node->name, NULL);
06631         xmlSchemaFreeFacet(facet);
06632         return (NULL);
06633     }
06634     if (IS_SCHEMA(node, "minInclusive")) {
06635         facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
06636     } else if (IS_SCHEMA(node, "minExclusive")) {
06637         facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
06638     } else if (IS_SCHEMA(node, "maxInclusive")) {
06639         facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
06640     } else if (IS_SCHEMA(node, "maxExclusive")) {
06641         facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
06642     } else if (IS_SCHEMA(node, "totalDigits")) {
06643         facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
06644     } else if (IS_SCHEMA(node, "fractionDigits")) {
06645         facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
06646     } else if (IS_SCHEMA(node, "pattern")) {
06647         facet->type = XML_SCHEMA_FACET_PATTERN;
06648     } else if (IS_SCHEMA(node, "enumeration")) {
06649         facet->type = XML_SCHEMA_FACET_ENUMERATION;
06650     } else if (IS_SCHEMA(node, "whiteSpace")) {
06651         facet->type = XML_SCHEMA_FACET_WHITESPACE;
06652     } else if (IS_SCHEMA(node, "length")) {
06653         facet->type = XML_SCHEMA_FACET_LENGTH;
06654     } else if (IS_SCHEMA(node, "maxLength")) {
06655         facet->type = XML_SCHEMA_FACET_MAXLENGTH;
06656     } else if (IS_SCHEMA(node, "minLength")) {
06657         facet->type = XML_SCHEMA_FACET_MINLENGTH;
06658     } else {
06659         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
06660                        "Unknown facet type %s\n", node->name, NULL);
06661         xmlSchemaFreeFacet(facet);
06662         return (NULL);
06663     }
06664     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
06665     facet->value = value;
06666     if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
06667     (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
06668     const xmlChar *fixed;
06669 
06670     fixed = xmlSchemaGetProp(ctxt, node, "fixed");
06671     if (fixed != NULL) {
06672         if (xmlStrEqual(fixed, BAD_CAST "true"))
06673         facet->fixed = 1;
06674     }
06675     }
06676     child = node->children;
06677 
06678     if (IS_SCHEMA(child, "annotation")) {
06679         facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
06680         child = child->next;
06681     }
06682     if (child != NULL) {
06683         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
06684                        "Facet %s has unexpected child content\n",
06685                        node->name, NULL);
06686     }
06687     return (facet);
06688 }
06689 
06703 static int
06704 xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
06705              xmlSchemaPtr schema ATTRIBUTE_UNUSED,
06706              xmlSchemaWildcardPtr wildc,
06707              xmlNodePtr node)
06708 {
06709     const xmlChar *pc, *ns, *dictnsItem;
06710     int ret = 0;
06711     xmlChar *nsItem;
06712     xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
06713     xmlAttrPtr attr;
06714 
06715     pc = xmlSchemaGetProp(ctxt, node, "processContents");
06716     if ((pc == NULL)
06717         || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
06718         wildc->processContents = XML_SCHEMAS_ANY_STRICT;
06719     } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
06720         wildc->processContents = XML_SCHEMAS_ANY_SKIP;
06721     } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
06722         wildc->processContents = XML_SCHEMAS_ANY_LAX;
06723     } else {
06724         xmlSchemaPSimpleTypeErr(ctxt,
06725         XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
06726         NULL, node,
06727         NULL, "(strict | skip | lax)", pc,
06728         NULL, NULL, NULL);
06729         wildc->processContents = XML_SCHEMAS_ANY_STRICT;
06730     ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
06731     }
06732     /*
06733      * Build the namespace constraints.
06734      */
06735     attr = xmlSchemaGetPropNode(node, "namespace");
06736     ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
06737     if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
06738     wildc->any = 1;
06739     else if (xmlStrEqual(ns, BAD_CAST "##other")) {
06740     wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
06741     if (wildc->negNsSet == NULL) {
06742         return (-1);
06743     }
06744     wildc->negNsSet->value = ctxt->targetNamespace;
06745     } else {
06746     const xmlChar *end, *cur;
06747 
06748     cur = ns;
06749     do {
06750         while (IS_BLANK_CH(*cur))
06751         cur++;
06752         end = cur;
06753         while ((*end != 0) && (!(IS_BLANK_CH(*end))))
06754         end++;
06755         if (end == cur)
06756         break;
06757         nsItem = xmlStrndup(cur, end - cur);
06758         if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
06759             (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
06760         xmlSchemaPSimpleTypeErr(ctxt,
06761             XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
06762             NULL, (xmlNodePtr) attr,
06763             NULL,
06764             "((##any | ##other) | List of (xs:anyURI | "
06765             "(##targetNamespace | ##local)))",
06766             nsItem, NULL, NULL, NULL);
06767         ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
06768         } else {
06769         if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
06770             dictnsItem = ctxt->targetNamespace;
06771         } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
06772             dictnsItem = NULL;
06773         } else {
06774             /*
06775             * Validate the item (anyURI).
06776             */
06777             xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
06778             nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
06779             dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
06780         }
06781         /*
06782         * Avoid dublicate namespaces.
06783         */
06784         tmp = wildc->nsSet;
06785         while (tmp != NULL) {
06786             if (dictnsItem == tmp->value)
06787             break;
06788             tmp = tmp->next;
06789         }
06790         if (tmp == NULL) {
06791             tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
06792             if (tmp == NULL) {
06793             xmlFree(nsItem);
06794             return (-1);
06795             }
06796             tmp->value = dictnsItem;
06797             tmp->next = NULL;
06798             if (wildc->nsSet == NULL)
06799             wildc->nsSet = tmp;
06800             else if (lastNs != NULL)
06801             lastNs->next = tmp;
06802             lastNs = tmp;
06803         }
06804 
06805         }
06806         xmlFree(nsItem);
06807         cur = end;
06808     } while (*cur != 0);
06809     }
06810     return (ret);
06811 }
06812 
06813 static int
06814 xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
06815                  xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
06816                  xmlNodePtr node,
06817                  int minOccurs,
06818                  int maxOccurs) {
06819 
06820     if ((maxOccurs == 0) && ( minOccurs == 0))
06821     return (0);
06822     if (maxOccurs != UNBOUNDED) {
06823     /*
06824     * TODO: Maybe we should better not create the particle,
06825     * if min/max is invalid, since it could confuse the build of the
06826     * content model.
06827     */
06828     /*
06829     * 3.9.6 Schema Component Constraint: Particle Correct
06830     *
06831     */
06832     if (maxOccurs < 1) {
06833         /*
06834         * 2.2 {max occurs} must be greater than or equal to 1.
06835         */
06836         xmlSchemaPCustomAttrErr(ctxt,
06837         XML_SCHEMAP_P_PROPS_CORRECT_2_2,
06838         NULL, NULL,
06839         xmlSchemaGetPropNode(node, "maxOccurs"),
06840         "The value must be greater than or equal to 1");
06841         return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
06842     } else if (minOccurs > maxOccurs) {
06843         /*
06844         * 2.1 {min occurs} must not be greater than {max occurs}.
06845         */
06846         xmlSchemaPCustomAttrErr(ctxt,
06847         XML_SCHEMAP_P_PROPS_CORRECT_2_1,
06848         NULL, NULL,
06849         xmlSchemaGetPropNode(node, "minOccurs"),
06850         "The value must not be greater than the value of 'maxOccurs'");
06851         return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
06852     }
06853     }
06854     return (0);
06855 }
06856 
06870 static xmlSchemaParticlePtr
06871 xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
06872                   xmlNodePtr node)
06873 {
06874     xmlSchemaParticlePtr particle;
06875     xmlNodePtr child = NULL;
06876     xmlSchemaWildcardPtr wild;
06877     int min, max;
06878     xmlAttrPtr attr;
06879     xmlSchemaAnnotPtr annot = NULL;
06880 
06881     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
06882         return (NULL);
06883     /*
06884     * Check for illegal attributes.
06885     */
06886     attr = node->properties;
06887     while (attr != NULL) {
06888     if (attr->ns == NULL) {
06889         if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
06890         (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
06891         (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
06892             (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
06893         (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
06894         xmlSchemaPIllegalAttrErr(ctxt,
06895             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
06896         }
06897     } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
06898         xmlSchemaPIllegalAttrErr(ctxt,
06899         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
06900     }
06901     attr = attr->next;
06902     }
06903     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
06904     /*
06905     * minOccurs/maxOccurs.
06906     */
06907     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
06908     "(xs:nonNegativeInteger | unbounded)");
06909     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
06910     "xs:nonNegativeInteger");
06911     xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
06912     /*
06913     * Create & parse the wildcard.
06914     */
06915     wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
06916     if (wild == NULL)
06917     return (NULL);
06918     xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
06919     /*
06920     * And now for the children...
06921     */
06922     child = node->children;
06923     if (IS_SCHEMA(child, "annotation")) {
06924         annot = xmlSchemaParseAnnotation(ctxt, child, 1);
06925         child = child->next;
06926     }
06927     if (child != NULL) {
06928     xmlSchemaPContentErr(ctxt,
06929         XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
06930         NULL, node, child,
06931         NULL, "(annotation?)");
06932     }
06933     /*
06934     * No component if minOccurs==maxOccurs==0.
06935     */
06936     if ((min == 0) && (max == 0)) {
06937     /* Don't free the wildcard, since it's already on the list. */
06938     return (NULL);
06939     }
06940     /*
06941     * Create the particle.
06942     */
06943     particle = xmlSchemaAddParticle(ctxt, node, min, max);
06944     if (particle == NULL)
06945         return (NULL);
06946     particle->annot = annot;
06947     particle->children = (xmlSchemaTreeItemPtr) wild;
06948 
06949     return (particle);
06950 }
06951 
06962 static xmlSchemaNotationPtr
06963 xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
06964                        xmlNodePtr node)
06965 {
06966     const xmlChar *name;
06967     xmlSchemaNotationPtr ret;
06968     xmlNodePtr child = NULL;
06969 
06970     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
06971         return (NULL);
06972     name = xmlSchemaGetProp(ctxt, node, "name");
06973     if (name == NULL) {
06974         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
06975                        "Notation has no name\n", NULL, NULL);
06976         return (NULL);
06977     }
06978     ret = xmlSchemaAddNotation(ctxt, schema, name,
06979     ctxt->targetNamespace, node);
06980     if (ret == NULL)
06981         return (NULL);
06982     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
06983 
06984     child = node->children;
06985     if (IS_SCHEMA(child, "annotation")) {
06986         ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
06987         child = child->next;
06988     }
06989     if (child != NULL) {
06990     xmlSchemaPContentErr(ctxt,
06991         XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
06992         NULL, node, child,
06993         NULL, "(annotation?)");
06994     }
06995 
06996     return (ret);
06997 }
06998 
07010 static xmlSchemaWildcardPtr
07011 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
07012                            xmlSchemaPtr schema, xmlNodePtr node)
07013 {
07014     xmlSchemaWildcardPtr ret;
07015     xmlNodePtr child = NULL;
07016     xmlAttrPtr attr;
07017 
07018     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
07019         return (NULL);
07020 
07021     ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
07022     node);
07023     if (ret == NULL) {
07024         return (NULL);
07025     }
07026     /*
07027     * Check for illegal attributes.
07028     */
07029     attr = node->properties;
07030     while (attr != NULL) {
07031     if (attr->ns == NULL) {
07032         if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
07033             (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
07034         (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
07035         xmlSchemaPIllegalAttrErr(ctxt,
07036             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
07037         }
07038     } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
07039         xmlSchemaPIllegalAttrErr(ctxt,
07040         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
07041     }
07042     attr = attr->next;
07043     }
07044     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
07045     /*
07046     * Parse the namespace list.
07047     */
07048     if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
07049     return (NULL);
07050     /*
07051     * And now for the children...
07052     */
07053     child = node->children;
07054     if (IS_SCHEMA(child, "annotation")) {
07055         ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
07056         child = child->next;
07057     }
07058     if (child != NULL) {
07059     xmlSchemaPContentErr(ctxt,
07060         XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
07061         NULL, node, child,
07062         NULL, "(annotation?)");
07063     }
07064 
07065     return (ret);
07066 }
07067 
07068 
07080 static xmlSchemaBasicItemPtr
07081 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
07082                  xmlSchemaPtr schema,
07083                  xmlNodePtr node,
07084                  xmlSchemaItemListPtr uses,
07085                  int parentType)
07086 {
07087     const xmlChar *attrValue, *name = NULL, *ns = NULL;
07088     xmlSchemaAttributeUsePtr use = NULL;
07089     xmlNodePtr child = NULL;
07090     xmlAttrPtr attr;
07091     const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
07092     int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
07093     int nberrors, hasForm = 0, defValueType = 0;
07094 
07095 #define WXS_ATTR_DEF_VAL_DEFAULT 1
07096 #define WXS_ATTR_DEF_VAL_FIXED 2
07097 
07098     /*
07099      * 3.2.3 Constraints on XML Representations of Attribute Declarations
07100      */
07101 
07102     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
07103         return (NULL);
07104     attr = xmlSchemaGetPropNode(node, "ref");
07105     if (attr != NULL) {
07106     if (xmlSchemaPValAttrNodeQName(pctxt, schema,
07107         NULL, attr, &tmpNs, &tmpName) != 0) {
07108         return (NULL);
07109     }
07110     if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
07111         return(NULL);
07112     isRef = 1;
07113     }
07114     nberrors = pctxt->nberrors;
07115     /*
07116     * Check for illegal attributes.
07117     */
07118     attr = node->properties;
07119     while (attr != NULL) {
07120     if (attr->ns == NULL) {
07121         if (isRef) {
07122         if (xmlStrEqual(attr->name, BAD_CAST "id")) {
07123             xmlSchemaPValAttrNodeID(pctxt, attr);
07124             goto attr_next;
07125         } else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
07126             goto attr_next;
07127         }
07128         } else {
07129         if (xmlStrEqual(attr->name, BAD_CAST "name")) {
07130             goto attr_next;
07131         } else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
07132             xmlSchemaPValAttrNodeID(pctxt, attr);
07133             goto attr_next;
07134         } else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
07135             xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
07136             attr, &tmpNs, &tmpName);
07137             goto attr_next;
07138         } else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
07139             /*
07140             * Evaluate the target namespace
07141             */
07142             hasForm = 1;
07143             attrValue = xmlSchemaGetNodeContent(pctxt,
07144             (xmlNodePtr) attr);
07145             if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
07146             ns = pctxt->targetNamespace;
07147             } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
07148             {
07149             xmlSchemaPSimpleTypeErr(pctxt,
07150                 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
07151                 NULL, (xmlNodePtr) attr,
07152                 NULL, "(qualified | unqualified)",
07153                 attrValue, NULL, NULL, NULL);
07154             }
07155             goto attr_next;
07156         }
07157         }
07158         if (xmlStrEqual(attr->name, BAD_CAST "use")) {
07159 
07160         attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
07161         /* TODO: Maybe we need to normalize the value beforehand. */
07162         if (xmlStrEqual(attrValue, BAD_CAST "optional"))
07163             occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
07164         else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
07165             occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
07166         else if (xmlStrEqual(attrValue, BAD_CAST "required"))
07167             occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
07168         else {
07169             xmlSchemaPSimpleTypeErr(pctxt,
07170             XML_SCHEMAP_INVALID_ATTR_USE,
07171             NULL, (xmlNodePtr) attr,
07172             NULL, "(optional | prohibited | required)",
07173             attrValue, NULL, NULL, NULL);
07174         }
07175         goto attr_next;
07176         } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
07177         /*
07178         * 3.2.3 : 1
07179         * default and fixed must not both be present.
07180         */
07181         if (defValue) {
07182             xmlSchemaPMutualExclAttrErr(pctxt,
07183             XML_SCHEMAP_SRC_ATTRIBUTE_1,
07184             NULL, attr, "default", "fixed");
07185         } else {
07186             defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
07187             defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
07188         }
07189         goto attr_next;
07190         } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
07191         /*
07192         * 3.2.3 : 1
07193         * default and fixed must not both be present.
07194         */
07195         if (defValue) {
07196             xmlSchemaPMutualExclAttrErr(pctxt,
07197             XML_SCHEMAP_SRC_ATTRIBUTE_1,
07198             NULL, attr, "default", "fixed");
07199         } else {
07200             defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
07201             defValueType = WXS_ATTR_DEF_VAL_FIXED;
07202         }
07203         goto attr_next;
07204         }
07205     } else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
07206         goto attr_next;
07207 
07208     xmlSchemaPIllegalAttrErr(pctxt,
07209         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
07210 
07211 attr_next:
07212     attr = attr->next;
07213     }
07214     /*
07215     * 3.2.3 : 2
07216     * If default and use are both present, use must have
07217     * the actual value optional.
07218     */
07219     if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
07220     (occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
07221     xmlSchemaPSimpleTypeErr(pctxt,
07222         XML_SCHEMAP_SRC_ATTRIBUTE_2,
07223         NULL, node, NULL,
07224         "(optional | prohibited | required)", NULL,
07225         "The value of the attribute 'use' must be 'optional' "
07226         "if the attribute 'default' is present",
07227         NULL, NULL);
07228     }
07229     /*
07230     * We want correct attributes.
07231     */
07232     if (nberrors != pctxt->nberrors)
07233     return(NULL);
07234     if (! isRef) {
07235     xmlSchemaAttributePtr attrDecl;
07236 
07237     /* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
07238     if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
07239         ns = pctxt->targetNamespace;
07240     /*
07241     * 3.2.6 Schema Component Constraint: xsi: Not Allowed
07242     * TODO: Move this to the component layer.
07243     */
07244     if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
07245         xmlSchemaCustomErr(ACTXT_CAST pctxt,
07246         XML_SCHEMAP_NO_XSI,
07247         node, NULL,
07248         "The target namespace must not match '%s'",
07249         xmlSchemaInstanceNs, NULL);
07250     }
07251     attr = xmlSchemaGetPropNode(node, "name");
07252     if (attr == NULL) {
07253         xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
07254         NULL, node, "name", NULL);
07255         return (NULL);
07256     }
07257     if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
07258         xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
07259         return (NULL);
07260     }
07261     /*
07262     * 3.2.6 Schema Component Constraint: xmlns Not Allowed
07263     * TODO: Move this to the component layer.
07264     */
07265     if (xmlStrEqual(name, BAD_CAST "xmlns")) {
07266         xmlSchemaPSimpleTypeErr(pctxt,
07267         XML_SCHEMAP_NO_XMLNS,
07268         NULL, (xmlNodePtr) attr,
07269         xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
07270         "The value of the attribute must not match 'xmlns'",
07271         NULL, NULL);
07272         return (NULL);
07273     }
07274     if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
07275         goto check_children;
07276     /*
07277     * Create the attribute use component.
07278     */
07279     use = xmlSchemaAddAttributeUse(pctxt, node);
07280     if (use == NULL)
07281         return(NULL);
07282     use->occurs = occurs;
07283     /*
07284     * Create the attribute declaration.
07285     */
07286     attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
07287     if (attrDecl == NULL)
07288         return (NULL);
07289     if (tmpName != NULL) {
07290         attrDecl->typeName = tmpName;
07291         attrDecl->typeNs = tmpNs;
07292     }
07293     use->attrDecl = attrDecl;
07294     /*
07295     * Value constraint.
07296     */
07297     if (defValue != NULL) {
07298         attrDecl->defValue = defValue;
07299         if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
07300         attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
07301     }
07302     } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
07303     xmlSchemaQNameRefPtr ref;
07304 
07305     /*
07306     * Create the attribute use component.
07307     */
07308     use = xmlSchemaAddAttributeUse(pctxt, node);
07309     if (use == NULL)
07310         return(NULL);
07311     /*
07312     * We need to resolve the reference at later stage.
07313     */
07314     WXS_ADD_PENDING(pctxt, use);
07315     use->occurs = occurs;
07316     /*
07317     * Create a QName reference to the attribute declaration.
07318     */
07319     ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
07320         tmpName, tmpNs);
07321     if (ref == NULL)
07322         return(NULL);
07323     /*
07324     * Assign the reference. This will be substituted for the
07325     * referenced attribute declaration when the QName is resolved.
07326     */
07327     use->attrDecl = WXS_ATTR_CAST ref;
07328     /*
07329     * Value constraint.
07330     */
07331     if (defValue != NULL)
07332         use->defValue = defValue;
07333         if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
07334         use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
07335     }
07336 
07337 check_children:
07338     /*
07339     * And now for the children...
07340     */
07341     child = node->children;
07342     if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
07343     xmlSchemaAttributeUseProhibPtr prohib;
07344 
07345     if (IS_SCHEMA(child, "annotation")) {
07346         xmlSchemaParseAnnotation(pctxt, child, 0);
07347         child = child->next;
07348     }
07349     if (child != NULL) {
07350         xmlSchemaPContentErr(pctxt,
07351         XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
07352         NULL, node, child, NULL,
07353         "(annotation?)");
07354     }
07355     /*
07356     * Check for pointlessness of attribute prohibitions.
07357     */
07358     if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
07359         xmlSchemaCustomWarning(ACTXT_CAST pctxt,
07360         XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
07361         node, NULL,
07362         "Skipping attribute use prohibition, since it is "
07363         "pointless inside an <attributeGroup>",
07364         NULL, NULL, NULL);
07365         return(NULL);
07366     } else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
07367         xmlSchemaCustomWarning(ACTXT_CAST pctxt,
07368         XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
07369         node, NULL,
07370         "Skipping attribute use prohibition, since it is "
07371         "pointless when extending a type",
07372         NULL, NULL, NULL);
07373         return(NULL);
07374     }
07375     if (! isRef) {
07376         tmpName = name;
07377         tmpNs = ns;
07378     }
07379     /*
07380     * Check for duplicate attribute prohibitions.
07381     */
07382     if (uses) {
07383         int i;
07384 
07385         for (i = 0; i < uses->nbItems; i++) {
07386         use = uses->items[i];
07387         if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
07388             (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
07389             (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
07390         {
07391             xmlChar *str = NULL;
07392 
07393             xmlSchemaCustomWarning(ACTXT_CAST pctxt,
07394             XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
07395             node, NULL,
07396             "Skipping duplicate attribute use prohibition '%s'",
07397             xmlSchemaFormatQName(&str, tmpNs, tmpName),
07398             NULL, NULL);
07399             FREE_AND_NULL(str)
07400             return(NULL);
07401         }
07402         }
07403     }
07404     /*
07405     * Create the attribute prohibition helper component.
07406     */
07407     prohib = xmlSchemaAddAttributeUseProhib(pctxt);
07408     if (prohib == NULL)
07409         return(NULL);
07410     prohib->node = node;
07411     prohib->name = tmpName;
07412     prohib->targetNamespace = tmpNs;
07413     if (isRef) {
07414         /*
07415         * We need at least to resolve to the attribute declaration.
07416         */
07417         WXS_ADD_PENDING(pctxt, prohib);
07418     }
07419     return(WXS_BASIC_CAST prohib);
07420     } else {
07421     if (IS_SCHEMA(child, "annotation")) {
07422         /*
07423         * TODO: Should this go into the attr decl?
07424         */
07425         use->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
07426         child = child->next;
07427     }
07428     if (isRef) {
07429         if (child != NULL) {
07430         if (IS_SCHEMA(child, "simpleType"))
07431             /*
07432             * 3.2.3 : 3.2
07433             * If ref is present, then all of <simpleType>,
07434             * form and type must be absent.
07435             */
07436             xmlSchemaPContentErr(pctxt,
07437             XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
07438             NULL, node, child, NULL,
07439             "(annotation?)");
07440         else
07441             xmlSchemaPContentErr(pctxt,
07442             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
07443             NULL, node, child, NULL,
07444             "(annotation?)");
07445         }
07446     } else {
07447         if (IS_SCHEMA(child, "simpleType")) {
07448         if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
07449             /*
07450             * 3.2.3 : 4
07451             * type and <simpleType> must not both be present.
07452             */
07453             xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
07454             NULL, node, child,
07455             "The attribute 'type' and the <simpleType> child "
07456             "are mutually exclusive", NULL);
07457         } else
07458             WXS_ATTRUSE_TYPEDEF(use) =
07459             xmlSchemaParseSimpleType(pctxt, schema, child, 0);
07460         child = child->next;
07461         }
07462         if (child != NULL)
07463         xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
07464         NULL, node, child, NULL,
07465         "(annotation?, simpleType?)");
07466     }
07467     }
07468     return (WXS_BASIC_CAST use);
07469 }
07470 
07471 
07472 static xmlSchemaAttributePtr
07473 xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
07474                   xmlSchemaPtr schema,
07475                   xmlNodePtr node)
07476 {
07477     const xmlChar *attrValue;
07478     xmlSchemaAttributePtr ret;
07479     xmlNodePtr child = NULL;
07480     xmlAttrPtr attr;
07481 
07482     /*
07483      * Note that the w3c spec assumes the schema to be validated with schema
07484      * for schemas beforehand.
07485      *
07486      * 3.2.3 Constraints on XML Representations of Attribute Declarations
07487      */
07488     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
07489         return (NULL);
07490     /*
07491     * 3.2.3 : 3.1
07492     * One of ref or name must be present, but not both
07493     */
07494     attr = xmlSchemaGetPropNode(node, "name");
07495     if (attr == NULL) {
07496     xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
07497         NULL, node, "name", NULL);
07498     return (NULL);
07499     }
07500     if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
07501     xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
07502     return (NULL);
07503     }
07504     /*
07505     * 3.2.6 Schema Component Constraint: xmlns Not Allowed
07506     * TODO: Move this to the component layer.
07507     */
07508     if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
07509     xmlSchemaPSimpleTypeErr(pctxt,
07510         XML_SCHEMAP_NO_XMLNS,
07511         NULL, (xmlNodePtr) attr,
07512         xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
07513         "The value of the attribute must not match 'xmlns'",
07514         NULL, NULL);
07515     return (NULL);
07516     }
07517     /*
07518     * 3.2.6 Schema Component Constraint: xsi: Not Allowed
07519     * TODO: Move this to the component layer.
07520     *       Or better leave it here and add it to the component layer
07521     *       if we have a schema construction API.
07522     */
07523     if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
07524     xmlSchemaCustomErr(ACTXT_CAST pctxt,
07525         XML_SCHEMAP_NO_XSI, node, NULL,
07526         "The target namespace must not match '%s'",
07527         xmlSchemaInstanceNs, NULL);
07528     }
07529 
07530     ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
07531     pctxt->targetNamespace, node, 1);
07532     if (ret == NULL)
07533     return (NULL);
07534     ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
07535 
07536     /*
07537     * Check for illegal attributes.
07538     */
07539     attr = node->properties;
07540     while (attr != NULL) {
07541     if (attr->ns == NULL) {
07542         if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
07543         (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
07544         (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
07545         (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
07546         (!xmlStrEqual(attr->name, BAD_CAST "type")))
07547         {
07548         xmlSchemaPIllegalAttrErr(pctxt,
07549             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
07550         }
07551     } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
07552         xmlSchemaPIllegalAttrErr(pctxt,
07553         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
07554     }
07555     attr = attr->next;
07556     }
07557     xmlSchemaPValAttrQName(pctxt, schema, NULL,
07558     node, "type", &ret->typeNs, &ret->typeName);
07559 
07560     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
07561     /*
07562     * Attribute "fixed".
07563     */
07564     ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
07565     if (ret->defValue != NULL)
07566     ret->flags |= XML_SCHEMAS_ATTR_FIXED;
07567     /*
07568     * Attribute "default".
07569     */
07570     attr = xmlSchemaGetPropNode(node, "default");
07571     if (attr != NULL) {
07572     /*
07573     * 3.2.3 : 1
07574     * default and fixed must not both be present.
07575     */
07576     if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
07577         xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
07578         WXS_BASIC_CAST ret, attr, "default", "fixed");
07579     } else
07580         ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
07581     }
07582     /*
07583     * And now for the children...
07584     */
07585     child = node->children;
07586     if (IS_SCHEMA(child, "annotation")) {
07587         ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
07588         child = child->next;
07589     }
07590     if (IS_SCHEMA(child, "simpleType")) {
07591     if (ret->typeName != NULL) {
07592         /*
07593         * 3.2.3 : 4
07594         * type and <simpleType> must not both be present.
07595         */
07596         xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
07597         NULL, node, child,
07598         "The attribute 'type' and the <simpleType> child "
07599         "are mutually exclusive", NULL);
07600     } else
07601         ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
07602     child = child->next;
07603     }
07604     if (child != NULL)
07605     xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
07606         NULL, node, child, NULL,
07607         "(annotation?, simpleType?)");
07608 
07609     return (ret);
07610 }
07611 
07625 static xmlSchemaQNameRefPtr
07626 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
07627                 xmlSchemaPtr schema,
07628                 xmlNodePtr node)
07629 {
07630     xmlSchemaQNameRefPtr ret;
07631     xmlNodePtr child = NULL;
07632     xmlAttrPtr attr;
07633     const xmlChar *refNs = NULL, *ref = NULL;
07634 
07635     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
07636         return (NULL);
07637 
07638     attr = xmlSchemaGetPropNode(node, "ref");
07639     if (attr == NULL) {
07640     xmlSchemaPMissingAttrErr(pctxt,
07641         XML_SCHEMAP_S4S_ATTR_MISSING,
07642         NULL, node, "ref", NULL);
07643     return (NULL);
07644     }
07645     xmlSchemaPValAttrNodeQName(pctxt, schema,
07646     NULL, attr, &refNs, &ref);
07647     if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
07648     return(NULL);
07649 
07650     /*
07651     * Check for illegal attributes.
07652     */
07653     attr = node->properties;
07654     while (attr != NULL) {
07655     if (attr->ns == NULL) {
07656         if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
07657         (!xmlStrEqual(attr->name, BAD_CAST "id")))
07658         {
07659         xmlSchemaPIllegalAttrErr(pctxt,
07660             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
07661         }
07662     } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
07663         xmlSchemaPIllegalAttrErr(pctxt,
07664         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
07665     }
07666     attr = attr->next;
07667     }
07668     /* Attribute ID */
07669     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
07670 
07671     /*
07672     * And now for the children...
07673     */
07674     child = node->children;
07675     if (IS_SCHEMA(child, "annotation")) {
07676     /*
07677     * TODO: We do not have a place to store the annotation, do we?
07678     */
07679         xmlSchemaParseAnnotation(pctxt, child, 0);
07680         child = child->next;
07681     }
07682     if (child != NULL) {
07683     xmlSchemaPContentErr(pctxt,
07684         XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
07685         NULL, node, child, NULL,
07686         "(annotation?)");
07687     }
07688 
07689     /*
07690     * Handle attribute group redefinitions.
07691     */
07692     if (pctxt->isRedefine && pctxt->redef &&
07693     (pctxt->redef->item->type ==
07694         XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
07695     (ref == pctxt->redef->refName) &&
07696     (refNs == pctxt->redef->refTargetNs))
07697     {
07698     /*
07699     * SPEC src-redefine:
07700     * (7.1) "If it has an <attributeGroup> among its contents
07701     * the �actual value� of whose ref [attribute] is the same
07702     * as the �actual value� of its own name attribute plus
07703     * target namespace, then it must have exactly one such group."
07704     */
07705     if (pctxt->redefCounter != 0) {
07706         xmlChar *str = NULL;
07707 
07708         xmlSchemaCustomErr(ACTXT_CAST pctxt,
07709         XML_SCHEMAP_SRC_REDEFINE, node, NULL,
07710         "The redefining attribute group definition "
07711         "'%s' must not contain more than one "
07712         "reference to the redefined definition",
07713         xmlSchemaFormatQName(&str, refNs, ref), NULL);
07714         FREE_AND_NULL(str);
07715         return(NULL);
07716     }
07717     pctxt->redefCounter++;
07718     /*
07719     * URGENT TODO: How to ensure that the reference will not be
07720     * handled by the normal component resolution mechanism?
07721     */
07722     ret = xmlSchemaNewQNameRef(pctxt,
07723         XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
07724     if (ret == NULL)
07725         return(NULL);
07726     ret->node = node;
07727     pctxt->redef->reference = WXS_BASIC_CAST ret;
07728     } else {
07729     /*
07730     * Create a QName-reference helper component. We will substitute this
07731     * component for the attribute uses of the referenced attribute group
07732     * definition.
07733     */
07734     ret = xmlSchemaNewQNameRef(pctxt,
07735         XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
07736     if (ret == NULL)
07737         return(NULL);
07738     ret->node = node;
07739     /* Add to pending items, to be able to resolve the reference. */
07740     WXS_ADD_PENDING(pctxt, ret);
07741     }
07742     return (ret);
07743 }
07744 
07756 static xmlSchemaAttributeGroupPtr
07757 xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
07758                        xmlSchemaPtr schema,
07759                        xmlNodePtr node)
07760 {
07761     const xmlChar *name;
07762     xmlSchemaAttributeGroupPtr ret;
07763     xmlNodePtr child = NULL;
07764     xmlAttrPtr attr;
07765     int hasRefs = 0;
07766 
07767     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
07768         return (NULL);
07769 
07770     attr = xmlSchemaGetPropNode(node, "name");
07771     if (attr == NULL) {
07772     xmlSchemaPMissingAttrErr(pctxt,
07773         XML_SCHEMAP_S4S_ATTR_MISSING,
07774         NULL, node, "name", NULL);
07775     return (NULL);
07776     }
07777     /*
07778     * The name is crucial, exit if invalid.
07779     */
07780     if (xmlSchemaPValAttrNode(pctxt,
07781     NULL, attr,
07782     xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
07783     return (NULL);
07784     }
07785     ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
07786     name, pctxt->targetNamespace, node);
07787     if (ret == NULL)
07788     return (NULL);
07789     /*
07790     * Check for illegal attributes.
07791     */
07792     attr = node->properties;
07793     while (attr != NULL) {
07794     if (attr->ns == NULL) {
07795         if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
07796         (!xmlStrEqual(attr->name, BAD_CAST "id")))
07797         {
07798         xmlSchemaPIllegalAttrErr(pctxt,
07799             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
07800         }
07801     } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
07802         xmlSchemaPIllegalAttrErr(pctxt,
07803         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
07804     }
07805     attr = attr->next;
07806     }
07807     /* Attribute ID */
07808     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
07809     /*
07810     * And now for the children...
07811     */
07812     child = node->children;
07813     if (IS_SCHEMA(child, "annotation")) {
07814         ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
07815         child = child->next;
07816     }
07817     /*
07818     * Parse contained attribute decls/refs.
07819     */
07820     if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
07821     (xmlSchemaItemListPtr *) &(ret->attrUses),
07822     XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
07823     return(NULL);
07824     if (hasRefs)
07825     ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
07826     /*
07827     * Parse the attribute wildcard.
07828     */
07829     if (IS_SCHEMA(child, "anyAttribute")) {
07830     ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
07831         schema, child);
07832     child = child->next;
07833     }
07834     if (child != NULL) {
07835     xmlSchemaPContentErr(pctxt,
07836         XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
07837         NULL, node, child, NULL,
07838         "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
07839     }
07840     return (ret);
07841 }
07842 
07851 static int
07852 xmlSchemaPValAttrFormDefault(const xmlChar *value,
07853                  int *flags,
07854                  int flagQualified)
07855 {
07856     if (xmlStrEqual(value, BAD_CAST "qualified")) {
07857     if  ((*flags & flagQualified) == 0)
07858         *flags |= flagQualified;
07859     } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
07860     return (1);
07861 
07862     return (0);
07863 }
07864 
07882 static int
07883 xmlSchemaPValAttrBlockFinal(const xmlChar *value,
07884                 int *flags,
07885                 int flagAll,
07886                 int flagExtension,
07887                 int flagRestriction,
07888                 int flagSubstitution,
07889                 int flagList,
07890                 int flagUnion)
07891 {
07892     int ret = 0;
07893 
07894     /*
07895     * TODO: This does not check for dublicate entries.
07896     */
07897     if ((flags == NULL) || (value == NULL))
07898     return (-1);
07899     if (value[0] == 0)
07900     return (0);
07901     if (xmlStrEqual(value, BAD_CAST "#all")) {
07902     if (flagAll != -1)
07903         *flags |= flagAll;
07904     else {
07905         if (flagExtension != -1)
07906         *flags |= flagExtension;
07907         if (flagRestriction != -1)
07908         *flags |= flagRestriction;
07909         if (flagSubstitution != -1)
07910         *flags |= flagSubstitution;
07911         if (flagList != -1)
07912         *flags |= flagList;
07913         if (flagUnion != -1)
07914         *flags |= flagUnion;
07915     }
07916     } else {
07917     const xmlChar *end, *cur = value;
07918     xmlChar *item;
07919 
07920     do {
07921         while (IS_BLANK_CH(*cur))
07922         cur++;
07923         end = cur;
07924         while ((*end != 0) && (!(IS_BLANK_CH(*end))))
07925         end++;
07926         if (end == cur)
07927         break;
07928         item = xmlStrndup(cur, end - cur);
07929         if (xmlStrEqual(item, BAD_CAST "extension")) {
07930         if (flagExtension != -1) {
07931             if ((*flags & flagExtension) == 0)
07932             *flags |= flagExtension;
07933         } else
07934             ret = 1;
07935         } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
07936         if (flagRestriction != -1) {
07937             if ((*flags & flagRestriction) == 0)
07938             *flags |= flagRestriction;
07939         } else
07940             ret = 1;
07941         } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
07942         if (flagSubstitution != -1) {
07943             if ((*flags & flagSubstitution) == 0)
07944             *flags |= flagSubstitution;
07945         } else
07946             ret = 1;
07947         } else if (xmlStrEqual(item, BAD_CAST "list")) {
07948         if (flagList != -1) {
07949             if ((*flags & flagList) == 0)
07950             *flags |= flagList;
07951         } else
07952             ret = 1;
07953         } else if (xmlStrEqual(item, BAD_CAST "union")) {
07954         if (flagUnion != -1) {
07955             if ((*flags & flagUnion) == 0)
07956             *flags |= flagUnion;
07957         } else
07958             ret = 1;
07959         } else
07960         ret = 1;
07961         if (item != NULL)
07962         xmlFree(item);
07963         cur = end;
07964     } while ((ret == 0) && (*cur != 0));
07965     }
07966 
07967     return (ret);
07968 }
07969 
07970 static int
07971 xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
07972                  xmlSchemaIDCPtr idc,
07973                  xmlSchemaIDCSelectPtr selector,
07974                  xmlAttrPtr attr,
07975                  int isField)
07976 {
07977     xmlNodePtr node;
07978 
07979     /*
07980     * c-selector-xpath:
07981     * Schema Component Constraint: Selector Value OK
07982     *
07983     * TODO: 1 The {selector} must be a valid XPath expression, as defined
07984     * in [XPath].
07985     */
07986     if (selector == NULL) {
07987     xmlSchemaPErr(ctxt, idc->node,
07988         XML_SCHEMAP_INTERNAL,
07989         "Internal error: xmlSchemaCheckCSelectorXPath, "
07990         "the selector is not specified.\n", NULL, NULL);
07991     return (-1);
07992     }
07993     if (attr == NULL)
07994     node = idc->node;
07995     else
07996     node = (xmlNodePtr) attr;
07997     if (selector->xpath == NULL) {
07998     xmlSchemaPCustomErr(ctxt,
07999         /* TODO: Adjust error code. */
08000         XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
08001         NULL, node,
08002         "The XPath expression of the selector is not valid", NULL);
08003     return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
08004     } else {
08005     const xmlChar **nsArray = NULL;
08006     xmlNsPtr *nsList = NULL;
08007     /*
08008     * Compile the XPath expression.
08009     */
08010     /*
08011     * TODO: We need the array of in-scope namespaces for compilation.
08012     * TODO: Call xmlPatterncompile with different options for selector/
08013     * field.
08014     */
08015     if (attr == NULL)
08016         nsList = NULL;
08017     else
08018         nsList = xmlGetNsList(attr->doc, attr->parent);
08019     /*
08020     * Build an array of prefixes and namespaces.
08021     */
08022     if (nsList != NULL) {
08023         int i, count = 0;
08024 
08025         for (i = 0; nsList[i] != NULL; i++)
08026         count++;
08027 
08028         nsArray = (const xmlChar **) xmlMalloc(
08029         (count * 2 + 1) * sizeof(const xmlChar *));
08030         if (nsArray == NULL) {
08031         xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
08032             NULL);
08033         xmlFree(nsList);
08034         return (-1);
08035         }
08036         for (i = 0; i < count; i++) {
08037         nsArray[2 * i] = nsList[i]->href;
08038         nsArray[2 * i + 1] = nsList[i]->prefix;
08039         }
08040         nsArray[count * 2] = NULL;
08041         xmlFree(nsList);
08042     }
08043     /*
08044     * TODO: Differentiate between "selector" and "field".
08045     */
08046     if (isField)
08047         selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
08048         NULL, XML_PATTERN_XSFIELD, nsArray);
08049     else
08050         selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
08051         NULL, XML_PATTERN_XSSEL, nsArray);
08052     if (nsArray != NULL)
08053         xmlFree((xmlChar **) nsArray);
08054 
08055     if (selector->xpathComp == NULL) {
08056         xmlSchemaPCustomErr(ctxt,
08057         /* TODO: Adjust error code? */
08058         XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
08059         NULL, node,
08060         "The XPath expression '%s' could not be "
08061         "compiled", selector->xpath);
08062         return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
08063     }
08064     }
08065     return (0);
08066 }
08067 
08068 #define ADD_ANNOTATION(annot)   \
08069     xmlSchemaAnnotPtr cur = item->annot; \
08070     if (item->annot == NULL) {  \
08071     item->annot = annot;    \
08072     return (annot);         \
08073     }                           \
08074     cur = item->annot;          \
08075     if (cur->next != NULL) {    \
08076     cur = cur->next;    \
08077     }                           \
08078     cur->next = annot;
08079 
08089 static xmlSchemaAnnotPtr
08090 xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
08091                xmlSchemaAnnotPtr annot)
08092 {
08093     if ((annItem == NULL) || (annot == NULL))
08094     return (NULL);
08095     switch (annItem->type) {
08096     case XML_SCHEMA_TYPE_ELEMENT: {
08097         xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
08098         ADD_ANNOTATION(annot)
08099         }
08100         break;
08101     case XML_SCHEMA_TYPE_ATTRIBUTE: {
08102         xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
08103         ADD_ANNOTATION(annot)
08104         }
08105         break;
08106     case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
08107     case XML_SCHEMA_TYPE_ANY: {
08108         xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
08109         ADD_ANNOTATION(annot)
08110         }
08111         break;
08112     case XML_SCHEMA_TYPE_PARTICLE:
08113     case XML_SCHEMA_TYPE_IDC_KEY:
08114     case XML_SCHEMA_TYPE_IDC_KEYREF:
08115     case XML_SCHEMA_TYPE_IDC_UNIQUE: {
08116         xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
08117         ADD_ANNOTATION(annot)
08118         }
08119         break;
08120     case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
08121         xmlSchemaAttributeGroupPtr item =
08122             (xmlSchemaAttributeGroupPtr) annItem;
08123         ADD_ANNOTATION(annot)
08124         }
08125         break;
08126     case XML_SCHEMA_TYPE_NOTATION: {
08127         xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
08128         ADD_ANNOTATION(annot)
08129         }
08130         break;
08131     case XML_SCHEMA_FACET_MININCLUSIVE:
08132     case XML_SCHEMA_FACET_MINEXCLUSIVE:
08133     case XML_SCHEMA_FACET_MAXINCLUSIVE:
08134     case XML_SCHEMA_FACET_MAXEXCLUSIVE:
08135     case XML_SCHEMA_FACET_TOTALDIGITS:
08136     case XML_SCHEMA_FACET_FRACTIONDIGITS:
08137     case XML_SCHEMA_FACET_PATTERN:
08138     case XML_SCHEMA_FACET_ENUMERATION:
08139     case XML_SCHEMA_FACET_WHITESPACE:
08140     case XML_SCHEMA_FACET_LENGTH:
08141     case XML_SCHEMA_FACET_MAXLENGTH:
08142     case XML_SCHEMA_FACET_MINLENGTH: {
08143         xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
08144         ADD_ANNOTATION(annot)
08145         }
08146         break;
08147     case XML_SCHEMA_TYPE_SIMPLE:
08148     case XML_SCHEMA_TYPE_COMPLEX: {
08149         xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
08150         ADD_ANNOTATION(annot)
08151         }
08152         break;
08153     case XML_SCHEMA_TYPE_GROUP: {
08154         xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
08155         ADD_ANNOTATION(annot)
08156         }
08157         break;
08158     case XML_SCHEMA_TYPE_SEQUENCE:
08159     case XML_SCHEMA_TYPE_CHOICE:
08160     case XML_SCHEMA_TYPE_ALL: {
08161         xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
08162         ADD_ANNOTATION(annot)
08163         }
08164         break;
08165     default:
08166          xmlSchemaPCustomErr(NULL,
08167         XML_SCHEMAP_INTERNAL,
08168         NULL, NULL,
08169         "Internal error: xmlSchemaAddAnnotation, "
08170         "The item is not a annotated schema component", NULL);
08171          break;
08172     }
08173     return (annot);
08174 }
08175 
08187 static xmlSchemaIDCSelectPtr
08188 xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
08189               xmlSchemaIDCPtr idc,
08190               xmlNodePtr node,
08191               int isField)
08192 {
08193     xmlSchemaIDCSelectPtr item;
08194     xmlNodePtr child = NULL;
08195     xmlAttrPtr attr;
08196 
08197     /*
08198     * Check for illegal attributes.
08199     */
08200     attr = node->properties;
08201     while (attr != NULL) {
08202     if (attr->ns == NULL) {
08203         if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
08204         (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
08205         xmlSchemaPIllegalAttrErr(ctxt,
08206             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
08207         }
08208     } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
08209         xmlSchemaPIllegalAttrErr(ctxt,
08210         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
08211     }
08212     attr = attr->next;
08213     }
08214     /*
08215     * Create the item.
08216     */
08217     item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
08218     if (item == NULL) {
08219         xmlSchemaPErrMemory(ctxt,
08220         "allocating a 'selector' of an identity-constraint definition",
08221         NULL);
08222         return (NULL);
08223     }
08224     memset(item, 0, sizeof(xmlSchemaIDCSelect));
08225     /*
08226     * Attribute "xpath" (mandatory).
08227     */
08228     attr = xmlSchemaGetPropNode(node, "xpath");
08229     if (attr == NULL) {
08230         xmlSchemaPMissingAttrErr(ctxt,
08231         XML_SCHEMAP_S4S_ATTR_MISSING,
08232         NULL, node,
08233         "name", NULL);
08234     } else {
08235     item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
08236     /*
08237     * URGENT TODO: "field"s have an other syntax than "selector"s.
08238     */
08239 
08240     if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
08241         isField) == -1) {
08242         xmlSchemaPErr(ctxt,
08243         (xmlNodePtr) attr,
08244         XML_SCHEMAP_INTERNAL,
08245         "Internal error: xmlSchemaParseIDCSelectorAndField, "
08246         "validating the XPath expression of a IDC selector.\n",
08247         NULL, NULL);
08248     }
08249 
08250     }
08251     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
08252     /*
08253     * And now for the children...
08254     */
08255     child = node->children;
08256     if (IS_SCHEMA(child, "annotation")) {
08257     /*
08258     * Add the annotation to the parent IDC.
08259     */
08260     xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
08261         xmlSchemaParseAnnotation(ctxt, child, 1));
08262     child = child->next;
08263     }
08264     if (child != NULL) {
08265     xmlSchemaPContentErr(ctxt,
08266         XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
08267         NULL, node, child,
08268         NULL, "(annotation?)");
08269     }
08270 
08271     return (item);
08272 }
08273 
08284 static xmlSchemaIDCPtr
08285 xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
08286           xmlSchemaPtr schema,
08287           xmlNodePtr node,
08288           xmlSchemaTypeType idcCategory,
08289           const xmlChar *targetNamespace)
08290 {
08291     xmlSchemaIDCPtr item = NULL;
08292     xmlNodePtr child = NULL;
08293     xmlAttrPtr attr;
08294     const xmlChar *name = NULL;
08295     xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
08296 
08297     /*
08298     * Check for illegal attributes.
08299     */
08300     attr = node->properties;
08301     while (attr != NULL) {
08302     if (attr->ns == NULL) {
08303         if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
08304         (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
08305         ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
08306          (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
08307         xmlSchemaPIllegalAttrErr(ctxt,
08308             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
08309         }
08310     } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
08311         xmlSchemaPIllegalAttrErr(ctxt,
08312         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
08313     }
08314     attr = attr->next;
08315     }
08316     /*
08317     * Attribute "name" (mandatory).
08318     */
08319     attr = xmlSchemaGetPropNode(node, "name");
08320     if (attr == NULL) {
08321     xmlSchemaPMissingAttrErr(ctxt,
08322         XML_SCHEMAP_S4S_ATTR_MISSING,
08323         NULL, node,
08324         "name", NULL);
08325     return (NULL);
08326     } else if (xmlSchemaPValAttrNode(ctxt,
08327     NULL, attr,
08328     xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
08329     return (NULL);
08330     }
08331     /* Create the component. */
08332     item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
08333     idcCategory, node);
08334     if (item == NULL)
08335     return(NULL);
08336 
08337     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
08338     if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
08339     /*
08340     * Attribute "refer" (mandatory).
08341     */
08342     attr = xmlSchemaGetPropNode(node, "refer");
08343     if (attr == NULL) {
08344         xmlSchemaPMissingAttrErr(ctxt,
08345         XML_SCHEMAP_S4S_ATTR_MISSING,
08346         NULL, node,
08347         "refer", NULL);
08348     } else {
08349         /*
08350         * Create a reference item.
08351         */
08352         item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
08353         NULL, NULL);
08354         if (item->ref == NULL)
08355         return (NULL);
08356         xmlSchemaPValAttrNodeQName(ctxt, schema,
08357         NULL, attr,
08358         &(item->ref->targetNamespace),
08359         &(item->ref->name));
08360         xmlSchemaCheckReference(ctxt, schema, node, attr,
08361         item->ref->targetNamespace);
08362     }
08363     }
08364     /*
08365     * And now for the children...
08366     */
08367     child = node->children;
08368     if (IS_SCHEMA(child, "annotation")) {
08369     item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
08370     child = child->next;
08371     }
08372     if (child == NULL) {
08373     xmlSchemaPContentErr(ctxt,
08374         XML_SCHEMAP_S4S_ELEM_MISSING,
08375         NULL, node, child,
08376         "A child element is missing",
08377         "(annotation?, (selector, field+))");
08378     }
08379     /*
08380     * Child element <selector>.
08381     */
08382     if (IS_SCHEMA(child, "selector")) {
08383     item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
08384         item, child, 0);
08385     child = child->next;
08386     /*
08387     * Child elements <field>.
08388     */
08389     if (IS_SCHEMA(child, "field")) {
08390         do {
08391         field = xmlSchemaParseIDCSelectorAndField(ctxt,
08392             item, child, 1);
08393         if (field != NULL) {
08394             field->index = item->nbFields;
08395             item->nbFields++;
08396             if (lastField != NULL)
08397             lastField->next = field;
08398             else
08399             item->fields = field;
08400             lastField = field;
08401         }
08402         child = child->next;
08403         } while (IS_SCHEMA(child, "field"));
08404     } else {
08405         xmlSchemaPContentErr(ctxt,
08406         XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
08407         NULL, node, child,
08408         NULL, "(annotation?, (selector, field+))");
08409     }
08410     }
08411     if (child != NULL) {
08412     xmlSchemaPContentErr(ctxt,
08413         XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
08414         NULL, node, child,
08415         NULL, "(annotation?, (selector, field+))");
08416     }
08417 
08418     return (item);
08419 }
08420 
08434 static xmlSchemaBasicItemPtr
08435 xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
08436                       xmlNodePtr node, int *isElemRef, int topLevel)
08437 {
08438     xmlSchemaElementPtr decl = NULL;
08439     xmlSchemaParticlePtr particle = NULL;
08440     xmlSchemaAnnotPtr annot = NULL;
08441     xmlNodePtr child = NULL;
08442     xmlAttrPtr attr, nameAttr;
08443     int min, max, isRef = 0;
08444     xmlChar *des = NULL;
08445 
08446     /* 3.3.3 Constraints on XML Representations of Element Declarations */
08447     /* TODO: Complete implementation of 3.3.6 */
08448 
08449     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
08450         return (NULL);
08451 
08452     if (isElemRef != NULL)
08453     *isElemRef = 0;
08454     /*
08455     * If we get a "ref" attribute on a local <element> we will assume it's
08456     * a reference - even if there's a "name" attribute; this seems to be more
08457     * robust.
08458     */
08459     nameAttr = xmlSchemaGetPropNode(node, "name");
08460     attr = xmlSchemaGetPropNode(node, "ref");
08461     if ((topLevel) || (attr == NULL)) {
08462     if (nameAttr == NULL) {
08463         xmlSchemaPMissingAttrErr(ctxt,
08464         XML_SCHEMAP_S4S_ATTR_MISSING,
08465         NULL, node, "name", NULL);
08466         return (NULL);
08467     }
08468     } else
08469     isRef = 1;
08470 
08471     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
08472     child = node->children;
08473     if (IS_SCHEMA(child, "annotation")) {
08474     annot = xmlSchemaParseAnnotation(ctxt, child, 1);
08475     child = child->next;
08476     }
08477     /*
08478     * Skip particle part if a global declaration.
08479     */
08480     if (topLevel)
08481     goto declaration_part;
08482     /*
08483     * The particle part ==================================================
08484     */
08485     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
08486     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
08487     xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
08488     particle = xmlSchemaAddParticle(ctxt, node, min, max);
08489     if (particle == NULL)
08490     goto return_null;
08491 
08492     /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
08493 
08494     if (isRef) {
08495     const xmlChar *refNs = NULL, *ref = NULL;
08496     xmlSchemaQNameRefPtr refer = NULL;
08497     /*
08498     * The reference part =============================================
08499     */
08500     if (isElemRef != NULL)
08501         *isElemRef = 1;
08502 
08503     xmlSchemaPValAttrNodeQName(ctxt, schema,
08504         NULL, attr, &refNs, &ref);
08505     xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
08506     /*
08507     * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
08508     */
08509     if (nameAttr != NULL) {
08510         xmlSchemaPMutualExclAttrErr(ctxt,
08511         XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
08512     }
08513     /*
08514     * Check for illegal attributes.
08515     */
08516     attr = node->properties;
08517     while (attr != NULL) {
08518         if (attr->ns == NULL) {
08519         if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
08520             xmlStrEqual(attr->name, BAD_CAST "name") ||
08521             xmlStrEqual(attr->name, BAD_CAST "id") ||
08522             xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
08523             xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
08524         {
08525             attr = attr->next;
08526             continue;
08527         } else {
08528             /* SPEC (3.3.3 : 2.2) */
08529             xmlSchemaPCustomAttrErr(ctxt,
08530             XML_SCHEMAP_SRC_ELEMENT_2_2,
08531             NULL, NULL, attr,
08532             "Only the attributes 'minOccurs', 'maxOccurs' and "
08533             "'id' are allowed in addition to 'ref'");
08534             break;
08535         }
08536         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
08537         xmlSchemaPIllegalAttrErr(ctxt,
08538             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
08539         }
08540         attr = attr->next;
08541     }
08542     /*
08543     * No children except <annotation> expected.
08544     */
08545     if (child != NULL) {
08546         xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
08547         NULL, node, child, NULL, "(annotation?)");
08548     }
08549     if ((min == 0) && (max == 0))
08550         goto return_null;
08551     /*
08552     * Create the reference item and attach it to the particle.
08553     */
08554     refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
08555         ref, refNs);
08556     if (refer == NULL)
08557         goto return_null;
08558     particle->children = (xmlSchemaTreeItemPtr) refer;
08559     particle->annot = annot;
08560     /*
08561     * Add the particle to pending components, since the reference
08562     * need to be resolved.
08563     */
08564     WXS_ADD_PENDING(ctxt, particle);
08565     return ((xmlSchemaBasicItemPtr) particle);
08566     }
08567     /*
08568     * The declaration part ===============================================
08569     */
08570 declaration_part:
08571     {
08572     const xmlChar *ns = NULL, *fixed, *name, *attrValue;
08573     xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
08574 
08575     if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
08576         xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
08577         goto return_null;
08578     /*
08579     * Evaluate the target namespace.
08580     */
08581     if (topLevel) {
08582         ns = ctxt->targetNamespace;
08583     } else {
08584         attr = xmlSchemaGetPropNode(node, "form");
08585         if (attr != NULL) {
08586         attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
08587         if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
08588             ns = ctxt->targetNamespace;
08589         } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
08590             xmlSchemaPSimpleTypeErr(ctxt,
08591             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
08592             NULL, (xmlNodePtr) attr,
08593             NULL, "(qualified | unqualified)",
08594             attrValue, NULL, NULL, NULL);
08595         }
08596         } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
08597         ns = ctxt->targetNamespace;
08598     }
08599     decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
08600     if (decl == NULL) {
08601         goto return_null;
08602     }
08603     /*
08604     * Check for illegal attributes.
08605     */
08606     attr = node->properties;
08607     while (attr != NULL) {
08608         if (attr->ns == NULL) {
08609         if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
08610             (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
08611             (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
08612             (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
08613             (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
08614             (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
08615             (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
08616         {
08617             if (topLevel == 0) {
08618             if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
08619                 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
08620                 (!xmlStrEqual(attr->name, BAD_CAST "form")))
08621             {
08622                 xmlSchemaPIllegalAttrErr(ctxt,
08623                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
08624             }
08625             } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
08626             (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
08627             (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
08628 
08629             xmlSchemaPIllegalAttrErr(ctxt,
08630                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
08631             }
08632         }
08633         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
08634 
08635         xmlSchemaPIllegalAttrErr(ctxt,
08636             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
08637         }
08638         attr = attr->next;
08639     }
08640     /*
08641     * Extract/validate attributes.
08642     */
08643     if (topLevel) {
08644         /*
08645         * Process top attributes of global element declarations here.
08646         */
08647         decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
08648         decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
08649         xmlSchemaPValAttrQName(ctxt, schema,
08650         NULL, node, "substitutionGroup",
08651         &(decl->substGroupNs), &(decl->substGroup));
08652         if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
08653         decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
08654         /*
08655         * Attribute "final".
08656         */
08657         attr = xmlSchemaGetPropNode(node, "final");
08658         if (attr == NULL) {
08659         if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
08660             decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
08661         if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
08662             decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
08663         } else {
08664         attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
08665         if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
08666             -1,
08667             XML_SCHEMAS_ELEM_FINAL_EXTENSION,
08668             XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
08669             xmlSchemaPSimpleTypeErr(ctxt,
08670             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
08671             NULL, (xmlNodePtr) attr,
08672             NULL, "(#all | List of (extension | restriction))",
08673             attrValue, NULL, NULL, NULL);
08674         }
08675         }
08676     }
08677     /*
08678     * Attribute "block".
08679     */
08680     attr = xmlSchemaGetPropNode(node, "block");
08681     if (attr == NULL) {
08682         /*
08683         * Apply default "block" values.
08684         */
08685         if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
08686         decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
08687         if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
08688         decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
08689         if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
08690         decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
08691     } else {
08692         attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
08693         if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
08694         -1,
08695         XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
08696         XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
08697         XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
08698         xmlSchemaPSimpleTypeErr(ctxt,
08699             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
08700             NULL, (xmlNodePtr) attr,
08701             NULL, "(#all | List of (extension | "
08702             "restriction | substitution))", attrValue,
08703             NULL, NULL, NULL);
08704         }
08705     }
08706     if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
08707         decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
08708 
08709     attr = xmlSchemaGetPropNode(node, "type");
08710     if (attr != NULL) {
08711         xmlSchemaPValAttrNodeQName(ctxt, schema,
08712         NULL, attr,
08713         &(decl->namedTypeNs), &(decl->namedType));
08714         xmlSchemaCheckReference(ctxt, schema, node,
08715         attr, decl->namedTypeNs);
08716     }
08717     decl->value = xmlSchemaGetProp(ctxt, node, "default");
08718     attr = xmlSchemaGetPropNode(node, "fixed");
08719     if (attr != NULL) {
08720         fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
08721         if (decl->value != NULL) {
08722         /*
08723         * 3.3.3 : 1
08724         * default and fixed must not both be present.
08725         */
08726         xmlSchemaPMutualExclAttrErr(ctxt,
08727             XML_SCHEMAP_SRC_ELEMENT_1,
08728             NULL, attr, "default", "fixed");
08729         } else {
08730         decl->flags |= XML_SCHEMAS_ELEM_FIXED;
08731         decl->value = fixed;
08732         }
08733     }
08734     /*
08735     * And now for the children...
08736     */
08737     if (IS_SCHEMA(child, "complexType")) {
08738         /*
08739         * 3.3.3 : 3
08740         * "type" and either <simpleType> or <complexType> are mutually
08741         * exclusive
08742         */
08743         if (decl->namedType != NULL) {
08744         xmlSchemaPContentErr(ctxt,
08745             XML_SCHEMAP_SRC_ELEMENT_3,
08746             NULL, node, child,
08747             "The attribute 'type' and the <complexType> child are "
08748             "mutually exclusive", NULL);
08749         } else
08750         WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
08751         child = child->next;
08752     } else if (IS_SCHEMA(child, "simpleType")) {
08753         /*
08754         * 3.3.3 : 3
08755         * "type" and either <simpleType> or <complexType> are
08756         * mutually exclusive
08757         */
08758         if (decl->namedType != NULL) {
08759         xmlSchemaPContentErr(ctxt,
08760             XML_SCHEMAP_SRC_ELEMENT_3,
08761             NULL, node, child,
08762             "The attribute 'type' and the <simpleType> child are "
08763             "mutually exclusive", NULL);
08764         } else
08765         WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
08766         child = child->next;
08767     }
08768     while ((IS_SCHEMA(child, "unique")) ||
08769         (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
08770         if (IS_SCHEMA(child, "unique")) {
08771         curIDC = xmlSchemaParseIDC(ctxt, schema, child,
08772             XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
08773         } else if (IS_SCHEMA(child, "key")) {
08774         curIDC = xmlSchemaParseIDC(ctxt, schema, child,
08775             XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
08776         } else if (IS_SCHEMA(child, "keyref")) {
08777         curIDC = xmlSchemaParseIDC(ctxt, schema, child,
08778             XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
08779         }
08780         if (lastIDC != NULL)
08781         lastIDC->next = curIDC;
08782         else
08783         decl->idcs = (void *) curIDC;
08784         lastIDC = curIDC;
08785         child = child->next;
08786     }
08787     if (child != NULL) {
08788         xmlSchemaPContentErr(ctxt,
08789         XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
08790         NULL, node, child,
08791         NULL, "(annotation?, ((simpleType | complexType)?, "
08792         "(unique | key | keyref)*))");
08793     }
08794     decl->annot = annot;
08795     }
08796     /*
08797     * NOTE: Element Declaration Representation OK 4. will be checked at a
08798     * different layer.
08799     */
08800     FREE_AND_NULL(des)
08801     if (topLevel)
08802     return ((xmlSchemaBasicItemPtr) decl);
08803     else {
08804     particle->children = (xmlSchemaTreeItemPtr) decl;
08805     return ((xmlSchemaBasicItemPtr) particle);
08806     }
08807 
08808 return_null:
08809     FREE_AND_NULL(des);
08810     if (annot != NULL) {
08811     if (particle != NULL)
08812         particle->annot = NULL;
08813     if (decl != NULL)
08814         decl->annot = NULL;
08815     xmlSchemaFreeAnnot(annot);
08816     }
08817     return (NULL);
08818 }
08819 
08832 static int
08833 xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
08834                     xmlNodePtr node)
08835 {
08836     xmlSchemaTypePtr type;
08837     xmlNodePtr child = NULL;
08838     xmlAttrPtr attr;
08839     const xmlChar *cur = NULL;
08840 
08841     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
08842         return (-1);
08843     /* Not a component, don't create it. */
08844     type = ctxt->ctxtType;
08845     /*
08846     * Mark the simple type as being of variety "union".
08847     */
08848     type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
08849     /*
08850     * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
08851     * then the �simple ur-type definition�."
08852     */
08853     type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
08854     /*
08855     * Check for illegal attributes.
08856     */
08857     attr = node->properties;
08858     while (attr != NULL) {
08859     if (attr->ns == NULL) {
08860         if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
08861         (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
08862         xmlSchemaPIllegalAttrErr(ctxt,
08863             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
08864         }
08865     } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
08866         xmlSchemaPIllegalAttrErr(ctxt,
08867         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
08868     }
08869     attr = attr->next;
08870     }
08871     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
08872     /*
08873     * Attribute "memberTypes". This is a list of QNames.
08874     * TODO: Check the value to contain anything.
08875     */
08876     attr = xmlSchemaGetPropNode(node, "memberTypes");
08877     if (attr != NULL) {
08878     const xmlChar *end;
08879     xmlChar *tmp;
08880     const xmlChar *localName, *nsName;
08881     xmlSchemaTypeLinkPtr link, lastLink = NULL;
08882     xmlSchemaQNameRefPtr ref;
08883 
08884     cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
08885     type->base = cur;
08886     do {
08887         while (IS_BLANK_CH(*cur))
08888         cur++;
08889         end = cur;
08890         while ((*end != 0) && (!(IS_BLANK_CH(*end))))
08891         end++;
08892         if (end == cur)
08893         break;
08894         tmp = xmlStrndup(cur, end - cur);
08895         if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
08896         NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
08897         /*
08898         * Create the member type link.
08899         */
08900         link = (xmlSchemaTypeLinkPtr)
08901             xmlMalloc(sizeof(xmlSchemaTypeLink));
08902         if (link == NULL) {
08903             xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
08904             "allocating a type link", NULL);
08905             return (-1);
08906         }
08907         link->type = NULL;
08908         link->next = NULL;
08909         if (lastLink == NULL)
08910             type->memberTypes = link;
08911         else
08912             lastLink->next = link;
08913         lastLink = link;
08914         /*
08915         * Create a reference item.
08916         */
08917         ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
08918             localName, nsName);
08919         if (ref == NULL) {
08920             FREE_AND_NULL(tmp)
08921             return (-1);
08922         }
08923         /*
08924         * Assign the reference to the link, it will be resolved
08925         * later during fixup of the union simple type.
08926         */
08927         link->type = (xmlSchemaTypePtr) ref;
08928         }
08929         FREE_AND_NULL(tmp)
08930         cur = end;
08931     } while (*cur != 0);
08932 
08933     }
08934     /*
08935     * And now for the children...
08936     */
08937     child = node->children;
08938     if (IS_SCHEMA(child, "annotation")) {
08939     /*
08940     * Add the annotation to the simple type ancestor.
08941     */
08942     xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
08943         xmlSchemaParseAnnotation(ctxt, child, 1));
08944         child = child->next;
08945     }
08946     if (IS_SCHEMA(child, "simpleType")) {
08947     xmlSchemaTypePtr subtype, last = NULL;
08948 
08949     /*
08950     * Anchor the member types in the "subtypes" field of the
08951     * simple type.
08952     */
08953     while (IS_SCHEMA(child, "simpleType")) {
08954         subtype = (xmlSchemaTypePtr)
08955         xmlSchemaParseSimpleType(ctxt, schema, child, 0);
08956         if (subtype != NULL) {
08957         if (last == NULL) {
08958             type->subtypes = subtype;
08959             last = subtype;
08960         } else {
08961             last->next = subtype;
08962             last = subtype;
08963         }
08964         last->next = NULL;
08965         }
08966         child = child->next;
08967     }
08968     }
08969     if (child != NULL) {
08970     xmlSchemaPContentErr(ctxt,
08971         XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
08972         NULL, node, child, NULL, "(annotation?, simpleType*)");
08973     }
08974     if ((attr == NULL) && (type->subtypes == NULL)) {
08975      /*
08976     * src-union-memberTypes-or-simpleTypes
08977     * Either the memberTypes [attribute] of the <union> element must
08978     * be non-empty or there must be at least one simpleType [child].
08979     */
08980     xmlSchemaPCustomErr(ctxt,
08981         XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
08982         NULL, node,
08983         "Either the attribute 'memberTypes' or "
08984         "at least one <simpleType> child must be present", NULL);
08985     }
08986     return (0);
08987 }
08988 
09001 static xmlSchemaTypePtr
09002 xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
09003                    xmlNodePtr node)
09004 {
09005     xmlSchemaTypePtr type;
09006     xmlNodePtr child = NULL;
09007     xmlAttrPtr attr;
09008 
09009     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
09010         return (NULL);
09011     /* Not a component, don't create it. */
09012     type = ctxt->ctxtType;
09013     /*
09014     * Mark the type as being of variety "list".
09015     */
09016     type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
09017     /*
09018     * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
09019     * then the �simple ur-type definition�."
09020     */
09021     type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
09022     /*
09023     * Check for illegal attributes.
09024     */
09025     attr = node->properties;
09026     while (attr != NULL) {
09027     if (attr->ns == NULL) {
09028         if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
09029         (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
09030         xmlSchemaPIllegalAttrErr(ctxt,
09031             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
09032         }
09033     } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
09034         xmlSchemaPIllegalAttrErr(ctxt,
09035         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
09036     }
09037     attr = attr->next;
09038     }
09039 
09040     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
09041 
09042     /*
09043     * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
09044     * fields for holding the reference to the itemType.
09045     *
09046     * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
09047     * the "ref" fields.
09048     */
09049     xmlSchemaPValAttrQName(ctxt, schema, NULL,
09050     node, "itemType", &(type->baseNs), &(type->base));
09051     /*
09052     * And now for the children...
09053     */
09054     child = node->children;
09055     if (IS_SCHEMA(child, "annotation")) {
09056     xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
09057         xmlSchemaParseAnnotation(ctxt, child, 1));
09058         child = child->next;
09059     }
09060     if (IS_SCHEMA(child, "simpleType")) {
09061     /*
09062     * src-list-itemType-or-simpleType
09063     * Either the itemType [attribute] or the <simpleType> [child] of
09064     * the <list> element must be present, but not both.
09065     */
09066     if (type->base != NULL) {
09067         xmlSchemaPCustomErr(ctxt,
09068         XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
09069         NULL, node,
09070         "The attribute 'itemType' and the <simpleType> child "
09071         "are mutually exclusive", NULL);
09072     } else {
09073         type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
09074     }
09075         child = child->next;
09076     } else if (type->base == NULL) {
09077     xmlSchemaPCustomErr(ctxt,
09078         XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
09079         NULL, node,
09080         "Either the attribute 'itemType' or the <simpleType> child "
09081         "must be present", NULL);
09082     }
09083     if (child != NULL) {
09084     xmlSchemaPContentErr(ctxt,
09085         XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
09086         NULL, node, child, NULL, "(annotation?, simpleType?)");
09087     }
09088     if ((type->base == NULL) &&
09089     (type->subtypes == NULL) &&
09090     (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
09091     xmlSchemaPCustomErr(ctxt,
09092         XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
09093         NULL, node,
09094         "Either the attribute 'itemType' or the <simpleType> child "
09095         "must be present", NULL);
09096     }
09097     return (NULL);
09098 }
09099 
09112 static xmlSchemaTypePtr
09113 xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
09114                          xmlNodePtr node, int topLevel)
09115 {
09116     xmlSchemaTypePtr type, oldCtxtType;
09117     xmlNodePtr child = NULL;
09118     const xmlChar *attrValue = NULL;
09119     xmlAttrPtr attr;
09120     int hasRestriction = 0;
09121 
09122     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
09123         return (NULL);
09124 
09125     if (topLevel) {
09126     attr = xmlSchemaGetPropNode(node, "name");
09127     if (attr == NULL) {
09128         xmlSchemaPMissingAttrErr(ctxt,
09129         XML_SCHEMAP_S4S_ATTR_MISSING,
09130         NULL, node,
09131         "name", NULL);
09132         return (NULL);
09133     } else {
09134         if (xmlSchemaPValAttrNode(ctxt,
09135         NULL, attr,
09136         xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
09137         return (NULL);
09138         /*
09139         * Skip built-in types.
09140         */
09141         if (ctxt->isS4S) {
09142         xmlSchemaTypePtr biType;
09143 
09144         if (ctxt->isRedefine) {
09145             /*
09146             * REDEFINE: Disallow redefinition of built-in-types.
09147             * TODO: It seems that the spec does not say anything
09148             * about this case.
09149             */
09150             xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
09151             NULL, node,
09152             "Redefinition of built-in simple types is not "
09153             "supported", NULL);
09154             return(NULL);
09155         }
09156         biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
09157         if (biType != NULL)
09158             return (biType);
09159         }
09160     }
09161     }
09162     /*
09163     * TargetNamespace:
09164     * SPEC "The �actual value� of the targetNamespace [attribute]
09165     * of the <schema> ancestor element information item if present,
09166     * otherwise �absent�.
09167     */
09168     if (topLevel == 0) {
09169 #ifdef ENABLE_NAMED_LOCALS
09170         char buf[40];
09171 #endif
09172     /*
09173     * Parse as local simple type definition.
09174     */
09175 #ifdef ENABLE_NAMED_LOCALS
09176         snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
09177     type = xmlSchemaAddType(ctxt, schema,
09178         XML_SCHEMA_TYPE_SIMPLE,
09179         xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
09180         ctxt->targetNamespace, node, 0);
09181 #else
09182     type = xmlSchemaAddType(ctxt, schema,
09183         XML_SCHEMA_TYPE_SIMPLE,
09184         NULL, ctxt->targetNamespace, node, 0);
09185 #endif
09186     if (type == NULL)
09187         return (NULL);
09188     type->type = XML_SCHEMA_TYPE_SIMPLE;
09189     type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
09190     /*
09191     * Check for illegal attributes.
09192     */
09193     attr = node->properties;
09194     while (attr != NULL) {
09195         if (attr->ns == NULL) {
09196         if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
09197             xmlSchemaPIllegalAttrErr(ctxt,
09198             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
09199         }
09200         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
09201             xmlSchemaPIllegalAttrErr(ctxt,
09202             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
09203         }
09204         attr = attr->next;
09205     }
09206     } else {
09207     /*
09208     * Parse as global simple type definition.
09209     *
09210     * Note that attrValue is the value of the attribute "name" here.
09211     */
09212     type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
09213         attrValue, ctxt->targetNamespace, node, 1);
09214     if (type == NULL)
09215         return (NULL);
09216     type->type = XML_SCHEMA_TYPE_SIMPLE;
09217     type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
09218     type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
09219     /*
09220     * Check for illegal attributes.
09221     */
09222     attr = node->properties;
09223     while (attr != NULL) {
09224         if (attr->ns == NULL) {
09225         if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
09226             (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
09227             (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
09228             xmlSchemaPIllegalAttrErr(ctxt,
09229             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
09230         }
09231         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
09232         xmlSchemaPIllegalAttrErr(ctxt,
09233             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
09234         }
09235         attr = attr->next;
09236     }
09237     /*
09238     * Attribute "final".
09239     */
09240     attr = xmlSchemaGetPropNode(node, "final");
09241     if (attr == NULL) {
09242         if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
09243         type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
09244         if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
09245         type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
09246         if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
09247         type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
09248     } else {
09249         attrValue = xmlSchemaGetProp(ctxt, node, "final");
09250         if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
09251         -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
09252         XML_SCHEMAS_TYPE_FINAL_LIST,
09253         XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
09254 
09255         xmlSchemaPSimpleTypeErr(ctxt,
09256             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
09257             WXS_BASIC_CAST type, (xmlNodePtr) attr,
09258             NULL, "(#all | List of (list | union | restriction)",
09259             attrValue, NULL, NULL, NULL);
09260         }
09261     }
09262     }
09263     type->targetNamespace = ctxt->targetNamespace;
09264     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
09265     /*
09266     * And now for the children...
09267     */
09268     oldCtxtType = ctxt->ctxtType;
09269 
09270     ctxt->ctxtType = type;
09271 
09272     child = node->children;
09273     if (IS_SCHEMA(child, "annotation")) {
09274         type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
09275         child = child->next;
09276     }
09277     if (child == NULL) {
09278     xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
09279         NULL, node, child, NULL,
09280         "(annotation?, (restriction | list | union))");
09281     } else if (IS_SCHEMA(child, "restriction")) {
09282         xmlSchemaParseRestriction(ctxt, schema, child,
09283         XML_SCHEMA_TYPE_SIMPLE);
09284     hasRestriction = 1;
09285         child = child->next;
09286     } else if (IS_SCHEMA(child, "list")) {
09287         xmlSchemaParseList(ctxt, schema, child);
09288         child = child->next;
09289     } else if (IS_SCHEMA(child, "union")) {
09290         xmlSchemaParseUnion(ctxt, schema, child);
09291         child = child->next;
09292     }
09293     if (child != NULL) {
09294     xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
09295         NULL, node, child, NULL,
09296         "(annotation?, (restriction | list | union))");
09297     }
09298     /*
09299     * REDEFINE: SPEC src-redefine (5)
09300     * "Within the [children], each <simpleType> must have a
09301     * <restriction> among its [children] ... the �actual value� of whose
09302     * base [attribute] must be the same as the �actual value� of its own
09303     * name attribute plus target namespace;"
09304     */
09305     if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
09306     xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
09307         NULL, node, "This is a redefinition, thus the "
09308         "<simpleType> must have a <restriction> child", NULL);
09309     }
09310 
09311     ctxt->ctxtType = oldCtxtType;
09312     return (type);
09313 }
09314 
09326 static xmlSchemaTreeItemPtr
09327 xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
09328                    xmlSchemaPtr schema,
09329                    xmlNodePtr node)
09330 {
09331     xmlSchemaParticlePtr item;
09332     xmlNodePtr child = NULL;
09333     xmlAttrPtr attr;
09334     const xmlChar *ref = NULL, *refNs = NULL;
09335     int min, max;
09336 
09337     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
09338         return (NULL);
09339 
09340     attr = xmlSchemaGetPropNode(node, "ref");
09341     if (attr == NULL) {
09342     xmlSchemaPMissingAttrErr(ctxt,
09343         XML_SCHEMAP_S4S_ATTR_MISSING,
09344         NULL, node, "ref", NULL);
09345     return (NULL);
09346     } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
09347     attr, &refNs, &ref) != 0) {
09348     return (NULL);
09349     }
09350     xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
09351     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
09352     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
09353     "(xs:nonNegativeInteger | unbounded)");
09354     /*
09355     * Check for illegal attributes.
09356     */
09357     attr = node->properties;
09358     while (attr != NULL) {
09359     if (attr->ns == NULL) {
09360         if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
09361         (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
09362         (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
09363         (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
09364         xmlSchemaPIllegalAttrErr(ctxt,
09365             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
09366         }
09367     } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
09368         xmlSchemaPIllegalAttrErr(ctxt,
09369         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
09370     }
09371     attr = attr->next;
09372     }
09373     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
09374     item = xmlSchemaAddParticle(ctxt, node, min, max);
09375     if (item == NULL)
09376     return (NULL);
09377     /*
09378     * Create a qname-reference and set as the term; it will be substituted
09379     * for the model group after the reference has been resolved.
09380     */
09381     item->children = (xmlSchemaTreeItemPtr)
09382     xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
09383     xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
09384     /*
09385     * And now for the children...
09386     */
09387     child = node->children;
09388     /* TODO: Is annotation even allowed for a model group reference? */
09389     if (IS_SCHEMA(child, "annotation")) {
09390     /*
09391     * TODO: What to do exactly with the annotation?
09392     */
09393     item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
09394     child = child->next;
09395     }
09396     if (child != NULL) {
09397     xmlSchemaPContentErr(ctxt,
09398         XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
09399         NULL, node, child, NULL,
09400         "(annotation?)");
09401     }
09402     /*
09403     * Corresponds to no component at all if minOccurs==maxOccurs==0.
09404     */
09405     if ((min == 0) && (max == 0))
09406     return (NULL);
09407 
09408     return ((xmlSchemaTreeItemPtr) item);
09409 }
09410 
09428 static xmlSchemaModelGroupDefPtr
09429 xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
09430                    xmlSchemaPtr schema,
09431                    xmlNodePtr node)
09432 {
09433     xmlSchemaModelGroupDefPtr item;
09434     xmlNodePtr child = NULL;
09435     xmlAttrPtr attr;
09436     const xmlChar *name;
09437 
09438     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
09439         return (NULL);
09440 
09441     attr = xmlSchemaGetPropNode(node, "name");
09442     if (attr == NULL) {
09443     xmlSchemaPMissingAttrErr(ctxt,
09444         XML_SCHEMAP_S4S_ATTR_MISSING,
09445         NULL, node,
09446         "name", NULL);
09447     return (NULL);
09448     } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
09449     xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
09450     return (NULL);
09451     }
09452     item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
09453     ctxt->targetNamespace, node);
09454     if (item == NULL)
09455     return (NULL);
09456     /*
09457     * Check for illegal attributes.
09458     */
09459     attr = node->properties;
09460     while (attr != NULL) {
09461     if (attr->ns == NULL) {
09462         if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
09463         (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
09464         xmlSchemaPIllegalAttrErr(ctxt,
09465             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
09466         }
09467     } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
09468         xmlSchemaPIllegalAttrErr(ctxt,
09469         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
09470     }
09471     attr = attr->next;
09472     }
09473     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
09474     /*
09475     * And now for the children...
09476     */
09477     child = node->children;
09478     if (IS_SCHEMA(child, "annotation")) {
09479     item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
09480     child = child->next;
09481     }
09482     if (IS_SCHEMA(child, "all")) {
09483     item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
09484         XML_SCHEMA_TYPE_ALL, 0);
09485     child = child->next;
09486     } else if (IS_SCHEMA(child, "choice")) {
09487     item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
09488         XML_SCHEMA_TYPE_CHOICE, 0);
09489     child = child->next;
09490     } else if (IS_SCHEMA(child, "sequence")) {
09491     item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
09492         XML_SCHEMA_TYPE_SEQUENCE, 0);
09493     child = child->next;
09494     }
09495 
09496 
09497 
09498     if (child != NULL) {
09499     xmlSchemaPContentErr(ctxt,
09500         XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
09501         NULL, node, child, NULL,
09502         "(annotation?, (all | choice | sequence)?)");
09503     }
09504     return (item);
09505 }
09506 
09514 static void
09515 xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
09516 {
09517     xmlNodePtr delete, cur;
09518 
09519     if ((ctxt == NULL) || (root == NULL)) return;
09520 
09521     /*
09522      * Remove all the blank text nodes
09523      */
09524     delete = NULL;
09525     cur = root;
09526     while (cur != NULL) {
09527         if (delete != NULL) {
09528             xmlUnlinkNode(delete);
09529             xmlFreeNode(delete);
09530             delete = NULL;
09531         }
09532         if (cur->type == XML_TEXT_NODE) {
09533             if (IS_BLANK_NODE(cur)) {
09534                 if (xmlNodeGetSpacePreserve(cur) != 1) {
09535                     delete = cur;
09536                 }
09537             }
09538         } else if ((cur->type != XML_ELEMENT_NODE) &&
09539                    (cur->type != XML_CDATA_SECTION_NODE)) {
09540             delete = cur;
09541             goto skip_children;
09542         }
09543 
09544         /*
09545          * Skip to next node
09546          */
09547         if (cur->children != NULL) {
09548             if ((cur->children->type != XML_ENTITY_DECL) &&
09549                 (cur->children->type != XML_ENTITY_REF_NODE) &&
09550                 (cur->children->type != XML_ENTITY_NODE)) {
09551                 cur = cur->children;
09552                 continue;
09553             }
09554         }
09555       skip_children:
09556         if (cur->next != NULL) {
09557             cur = cur->next;
09558             continue;
09559         }
09560 
09561         do {
09562             cur = cur->parent;
09563             if (cur == NULL)
09564                 break;
09565             if (cur == root) {
09566                 cur = NULL;
09567                 break;
09568             }
09569             if (cur->next != NULL) {
09570                 cur = cur->next;
09571                 break;
09572             }
09573         } while (cur != NULL);
09574     }
09575     if (delete != NULL) {
09576         xmlUnlinkNode(delete);
09577         xmlFreeNode(delete);
09578         delete = NULL;
09579     }
09580 }
09581 
09582 
09583 static void
09584 xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
09585 {
09586     if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
09587     schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
09588 
09589     if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
09590     schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
09591 
09592     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
09593     schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
09594     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
09595     schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
09596     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
09597     schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
09598     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
09599     schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
09600 
09601     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
09602     schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
09603     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
09604     schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
09605     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
09606     schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
09607 }
09608 
09609 static int
09610 xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
09611                  xmlSchemaPtr schema,
09612                  xmlNodePtr node)
09613 {
09614     xmlAttrPtr attr;
09615     const xmlChar *val;
09616     int res = 0, oldErrs = ctxt->nberrors;
09617 
09618     /*
09619     * Those flags should be moved to the parser context flags,
09620     * since they are not visible at the component level. I.e.
09621     * they are used if processing schema *documents* only.
09622     */
09623     res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
09624     HFAILURE;
09625 
09626     /*
09627     * Since the version is of type xs:token, we won't bother to
09628     * check it.
09629     */
09630     /* REMOVED:
09631     attr = xmlSchemaGetPropNode(node, "version");
09632     if (attr != NULL) {
09633     res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
09634         xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
09635     HFAILURE;
09636     }
09637     */
09638     attr = xmlSchemaGetPropNode(node, "targetNamespace");
09639     if (attr != NULL) {
09640     res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
09641         xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
09642     HFAILURE;
09643     if (res != 0) {
09644         ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
09645         goto exit;
09646     }
09647     }
09648     attr = xmlSchemaGetPropNode(node, "elementFormDefault");
09649     if (attr != NULL) {
09650     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
09651     res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
09652         XML_SCHEMAS_QUALIF_ELEM);
09653     HFAILURE;
09654     if (res != 0) {
09655         xmlSchemaPSimpleTypeErr(ctxt,
09656         XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
09657         NULL, (xmlNodePtr) attr, NULL,
09658         "(qualified | unqualified)", val, NULL, NULL, NULL);
09659     }
09660     }
09661     attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
09662     if (attr != NULL) {
09663     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
09664     res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
09665         XML_SCHEMAS_QUALIF_ATTR);
09666     HFAILURE;
09667     if (res != 0) {
09668         xmlSchemaPSimpleTypeErr(ctxt,
09669         XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
09670         NULL, (xmlNodePtr) attr, NULL,
09671         "(qualified | unqualified)", val, NULL, NULL, NULL);
09672     }
09673     }
09674     attr = xmlSchemaGetPropNode(node, "finalDefault");
09675     if (attr != NULL) {
09676     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
09677     res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
09678         XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
09679         XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
09680         -1,
09681         XML_SCHEMAS_FINAL_DEFAULT_LIST,
09682         XML_SCHEMAS_FINAL_DEFAULT_UNION);
09683     HFAILURE;
09684     if (res != 0) {
09685         xmlSchemaPSimpleTypeErr(ctxt,
09686         XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
09687         NULL, (xmlNodePtr) attr, NULL,
09688         "(#all | List of (extension | restriction | list | union))",
09689         val, NULL, NULL, NULL);
09690     }
09691     }
09692     attr = xmlSchemaGetPropNode(node, "blockDefault");
09693     if (attr != NULL) {
09694     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
09695     res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
09696         XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
09697         XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
09698         XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
09699     HFAILURE;
09700     if (res != 0) {
09701         xmlSchemaPSimpleTypeErr(ctxt,
09702         XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
09703         NULL, (xmlNodePtr) attr, NULL,
09704         "(#all | List of (extension | restriction | substitution))",
09705         val, NULL, NULL, NULL);
09706     }
09707     }
09708 
09709 exit:
09710     if (oldErrs != ctxt->nberrors)
09711     res = ctxt->err;
09712     return(res);
09713 exit_failure:
09714     return(-1);
09715 }
09716 
09726 static int
09727 xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
09728                              xmlSchemaPtr schema, xmlNodePtr nodes)
09729 {
09730     xmlNodePtr child;
09731     xmlSchemaAnnotPtr annot;
09732     int res = 0, oldErrs, tmpOldErrs;
09733 
09734     if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
09735         return(-1);
09736 
09737     oldErrs = ctxt->nberrors;
09738     child = nodes;
09739     while ((IS_SCHEMA(child, "include")) ||
09740        (IS_SCHEMA(child, "import")) ||
09741        (IS_SCHEMA(child, "redefine")) ||
09742        (IS_SCHEMA(child, "annotation"))) {
09743     if (IS_SCHEMA(child, "annotation")) {
09744         annot = xmlSchemaParseAnnotation(ctxt, child, 1);
09745         if (schema->annot == NULL)
09746         schema->annot = annot;
09747         else
09748         xmlSchemaFreeAnnot(annot);
09749     } else if (IS_SCHEMA(child, "import")) {
09750         tmpOldErrs = ctxt->nberrors;
09751         res = xmlSchemaParseImport(ctxt, schema, child);
09752         HFAILURE;
09753         HSTOP(ctxt);
09754         if (tmpOldErrs != ctxt->nberrors)
09755         goto exit;
09756     } else if (IS_SCHEMA(child, "include")) {
09757         tmpOldErrs = ctxt->nberrors;
09758         res = xmlSchemaParseInclude(ctxt, schema, child);
09759         HFAILURE;
09760         HSTOP(ctxt);
09761         if (tmpOldErrs != ctxt->nberrors)
09762         goto exit;
09763     } else if (IS_SCHEMA(child, "redefine")) {
09764         tmpOldErrs = ctxt->nberrors;
09765         res = xmlSchemaParseRedefine(ctxt, schema, child);
09766         HFAILURE;
09767         HSTOP(ctxt);
09768         if (tmpOldErrs != ctxt->nberrors)
09769         goto exit;
09770     }
09771     child = child->next;
09772     }
09773     /*
09774     * URGENT TODO: Change the functions to return int results.
09775     * We need especially to catch internal errors.
09776     */
09777     while (child != NULL) {
09778     if (IS_SCHEMA(child, "complexType")) {
09779         xmlSchemaParseComplexType(ctxt, schema, child, 1);
09780         child = child->next;
09781     } else if (IS_SCHEMA(child, "simpleType")) {
09782         xmlSchemaParseSimpleType(ctxt, schema, child, 1);
09783         child = child->next;
09784     } else if (IS_SCHEMA(child, "element")) {
09785         xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
09786         child = child->next;
09787     } else if (IS_SCHEMA(child, "attribute")) {
09788         xmlSchemaParseGlobalAttribute(ctxt, schema, child);
09789         child = child->next;
09790     } else if (IS_SCHEMA(child, "attributeGroup")) {
09791         xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
09792         child = child->next;
09793     } else if (IS_SCHEMA(child, "group")) {
09794         xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
09795         child = child->next;
09796     } else if (IS_SCHEMA(child, "notation")) {
09797         xmlSchemaParseNotation(ctxt, schema, child);
09798         child = child->next;
09799     } else {
09800         xmlSchemaPContentErr(ctxt,
09801         XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
09802         NULL, child->parent, child,
09803         NULL, "((include | import | redefine | annotation)*, "
09804         "(((simpleType | complexType | group | attributeGroup) "
09805         "| element | attribute | notation), annotation*)*)");
09806         child = child->next;
09807     }
09808     while (IS_SCHEMA(child, "annotation")) {
09809         /*
09810         * TODO: We should add all annotations.
09811         */
09812         annot = xmlSchemaParseAnnotation(ctxt, child, 1);
09813         if (schema->annot == NULL)
09814         schema->annot = annot;
09815         else
09816         xmlSchemaFreeAnnot(annot);
09817         child = child->next;
09818     }
09819     }
09820 exit:
09821     ctxt->ctxtType = NULL;
09822     if (oldErrs != ctxt->nberrors)
09823     res = ctxt->err;
09824     return(res);
09825 exit_failure:
09826     return(-1);
09827 }
09828 
09829 static xmlSchemaSchemaRelationPtr
09830 xmlSchemaSchemaRelationCreate(void)
09831 {
09832     xmlSchemaSchemaRelationPtr ret;
09833 
09834     ret = (xmlSchemaSchemaRelationPtr)
09835     xmlMalloc(sizeof(xmlSchemaSchemaRelation));
09836     if (ret == NULL) {
09837     xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
09838     return(NULL);
09839     }
09840     memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
09841     return(ret);
09842 }
09843 
09844 #if 0
09845 static void
09846 xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
09847 {
09848     xmlFree(rel);
09849 }
09850 #endif
09851 
09852 static void
09853 xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
09854 {
09855     xmlSchemaRedefPtr prev;
09856 
09857     while (redef != NULL) {
09858     prev = redef;
09859     redef = redef->next;
09860     xmlFree(prev);
09861     }
09862 }
09863 
09864 static void
09865 xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
09866 {
09867     /*
09868     * After the construction context has been freed, there will be
09869     * no schema graph available any more. Only the schema buckets
09870     * will stay alive, which are put into the "schemasImports" and
09871     * "includes" slots of the xmlSchema.
09872     */
09873     if (con->buckets != NULL)
09874     xmlSchemaItemListFree(con->buckets);
09875     if (con->pending != NULL)
09876     xmlSchemaItemListFree(con->pending);
09877     if (con->substGroups != NULL)
09878     xmlHashFree(con->substGroups,
09879         (xmlHashDeallocator) xmlSchemaSubstGroupFree);
09880     if (con->redefs != NULL)
09881     xmlSchemaRedefListFree(con->redefs);
09882     if (con->dict != NULL)
09883     xmlDictFree(con->dict);
09884     xmlFree(con);
09885 }
09886 
09887 static xmlSchemaConstructionCtxtPtr
09888 xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
09889 {
09890     xmlSchemaConstructionCtxtPtr ret;
09891 
09892     ret = (xmlSchemaConstructionCtxtPtr)
09893     xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
09894     if (ret == NULL) {
09895         xmlSchemaPErrMemory(NULL,
09896         "allocating schema construction context", NULL);
09897         return (NULL);
09898     }
09899     memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
09900 
09901     ret->buckets = xmlSchemaItemListCreate();
09902     if (ret->buckets == NULL) {
09903     xmlSchemaPErrMemory(NULL,
09904         "allocating list of schema buckets", NULL);
09905     xmlFree(ret);
09906         return (NULL);
09907     }
09908     ret->pending = xmlSchemaItemListCreate();
09909     if (ret->pending == NULL) {
09910     xmlSchemaPErrMemory(NULL,
09911         "allocating list of pending global components", NULL);
09912     xmlSchemaConstructionCtxtFree(ret);
09913         return (NULL);
09914     }
09915     ret->dict = dict;
09916     xmlDictReference(dict);
09917     return(ret);
09918 }
09919 
09920 static xmlSchemaParserCtxtPtr
09921 xmlSchemaParserCtxtCreate(void)
09922 {
09923     xmlSchemaParserCtxtPtr ret;
09924 
09925     ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
09926     if (ret == NULL) {
09927         xmlSchemaPErrMemory(NULL, "allocating schema parser context",
09928                             NULL);
09929         return (NULL);
09930     }
09931     memset(ret, 0, sizeof(xmlSchemaParserCtxt));
09932     ret->type = XML_SCHEMA_CTXT_PARSER;
09933     ret->attrProhibs = xmlSchemaItemListCreate();
09934     if (ret->attrProhibs == NULL) {
09935     xmlFree(ret);
09936     return(NULL);
09937     }
09938     return(ret);
09939 }
09940 
09951 static xmlSchemaParserCtxtPtr
09952 xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
09953 {
09954     xmlSchemaParserCtxtPtr ret;
09955 
09956     ret = xmlSchemaParserCtxtCreate();
09957     if (ret == NULL)
09958         return (NULL);
09959     ret->dict = dict;
09960     xmlDictReference(dict);
09961     if (URL != NULL)
09962     ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
09963     return (ret);
09964 }
09965 
09966 static int
09967 xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
09968 {
09969     if (vctxt->pctxt == NULL) {
09970         if (vctxt->schema != NULL)
09971         vctxt->pctxt =
09972         xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
09973     else
09974         vctxt->pctxt = xmlSchemaNewParserCtxt("*");
09975     if (vctxt->pctxt == NULL) {
09976         VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
09977         "failed to create a temp. parser context");
09978         return (-1);
09979     }
09980     /* TODO: Pass user data. */
09981     xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
09982         vctxt->warning, vctxt->errCtxt);
09983     xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
09984         vctxt->errCtxt);
09985     }
09986     return (0);
09987 }
09988 
09999 static xmlSchemaBucketPtr
10000 xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10001                 const xmlChar *schemaLocation)
10002 {
10003     xmlSchemaBucketPtr cur;
10004     xmlSchemaItemListPtr list;
10005 
10006     list = pctxt->constructor->buckets;
10007     if (list->nbItems == 0)
10008     return(NULL);
10009     else {
10010     int i;
10011     for (i = 0; i < list->nbItems; i++) {
10012         cur = (xmlSchemaBucketPtr) list->items[i];
10013         /* Pointer comparison! */
10014         if (cur->schemaLocation == schemaLocation)
10015         return(cur);
10016     }
10017     }
10018     return(NULL);
10019 }
10020 
10021 static xmlSchemaBucketPtr
10022 xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10023                      const xmlChar *schemaLocation,
10024                      const xmlChar *targetNamespace)
10025 {
10026     xmlSchemaBucketPtr cur;
10027     xmlSchemaItemListPtr list;
10028 
10029     list = pctxt->constructor->buckets;
10030     if (list->nbItems == 0)
10031     return(NULL);
10032     else {
10033     int i;
10034     for (i = 0; i < list->nbItems; i++) {
10035         cur = (xmlSchemaBucketPtr) list->items[i];
10036         /* Pointer comparison! */
10037         if ((cur->origTargetNamespace == NULL) &&
10038         (cur->schemaLocation == schemaLocation) &&
10039         (cur->targetNamespace == targetNamespace))
10040         return(cur);
10041     }
10042     }
10043     return(NULL);
10044 }
10045 
10046 
10047 #define IS_BAD_SCHEMA_DOC(b) \
10048     (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10049 
10050 static xmlSchemaBucketPtr
10051 xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10052                  const xmlChar *targetNamespace,
10053                  int imported)
10054 {
10055     xmlSchemaBucketPtr cur;
10056     xmlSchemaItemListPtr list;
10057 
10058     list = pctxt->constructor->buckets;
10059     if (list->nbItems == 0)
10060     return(NULL);
10061     else {
10062     int i;
10063     for (i = 0; i < list->nbItems; i++) {
10064         cur = (xmlSchemaBucketPtr) list->items[i];
10065         if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10066         (cur->origTargetNamespace == targetNamespace) &&
10067         ((imported && cur->imported) ||
10068          ((!imported) && (!cur->imported))))
10069         return(cur);
10070     }
10071     }
10072     return(NULL);
10073 }
10074 
10075 static int
10076 xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10077              xmlSchemaPtr schema,
10078              xmlSchemaBucketPtr bucket)
10079 {
10080     int oldFlags;
10081     xmlDocPtr oldDoc;
10082     xmlNodePtr node;
10083     int ret, oldErrs;
10084     xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10085 
10086     /*
10087     * Save old values; reset the *main* schema.
10088     * URGENT TODO: This is not good; move the per-document information
10089     * to the parser. Get rid of passing the main schema to the
10090     * parsing functions.
10091     */
10092     oldFlags = schema->flags;
10093     oldDoc = schema->doc;
10094     if (schema->flags != 0)
10095     xmlSchemaClearSchemaDefaults(schema);
10096     schema->doc = bucket->doc;
10097     pctxt->schema = schema;
10098     /*
10099     * Keep the current target namespace on the parser *not* on the
10100     * main schema.
10101     */
10102     pctxt->targetNamespace = bucket->targetNamespace;
10103     WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
10104 
10105     if ((bucket->targetNamespace != NULL) &&
10106     xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
10107     /*
10108     * We are parsing the schema for schemas!
10109     */
10110     pctxt->isS4S = 1;
10111     }
10112     /* Mark it as parsed, even if parsing fails. */
10113     bucket->parsed++;
10114     /* Compile the schema doc. */
10115     node = xmlDocGetRootElement(bucket->doc);
10116     ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10117     if (ret != 0)
10118     goto exit;
10119     /* An empty schema; just get out. */
10120     if (node->children == NULL)
10121     goto exit;
10122     oldErrs = pctxt->nberrors;
10123     ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10124     if (ret != 0)
10125     goto exit;
10126     /*
10127     * TODO: Not nice, but I'm not 100% sure we will get always an error
10128     * as a result of the obove functions; so better rely on pctxt->err
10129     * as well.
10130     */
10131     if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10132     ret = pctxt->err;
10133     goto exit;
10134     }
10135 
10136 exit:
10137     WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10138     /* Restore schema values. */
10139     schema->doc = oldDoc;
10140     schema->flags = oldFlags;
10141     return(ret);
10142 }
10143 
10144 static int
10145 xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10146              xmlSchemaPtr schema,
10147              xmlSchemaBucketPtr bucket)
10148 {
10149     xmlSchemaParserCtxtPtr newpctxt;
10150     int res = 0;
10151 
10152     if (bucket == NULL)
10153     return(0);
10154     if (bucket->parsed) {
10155     PERROR_INT("xmlSchemaParseNewDoc",
10156         "reparsing a schema doc");
10157     return(-1);
10158     }
10159     if (bucket->doc == NULL) {
10160     PERROR_INT("xmlSchemaParseNewDoc",
10161         "parsing a schema doc, but there's no doc");
10162     return(-1);
10163     }
10164     if (pctxt->constructor == NULL) {
10165     PERROR_INT("xmlSchemaParseNewDoc",
10166         "no constructor");
10167     return(-1);
10168     }
10169     /* Create and init the temporary parser context. */
10170     newpctxt = xmlSchemaNewParserCtxtUseDict(
10171     (const char *) bucket->schemaLocation, pctxt->dict);
10172     if (newpctxt == NULL)
10173     return(-1);
10174     newpctxt->constructor = pctxt->constructor;
10175     /*
10176     * TODO: Can we avoid that the parser knows about the main schema?
10177     * It would be better if he knows about the current schema bucket
10178     * only.
10179     */
10180     newpctxt->schema = schema;
10181     xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
10182     pctxt->errCtxt);
10183     xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10184     pctxt->errCtxt);
10185     newpctxt->counter = pctxt->counter;
10186 
10187 
10188     res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10189 
10190     /* Channel back errors and cleanup the temporary parser context. */
10191     if (res != 0)
10192     pctxt->err = res;
10193     pctxt->nberrors += newpctxt->nberrors;
10194     pctxt->counter = newpctxt->counter;
10195     newpctxt->constructor = NULL;
10196     /* Free the parser context. */
10197     xmlSchemaFreeParserCtxt(newpctxt);
10198     return(res);
10199 }
10200 
10201 static void
10202 xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10203                 xmlSchemaSchemaRelationPtr rel)
10204 {
10205     xmlSchemaSchemaRelationPtr cur = bucket->relations;
10206 
10207     if (cur == NULL) {
10208     bucket->relations = rel;
10209     return;
10210     }
10211     while (cur->next != NULL)
10212     cur = cur->next;
10213     cur->next = rel;
10214 }
10215 
10216 
10217 static const xmlChar *
10218 xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10219               xmlNodePtr ctxtNode)
10220 {
10221     /*
10222     * Build an absolue location URI.
10223     */
10224     if (location != NULL) {
10225     if (ctxtNode == NULL)
10226         return(location);
10227     else {
10228         xmlChar *base, *URI;
10229         const xmlChar *ret = NULL;
10230 
10231         base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10232         if (base == NULL) {
10233         URI = xmlBuildURI(location, ctxtNode->doc->URL);
10234         } else {
10235         URI = xmlBuildURI(location, base);
10236         xmlFree(base);
10237         }
10238         if (URI != NULL) {
10239         ret = xmlDictLookup(dict, URI, -1);
10240         xmlFree(URI);
10241         return(ret);
10242         }
10243     }
10244     }
10245     return(NULL);
10246 }
10247 
10248 
10249 
10262 static int
10263 xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10264         int type, /* import or include or redefine */
10265         const xmlChar *schemaLocation,
10266         xmlDocPtr schemaDoc,
10267         const char *schemaBuffer,
10268         int schemaBufferLen,
10269         xmlNodePtr invokingNode,
10270         const xmlChar *sourceTargetNamespace,
10271         const xmlChar *importNamespace,
10272         xmlSchemaBucketPtr *bucket)
10273 {
10274     const xmlChar *targetNamespace = NULL;
10275     xmlSchemaSchemaRelationPtr relation = NULL;
10276     xmlDocPtr doc = NULL;
10277     int res = 0, err = 0, located = 0, preserveDoc = 0;
10278     xmlSchemaBucketPtr bkt = NULL;
10279 
10280     if (bucket != NULL)
10281     *bucket = NULL;
10282 
10283     switch (type) {
10284     case XML_SCHEMA_SCHEMA_IMPORT:
10285     case XML_SCHEMA_SCHEMA_MAIN:
10286         err = XML_SCHEMAP_SRC_IMPORT;
10287         break;
10288     case XML_SCHEMA_SCHEMA_INCLUDE:
10289         err = XML_SCHEMAP_SRC_INCLUDE;
10290         break;
10291     case XML_SCHEMA_SCHEMA_REDEFINE:
10292         err = XML_SCHEMAP_SRC_REDEFINE;
10293         break;
10294     }
10295 
10296 
10297     /* Special handling for the main schema:
10298     * skip the location and relation logic and just parse the doc.
10299     * We need just a bucket to be returned in this case.
10300     */
10301     if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10302     goto doc_load;
10303 
10304     /* Note that we expect the location to be an absulute URI. */
10305     if (schemaLocation != NULL) {
10306     bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10307     if ((bkt != NULL) &&
10308         (pctxt->constructor->bucket == bkt)) {
10309         /* Report self-imports/inclusions/redefinitions. */
10310 
10311         xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10312         invokingNode, NULL,
10313         "The schema must not import/include/redefine itself",
10314         NULL, NULL);
10315         goto exit;
10316     }
10317     }
10318     /*
10319     * Create a relation for the graph of schemas.
10320     */
10321     relation = xmlSchemaSchemaRelationCreate();
10322     if (relation == NULL)
10323     return(-1);
10324     xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10325     relation);
10326     relation->type = type;
10327 
10328     /*
10329     * Save the namespace import information.
10330     */
10331     if (WXS_IS_BUCKET_IMPMAIN(type)) {
10332     relation->importNamespace = importNamespace;
10333     if (schemaLocation == NULL) {
10334         /*
10335         * No location; this is just an import of the namespace.
10336         * Note that we don't assign a bucket to the relation
10337         * in this case.
10338         */
10339         goto exit;
10340     }
10341     targetNamespace = importNamespace;
10342     }
10343 
10344     /* Did we already fetch the doc? */
10345     if (bkt != NULL) {
10346     if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
10347         /*
10348         * We included/redefined and then try to import a schema,
10349         * but the new location provided for import was different.
10350         */
10351         if (schemaLocation == NULL)
10352         schemaLocation = BAD_CAST "in_memory_buffer";
10353         if (!xmlStrEqual(schemaLocation,
10354         bkt->schemaLocation)) {
10355         xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10356             invokingNode, NULL,
10357             "The schema document '%s' cannot be imported, since "
10358             "it was already included or redefined",
10359             schemaLocation, NULL);
10360         goto exit;
10361         }
10362     } else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
10363         /*
10364         * We imported and then try to include/redefine a schema,
10365         * but the new location provided for the include/redefine
10366         * was different.
10367         */
10368         if (schemaLocation == NULL)
10369         schemaLocation = BAD_CAST "in_memory_buffer";
10370         if (!xmlStrEqual(schemaLocation,
10371         bkt->schemaLocation)) {
10372         xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10373             invokingNode, NULL,
10374             "The schema document '%s' cannot be included or "
10375             "redefined, since it was already imported",
10376             schemaLocation, NULL);
10377         goto exit;
10378         }
10379     }
10380     }
10381 
10382     if (WXS_IS_BUCKET_IMPMAIN(type)) {
10383     /*
10384     * Given that the schemaLocation [attribute] is only a hint, it is open
10385     * to applications to ignore all but the first <import> for a given
10386     * namespace, regardless of the �actual value� of schemaLocation, but
10387     * such a strategy risks missing useful information when new
10388     * schemaLocations are offered.
10389     *
10390     * We will use the first <import> that comes with a location.
10391     * Further <import>s *with* a location, will result in an error.
10392     * TODO: Better would be to just report a warning here, but
10393     * we'll try it this way until someone complains.
10394     *
10395     * Schema Document Location Strategy:
10396     * 3 Based on the namespace name, identify an existing schema document,
10397     * either as a resource which is an XML document or a <schema> element
10398     * information item, in some local schema repository;
10399     * 5 Attempt to resolve the namespace name to locate such a resource.
10400     *
10401     * NOTE: (3) and (5) are not supported.
10402     */
10403     if (bkt != NULL) {
10404         relation->bucket = bkt;
10405         goto exit;
10406     }
10407     bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10408         importNamespace, 1);
10409 
10410     if (bkt != NULL) {
10411         relation->bucket = bkt;
10412         if (bkt->schemaLocation == NULL) {
10413         /* First given location of the schema; load the doc. */
10414         bkt->schemaLocation = schemaLocation;
10415         } else {
10416         if (!xmlStrEqual(schemaLocation,
10417             bkt->schemaLocation)) {
10418             /*
10419             * Additional location given; just skip it.
10420             * URGENT TODO: We should report a warning here.
10421             * res = XML_SCHEMAP_SRC_IMPORT;
10422             */
10423             if (schemaLocation == NULL)
10424             schemaLocation = BAD_CAST "in_memory_buffer";
10425 
10426             xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10427             XML_SCHEMAP_WARN_SKIP_SCHEMA,
10428             invokingNode, NULL,
10429             "Skipping import of schema located at '%s' for the "
10430             "namespace '%s', since this namespace was already "
10431             "imported with the schema located at '%s'",
10432             schemaLocation, importNamespace, bkt->schemaLocation);
10433         }
10434         goto exit;
10435         }
10436     }
10437     /*
10438     * No bucket + first location: load the doc and create a
10439     * bucket.
10440     */
10441     } else {
10442     /* <include> and <redefine> */
10443     if (bkt != NULL) {
10444 
10445         if ((bkt->origTargetNamespace == NULL) &&
10446         (bkt->targetNamespace != sourceTargetNamespace)) {
10447         xmlSchemaBucketPtr chamel;
10448 
10449         /*
10450         * Chameleon include/redefine: skip loading only if it was
10451         * aleady build for the targetNamespace of the including
10452         * schema.
10453         */
10454         /*
10455         * URGENT TODO: If the schema is a chameleon-include then copy
10456         * the components into the including schema and modify the
10457         * targetNamespace of those components, do nothing otherwise.
10458         * NOTE: This is currently worked-around by compiling the
10459         * chameleon for every destinct including targetNamespace; thus
10460         * not performant at the moment.
10461         * TODO: Check when the namespace in wildcards for chameleons
10462         * needs to be converted: before we built wildcard intersections
10463         * or after.
10464         *   Answer: after!
10465         */
10466         chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10467             schemaLocation, sourceTargetNamespace);
10468         if (chamel != NULL) {
10469             /* A fitting chameleon was already parsed; NOP. */
10470             relation->bucket = chamel;
10471             goto exit;
10472         }
10473         /*
10474         * We need to parse the chameleon again for a different
10475         * targetNamespace.
10476         * CHAMELEON TODO: Optimize this by only parsing the
10477         * chameleon once, and then copying the components to
10478         * the new targetNamespace.
10479         */
10480         bkt = NULL;
10481         } else {
10482         relation->bucket = bkt;
10483         goto exit;
10484         }
10485     }
10486     }
10487     if ((bkt != NULL) && (bkt->doc != NULL)) {
10488     PERROR_INT("xmlSchemaAddSchemaDoc",
10489         "trying to load a schema doc, but a doc is already "
10490         "assigned to the schema bucket");
10491     goto exit_failure;
10492     }
10493 
10494 doc_load:
10495     /*
10496     * Load the document.
10497     */
10498     if (schemaDoc != NULL) {
10499     doc = schemaDoc;
10500     /* Don' free this one, since it was provided by the caller. */
10501     preserveDoc = 1;
10502     /* TODO: Does the context or the doc hold the location? */
10503     if (schemaDoc->URL != NULL)
10504         schemaLocation = xmlDictLookup(pctxt->dict,
10505         schemaDoc->URL, -1);
10506         else
10507         schemaLocation = BAD_CAST "in_memory_buffer";
10508     } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10509     xmlParserCtxtPtr parserCtxt;
10510 
10511     parserCtxt = xmlNewParserCtxt();
10512     if (parserCtxt == NULL) {
10513         xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10514         "allocating a parser context", NULL);
10515         goto exit_failure;
10516     }
10517     if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10518         /*
10519         * TODO: Do we have to burden the schema parser dict with all
10520         * the content of the schema doc?
10521         */
10522         xmlDictFree(parserCtxt->dict);
10523         parserCtxt->dict = pctxt->dict;
10524         xmlDictReference(parserCtxt->dict);
10525     }
10526     if (schemaLocation != NULL) {
10527         /* Parse from file. */
10528         doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10529         NULL, SCHEMAS_PARSE_OPTIONS);
10530     } else if (schemaBuffer != NULL) {
10531         /* Parse from memory buffer. */
10532         doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10533         NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10534         schemaLocation = BAD_CAST "in_memory_buffer";
10535         if (doc != NULL)
10536         doc->URL = xmlStrdup(schemaLocation);
10537     }
10538     /*
10539     * For <import>:
10540     * 2.1 The referent is (a fragment of) a resource which is an
10541     * XML document (see clause 1.1), which in turn corresponds to
10542     * a <schema> element information item in a well-formed information
10543     * set, which in turn corresponds to a valid schema.
10544     * TODO: (2.1) fragments of XML documents are not supported.
10545     *
10546     * 2.2 The referent is a <schema> element information item in
10547     * a well-formed information set, which in turn corresponds
10548     * to a valid schema.
10549     * TODO: (2.2) is not supported.
10550     */
10551     if (doc == NULL) {
10552         xmlErrorPtr lerr;
10553         lerr = xmlGetLastError();
10554         /*
10555         * Check if this a parser error, or if the document could
10556         * just not be located.
10557         * TODO: Try to find specific error codes to react only on
10558         * localisation failures.
10559         */
10560         if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10561         /*
10562         * We assume a parser error here.
10563         */
10564         located = 1;
10565         /* TODO: Error code ?? */
10566         res = XML_SCHEMAP_SRC_IMPORT_2_1;
10567         xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10568             invokingNode, NULL,
10569             "Failed to parse the XML resource '%s'",
10570             schemaLocation, NULL);
10571         }
10572     }
10573     xmlFreeParserCtxt(parserCtxt);
10574     if ((doc == NULL) && located)
10575         goto exit_error;
10576     } else {
10577     xmlSchemaPErr(pctxt, NULL,
10578         XML_SCHEMAP_NOTHING_TO_PARSE,
10579         "No information for parsing was provided with the "
10580         "given schema parser context.\n",
10581         NULL, NULL);
10582     goto exit_failure;
10583     }
10584     /*
10585     * Preprocess the document.
10586     */
10587     if (doc != NULL) {
10588     xmlNodePtr docElem = NULL;
10589 
10590     located = 1;
10591     docElem = xmlDocGetRootElement(doc);
10592     if (docElem == NULL) {
10593         xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10594         invokingNode, NULL,
10595         "The document '%s' has no document element",
10596         schemaLocation, NULL);
10597         goto exit_error;
10598     }
10599     /*
10600     * Remove all the blank text nodes.
10601     */
10602     xmlSchemaCleanupDoc(pctxt, docElem);
10603     /*
10604     * Check the schema's top level element.
10605     */
10606     if (!IS_SCHEMA(docElem, "schema")) {
10607         xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10608         invokingNode, NULL,
10609         "The XML document '%s' is not a schema document",
10610         schemaLocation, NULL);
10611         goto exit_error;
10612     }
10613     /*
10614     * Note that we don't apply a type check for the
10615     * targetNamespace value here.
10616     */
10617     targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10618         "targetNamespace");
10619     }
10620 
10621 /* after_doc_loading: */
10622     if ((bkt == NULL) && located) {
10623     /* Only create a bucket if the schema was located. */
10624         bkt = xmlSchemaBucketCreate(pctxt, type,
10625         targetNamespace);
10626     if (bkt == NULL)
10627         goto exit_failure;
10628     }
10629     if (bkt != NULL) {
10630     bkt->schemaLocation = schemaLocation;
10631     bkt->located = located;
10632     if (doc != NULL) {
10633         bkt->doc = doc;
10634         bkt->targetNamespace = targetNamespace;
10635         bkt->origTargetNamespace = targetNamespace;
10636         if (preserveDoc)
10637         bkt->preserveDoc = 1;
10638     }
10639     if (WXS_IS_BUCKET_IMPMAIN(type))
10640         bkt->imported++;
10641         /*
10642         * Add it to the graph of schemas.
10643         */
10644     if (relation != NULL)
10645         relation->bucket = bkt;
10646     }
10647 
10648 exit:
10649     /*
10650     * Return the bucket explicitely; this is needed for the
10651     * main schema.
10652     */
10653     if (bucket != NULL)
10654     *bucket = bkt;
10655     return (0);
10656 
10657 exit_error:
10658     if ((doc != NULL) && (! preserveDoc)) {
10659     xmlFreeDoc(doc);
10660     if (bkt != NULL)
10661         bkt->doc = NULL;
10662     }
10663     return(pctxt->err);
10664 
10665 exit_failure:
10666     if ((doc != NULL) && (! preserveDoc)) {
10667     xmlFreeDoc(doc);
10668     if (bkt != NULL)
10669         bkt->doc = NULL;
10670     }
10671     return (-1);
10672 }
10673 
10686 static int
10687 xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
10688                      xmlNodePtr node)
10689 {
10690     xmlNodePtr child;
10691     const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10692     const xmlChar *thisTargetNamespace;
10693     xmlAttrPtr attr;
10694     int ret = 0;
10695     xmlSchemaBucketPtr bucket = NULL;
10696 
10697     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10698         return (-1);
10699 
10700     /*
10701     * Check for illegal attributes.
10702     */
10703     attr = node->properties;
10704     while (attr != NULL) {
10705     if (attr->ns == NULL) {
10706         if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10707         (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10708         (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10709         xmlSchemaPIllegalAttrErr(pctxt,
10710             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10711         }
10712     } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10713         xmlSchemaPIllegalAttrErr(pctxt,
10714         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10715     }
10716     attr = attr->next;
10717     }
10718     /*
10719     * Extract and validate attributes.
10720     */
10721     if (xmlSchemaPValAttr(pctxt, NULL, node,
10722     "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10723     &namespaceName) != 0) {
10724     xmlSchemaPSimpleTypeErr(pctxt,
10725         XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10726         NULL, node,
10727         xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10728         NULL, namespaceName, NULL, NULL, NULL);
10729     return (pctxt->err);
10730     }
10731 
10732     if (xmlSchemaPValAttr(pctxt, NULL, node,
10733     "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10734     &schemaLocation) != 0) {
10735     xmlSchemaPSimpleTypeErr(pctxt,
10736         XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10737         NULL, node,
10738         xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10739         NULL, namespaceName, NULL, NULL, NULL);
10740     return (pctxt->err);
10741     }
10742     /*
10743     * And now for the children...
10744     */
10745     child = node->children;
10746     if (IS_SCHEMA(child, "annotation")) {
10747         /*
10748          * the annotation here is simply discarded ...
10749      * TODO: really?
10750          */
10751         child = child->next;
10752     }
10753     if (child != NULL) {
10754     xmlSchemaPContentErr(pctxt,
10755         XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10756         NULL, node, child, NULL,
10757         "(annotation?)");
10758     }
10759     /*
10760     * Apply additional constraints.
10761     *
10762     * Note that it is important to use the original @targetNamespace
10763     * (or none at all), to rule out imports of schemas _with_ a
10764     * @targetNamespace if the importing schema is a chameleon schema
10765     * (with no @targetNamespace).
10766     */
10767     thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
10768     if (namespaceName != NULL) {
10769     /*
10770     * 1.1 If the namespace [attribute] is present, then its �actual value�
10771     * must not match the �actual value� of the enclosing <schema>'s
10772     * targetNamespace [attribute].
10773     */
10774     if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
10775         xmlSchemaPCustomErr(pctxt,
10776         XML_SCHEMAP_SRC_IMPORT_1_1,
10777         NULL, node,
10778         "The value of the attribute 'namespace' must not match "
10779         "the target namespace '%s' of the importing schema",
10780         thisTargetNamespace);
10781         return (pctxt->err);
10782     }
10783     } else {
10784     /*
10785     * 1.2 If the namespace [attribute] is not present, then the enclosing
10786     * <schema> must have a targetNamespace [attribute].
10787     */
10788     if (thisTargetNamespace == NULL) {
10789         xmlSchemaPCustomErr(pctxt,
10790         XML_SCHEMAP_SRC_IMPORT_1_2,
10791         NULL, node,
10792         "The attribute 'namespace' must be existent if "
10793         "the importing schema has no target namespace",
10794         NULL);
10795         return (pctxt->err);
10796     }
10797     }
10798     /*
10799     * Locate and acquire the schema document.
10800     */
10801     if (schemaLocation != NULL)
10802     schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10803         schemaLocation, node);
10804     ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
10805     schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
10806     namespaceName, &bucket);
10807 
10808     if (ret != 0)
10809     return(ret);
10810 
10811     /*
10812     * For <import>: "It is *not* an error for the application
10813     * schema reference strategy to fail."
10814     * So just don't parse if no schema document was found.
10815     * Note that we will get no bucket if the schema could not be
10816     * located or if there was no schemaLocation.
10817     */
10818     if ((bucket == NULL) && (schemaLocation != NULL)) {
10819     xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10820         XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10821         node, NULL,
10822         "Failed to locate a schema at location '%s'. "
10823         "Skipping the import", schemaLocation, NULL, NULL);
10824     }
10825 
10826     if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10827     ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10828     }
10829 
10830     return (ret);
10831 }
10832 
10833 static int
10834 xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10835                      xmlSchemaPtr schema,
10836                      xmlNodePtr node,
10837                      xmlChar **schemaLocation,
10838                      int type)
10839 {
10840     xmlAttrPtr attr;
10841 
10842     if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10843     (schemaLocation == NULL))
10844         return (-1);
10845 
10846     *schemaLocation = NULL;
10847     /*
10848     * Check for illegal attributes.
10849     * Applies for both <include> and <redefine>.
10850     */
10851     attr = node->properties;
10852     while (attr != NULL) {
10853     if (attr->ns == NULL) {
10854         if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10855         (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10856         xmlSchemaPIllegalAttrErr(pctxt,
10857             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10858         }
10859     } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10860         xmlSchemaPIllegalAttrErr(pctxt,
10861         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10862     }
10863     attr = attr->next;
10864     }
10865     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
10866     /*
10867     * Preliminary step, extract the URI-Reference and make an URI
10868     * from the base.
10869     */
10870     /*
10871     * Attribute "schemaLocation" is mandatory.
10872     */
10873     attr = xmlSchemaGetPropNode(node, "schemaLocation");
10874     if (attr != NULL) {
10875         xmlChar *base = NULL;
10876         xmlChar *uri = NULL;
10877 
10878     if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
10879         xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10880         (const xmlChar **) schemaLocation) != 0)
10881         goto exit_error;
10882     base = xmlNodeGetBase(node->doc, node);
10883     if (base == NULL) {
10884         uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10885     } else {
10886         uri = xmlBuildURI(*schemaLocation, base);
10887         xmlFree(base);
10888     }
10889     if (uri == NULL) {
10890         PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10891         "could not build an URI from the schemaLocation")
10892         goto exit_failure;
10893     }
10894     (*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10895     xmlFree(uri);
10896     } else {
10897     xmlSchemaPMissingAttrErr(pctxt,
10898         XML_SCHEMAP_S4S_ATTR_MISSING,
10899         NULL, node, "schemaLocation", NULL);
10900     goto exit_error;
10901     }
10902     /*
10903     * Report self-inclusion and self-redefinition.
10904     */
10905     if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
10906     if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
10907         xmlSchemaPCustomErr(pctxt,
10908         XML_SCHEMAP_SRC_REDEFINE,
10909         NULL, node,
10910         "The schema document '%s' cannot redefine itself.",
10911         *schemaLocation);
10912     } else {
10913         xmlSchemaPCustomErr(pctxt,
10914         XML_SCHEMAP_SRC_INCLUDE,
10915         NULL, node,
10916         "The schema document '%s' cannot include itself.",
10917         *schemaLocation);
10918     }
10919     goto exit_error;
10920     }
10921 
10922     return(0);
10923 exit_error:
10924     return(pctxt->err);
10925 exit_failure:
10926     return(-1);
10927 }
10928 
10929 static int
10930 xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
10931                 xmlSchemaPtr schema,
10932                 xmlNodePtr node,
10933                 int type)
10934 {
10935     xmlNodePtr child = NULL;
10936     const xmlChar *schemaLocation = NULL;
10937     int res = 0; /* hasRedefinitions = 0 */
10938     int isChameleon = 0, wasChameleon = 0;
10939     xmlSchemaBucketPtr bucket = NULL;
10940 
10941     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10942         return (-1);
10943 
10944     /*
10945     * Parse attributes. Note that the returned schemaLocation will
10946     * be already converted to an absolute URI.
10947     */
10948     res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
10949     node, (xmlChar **) (&schemaLocation), type);
10950     if (res != 0)
10951     return(res);
10952     /*
10953     * Load and add the schema document.
10954     */
10955     res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
10956     NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
10957     if (res != 0)
10958     return(res);
10959     /*
10960     * If we get no schema bucket back, then this means that the schema
10961     * document could not be located or was broken XML or was not
10962     * a schema document.
10963     */
10964     if ((bucket == NULL) || (bucket->doc == NULL)) {
10965     if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
10966         /*
10967         * WARNING for <include>:
10968         * We will raise an error if the schema cannot be located
10969         * for inclusions, since the that was the feedback from the
10970         * schema people. I.e. the following spec piece will *not* be
10971         * satisfied:
10972         * SPEC src-include: "It is not an error for the �actual value� of the
10973         * schemaLocation [attribute] to fail to resolve it all, in which
10974         * case no corresponding inclusion is performed.
10975         * So do we need a warning report here?"
10976         */
10977         res = XML_SCHEMAP_SRC_INCLUDE;
10978         xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10979         node, NULL,
10980         "Failed to load the document '%s' for inclusion",
10981         schemaLocation, NULL);
10982     } else {
10983         /*
10984         * NOTE: This was changed to raise an error even if no redefinitions
10985         * are specified.
10986         *
10987         * SPEC src-redefine (1)
10988         * "If there are any element information items among the [children]
10989         * other than <annotation> then the �actual value� of the
10990         * schemaLocation [attribute] must successfully resolve."
10991         * TODO: Ask the WG if a the location has always to resolve
10992         * here as well!
10993         */
10994         res = XML_SCHEMAP_SRC_REDEFINE;
10995         xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10996         node, NULL,
10997         "Failed to load the document '%s' for redefinition",
10998         schemaLocation, NULL);
10999     }
11000     } else {
11001     /*
11002     * Check targetNamespace sanity before parsing the new schema.
11003     * TODO: Note that we won't check further content if the
11004     * targetNamespace was bad.
11005     */
11006     if (bucket->origTargetNamespace != NULL) {
11007         /*
11008         * SPEC src-include (2.1)
11009         * "SII has a targetNamespace [attribute], and its �actual
11010         * value� is identical to the �actual value� of the targetNamespace
11011         * [attribute] of SII� (which must have such an [attribute])."
11012         */
11013         if (pctxt->targetNamespace == NULL) {
11014         xmlSchemaCustomErr(ACTXT_CAST pctxt,
11015             XML_SCHEMAP_SRC_INCLUDE,
11016             node, NULL,
11017             "The target namespace of the included/redefined schema "
11018             "'%s' has to be absent, since the including/redefining "
11019             "schema has no target namespace",
11020             schemaLocation, NULL);
11021         goto exit_error;
11022         } else if (!xmlStrEqual(bucket->origTargetNamespace,
11023         pctxt->targetNamespace)) {
11024         /* TODO: Change error function. */
11025         xmlSchemaPCustomErrExt(pctxt,
11026             XML_SCHEMAP_SRC_INCLUDE,
11027             NULL, node,
11028             "The target namespace '%s' of the included/redefined "
11029             "schema '%s' differs from '%s' of the "
11030             "including/redefining schema",
11031             bucket->origTargetNamespace, schemaLocation,
11032             pctxt->targetNamespace);
11033         goto exit_error;
11034         }
11035     } else if (pctxt->targetNamespace != NULL) {
11036         /*
11037         * Chameleons: the original target namespace will
11038         * differ from the resulting namespace.
11039         */
11040         isChameleon = 1;
11041         if (bucket->parsed &&
11042         bucket->origTargetNamespace != NULL) {
11043         xmlSchemaCustomErr(ACTXT_CAST pctxt,
11044             XML_SCHEMAP_SRC_INCLUDE,
11045             node, NULL,
11046             "The target namespace of the included/redefined schema "
11047             "'%s' has to be absent or the same as the "
11048             "including/redefining schema's target namespace",
11049             schemaLocation, NULL);
11050         goto exit_error;
11051         }
11052         bucket->targetNamespace = pctxt->targetNamespace;
11053     }
11054     }
11055     /*
11056     * Parse the schema.
11057     */
11058     if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11059     if (isChameleon) {
11060         /* TODO: Get rid of this flag on the schema itself. */
11061         if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11062         schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11063         } else
11064         wasChameleon = 1;
11065     }
11066     xmlSchemaParseNewDoc(pctxt, schema, bucket);
11067     /* Restore chameleon flag. */
11068     if (isChameleon && (!wasChameleon))
11069         schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11070     }
11071     /*
11072     * And now for the children...
11073     */
11074     child = node->children;
11075     if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11076     /*
11077     * Parse (simpleType | complexType | group | attributeGroup))*
11078     */
11079     pctxt->redefined = bucket;
11080     /*
11081     * How to proceed if the redefined schema was not located?
11082     */
11083     pctxt->isRedefine = 1;
11084     while (IS_SCHEMA(child, "annotation") ||
11085         IS_SCHEMA(child, "simpleType") ||
11086         IS_SCHEMA(child, "complexType") ||
11087         IS_SCHEMA(child, "group") ||
11088         IS_SCHEMA(child, "attributeGroup")) {
11089         if (IS_SCHEMA(child, "annotation")) {
11090         /*
11091         * TODO: discard or not?
11092         */
11093         } else if (IS_SCHEMA(child, "simpleType")) {
11094         xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11095         } else if (IS_SCHEMA(child, "complexType")) {
11096         xmlSchemaParseComplexType(pctxt, schema, child, 1);
11097         /* hasRedefinitions = 1; */
11098         } else if (IS_SCHEMA(child, "group")) {
11099         /* hasRedefinitions = 1; */
11100         xmlSchemaParseModelGroupDefinition(pctxt,
11101             schema, child);
11102         } else if (IS_SCHEMA(child, "attributeGroup")) {
11103         /* hasRedefinitions = 1; */
11104         xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11105             child);
11106         }
11107         child = child->next;
11108     }
11109     pctxt->redefined = NULL;
11110     pctxt->isRedefine = 0;
11111     } else {
11112     if (IS_SCHEMA(child, "annotation")) {
11113         /*
11114         * TODO: discard or not?
11115         */
11116         child = child->next;
11117     }
11118     }
11119     if (child != NULL) {
11120     res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
11121     if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11122         xmlSchemaPContentErr(pctxt, res,
11123         NULL, node, child, NULL,
11124         "(annotation | (simpleType | complexType | group | attributeGroup))*");
11125     } else {
11126          xmlSchemaPContentErr(pctxt, res,
11127         NULL, node, child, NULL,
11128         "(annotation?)");
11129     }
11130     }
11131     return(res);
11132 
11133 exit_error:
11134     return(pctxt->err);
11135 }
11136 
11137 static int
11138 xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11139                        xmlNodePtr node)
11140 {
11141     int res;
11142 #ifndef ENABLE_REDEFINE
11143     TODO
11144     return(0);
11145 #endif
11146     res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11147     XML_SCHEMA_SCHEMA_REDEFINE);
11148     if (res != 0)
11149     return(res);
11150     return(0);
11151 }
11152 
11153 static int
11154 xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11155                        xmlNodePtr node)
11156 {
11157     int res;
11158 
11159     res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11160     XML_SCHEMA_SCHEMA_INCLUDE);
11161     if (res != 0)
11162     return(res);
11163     return(0);
11164 }
11165 
11191 static xmlSchemaTreeItemPtr
11192 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11193              xmlNodePtr node, xmlSchemaTypeType type,
11194              int withParticle)
11195 {
11196     xmlSchemaModelGroupPtr item;
11197     xmlSchemaParticlePtr particle = NULL;
11198     xmlNodePtr child = NULL;
11199     xmlAttrPtr attr;
11200     int min = 1, max = 1, isElemRef, hasRefs = 0;
11201 
11202     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11203         return (NULL);
11204     /*
11205     * Create a model group with the given compositor.
11206     */
11207     item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
11208     if (item == NULL)
11209     return (NULL);
11210 
11211     if (withParticle) {
11212     if (type == XML_SCHEMA_TYPE_ALL) {
11213         min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
11214         max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
11215     } else {
11216         /* choice + sequence */
11217         min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11218         max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11219         "(xs:nonNegativeInteger | unbounded)");
11220     }
11221     xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11222     /*
11223     * Create a particle
11224     */
11225     particle = xmlSchemaAddParticle(ctxt, node, min, max);
11226     if (particle == NULL)
11227         return (NULL);
11228     particle->children = (xmlSchemaTreeItemPtr) item;
11229     /*
11230     * Check for illegal attributes.
11231     */
11232     attr = node->properties;
11233     while (attr != NULL) {
11234         if (attr->ns == NULL) {
11235         if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11236             (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11237             (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
11238             xmlSchemaPIllegalAttrErr(ctxt,
11239             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11240         }
11241         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11242         xmlSchemaPIllegalAttrErr(ctxt,
11243             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11244         }
11245         attr = attr->next;
11246     }
11247     } else {
11248     /*
11249     * Check for illegal attributes.
11250     */
11251     attr = node->properties;
11252     while (attr != NULL) {
11253         if (attr->ns == NULL) {
11254         if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
11255             xmlSchemaPIllegalAttrErr(ctxt,
11256             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11257         }
11258         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11259         xmlSchemaPIllegalAttrErr(ctxt,
11260             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11261         }
11262         attr = attr->next;
11263     }
11264     }
11265 
11266     /*
11267     * Extract and validate attributes.
11268     */
11269     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11270     /*
11271     * And now for the children...
11272     */
11273     child = node->children;
11274     if (IS_SCHEMA(child, "annotation")) {
11275         item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
11276         child = child->next;
11277     }
11278     if (type == XML_SCHEMA_TYPE_ALL) {
11279     xmlSchemaParticlePtr part, last = NULL;
11280 
11281     while (IS_SCHEMA(child, "element")) {
11282         part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
11283         schema, child, &isElemRef, 0);
11284         /*
11285         * SPEC cos-all-limited (2)
11286         * "The {max occurs} of all the particles in the {particles}
11287         * of the ('all') group must be 0 or 1.
11288         */
11289         if (part != NULL) {
11290         if (isElemRef)
11291             hasRefs++;
11292         if (part->minOccurs > 1) {
11293             xmlSchemaPCustomErr(ctxt,
11294             XML_SCHEMAP_COS_ALL_LIMITED,
11295             NULL, child,
11296             "Invalid value for minOccurs (must be 0 or 1)",
11297             NULL);
11298             /* Reset to 1. */
11299             part->minOccurs = 1;
11300         }
11301         if (part->maxOccurs > 1) {
11302             xmlSchemaPCustomErr(ctxt,
11303             XML_SCHEMAP_COS_ALL_LIMITED,
11304             NULL, child,
11305             "Invalid value for maxOccurs (must be 0 or 1)",
11306             NULL);
11307             /* Reset to 1. */
11308             part->maxOccurs = 1;
11309         }
11310         if (last == NULL)
11311             item->children = (xmlSchemaTreeItemPtr) part;
11312         else
11313             last->next = (xmlSchemaTreeItemPtr) part;
11314         last = part;
11315         }
11316         child = child->next;
11317     }
11318     if (child != NULL) {
11319         xmlSchemaPContentErr(ctxt,
11320         XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11321         NULL, node, child, NULL,
11322         "(annotation?, (annotation?, element*)");
11323     }
11324     } else {
11325     /* choice + sequence */
11326     xmlSchemaTreeItemPtr part = NULL, last = NULL;
11327 
11328     while ((IS_SCHEMA(child, "element")) ||
11329         (IS_SCHEMA(child, "group")) ||
11330         (IS_SCHEMA(child, "any")) ||
11331         (IS_SCHEMA(child, "choice")) ||
11332         (IS_SCHEMA(child, "sequence"))) {
11333 
11334         if (IS_SCHEMA(child, "element")) {
11335         part = (xmlSchemaTreeItemPtr)
11336             xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11337         if (part && isElemRef)
11338             hasRefs++;
11339         } else if (IS_SCHEMA(child, "group")) {
11340         part =
11341             xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11342         if (part != NULL)
11343             hasRefs++;
11344         /*
11345         * Handle redefinitions.
11346         */
11347         if (ctxt->isRedefine && ctxt->redef &&
11348             (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11349             part && part->children)
11350         {
11351             if ((xmlSchemaGetQNameRefName(part->children) ==
11352                 ctxt->redef->refName) &&
11353             (xmlSchemaGetQNameRefTargetNs(part->children) ==
11354                 ctxt->redef->refTargetNs))
11355             {
11356             /*
11357             * SPEC src-redefine:
11358             * (6.1) "If it has a <group> among its contents at
11359             * some level the �actual value� of whose ref
11360             * [attribute] is the same as the �actual value� of
11361             * its own name attribute plus target namespace, then
11362             * all of the following must be true:"
11363             * (6.1.1) "It must have exactly one such group."
11364             */
11365             if (ctxt->redefCounter != 0) {
11366                 xmlChar *str = NULL;
11367 
11368                 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11369                 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11370                 "The redefining model group definition "
11371                 "'%s' must not contain more than one "
11372                 "reference to the redefined definition",
11373                 xmlSchemaFormatQName(&str,
11374                     ctxt->redef->refTargetNs,
11375                     ctxt->redef->refName),
11376                 NULL);
11377                 FREE_AND_NULL(str)
11378                 part = NULL;
11379             } else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11380                 ((WXS_PARTICLE(part))->maxOccurs != 1))
11381             {
11382                 xmlChar *str = NULL;
11383                 /*
11384                 * SPEC src-redefine:
11385                 * (6.1.2) "The �actual value� of both that
11386                 * group's minOccurs and maxOccurs [attribute]
11387                 * must be 1 (or �absent�).
11388                 */
11389                 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11390                 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11391                 "The redefining model group definition "
11392                 "'%s' must not contain a reference to the "
11393                 "redefined definition with a "
11394                 "maxOccurs/minOccurs other than 1",
11395                 xmlSchemaFormatQName(&str,
11396                     ctxt->redef->refTargetNs,
11397                     ctxt->redef->refName),
11398                 NULL);
11399                 FREE_AND_NULL(str)
11400                 part = NULL;
11401             }
11402             ctxt->redef->reference = WXS_BASIC_CAST part;
11403             ctxt->redefCounter++;
11404             }
11405         }
11406         } else if (IS_SCHEMA(child, "any")) {
11407         part = (xmlSchemaTreeItemPtr)
11408             xmlSchemaParseAny(ctxt, schema, child);
11409         } else if (IS_SCHEMA(child, "choice")) {
11410         part = xmlSchemaParseModelGroup(ctxt, schema, child,
11411             XML_SCHEMA_TYPE_CHOICE, 1);
11412         } else if (IS_SCHEMA(child, "sequence")) {
11413         part = xmlSchemaParseModelGroup(ctxt, schema, child,
11414             XML_SCHEMA_TYPE_SEQUENCE, 1);
11415         }
11416         if (part != NULL) {
11417         if (last == NULL)
11418             item->children = part;
11419         else
11420             last->next = part;
11421         last = part;
11422         }
11423         child = child->next;
11424     }
11425     if (child != NULL) {
11426         xmlSchemaPContentErr(ctxt,
11427         XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11428         NULL, node, child, NULL,
11429         "(annotation?, (element | group | choice | sequence | any)*)");
11430     }
11431     }
11432     if ((max == 0) && (min == 0))
11433     return (NULL);
11434     if (hasRefs) {
11435     /*
11436     * We need to resolve references.
11437     */
11438     WXS_ADD_PENDING(ctxt, item);
11439     }
11440     if (withParticle)
11441     return ((xmlSchemaTreeItemPtr) particle);
11442     else
11443     return ((xmlSchemaTreeItemPtr) item);
11444 }
11445 
11457 static xmlSchemaTypePtr
11458 xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11459                           xmlNodePtr node, xmlSchemaTypeType parentType)
11460 {
11461     xmlSchemaTypePtr type;
11462     xmlNodePtr child = NULL;
11463     xmlAttrPtr attr;
11464 
11465     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11466         return (NULL);
11467     /* Not a component, don't create it. */
11468     type = ctxt->ctxtType;
11469     type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
11470 
11471     /*
11472     * Check for illegal attributes.
11473     */
11474     attr = node->properties;
11475     while (attr != NULL) {
11476     if (attr->ns == NULL) {
11477         if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11478         (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11479         xmlSchemaPIllegalAttrErr(ctxt,
11480             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11481         }
11482     } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11483         xmlSchemaPIllegalAttrErr(ctxt,
11484         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11485     }
11486     attr = attr->next;
11487     }
11488     /*
11489     * Extract and validate attributes.
11490     */
11491     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11492     /*
11493     * Attribute
11494     */
11495     /*
11496     * Extract the base type. The "base" attribute is mandatory if inside
11497     * a complex type or if redefining.
11498     *
11499     * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
11500     * among its [children]), the simple type definition which is
11501     * the {content type} of the type definition �resolved� to by
11502     * the �actual value� of the base [attribute]"
11503     */
11504     if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
11505     &(type->baseNs), &(type->base)) == 0)
11506     {
11507     if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11508         xmlSchemaPMissingAttrErr(ctxt,
11509         XML_SCHEMAP_S4S_ATTR_MISSING,
11510         NULL, node, "base", NULL);
11511     } else if ((ctxt->isRedefine) &&
11512         (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11513     {
11514         if (type->base == NULL) {
11515         xmlSchemaPMissingAttrErr(ctxt,
11516             XML_SCHEMAP_S4S_ATTR_MISSING,
11517             NULL, node, "base", NULL);
11518         } else if ((! xmlStrEqual(type->base, type->name)) ||
11519         (! xmlStrEqual(type->baseNs, type->targetNamespace)))
11520         {
11521         xmlChar *str1 = NULL, *str2 = NULL;
11522         /*
11523         * REDEFINE: SPEC src-redefine (5)
11524         * "Within the [children], each <simpleType> must have a
11525         * <restriction> among its [children] ... the �actual value� of
11526         * whose base [attribute] must be the same as the �actual value�
11527         * of its own name attribute plus target namespace;"
11528         */
11529         xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
11530             NULL, node, "This is a redefinition, but the QName "
11531             "value '%s' of the 'base' attribute does not match the "
11532             "type's designation '%s'",
11533             xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11534             xmlSchemaFormatQName(&str2, type->targetNamespace,
11535             type->name), NULL);
11536         FREE_AND_NULL(str1);
11537         FREE_AND_NULL(str2);
11538         /* Avoid confusion and erase the values. */
11539         type->base = NULL;
11540         type->baseNs = NULL;
11541         }
11542     }
11543     }
11544     /*
11545     * And now for the children...
11546     */
11547     child = node->children;
11548     if (IS_SCHEMA(child, "annotation")) {
11549     /*
11550     * Add the annotation to the simple type ancestor.
11551     */
11552     xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11553         xmlSchemaParseAnnotation(ctxt, child, 1));
11554         child = child->next;
11555     }
11556     if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11557     /*
11558     * Corresponds to <simpleType><restriction><simpleType>.
11559     */
11560     if (IS_SCHEMA(child, "simpleType")) {
11561         if (type->base != NULL) {
11562         /*
11563         * src-restriction-base-or-simpleType
11564         * Either the base [attribute] or the simpleType [child] of the
11565         * <restriction> element must be present, but not both.
11566         */
11567         xmlSchemaPContentErr(ctxt,
11568             XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11569             NULL, node, child,
11570             "The attribute 'base' and the <simpleType> child are "
11571             "mutually exclusive", NULL);
11572         } else {
11573         type->baseType = (xmlSchemaTypePtr)
11574             xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11575         }
11576         child = child->next;
11577     } else if (type->base == NULL) {
11578         xmlSchemaPContentErr(ctxt,
11579         XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11580         NULL, node, child,
11581         "Either the attribute 'base' or a <simpleType> child "
11582         "must be present", NULL);
11583     }
11584     } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11585     /*
11586     * Corresponds to <complexType><complexContent><restriction>...
11587     * followed by:
11588     *
11589     * Model groups <all>, <choice> and <sequence>.
11590     */
11591     if (IS_SCHEMA(child, "all")) {
11592         type->subtypes = (xmlSchemaTypePtr)
11593         xmlSchemaParseModelGroup(ctxt, schema, child,
11594             XML_SCHEMA_TYPE_ALL, 1);
11595         child = child->next;
11596     } else if (IS_SCHEMA(child, "choice")) {
11597         type->subtypes = (xmlSchemaTypePtr)
11598         xmlSchemaParseModelGroup(ctxt,
11599             schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11600         child = child->next;
11601     } else if (IS_SCHEMA(child, "sequence")) {
11602         type->subtypes = (xmlSchemaTypePtr)
11603         xmlSchemaParseModelGroup(ctxt, schema, child,
11604             XML_SCHEMA_TYPE_SEQUENCE, 1);
11605         child = child->next;
11606     /*
11607     * Model group reference <group>.
11608     */
11609     } else if (IS_SCHEMA(child, "group")) {
11610         type->subtypes = (xmlSchemaTypePtr)
11611         xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11612         /*
11613         * Note that the reference will be resolved in
11614         * xmlSchemaResolveTypeReferences();
11615         */
11616         child = child->next;
11617     }
11618     } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11619     /*
11620     * Corresponds to <complexType><simpleContent><restriction>...
11621     *
11622     * "1.1 the simple type definition corresponding to the <simpleType>
11623     * among the [children] of <restriction> if there is one;"
11624     */
11625     if (IS_SCHEMA(child, "simpleType")) {
11626         /*
11627         * We will store the to-be-restricted simple type in
11628         * type->contentTypeDef *temporarily*.
11629         */
11630         type->contentTypeDef = (xmlSchemaTypePtr)
11631         xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11632         if ( type->contentTypeDef == NULL)
11633         return (NULL);
11634         child = child->next;
11635     }
11636     }
11637 
11638     if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
11639     (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
11640     xmlSchemaFacetPtr facet, lastfacet = NULL;
11641     /*
11642     * Corresponds to <complexType><simpleContent><restriction>...
11643     * <simpleType><restriction>...
11644     */
11645 
11646     /*
11647     * Add the facets to the simple type ancestor.
11648     */
11649     /*
11650     * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11651     * Simple Type Definition Schema Representation Constraint:
11652     * *Single Facet Value*
11653     */
11654     while ((IS_SCHEMA(child, "minInclusive")) ||
11655         (IS_SCHEMA(child, "minExclusive")) ||
11656         (IS_SCHEMA(child, "maxInclusive")) ||
11657         (IS_SCHEMA(child, "maxExclusive")) ||
11658         (IS_SCHEMA(child, "totalDigits")) ||
11659         (IS_SCHEMA(child, "fractionDigits")) ||
11660         (IS_SCHEMA(child, "pattern")) ||
11661         (IS_SCHEMA(child, "enumeration")) ||
11662         (IS_SCHEMA(child, "whiteSpace")) ||
11663         (IS_SCHEMA(child, "length")) ||
11664         (IS_SCHEMA(child, "maxLength")) ||
11665         (IS_SCHEMA(child, "minLength"))) {
11666         facet = xmlSchemaParseFacet(ctxt, schema, child);
11667         if (facet != NULL) {
11668         if (lastfacet == NULL)
11669             type->facets = facet;
11670         else
11671             lastfacet->next = facet;
11672         lastfacet = facet;
11673         lastfacet->next = NULL;
11674         }
11675         child = child->next;
11676     }
11677     /*
11678     * Create links for derivation and validation.
11679     */
11680     if (type->facets != NULL) {
11681         xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11682 
11683         facet = type->facets;
11684         do {
11685         facetLink = (xmlSchemaFacetLinkPtr)
11686             xmlMalloc(sizeof(xmlSchemaFacetLink));
11687         if (facetLink == NULL) {
11688             xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
11689             xmlFree(facetLink);
11690             return (NULL);
11691         }
11692         facetLink->facet = facet;
11693         facetLink->next = NULL;
11694         if (lastFacetLink == NULL)
11695             type->facetSet = facetLink;
11696         else
11697             lastFacetLink->next = facetLink;
11698         lastFacetLink = facetLink;
11699         facet = facet->next;
11700         } while (facet != NULL);
11701     }
11702     }
11703     if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11704     /*
11705     * Attribute uses/declarations.
11706     */
11707     if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11708         (xmlSchemaItemListPtr *) &(type->attrUses),
11709         XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11710         return(NULL);
11711     /*
11712     * Attribute wildcard.
11713     */
11714     if (IS_SCHEMA(child, "anyAttribute")) {
11715         type->attributeWildcard =
11716         xmlSchemaParseAnyAttribute(ctxt, schema, child);
11717         child = child->next;
11718     }
11719     }
11720     if (child != NULL) {
11721     if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11722         xmlSchemaPContentErr(ctxt,
11723         XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11724         NULL, node, child, NULL,
11725         "annotation?, (group | all | choice | sequence)?, "
11726         "((attribute | attributeGroup)*, anyAttribute?))");
11727     } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11728          xmlSchemaPContentErr(ctxt,
11729         XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11730         NULL, node, child, NULL,
11731         "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11732         "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11733         "length | minLength | maxLength | enumeration | whiteSpace | "
11734         "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11735     } else {
11736         /* Simple type */
11737         xmlSchemaPContentErr(ctxt,
11738         XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11739         NULL, node, child, NULL,
11740         "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11741         "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11742         "length | minLength | maxLength | enumeration | whiteSpace | "
11743         "pattern)*))");
11744     }
11745     }
11746     return (NULL);
11747 }
11748 
11761 static xmlSchemaTypePtr
11762 xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11763                         xmlNodePtr node, xmlSchemaTypeType parentType)
11764 {
11765     xmlSchemaTypePtr type;
11766     xmlNodePtr child = NULL;
11767     xmlAttrPtr attr;
11768 
11769     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11770         return (NULL);
11771     /* Not a component, don't create it. */
11772     type = ctxt->ctxtType;
11773     type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
11774 
11775     /*
11776     * Check for illegal attributes.
11777     */
11778     attr = node->properties;
11779     while (attr != NULL) {
11780     if (attr->ns == NULL) {
11781         if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11782         (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11783         xmlSchemaPIllegalAttrErr(ctxt,
11784             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11785         }
11786     } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11787         xmlSchemaPIllegalAttrErr(ctxt,
11788         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11789     }
11790     attr = attr->next;
11791     }
11792 
11793     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11794 
11795     /*
11796     * Attribute "base" - mandatory.
11797     */
11798     if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11799     "base", &(type->baseNs), &(type->base)) == 0) &&
11800     (type->base == NULL)) {
11801     xmlSchemaPMissingAttrErr(ctxt,
11802         XML_SCHEMAP_S4S_ATTR_MISSING,
11803         NULL, node, "base", NULL);
11804     }
11805     /*
11806     * And now for the children...
11807     */
11808     child = node->children;
11809     if (IS_SCHEMA(child, "annotation")) {
11810     /*
11811     * Add the annotation to the type ancestor.
11812     */
11813     xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11814         xmlSchemaParseAnnotation(ctxt, child, 1));
11815         child = child->next;
11816     }
11817     if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11818     /*
11819     * Corresponds to <complexType><complexContent><extension>... and:
11820     *
11821     * Model groups <all>, <choice>, <sequence> and <group>.
11822     */
11823     if (IS_SCHEMA(child, "all")) {
11824         type->subtypes = (xmlSchemaTypePtr)
11825         xmlSchemaParseModelGroup(ctxt, schema,
11826             child, XML_SCHEMA_TYPE_ALL, 1);
11827         child = child->next;
11828     } else if (IS_SCHEMA(child, "choice")) {
11829         type->subtypes = (xmlSchemaTypePtr)
11830         xmlSchemaParseModelGroup(ctxt, schema,
11831             child, XML_SCHEMA_TYPE_CHOICE, 1);
11832         child = child->next;
11833     } else if (IS_SCHEMA(child, "sequence")) {
11834         type->subtypes = (xmlSchemaTypePtr)
11835         xmlSchemaParseModelGroup(ctxt, schema,
11836         child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11837         child = child->next;
11838     } else if (IS_SCHEMA(child, "group")) {
11839         type->subtypes = (xmlSchemaTypePtr)
11840         xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11841         /*
11842         * Note that the reference will be resolved in
11843         * xmlSchemaResolveTypeReferences();
11844         */
11845         child = child->next;
11846     }
11847     }
11848     if (child != NULL) {
11849     /*
11850     * Attribute uses/declarations.
11851     */
11852     if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11853         (xmlSchemaItemListPtr *) &(type->attrUses),
11854         XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11855         return(NULL);
11856     /*
11857     * Attribute wildcard.
11858     */
11859     if (IS_SCHEMA(child, "anyAttribute")) {
11860         ctxt->ctxtType->attributeWildcard =
11861         xmlSchemaParseAnyAttribute(ctxt, schema, child);
11862         child = child->next;
11863     }
11864     }
11865     if (child != NULL) {
11866     if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11867         /* Complex content extension. */
11868         xmlSchemaPContentErr(ctxt,
11869         XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11870         NULL, node, child, NULL,
11871         "(annotation?, ((group | all | choice | sequence)?, "
11872         "((attribute | attributeGroup)*, anyAttribute?)))");
11873     } else {
11874         /* Simple content extension. */
11875         xmlSchemaPContentErr(ctxt,
11876         XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11877         NULL, node, child, NULL,
11878         "(annotation?, ((attribute | attributeGroup)*, "
11879         "anyAttribute?))");
11880     }
11881     }
11882     return (NULL);
11883 }
11884 
11896 static int
11897 xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
11898                             xmlSchemaPtr schema, xmlNodePtr node,
11899                 int *hasRestrictionOrExtension)
11900 {
11901     xmlSchemaTypePtr type;
11902     xmlNodePtr child = NULL;
11903     xmlAttrPtr attr;
11904 
11905     if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11906     (hasRestrictionOrExtension == NULL))
11907         return (-1);
11908     *hasRestrictionOrExtension = 0;
11909     /* Not a component, don't create it. */
11910     type = ctxt->ctxtType;
11911     type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11912     /*
11913     * Check for illegal attributes.
11914     */
11915     attr = node->properties;
11916     while (attr != NULL) {
11917     if (attr->ns == NULL) {
11918         if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
11919         xmlSchemaPIllegalAttrErr(ctxt,
11920             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11921         }
11922     } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11923         xmlSchemaPIllegalAttrErr(ctxt,
11924         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11925     }
11926     attr = attr->next;
11927     }
11928 
11929     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11930 
11931     /*
11932     * And now for the children...
11933     */
11934     child = node->children;
11935     if (IS_SCHEMA(child, "annotation")) {
11936     /*
11937     * Add the annotation to the complex type ancestor.
11938     */
11939     xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11940         xmlSchemaParseAnnotation(ctxt, child, 1));
11941         child = child->next;
11942     }
11943     if (child == NULL) {
11944     xmlSchemaPContentErr(ctxt,
11945         XML_SCHEMAP_S4S_ELEM_MISSING,
11946         NULL, node, NULL, NULL,
11947         "(annotation?, (restriction | extension))");
11948     }
11949     if (child == NULL) {
11950     xmlSchemaPContentErr(ctxt,
11951         XML_SCHEMAP_S4S_ELEM_MISSING,
11952         NULL, node, NULL, NULL,
11953         "(annotation?, (restriction | extension))");
11954     }
11955     if (IS_SCHEMA(child, "restriction")) {
11956         xmlSchemaParseRestriction(ctxt, schema, child,
11957         XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11958     (*hasRestrictionOrExtension) = 1;
11959         child = child->next;
11960     } else if (IS_SCHEMA(child, "extension")) {
11961         xmlSchemaParseExtension(ctxt, schema, child,
11962         XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11963     (*hasRestrictionOrExtension) = 1;
11964         child = child->next;
11965     }
11966     if (child != NULL) {
11967     xmlSchemaPContentErr(ctxt,
11968         XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11969         NULL, node, child, NULL,
11970         "(annotation?, (restriction | extension))");
11971     }
11972     return (0);
11973 }
11974 
11986 static int
11987 xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
11988                              xmlSchemaPtr schema, xmlNodePtr node,
11989                  int *hasRestrictionOrExtension)
11990 {
11991     xmlSchemaTypePtr type;
11992     xmlNodePtr child = NULL;
11993     xmlAttrPtr attr;
11994 
11995     if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11996     (hasRestrictionOrExtension == NULL))
11997         return (-1);
11998     *hasRestrictionOrExtension = 0;
11999     /* Not a component, don't create it. */
12000     type = ctxt->ctxtType;
12001     /*
12002     * Check for illegal attributes.
12003     */
12004     attr = node->properties;
12005     while (attr != NULL) {
12006     if (attr->ns == NULL) {
12007         if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
12008         (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
12009         {
12010         xmlSchemaPIllegalAttrErr(ctxt,
12011             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12012         }
12013     } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12014         xmlSchemaPIllegalAttrErr(ctxt,
12015         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12016     }
12017     attr = attr->next;
12018     }
12019 
12020     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12021 
12022     /*
12023     * Set the 'mixed' on the complex type ancestor.
12024     */
12025     if (xmlGetBooleanProp(ctxt, node, "mixed", 0))  {
12026     if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
12027         type->flags |= XML_SCHEMAS_TYPE_MIXED;
12028     }
12029     child = node->children;
12030     if (IS_SCHEMA(child, "annotation")) {
12031     /*
12032     * Add the annotation to the complex type ancestor.
12033     */
12034     xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12035         xmlSchemaParseAnnotation(ctxt, child, 1));
12036         child = child->next;
12037     }
12038     if (child == NULL) {
12039     xmlSchemaPContentErr(ctxt,
12040         XML_SCHEMAP_S4S_ELEM_MISSING,
12041         NULL, node, NULL,
12042         NULL, "(annotation?, (restriction | extension))");
12043     }
12044     if (child == NULL) {
12045     xmlSchemaPContentErr(ctxt,
12046         XML_SCHEMAP_S4S_ELEM_MISSING,
12047         NULL, node, NULL,
12048         NULL, "(annotation?, (restriction | extension))");
12049     }
12050     if (IS_SCHEMA(child, "restriction")) {
12051         xmlSchemaParseRestriction(ctxt, schema, child,
12052         XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12053     (*hasRestrictionOrExtension) = 1;
12054         child = child->next;
12055     } else if (IS_SCHEMA(child, "extension")) {
12056         xmlSchemaParseExtension(ctxt, schema, child,
12057         XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12058     (*hasRestrictionOrExtension) = 1;
12059         child = child->next;
12060     }
12061     if (child != NULL) {
12062     xmlSchemaPContentErr(ctxt,
12063         XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12064         NULL, node, child,
12065         NULL, "(annotation?, (restriction | extension))");
12066     }
12067     return (0);
12068 }
12069 
12081 static xmlSchemaTypePtr
12082 xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
12083                           xmlNodePtr node, int topLevel)
12084 {
12085     xmlSchemaTypePtr type, ctxtType;
12086     xmlNodePtr child = NULL;
12087     const xmlChar *name = NULL;
12088     xmlAttrPtr attr;
12089     const xmlChar *attrValue;
12090 #ifdef ENABLE_NAMED_LOCALS
12091     char buf[40];
12092 #endif
12093     int final = 0, block = 0, hasRestrictionOrExtension = 0;
12094 
12095 
12096     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12097         return (NULL);
12098 
12099     ctxtType = ctxt->ctxtType;
12100 
12101     if (topLevel) {
12102     attr = xmlSchemaGetPropNode(node, "name");
12103     if (attr == NULL) {
12104         xmlSchemaPMissingAttrErr(ctxt,
12105         XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
12106         return (NULL);
12107     } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
12108         xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12109         return (NULL);
12110     }
12111     }
12112 
12113     if (topLevel == 0) {
12114     /*
12115     * Parse as local complex type definition.
12116     */
12117 #ifdef ENABLE_NAMED_LOCALS
12118         snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
12119     type = xmlSchemaAddType(ctxt, schema,
12120         XML_SCHEMA_TYPE_COMPLEX,
12121         xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
12122         ctxt->targetNamespace, node, 0);
12123 #else
12124     type = xmlSchemaAddType(ctxt, schema,
12125         XML_SCHEMA_TYPE_COMPLEX,
12126         NULL, ctxt->targetNamespace, node, 0);
12127 #endif
12128     if (type == NULL)
12129         return (NULL);
12130     name = type->name;
12131     type->node = node;
12132     type->type = XML_SCHEMA_TYPE_COMPLEX;
12133     /*
12134     * TODO: We need the target namespace.
12135     */
12136     } else {
12137     /*
12138     * Parse as global complex type definition.
12139     */
12140     type = xmlSchemaAddType(ctxt, schema,
12141         XML_SCHEMA_TYPE_COMPLEX,
12142         name, ctxt->targetNamespace, node, 1);
12143     if (type == NULL)
12144         return (NULL);
12145     type->node = node;
12146     type->type = XML_SCHEMA_TYPE_COMPLEX;
12147     type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
12148     }
12149     type->targetNamespace = ctxt->targetNamespace;
12150     /*
12151     * Handle attributes.
12152     */
12153     attr = node->properties;
12154     while (attr != NULL) {
12155     if (attr->ns == NULL) {
12156         if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12157         /*
12158         * Attribute "id".
12159         */
12160         xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12161         } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12162         /*
12163         * Attribute "mixed".
12164         */
12165         if (xmlSchemaPGetBoolNodeValue(ctxt,
12166             NULL, (xmlNodePtr) attr))
12167             type->flags |= XML_SCHEMAS_TYPE_MIXED;
12168         } else if (topLevel) {
12169         /*
12170         * Attributes of global complex type definitions.
12171         */
12172         if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12173             /* Pass. */
12174         } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12175             /*
12176             * Attribute "abstract".
12177             */
12178             if (xmlSchemaPGetBoolNodeValue(ctxt,
12179                 NULL, (xmlNodePtr) attr))
12180             type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12181         } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12182             /*
12183             * Attribute "final".
12184             */
12185             attrValue = xmlSchemaGetNodeContent(ctxt,
12186             (xmlNodePtr) attr);
12187             if (xmlSchemaPValAttrBlockFinal(attrValue,
12188             &(type->flags),
12189             -1,
12190             XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12191             XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12192             -1, -1, -1) != 0)
12193             {
12194             xmlSchemaPSimpleTypeErr(ctxt,
12195                 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12196                 NULL, (xmlNodePtr) attr, NULL,
12197                 "(#all | List of (extension | restriction))",
12198                 attrValue, NULL, NULL, NULL);
12199             } else
12200             final = 1;
12201         } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12202             /*
12203             * Attribute "block".
12204             */
12205             attrValue = xmlSchemaGetNodeContent(ctxt,
12206             (xmlNodePtr) attr);
12207             if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
12208             -1,
12209             XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
12210             XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
12211             -1, -1, -1) != 0) {
12212             xmlSchemaPSimpleTypeErr(ctxt,
12213                 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12214                 NULL, (xmlNodePtr) attr, NULL,
12215                 "(#all | List of (extension | restriction)) ",
12216                 attrValue, NULL, NULL, NULL);
12217             } else
12218             block = 1;
12219         } else {
12220             xmlSchemaPIllegalAttrErr(ctxt,
12221                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12222         }
12223         } else {
12224         xmlSchemaPIllegalAttrErr(ctxt,
12225             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12226         }
12227     } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12228         xmlSchemaPIllegalAttrErr(ctxt,
12229         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12230     }
12231     attr = attr->next;
12232     }
12233     if (! block) {
12234     /*
12235     * Apply default "block" values.
12236     */
12237     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12238         type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12239     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12240         type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12241     }
12242     if (! final) {
12243     /*
12244     * Apply default "block" values.
12245     */
12246     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12247         type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12248     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12249         type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12250     }
12251     /*
12252     * And now for the children...
12253     */
12254     child = node->children;
12255     if (IS_SCHEMA(child, "annotation")) {
12256         type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
12257         child = child->next;
12258     }
12259     ctxt->ctxtType = type;
12260     if (IS_SCHEMA(child, "simpleContent")) {
12261     /*
12262     * <complexType><simpleContent>...
12263     * 3.4.3 : 2.2
12264     * Specifying mixed='true' when the <simpleContent>
12265     * alternative is chosen has no effect
12266     */
12267     if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12268         type->flags ^= XML_SCHEMAS_TYPE_MIXED;
12269         xmlSchemaParseSimpleContent(ctxt, schema, child,
12270         &hasRestrictionOrExtension);
12271         child = child->next;
12272     } else if (IS_SCHEMA(child, "complexContent")) {
12273     /*
12274     * <complexType><complexContent>...
12275     */
12276     type->contentType = XML_SCHEMA_CONTENT_EMPTY;
12277         xmlSchemaParseComplexContent(ctxt, schema, child,
12278         &hasRestrictionOrExtension);
12279         child = child->next;
12280     } else {
12281     /*
12282     * E.g <complexType><sequence>... or <complexType><attribute>... etc.
12283     *
12284     * SPEC
12285     * "...the third alternative (neither <simpleContent> nor
12286     * <complexContent>) is chosen. This case is understood as shorthand
12287     * for complex content restricting the �ur-type definition�, and the
12288     * details of the mappings should be modified as necessary.
12289     */
12290     type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12291     type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
12292     /*
12293     * Parse model groups.
12294     */
12295         if (IS_SCHEMA(child, "all")) {
12296             type->subtypes = (xmlSchemaTypePtr)
12297         xmlSchemaParseModelGroup(ctxt, schema, child,
12298             XML_SCHEMA_TYPE_ALL, 1);
12299             child = child->next;
12300         } else if (IS_SCHEMA(child, "choice")) {
12301             type->subtypes = (xmlSchemaTypePtr)
12302         xmlSchemaParseModelGroup(ctxt, schema, child,
12303             XML_SCHEMA_TYPE_CHOICE, 1);
12304             child = child->next;
12305         } else if (IS_SCHEMA(child, "sequence")) {
12306             type->subtypes = (xmlSchemaTypePtr)
12307         xmlSchemaParseModelGroup(ctxt, schema, child,
12308             XML_SCHEMA_TYPE_SEQUENCE, 1);
12309             child = child->next;
12310         } else if (IS_SCHEMA(child, "group")) {
12311             type->subtypes = (xmlSchemaTypePtr)
12312         xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
12313         /*
12314         * Note that the reference will be resolved in
12315         * xmlSchemaResolveTypeReferences();
12316         */
12317             child = child->next;
12318         }
12319     /*
12320     * Parse attribute decls/refs.
12321     */
12322         if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12323         (xmlSchemaItemListPtr *) &(type->attrUses),
12324         XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12325         return(NULL);
12326     /*
12327     * Parse attribute wildcard.
12328     */
12329     if (IS_SCHEMA(child, "anyAttribute")) {
12330         type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12331         child = child->next;
12332     }
12333     }
12334     if (child != NULL) {
12335     xmlSchemaPContentErr(ctxt,
12336         XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12337         NULL, node, child,
12338         NULL, "(annotation?, (simpleContent | complexContent | "
12339         "((group | all | choice | sequence)?, ((attribute | "
12340         "attributeGroup)*, anyAttribute?))))");
12341     }
12342     /*
12343     * REDEFINE: SPEC src-redefine (5)
12344     */
12345     if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12346     xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
12347         NULL, node, "This is a redefinition, thus the "
12348         "<complexType> must have a <restriction> or <extension> "
12349         "grand-child", NULL);
12350     }
12351     ctxt->ctxtType = ctxtType;
12352     return (type);
12353 }
12354 
12355 /************************************************************************
12356  *                                  *
12357  *          Validating using Schemas            *
12358  *                                  *
12359  ************************************************************************/
12360 
12361 /************************************************************************
12362  *                                  *
12363  *          Reading/Writing Schemas             *
12364  *                                  *
12365  ************************************************************************/
12366 
12367 #if 0 /* Will be enabled if it is clear what options are needed. */
12368 
12378 static int
12379 xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12380                   int options)
12381 
12382 {
12383     int i;
12384 
12385     if (ctxt == NULL)
12386     return (-1);
12387     /*
12388     * WARNING: Change the start value if adding to the
12389     * xmlSchemaParseOption.
12390     */
12391     for (i = 1; i < (int) sizeof(int) * 8; i++) {
12392         if (options & 1<<i) {
12393         return (-1);
12394         }
12395     }
12396     ctxt->options = options;
12397     return (0);
12398 }
12399 
12406 static int
12407 xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
12408 
12409 {
12410     if (ctxt == NULL)
12411     return (-1);
12412     else
12413     return (ctxt->options);
12414 }
12415 #endif
12416 
12426 xmlSchemaParserCtxtPtr
12427 xmlSchemaNewParserCtxt(const char *URL)
12428 {
12429     xmlSchemaParserCtxtPtr ret;
12430 
12431     if (URL == NULL)
12432         return (NULL);
12433 
12434     ret = xmlSchemaParserCtxtCreate();
12435     if (ret == NULL)
12436     return(NULL);
12437     ret->dict = xmlDictCreate();
12438     ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
12439     return (ret);
12440 }
12441 
12452 xmlSchemaParserCtxtPtr
12453 xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12454 {
12455     xmlSchemaParserCtxtPtr ret;
12456 
12457     if ((buffer == NULL) || (size <= 0))
12458         return (NULL);
12459     ret = xmlSchemaParserCtxtCreate();
12460     if (ret == NULL)
12461     return(NULL);
12462     ret->buffer = buffer;
12463     ret->size = size;
12464     ret->dict = xmlDictCreate();
12465     return (ret);
12466 }
12467 
12477 xmlSchemaParserCtxtPtr
12478 xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12479 {
12480     xmlSchemaParserCtxtPtr ret;
12481 
12482     if (doc == NULL)
12483       return (NULL);
12484     ret = xmlSchemaParserCtxtCreate();
12485     if (ret == NULL)
12486     return(NULL);
12487     ret->doc = doc;
12488     ret->dict = xmlDictCreate();
12489     /* The application has responsibility for the document */
12490     ret->preserve = 1;
12491 
12492     return (ret);
12493 }
12494 
12501 void
12502 xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12503 {
12504     if (ctxt == NULL)
12505         return;
12506     if (ctxt->doc != NULL && !ctxt->preserve)
12507         xmlFreeDoc(ctxt->doc);
12508     if (ctxt->vctxt != NULL) {
12509     xmlSchemaFreeValidCtxt(ctxt->vctxt);
12510     }
12511     if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12512     xmlSchemaConstructionCtxtFree(ctxt->constructor);
12513     ctxt->constructor = NULL;
12514     ctxt->ownsConstructor = 0;
12515     }
12516     if (ctxt->attrProhibs != NULL)
12517     xmlSchemaItemListFree(ctxt->attrProhibs);
12518     xmlDictFree(ctxt->dict);
12519     xmlFree(ctxt);
12520 }
12521 
12522 /************************************************************************
12523  *                                  *
12524  *          Building the content models         *
12525  *                                  *
12526  ************************************************************************/
12527 
12533 static int
12534 xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
12535     xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
12536 {
12537     xmlAutomataStatePtr start, tmp;
12538     xmlSchemaElementPtr elemDecl, member;
12539     xmlSchemaSubstGroupPtr substGroup;
12540     int i;
12541     int ret = 0;
12542 
12543     elemDecl = (xmlSchemaElementPtr) particle->children;
12544     /*
12545     * Wrap the substitution group with a CHOICE.
12546     */
12547     start = pctxt->state;
12548     if (end == NULL)
12549     end = xmlAutomataNewState(pctxt->am);
12550     substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
12551     if (substGroup == NULL) {
12552     xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
12553         XML_SCHEMAP_INTERNAL,
12554         "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12555         "declaration is marked having a subst. group but none "
12556         "available.\n", elemDecl->name, NULL);
12557     return(0);
12558     }
12559     if (counter >= 0) {
12560     /*
12561     * NOTE that we put the declaration in, even if it's abstract.
12562     * However, an error will be raised during *validation* if an element
12563     * information item shall be validated against an abstract element
12564     * declaration.
12565     */
12566     tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12567         xmlAutomataNewTransition2(pctxt->am, tmp, end,
12568                 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12569     /*
12570     * Add subst. group members.
12571     */
12572     for (i = 0; i < substGroup->members->nbItems; i++) {
12573         member = (xmlSchemaElementPtr) substGroup->members->items[i];
12574             xmlAutomataNewTransition2(pctxt->am, tmp, end,
12575                        member->name, member->targetNamespace, member);
12576     }
12577     } else if (particle->maxOccurs == 1) {
12578     /*
12579     * NOTE that we put the declaration in, even if it's abstract,
12580     */
12581     xmlAutomataNewEpsilon(pctxt->am,
12582         xmlAutomataNewTransition2(pctxt->am,
12583         start, NULL,
12584         elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12585     /*
12586     * Add subst. group members.
12587     */
12588     for (i = 0; i < substGroup->members->nbItems; i++) {
12589         member = (xmlSchemaElementPtr) substGroup->members->items[i];
12590         /*
12591         * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2()
12592         *  was incorrectly used instead of xmlAutomataNewTransition2()
12593         *  (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL
12594         *  section in xmlSchemaBuildAContentModel() ).
12595         * TODO: Check if xmlAutomataNewOnceTrans2() was instead
12596         *  intended for the above "counter" section originally. I.e.,
12597         *  check xs:all with subst-groups.
12598         *
12599         * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12600         *                  member->name, member->targetNamespace,
12601         *              1, 1, member);
12602         */
12603         tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL,
12604         member->name, member->targetNamespace, member);
12605         xmlAutomataNewEpsilon(pctxt->am, tmp, end);
12606     }
12607     } else {
12608     xmlAutomataStatePtr hop;
12609     int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12610         UNBOUNDED : particle->maxOccurs - 1;
12611     int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12612 
12613     counter =
12614         xmlAutomataNewCounter(pctxt->am, minOccurs,
12615         maxOccurs);
12616     hop = xmlAutomataNewState(pctxt->am);
12617 
12618     xmlAutomataNewEpsilon(pctxt->am,
12619         xmlAutomataNewTransition2(pctxt->am,
12620         start, NULL,
12621         elemDecl->name, elemDecl->targetNamespace, elemDecl),
12622         hop);
12623     /*
12624      * Add subst. group members.
12625      */
12626     for (i = 0; i < substGroup->members->nbItems; i++) {
12627         member = (xmlSchemaElementPtr) substGroup->members->items[i];
12628         xmlAutomataNewEpsilon(pctxt->am,
12629         xmlAutomataNewTransition2(pctxt->am,
12630         start, NULL,
12631         member->name, member->targetNamespace, member),
12632         hop);
12633     }
12634     xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12635     xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12636     }
12637     if (particle->minOccurs == 0) {
12638     xmlAutomataNewEpsilon(pctxt->am, start, end);
12639         ret = 1;
12640     }
12641     pctxt->state = end;
12642     return(ret);
12643 }
12644 
12650 static int
12651 xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12652                      xmlSchemaParticlePtr particle)
12653 {
12654     int ret = 0;
12655 
12656     if (((xmlSchemaElementPtr) particle->children)->flags &
12657     XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12658     /*
12659     * Substitution groups.
12660     */
12661     ret = xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
12662     } else {
12663     xmlSchemaElementPtr elemDecl;
12664     xmlAutomataStatePtr start;
12665 
12666     elemDecl = (xmlSchemaElementPtr) particle->children;
12667 
12668     if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
12669         return(0);
12670     if (particle->maxOccurs == 1) {
12671         start = ctxt->state;
12672         ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12673             elemDecl->name, elemDecl->targetNamespace, elemDecl);
12674     } else if ((particle->maxOccurs >= UNBOUNDED) &&
12675                (particle->minOccurs < 2)) {
12676         /* Special case. */
12677         start = ctxt->state;
12678         ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12679         elemDecl->name, elemDecl->targetNamespace, elemDecl);
12680         ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
12681         elemDecl->name, elemDecl->targetNamespace, elemDecl);
12682     } else {
12683         int counter;
12684         int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12685                 UNBOUNDED : particle->maxOccurs - 1;
12686         int minOccurs = particle->minOccurs < 1 ?
12687                 0 : particle->minOccurs - 1;
12688 
12689         start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
12690         counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12691         ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12692         elemDecl->name, elemDecl->targetNamespace, elemDecl);
12693         xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12694         ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12695         NULL, counter);
12696     }
12697     if (particle->minOccurs == 0) {
12698         xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12699             ret = 1;
12700         }
12701     }
12702     return(ret);
12703 }
12704 
12715 static int
12716 xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
12717                 xmlSchemaParticlePtr particle)
12718 {
12719     int ret = 0, tmp2;
12720 
12721     if (particle == NULL) {
12722     PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
12723     return(1);
12724     }
12725     if (particle->children == NULL) {
12726     /*
12727     * Just return in this case. A missing "term" of the particle
12728     * might arise due to an invalid "term" component.
12729     */
12730     return(1);
12731     }
12732 
12733     switch (particle->children->type) {
12734     case XML_SCHEMA_TYPE_ANY: {
12735         xmlAutomataStatePtr start, end;
12736         xmlSchemaWildcardPtr wild;
12737         xmlSchemaWildcardNsPtr ns;
12738 
12739         wild = (xmlSchemaWildcardPtr) particle->children;
12740 
12741         start = pctxt->state;
12742         end = xmlAutomataNewState(pctxt->am);
12743 
12744         if (particle->maxOccurs == 1) {
12745         if (wild->any == 1) {
12746             /*
12747             * We need to add both transitions:
12748             *
12749             * 1. the {"*", "*"} for elements in a namespace.
12750             */
12751             pctxt->state =
12752             xmlAutomataNewTransition2(pctxt->am,
12753             start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12754             xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12755             /*
12756             * 2. the {"*"} for elements in no namespace.
12757             */
12758             pctxt->state =
12759             xmlAutomataNewTransition2(pctxt->am,
12760             start, NULL, BAD_CAST "*", NULL, wild);
12761             xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12762 
12763         } else if (wild->nsSet != NULL) {
12764             ns = wild->nsSet;
12765             do {
12766             pctxt->state = start;
12767             pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12768                 pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12769             xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12770             ns = ns->next;
12771             } while (ns != NULL);
12772 
12773         } else if (wild->negNsSet != NULL) {
12774             pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12775             start, end, BAD_CAST "*", wild->negNsSet->value,
12776             wild);
12777         }
12778         } else {
12779         int counter;
12780         xmlAutomataStatePtr hop;
12781         int maxOccurs =
12782             particle->maxOccurs == UNBOUNDED ? UNBOUNDED :
12783                                            particle->maxOccurs - 1;
12784         int minOccurs =
12785             particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12786 
12787         counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12788         hop = xmlAutomataNewState(pctxt->am);
12789         if (wild->any == 1) {
12790             pctxt->state =
12791             xmlAutomataNewTransition2(pctxt->am,
12792             start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12793             xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12794             pctxt->state =
12795             xmlAutomataNewTransition2(pctxt->am,
12796             start, NULL, BAD_CAST "*", NULL, wild);
12797             xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12798         } else if (wild->nsSet != NULL) {
12799             ns = wild->nsSet;
12800             do {
12801             pctxt->state =
12802                 xmlAutomataNewTransition2(pctxt->am,
12803                 start, NULL, BAD_CAST "*", ns->value, wild);
12804             xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12805             ns = ns->next;
12806             } while (ns != NULL);
12807 
12808         } else if (wild->negNsSet != NULL) {
12809             pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12810             start, hop, BAD_CAST "*", wild->negNsSet->value,
12811             wild);
12812         }
12813         xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12814         xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12815         }
12816         if (particle->minOccurs == 0) {
12817         xmlAutomataNewEpsilon(pctxt->am, start, end);
12818                 ret = 1;
12819         }
12820         pctxt->state = end;
12821             break;
12822     }
12823         case XML_SCHEMA_TYPE_ELEMENT:
12824         ret = xmlSchemaBuildContentModelForElement(pctxt, particle);
12825         break;
12826         case XML_SCHEMA_TYPE_SEQUENCE:{
12827             xmlSchemaTreeItemPtr sub;
12828 
12829             ret = 1;
12830             /*
12831              * If max and min occurances are default (1) then
12832              * simply iterate over the particles of the <sequence>.
12833              */
12834             if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12835                 sub = particle->children->children;
12836 
12837                 while (sub != NULL) {
12838                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
12839                                         (xmlSchemaParticlePtr) sub);
12840                     if (tmp2 != 1) ret = 0;
12841                     sub = sub->next;
12842                 }
12843             } else {
12844                 xmlAutomataStatePtr oldstate = pctxt->state;
12845 
12846                 if (particle->maxOccurs >= UNBOUNDED) {
12847                     if (particle->minOccurs > 1) {
12848                         xmlAutomataStatePtr tmp;
12849                         int counter;
12850 
12851                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12852                             oldstate, NULL);
12853                         oldstate = pctxt->state;
12854 
12855                         counter = xmlAutomataNewCounter(pctxt->am,
12856                             particle->minOccurs - 1, UNBOUNDED);
12857 
12858                         sub = particle->children->children;
12859                         while (sub != NULL) {
12860                             tmp2 = xmlSchemaBuildAContentModel(pctxt,
12861                                             (xmlSchemaParticlePtr) sub);
12862                             if (tmp2 != 1) ret = 0;
12863                             sub = sub->next;
12864                         }
12865                         tmp = pctxt->state;
12866                         xmlAutomataNewCountedTrans(pctxt->am, tmp,
12867                                                    oldstate, counter);
12868                         pctxt->state =
12869                             xmlAutomataNewCounterTrans(pctxt->am, tmp,
12870                                                        NULL, counter);
12871                         if (ret == 1)
12872                             xmlAutomataNewEpsilon(pctxt->am,
12873                                                 oldstate, pctxt->state);
12874 
12875                     } else {
12876                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12877                             oldstate, NULL);
12878                         oldstate = pctxt->state;
12879 
12880                         sub = particle->children->children;
12881                         while (sub != NULL) {
12882                             tmp2 = xmlSchemaBuildAContentModel(pctxt,
12883                                         (xmlSchemaParticlePtr) sub);
12884                             if (tmp2 != 1) ret = 0;
12885                             sub = sub->next;
12886                         }
12887                         xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
12888                                               oldstate);
12889                         /*
12890                          * epsilon needed to block previous trans from
12891                          * being allowed to enter back from another
12892                          * construct
12893                          */
12894                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12895                                             pctxt->state, NULL);
12896                         if (particle->minOccurs == 0) {
12897                             xmlAutomataNewEpsilon(pctxt->am,
12898                                 oldstate, pctxt->state);
12899                             ret = 1;
12900                         }
12901                     }
12902                 } else if ((particle->maxOccurs > 1)
12903                            || (particle->minOccurs > 1)) {
12904                     xmlAutomataStatePtr tmp;
12905                     int counter;
12906 
12907                     pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12908                         oldstate, NULL);
12909                     oldstate = pctxt->state;
12910 
12911                     counter = xmlAutomataNewCounter(pctxt->am,
12912                         particle->minOccurs - 1,
12913                         particle->maxOccurs - 1);
12914 
12915                     sub = particle->children->children;
12916                     while (sub != NULL) {
12917                         tmp2 = xmlSchemaBuildAContentModel(pctxt,
12918                                         (xmlSchemaParticlePtr) sub);
12919                         if (tmp2 != 1) ret = 0;
12920                         sub = sub->next;
12921                     }
12922                     tmp = pctxt->state;
12923                     xmlAutomataNewCountedTrans(pctxt->am,
12924                         tmp, oldstate, counter);
12925                     pctxt->state =
12926                         xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
12927                                                    counter);
12928                     if ((particle->minOccurs == 0) || (ret == 1)) {
12929                         xmlAutomataNewEpsilon(pctxt->am,
12930                                             oldstate, pctxt->state);
12931                         ret = 1;
12932                     }
12933                 } else {
12934                     sub = particle->children->children;
12935                     while (sub != NULL) {
12936                         tmp2 = xmlSchemaBuildAContentModel(pctxt,
12937                                         (xmlSchemaParticlePtr) sub);
12938                         if (tmp2 != 1) ret = 0;
12939                         sub = sub->next;
12940                     }
12941                     if (particle->minOccurs == 0) {
12942                         xmlAutomataNewEpsilon(pctxt->am, oldstate,
12943                                               pctxt->state);
12944                         ret = 1;
12945                     }
12946                 }
12947             }
12948             break;
12949         }
12950         case XML_SCHEMA_TYPE_CHOICE:{
12951             xmlSchemaTreeItemPtr sub;
12952             xmlAutomataStatePtr start, end;
12953 
12954             ret = 0;
12955             start = pctxt->state;
12956             end = xmlAutomataNewState(pctxt->am);
12957 
12958             /*
12959              * iterate over the subtypes and remerge the end with an
12960              * epsilon transition
12961              */
12962             if (particle->maxOccurs == 1) {
12963                 sub = particle->children->children;
12964                 while (sub != NULL) {
12965                     pctxt->state = start;
12966                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
12967                                         (xmlSchemaParticlePtr) sub);
12968                     if (tmp2 == 1) ret = 1;
12969                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12970                     sub = sub->next;
12971                 }
12972             } else {
12973                 int counter;
12974                 xmlAutomataStatePtr hop, base;
12975                 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12976                     UNBOUNDED : particle->maxOccurs - 1;
12977                 int minOccurs =
12978                     particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12979 
12980                 /*
12981                  * use a counter to keep track of the number of transtions
12982                  * which went through the choice.
12983                  */
12984                 counter =
12985                     xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12986                 hop = xmlAutomataNewState(pctxt->am);
12987                 base = xmlAutomataNewState(pctxt->am);
12988 
12989                 sub = particle->children->children;
12990                 while (sub != NULL) {
12991                     pctxt->state = base;
12992                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
12993                                         (xmlSchemaParticlePtr) sub);
12994                     if (tmp2 == 1) ret = 1;
12995                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12996                     sub = sub->next;
12997                 }
12998                 xmlAutomataNewEpsilon(pctxt->am, start, base);
12999                 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
13000                 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
13001                 if (ret == 1)
13002                     xmlAutomataNewEpsilon(pctxt->am, base, end);
13003             }
13004             if (particle->minOccurs == 0) {
13005                 xmlAutomataNewEpsilon(pctxt->am, start, end);
13006                 ret = 1;
13007             }
13008             pctxt->state = end;
13009             break;
13010         }
13011         case XML_SCHEMA_TYPE_ALL:{
13012             xmlAutomataStatePtr start, tmp;
13013             xmlSchemaParticlePtr sub;
13014             xmlSchemaElementPtr elemDecl;
13015 
13016             ret = 1;
13017 
13018             sub = (xmlSchemaParticlePtr) particle->children->children;
13019             if (sub == NULL)
13020                 break;
13021 
13022             ret = 0;
13023 
13024             start = pctxt->state;
13025             tmp = xmlAutomataNewState(pctxt->am);
13026             xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp);
13027             pctxt->state = tmp;
13028             while (sub != NULL) {
13029                 pctxt->state = tmp;
13030 
13031                 elemDecl = (xmlSchemaElementPtr) sub->children;
13032                 if (elemDecl == NULL) {
13033                     PERROR_INT("xmlSchemaBuildAContentModel",
13034                         "<element> particle has no term");
13035                     return(ret);
13036                 };
13037                 /*
13038                 * NOTE: The {max occurs} of all the particles in the
13039                 * {particles} of the group must be 0 or 1; this is
13040                 * already ensured during the parse of the content of
13041                 * <all>.
13042                 */
13043                 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
13044                     int counter;
13045 
13046                     /*
13047                      * This is an abstract group, we need to share
13048                      * the same counter for all the element transitions
13049                      * derived from the group
13050                      */
13051                     counter = xmlAutomataNewCounter(pctxt->am,
13052                                        sub->minOccurs, sub->maxOccurs);
13053                     xmlSchemaBuildContentModelForSubstGroup(pctxt,
13054                                        sub, counter, pctxt->state);
13055                 } else {
13056                     if ((sub->minOccurs == 1) &&
13057                         (sub->maxOccurs == 1)) {
13058                         xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
13059                                                 pctxt->state,
13060                                                 elemDecl->name,
13061                                                 elemDecl->targetNamespace,
13062                                                 1, 1, elemDecl);
13063                     } else if ((sub->minOccurs == 0) &&
13064                         (sub->maxOccurs == 1)) {
13065 
13066                         xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
13067                                                  pctxt->state,
13068                                                  elemDecl->name,
13069                                                  elemDecl->targetNamespace,
13070                                                  0,
13071                                                  1,
13072                                                  elemDecl);
13073                     }
13074                 }
13075                 sub = (xmlSchemaParticlePtr) sub->next;
13076             }
13077             pctxt->state =
13078                 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0);
13079             if (particle->minOccurs == 0) {
13080                 xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state);
13081                 ret = 1;
13082             }
13083             break;
13084         }
13085     case XML_SCHEMA_TYPE_GROUP:
13086         /*
13087         * If we hit a model group definition, then this means that
13088         * it was empty, thus was not substituted for the containing
13089         * model group. Just do nothing in this case.
13090         * TODO: But the group should be substituted and not occur at
13091         * all in the content model at this point. Fix this.
13092         */
13093             ret = 1;
13094         break;
13095         default:
13096         xmlSchemaInternalErr2(ACTXT_CAST pctxt,
13097         "xmlSchemaBuildAContentModel",
13098         "found unexpected term of type '%s' in content model",
13099         WXS_ITEM_TYPE_NAME(particle->children), NULL);
13100             return(ret);
13101     }
13102     return(ret);
13103 }
13104 
13113 static void
13114 xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
13115                xmlSchemaParserCtxtPtr ctxt)
13116 {
13117     if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13118     (type->contModel != NULL) ||
13119     ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13120     (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
13121     return;
13122 
13123 #ifdef DEBUG_CONTENT
13124     xmlGenericError(xmlGenericErrorContext,
13125                     "Building content model for %s\n", name);
13126 #endif
13127     ctxt->am = NULL;
13128     ctxt->am = xmlNewAutomata();
13129     if (ctxt->am == NULL) {
13130         xmlGenericError(xmlGenericErrorContext,
13131         "Cannot create automata for complex type %s\n", type->name);
13132         return;
13133     }
13134     ctxt->state = xmlAutomataGetInitState(ctxt->am);
13135     /*
13136     * Build the automaton.
13137     */
13138     xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
13139     xmlAutomataSetFinalState(ctxt->am, ctxt->state);
13140     type->contModel = xmlAutomataCompile(ctxt->am);
13141     if (type->contModel == NULL) {
13142         xmlSchemaPCustomErr(ctxt,
13143         XML_SCHEMAP_INTERNAL,
13144         WXS_BASIC_CAST type, type->node,
13145         "Failed to compile the content model", NULL);
13146     } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
13147         xmlSchemaPCustomErr(ctxt,
13148         XML_SCHEMAP_NOT_DETERMINISTIC,
13149         /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
13150         WXS_BASIC_CAST type, type->node,
13151         "The content model is not determinist", NULL);
13152     } else {
13153 #ifdef DEBUG_CONTENT_REGEXP
13154         xmlGenericError(xmlGenericErrorContext,
13155                         "Content model of %s:\n", type->name);
13156         xmlRegexpPrint(stderr, type->contModel);
13157 #endif
13158     }
13159     ctxt->state = NULL;
13160     xmlFreeAutomata(ctxt->am);
13161     ctxt->am = NULL;
13162 }
13163 
13173 static void
13174 xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13175                   xmlSchemaParserCtxtPtr ctxt)
13176 {
13177     if ((ctxt == NULL) || (elemDecl == NULL) ||
13178     ((elemDecl != NULL) &&
13179     (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
13180         return;
13181     elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
13182 
13183     if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
13184     xmlSchemaTypePtr type;
13185 
13186     /* (type definition) ... otherwise the type definition �resolved�
13187     * to by the �actual value� of the type [attribute] ...
13188     */
13189     type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
13190         elemDecl->namedTypeNs);
13191     if (type == NULL) {
13192         xmlSchemaPResCompAttrErr(ctxt,
13193         XML_SCHEMAP_SRC_RESOLVE,
13194         WXS_BASIC_CAST elemDecl, elemDecl->node,
13195         "type", elemDecl->namedType, elemDecl->namedTypeNs,
13196         XML_SCHEMA_TYPE_BASIC, "type definition");
13197     } else
13198         elemDecl->subtypes = type;
13199     }
13200     if (elemDecl->substGroup != NULL) {
13201     xmlSchemaElementPtr substHead;
13202 
13203     /*
13204     * FIXME TODO: Do we need a new field in _xmlSchemaElement for
13205     * substitutionGroup?
13206     */
13207     substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13208         elemDecl->substGroupNs);
13209     if (substHead == NULL) {
13210         xmlSchemaPResCompAttrErr(ctxt,
13211         XML_SCHEMAP_SRC_RESOLVE,
13212         WXS_BASIC_CAST elemDecl, NULL,
13213         "substitutionGroup", elemDecl->substGroup,
13214         elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
13215     } else {
13216         xmlSchemaResolveElementReferences(substHead, ctxt);
13217         /*
13218         * Set the "substitution group affiliation".
13219         * NOTE that now we use the "refDecl" field for this.
13220         */
13221         WXS_SUBST_HEAD(elemDecl) = substHead;
13222         /*
13223         * The type definitions is set to:
13224         * SPEC "...the {type definition} of the element
13225         * declaration �resolved� to by the �actual value�
13226         * of the substitutionGroup [attribute], if present"
13227         */
13228         if (elemDecl->subtypes == NULL)
13229         elemDecl->subtypes = substHead->subtypes;
13230     }
13231     }
13232     /*
13233     * SPEC "The definition of anyType serves as the default type definition
13234     * for element declarations whose XML representation does not specify one."
13235     */
13236     if ((elemDecl->subtypes == NULL) &&
13237     (elemDecl->namedType == NULL) &&
13238     (elemDecl->substGroup == NULL))
13239     elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13240 }
13241 
13253 static int
13254 xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13255                  xmlSchemaTypePtr type)
13256 {
13257 
13258     xmlSchemaTypeLinkPtr link, lastLink, newLink;
13259     xmlSchemaTypePtr memberType;
13260 
13261     /*
13262     * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13263     * define the explicit members as the type definitions �resolved�
13264     * to by the items in the �actual value� of the memberTypes [attribute],
13265     * if any, followed by the type definitions corresponding to the
13266     * <simpleType>s among the [children] of <union>, if any."
13267     */
13268     /*
13269     * Resolve references.
13270     */
13271     link = type->memberTypes;
13272     lastLink = NULL;
13273     while (link != NULL) {
13274     const xmlChar *name, *nsName;
13275 
13276     name = ((xmlSchemaQNameRefPtr) link->type)->name;
13277     nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13278 
13279     memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
13280     if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
13281         xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
13282         WXS_BASIC_CAST type, type->node, "memberTypes",
13283         name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13284         /*
13285         * Remove the member type link.
13286         */
13287         if (lastLink == NULL)
13288         type->memberTypes = link->next;
13289         else
13290         lastLink->next = link->next;
13291         newLink = link;
13292         link = link->next;
13293         xmlFree(newLink);
13294     } else {
13295         link->type = memberType;
13296         lastLink = link;
13297         link = link->next;
13298     }
13299     }
13300     /*
13301     * Add local simple types,
13302     */
13303     memberType = type->subtypes;
13304     while (memberType != NULL) {
13305     link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13306     if (link == NULL) {
13307         xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13308         return (-1);
13309     }
13310     link->type = memberType;
13311     link->next = NULL;
13312     if (lastLink == NULL)
13313         type->memberTypes = link;
13314     else
13315         lastLink->next = link;
13316     lastLink = link;
13317     memberType = memberType->next;
13318     }
13319     return (0);
13320 }
13321 
13332 static int
13333 xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13334 {
13335     if (type == NULL)
13336     return (0);
13337     if (WXS_IS_COMPLEX(type))
13338     return (0);
13339     if (type->type == XML_SCHEMA_TYPE_BASIC) {
13340     if (type->builtInType == valType)
13341         return(1);
13342     if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13343         (type->builtInType == XML_SCHEMAS_ANYTYPE))
13344         return (0);
13345     return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13346     }
13347     return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13348 }
13349 
13350 #if 0
13351 
13361 static int
13362 xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13363 {
13364     if (type == NULL)
13365     return (0);
13366     if (WXS_IS_COMPLEX(type))
13367     return (0);
13368     if (type->type == XML_SCHEMA_TYPE_BASIC) {
13369     if (type->builtInType == valType)
13370         return(1);
13371     return (0);
13372     } else
13373     return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13374 
13375     return (0);
13376 }
13377 
13378 static xmlSchemaTypePtr
13379 xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13380 {
13381     if (type == NULL)
13382     return (NULL);
13383     if (WXS_IS_COMPLEX(type))
13384     return (NULL);
13385     if (type->type == XML_SCHEMA_TYPE_BASIC)
13386     return(type);
13387     return(xmlSchemaQueryBuiltInType(type->subtypes));
13388 }
13389 #endif
13390 
13398 static xmlSchemaTypePtr
13399 xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13400 {
13401 
13402     while (type != NULL) {
13403     /*
13404     * Note that anySimpleType is actually not a primitive type
13405     * but we need that here.
13406     */
13407     if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13408        (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
13409         return (type);
13410     type = type->baseType;
13411     }
13412 
13413     return (NULL);
13414 }
13415 
13416 #if 0
13417 
13424 static xmlSchemaTypePtr
13425 xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13426 {
13427     if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
13428     return (0);
13429     while (type != NULL) {
13430     if (type->type == XML_SCHEMA_TYPE_BASIC)
13431         return (type);
13432     type = type->baseType;
13433     }
13434 
13435     return (NULL);
13436 }
13437 #endif
13438 
13449 static int
13450 xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
13451                     xmlSchemaWildcardPtr dest,
13452                     xmlSchemaWildcardPtr source)
13453 {
13454     xmlSchemaWildcardNsPtr cur, tmp, last;
13455 
13456     if ((source == NULL) || (dest == NULL))
13457     return(-1);
13458     dest->any = source->any;
13459     cur = source->nsSet;
13460     last = NULL;
13461     while (cur != NULL) {
13462     tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13463     if (tmp == NULL)
13464         return(-1);
13465     tmp->value = cur->value;
13466     if (last == NULL)
13467         dest->nsSet = tmp;
13468     else
13469         last->next = tmp;
13470     last = tmp;
13471     cur = cur->next;
13472     }
13473     if (dest->negNsSet != NULL)
13474     xmlSchemaFreeWildcardNsSet(dest->negNsSet);
13475     if (source->negNsSet != NULL) {
13476     dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13477     if (dest->negNsSet == NULL)
13478         return(-1);
13479     dest->negNsSet->value = source->negNsSet->value;
13480     } else
13481     dest->negNsSet = NULL;
13482     return(0);
13483 }
13484 
13496 static int
13497 xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
13498                 xmlSchemaWildcardPtr completeWild,
13499                 xmlSchemaWildcardPtr curWild)
13500 {
13501     xmlSchemaWildcardNsPtr cur, curB, tmp;
13502 
13503     /*
13504     * 1 If O1 and O2 are the same value, then that value must be the
13505     * value.
13506     */
13507     if ((completeWild->any == curWild->any) &&
13508     ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13509     ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13510 
13511     if ((completeWild->negNsSet == NULL) ||
13512         (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13513 
13514         if (completeWild->nsSet != NULL) {
13515         int found = 0;
13516 
13517         /*
13518         * Check equality of sets.
13519         */
13520         cur = completeWild->nsSet;
13521         while (cur != NULL) {
13522             found = 0;
13523             curB = curWild->nsSet;
13524             while (curB != NULL) {
13525             if (cur->value == curB->value) {
13526                 found = 1;
13527                 break;
13528             }
13529             curB = curB->next;
13530             }
13531             if (!found)
13532             break;
13533             cur = cur->next;
13534         }
13535         if (found)
13536             return(0);
13537         } else
13538         return(0);
13539     }
13540     }
13541     /*
13542     * 2 If either O1 or O2 is any, then any must be the value
13543     */
13544     if (completeWild->any != curWild->any) {
13545     if (completeWild->any == 0) {
13546         completeWild->any = 1;
13547         if (completeWild->nsSet != NULL) {
13548         xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13549         completeWild->nsSet = NULL;
13550         }
13551         if (completeWild->negNsSet != NULL) {
13552         xmlFree(completeWild->negNsSet);
13553         completeWild->negNsSet = NULL;
13554         }
13555     }
13556     return (0);
13557     }
13558     /*
13559     * 3 If both O1 and O2 are sets of (namespace names or �absent�),
13560     * then the union of those sets must be the value.
13561     */
13562     if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13563     int found;
13564     xmlSchemaWildcardNsPtr start;
13565 
13566     cur = curWild->nsSet;
13567     start = completeWild->nsSet;
13568     while (cur != NULL) {
13569         found = 0;
13570         curB = start;
13571         while (curB != NULL) {
13572         if (cur->value == curB->value) {
13573             found = 1;
13574             break;
13575         }
13576         curB = curB->next;
13577         }
13578         if (!found) {
13579         tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13580         if (tmp == NULL)
13581             return (-1);
13582         tmp->value = cur->value;
13583         tmp->next = completeWild->nsSet;
13584         completeWild->nsSet = tmp;
13585         }
13586         cur = cur->next;
13587     }
13588 
13589     return(0);
13590     }
13591     /*
13592     * 4 If the two are negations of different values (namespace names
13593     * or �absent�), then a pair of not and �absent� must be the value.
13594     */
13595     if ((completeWild->negNsSet != NULL) &&
13596     (curWild->negNsSet != NULL) &&
13597     (completeWild->negNsSet->value != curWild->negNsSet->value)) {
13598     completeWild->negNsSet->value = NULL;
13599 
13600     return(0);
13601     }
13602     /*
13603      * 5.
13604      */
13605     if (((completeWild->negNsSet != NULL) &&
13606     (completeWild->negNsSet->value != NULL) &&
13607     (curWild->nsSet != NULL)) ||
13608     ((curWild->negNsSet != NULL) &&
13609     (curWild->negNsSet->value != NULL) &&
13610     (completeWild->nsSet != NULL))) {
13611 
13612     int nsFound, absentFound = 0;
13613 
13614     if (completeWild->nsSet != NULL) {
13615         cur = completeWild->nsSet;
13616         curB = curWild->negNsSet;
13617     } else {
13618         cur = curWild->nsSet;
13619         curB = completeWild->negNsSet;
13620     }
13621     nsFound = 0;
13622     while (cur != NULL) {
13623         if (cur->value == NULL)
13624         absentFound = 1;
13625         else if (cur->value == curB->value)
13626         nsFound = 1;
13627         if (nsFound && absentFound)
13628         break;
13629         cur = cur->next;
13630     }
13631 
13632     if (nsFound && absentFound) {
13633         /*
13634         * 5.1 If the set S includes both the negated namespace
13635         * name and �absent�, then any must be the value.
13636         */
13637         completeWild->any = 1;
13638         if (completeWild->nsSet != NULL) {
13639         xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13640         completeWild->nsSet = NULL;
13641         }
13642         if (completeWild->negNsSet != NULL) {
13643         xmlFree(completeWild->negNsSet);
13644         completeWild->negNsSet = NULL;
13645         }
13646     } else if (nsFound && (!absentFound)) {
13647         /*
13648         * 5.2 If the set S includes the negated namespace name
13649         * but not �absent�, then a pair of not and �absent� must
13650         * be the value.
13651         */
13652         if (completeWild->nsSet != NULL) {
13653         xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13654         completeWild->nsSet = NULL;
13655         }
13656         if (completeWild->negNsSet == NULL) {
13657         completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13658         if (completeWild->negNsSet == NULL)
13659             return (-1);
13660         }
13661         completeWild->negNsSet->value = NULL;
13662     } else if ((!nsFound) && absentFound) {
13663         /*
13664         * 5.3 If the set S includes �absent� but not the negated
13665         * namespace name, then the union is not expressible.
13666         */
13667         xmlSchemaPErr(ctxt, completeWild->node,
13668         XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
13669         "The union of the wilcard is not expressible.\n",
13670         NULL, NULL);
13671         return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
13672     } else if ((!nsFound) && (!absentFound)) {
13673         /*
13674         * 5.4 If the set S does not include either the negated namespace
13675         * name or �absent�, then whichever of O1 or O2 is a pair of not
13676         * and a namespace name must be the value.
13677         */
13678         if (completeWild->negNsSet == NULL) {
13679         if (completeWild->nsSet != NULL) {
13680             xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13681             completeWild->nsSet = NULL;
13682         }
13683         completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13684         if (completeWild->negNsSet == NULL)
13685             return (-1);
13686         completeWild->negNsSet->value = curWild->negNsSet->value;
13687         }
13688     }
13689     return (0);
13690     }
13691     /*
13692      * 6.
13693      */
13694     if (((completeWild->negNsSet != NULL) &&
13695     (completeWild->negNsSet->value == NULL) &&
13696     (curWild->nsSet != NULL)) ||
13697     ((curWild->negNsSet != NULL) &&
13698     (curWild->negNsSet->value == NULL) &&
13699     (completeWild->nsSet != NULL))) {
13700 
13701     if (completeWild->nsSet != NULL) {
13702         cur = completeWild->nsSet;
13703     } else {
13704         cur = curWild->nsSet;
13705     }
13706     while (cur != NULL) {
13707         if (cur->value == NULL) {
13708         /*
13709         * 6.1 If the set S includes �absent�, then any must be the
13710         * value.
13711         */
13712         completeWild->any = 1;
13713         if (completeWild->nsSet != NULL) {
13714             xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13715             completeWild->nsSet = NULL;
13716         }
13717         if (completeWild->negNsSet != NULL) {
13718             xmlFree(completeWild->negNsSet);
13719             completeWild->negNsSet = NULL;
13720         }
13721         return (0);
13722         }
13723         cur = cur->next;
13724     }
13725     if (completeWild->negNsSet == NULL) {
13726         /*
13727         * 6.2 If the set S does not include �absent�, then a pair of not
13728         * and �absent� must be the value.
13729         */
13730         if (completeWild->nsSet != NULL) {
13731         xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13732         completeWild->nsSet = NULL;
13733         }
13734         completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13735         if (completeWild->negNsSet == NULL)
13736         return (-1);
13737         completeWild->negNsSet->value = NULL;
13738     }
13739     return (0);
13740     }
13741     return (0);
13742 
13743 }
13744 
13756 static int
13757 xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
13758                 xmlSchemaWildcardPtr completeWild,
13759                 xmlSchemaWildcardPtr curWild)
13760 {
13761     xmlSchemaWildcardNsPtr cur, curB, prev,  tmp;
13762 
13763     /*
13764     * 1 If O1 and O2 are the same value, then that value must be the
13765     * value.
13766     */
13767     if ((completeWild->any == curWild->any) &&
13768     ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13769     ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13770 
13771     if ((completeWild->negNsSet == NULL) ||
13772         (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13773 
13774         if (completeWild->nsSet != NULL) {
13775         int found = 0;
13776 
13777         /*
13778         * Check equality of sets.
13779         */
13780         cur = completeWild->nsSet;
13781         while (cur != NULL) {
13782             found = 0;
13783             curB = curWild->nsSet;
13784             while (curB != NULL) {
13785             if (cur->value == curB->value) {
13786                 found = 1;
13787                 break;
13788             }
13789             curB = curB->next;
13790             }
13791             if (!found)
13792             break;
13793             cur = cur->next;
13794         }
13795         if (found)
13796             return(0);
13797         } else
13798         return(0);
13799     }
13800     }
13801     /*
13802     * 2 If either O1 or O2 is any, then the other must be the value.
13803     */
13804     if ((completeWild->any != curWild->any) && (completeWild->any)) {
13805     if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13806         return(-1);
13807     return(0);
13808     }
13809     /*
13810     * 3 If either O1 or O2 is a pair of not and a value (a namespace
13811     * name or �absent�) and the other is a set of (namespace names or
13812     * �absent�), then that set, minus the negated value if it was in
13813     * the set, minus �absent� if it was in the set, must be the value.
13814     */
13815     if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13816     ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13817     const xmlChar *neg;
13818 
13819     if (completeWild->nsSet == NULL) {
13820         neg = completeWild->negNsSet->value;
13821         if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13822         return(-1);
13823     } else
13824         neg = curWild->negNsSet->value;
13825     /*
13826     * Remove absent and negated.
13827     */
13828     prev = NULL;
13829     cur = completeWild->nsSet;
13830     while (cur != NULL) {
13831         if (cur->value == NULL) {
13832         if (prev == NULL)
13833             completeWild->nsSet = cur->next;
13834         else
13835             prev->next = cur->next;
13836         xmlFree(cur);
13837         break;
13838         }
13839         prev = cur;
13840         cur = cur->next;
13841     }
13842     if (neg != NULL) {
13843         prev = NULL;
13844         cur = completeWild->nsSet;
13845         while (cur != NULL) {
13846         if (cur->value == neg) {
13847             if (prev == NULL)
13848             completeWild->nsSet = cur->next;
13849             else
13850             prev->next = cur->next;
13851             xmlFree(cur);
13852             break;
13853         }
13854         prev = cur;
13855         cur = cur->next;
13856         }
13857     }
13858 
13859     return(0);
13860     }
13861     /*
13862     * 4 If both O1 and O2 are sets of (namespace names or �absent�),
13863     * then the intersection of those sets must be the value.
13864     */
13865     if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13866     int found;
13867 
13868     cur = completeWild->nsSet;
13869     prev = NULL;
13870     while (cur != NULL) {
13871         found = 0;
13872         curB = curWild->nsSet;
13873         while (curB != NULL) {
13874         if (cur->value == curB->value) {
13875             found = 1;
13876             break;
13877         }
13878         curB = curB->next;
13879         }
13880         if (!found) {
13881         if (prev == NULL)
13882             completeWild->nsSet = cur->next;
13883         else
13884             prev->next = cur->next;
13885         tmp = cur->next;
13886         xmlFree(cur);
13887         cur = tmp;
13888         continue;
13889         }
13890         prev = cur;
13891         cur = cur->next;
13892     }
13893 
13894     return(0);
13895     }
13896     /* 5 If the two are negations of different namespace names,
13897     * then the intersection is not expressible
13898     */
13899     if ((completeWild->negNsSet != NULL) &&
13900     (curWild->negNsSet != NULL) &&
13901     (completeWild->negNsSet->value != curWild->negNsSet->value) &&
13902     (completeWild->negNsSet->value != NULL) &&
13903     (curWild->negNsSet->value != NULL)) {
13904 
13905     xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
13906         "The intersection of the wilcard is not expressible.\n",
13907         NULL, NULL);
13908     return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
13909     }
13910     /*
13911     * 6 If the one is a negation of a namespace name and the other
13912     * is a negation of �absent�, then the one which is the negation
13913     * of a namespace name must be the value.
13914     */
13915     if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
13916     (completeWild->negNsSet->value != curWild->negNsSet->value) &&
13917     (completeWild->negNsSet->value == NULL)) {
13918     completeWild->negNsSet->value =  curWild->negNsSet->value;
13919     }
13920     return(0);
13921 }
13922 
13934 static int
13935 xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
13936               xmlSchemaWildcardPtr super)
13937 {
13938     /*
13939     * 1 super must be any.
13940     */
13941     if (super->any)
13942     return (0);
13943     /*
13944     * 2.1 sub must be a pair of not and a namespace name or �absent�.
13945     * 2.2 super must be a pair of not and the same value.
13946     */
13947     if ((sub->negNsSet != NULL) &&
13948     (super->negNsSet != NULL) &&
13949     (sub->negNsSet->value == sub->negNsSet->value))
13950     return (0);
13951     /*
13952     * 3.1 sub must be a set whose members are either namespace names or �absent�.
13953     */
13954     if (sub->nsSet != NULL) {
13955     /*
13956     * 3.2.1 super must be the same set or a superset thereof.
13957     */
13958     if (super->nsSet != NULL) {
13959         xmlSchemaWildcardNsPtr cur, curB;
13960         int found = 0;
13961 
13962         cur = sub->nsSet;
13963         while (cur != NULL) {
13964         found = 0;
13965         curB = super->nsSet;
13966         while (curB != NULL) {
13967             if (cur->value == curB->value) {
13968             found = 1;
13969             break;
13970             }
13971             curB = curB->next;
13972         }
13973         if (!found)
13974             return (1);
13975         cur = cur->next;
13976         }
13977         if (found)
13978         return (0);
13979     } else if (super->negNsSet != NULL) {
13980         xmlSchemaWildcardNsPtr cur;
13981         /*
13982         * 3.2.2 super must be a pair of not and a namespace name or
13983         * �absent� and that value must not be in sub's set.
13984         */
13985         cur = sub->nsSet;
13986         while (cur != NULL) {
13987         if (cur->value == super->negNsSet->value)
13988             return (1);
13989         cur = cur->next;
13990         }
13991         return (0);
13992     }
13993     }
13994     return (1);
13995 }
13996 
13997 static int
13998 xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
13999                      int *fixed,
14000                      const xmlChar **value,
14001                      xmlSchemaValPtr *val)
14002 {
14003     *fixed = 0;
14004     *value = NULL;
14005     if (val != 0)
14006     *val = NULL;
14007 
14008     if (attruse->defValue != NULL) {
14009     *value = attruse->defValue;
14010     if (val != NULL)
14011         *val = attruse->defVal;
14012     if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
14013         *fixed = 1;
14014     return(1);
14015     } else if ((attruse->attrDecl != NULL) &&
14016     (attruse->attrDecl->defValue != NULL)) {
14017     *value = attruse->attrDecl->defValue;
14018     if (val != NULL)
14019         *val = attruse->attrDecl->defVal;
14020     if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
14021         *fixed = 1;
14022     return(1);
14023     }
14024     return(0);
14025 }
14037 static int
14038 xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
14039                    const xmlChar* ns)
14040 {
14041     if (wild == NULL)
14042     return(-1);
14043 
14044     if (wild->any)
14045     return(0);
14046     else if (wild->nsSet != NULL) {
14047     xmlSchemaWildcardNsPtr cur;
14048 
14049     cur = wild->nsSet;
14050     while (cur != NULL) {
14051         if (xmlStrEqual(cur->value, ns))
14052         return(0);
14053         cur = cur->next;
14054     }
14055     } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
14056     (!xmlStrEqual(wild->negNsSet->value, ns)))
14057     return(0);
14058 
14059     return(1);
14060 }
14061 
14062 #define XML_SCHEMA_ACTION_DERIVE 0
14063 #define XML_SCHEMA_ACTION_REDEFINE 1
14064 
14065 #define WXS_ACTION_STR(a) \
14066 ((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
14067 
14068 /*
14069 * Schema Component Constraint:
14070 *   Derivation Valid (Restriction, Complex)
14071 *   derivation-ok-restriction (2) - (4)
14072 *
14073 * ATTENTION:
14074 * In XML Schema 1.1 this will be:
14075 * Validation Rule:
14076 *     Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
14077 *
14078 */
14079 static int
14080 xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
14081                        int action,
14082                        xmlSchemaBasicItemPtr item,
14083                        xmlSchemaBasicItemPtr baseItem,
14084                        xmlSchemaItemListPtr uses,
14085                        xmlSchemaItemListPtr baseUses,
14086                        xmlSchemaWildcardPtr wild,
14087                        xmlSchemaWildcardPtr baseWild)
14088 {
14089     xmlSchemaAttributeUsePtr cur = NULL, bcur;
14090     int i, j, found; /* err = 0; */
14091     const xmlChar *bEffValue;
14092     int effFixed;
14093 
14094     if (uses != NULL) {
14095     for (i = 0; i < uses->nbItems; i++) {
14096         cur = uses->items[i];
14097         found = 0;
14098         if (baseUses == NULL)
14099         goto not_found;
14100         for (j = 0; j < baseUses->nbItems; j++) {
14101         bcur = baseUses->items[j];
14102         if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14103             WXS_ATTRUSE_DECL_NAME(bcur)) &&
14104             (WXS_ATTRUSE_DECL_TNS(cur) ==
14105             WXS_ATTRUSE_DECL_TNS(bcur)))
14106         {
14107             /*
14108             * (2.1) "If there is an attribute use in the {attribute
14109             * uses} of the {base type definition} (call this B) whose
14110             * {attribute declaration} has the same {name} and {target
14111             * namespace}, then  all of the following must be true:"
14112             */
14113             found = 1;
14114 
14115             if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14116             (bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14117             {
14118             xmlChar *str = NULL;
14119             /*
14120             * (2.1.1) "one of the following must be true:"
14121             * (2.1.1.1) "B's {required} is false."
14122             * (2.1.1.2) "R's {required} is true."
14123             */
14124             xmlSchemaPAttrUseErr4(pctxt,
14125                 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14126                 WXS_ITEM_NODE(item), item, cur,
14127                 "The 'optional' attribute use is inconsistent "
14128                 "with the corresponding 'required' attribute use of "
14129                 "the %s %s",
14130                 WXS_ACTION_STR(action),
14131                 xmlSchemaGetComponentDesignation(&str, baseItem),
14132                 NULL, NULL);
14133             FREE_AND_NULL(str);
14134             /* err = pctxt->err; */
14135             } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
14136             WXS_ATTRUSE_TYPEDEF(cur),
14137             WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14138             {
14139             xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14140 
14141             /*
14142             * SPEC (2.1.2) "R's {attribute declaration}'s
14143             * {type definition} must be validly derived from
14144             * B's {type definition} given the empty set as
14145             * defined in Type Derivation OK (Simple) (�3.14.6)."
14146             */
14147             xmlSchemaPAttrUseErr4(pctxt,
14148                 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14149                 WXS_ITEM_NODE(item), item, cur,
14150                 "The attribute declaration's %s "
14151                 "is not validly derived from "
14152                 "the corresponding %s of the "
14153                 "attribute declaration in the %s %s",
14154                 xmlSchemaGetComponentDesignation(&strA,
14155                 WXS_ATTRUSE_TYPEDEF(cur)),
14156                 xmlSchemaGetComponentDesignation(&strB,
14157                 WXS_ATTRUSE_TYPEDEF(bcur)),
14158                 WXS_ACTION_STR(action),
14159                 xmlSchemaGetComponentDesignation(&strC, baseItem));
14160                 /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14161             FREE_AND_NULL(strA);
14162             FREE_AND_NULL(strB);
14163             FREE_AND_NULL(strC);
14164             /* err = pctxt->err; */
14165             } else {
14166             /*
14167             * 2.1.3 [Definition:]  Let the effective value
14168             * constraint of an attribute use be its {value
14169             * constraint}, if present, otherwise its {attribute
14170             * declaration}'s {value constraint} .
14171             */
14172             xmlSchemaGetEffectiveValueConstraint(bcur,
14173                 &effFixed, &bEffValue, NULL);
14174             /*
14175             * 2.1.3 ... one of the following must be true
14176             *
14177             * 2.1.3.1 B's �effective value constraint� is
14178             * �absent� or default.
14179             */
14180             if ((bEffValue != NULL) &&
14181                 (effFixed == 1)) {
14182                 const xmlChar *rEffValue = NULL;
14183 
14184                 xmlSchemaGetEffectiveValueConstraint(bcur,
14185                 &effFixed, &rEffValue, NULL);
14186                 /*
14187                 * 2.1.3.2 R's �effective value constraint� is
14188                 * fixed with the same string as B's.
14189                 * MAYBE TODO: Compare the computed values.
14190                 *       Hmm, it says "same string" so
14191                 *       string-equality might really be sufficient.
14192                 */
14193                 if ((effFixed == 0) ||
14194                 (! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14195                 {
14196                 xmlChar *str = NULL;
14197 
14198                 xmlSchemaPAttrUseErr4(pctxt,
14199                     XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14200                     WXS_ITEM_NODE(item), item, cur,
14201                     "The effective value constraint of the "
14202                     "attribute use is inconsistent with "
14203                     "its correspondent in the %s %s",
14204                     WXS_ACTION_STR(action),
14205                     xmlSchemaGetComponentDesignation(&str,
14206                     baseItem),
14207                     NULL, NULL);
14208                 FREE_AND_NULL(str);
14209                 /* err = pctxt->err; */
14210                 }
14211             }
14212             }
14213             break;
14214         }
14215         }
14216 not_found:
14217         if (!found) {
14218         /*
14219         * (2.2) "otherwise the {base type definition} must have an
14220         * {attribute wildcard} and the {target namespace} of the
14221         * R's {attribute declaration} must be �valid� with respect
14222         * to that wildcard, as defined in Wildcard allows Namespace
14223         * Name (�3.10.4)."
14224         */
14225         if ((baseWild == NULL) ||
14226             (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14227             (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14228         {
14229             xmlChar *str = NULL;
14230 
14231             xmlSchemaPAttrUseErr4(pctxt,
14232             XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14233             WXS_ITEM_NODE(item), item, cur,
14234             "Neither a matching attribute use, "
14235             "nor a matching wildcard exists in the %s %s",
14236             WXS_ACTION_STR(action),
14237             xmlSchemaGetComponentDesignation(&str, baseItem),
14238             NULL, NULL);
14239             FREE_AND_NULL(str);
14240             /* err = pctxt->err; */
14241         }
14242         }
14243     }
14244     }
14245     /*
14246     * SPEC derivation-ok-restriction (3):
14247     * (3) "For each attribute use in the {attribute uses} of the {base type
14248     * definition} whose {required} is true, there must be an attribute
14249     * use with an {attribute declaration} with the same {name} and
14250     * {target namespace} as its {attribute declaration} in the {attribute
14251     * uses} of the complex type definition itself whose {required} is true.
14252     */
14253     if (baseUses != NULL) {
14254     for (j = 0; j < baseUses->nbItems; j++) {
14255         bcur = baseUses->items[j];
14256         if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14257         continue;
14258         found = 0;
14259         if (uses != NULL) {
14260         for (i = 0; i < uses->nbItems; i++) {
14261             cur = uses->items[i];
14262             if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14263             WXS_ATTRUSE_DECL_NAME(bcur)) &&
14264             (WXS_ATTRUSE_DECL_TNS(cur) ==
14265             WXS_ATTRUSE_DECL_TNS(bcur))) {
14266             found = 1;
14267             break;
14268             }
14269         }
14270         }
14271         if (!found) {
14272         xmlChar *strA = NULL, *strB = NULL;
14273 
14274         xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14275             XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14276             NULL, item,
14277             "A matching attribute use for the "
14278             "'required' %s of the %s %s is missing",
14279             xmlSchemaGetComponentDesignation(&strA, bcur),
14280             WXS_ACTION_STR(action),
14281             xmlSchemaGetComponentDesignation(&strB, baseItem),
14282             NULL);
14283         FREE_AND_NULL(strA);
14284         FREE_AND_NULL(strB);
14285         }
14286     }
14287     }
14288     /*
14289     * derivation-ok-restriction (4)
14290     */
14291     if (wild != NULL) {
14292     /*
14293     * (4) "If there is an {attribute wildcard}, all of the
14294     * following must be true:"
14295     */
14296     if (baseWild == NULL) {
14297         xmlChar *str = NULL;
14298 
14299         /*
14300         * (4.1) "The {base type definition} must also have one."
14301         */
14302         xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14303         XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14304         NULL, item,
14305         "The %s has an attribute wildcard, "
14306         "but the %s %s '%s' does not have one",
14307         WXS_ITEM_TYPE_NAME(item),
14308         WXS_ACTION_STR(action),
14309         WXS_ITEM_TYPE_NAME(baseItem),
14310         xmlSchemaGetComponentQName(&str, baseItem));
14311         FREE_AND_NULL(str);
14312         return(pctxt->err);
14313     } else if ((baseWild->any == 0) &&
14314         xmlSchemaCheckCOSNSSubset(wild, baseWild))
14315     {
14316         xmlChar *str = NULL;
14317         /*
14318         * (4.2) "The complex type definition's {attribute wildcard}'s
14319         * {namespace constraint} must be a subset of the {base type
14320         * definition}'s {attribute wildcard}'s {namespace constraint},
14321         * as defined by Wildcard Subset (�3.10.6)."
14322         */
14323         xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14324         XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14325         NULL, item,
14326         "The attribute wildcard is not a valid "
14327         "subset of the wildcard in the %s %s '%s'",
14328         WXS_ACTION_STR(action),
14329         WXS_ITEM_TYPE_NAME(baseItem),
14330         xmlSchemaGetComponentQName(&str, baseItem),
14331         NULL);
14332         FREE_AND_NULL(str);
14333         return(pctxt->err);
14334     }
14335     /* 4.3 Unless the {base type definition} is the �ur-type
14336     * definition�, the complex type definition's {attribute
14337     * wildcard}'s {process contents} must be identical to or
14338     * stronger than the {base type definition}'s {attribute
14339     * wildcard}'s {process contents}, where strict is stronger
14340     * than lax is stronger than skip.
14341     */
14342     if ((! WXS_IS_ANYTYPE(baseItem)) &&
14343         (wild->processContents < baseWild->processContents)) {
14344         xmlChar *str = NULL;
14345         xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14346         XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14347         NULL, baseItem,
14348         "The {process contents} of the attribute wildcard is "
14349         "weaker than the one in the %s %s '%s'",
14350         WXS_ACTION_STR(action),
14351         WXS_ITEM_TYPE_NAME(baseItem),
14352         xmlSchemaGetComponentQName(&str, baseItem),
14353         NULL);
14354         FREE_AND_NULL(str)
14355         return(pctxt->err);
14356     }
14357     }
14358     return(0);
14359 }
14360 
14361 
14362 static int
14363 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14364                   xmlSchemaBasicItemPtr item,
14365                   xmlSchemaWildcardPtr *completeWild,
14366                   xmlSchemaItemListPtr list,
14367                   xmlSchemaItemListPtr prohibs);
14382 static int
14383 xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
14384                   xmlSchemaTypePtr type)
14385 {
14386     xmlSchemaTypePtr baseType = NULL;
14387     xmlSchemaAttributeUsePtr use;
14388     xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
14389 
14390     if (type->baseType == NULL) {
14391     PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14392         "no base type");
14393         return (-1);
14394     }
14395     baseType = type->baseType;
14396     if (WXS_IS_TYPE_NOT_FIXED(baseType))
14397     if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
14398         return(-1);
14399 
14400     uses = type->attrUses;
14401     baseUses = baseType->attrUses;
14402     /*
14403     * Expand attribute group references. And build the 'complete'
14404     * wildcard, i.e. intersect multiple wildcards.
14405     * Move attribute prohibitions into a separate list.
14406     */
14407     if (uses != NULL) {
14408     if (WXS_IS_RESTRICTION(type)) {
14409         /*
14410         * This one will transfer all attr. prohibitions
14411         * into pctxt->attrProhibs.
14412         */
14413         if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14414         WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14415         pctxt->attrProhibs) == -1)
14416         {
14417         PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14418         "failed to expand attributes");
14419         }
14420         if (pctxt->attrProhibs->nbItems != 0)
14421         prohibs = pctxt->attrProhibs;
14422     } else {
14423         if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14424         WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14425         NULL) == -1)
14426         {
14427         PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14428         "failed to expand attributes");
14429         }
14430     }
14431     }
14432     /*
14433     * Inherit the attribute uses of the base type.
14434     */
14435     if (baseUses != NULL) {
14436     int i, j;
14437     xmlSchemaAttributeUseProhibPtr pro;
14438 
14439     if (WXS_IS_RESTRICTION(type)) {
14440         int usesCount;
14441         xmlSchemaAttributeUsePtr tmp;
14442 
14443         if (uses != NULL)
14444         usesCount = uses->nbItems;
14445         else
14446         usesCount = 0;
14447 
14448         /* Restriction. */
14449         for (i = 0; i < baseUses->nbItems; i++) {
14450         use = baseUses->items[i];
14451         if (prohibs) {
14452             /*
14453             * Filter out prohibited uses.
14454             */
14455             for (j = 0; j < prohibs->nbItems; j++) {
14456             pro = prohibs->items[j];
14457             if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14458                 (WXS_ATTRUSE_DECL_TNS(use) ==
14459                 pro->targetNamespace))
14460             {
14461                 goto inherit_next;
14462             }
14463             }
14464         }
14465         if (usesCount) {
14466             /*
14467             * Filter out existing uses.
14468             */
14469             for (j = 0; j < usesCount; j++) {
14470             tmp = uses->items[j];
14471             if ((WXS_ATTRUSE_DECL_NAME(use) ==
14472                 WXS_ATTRUSE_DECL_NAME(tmp)) &&
14473                 (WXS_ATTRUSE_DECL_TNS(use) ==
14474                 WXS_ATTRUSE_DECL_TNS(tmp)))
14475             {
14476                 goto inherit_next;
14477             }
14478             }
14479         }
14480         if (uses == NULL) {
14481             type->attrUses = xmlSchemaItemListCreate();
14482             if (type->attrUses == NULL)
14483             goto exit_failure;
14484             uses = type->attrUses;
14485         }
14486         xmlSchemaItemListAddSize(uses, 2, use);
14487 inherit_next: {}
14488         }
14489     } else {
14490         /* Extension. */
14491         for (i = 0; i < baseUses->nbItems; i++) {
14492         use = baseUses->items[i];
14493         if (uses == NULL) {
14494             type->attrUses = xmlSchemaItemListCreate();
14495             if (type->attrUses == NULL)
14496             goto exit_failure;
14497             uses = type->attrUses;
14498         }
14499         xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14500         }
14501     }
14502     }
14503     /*
14504     * Shrink attr. uses.
14505     */
14506     if (uses) {
14507     if (uses->nbItems == 0) {
14508         xmlSchemaItemListFree(uses);
14509         type->attrUses = NULL;
14510     }
14511     /*
14512     * TODO: We could shrink the size of the array
14513     * to fit the actual number of items.
14514     */
14515     }
14516     /*
14517     * Compute the complete wildcard.
14518     */
14519     if (WXS_IS_EXTENSION(type)) {
14520     if (baseType->attributeWildcard != NULL) {
14521         /*
14522         * (3.2.2.1) "If the �base wildcard� is non-�absent�, then
14523         * the appropriate case among the following:"
14524         */
14525         if (type->attributeWildcard != NULL) {
14526         /*
14527         * Union the complete wildcard with the base wildcard.
14528         * SPEC {attribute wildcard}
14529         * (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14530         * and {annotation} are those of the �complete wildcard�,
14531         * and whose {namespace constraint} is the intensional union
14532         * of the {namespace constraint} of the �complete wildcard�
14533         * and of the �base wildcard�, as defined in Attribute
14534         * Wildcard Union (�3.10.6)."
14535         */
14536         if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14537             baseType->attributeWildcard) == -1)
14538             goto exit_failure;
14539         } else {
14540         /*
14541         * (3.2.2.1.1) "If the �complete wildcard� is �absent�,
14542         * then the �base wildcard�."
14543         */
14544         type->attributeWildcard = baseType->attributeWildcard;
14545         }
14546     } else {
14547         /*
14548         * (3.2.2.2) "otherwise (the �base wildcard� is �absent�) the
14549         * �complete wildcard"
14550         * NOOP
14551         */
14552     }
14553     } else {
14554     /*
14555     * SPEC {attribute wildcard}
14556     * (3.1) "If the <restriction> alternative is chosen, then the
14557     * �complete wildcard�;"
14558     * NOOP
14559     */
14560     }
14561 
14562     return (0);
14563 
14564 exit_failure:
14565     return(-1);
14566 }
14567 
14580 static int
14581 xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
14582 {
14583     if (type == NULL)
14584     return (0);
14585     if (type->flags & final)
14586     return (1);
14587     else
14588     return (0);
14589 }
14590 
14598 static xmlSchemaTypeLinkPtr
14599 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14600 {
14601     while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
14602     if (type->memberTypes != NULL)
14603         return (type->memberTypes);
14604     else
14605         type = type->baseType;
14606     }
14607     return (NULL);
14608 }
14609 
14619 static int
14620 xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
14621 {
14622     if ((particle->children == NULL) ||
14623     (particle->minOccurs == 0))
14624     return (0);
14625     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14626     int min = -1, cur;
14627     xmlSchemaParticlePtr part =
14628         (xmlSchemaParticlePtr) particle->children->children;
14629 
14630     if (part == NULL)
14631         return (0);
14632     while (part != NULL) {
14633         if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14634         (part->children->type == XML_SCHEMA_TYPE_ANY))
14635         cur = part->minOccurs;
14636         else
14637         cur = xmlSchemaGetParticleTotalRangeMin(part);
14638         if (cur == 0)
14639         return (0);
14640         if ((min > cur) || (min == -1))
14641         min = cur;
14642         part = (xmlSchemaParticlePtr) part->next;
14643     }
14644     return (particle->minOccurs * min);
14645     } else {
14646     /* <all> and <sequence> */
14647     int sum = 0;
14648     xmlSchemaParticlePtr part =
14649         (xmlSchemaParticlePtr) particle->children->children;
14650 
14651     if (part == NULL)
14652         return (0);
14653     do {
14654         if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14655         (part->children->type == XML_SCHEMA_TYPE_ANY))
14656         sum += part->minOccurs;
14657         else
14658         sum += xmlSchemaGetParticleTotalRangeMin(part);
14659         part = (xmlSchemaParticlePtr) part->next;
14660     } while (part != NULL);
14661     return (particle->minOccurs * sum);
14662     }
14663 }
14664 
14665 #if 0
14666 
14675 static int
14676 xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14677 {
14678     if ((particle->children == NULL) ||
14679     (particle->children->children == NULL))
14680     return (0);
14681     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14682     int max = -1, cur;
14683     xmlSchemaParticlePtr part =
14684         (xmlSchemaParticlePtr) particle->children->children;
14685 
14686     for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14687         if (part->children == NULL)
14688         continue;
14689         if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14690         (part->children->type == XML_SCHEMA_TYPE_ANY))
14691         cur = part->maxOccurs;
14692         else
14693         cur = xmlSchemaGetParticleTotalRangeMax(part);
14694         if (cur == UNBOUNDED)
14695         return (UNBOUNDED);
14696         if ((max < cur) || (max == -1))
14697         max = cur;
14698     }
14699     /* TODO: Handle overflows? */
14700     return (particle->maxOccurs * max);
14701     } else {
14702     /* <all> and <sequence> */
14703     int sum = 0, cur;
14704     xmlSchemaParticlePtr part =
14705         (xmlSchemaParticlePtr) particle->children->children;
14706 
14707     for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14708         if (part->children == NULL)
14709         continue;
14710         if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14711         (part->children->type == XML_SCHEMA_TYPE_ANY))
14712         cur = part->maxOccurs;
14713         else
14714         cur = xmlSchemaGetParticleTotalRangeMax(part);
14715         if (cur == UNBOUNDED)
14716         return (UNBOUNDED);
14717         if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14718         return (UNBOUNDED);
14719         sum += cur;
14720     }
14721     /* TODO: Handle overflows? */
14722     return (particle->maxOccurs * sum);
14723     }
14724 }
14725 #endif
14726 
14736 static int
14737 xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14738 {
14739     /*
14740     * SPEC (1) "Its {min occurs} is 0."
14741     */
14742     if ((particle == NULL) || (particle->minOccurs == 0) ||
14743     (particle->children == NULL))
14744     return (1);
14745     /*
14746     * SPEC (2) "Its {term} is a group and the minimum part of the
14747     * effective total range of that group, [...] is 0."
14748     */
14749     if (WXS_IS_MODEL_GROUP(particle->children)) {
14750     if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
14751         return (1);
14752     }
14753     return (0);
14754 }
14755 
14771 static int
14772 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
14773                  xmlSchemaTypePtr type,
14774                  xmlSchemaTypePtr baseType,
14775                  int subset)
14776 {
14777     /*
14778     * 1 They are the same type definition.
14779     * TODO: The identy check might have to be more complex than this.
14780     */
14781     if (type == baseType)
14782     return (0);
14783     /*
14784     * 2.1 restriction is not in the subset, or in the {final}
14785     * of its own {base type definition};
14786     *
14787     * NOTE that this will be used also via "xsi:type".
14788     *
14789     * TODO: Revise this, it looks strange. How can the "type"
14790     * not be fixed or *in* fixing?
14791     */
14792     if (WXS_IS_TYPE_NOT_FIXED(type))
14793     if (xmlSchemaTypeFixup(type, actxt) == -1)
14794         return(-1);
14795     if (WXS_IS_TYPE_NOT_FIXED(baseType))
14796     if (xmlSchemaTypeFixup(baseType, actxt) == -1)
14797         return(-1);
14798     if ((subset & SUBSET_RESTRICTION) ||
14799     (xmlSchemaTypeFinalContains(type->baseType,
14800         XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14801     return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
14802     }
14803     /* 2.2 */
14804     if (type->baseType == baseType) {
14805     /*
14806     * 2.2.1 D's �base type definition� is B.
14807     */
14808     return (0);
14809     }
14810     /*
14811     * 2.2.2 D's �base type definition� is not the �ur-type definition�
14812     * and is validly derived from B given the subset, as defined by this
14813     * constraint.
14814     */
14815     if ((! WXS_IS_ANYTYPE(type->baseType)) &&
14816     (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
14817         baseType, subset) == 0)) {
14818     return (0);
14819     }
14820     /*
14821     * 2.2.3 D's {variety} is list or union and B is the �simple ur-type
14822     * definition�.
14823     */
14824     if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14825     (WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
14826     return (0);
14827     }
14828     /*
14829     * 2.2.4 B's {variety} is union and D is validly derived from a type
14830     * definition in B's {member type definitions} given the subset, as
14831     * defined by this constraint.
14832     *
14833     * NOTE: This seems not to involve built-in types, since there is no
14834     * built-in Union Simple Type.
14835     */
14836     if (WXS_IS_UNION(baseType)) {
14837     xmlSchemaTypeLinkPtr cur;
14838 
14839     cur = baseType->memberTypes;
14840     while (cur != NULL) {
14841         if (WXS_IS_TYPE_NOT_FIXED(cur->type))
14842         if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
14843             return(-1);
14844         if (xmlSchemaCheckCOSSTDerivedOK(actxt,
14845             type, cur->type, subset) == 0)
14846         {
14847         /*
14848         * It just has to be validly derived from at least one
14849         * member-type.
14850         */
14851         return (0);
14852         }
14853         cur = cur->next;
14854     }
14855     }
14856     return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14857 }
14858 
14871 static int
14872 xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14873                xmlSchemaTypePtr ctxtType,
14874                xmlSchemaTypePtr ancestor)
14875 {
14876     int ret;
14877 
14878     if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14879     return (0);
14880 
14881     if (ctxtType == ancestor) {
14882     xmlSchemaPCustomErr(pctxt,
14883         XML_SCHEMAP_ST_PROPS_CORRECT_2,
14884         WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
14885         "The definition is circular", NULL);
14886     return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14887     }
14888     if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14889     /*
14890     * Avoid inifinite recursion on circular types not yet checked.
14891     */
14892     return (0);
14893     }
14894     ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14895     ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14896     ancestor->baseType);
14897     ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14898     return (ret);
14899 }
14900 
14909 static void
14910 xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
14911                   xmlSchemaParserCtxtPtr ctxt)
14912 {
14913     if ((item == NULL) ||
14914     (item->type == XML_SCHEMA_TYPE_BASIC) ||
14915     (item->baseType == NULL))
14916     return;
14917     xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
14918     item->baseType);
14919 }
14920 
14921 /*
14922 * Simple Type Definition Representation OK (src-simple-type) 4
14923 *
14924 * "4 Circular union type definition is disallowed. That is, if the
14925 * <union> alternative is chosen, there must not be any entries in the
14926 * memberTypes [attribute] at any depth which resolve to the component
14927 * corresponding to the <simpleType>."
14928 *
14929 * Note that this should work on the *representation* of a component,
14930 * thus assumes any union types in the member types not being yet
14931 * substituted. At this stage we need the variety of the types
14932 * to be already computed.
14933 */
14934 static int
14935 xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
14936                     xmlSchemaTypePtr ctxType,
14937                     xmlSchemaTypeLinkPtr members)
14938 {
14939     xmlSchemaTypeLinkPtr member;
14940     xmlSchemaTypePtr memberType;
14941 
14942     member = members;
14943     while (member != NULL) {
14944     memberType = member->type;
14945     while ((memberType != NULL) &&
14946         (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
14947         if (memberType == ctxType) {
14948         xmlSchemaPCustomErr(pctxt,
14949             XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
14950             WXS_BASIC_CAST ctxType, NULL,
14951             "The union type definition is circular", NULL);
14952         return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
14953         }
14954         if ((WXS_IS_UNION(memberType)) &&
14955         ((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
14956         {
14957         int res;
14958         memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
14959         res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
14960             ctxType,
14961             xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
14962         memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
14963         if (res != 0)
14964             return(res);
14965         }
14966         memberType = memberType->baseType;
14967     }
14968     member = member->next;
14969     }
14970     return(0);
14971 }
14972 
14973 static int
14974 xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
14975                    xmlSchemaTypePtr type)
14976 {
14977     if (! WXS_IS_UNION(type))
14978     return(0);
14979     return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
14980     type->memberTypes));
14981 }
14982 
14991 static void
14992 xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
14993              xmlSchemaParserCtxtPtr ctxt)
14994 {
14995     if (typeDef == NULL)
14996     return;
14997 
14998     /*
14999     * Resolve the base type.
15000     */
15001     if (typeDef->baseType == NULL) {
15002     typeDef->baseType = xmlSchemaGetType(ctxt->schema,
15003         typeDef->base, typeDef->baseNs);
15004     if (typeDef->baseType == NULL) {
15005         xmlSchemaPResCompAttrErr(ctxt,
15006         XML_SCHEMAP_SRC_RESOLVE,
15007         WXS_BASIC_CAST typeDef, typeDef->node,
15008         "base", typeDef->base, typeDef->baseNs,
15009         XML_SCHEMA_TYPE_SIMPLE, NULL);
15010         return;
15011     }
15012     }
15013     if (WXS_IS_SIMPLE(typeDef)) {
15014     if (WXS_IS_UNION(typeDef)) {
15015         /*
15016         * Resolve the memberTypes.
15017         */
15018         xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
15019         return;
15020     } else if (WXS_IS_LIST(typeDef)) {
15021         /*
15022         * Resolve the itemType.
15023         */
15024         if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
15025 
15026         typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
15027             typeDef->base, typeDef->baseNs);
15028 
15029         if ((typeDef->subtypes == NULL) ||
15030             (! WXS_IS_SIMPLE(typeDef->subtypes)))
15031         {
15032             typeDef->subtypes = NULL;
15033             xmlSchemaPResCompAttrErr(ctxt,
15034             XML_SCHEMAP_SRC_RESOLVE,
15035             WXS_BASIC_CAST typeDef, typeDef->node,
15036             "itemType", typeDef->base, typeDef->baseNs,
15037             XML_SCHEMA_TYPE_SIMPLE, NULL);
15038         }
15039         }
15040         return;
15041     }
15042     }
15043     /*
15044     * The ball of letters below means, that if we have a particle
15045     * which has a QName-helper component as its {term}, we want
15046     * to resolve it...
15047     */
15048     else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
15049     ((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
15050         XML_SCHEMA_TYPE_PARTICLE) &&
15051     (WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
15052     ((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
15053         XML_SCHEMA_EXTRA_QNAMEREF))
15054     {
15055     xmlSchemaQNameRefPtr ref =
15056         WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
15057     xmlSchemaModelGroupDefPtr groupDef;
15058 
15059     /*
15060     * URGENT TODO: Test this.
15061     */
15062     WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
15063     /*
15064     * Resolve the MG definition reference.
15065     */
15066     groupDef =
15067         WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
15068         ref->itemType, ref->name, ref->targetNamespace);
15069     if (groupDef == NULL) {
15070         xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
15071         NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
15072         "ref", ref->name, ref->targetNamespace, ref->itemType,
15073         NULL);
15074         /* Remove the particle. */
15075         WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15076     } else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
15077         /* Remove the particle. */
15078         WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15079     else {
15080         /*
15081         * Assign the MG definition's {model group} to the
15082         * particle's {term}.
15083         */
15084         WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
15085 
15086         if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
15087         /*
15088         * SPEC cos-all-limited (1.2)
15089         * "1.2 the {term} property of a particle with
15090         * {max occurs}=1 which is part of a pair which constitutes
15091         * the {content type} of a complex type definition."
15092         */
15093         if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
15094             xmlSchemaCustomErr(ACTXT_CAST ctxt,
15095             /* TODO: error code */
15096             XML_SCHEMAP_COS_ALL_LIMITED,
15097             WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
15098             "The particle's {max occurs} must be 1, since the "
15099             "reference resolves to an 'all' model group",
15100             NULL, NULL);
15101         }
15102         }
15103     }
15104     }
15105 }
15106 
15107 
15108 
15120 static int
15121 xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
15122                  xmlSchemaTypePtr type)
15123 {
15124     xmlSchemaTypePtr baseType = type->baseType;
15125     xmlChar *str = NULL;
15126 
15127     /* STATE: error funcs converted. */
15128     /*
15129     * Schema Component Constraint: Simple Type Definition Properties Correct
15130     *
15131     * NOTE: This is somehow redundant, since we actually built a simple type
15132     * to have all the needed information; this acts as an self test.
15133     */
15134     /* Base type: If the datatype has been �derived� by �restriction�
15135     * then the Simple Type Definition component from which it is �derived�,
15136     * otherwise the Simple Type Definition for anySimpleType (�4.1.6).
15137     */
15138     if (baseType == NULL) {
15139     /*
15140     * TODO: Think about: "modulo the impact of Missing
15141     * Sub-components (�5.3)."
15142     */
15143     xmlSchemaPCustomErr(ctxt,
15144         XML_SCHEMAP_ST_PROPS_CORRECT_1,
15145         WXS_BASIC_CAST type, NULL,
15146         "No base type existent", NULL);
15147     return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15148 
15149     }
15150     if (! WXS_IS_SIMPLE(baseType)) {
15151     xmlSchemaPCustomErr(ctxt,
15152         XML_SCHEMAP_ST_PROPS_CORRECT_1,
15153         WXS_BASIC_CAST type, NULL,
15154         "The base type '%s' is not a simple type",
15155         xmlSchemaGetComponentQName(&str, baseType));
15156     FREE_AND_NULL(str)
15157     return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15158     }
15159     if ( (WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
15160      (WXS_IS_RESTRICTION(type) == 0) &&
15161      (! WXS_IS_ANY_SIMPLE_TYPE(baseType))) {
15162     xmlSchemaPCustomErr(ctxt,
15163         XML_SCHEMAP_ST_PROPS_CORRECT_1,
15164         WXS_BASIC_CAST type, NULL,
15165         "A type, derived by list or union, must have "
15166         "the simple ur-type definition as base type, not '%s'",
15167         xmlSchemaGetComponentQName(&str, baseType));
15168     FREE_AND_NULL(str)
15169     return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15170     }
15171     /*
15172     * Variety: One of {atomic, list, union}.
15173     */
15174     if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15175     (! WXS_IS_LIST(type))) {
15176     xmlSchemaPCustomErr(ctxt,
15177         XML_SCHEMAP_ST_PROPS_CORRECT_1,
15178         WXS_BASIC_CAST type, NULL,
15179         "The variety is absent", NULL);
15180     return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15181     }
15182     /* TODO: Finish this. Hmm, is this finished? */
15183 
15184     /*
15185     * 3 The {final} of the {base type definition} must not contain restriction.
15186     */
15187     if (xmlSchemaTypeFinalContains(baseType,
15188     XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15189     xmlSchemaPCustomErr(ctxt,
15190         XML_SCHEMAP_ST_PROPS_CORRECT_3,
15191         WXS_BASIC_CAST type, NULL,
15192         "The 'final' of its base type '%s' must not contain "
15193         "'restriction'",
15194         xmlSchemaGetComponentQName(&str, baseType));
15195     FREE_AND_NULL(str)
15196     return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
15197     }
15198 
15199     /*
15200     * 2 All simple type definitions must be derived ultimately from the �simple
15201     * ur-type definition (so� circular definitions are disallowed). That is, it
15202     * must be possible to reach a built-in primitive datatype or the �simple
15203     * ur-type definition� by repeatedly following the {base type definition}.
15204     *
15205     * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
15206     */
15207     return (0);
15208 }
15209 
15224 static int
15225 xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
15226                  xmlSchemaTypePtr type)
15227 {
15228     xmlChar *str = NULL;
15229 
15230     if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
15231     PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15232         "given type is not a user-derived simpleType");
15233     return (-1);
15234     }
15235 
15236     if (WXS_IS_ATOMIC(type)) {
15237     xmlSchemaTypePtr primitive;
15238     /*
15239     * 1.1 The {base type definition} must be an atomic simple
15240     * type definition or a built-in primitive datatype.
15241     */
15242     if (! WXS_IS_ATOMIC(type->baseType)) {
15243         xmlSchemaPCustomErr(pctxt,
15244         XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
15245         WXS_BASIC_CAST type, NULL,
15246         "The base type '%s' is not an atomic simple type",
15247         xmlSchemaGetComponentQName(&str, type->baseType));
15248         FREE_AND_NULL(str)
15249         return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15250     }
15251     /* 1.2 The {final} of the {base type definition} must not contain
15252     * restriction.
15253     */
15254     /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
15255     if (xmlSchemaTypeFinalContains(type->baseType,
15256         XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15257         xmlSchemaPCustomErr(pctxt,
15258         XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
15259         WXS_BASIC_CAST type, NULL,
15260         "The final of its base type '%s' must not contain 'restriction'",
15261         xmlSchemaGetComponentQName(&str, type->baseType));
15262         FREE_AND_NULL(str)
15263         return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15264     }
15265 
15266     /*
15267     * 1.3.1 DF must be an allowed constraining facet for the {primitive
15268     * type definition}, as specified in the appropriate subsection of 3.2
15269     * Primitive datatypes.
15270     */
15271     if (type->facets != NULL) {
15272         xmlSchemaFacetPtr facet;
15273         int ok = 1;
15274 
15275         primitive = xmlSchemaGetPrimitiveType(type);
15276         if (primitive == NULL) {
15277         PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15278             "failed to get primitive type");
15279         return (-1);
15280         }
15281         facet = type->facets;
15282         do {
15283         if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
15284             ok = 0;
15285             xmlSchemaPIllegalFacetAtomicErr(pctxt,
15286             XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
15287             type, primitive, facet);
15288         }
15289         facet = facet->next;
15290         } while (facet != NULL);
15291         if (ok == 0)
15292         return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
15293     }
15294     /*
15295     * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15296     * of the {base type definition} (call this BF),then the DF's {value}
15297     * must be a valid restriction of BF's {value} as defined in
15298     * [XML Schemas: Datatypes]."
15299     *
15300     * NOTE (1.3.2) Facet derivation constraints are currently handled in
15301     * xmlSchemaDeriveAndValidateFacets()
15302     */
15303     } else if (WXS_IS_LIST(type)) {
15304     xmlSchemaTypePtr itemType = NULL;
15305 
15306     itemType = type->subtypes;
15307     if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
15308         PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15309         "failed to evaluate the item type");
15310         return (-1);
15311     }
15312     if (WXS_IS_TYPE_NOT_FIXED(itemType))
15313         xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
15314     /*
15315     * 2.1 The {item type definition} must have a {variety} of atomic or
15316     * union (in which case all the {member type definitions}
15317     * must be atomic).
15318     */
15319     if ((! WXS_IS_ATOMIC(itemType)) &&
15320         (! WXS_IS_UNION(itemType))) {
15321         xmlSchemaPCustomErr(pctxt,
15322         XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15323         WXS_BASIC_CAST type, NULL,
15324         "The item type '%s' does not have a variety of atomic or union",
15325         xmlSchemaGetComponentQName(&str, itemType));
15326         FREE_AND_NULL(str)
15327         return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15328     } else if (WXS_IS_UNION(itemType)) {
15329         xmlSchemaTypeLinkPtr member;
15330 
15331         member = itemType->memberTypes;
15332         while (member != NULL) {
15333         if (! WXS_IS_ATOMIC(member->type)) {
15334             xmlSchemaPCustomErr(pctxt,
15335             XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15336             WXS_BASIC_CAST type, NULL,
15337             "The item type is a union type, but the "
15338             "member type '%s' of this item type is not atomic",
15339             xmlSchemaGetComponentQName(&str, member->type));
15340             FREE_AND_NULL(str)
15341             return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15342         }
15343         member = member->next;
15344         }
15345     }
15346 
15347     if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
15348         xmlSchemaFacetPtr facet;
15349         /*
15350         * This is the case if we have: <simpleType><list ..
15351         */
15352         /*
15353         * 2.3.1
15354         * 2.3.1.1 The {final} of the {item type definition} must not
15355         * contain list.
15356         */
15357         if (xmlSchemaTypeFinalContains(itemType,
15358         XML_SCHEMAS_TYPE_FINAL_LIST)) {
15359         xmlSchemaPCustomErr(pctxt,
15360             XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
15361             WXS_BASIC_CAST type, NULL,
15362             "The final of its item type '%s' must not contain 'list'",
15363             xmlSchemaGetComponentQName(&str, itemType));
15364         FREE_AND_NULL(str)
15365         return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15366         }
15367         /*
15368         * 2.3.1.2 The {facets} must only contain the whiteSpace
15369         * facet component.
15370         * OPTIMIZE TODO: the S4S already disallows any facet
15371         * to be specified.
15372         */
15373         if (type->facets != NULL) {
15374         facet = type->facets;
15375         do {
15376             if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15377             xmlSchemaPIllegalFacetListUnionErr(pctxt,
15378                 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
15379                 type, facet);
15380             return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15381             }
15382             facet = facet->next;
15383         } while (facet != NULL);
15384         }
15385         /*
15386         * MAYBE TODO: (Hmm, not really) Datatypes states:
15387         * A �list� datatype can be �derived� from an �atomic� datatype
15388         * whose �lexical space� allows space (such as string or anyURI)or
15389         * a �union� datatype any of whose {member type definitions}'s
15390         * �lexical space� allows space.
15391         */
15392     } else {
15393         /*
15394         * This is the case if we have: <simpleType><restriction ...
15395         * I.e. the variety of "list" is inherited.
15396         */
15397         /*
15398         * 2.3.2
15399         * 2.3.2.1 The {base type definition} must have a {variety} of list.
15400         */
15401         if (! WXS_IS_LIST(type->baseType)) {
15402         xmlSchemaPCustomErr(pctxt,
15403             XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
15404             WXS_BASIC_CAST type, NULL,
15405             "The base type '%s' must be a list type",
15406             xmlSchemaGetComponentQName(&str, type->baseType));
15407         FREE_AND_NULL(str)
15408         return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15409         }
15410         /*
15411         * 2.3.2.2 The {final} of the {base type definition} must not
15412         * contain restriction.
15413         */
15414         if (xmlSchemaTypeFinalContains(type->baseType,
15415         XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15416         xmlSchemaPCustomErr(pctxt,
15417             XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
15418             WXS_BASIC_CAST type, NULL,
15419             "The 'final' of the base type '%s' must not contain 'restriction'",
15420             xmlSchemaGetComponentQName(&str, type->baseType));
15421         FREE_AND_NULL(str)
15422         return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15423         }
15424         /*
15425         * 2.3.2.3 The {item type definition} must be validly derived
15426         * from the {base type definition}'s {item type definition} given
15427         * the empty set, as defined in Type Derivation OK (Simple) (�3.14.6).
15428         */
15429         {
15430         xmlSchemaTypePtr baseItemType;
15431 
15432         baseItemType = type->baseType->subtypes;
15433         if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
15434             PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15435             "failed to eval the item type of a base type");
15436             return (-1);
15437         }
15438         if ((itemType != baseItemType) &&
15439             (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
15440             baseItemType, 0) != 0)) {
15441             xmlChar *strBIT = NULL, *strBT = NULL;
15442             xmlSchemaPCustomErrExt(pctxt,
15443             XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
15444             WXS_BASIC_CAST type, NULL,
15445             "The item type '%s' is not validly derived from "
15446             "the item type '%s' of the base type '%s'",
15447             xmlSchemaGetComponentQName(&str, itemType),
15448             xmlSchemaGetComponentQName(&strBIT, baseItemType),
15449             xmlSchemaGetComponentQName(&strBT, type->baseType));
15450 
15451             FREE_AND_NULL(str)
15452             FREE_AND_NULL(strBIT)
15453             FREE_AND_NULL(strBT)
15454             return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15455         }
15456         }
15457 
15458         if (type->facets != NULL) {
15459         xmlSchemaFacetPtr facet;
15460         int ok = 1;
15461         /*
15462         * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
15463         * and enumeration facet components are allowed among the {facets}.
15464         */
15465         facet = type->facets;
15466         do {
15467             switch (facet->type) {
15468             case XML_SCHEMA_FACET_LENGTH:
15469             case XML_SCHEMA_FACET_MINLENGTH:
15470             case XML_SCHEMA_FACET_MAXLENGTH:
15471             case XML_SCHEMA_FACET_WHITESPACE:
15472                 /*
15473                 * TODO: 2.5.1.2 List datatypes
15474                 * The value of �whiteSpace� is fixed to the value collapse.
15475                 */
15476             case XML_SCHEMA_FACET_PATTERN:
15477             case XML_SCHEMA_FACET_ENUMERATION:
15478                 break;
15479             default: {
15480                 xmlSchemaPIllegalFacetListUnionErr(pctxt,
15481                 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
15482                 type, facet);
15483                 /*
15484                 * We could return, but it's nicer to report all
15485                 * invalid facets.
15486                 */
15487                 ok = 0;
15488             }
15489             }
15490             facet = facet->next;
15491         } while (facet != NULL);
15492         if (ok == 0)
15493             return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15494         /*
15495         * SPEC (2.3.2.5) (same as 1.3.2)
15496         *
15497         * NOTE (2.3.2.5) This is currently done in
15498         * xmlSchemaDeriveAndValidateFacets()
15499         */
15500         }
15501     }
15502     } else if (WXS_IS_UNION(type)) {
15503     /*
15504     * 3.1 The {member type definitions} must all have {variety} of
15505     * atomic or list.
15506     */
15507     xmlSchemaTypeLinkPtr member;
15508 
15509     member = type->memberTypes;
15510     while (member != NULL) {
15511         if (WXS_IS_TYPE_NOT_FIXED(member->type))
15512         xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
15513 
15514         if ((! WXS_IS_ATOMIC(member->type)) &&
15515         (! WXS_IS_LIST(member->type))) {
15516         xmlSchemaPCustomErr(pctxt,
15517             XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
15518             WXS_BASIC_CAST type, NULL,
15519             "The member type '%s' is neither an atomic, nor a list type",
15520             xmlSchemaGetComponentQName(&str, member->type));
15521         FREE_AND_NULL(str)
15522         return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15523         }
15524         member = member->next;
15525     }
15526     /*
15527     * 3.3.1 If the {base type definition} is the �simple ur-type
15528     * definition�
15529     */
15530     if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
15531         /*
15532         * 3.3.1.1 All of the {member type definitions} must have a
15533         * {final} which does not contain union.
15534         */
15535         member = type->memberTypes;
15536         while (member != NULL) {
15537         if (xmlSchemaTypeFinalContains(member->type,
15538             XML_SCHEMAS_TYPE_FINAL_UNION)) {
15539             xmlSchemaPCustomErr(pctxt,
15540             XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
15541             WXS_BASIC_CAST type, NULL,
15542             "The 'final' of member type '%s' contains 'union'",
15543             xmlSchemaGetComponentQName(&str, member->type));
15544             FREE_AND_NULL(str)
15545             return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15546         }
15547         member = member->next;
15548         }
15549         /*
15550         * 3.3.1.2 The {facets} must be empty.
15551         */
15552         if (type->facetSet != NULL) {
15553         xmlSchemaPCustomErr(pctxt,
15554             XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
15555             WXS_BASIC_CAST type, NULL,
15556             "No facets allowed", NULL);
15557         return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15558         }
15559     } else {
15560         /*
15561         * 3.3.2.1 The {base type definition} must have a {variety} of union.
15562         * I.e. the variety of "list" is inherited.
15563         */
15564         if (! WXS_IS_UNION(type->baseType)) {
15565         xmlSchemaPCustomErr(pctxt,
15566             XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
15567             WXS_BASIC_CAST type, NULL,
15568             "The base type '%s' is not a union type",
15569             xmlSchemaGetComponentQName(&str, type->baseType));
15570         FREE_AND_NULL(str)
15571         return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15572         }
15573         /*
15574         * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15575         */
15576         if (xmlSchemaTypeFinalContains(type->baseType,
15577         XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15578         xmlSchemaPCustomErr(pctxt,
15579             XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
15580             WXS_BASIC_CAST type, NULL,
15581             "The 'final' of its base type '%s' must not contain 'restriction'",
15582             xmlSchemaGetComponentQName(&str, type->baseType));
15583         FREE_AND_NULL(str)
15584         return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15585         }
15586         /*
15587         * 3.3.2.3 The {member type definitions}, in order, must be validly
15588         * derived from the corresponding type definitions in the {base
15589         * type definition}'s {member type definitions} given the empty set,
15590         * as defined in Type Derivation OK (Simple) (�3.14.6).
15591         */
15592         {
15593         xmlSchemaTypeLinkPtr baseMember;
15594 
15595         /*
15596         * OPTIMIZE: if the type is restricting, it has no local defined
15597         * member types and inherits the member types of the base type;
15598         * thus a check for equality can be skipped.
15599         */
15600         /*
15601         * Even worse: I cannot see a scenario where a restricting
15602         * union simple type can have other member types as the member
15603         * types of it's base type. This check seems not necessary with
15604         * respect to the derivation process in libxml2.
15605         * But necessary if constructing types with an API.
15606         */
15607         if (type->memberTypes != NULL) {
15608             member = type->memberTypes;
15609             baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
15610             if ((member == NULL) && (baseMember != NULL)) {
15611             PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15612                 "different number of member types in base");
15613             }
15614             while (member != NULL) {
15615             if (baseMember == NULL) {
15616                 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15617                 "different number of member types in base");
15618             } else if ((member->type != baseMember->type) &&
15619                 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
15620                 member->type, baseMember->type, 0) != 0)) {
15621                 xmlChar *strBMT = NULL, *strBT = NULL;
15622 
15623                 xmlSchemaPCustomErrExt(pctxt,
15624                 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
15625                 WXS_BASIC_CAST type, NULL,
15626                 "The member type %s is not validly "
15627                 "derived from its corresponding member "
15628                 "type %s of the base type %s",
15629                 xmlSchemaGetComponentQName(&str, member->type),
15630                 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15631                 xmlSchemaGetComponentQName(&strBT, type->baseType));
15632                 FREE_AND_NULL(str)
15633                 FREE_AND_NULL(strBMT)
15634                 FREE_AND_NULL(strBT)
15635                 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
15636             }
15637             member = member->next;
15638                         if (baseMember != NULL)
15639                             baseMember = baseMember->next;
15640             }
15641         }
15642         }
15643         /*
15644         * 3.3.2.4 Only pattern and enumeration facet components are
15645         * allowed among the {facets}.
15646         */
15647         if (type->facets != NULL) {
15648         xmlSchemaFacetPtr facet;
15649         int ok = 1;
15650 
15651         facet = type->facets;
15652         do {
15653             if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15654             (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
15655             xmlSchemaPIllegalFacetListUnionErr(pctxt,
15656                 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
15657                 type, facet);
15658             ok = 0;
15659             }
15660             facet = facet->next;
15661         } while (facet != NULL);
15662         if (ok == 0)
15663             return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
15664 
15665         }
15666         /*
15667         * SPEC (3.3.2.5) (same as 1.3.2)
15668         *
15669         * NOTE (3.3.2.5) This is currently done in
15670         * xmlSchemaDeriveAndValidateFacets()
15671         */
15672     }
15673     }
15674 
15675     return (0);
15676 }
15677 
15689 #if 0
15690 static int
15691 xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15692                 xmlSchemaTypePtr type)
15693 {
15694     /*
15695     * src-simple-type.1 The corresponding simple type definition, if any,
15696     * must satisfy the conditions set out in Constraints on Simple Type
15697     * Definition Schema Components (�3.14.6).
15698     */
15699     if (WXS_IS_RESTRICTION(type)) {
15700     /*
15701     * src-simple-type.2 "If the <restriction> alternative is chosen,
15702     * either it must have a base [attribute] or a <simpleType> among its
15703     * [children], but not both."
15704     * NOTE: This is checked in the parse function of <restriction>.
15705     */
15706     /*
15707     *
15708     */
15709     } else if (WXS_IS_LIST(type)) {
15710     /* src-simple-type.3 "If the <list> alternative is chosen, either it must have
15711     * an itemType [attribute] or a <simpleType> among its [children],
15712     * but not both."
15713     *
15714     * NOTE: This is checked in the parse function of <list>.
15715     */
15716     } else if (WXS_IS_UNION(type)) {
15717     /*
15718     * src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
15719     */
15720     }
15721     return (0);
15722 }
15723 #endif
15724 
15725 static int
15726 xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15727 {
15728    if (ctxt->vctxt == NULL) {
15729     ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15730     if (ctxt->vctxt == NULL) {
15731         xmlSchemaPErr(ctxt, NULL,
15732         XML_SCHEMAP_INTERNAL,
15733         "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
15734         "failed to create a temp. validation context.\n",
15735         NULL, NULL);
15736         return (-1);
15737     }
15738     /* TODO: Pass user data. */
15739     xmlSchemaSetValidErrors(ctxt->vctxt,
15740         ctxt->error, ctxt->warning, ctxt->errCtxt);
15741     xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15742         ctxt->serror, ctxt->errCtxt);
15743     }
15744     return (0);
15745 }
15746 
15747 static int
15748 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15749                  xmlNodePtr node,
15750                  xmlSchemaTypePtr type,
15751                  const xmlChar *value,
15752                  xmlSchemaValPtr *retVal,
15753                  int fireErrors,
15754                  int normalize,
15755                  int isNormalized);
15756 
15773 static int
15774 xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15775                    xmlNodePtr node,
15776                    xmlSchemaTypePtr type,
15777                    const xmlChar *value,
15778                    xmlSchemaValPtr *val)
15779 {
15780     int ret = 0;
15781 
15782     /*
15783     * cos-valid-default:
15784     * Schema Component Constraint: Element Default Valid (Immediate)
15785     * For a string to be a valid default with respect to a type
15786     * definition the appropriate case among the following must be true:
15787     */
15788     if WXS_IS_COMPLEX(type) {
15789     /*
15790     * Complex type.
15791     *
15792     * SPEC (2.1) "its {content type} must be a simple type definition
15793     * or mixed."
15794     * SPEC (2.2.2) "If the {content type} is mixed, then the {content
15795     * type}'s particle must be �emptiable� as defined by
15796     * Particle Emptiable (�3.9.6)."
15797     */
15798     if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15799         ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
15800         /* NOTE that this covers (2.2.2) as well. */
15801         xmlSchemaPCustomErr(pctxt,
15802         XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
15803         WXS_BASIC_CAST type, type->node,
15804         "For a string to be a valid default, the type definition "
15805         "must be a simple type or a complex type with mixed content "
15806         "and a particle emptiable", NULL);
15807         return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15808     }
15809     }
15810     /*
15811     * 1 If the type definition is a simple type definition, then the string
15812     * must be �valid� with respect to that definition as defined by String
15813     * Valid (�3.14.4).
15814     *
15815     * AND
15816     *
15817     * 2.2.1 If the {content type} is a simple type definition, then the
15818     * string must be �valid� with respect to that simple type definition
15819     * as defined by String Valid (�3.14.4).
15820     */
15821     if (WXS_IS_SIMPLE(type))
15822     ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15823         type, value, val, 1, 1, 0);
15824     else if (WXS_HAS_SIMPLE_CONTENT(type))
15825     ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15826         type->contentTypeDef, value, val, 1, 1, 0);
15827     else
15828     return (ret);
15829 
15830     if (ret < 0) {
15831     PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15832         "calling xmlSchemaVCheckCVCSimpleType()");
15833     }
15834 
15835     return (ret);
15836 }
15837 
15851 static int
15852 xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15853                  xmlSchemaTypePtr type)
15854 {
15855     /*
15856     * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15857     *
15858     * SPEC (1) "The values of the properties of a complex type definition must
15859     * be as described in the property tableau in The Complex Type Definition
15860     * Schema Component (�3.4.1), modulo the impact of Missing
15861     * Sub-components (�5.3)."
15862     */
15863     if ((type->baseType != NULL) &&
15864     (WXS_IS_SIMPLE(type->baseType)) &&
15865     (WXS_IS_EXTENSION(type) == 0)) {
15866     /*
15867     * SPEC (2) "If the {base type definition} is a simple type definition,
15868     * the {derivation method} must be extension."
15869     */
15870     xmlSchemaCustomErr(ACTXT_CAST pctxt,
15871         XML_SCHEMAP_SRC_CT_1,
15872         NULL, WXS_BASIC_CAST type,
15873         "If the base type is a simple type, the derivation method must be "
15874         "'extension'", NULL, NULL);
15875     return (XML_SCHEMAP_SRC_CT_1);
15876     }
15877     /*
15878     * SPEC (3) "Circular definitions are disallowed, except for the �ur-type
15879     * definition�. That is, it must be possible to reach the �ur-type
15880     * definition by repeatedly following the {base type definition}."
15881     *
15882     * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
15883     */
15884     /*
15885     * NOTE that (4) and (5) need the following:
15886     *   - attribute uses need to be already inherited (apply attr. prohibitions)
15887     *   - attribute group references need to be expanded already
15888     *   - simple types need to be typefixed already
15889     */
15890     if (type->attrUses &&
15891     (((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15892     {
15893     xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15894     xmlSchemaAttributeUsePtr use, tmp;
15895     int i, j, hasId = 0;
15896 
15897     for (i = uses->nbItems -1; i >= 0; i--) {
15898         use = uses->items[i];
15899 
15900         /*
15901         * SPEC ct-props-correct
15902         * (4) "Two distinct attribute declarations in the
15903         * {attribute uses} must not have identical {name}s and
15904         * {target namespace}s."
15905         */
15906         if (i > 0) {
15907         for (j = i -1; j >= 0; j--) {
15908             tmp = uses->items[j];
15909             if ((WXS_ATTRUSE_DECL_NAME(use) ==
15910             WXS_ATTRUSE_DECL_NAME(tmp)) &&
15911             (WXS_ATTRUSE_DECL_TNS(use) ==
15912             WXS_ATTRUSE_DECL_TNS(tmp)))
15913             {
15914             xmlChar *str = NULL;
15915 
15916             xmlSchemaCustomErr(ACTXT_CAST pctxt,
15917                 XML_SCHEMAP_AG_PROPS_CORRECT,
15918                 NULL, WXS_BASIC_CAST type,
15919                 "Duplicate %s",
15920                 xmlSchemaGetComponentDesignation(&str, use),
15921                 NULL);
15922             FREE_AND_NULL(str);
15923             /*
15924             * Remove the duplicate.
15925             */
15926             if (xmlSchemaItemListRemove(uses, i) == -1)
15927                 goto exit_failure;
15928             goto next_use;
15929             }
15930         }
15931         }
15932         /*
15933         * SPEC ct-props-correct
15934         * (5) "Two distinct attribute declarations in the
15935         * {attribute uses} must not have {type definition}s which
15936         * are or are derived from ID."
15937         */
15938         if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15939         if (xmlSchemaIsDerivedFromBuiltInType(
15940             WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
15941         {
15942             if (hasId) {
15943             xmlChar *str = NULL;
15944 
15945             xmlSchemaCustomErr(ACTXT_CAST pctxt,
15946                 XML_SCHEMAP_AG_PROPS_CORRECT,
15947                 NULL, WXS_BASIC_CAST type,
15948                 "There must not exist more than one attribute "
15949                 "declaration of type 'xs:ID' "
15950                 "(or derived from 'xs:ID'). The %s violates this "
15951                 "constraint",
15952                 xmlSchemaGetComponentDesignation(&str, use),
15953                 NULL);
15954             FREE_AND_NULL(str);
15955             if (xmlSchemaItemListRemove(uses, i) == -1)
15956                 goto exit_failure;
15957             }
15958 
15959             hasId = 1;
15960         }
15961         }
15962 next_use: {}
15963     }
15964     }
15965     return (0);
15966 exit_failure:
15967     return(-1);
15968 }
15969 
15970 static int
15971 xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
15972                xmlSchemaTypePtr typeB)
15973 {
15974     /*
15975     * TODO: This should implement component-identity
15976     * in the future.
15977     */
15978     if ((typeA == NULL) || (typeB == NULL))
15979     return (0);
15980     return (typeA == typeB);
15981 }
15982 
15998 static int
15999 xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16000                  xmlSchemaTypePtr type,
16001                  xmlSchemaTypePtr baseType,
16002                  int set)
16003 {
16004     int equal = xmlSchemaAreEqualTypes(type, baseType);
16005     /* TODO: Error codes. */
16006     /*
16007     * SPEC "For a complex type definition (call it D, for derived)
16008     * to be validly derived from a type definition (call this
16009     * B, for base) given a subset of {extension, restriction}
16010     * all of the following must be true:"
16011     */
16012     if (! equal) {
16013     /*
16014     * SPEC (1) "If B and D are not the same type definition, then the
16015     * {derivation method} of D must not be in the subset."
16016     */
16017     if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
16018         ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
16019         return (1);
16020     } else {
16021     /*
16022     * SPEC (2.1) "B and D must be the same type definition."
16023     */
16024     return (0);
16025     }
16026     /*
16027     * SPEC (2.2) "B must be D's {base type definition}."
16028     */
16029     if (type->baseType == baseType)
16030     return (0);
16031     /*
16032     * SPEC (2.3.1) "D's {base type definition} must not be the �ur-type
16033     * definition�."
16034     */
16035     if (WXS_IS_ANYTYPE(type->baseType))
16036     return (1);
16037 
16038     if (WXS_IS_COMPLEX(type->baseType)) {
16039     /*
16040     * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
16041     * must be validly derived from B given the subset as defined by this
16042     * constraint."
16043     */
16044     return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
16045         baseType, set));
16046     } else {
16047     /*
16048     * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
16049     * must be validly derived from B given the subset as defined in Type
16050     * Derivation OK (Simple) (�3.14.6).
16051     */
16052     return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
16053         baseType, set));
16054     }
16055 }
16056 
16069 static int
16070 xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16071                xmlSchemaTypePtr type,
16072                xmlSchemaTypePtr baseType,
16073                int set)
16074 {
16075     if (WXS_IS_SIMPLE(type))
16076     return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
16077     else
16078     return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
16079 }
16080 
16098 static int
16099 xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16100                xmlSchemaTypePtr type)
16101 {
16102     xmlSchemaTypePtr base = type->baseType;
16103     /*
16104     * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16105     * temporarily only.
16106     */
16107     /*
16108     * SPEC (1) "If the {base type definition} is a complex type definition,
16109     * then all of the following must be true:"
16110     */
16111     if (WXS_IS_COMPLEX(base)) {
16112     /*
16113     * SPEC (1.1) "The {final} of the {base type definition} must not
16114     * contain extension."
16115     */
16116     if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16117         xmlSchemaPCustomErr(ctxt,
16118         XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16119         WXS_BASIC_CAST type, NULL,
16120         "The 'final' of the base type definition "
16121         "contains 'extension'", NULL);
16122         return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16123     }
16124 
16125     /*
16126     * ATTENTION: The constrains (1.2) and (1.3) are not applied,
16127     * since they are automatically satisfied through the
16128     * inheriting mechanism.
16129     * Note that even if redefining components, the inheriting mechanism
16130     * is used.
16131     */
16132 #if 0
16133     /*
16134     * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
16135     * uses}
16136     * of the complex type definition itself, that is, for every attribute
16137     * use in the {attribute uses} of the {base type definition}, there
16138     * must be an attribute use in the {attribute uses} of the complex
16139     * type definition itself whose {attribute declaration} has the same
16140     * {name}, {target namespace} and {type definition} as its attribute
16141     * declaration"
16142     */
16143     if (base->attrUses != NULL) {
16144         int i, j, found;
16145         xmlSchemaAttributeUsePtr use, buse;
16146 
16147         for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16148         buse = (WXS_LIST_CAST base->attrUses)->items[i];
16149         found = 0;
16150         if (type->attrUses != NULL) {
16151             use = (WXS_LIST_CAST type->attrUses)->items[j];
16152             for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16153             {
16154             if ((WXS_ATTRUSE_DECL_NAME(use) ==
16155                 WXS_ATTRUSE_DECL_NAME(buse)) &&
16156                 (WXS_ATTRUSE_DECL_TNS(use) ==
16157                 WXS_ATTRUSE_DECL_TNS(buse)) &&
16158                 (WXS_ATTRUSE_TYPEDEF(use) ==
16159                 WXS_ATTRUSE_TYPEDEF(buse))
16160             {
16161                 found = 1;
16162                 break;
16163             }
16164             }
16165         }
16166         if (! found) {
16167             xmlChar *str = NULL;
16168 
16169             xmlSchemaCustomErr(ACTXT_CAST ctxt,
16170             XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16171             NULL, WXS_BASIC_CAST type,
16172             /*
16173             * TODO: The report does not indicate that also the
16174             * type needs to be the same.
16175             */
16176             "This type is missing a matching correspondent "
16177             "for its {base type}'s %s in its {attribute uses}",
16178             xmlSchemaGetComponentDesignation(&str,
16179                 buse->children),
16180             NULL);
16181             FREE_AND_NULL(str)
16182         }
16183         }
16184     }
16185     /*
16186     * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16187     * definition must also have one, and the base type definition's
16188     * {attribute  wildcard}'s {namespace constraint} must be a subset
16189     * of the complex  type definition's {attribute wildcard}'s {namespace
16190     * constraint}, as defined by Wildcard Subset (�3.10.6)."
16191     */
16192 
16193     /*
16194     * MAYBE TODO: Enable if ever needed. But this will be needed only
16195     * if created the type via a schema construction API.
16196     */
16197     if (base->attributeWildcard != NULL) {
16198         if (type->attributeWilcard == NULL) {
16199         xmlChar *str = NULL;
16200 
16201         xmlSchemaCustomErr(ACTXT_CAST pctxt,
16202             XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16203             NULL, type,
16204             "The base %s has an attribute wildcard, "
16205             "but this type is missing an attribute wildcard",
16206             xmlSchemaGetComponentDesignation(&str, base));
16207         FREE_AND_NULL(str)
16208 
16209         } else if (xmlSchemaCheckCOSNSSubset(
16210         base->attributeWildcard, type->attributeWildcard))
16211         {
16212         xmlChar *str = NULL;
16213 
16214         xmlSchemaCustomErr(ACTXT_CAST pctxt,
16215             XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16216             NULL, type,
16217             "The attribute wildcard is not a valid "
16218             "superset of the one in the base %s",
16219             xmlSchemaGetComponentDesignation(&str, base));
16220         FREE_AND_NULL(str)
16221         }
16222     }
16223 #endif
16224     /*
16225     * SPEC (1.4) "One of the following must be true:"
16226     */
16227     if ((type->contentTypeDef != NULL) &&
16228         (type->contentTypeDef == base->contentTypeDef)) {
16229         /*
16230         * SPEC (1.4.1) "The {content type} of the {base type definition}
16231         * and the {content type} of the complex type definition itself
16232         * must be the same simple type definition"
16233         * PASS
16234         */
16235     } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16236         (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16237         /*
16238         * SPEC (1.4.2) "The {content type} of both the {base type
16239         * definition} and the complex type definition itself must
16240         * be empty."
16241         * PASS
16242         */
16243     } else {
16244         /*
16245         * SPEC (1.4.3) "All of the following must be true:"
16246         */
16247         if (type->subtypes == NULL) {
16248         /*
16249         * SPEC 1.4.3.1 The {content type} of the complex type
16250         * definition itself must specify a particle.
16251         */
16252         xmlSchemaPCustomErr(ctxt,
16253             XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16254             WXS_BASIC_CAST type, NULL,
16255             "The content type must specify a particle", NULL);
16256         return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16257         }
16258         /*
16259         * SPEC (1.4.3.2) "One of the following must be true:"
16260         */
16261         if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16262         /*
16263         * SPEC (1.4.3.2.1) "The {content type} of the {base type
16264         * definition} must be empty.
16265         * PASS
16266         */
16267         } else {
16268         /*
16269         * SPEC (1.4.3.2.2) "All of the following must be true:"
16270         */
16271         if ((type->contentType != base->contentType) ||
16272             ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16273             (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16274             /*
16275             * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16276             * or both must be element-only."
16277             */
16278             xmlSchemaPCustomErr(ctxt,
16279             XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16280             WXS_BASIC_CAST type, NULL,
16281             "The content type of both, the type and its base "
16282             "type, must either 'mixed' or 'element-only'", NULL);
16283             return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16284         }
16285         /*
16286         * URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
16287         * complex type definition must be a �valid extension�
16288         * of the {base type definition}'s particle, as defined
16289         * in Particle Valid (Extension) (�3.9.6)."
16290         *
16291         * NOTE that we won't check "Particle Valid (Extension)",
16292         * since it is ensured by the derivation process in
16293         * xmlSchemaTypeFixup(). We need to implement this when heading
16294         * for a construction API
16295         * TODO: !! This is needed to be checked if redefining a type !!
16296         */
16297         }
16298         /*
16299         * URGENT TODO (1.5)
16300         */
16301     }
16302     } else {
16303     /*
16304     * SPEC (2) "If the {base type definition} is a simple type definition,
16305     * then all of the following must be true:"
16306     */
16307     if (type->contentTypeDef != base) {
16308         /*
16309         * SPEC (2.1) "The {content type} must be the same simple type
16310         * definition."
16311         */
16312         xmlSchemaPCustomErr(ctxt,
16313         XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16314         WXS_BASIC_CAST type, NULL,
16315         "The content type must be the simple base type", NULL);
16316         return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16317     }
16318     if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16319         /*
16320         * SPEC (2.2) "The {final} of the {base type definition} must not
16321         * contain extension"
16322         * NOTE that this is the same as (1.1).
16323         */
16324         xmlSchemaPCustomErr(ctxt,
16325         XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16326         WXS_BASIC_CAST type, NULL,
16327         "The 'final' of the base type definition "
16328         "contains 'extension'", NULL);
16329         return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16330     }
16331     }
16332     return (0);
16333 }
16334 
16355 static int
16356 xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16357                       xmlSchemaTypePtr type)
16358 {
16359     xmlSchemaTypePtr base;
16360 
16361     /*
16362     * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
16363     * temporarily only.
16364     */
16365     base = type->baseType;
16366     if (! WXS_IS_COMPLEX(base)) {
16367     xmlSchemaCustomErr(ACTXT_CAST ctxt,
16368         XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16369         type->node, WXS_BASIC_CAST type,
16370         "The base type must be a complex type", NULL, NULL);
16371     return(ctxt->err);
16372     }
16373     if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16374     /*
16375     * SPEC (1) "The {base type definition} must be a complex type
16376     * definition whose {final} does not contain restriction."
16377     */
16378     xmlSchemaCustomErr(ACTXT_CAST ctxt,
16379         XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16380         type->node, WXS_BASIC_CAST type,
16381         "The 'final' of the base type definition "
16382         "contains 'restriction'", NULL, NULL);
16383     return (ctxt->err);
16384     }
16385     /*
16386     * SPEC (2), (3) and (4)
16387     * Those are handled in a separate function, since the
16388     * same constraints are needed for redefinition of
16389     * attribute groups as well.
16390     */
16391     if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16392     XML_SCHEMA_ACTION_DERIVE,
16393     WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16394     type->attrUses, base->attrUses,
16395     type->attributeWildcard,
16396     base->attributeWildcard) == -1)
16397     {
16398     return(-1);
16399     }
16400     /*
16401     * SPEC (5) "One of the following must be true:"
16402     */
16403     if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16404     /*
16405     * SPEC (5.1) "The {base type definition} must be the
16406     * �ur-type definition�."
16407     * PASS
16408     */
16409     } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16410         (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16411     /*
16412     * SPEC (5.2.1) "The {content type} of the complex type definition
16413     * must be a simple type definition"
16414     *
16415     * SPEC (5.2.2) "One of the following must be true:"
16416     */
16417     if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16418         (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16419     {
16420         int err;
16421         /*
16422         * SPEC (5.2.2.1) "The {content type} of the {base type
16423         * definition} must be a simple type definition from which
16424         * the {content type} is validly derived given the empty
16425         * set as defined in Type Derivation OK (Simple) (�3.14.6)."
16426         *
16427         * ATTENTION TODO: This seems not needed if the type implicitely
16428         * derived from the base type.
16429         *
16430         */
16431         err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16432         type->contentTypeDef, base->contentTypeDef, 0);
16433         if (err != 0) {
16434         xmlChar *strA = NULL, *strB = NULL;
16435 
16436         if (err == -1)
16437             return(-1);
16438         xmlSchemaCustomErr(ACTXT_CAST ctxt,
16439             XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16440             NULL, WXS_BASIC_CAST type,
16441             "The {content type} %s is not validly derived from the "
16442             "base type's {content type} %s",
16443             xmlSchemaGetComponentDesignation(&strA,
16444             type->contentTypeDef),
16445             xmlSchemaGetComponentDesignation(&strB,
16446             base->contentTypeDef));
16447         FREE_AND_NULL(strA);
16448         FREE_AND_NULL(strB);
16449         return(ctxt->err);
16450         }
16451     } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16452         (xmlSchemaIsParticleEmptiable(
16453         (xmlSchemaParticlePtr) base->subtypes))) {
16454         /*
16455         * SPEC (5.2.2.2) "The {base type definition} must be mixed
16456         * and have a particle which is �emptiable� as defined in
16457         * Particle Emptiable (�3.9.6)."
16458         * PASS
16459         */
16460     } else {
16461         xmlSchemaPCustomErr(ctxt,
16462         XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16463         WXS_BASIC_CAST type, NULL,
16464         "The content type of the base type must be either "
16465         "a simple type or 'mixed' and an emptiable particle", NULL);
16466         return (ctxt->err);
16467     }
16468     } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16469     /*
16470     * SPEC (5.3.1) "The {content type} of the complex type itself must
16471     * be empty"
16472     */
16473     if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16474         /*
16475         * SPEC (5.3.2.1) "The {content type} of the {base type
16476         * definition} must also be empty."
16477         * PASS
16478         */
16479     } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16480         (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16481         xmlSchemaIsParticleEmptiable(
16482         (xmlSchemaParticlePtr) base->subtypes)) {
16483         /*
16484         * SPEC (5.3.2.2) "The {content type} of the {base type
16485         * definition} must be elementOnly or mixed and have a particle
16486         * which is �emptiable� as defined in Particle Emptiable (�3.9.6)."
16487         * PASS
16488         */
16489     } else {
16490         xmlSchemaPCustomErr(ctxt,
16491         XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16492         WXS_BASIC_CAST type, NULL,
16493         "The content type of the base type must be either "
16494         "empty or 'mixed' (or 'elements-only') and an emptiable "
16495         "particle", NULL);
16496         return (ctxt->err);
16497     }
16498     } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16499     WXS_HAS_MIXED_CONTENT(type)) {
16500     /*
16501     * SPEC (5.4.1.1) "The {content type} of the complex type definition
16502     * itself must be element-only"
16503     */
16504     if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
16505         /*
16506         * SPEC (5.4.1.2) "The {content type} of the complex type
16507         * definition itself and of the {base type definition} must be
16508         * mixed"
16509         */
16510         xmlSchemaPCustomErr(ctxt,
16511         XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16512         WXS_BASIC_CAST type, NULL,
16513         "If the content type is 'mixed', then the content type of the "
16514         "base type must also be 'mixed'", NULL);
16515         return (ctxt->err);
16516     }
16517     /*
16518     * SPEC (5.4.2) "The particle of the complex type definition itself
16519     * must be a �valid restriction� of the particle of the {content
16520     * type} of the {base type definition} as defined in Particle Valid
16521     * (Restriction) (�3.9.6).
16522     *
16523     * URGENT TODO: (5.4.2)
16524     */
16525     } else {
16526     xmlSchemaPCustomErr(ctxt,
16527         XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16528         WXS_BASIC_CAST type, NULL,
16529         "The type is not a valid restriction of its base type", NULL);
16530     return (ctxt->err);
16531     }
16532     return (0);
16533 }
16534 
16545 static int
16546 xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16547               xmlSchemaTypePtr type)
16548 {
16549     int ret;
16550     /*
16551     * Complex Type Definition Properties Correct
16552     */
16553     ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16554     if (ret != 0)
16555     return (ret);
16556     if (WXS_IS_EXTENSION(type))
16557     ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16558     else
16559     ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16560     return (ret);
16561 }
16562 
16575 static int
16576 xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
16577             xmlSchemaTypePtr type)
16578 {
16579     xmlSchemaTypePtr base;
16580     int ret = 0;
16581 
16582     /*
16583     * TODO: Adjust the error codes here, as I used
16584     * XML_SCHEMAP_SRC_CT_1 only yet.
16585     */
16586     base = type->baseType;
16587     if (! WXS_HAS_SIMPLE_CONTENT(type)) {
16588     /*
16589     * 1 If the <complexContent> alternative is chosen, the type definition
16590     * �resolved� to by the �actual value� of the base [attribute]
16591     * must be a complex type definition;
16592     */
16593     if (! WXS_IS_COMPLEX(base)) {
16594         xmlChar *str = NULL;
16595         xmlSchemaPCustomErr(ctxt,
16596         XML_SCHEMAP_SRC_CT_1,
16597         WXS_BASIC_CAST type, type->node,
16598         "If using <complexContent>, the base type is expected to be "
16599         "a complex type. The base type '%s' is a simple type",
16600         xmlSchemaFormatQName(&str, base->targetNamespace,
16601         base->name));
16602         FREE_AND_NULL(str)
16603         return (XML_SCHEMAP_SRC_CT_1);
16604     }
16605     } else {
16606     /*
16607     * SPEC
16608     * 2 If the <simpleContent> alternative is chosen, all of the
16609     * following must be true:
16610     * 2.1 The type definition �resolved� to by the �actual value� of the
16611     * base [attribute] must be one of the following:
16612     */
16613     if (WXS_IS_SIMPLE(base)) {
16614         if (WXS_IS_EXTENSION(type) == 0) {
16615         xmlChar *str = NULL;
16616         /*
16617         * 2.1.3 only if the <extension> alternative is also
16618         * chosen, a simple type definition.
16619         */
16620         /* TODO: Change error code to ..._SRC_CT_2_1_3. */
16621         xmlSchemaPCustomErr(ctxt,
16622             XML_SCHEMAP_SRC_CT_1,
16623             WXS_BASIC_CAST type, NULL,
16624             "If using <simpleContent> and <restriction>, the base "
16625             "type must be a complex type. The base type '%s' is "
16626             "a simple type",
16627             xmlSchemaFormatQName(&str, base->targetNamespace,
16628             base->name));
16629         FREE_AND_NULL(str)
16630         return (XML_SCHEMAP_SRC_CT_1);
16631         }
16632     } else {
16633         /* Base type is a complex type. */
16634         if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16635         (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16636         /*
16637         * 2.1.1 a complex type definition whose {content type} is a
16638         * simple type definition;
16639         * PASS
16640         */
16641         if (base->contentTypeDef == NULL) {
16642             xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16643             WXS_BASIC_CAST type, NULL,
16644             "Internal error: xmlSchemaCheckSRCCT, "
16645             "'%s', base type has no content type",
16646             type->name);
16647             return (-1);
16648         }
16649         } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16650         (WXS_IS_RESTRICTION(type))) {
16651 
16652         /*
16653         * 2.1.2 only if the <restriction> alternative is also
16654         * chosen, a complex type definition whose {content type}
16655         * is mixed and a particle emptiable.
16656         */
16657         if (! xmlSchemaIsParticleEmptiable(
16658             (xmlSchemaParticlePtr) base->subtypes)) {
16659             ret = XML_SCHEMAP_SRC_CT_1;
16660         } else
16661             /*
16662             * Attention: at this point the <simpleType> child is in
16663             * ->contentTypeDef (put there during parsing).
16664             */
16665             if (type->contentTypeDef == NULL) {
16666             xmlChar *str = NULL;
16667             /*
16668             * 2.2 If clause 2.1.2 above is satisfied, then there
16669             * must be a <simpleType> among the [children] of
16670             * <restriction>.
16671             */
16672             /* TODO: Change error code to ..._SRC_CT_2_2. */
16673             xmlSchemaPCustomErr(ctxt,
16674             XML_SCHEMAP_SRC_CT_1,
16675             WXS_BASIC_CAST type, NULL,
16676             "A <simpleType> is expected among the children "
16677             "of <restriction>, if <simpleContent> is used and "
16678             "the base type '%s' is a complex type",
16679             xmlSchemaFormatQName(&str, base->targetNamespace,
16680             base->name));
16681             FREE_AND_NULL(str)
16682             return (XML_SCHEMAP_SRC_CT_1);
16683         }
16684         } else {
16685         ret = XML_SCHEMAP_SRC_CT_1;
16686         }
16687     }
16688     if (ret > 0) {
16689         xmlChar *str = NULL;
16690         if (WXS_IS_RESTRICTION(type)) {
16691         xmlSchemaPCustomErr(ctxt,
16692             XML_SCHEMAP_SRC_CT_1,
16693             WXS_BASIC_CAST type, NULL,
16694             "If <simpleContent> and <restriction> is used, the "
16695             "base type must be a simple type or a complex type with "
16696             "mixed content and particle emptiable. The base type "
16697             "'%s' is none of those",
16698             xmlSchemaFormatQName(&str, base->targetNamespace,
16699             base->name));
16700         } else {
16701         xmlSchemaPCustomErr(ctxt,
16702             XML_SCHEMAP_SRC_CT_1,
16703             WXS_BASIC_CAST type, NULL,
16704             "If <simpleContent> and <extension> is used, the "
16705             "base type must be a simple type. The base type '%s' "
16706             "is a complex type",
16707             xmlSchemaFormatQName(&str, base->targetNamespace,
16708             base->name));
16709         }
16710         FREE_AND_NULL(str)
16711     }
16712     }
16713     /*
16714     * SPEC (3) "The corresponding complex type definition component must
16715     * satisfy the conditions set out in Constraints on Complex Type
16716     * Definition Schema Components (�3.4.6);"
16717     * NOTE (3) will be done in xmlSchemaTypeFixup().
16718     */
16719     /*
16720     * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
16721     * above for {attribute wildcard} is satisfied, the intensional
16722     * intersection must be expressible, as defined in Attribute Wildcard
16723     * Intersection (�3.10.6).
16724     * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
16725     */
16726     return (ret);
16727 }
16728 
16729 #ifdef ENABLE_PARTICLE_RESTRICTION
16730 
16744 static int
16745 xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16746                   int bmin, int bmax)
16747 {
16748     if (rmin < bmin)
16749     return (1);
16750     if ((bmax != UNBOUNDED) &&
16751     (rmax > bmax))
16752     return (1);
16753     return (0);
16754 }
16755 
16774 static int
16775 xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16776                  xmlSchemaParticlePtr r,
16777                  xmlSchemaParticlePtr b)
16778 {
16779     xmlSchemaElementPtr elemR, elemB;
16780 
16781     /* TODO: Error codes (rcase-NameAndTypeOK). */
16782     elemR = (xmlSchemaElementPtr) r->children;
16783     elemB = (xmlSchemaElementPtr) b->children;
16784     /*
16785     * SPEC (1) "The declarations' {name}s and {target namespace}s are
16786     * the same."
16787     */
16788     if ((elemR != elemB) &&
16789     ((! xmlStrEqual(elemR->name, elemB->name)) ||
16790     (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16791     return (1);
16792     /*
16793     * SPEC (2) "R's occurrence range is a valid restriction of B's
16794     * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16795     */
16796     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16797         b->minOccurs, b->maxOccurs) != 0)
16798     return (1);
16799     /*
16800     * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16801     * {scope} are global."
16802     */
16803     if (elemR == elemB)
16804     return (0);
16805     /*
16806     * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16807     */
16808     if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16809     (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16810      return (1);
16811     /*
16812     * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16813     * or is not fixed, or R's declaration's {value constraint} is fixed
16814     * with the same value."
16815     */
16816     if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16817     ((elemR->value == NULL) ||
16818      ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16819      /* TODO: Equality of the initial value or normalized or canonical? */
16820      (! xmlStrEqual(elemR->value, elemB->value))))
16821      return (1);
16822     /*
16823     * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16824     * definitions} is a subset of B's declaration's {identity-constraint
16825     * definitions}, if any."
16826     */
16827     if (elemB->idcs != NULL) {
16828     /* TODO */
16829     }
16830     /*
16831     * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16832     * superset of B's declaration's {disallowed substitutions}."
16833     */
16834     if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16835      ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16836     ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16837      ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16838     ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16839      ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16840      return (1);
16841     /*
16842     * SPEC (3.2.5) "R's {type definition} is validly derived given
16843     * {extension, list, union} from B's {type definition}"
16844     *
16845     * BADSPEC TODO: What's the point of adding "list" and "union" to the
16846     * set, if the corresponding constraints handle "restriction" and
16847     * "extension" only?
16848     *
16849     */
16850     {
16851     int set = 0;
16852 
16853     set |= SUBSET_EXTENSION;
16854     set |= SUBSET_LIST;
16855     set |= SUBSET_UNION;
16856     if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
16857         elemB->subtypes, set) != 0)
16858         return (1);
16859     }
16860     return (0);
16861 }
16862 
16879 static int
16880 xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16881                 xmlSchemaParticlePtr r,
16882                 xmlSchemaParticlePtr b)
16883 {
16884     /* TODO:Error codes (rcase-NSCompat). */
16885     /*
16886     * SPEC "For an element declaration particle to be a �valid restriction�
16887     * of a wildcard particle all of the following must be true:"
16888     *
16889     * SPEC (1) "The element declaration's {target namespace} is �valid�
16890     * with respect to the wildcard's {namespace constraint} as defined by
16891     * Wildcard allows Namespace Name (�3.10.4)."
16892     */
16893     if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
16894     ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16895     return (1);
16896     /*
16897     * SPEC (2) "R's occurrence range is a valid restriction of B's
16898     * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16899     */
16900     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16901         b->minOccurs, b->maxOccurs) != 0)
16902     return (1);
16903 
16904     return (0);
16905 }
16906 
16923 static int
16924 xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16925                     xmlSchemaParticlePtr r,
16926                     xmlSchemaParticlePtr b)
16927 {
16928     /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16929     TODO
16930     return (0);
16931 }
16932 
16949 static int
16950 xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
16951                     xmlSchemaParticlePtr r,
16952                     xmlSchemaParticlePtr b,
16953                     int isAnyTypeBase)
16954 {
16955     /* TODO: Error codes (rcase-NSSubset). */
16956     /*
16957     * SPEC (1) "R's occurrence range is a valid restriction of B's
16958     * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16959     */
16960     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16961         b->minOccurs, b->maxOccurs))
16962     return (1);
16963     /*
16964     * SPEC (2) "R's {namespace constraint} must be an intensional subset
16965     * of B's {namespace constraint} as defined by Wildcard Subset (�3.10.6)."
16966     */
16967     if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
16968     (xmlSchemaWildcardPtr) b->children))
16969     return (1);
16970     /*
16971     * SPEC (3) "Unless B is the content model wildcard of the �ur-type
16972     * definition�, R's {process contents} must be identical to or stronger
16973     * than B's {process contents}, where strict is stronger than lax is
16974     * stronger than skip."
16975     */
16976     if (! isAnyTypeBase) {
16977     if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
16978         ((xmlSchemaWildcardPtr) b->children)->processContents)
16979         return (1);
16980     }
16981 
16982     return (0);
16983 }
16984 
16999 static int
17000 xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
17001                   xmlSchemaParticlePtr r,
17002                   xmlSchemaParticlePtr b)
17003 {
17004     int ret = 0;
17005 
17006     /*part = WXS_TYPE_PARTICLE(type);
17007     basePart = WXS_TYPE_PARTICLE(base);
17008     */
17009 
17010     TODO
17011 
17012     /*
17013     * SPEC (1) "They are the same particle."
17014     */
17015     if (r == b)
17016     return (0);
17017 
17018 
17019     return (0);
17020 }
17021 
17022 #if 0
17023 
17040 static int
17041 xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
17042                          xmlSchemaParticlePtr r,
17043                          xmlSchemaParticlePtr b)
17044 {
17045     xmlSchemaParticlePtr part;
17046     /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
17047     if ((r->children == NULL) || (r->children->children == NULL))
17048     return (-1);
17049     /*
17050     * SPEC "For a group particle to be a �valid restriction� of a
17051     * wildcard particle..."
17052     *
17053     * SPEC (1) "Every member of the {particles} of the group is a �valid
17054     * restriction� of the wildcard as defined by
17055     * Particle Valid (Restriction) (�3.9.6)."
17056     */
17057     part = (xmlSchemaParticlePtr) r->children->children;
17058     do {
17059     if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
17060         return (1);
17061     part = (xmlSchemaParticlePtr) part->next;
17062     } while (part != NULL);
17063     /*
17064     * SPEC (2) "The effective total range of the group [...] is a
17065     * valid restriction of B's occurrence range as defined by
17066     * Occurrence Range OK (�3.9.6)."
17067     */
17068     if (xmlSchemaCheckParticleRangeOK(
17069         xmlSchemaGetParticleTotalRangeMin(r),
17070         xmlSchemaGetParticleTotalRangeMax(r),
17071         b->minOccurs, b->maxOccurs) != 0)
17072     return (1);
17073     return (0);
17074 }
17075 #endif
17076 
17095 static int
17096 xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17097                xmlSchemaParticlePtr r,
17098                xmlSchemaParticlePtr b)
17099 {
17100     /* xmlSchemaParticlePtr part; */
17101     /* TODO: Error codes (rcase-Recurse). */
17102     if ((r->children == NULL) || (b->children == NULL) ||
17103     (r->children->type != b->children->type))
17104     return (-1);
17105     /*
17106     * SPEC "For an all or sequence group particle to be a �valid
17107     * restriction� of another group particle with the same {compositor}..."
17108     *
17109     * SPEC (1) "R's occurrence range is a valid restriction of B's
17110     * occurrence range as defined by Occurrence Range OK (�3.9.6)."
17111     */
17112     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17113         b->minOccurs, b->maxOccurs))
17114     return (1);
17115 
17116 
17117     return (0);
17118 }
17119 
17120 #endif
17121 
17122 #define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17123     xmlSchemaPCustomErrExt(pctxt,      \
17124     XML_SCHEMAP_INVALID_FACET_VALUE, \
17125     WXS_BASIC_CAST fac1, fac1->node, \
17126     "It is an error for both '%s' and '%s' to be specified on the "\
17127     "same type definition", \
17128     BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17129     BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17130 
17131 #define FACET_RESTR_ERR(fac1, msg) \
17132     xmlSchemaPCustomErr(pctxt,      \
17133     XML_SCHEMAP_INVALID_FACET_VALUE, \
17134     WXS_BASIC_CAST fac1, fac1->node, \
17135     msg, NULL);
17136 
17137 #define FACET_RESTR_FIXED_ERR(fac) \
17138     xmlSchemaPCustomErr(pctxt, \
17139     XML_SCHEMAP_INVALID_FACET_VALUE, \
17140     WXS_BASIC_CAST fac, fac->node, \
17141     "The base type's facet is 'fixed', thus the value must not " \
17142     "differ", NULL);
17143 
17144 static void
17145 xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17146             xmlSchemaFacetPtr facet1,
17147             xmlSchemaFacetPtr facet2,
17148             int lessGreater,
17149             int orEqual,
17150             int ofBase)
17151 {
17152     xmlChar *msg = NULL;
17153 
17154     msg = xmlStrdup(BAD_CAST "'");
17155     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17156     msg = xmlStrcat(msg, BAD_CAST "' has to be");
17157     if (lessGreater == 0)
17158     msg = xmlStrcat(msg, BAD_CAST " equal to");
17159     if (lessGreater == 1)
17160     msg = xmlStrcat(msg, BAD_CAST " greater than");
17161     else
17162     msg = xmlStrcat(msg, BAD_CAST " less than");
17163 
17164     if (orEqual)
17165     msg = xmlStrcat(msg, BAD_CAST " or equal to");
17166     msg = xmlStrcat(msg, BAD_CAST " '");
17167     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17168     if (ofBase)
17169     msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17170     else
17171     msg = xmlStrcat(msg, BAD_CAST "'");
17172 
17173     xmlSchemaPCustomErr(pctxt,
17174     XML_SCHEMAP_INVALID_FACET_VALUE,
17175     WXS_BASIC_CAST facet1, NULL,
17176     (const char *) msg, NULL);
17177 
17178     if (msg != NULL)
17179     xmlFree(msg);
17180 }
17181 
17182 /*
17183 * xmlSchemaDeriveAndValidateFacets:
17184 *
17185 * Schema Component Constraint: Simple Type Restriction (Facets)
17186 * (st-restrict-facets)
17187 */
17188 static int
17189 xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17190                  xmlSchemaTypePtr type)
17191 {
17192     xmlSchemaTypePtr base = type->baseType;
17193     xmlSchemaFacetLinkPtr link, cur, last = NULL;
17194     xmlSchemaFacetPtr facet, bfacet,
17195     flength = NULL, ftotdig = NULL, ffracdig = NULL,
17196     fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17197     fmininc = NULL, fmaxinc = NULL,
17198     fminexc = NULL, fmaxexc = NULL,
17199     bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17200     bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17201     bfmininc = NULL, bfmaxinc = NULL,
17202     bfminexc = NULL, bfmaxexc = NULL;
17203     int res; /* err = 0, fixedErr; */
17204 
17205     /*
17206     * SPEC st-restrict-facets 1:
17207     * "The {variety} of R is the same as that of B."
17208     */
17209     /*
17210     * SPEC st-restrict-facets 2:
17211     * "If {variety} is atomic, the {primitive type definition}
17212     * of R is the same as that of B."
17213     *
17214     * NOTE: we leave 1 & 2 out for now, since this will be
17215     * satisfied by the derivation process.
17216     * CONSTRUCTION TODO: Maybe needed if using a construction API.
17217     */
17218     /*
17219     * SPEC st-restrict-facets 3:
17220     * "The {facets} of R are the union of S and the {facets}
17221     * of B, eliminating duplicates. To eliminate duplicates,
17222     * when a facet of the same kind occurs in both S and the
17223     * {facets} of B, the one in the {facets} of B is not
17224     * included, with the exception of enumeration and pattern
17225     * facets, for which multiple occurrences with distinct values
17226     * are allowed."
17227     */
17228 
17229     if ((type->facetSet == NULL) && (base->facetSet == NULL))
17230     return (0);
17231 
17232     last = type->facetSet;
17233     if (last != NULL)
17234     while (last->next != NULL)
17235         last = last->next;
17236 
17237     for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17238     facet = cur->facet;
17239     switch (facet->type) {
17240         case XML_SCHEMA_FACET_LENGTH:
17241         flength = facet; break;
17242         case XML_SCHEMA_FACET_MINLENGTH:
17243         fminlen = facet; break;
17244         case XML_SCHEMA_FACET_MININCLUSIVE:
17245         fmininc = facet; break;
17246         case XML_SCHEMA_FACET_MINEXCLUSIVE:
17247         fminexc = facet; break;
17248         case XML_SCHEMA_FACET_MAXLENGTH:
17249         fmaxlen = facet; break;
17250         case XML_SCHEMA_FACET_MAXINCLUSIVE:
17251         fmaxinc = facet; break;
17252         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17253         fmaxexc = facet; break;
17254         case XML_SCHEMA_FACET_TOTALDIGITS:
17255         ftotdig = facet; break;
17256         case XML_SCHEMA_FACET_FRACTIONDIGITS:
17257         ffracdig = facet; break;
17258         default:
17259         break;
17260     }
17261     }
17262     for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17263     facet = cur->facet;
17264     switch (facet->type) {
17265         case XML_SCHEMA_FACET_LENGTH:
17266         bflength = facet; break;
17267         case XML_SCHEMA_FACET_MINLENGTH:
17268         bfminlen = facet; break;
17269         case XML_SCHEMA_FACET_MININCLUSIVE:
17270         bfmininc = facet; break;
17271         case XML_SCHEMA_FACET_MINEXCLUSIVE:
17272         bfminexc = facet; break;
17273         case XML_SCHEMA_FACET_MAXLENGTH:
17274         bfmaxlen = facet; break;
17275         case XML_SCHEMA_FACET_MAXINCLUSIVE:
17276         bfmaxinc = facet; break;
17277         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17278         bfmaxexc = facet; break;
17279         case XML_SCHEMA_FACET_TOTALDIGITS:
17280         bftotdig = facet; break;
17281         case XML_SCHEMA_FACET_FRACTIONDIGITS:
17282         bffracdig = facet; break;
17283         default:
17284         break;
17285     }
17286     }
17287     /*
17288     * length and minLength or maxLength (2.2) + (3.2)
17289     */
17290     if (flength && (fminlen || fmaxlen)) {
17291     FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17292         "either of 'minLength' or 'maxLength' to be specified on "
17293         "the same type definition")
17294     }
17295     /*
17296     * Mutual exclusions in the same derivation step.
17297     */
17298     if ((fmaxinc) && (fmaxexc)) {
17299     /*
17300     * SCC "maxInclusive and maxExclusive"
17301     */
17302     FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17303     }
17304     if ((fmininc) && (fminexc)) {
17305     /*
17306     * SCC "minInclusive and minExclusive"
17307     */
17308     FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
17309     }
17310 
17311     if (flength && bflength) {
17312     /*
17313     * SCC "length valid restriction"
17314     * The values have to be equal.
17315     */
17316     res = xmlSchemaCompareValues(flength->val, bflength->val);
17317     if (res == -2)
17318         goto internal_error;
17319     if (res != 0)
17320         xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17321     if ((res != 0) && (bflength->fixed)) {
17322         FACET_RESTR_FIXED_ERR(flength)
17323     }
17324 
17325     }
17326     if (fminlen && bfminlen) {
17327     /*
17328     * SCC "minLength valid restriction"
17329     * minLength >= BASE minLength
17330     */
17331     res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17332     if (res == -2)
17333         goto internal_error;
17334     if (res == -1)
17335         xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17336     if ((res != 0) && (bfminlen->fixed)) {
17337         FACET_RESTR_FIXED_ERR(fminlen)
17338     }
17339     }
17340     if (fmaxlen && bfmaxlen) {
17341     /*
17342     * SCC "maxLength valid restriction"
17343     * maxLength <= BASE minLength
17344     */
17345     res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17346     if (res == -2)
17347         goto internal_error;
17348     if (res == 1)
17349         xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17350     if ((res != 0) && (bfmaxlen->fixed)) {
17351         FACET_RESTR_FIXED_ERR(fmaxlen)
17352     }
17353     }
17354     /*
17355     * SCC "length and minLength or maxLength"
17356     */
17357     if (! flength)
17358     flength = bflength;
17359     if (flength) {
17360     if (! fminlen)
17361         fminlen = bfminlen;
17362     if (fminlen) {
17363         /* (1.1) length >= minLength */
17364         res = xmlSchemaCompareValues(flength->val, fminlen->val);
17365         if (res == -2)
17366         goto internal_error;
17367         if (res == -1)
17368         xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17369     }
17370     if (! fmaxlen)
17371         fmaxlen = bfmaxlen;
17372     if (fmaxlen) {
17373         /* (2.1) length <= maxLength */
17374         res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17375         if (res == -2)
17376         goto internal_error;
17377         if (res == 1)
17378         xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17379     }
17380     }
17381     if (fmaxinc) {
17382     /*
17383     * "maxInclusive"
17384     */
17385     if (fmininc) {
17386         /* SCC "maxInclusive >= minInclusive" */
17387         res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17388         if (res == -2)
17389         goto internal_error;
17390         if (res == -1) {
17391         xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17392         }
17393     }
17394     /*
17395     * SCC "maxInclusive valid restriction"
17396     */
17397     if (bfmaxinc) {
17398         /* maxInclusive <= BASE maxInclusive */
17399         res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17400         if (res == -2)
17401         goto internal_error;
17402         if (res == 1)
17403         xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17404         if ((res != 0) && (bfmaxinc->fixed)) {
17405         FACET_RESTR_FIXED_ERR(fmaxinc)
17406         }
17407     }
17408     if (bfmaxexc) {
17409         /* maxInclusive < BASE maxExclusive */
17410         res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17411         if (res == -2)
17412         goto internal_error;
17413         if (res != -1) {
17414         xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17415         }
17416     }
17417     if (bfmininc) {
17418         /* maxInclusive >= BASE minInclusive */
17419         res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17420         if (res == -2)
17421         goto internal_error;
17422         if (res == -1) {
17423         xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17424         }
17425     }
17426     if (bfminexc) {
17427         /* maxInclusive > BASE minExclusive */
17428         res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17429         if (res == -2)
17430         goto internal_error;
17431         if (res != 1) {
17432         xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17433         }
17434     }
17435     }
17436     if (fmaxexc) {
17437     /*
17438     * "maxExclusive >= minExclusive"
17439     */
17440     if (fminexc) {
17441         res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17442         if (res == -2)
17443         goto internal_error;
17444         if (res == -1) {
17445         xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17446         }
17447     }
17448     /*
17449     * "maxExclusive valid restriction"
17450     */
17451     if (bfmaxexc) {
17452         /* maxExclusive <= BASE maxExclusive */
17453         res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17454         if (res == -2)
17455         goto internal_error;
17456         if (res == 1) {
17457         xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17458         }
17459         if ((res != 0) && (bfmaxexc->fixed)) {
17460         FACET_RESTR_FIXED_ERR(fmaxexc)
17461         }
17462     }
17463     if (bfmaxinc) {
17464         /* maxExclusive <= BASE maxInclusive */
17465         res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17466         if (res == -2)
17467         goto internal_error;
17468         if (res == 1) {
17469         xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17470         }
17471     }
17472     if (bfmininc) {
17473         /* maxExclusive > BASE minInclusive */
17474         res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17475         if (res == -2)
17476         goto internal_error;
17477         if (res != 1) {
17478         xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17479         }
17480     }
17481     if (bfminexc) {
17482         /* maxExclusive > BASE minExclusive */
17483         res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17484         if (res == -2)
17485         goto internal_error;
17486         if (res != 1) {
17487         xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17488         }
17489     }
17490     }
17491     if (fminexc) {
17492     /*
17493     * "minExclusive < maxInclusive"
17494     */
17495     if (fmaxinc) {
17496         res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17497         if (res == -2)
17498         goto internal_error;
17499         if (res != -1) {
17500         xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17501         }
17502     }
17503     /*
17504     * "minExclusive valid restriction"
17505     */
17506     if (bfminexc) {
17507         /* minExclusive >= BASE minExclusive */
17508         res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17509         if (res == -2)
17510         goto internal_error;
17511         if (res == -1) {
17512         xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17513         }
17514         if ((res != 0) && (bfminexc->fixed)) {
17515         FACET_RESTR_FIXED_ERR(fminexc)
17516         }
17517     }
17518     if (bfmaxinc) {
17519         /* minExclusive <= BASE maxInclusive */
17520         res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17521         if (res == -2)
17522         goto internal_error;
17523         if (res == 1) {
17524         xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17525         }
17526     }
17527     if (bfmininc) {
17528         /* minExclusive >= BASE minInclusive */
17529         res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17530         if (res == -2)
17531         goto internal_error;
17532         if (res == -1) {
17533         xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17534         }
17535     }
17536     if (bfmaxexc) {
17537         /* minExclusive < BASE maxExclusive */
17538         res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17539         if (res == -2)
17540         goto internal_error;
17541         if (res != -1) {
17542         xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17543         }
17544     }
17545     }
17546     if (fmininc) {
17547     /*
17548     * "minInclusive < maxExclusive"
17549     */
17550     if (fmaxexc) {
17551         res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17552         if (res == -2)
17553         goto internal_error;
17554         if (res != -1) {
17555         xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17556         }
17557     }
17558     /*
17559     * "minExclusive valid restriction"
17560     */
17561     if (bfmininc) {
17562         /* minInclusive >= BASE minInclusive */
17563         res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17564         if (res == -2)
17565         goto internal_error;
17566         if (res == -1) {
17567         xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17568         }
17569         if ((res != 0) && (bfmininc->fixed)) {
17570         FACET_RESTR_FIXED_ERR(fmininc)
17571         }
17572     }
17573     if (bfmaxinc) {
17574         /* minInclusive <= BASE maxInclusive */
17575         res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17576         if (res == -2)
17577         goto internal_error;
17578         if (res == 1) {
17579         xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17580         }
17581     }
17582     if (bfminexc) {
17583         /* minInclusive > BASE minExclusive */
17584         res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17585         if (res == -2)
17586         goto internal_error;
17587         if (res != 1)
17588         xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17589     }
17590     if (bfmaxexc) {
17591         /* minInclusive < BASE maxExclusive */
17592         res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17593         if (res == -2)
17594         goto internal_error;
17595         if (res != -1)
17596         xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17597     }
17598     }
17599     if (ftotdig && bftotdig) {
17600     /*
17601     * SCC " totalDigits valid restriction"
17602     * totalDigits <= BASE totalDigits
17603     */
17604     res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17605     if (res == -2)
17606         goto internal_error;
17607     if (res == 1)
17608         xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17609         -1, 1, 1);
17610     if ((res != 0) && (bftotdig->fixed)) {
17611         FACET_RESTR_FIXED_ERR(ftotdig)
17612     }
17613     }
17614     if (ffracdig && bffracdig) {
17615     /*
17616     * SCC  "fractionDigits valid restriction"
17617     * fractionDigits <= BASE fractionDigits
17618     */
17619     res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17620     if (res == -2)
17621         goto internal_error;
17622     if (res == 1)
17623         xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17624         -1, 1, 1);
17625     if ((res != 0) && (bffracdig->fixed)) {
17626         FACET_RESTR_FIXED_ERR(ffracdig)
17627     }
17628     }
17629     /*
17630     * SCC "fractionDigits less than or equal to totalDigits"
17631     */
17632     if (! ftotdig)
17633     ftotdig = bftotdig;
17634     if (! ffracdig)
17635     ffracdig = bffracdig;
17636     if (ftotdig && ffracdig) {
17637     res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17638     if (res == -2)
17639         goto internal_error;
17640     if (res == 1)
17641         xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17642         -1, 1, 0);
17643     }
17644     /*
17645     * *Enumerations* won' be added here, since only the first set
17646     * of enumerations in the ancestor-or-self axis is used
17647     * for validation, plus we need to use the base type of those
17648     * enumerations for whitespace.
17649     *
17650     * *Patterns*: won't be add here, since they are ORed at
17651     * type level and ANDed at ancestor level. This will
17652     * happed during validation by walking the base axis
17653     * of the type.
17654     */
17655     for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17656     bfacet = cur->facet;
17657     /*
17658     * Special handling of enumerations and patterns.
17659     * TODO: hmm, they should not appear in the set, so remove this.
17660     */
17661     if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
17662         (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
17663         continue;
17664     /*
17665     * Search for a duplicate facet in the current type.
17666     */
17667     link = type->facetSet;
17668     /* err = 0; */
17669     /* fixedErr = 0; */
17670     while (link != NULL) {
17671         facet = link->facet;
17672         if (facet->type == bfacet->type) {
17673         switch (facet->type) {
17674             case XML_SCHEMA_FACET_WHITESPACE:
17675             /*
17676             * The whitespace must be stronger.
17677             */
17678             if (facet->whitespace < bfacet->whitespace) {
17679                 FACET_RESTR_ERR(facet,
17680                 "The 'whitespace' value has to be equal to "
17681                 "or stronger than the 'whitespace' value of "
17682                 "the base type")
17683             }
17684             if ((bfacet->fixed) &&
17685                 (facet->whitespace != bfacet->whitespace)) {
17686                 FACET_RESTR_FIXED_ERR(facet)
17687             }
17688             break;
17689             default:
17690             break;
17691         }
17692         /* Duplicate found. */
17693         break;
17694         }
17695         link = link->next;
17696     }
17697     /*
17698     * If no duplicate was found: add the base types's facet
17699     * to the set.
17700     */
17701     if (link == NULL) {
17702         link = (xmlSchemaFacetLinkPtr)
17703         xmlMalloc(sizeof(xmlSchemaFacetLink));
17704         if (link == NULL) {
17705         xmlSchemaPErrMemory(pctxt,
17706             "deriving facets, creating a facet link", NULL);
17707         return (-1);
17708         }
17709         link->facet = cur->facet;
17710         link->next = NULL;
17711         if (last == NULL)
17712         type->facetSet = link;
17713         else
17714         last->next = link;
17715         last = link;
17716     }
17717 
17718     }
17719 
17720     return (0);
17721 internal_error:
17722     PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17723     "an error occured");
17724     return (-1);
17725 }
17726 
17727 static int
17728 xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17729                          xmlSchemaTypePtr type)
17730 {
17731     xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17732     /*
17733     * The actual value is then formed by replacing any union type
17734     * definition in the �explicit members� with the members of their
17735     * {member type definitions}, in order.
17736     *
17737     * TODO: There's a bug entry at
17738     * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17739     * which indicates that we'll keep the union types the future.
17740     */
17741     link = type->memberTypes;
17742     while (link != NULL) {
17743 
17744     if (WXS_IS_TYPE_NOT_FIXED(link->type))
17745         xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
17746 
17747     if (WXS_IS_UNION(link->type)) {
17748         subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
17749         if (subLink != NULL) {
17750         link->type = subLink->type;
17751         if (subLink->next != NULL) {
17752             lastLink = link->next;
17753             subLink = subLink->next;
17754             prevLink = link;
17755             while (subLink != NULL) {
17756             newLink = (xmlSchemaTypeLinkPtr)
17757                 xmlMalloc(sizeof(xmlSchemaTypeLink));
17758             if (newLink == NULL) {
17759                 xmlSchemaPErrMemory(pctxt, "allocating a type link",
17760                 NULL);
17761                 return (-1);
17762             }
17763             newLink->type = subLink->type;
17764             prevLink->next = newLink;
17765             prevLink = newLink;
17766             newLink->next = lastLink;
17767 
17768             subLink = subLink->next;
17769             }
17770         }
17771         }
17772     }
17773     link = link->next;
17774     }
17775     return (0);
17776 }
17777 
17778 static void
17779 xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17780 {
17781     int has = 0, needVal = 0, normVal = 0;
17782 
17783     has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17784     if (has) {
17785     needVal = (type->baseType->flags &
17786         XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17787     normVal = (type->baseType->flags &
17788         XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17789     }
17790     if (type->facets != NULL) {
17791     xmlSchemaFacetPtr fac;
17792 
17793     for (fac = type->facets; fac != NULL; fac = fac->next) {
17794         switch (fac->type) {
17795         case XML_SCHEMA_FACET_WHITESPACE:
17796             break;
17797         case XML_SCHEMA_FACET_PATTERN:
17798             normVal = 1;
17799             has = 1;
17800             break;
17801         case XML_SCHEMA_FACET_ENUMERATION:
17802             needVal = 1;
17803             normVal = 1;
17804             has = 1;
17805             break;
17806         default:
17807             has = 1;
17808             break;
17809         }
17810     }
17811     }
17812     if (normVal)
17813     type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17814     if (needVal)
17815     type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17816     if (has)
17817     type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17818 
17819     if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
17820     xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17821     /*
17822     * OPTIMIZE VAL TODO: Some facets need a computed value.
17823     */
17824     if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17825         (prim->builtInType != XML_SCHEMAS_STRING)) {
17826         type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17827     }
17828     }
17829 }
17830 
17831 static int
17832 xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17833 {
17834 
17835 
17836     /*
17837     * Evaluate the whitespace-facet value.
17838     */
17839     if (WXS_IS_LIST(type)) {
17840     type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17841     return (0);
17842     } else if (WXS_IS_UNION(type))
17843     return (0);
17844 
17845     if (type->facetSet != NULL) {
17846     xmlSchemaFacetLinkPtr lin;
17847 
17848     for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17849         if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17850         switch (lin->facet->whitespace) {
17851         case XML_SCHEMAS_FACET_PRESERVE:
17852             type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17853             break;
17854         case XML_SCHEMAS_FACET_REPLACE:
17855             type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17856             break;
17857         case XML_SCHEMAS_FACET_COLLAPSE:
17858             type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17859             break;
17860         default:
17861             return (-1);
17862         }
17863         return (0);
17864         }
17865     }
17866     }
17867     /*
17868     * For all �atomic� datatypes other than string (and types �derived�
17869     * by �restriction� from it) the value of whiteSpace is fixed to
17870     * collapse
17871     */
17872     {
17873     xmlSchemaTypePtr anc;
17874 
17875     for (anc = type->baseType; anc != NULL &&
17876         anc->builtInType != XML_SCHEMAS_ANYTYPE;
17877         anc = anc->baseType) {
17878 
17879         if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17880         if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17881             type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17882 
17883         } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17884             (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17885             type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17886 
17887         } else
17888             type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17889         break;
17890         }
17891     }
17892     }
17893     return (0);
17894 }
17895 
17896 static int
17897 xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17898               xmlSchemaTypePtr type)
17899 {
17900     if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17901     return(0);
17902     if (! WXS_IS_TYPE_NOT_FIXED_1(type))
17903     return(0);
17904     type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
17905 
17906     if (WXS_IS_LIST(type)) {
17907     /*
17908     * Corresponds to <simpleType><list>...
17909     */
17910     if (type->subtypes == NULL) {
17911         /*
17912         * This one is really needed, so get out.
17913         */
17914         PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17915         "list type has no item-type assigned");
17916         return(-1);
17917     }
17918     } else if (WXS_IS_UNION(type)) {
17919     /*
17920     * Corresponds to <simpleType><union>...
17921     */
17922     if (type->memberTypes == NULL) {
17923         /*
17924         * This one is really needed, so get out.
17925         */
17926         PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17927         "union type has no member-types assigned");
17928         return(-1);
17929     }
17930     } else {
17931     /*
17932     * Corresponds to <simpleType><restriction>...
17933     */
17934     if (type->baseType == NULL) {
17935         PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17936         "type has no base-type assigned");
17937         return(-1);
17938     }
17939     if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
17940         if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17941         return(-1);
17942     /*
17943     * Variety
17944     * If the <restriction> alternative is chosen, then the
17945     * {variety} of the {base type definition}.
17946     */
17947     if (WXS_IS_ATOMIC(type->baseType))
17948         type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
17949     else if (WXS_IS_LIST(type->baseType)) {
17950         type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
17951         /*
17952         * Inherit the itemType.
17953         */
17954         type->subtypes = type->baseType->subtypes;
17955     } else if (WXS_IS_UNION(type->baseType)) {
17956         type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
17957         /*
17958         * NOTE that we won't assign the memberTypes of the base,
17959         * since this will make trouble when freeing them; we will
17960         * use a lookup function to access them instead.
17961         */
17962     }
17963     }
17964     return(0);
17965 }
17966 
17967 #ifdef DEBUG_TYPE
17968 static void
17969 xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
17970                xmlSchemaTypePtr type)
17971 {
17972     if (type->node != NULL) {
17973         xmlGenericError(xmlGenericErrorContext,
17974                         "Type of %s : %s:%d :", name,
17975                         type->node->doc->URL,
17976                         xmlGetLineNo(type->node));
17977     } else {
17978         xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
17979     }
17980     if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
17981     switch (type->contentType) {
17982         case XML_SCHEMA_CONTENT_SIMPLE:
17983         xmlGenericError(xmlGenericErrorContext, "simple\n");
17984         break;
17985         case XML_SCHEMA_CONTENT_ELEMENTS:
17986         xmlGenericError(xmlGenericErrorContext, "elements\n");
17987         break;
17988         case XML_SCHEMA_CONTENT_UNKNOWN:
17989         xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
17990         break;
17991         case XML_SCHEMA_CONTENT_EMPTY:
17992         xmlGenericError(xmlGenericErrorContext, "empty\n");
17993         break;
17994         case XML_SCHEMA_CONTENT_MIXED:
17995         if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
17996             type->subtypes))
17997             xmlGenericError(xmlGenericErrorContext,
17998             "mixed as emptiable particle\n");
17999         else
18000             xmlGenericError(xmlGenericErrorContext, "mixed\n");
18001         break;
18002         /* Removed, since not used. */
18003         /*
18004         case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
18005         xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
18006         break;
18007         */
18008         case XML_SCHEMA_CONTENT_BASIC:
18009         xmlGenericError(xmlGenericErrorContext, "basic\n");
18010         break;
18011         default:
18012         xmlGenericError(xmlGenericErrorContext,
18013             "not registered !!!\n");
18014         break;
18015     }
18016     }
18017 }
18018 #endif
18019 
18020 /*
18021 * 3.14.6 Constraints on Simple Type Definition Schema Components
18022 */
18023 static int
18024 xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
18025                  xmlSchemaTypePtr type)
18026 {
18027     int res, olderrs = pctxt->nberrors;
18028 
18029     if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18030     return(-1);
18031 
18032     if (! WXS_IS_TYPE_NOT_FIXED(type))
18033     return(0);
18034 
18035     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18036     type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
18037 
18038     if (type->baseType == NULL) {
18039     PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
18040         "missing baseType");
18041     goto exit_failure;
18042     }
18043     if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
18044     xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
18045     /*
18046     * If a member type of a union is a union itself, we need to substitute
18047     * that member type for its member types.
18048     * NOTE that this might change in WXS 1.1; i.e. we will keep the union
18049     * types in WXS 1.1.
18050     */
18051     if ((type->memberTypes != NULL) &&
18052     (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
18053     return(-1);
18054     /*
18055     * SPEC src-simple-type 1
18056     * "The corresponding simple type definition, if any, must satisfy
18057     * the conditions set out in Constraints on Simple Type Definition
18058     * Schema Components (�3.14.6)."
18059     */
18060     /*
18061     * Schema Component Constraint: Simple Type Definition Properties Correct
18062     * (st-props-correct)
18063     */
18064     res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
18065     HFAILURE HERROR
18066     /*
18067     * Schema Component Constraint: Derivation Valid (Restriction, Simple)
18068     * (cos-st-restricts)
18069     */
18070     res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
18071     HFAILURE HERROR
18072     /*
18073     * TODO: Removed the error report, since it got annoying to get an
18074     * extra error report, if anything failed until now.
18075     * Enable this if needed.
18076     *
18077     * xmlSchemaPErr(ctxt, type->node,
18078     *    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
18079     *    "Simple type '%s' does not satisfy the constraints "
18080     *    "on simple type definitions.\n",
18081     *    type->name, NULL);
18082     */
18083     /*
18084     * Schema Component Constraint: Simple Type Restriction (Facets)
18085     * (st-restrict-facets)
18086     */
18087     res = xmlSchemaCheckFacetValues(type, pctxt);
18088     HFAILURE HERROR
18089     if ((type->facetSet != NULL) ||
18090     (type->baseType->facetSet != NULL)) {
18091     res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18092     HFAILURE HERROR
18093     }
18094     /*
18095     * Whitespace value.
18096     */
18097     res = xmlSchemaTypeFixupWhitespace(type);
18098     HFAILURE HERROR
18099     xmlSchemaTypeFixupOptimFacets(type);
18100 
18101 exit_error:
18102 #ifdef DEBUG_TYPE
18103     xmlSchemaDebugFixedType(pctxt, type);
18104 #endif
18105     if (olderrs != pctxt->nberrors)
18106     return(pctxt->err);
18107     return(0);
18108 
18109 exit_failure:
18110 #ifdef DEBUG_TYPE
18111     xmlSchemaDebugFixedType(pctxt, type);
18112 #endif
18113     return(-1);
18114 }
18115 
18116 static int
18117 xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18118               xmlSchemaTypePtr type)
18119 {
18120     int res = 0, olderrs = pctxt->nberrors;
18121     xmlSchemaTypePtr baseType = type->baseType;
18122 
18123     if (! WXS_IS_TYPE_NOT_FIXED(type))
18124     return(0);
18125     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18126     if (baseType == NULL) {
18127     PERROR_INT("xmlSchemaFixupComplexType",
18128         "missing baseType");
18129     goto exit_failure;
18130     }
18131     /*
18132     * Fixup the base type.
18133     */
18134     if (WXS_IS_TYPE_NOT_FIXED(baseType))
18135     xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
18136     if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18137     /*
18138     * Skip fixup if the base type is invalid.
18139     * TODO: Generate a warning!
18140     */
18141     return(0);
18142     }
18143     /*
18144     * This basically checks if the base type can be derived.
18145     */
18146     res = xmlSchemaCheckSRCCT(pctxt, type);
18147     HFAILURE HERROR
18148     /*
18149     * Fixup the content type.
18150     */
18151     if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18152     /*
18153     * Corresponds to <complexType><simpleContent>...
18154     */
18155     if ((WXS_IS_COMPLEX(baseType)) &&
18156         (baseType->contentTypeDef != NULL) &&
18157         (WXS_IS_RESTRICTION(type))) {
18158         xmlSchemaTypePtr contentBase, content;
18159 #ifdef ENABLE_NAMED_LOCALS
18160         char buf[30];
18161         const xmlChar *tmpname;
18162 #endif
18163         /*
18164         * SPEC (1) If <restriction> + base type is <complexType>,
18165         * "whose own {content type} is a simple type..."
18166         */
18167         if (type->contentTypeDef != NULL) {
18168         /*
18169         * SPEC (1.1) "the simple type definition corresponding to the
18170         * <simpleType> among the [children] of <restriction> if there
18171         * is one;"
18172         * Note that this "<simpleType> among the [children]" was put
18173         * into ->contentTypeDef during parsing.
18174         */
18175         contentBase = type->contentTypeDef;
18176         type->contentTypeDef = NULL;
18177         } else {
18178         /*
18179         * (1.2) "...otherwise (<restriction> has no <simpleType>
18180         * among its [children]), the simple type definition which
18181         * is the {content type} of the ... base type."
18182         */
18183         contentBase = baseType->contentTypeDef;
18184         }
18185         /*
18186         * SPEC
18187         * "... a simple type definition which restricts the simple
18188         * type definition identified in clause 1.1 or clause 1.2
18189         * with a set of facet components"
18190         *
18191         * Create the anonymous simple type, which will be the content
18192         * type of the complex type.
18193         */
18194 #ifdef ENABLE_NAMED_LOCALS
18195         snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18196         tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
18197         content = xmlSchemaAddType(pctxt, pctxt->schema,
18198         XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
18199         type->node, 0);
18200 #else
18201         content = xmlSchemaAddType(pctxt, pctxt->schema,
18202         XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
18203         type->node, 0);
18204 #endif
18205         if (content == NULL)
18206         goto exit_failure;
18207         /*
18208         * We will use the same node as for the <complexType>
18209         * to have it somehow anchored in the schema doc.
18210         */
18211         content->type = XML_SCHEMA_TYPE_SIMPLE;
18212         content->baseType = contentBase;
18213         /*
18214         * Move the facets, previously anchored on the
18215         * complexType during parsing.
18216         */
18217         content->facets = type->facets;
18218         type->facets = NULL;
18219         content->facetSet = type->facetSet;
18220         type->facetSet = NULL;
18221 
18222         type->contentTypeDef = content;
18223         if (WXS_IS_TYPE_NOT_FIXED(contentBase))
18224         xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
18225         /*
18226         * Fixup the newly created type. We don't need to check
18227         * for circularity here.
18228         */
18229         res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18230         HFAILURE HERROR
18231         res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18232         HFAILURE HERROR
18233 
18234     } else if ((WXS_IS_COMPLEX(baseType)) &&
18235         (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18236         (WXS_IS_RESTRICTION(type))) {
18237         /*
18238         * SPEC (2) If <restriction> + base is a mixed <complexType> with
18239         * an emptiable particle, then a simple type definition which
18240         * restricts the <restriction>'s <simpleType> child.
18241         */
18242         if ((type->contentTypeDef == NULL) ||
18243         (type->contentTypeDef->baseType == NULL)) {
18244         /*
18245         * TODO: Check if this ever happens.
18246         */
18247         xmlSchemaPCustomErr(pctxt,
18248             XML_SCHEMAP_INTERNAL,
18249             WXS_BASIC_CAST type, NULL,
18250             "Internal error: xmlSchemaTypeFixup, "
18251             "complex type '%s': the <simpleContent><restriction> "
18252             "is missing a <simpleType> child, but was not catched "
18253             "by xmlSchemaCheckSRCCT()", type->name);
18254         goto exit_failure;
18255         }
18256     } else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
18257         /*
18258         * SPEC (3) If <extension> + base is <complexType> with
18259         * <simpleType> content, "...then the {content type} of that
18260         * complex type definition"
18261         */
18262         if (baseType->contentTypeDef == NULL) {
18263         /*
18264         * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18265         * should have catched this already.
18266         */
18267         xmlSchemaPCustomErr(pctxt,
18268             XML_SCHEMAP_INTERNAL,
18269             WXS_BASIC_CAST type, NULL,
18270             "Internal error: xmlSchemaTypeFixup, "
18271             "complex type '%s': the <extension>ed base type is "
18272             "a complex type with no simple content type",
18273             type->name);
18274         goto exit_failure;
18275         }
18276         type->contentTypeDef = baseType->contentTypeDef;
18277     } else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
18278         /*
18279         * SPEC (4) <extension> + base is <simpleType>
18280         * "... then that simple type definition"
18281         */
18282         type->contentTypeDef = baseType;
18283     } else {
18284         /*
18285         * TODO: Check if this ever happens.
18286         */
18287         xmlSchemaPCustomErr(pctxt,
18288         XML_SCHEMAP_INTERNAL,
18289         WXS_BASIC_CAST type, NULL,
18290         "Internal error: xmlSchemaTypeFixup, "
18291         "complex type '%s' with <simpleContent>: unhandled "
18292         "derivation case", type->name);
18293         goto exit_failure;
18294     }
18295     } else {
18296     int dummySequence = 0;
18297     xmlSchemaParticlePtr particle =
18298         (xmlSchemaParticlePtr) type->subtypes;
18299     /*
18300     * Corresponds to <complexType><complexContent>...
18301     *
18302     * NOTE that the effective mixed was already set during parsing of
18303     * <complexType> and <complexContent>; its flag value is
18304     * XML_SCHEMAS_TYPE_MIXED.
18305     *
18306     * Compute the "effective content":
18307     * (2.1.1) + (2.1.2) + (2.1.3)
18308     */
18309     if ((particle == NULL) ||
18310         ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18311         ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18312         (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18313         ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18314         (particle->minOccurs == 0))) &&
18315         ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18316         if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18317         /*
18318         * SPEC (2.1.4) "If the �effective mixed� is true, then
18319         * a particle whose properties are as follows:..."
18320         *
18321         * Empty sequence model group with
18322         * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18323         * NOTE that we sill assign it the <complexType> node to
18324         * somehow anchor it in the doc.
18325         */
18326         if ((particle == NULL) ||
18327             (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18328             /*
18329             * Create the particle.
18330             */
18331             particle = xmlSchemaAddParticle(pctxt,
18332             type->node, 1, 1);
18333             if (particle == NULL)
18334             goto exit_failure;
18335             /*
18336             * Create the model group.
18337             */ /* URGENT TODO: avoid adding to pending items. */
18338             particle->children = (xmlSchemaTreeItemPtr)
18339             xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18340             XML_SCHEMA_TYPE_SEQUENCE, type->node);
18341             if (particle->children == NULL)
18342             goto exit_failure;
18343 
18344             type->subtypes = (xmlSchemaTypePtr) particle;
18345         }
18346         dummySequence = 1;
18347         type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18348         } else {
18349         /*
18350         * SPEC (2.1.5) "otherwise empty"
18351         */
18352         type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18353         }
18354     } else {
18355         /*
18356         * SPEC (2.2) "otherwise the particle corresponding to the
18357         * <all>, <choice>, <group> or <sequence> among the
18358         * [children]."
18359         */
18360         type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18361     }
18362     /*
18363     * Compute the "content type".
18364     */
18365     if (WXS_IS_RESTRICTION(type)) {
18366         /*
18367         * SPEC (3.1) "If <restriction>..."
18368         * (3.1.1) + (3.1.2) */
18369         if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18370         if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18371             type->contentType = XML_SCHEMA_CONTENT_MIXED;
18372         }
18373     } else {
18374         /*
18375         * SPEC (3.2) "If <extension>..."
18376         */
18377         if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18378         /*
18379         * SPEC (3.2.1)
18380         * "If the �effective content� is empty, then the
18381         *  {content type} of the [...] base ..."
18382         */
18383         type->contentType = baseType->contentType;
18384         type->subtypes = baseType->subtypes;
18385         /*
18386         * Fixes bug #347316:
18387         * This is the case when the base type has a simple
18388         * type definition as content.
18389         */
18390         type->contentTypeDef = baseType->contentTypeDef;
18391         /*
18392         * NOTE that the effective mixed is ignored here.
18393         */
18394         } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18395         /*
18396         * SPEC (3.2.2)
18397         */
18398         if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18399             type->contentType = XML_SCHEMA_CONTENT_MIXED;
18400         } else {
18401         /*
18402         * SPEC (3.2.3)
18403         */
18404         if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18405             type->contentType = XML_SCHEMA_CONTENT_MIXED;
18406             /*
18407             * "A model group whose {compositor} is sequence and whose
18408             * {particles} are..."
18409             */
18410         if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18411             (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18412             ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18413             XML_SCHEMA_TYPE_ALL))
18414         {
18415             /*
18416             * SPEC cos-all-limited (1)
18417             */
18418             xmlSchemaCustomErr(ACTXT_CAST pctxt,
18419             /* TODO: error code */
18420             XML_SCHEMAP_COS_ALL_LIMITED,
18421             WXS_ITEM_NODE(type), NULL,
18422             "The type has an 'all' model group in its "
18423             "{content type} and thus cannot be derived from "
18424             "a non-empty type, since this would produce a "
18425             "'sequence' model group containing the 'all' "
18426             "model group; 'all' model groups are not "
18427             "allowed to appear inside other model groups",
18428             NULL, NULL);
18429 
18430         } else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18431             (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18432             ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18433             XML_SCHEMA_TYPE_ALL))
18434         {
18435             /*
18436             * SPEC cos-all-limited (1)
18437             */
18438             xmlSchemaCustomErr(ACTXT_CAST pctxt,
18439             /* TODO: error code */
18440             XML_SCHEMAP_COS_ALL_LIMITED,
18441             WXS_ITEM_NODE(type), NULL,
18442             "A type cannot be derived by extension from a type "
18443             "which has an 'all' model group in its "
18444             "{content type}, since this would produce a "
18445             "'sequence' model group containing the 'all' "
18446             "model group; 'all' model groups are not "
18447             "allowed to appear inside other model groups",
18448             NULL, NULL);
18449 
18450         } else if (! dummySequence) {
18451             xmlSchemaTreeItemPtr effectiveContent =
18452             (xmlSchemaTreeItemPtr) type->subtypes;
18453             /*
18454             * Create the particle.
18455             */
18456             particle = xmlSchemaAddParticle(pctxt,
18457             type->node, 1, 1);
18458             if (particle == NULL)
18459             goto exit_failure;
18460             /*
18461             * Create the "sequence" model group.
18462             */
18463             particle->children = (xmlSchemaTreeItemPtr)
18464             xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18465             XML_SCHEMA_TYPE_SEQUENCE, type->node);
18466             if (particle->children == NULL)
18467             goto exit_failure;
18468             WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
18469             /*
18470             * SPEC "the particle of the {content type} of
18471             * the ... base ..."
18472             * Create a duplicate of the base type's particle
18473             * and assign its "term" to it.
18474             */
18475             particle->children->children =
18476             (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18477             type->node,
18478             ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
18479             ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
18480             if (particle->children->children == NULL)
18481             goto exit_failure;
18482             particle = (xmlSchemaParticlePtr)
18483             particle->children->children;
18484             particle->children =
18485             ((xmlSchemaParticlePtr) baseType->subtypes)->children;
18486             /*
18487             * SPEC "followed by the �effective content�."
18488             */
18489             particle->next = effectiveContent;
18490             /*
18491             * This all will result in:
18492             * new-particle
18493             *   --> new-sequence(
18494             *         new-particle
18495             *           --> base-model,
18496             *         this-particle
18497             *           --> this-model
18498             *       )
18499             */
18500         } else {
18501             /*
18502             * This is the case when there is already an empty
18503             * <sequence> with minOccurs==maxOccurs==1.
18504             * Just add the base types's content type.
18505             * NOTE that, although we miss to add an intermediate
18506             * <sequence>, this should produce no difference to
18507             * neither the regex compilation of the content model,
18508             * nor to the complex type contraints.
18509             */
18510             particle->children->children =
18511             (xmlSchemaTreeItemPtr) baseType->subtypes;
18512         }
18513         }
18514     }
18515     }
18516     /*
18517     * Now fixup attribute uses:
18518     *   - expand attr. group references
18519     *     - intersect attribute wildcards
18520     *   - inherit attribute uses of the base type
18521     *   - inherit or union attr. wildcards if extending
18522     *   - apply attr. use prohibitions if restricting
18523     */
18524     res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
18525     HFAILURE HERROR
18526     /*
18527     * Apply the complex type component constraints; this will not
18528     * check attributes, since this is done in
18529     * xmlSchemaFixupTypeAttributeUses().
18530     */
18531     res = xmlSchemaCheckCTComponent(pctxt, type);
18532     HFAILURE HERROR
18533 
18534 #ifdef DEBUG_TYPE
18535     xmlSchemaDebugFixedType(pctxt, type);
18536 #endif
18537     if (olderrs != pctxt->nberrors)
18538     return(pctxt->err);
18539     else
18540     return(0);
18541 
18542 exit_error:
18543     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18544 #ifdef DEBUG_TYPE
18545     xmlSchemaDebugFixedType(pctxt, type);
18546 #endif
18547     return(pctxt->err);
18548 
18549 exit_failure:
18550     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18551 #ifdef DEBUG_TYPE
18552     xmlSchemaDebugFixedType(pctxt, type);
18553 #endif
18554     return(-1);
18555 }
18556 
18557 
18566 static int
18567 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
18568                    xmlSchemaAbstractCtxtPtr actxt)
18569 {
18570     if (type == NULL)
18571         return(0);
18572     if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18573     AERROR_INT("xmlSchemaTypeFixup",
18574         "this function needs a parser context");
18575     return(-1);
18576     }
18577     if (! WXS_IS_TYPE_NOT_FIXED(type))
18578     return(0);
18579     if (type->type == XML_SCHEMA_TYPE_COMPLEX)
18580     return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
18581     else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
18582     return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
18583     return(0);
18584 }
18585 
18598 int
18599 xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
18600                     xmlSchemaTypePtr typeDecl,
18601                     xmlSchemaParserCtxtPtr pctxt,
18602             const xmlChar * name ATTRIBUTE_UNUSED)
18603 {
18604     int ret = 0, ctxtGiven;
18605 
18606     if ((facet == NULL) || (typeDecl == NULL))
18607         return(-1);
18608     /*
18609     * TODO: will the parser context be given if used from
18610     * the relaxNG module?
18611     */
18612     if (pctxt == NULL)
18613     ctxtGiven = 0;
18614     else
18615     ctxtGiven = 1;
18616 
18617     switch (facet->type) {
18618         case XML_SCHEMA_FACET_MININCLUSIVE:
18619         case XML_SCHEMA_FACET_MINEXCLUSIVE:
18620         case XML_SCHEMA_FACET_MAXINCLUSIVE:
18621         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18622     case XML_SCHEMA_FACET_ENUMERATION: {
18623                 /*
18624                  * Okay we need to validate the value
18625                  * at that point.
18626                  */
18627         xmlSchemaTypePtr base;
18628 
18629         /* 4.3.5.5 Constraints on enumeration Schema Components
18630         * Schema Component Constraint: enumeration valid restriction
18631         * It is an �error� if any member of {value} is not in the
18632         * �value space� of {base type definition}.
18633         *
18634         * minInclusive, maxInclusive, minExclusive, maxExclusive:
18635         * The value �must� be in the
18636         * �value space� of the �base type�.
18637         */
18638         /*
18639         * This function is intended to deliver a compiled value
18640         * on the facet. In this implementation of XML Schemata the
18641         * type holding a facet, won't be a built-in type.
18642         * Thus to ensure that other API
18643         * calls (relaxng) do work, if the given type is a built-in
18644         * type, we will assume that the given built-in type *is
18645         * already* the base type.
18646         */
18647         if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18648             base = typeDecl->baseType;
18649             if (base == NULL) {
18650             PERROR_INT("xmlSchemaCheckFacet",
18651                 "a type user derived type has no base type");
18652             return (-1);
18653             }
18654         } else
18655             base = typeDecl;
18656 
18657         if (! ctxtGiven) {
18658             /*
18659             * A context is needed if called from RelaxNG.
18660             */
18661             pctxt = xmlSchemaNewParserCtxt("*");
18662             if (pctxt == NULL)
18663             return (-1);
18664         }
18665         /*
18666         * NOTE: This call does not check the content nodes,
18667         * since they are not available:
18668         * facet->node is just the node holding the facet
18669         * definition, *not* the attribute holding the *value*
18670         * of the facet.
18671         */
18672         ret = xmlSchemaVCheckCVCSimpleType(
18673             ACTXT_CAST pctxt, facet->node, base,
18674             facet->value, &(facet->val), 1, 1, 0);
18675                 if (ret != 0) {
18676             if (ret < 0) {
18677             /* No error message for RelaxNG. */
18678             if (ctxtGiven) {
18679                 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18680                 XML_SCHEMAP_INTERNAL, facet->node, NULL,
18681                 "Internal error: xmlSchemaCheckFacet, "
18682                 "failed to validate the value '%s' of the "
18683                 "facet '%s' against the base type",
18684                 facet->value, xmlSchemaFacetTypeToString(facet->type));
18685             }
18686             goto internal_error;
18687             }
18688             ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18689             /* No error message for RelaxNG. */
18690             if (ctxtGiven) {
18691             xmlChar *str = NULL;
18692 
18693             xmlSchemaCustomErr(ACTXT_CAST pctxt,
18694                 ret, facet->node, WXS_BASIC_CAST facet,
18695                 "The value '%s' of the facet does not validate "
18696                 "against the base type '%s'",
18697                 facet->value,
18698                 xmlSchemaFormatQName(&str,
18699                 base->targetNamespace, base->name));
18700             FREE_AND_NULL(str);
18701             }
18702             goto exit;
18703                 } else if (facet->val == NULL) {
18704             if (ctxtGiven) {
18705             PERROR_INT("xmlSchemaCheckFacet",
18706                 "value was not computed");
18707             }
18708             TODO
18709         }
18710                 break;
18711             }
18712         case XML_SCHEMA_FACET_PATTERN:
18713             facet->regexp = xmlRegexpCompile(facet->value);
18714             if (facet->regexp == NULL) {
18715         ret = XML_SCHEMAP_REGEXP_INVALID;
18716         /* No error message for RelaxNG. */
18717         if (ctxtGiven) {
18718             xmlSchemaCustomErr(ACTXT_CAST pctxt,
18719             ret, facet->node, WXS_BASIC_CAST typeDecl,
18720             "The value '%s' of the facet 'pattern' is not a "
18721             "valid regular expression",
18722             facet->value, NULL);
18723         }
18724             }
18725             break;
18726         case XML_SCHEMA_FACET_TOTALDIGITS:
18727         case XML_SCHEMA_FACET_FRACTIONDIGITS:
18728         case XML_SCHEMA_FACET_LENGTH:
18729         case XML_SCHEMA_FACET_MAXLENGTH:
18730         case XML_SCHEMA_FACET_MINLENGTH:
18731 
18732         if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18733         ret = xmlSchemaValidatePredefinedType(
18734             xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18735             facet->value, &(facet->val));
18736         } else {
18737         ret = xmlSchemaValidatePredefinedType(
18738             xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18739             facet->value, &(facet->val));
18740         }
18741         if (ret != 0) {
18742         if (ret < 0) {
18743             /* No error message for RelaxNG. */
18744             if (ctxtGiven) {
18745             PERROR_INT("xmlSchemaCheckFacet",
18746                 "validating facet value");
18747             }
18748             goto internal_error;
18749         }
18750         ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18751         /* No error message for RelaxNG. */
18752         if (ctxtGiven) {
18753             /* error code */
18754             xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18755             ret, facet->node, WXS_BASIC_CAST typeDecl,
18756             "The value '%s' of the facet '%s' is not a valid '%s'",
18757             facet->value,
18758             xmlSchemaFacetTypeToString(facet->type),
18759             (facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18760                 BAD_CAST "nonNegativeInteger" :
18761                 BAD_CAST "positiveInteger",
18762             NULL);
18763         }
18764         }
18765         break;
18766 
18767         case XML_SCHEMA_FACET_WHITESPACE:{
18768                 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18769                     facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18770                 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18771                     facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18772                 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18773                     facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18774                 } else {
18775             ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18776                     /* No error message for RelaxNG. */
18777             if (ctxtGiven) {
18778             /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
18779             xmlSchemaCustomErr(ACTXT_CAST pctxt,
18780                 ret, facet->node, WXS_BASIC_CAST typeDecl,
18781                 "The value '%s' of the facet 'whitespace' is not "
18782                 "valid", facet->value, NULL);
18783                     }
18784                 }
18785             }
18786         default:
18787             break;
18788     }
18789 exit:
18790     if ((! ctxtGiven) && (pctxt != NULL))
18791     xmlSchemaFreeParserCtxt(pctxt);
18792     return (ret);
18793 internal_error:
18794     if ((! ctxtGiven) && (pctxt != NULL))
18795     xmlSchemaFreeParserCtxt(pctxt);
18796     return (-1);
18797 }
18798 
18806 static int
18807 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
18808               xmlSchemaParserCtxtPtr pctxt)
18809 {
18810     int res, olderrs = pctxt->nberrors;
18811     const xmlChar *name = typeDecl->name;
18812     /*
18813     * NOTE: It is intended to use the facets list, instead
18814     * of facetSet.
18815     */
18816     if (typeDecl->facets != NULL) {
18817     xmlSchemaFacetPtr facet = typeDecl->facets;
18818 
18819     /*
18820     * Temporarily assign the "schema" to the validation context
18821     * of the parser context. This is needed for NOTATION validation.
18822     */
18823     if (pctxt->vctxt == NULL) {
18824         if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18825         return(-1);
18826     }
18827     pctxt->vctxt->schema = pctxt->schema;
18828     while (facet != NULL) {
18829         res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18830         HFAILURE
18831         facet = facet->next;
18832     }
18833     pctxt->vctxt->schema = NULL;
18834     }
18835     if (olderrs != pctxt->nberrors)
18836     return(pctxt->err);
18837     return(0);
18838 exit_failure:
18839     return(-1);
18840 }
18841 
18854 static xmlSchemaTreeItemPtr
18855 xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
18856                   xmlSchemaTreeItemPtr particle)
18857 {
18858     xmlSchemaTreeItemPtr circ = NULL;
18859     xmlSchemaTreeItemPtr term;
18860     xmlSchemaModelGroupDefPtr gdef;
18861 
18862     for (; particle != NULL; particle = particle->next) {
18863     term = particle->children;
18864     if (term == NULL)
18865         continue;
18866     switch (term->type) {
18867         case XML_SCHEMA_TYPE_GROUP:
18868         gdef = (xmlSchemaModelGroupDefPtr) term;
18869         if (gdef == groupDef)
18870             return (particle);
18871         /*
18872         * Mark this model group definition to avoid infinite
18873         * recursion on circular references not yet examined.
18874         */
18875         if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18876             continue;
18877         if (gdef->children != NULL) {
18878             gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18879             circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18880             gdef->children->children);
18881             gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18882             if (circ != NULL)
18883             return (circ);
18884         }
18885         break;
18886         case XML_SCHEMA_TYPE_SEQUENCE:
18887         case XML_SCHEMA_TYPE_CHOICE:
18888         case XML_SCHEMA_TYPE_ALL:
18889         circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18890         if (circ != NULL)
18891             return (circ);
18892         break;
18893         default:
18894         break;
18895     }
18896     }
18897     return (NULL);
18898 }
18899 
18908 static void
18909 xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
18910                    xmlSchemaParserCtxtPtr ctxt)
18911 {
18912     /*
18913     * Schema Component Constraint: Model Group Correct
18914     * 2 Circular groups are disallowed. That is, within the {particles}
18915     * of a group there must not be at any depth a particle whose {term}
18916     * is the group itself.
18917     */
18918     if ((item == NULL) ||
18919     (item->type != XML_SCHEMA_TYPE_GROUP) ||
18920     (item->children == NULL))
18921     return;
18922     {
18923     xmlSchemaTreeItemPtr circ;
18924 
18925     circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
18926     if (circ != NULL) {
18927         xmlChar *str = NULL;
18928         /*
18929         * TODO: The error report is not adequate: this constraint
18930         * is defined for model groups but not definitions, but since
18931         * there cannot be any circular model groups without a model group
18932         * definition (if not using a construction API), we check those
18933         * defintions only.
18934         */
18935         xmlSchemaPCustomErr(ctxt,
18936         XML_SCHEMAP_MG_PROPS_CORRECT_2,
18937         NULL, WXS_ITEM_NODE(circ),
18938         "Circular reference to the model group definition '%s' "
18939         "defined", xmlSchemaFormatQName(&str,
18940             item->targetNamespace, item->name));
18941         FREE_AND_NULL(str)
18942         /*
18943         * NOTE: We will cut the reference to avoid further
18944         * confusion of the processor. This is a fatal error.
18945         */
18946         circ->children = NULL;
18947     }
18948     }
18949 }
18950 
18965 static void
18966 xmlSchemaModelGroupToModelGroupDefFixup(
18967     xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
18968     xmlSchemaModelGroupPtr mg)
18969 {
18970     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
18971 
18972     while (particle != NULL) {
18973     if ((WXS_PARTICLE_TERM(particle) == NULL) ||
18974         ((WXS_PARTICLE_TERM(particle))->type !=
18975         XML_SCHEMA_TYPE_GROUP))
18976     {
18977         particle = WXS_PTC_CAST particle->next;
18978         continue;
18979     }
18980     if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
18981         /*
18982         * TODO: Remove the particle.
18983         */
18984         WXS_PARTICLE_TERM(particle) = NULL;
18985         particle = WXS_PTC_CAST particle->next;
18986         continue;
18987     }
18988     /*
18989     * Assign the model group to the {term} of the particle.
18990     */
18991     WXS_PARTICLE_TERM(particle) =
18992         WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
18993 
18994     particle = WXS_PTC_CAST particle->next;
18995     }
18996 }
18997 
19008 static xmlSchemaQNameRefPtr
19009 xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
19010                      xmlSchemaItemListPtr list)
19011 {
19012     xmlSchemaAttributeGroupPtr gr;
19013     xmlSchemaQNameRefPtr ref, circ;
19014     int i;
19015     /*
19016     * We will search for an attribute group reference which
19017     * references the context attribute group.
19018     */
19019     for (i = 0; i < list->nbItems; i++) {
19020     ref = list->items[i];
19021     if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19022         (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
19023         (ref->item != NULL))
19024     {
19025         gr = WXS_ATTR_GROUP_CAST ref->item;
19026         if (gr == ctxtGr)
19027         return(ref);
19028         if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
19029         continue;
19030         /*
19031         * Mark as visited to avoid infinite recursion on
19032         * circular references not yet examined.
19033         */
19034         if ((gr->attrUses) &&
19035         (gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
19036         {
19037         gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
19038         circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
19039             (xmlSchemaItemListPtr) gr->attrUses);
19040         gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
19041         if (circ != NULL)
19042             return (circ);
19043         }
19044 
19045     }
19046     }
19047     return (NULL);
19048 }
19049 
19058 static int
19059 xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
19060                 xmlSchemaParserCtxtPtr ctxt)
19061 {
19062     /*
19063     * Schema Representation Constraint:
19064     * Attribute Group Definition Representation OK
19065     * 3 Circular group reference is disallowed outside <redefine>.
19066     * That is, unless this element information item's parent is
19067     * <redefine>, then among the [children], if any, there must
19068     * not be an <attributeGroup> with ref [attribute] which resolves
19069     * to the component corresponding to this <attributeGroup>. Indirect
19070     * circularity is also ruled out. That is, when QName resolution
19071     * (Schema Document) (�3.15.3) is applied to a �QName� arising from
19072     * any <attributeGroup>s with a ref [attribute] among the [children],
19073     * it must not be the case that a �QName� is encountered at any depth
19074     * which resolves to the component corresponding to this <attributeGroup>.
19075     */
19076     if (attrGr->attrUses == NULL)
19077     return(0);
19078     else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
19079     return(0);
19080     else {
19081     xmlSchemaQNameRefPtr circ;
19082 
19083     circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
19084         (xmlSchemaItemListPtr) attrGr->attrUses);
19085     if (circ != NULL) {
19086         xmlChar *str = NULL;
19087         /*
19088         * TODO: Report the referenced attr group as QName.
19089         */
19090         xmlSchemaPCustomErr(ctxt,
19091         XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
19092         NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
19093         "Circular reference to the attribute group '%s' "
19094         "defined", xmlSchemaGetComponentQName(&str, attrGr));
19095         FREE_AND_NULL(str);
19096         /*
19097         * NOTE: We will cut the reference to avoid further
19098         * confusion of the processor.
19099         * BADSPEC TODO: The spec should define how to process in this case.
19100         */
19101         circ->item = NULL;
19102         return(ctxt->err);
19103     }
19104     }
19105     return(0);
19106 }
19107 
19108 static int
19109 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19110                   xmlSchemaAttributeGroupPtr attrGr);
19111 
19126 static int
19127 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19128                   xmlSchemaBasicItemPtr item,
19129                   xmlSchemaWildcardPtr *completeWild,
19130                   xmlSchemaItemListPtr list,
19131                   xmlSchemaItemListPtr prohibs)
19132 {
19133     xmlSchemaAttributeGroupPtr gr;
19134     xmlSchemaAttributeUsePtr use;
19135     xmlSchemaItemListPtr sublist;
19136     int i, j;
19137     int created = (*completeWild == NULL) ? 0 : 1;
19138 
19139     if (prohibs)
19140     prohibs->nbItems = 0;
19141 
19142     for (i = 0; i < list->nbItems; i++) {
19143     use = list->items[i];
19144 
19145     if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19146         if (prohibs == NULL) {
19147         PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19148             "unexpected attr prohibition found");
19149         return(-1);
19150         }
19151         /*
19152         * Remove from attribute uses.
19153         */
19154         if (xmlSchemaItemListRemove(list, i) == -1)
19155         return(-1);
19156         i--;
19157         /*
19158         * Note that duplicate prohibitions were already
19159         * handled at parsing time.
19160         */
19161         /*
19162         * Add to list of prohibitions.
19163         */
19164         xmlSchemaItemListAddSize(prohibs, 2, use);
19165         continue;
19166     }
19167     if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19168         ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19169     {
19170         if ((WXS_QNAME_CAST use)->item == NULL)
19171         return(-1);
19172         gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19173         /*
19174         * Expand the referenced attr. group.
19175         * TODO: remove this, this is done in a previous step, so
19176         * already done here.
19177         */
19178         if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19179         if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19180             return(-1);
19181         }
19182         /*
19183         * Build the 'complete' wildcard; i.e. intersect multiple
19184         * wildcards.
19185         */
19186         if (gr->attributeWildcard != NULL) {
19187         if (*completeWild == NULL) {
19188             *completeWild = gr->attributeWildcard;
19189         } else {
19190             if (! created) {
19191             xmlSchemaWildcardPtr tmpWild;
19192 
19193              /*
19194             * Copy the first encountered wildcard as context,
19195             * except for the annotation.
19196             *
19197             * Although the complete wildcard might not correspond
19198             * to any node in the schema, we will anchor it on
19199             * the node of the owner component.
19200             */
19201             tmpWild =  xmlSchemaAddWildcard(pctxt, pctxt->schema,
19202                 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19203                 WXS_ITEM_NODE(item));
19204             if (tmpWild == NULL)
19205                 return(-1);
19206             if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19207                 tmpWild, *completeWild) == -1)
19208                 return (-1);
19209             tmpWild->processContents = (*completeWild)->processContents;
19210             *completeWild = tmpWild;
19211             created = 1;
19212             }
19213 
19214             if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19215             gr->attributeWildcard) == -1)
19216             return(-1);
19217         }
19218         }
19219         /*
19220         * Just remove the reference if the referenced group does not
19221         * contain any attribute uses.
19222         */
19223         sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19224         if ((sublist == NULL) || sublist->nbItems == 0) {
19225         if (xmlSchemaItemListRemove(list, i) == -1)
19226             return(-1);
19227         i--;
19228         continue;
19229         }
19230         /*
19231         * Add the attribute uses.
19232         */
19233         list->items[i] = sublist->items[0];
19234         if (sublist->nbItems != 1) {
19235         for (j = 1; j < sublist->nbItems; j++) {
19236             i++;
19237             if (xmlSchemaItemListInsert(list,
19238                 sublist->items[j], i) == -1)
19239             return(-1);
19240         }
19241         }
19242     }
19243 
19244     }
19245     /*
19246     * Handle pointless prohibitions of declared attributes.
19247     */
19248     if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19249     xmlSchemaAttributeUseProhibPtr prohib;
19250 
19251     for (i = prohibs->nbItems -1; i >= 0; i--) {
19252         prohib = prohibs->items[i];
19253         for (j = 0; j < list->nbItems; j++) {
19254         use = list->items[j];
19255 
19256         if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19257             (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19258         {
19259             xmlChar *str = NULL;
19260 
19261             xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19262             XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19263             prohib->node, NULL,
19264             "Skipping pointless attribute use prohibition "
19265             "'%s', since a corresponding attribute use "
19266             "exists already in the type definition",
19267             xmlSchemaFormatQName(&str,
19268                 prohib->targetNamespace, prohib->name),
19269             NULL, NULL);
19270             FREE_AND_NULL(str);
19271             /*
19272             * Remove the prohibition.
19273             */
19274             if (xmlSchemaItemListRemove(prohibs, i) == -1)
19275             return(-1);
19276             break;
19277         }
19278         }
19279     }
19280     }
19281     return(0);
19282 }
19283 
19296 static int
19297 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19298                   xmlSchemaAttributeGroupPtr attrGr)
19299 {
19300     if ((attrGr->attrUses == NULL) ||
19301     (attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19302     return(0);
19303 
19304     attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19305     if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19306     &(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19307     return(-1);
19308     return(0);
19309 }
19310 
19322 static int
19323 xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19324                   xmlSchemaAttributeGroupPtr attrGr)
19325 {
19326     /*
19327     * SPEC ag-props-correct
19328     * (1) "The values of the properties of an attribute group definition
19329     * must be as described in the property tableau in The Attribute
19330     * Group Definition Schema Component (�3.6.1), modulo the impact of
19331     * Missing Sub-components (�5.3);"
19332     */
19333 
19334     if ((attrGr->attrUses != NULL) &&
19335     (WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19336     {
19337     xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19338     xmlSchemaAttributeUsePtr use, tmp;
19339     int i, j, hasId = 0;
19340 
19341     for (i = uses->nbItems -1; i >= 0; i--) {
19342         use = uses->items[i];
19343         /*
19344         * SPEC ag-props-correct
19345         * (2) "Two distinct members of the {attribute uses} must not have
19346         * {attribute declaration}s both of whose {name}s match and whose
19347         * {target namespace}s are identical."
19348         */
19349         if (i > 0) {
19350         for (j = i -1; j >= 0; j--) {
19351             tmp = uses->items[j];
19352             if ((WXS_ATTRUSE_DECL_NAME(use) ==
19353             WXS_ATTRUSE_DECL_NAME(tmp)) &&
19354             (WXS_ATTRUSE_DECL_TNS(use) ==
19355             WXS_ATTRUSE_DECL_TNS(tmp)))
19356             {
19357             xmlChar *str = NULL;
19358 
19359             xmlSchemaCustomErr(ACTXT_CAST pctxt,
19360                 XML_SCHEMAP_AG_PROPS_CORRECT,
19361                 attrGr->node, WXS_BASIC_CAST attrGr,
19362                 "Duplicate %s",
19363                 xmlSchemaGetComponentDesignation(&str, use),
19364                 NULL);
19365             FREE_AND_NULL(str);
19366             /*
19367             * Remove the duplicate.
19368             */
19369             if (xmlSchemaItemListRemove(uses, i) == -1)
19370                 return(-1);
19371             goto next_use;
19372             }
19373         }
19374         }
19375         /*
19376         * SPEC ag-props-correct
19377         * (3) "Two distinct members of the {attribute uses} must not have
19378         * {attribute declaration}s both of whose {type definition}s are or
19379         * are derived from ID."
19380         * TODO: Does 'derived' include member-types of unions?
19381         */
19382         if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19383         if (xmlSchemaIsDerivedFromBuiltInType(
19384             WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19385         {
19386             if (hasId) {
19387             xmlChar *str = NULL;
19388 
19389             xmlSchemaCustomErr(ACTXT_CAST pctxt,
19390                 XML_SCHEMAP_AG_PROPS_CORRECT,
19391                 attrGr->node, WXS_BASIC_CAST attrGr,
19392                 "There must not exist more than one attribute "
19393                 "declaration of type 'xs:ID' "
19394                 "(or derived from 'xs:ID'). The %s violates this "
19395                 "constraint",
19396                 xmlSchemaGetComponentDesignation(&str, use),
19397                 NULL);
19398             FREE_AND_NULL(str);
19399             if (xmlSchemaItemListRemove(uses, i) == -1)
19400                 return(-1);
19401             }
19402             hasId = 1;
19403         }
19404         }
19405 next_use: {}
19406     }
19407     }
19408     return(0);
19409 }
19410 
19419 static int
19420 xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19421                     xmlSchemaParserCtxtPtr ctxt)
19422 {
19423     xmlSchemaAttributeGroupPtr group;
19424 
19425     if (ref->item != NULL)
19426         return(0);
19427     group = xmlSchemaGetAttributeGroup(ctxt->schema,
19428     ref->name,
19429     ref->targetNamespace);
19430     if (group == NULL) {
19431     xmlSchemaPResCompAttrErr(ctxt,
19432         XML_SCHEMAP_SRC_RESOLVE,
19433         NULL, ref->node,
19434         "ref", ref->name, ref->targetNamespace,
19435         ref->itemType, NULL);
19436     return(ctxt->err);
19437     }
19438     ref->item = WXS_BASIC_CAST group;
19439     return(0);
19440 }
19441 
19456 static int
19457 xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19458                    xmlSchemaAttributePtr attr)
19459 {
19460 
19461     /*
19462     * SPEC a-props-correct (1)
19463     * "The values of the properties of an attribute declaration must
19464     * be as described in the property tableau in The Attribute
19465     * Declaration Schema Component (�3.2.1), modulo the impact of
19466     * Missing Sub-components (�5.3)."
19467     */
19468 
19469     if (WXS_ATTR_TYPEDEF(attr) == NULL)
19470     return(0);
19471 
19472     if (attr->defValue != NULL) {
19473     int ret;
19474 
19475     /*
19476     * SPEC a-props-correct (3)
19477     * "If the {type definition} is or is derived from ID then there
19478     * must not be a {value constraint}."
19479     */
19480     if (xmlSchemaIsDerivedFromBuiltInType(
19481         WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19482     {
19483         xmlSchemaCustomErr(ACTXT_CAST pctxt,
19484         XML_SCHEMAP_A_PROPS_CORRECT_3,
19485         NULL, WXS_BASIC_CAST attr,
19486         "Value constraints are not allowed if the type definition "
19487         "is or is derived from xs:ID",
19488         NULL, NULL);
19489         return(pctxt->err);
19490     }
19491     /*
19492     * SPEC a-props-correct (2)
19493     * "if there is a {value constraint}, the canonical lexical
19494     * representation of its value must be �valid� with respect
19495     * to the {type definition} as defined in String Valid (�3.14.4)."
19496     * TODO: Don't care about the *cononical* stuff here, this requirement
19497     * will be removed in WXS 1.1 anyway.
19498     */
19499     ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
19500         attr->node, WXS_ATTR_TYPEDEF(attr),
19501         attr->defValue, &(attr->defVal),
19502         1, 1, 0);
19503     if (ret != 0) {
19504         if (ret < 0) {
19505         PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
19506             "calling xmlSchemaVCheckCVCSimpleType()");
19507         return(-1);
19508         }
19509         xmlSchemaCustomErr(ACTXT_CAST pctxt,
19510         XML_SCHEMAP_A_PROPS_CORRECT_2,
19511         NULL, WXS_BASIC_CAST attr,
19512         "The value of the value constraint is not valid",
19513         NULL, NULL);
19514         return(pctxt->err);
19515     }
19516     }
19517 
19518     return(0);
19519 }
19520 
19521 static xmlSchemaElementPtr
19522 xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19523                  xmlSchemaElementPtr ancestor)
19524 {
19525     xmlSchemaElementPtr ret;
19526 
19527     if (WXS_SUBST_HEAD(ancestor) == NULL)
19528     return (NULL);
19529     if (WXS_SUBST_HEAD(ancestor) == elemDecl)
19530     return (ancestor);
19531 
19532     if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
19533     return (NULL);
19534     WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
19535     ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
19536     WXS_SUBST_HEAD(ancestor));
19537     WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
19538 
19539     return (ret);
19540 }
19541 
19554 static int
19555 xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19556                    xmlSchemaElementPtr elemDecl)
19557 {
19558     int ret = 0;
19559     xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
19560     /*
19561     * SPEC (1) "The values of the properties of an element declaration
19562     * must be as described in the property tableau in The Element
19563     * Declaration Schema Component (�3.3.1), modulo the impact of Missing
19564     * Sub-components (�5.3)."
19565     */
19566     if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19567     xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
19568 
19569     xmlSchemaCheckElementDeclComponent(head, pctxt);
19570     /*
19571     * SPEC (3) "If there is a non-�absent� {substitution group
19572     * affiliation}, then {scope} must be global."
19573     */
19574     if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19575         xmlSchemaPCustomErr(pctxt,
19576         XML_SCHEMAP_E_PROPS_CORRECT_3,
19577         WXS_BASIC_CAST elemDecl, NULL,
19578         "Only global element declarations can have a "
19579         "substitution group affiliation", NULL);
19580         ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
19581     }
19582     /*
19583     * TODO: SPEC (6) "Circular substitution groups are disallowed.
19584     * That is, it must not be possible to return to an element declaration
19585     * by repeatedly following the {substitution group affiliation}
19586     * property."
19587     */
19588     if (head == elemDecl)
19589         circ = head;
19590     else if (WXS_SUBST_HEAD(head) != NULL)
19591         circ = xmlSchemaCheckSubstGroupCircular(head, head);
19592     else
19593         circ = NULL;
19594     if (circ != NULL) {
19595         xmlChar *strA = NULL, *strB = NULL;
19596 
19597         xmlSchemaPCustomErrExt(pctxt,
19598         XML_SCHEMAP_E_PROPS_CORRECT_6,
19599         WXS_BASIC_CAST circ, NULL,
19600         "The element declaration '%s' defines a circular "
19601         "substitution group to element declaration '%s'",
19602         xmlSchemaGetComponentQName(&strA, circ),
19603         xmlSchemaGetComponentQName(&strB, head),
19604         NULL);
19605         FREE_AND_NULL(strA)
19606         FREE_AND_NULL(strB)
19607         ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19608     }
19609     /*
19610     * SPEC (4) "If there is a {substitution group affiliation},
19611     * the {type definition}
19612     * of the element declaration must be validly derived from the {type
19613     * definition} of the {substitution group affiliation}, given the value
19614     * of the {substitution group exclusions} of the {substitution group
19615     * affiliation}, as defined in Type Derivation OK (Complex) (�3.4.6)
19616     * (if the {type definition} is complex) or as defined in
19617     * Type Derivation OK (Simple) (�3.14.6) (if the {type definition} is
19618     * simple)."
19619     *
19620     * NOTE: {substitution group exclusions} means the values of the
19621     * attribute "final".
19622     */
19623 
19624     if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
19625         int set = 0;
19626 
19627         if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19628         set |= SUBSET_EXTENSION;
19629         if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19630         set |= SUBSET_RESTRICTION;
19631 
19632         if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
19633         WXS_ELEM_TYPEDEF(head), set) != 0) {
19634         xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19635 
19636         ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
19637         xmlSchemaPCustomErrExt(pctxt,
19638             XML_SCHEMAP_E_PROPS_CORRECT_4,
19639             WXS_BASIC_CAST elemDecl, NULL,
19640             "The type definition '%s' was "
19641             "either rejected by the substitution group "
19642             "affiliation '%s', or not validly derived from its type "
19643             "definition '%s'",
19644             xmlSchemaGetComponentQName(&strA, typeDef),
19645             xmlSchemaGetComponentQName(&strB, head),
19646             xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
19647         FREE_AND_NULL(strA)
19648         FREE_AND_NULL(strB)
19649         FREE_AND_NULL(strC)
19650         }
19651     }
19652     }
19653     /*
19654     * SPEC (5) "If the {type definition} or {type definition}'s
19655     * {content type}
19656     * is or is derived from ID then there must not be a {value constraint}.
19657     * Note: The use of ID as a type definition for elements goes beyond
19658     * XML 1.0, and should be avoided if backwards compatibility is desired"
19659     */
19660     if ((elemDecl->value != NULL) &&
19661     ((WXS_IS_SIMPLE(typeDef) &&
19662       xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
19663      (WXS_IS_COMPLEX(typeDef) &&
19664       WXS_HAS_SIMPLE_CONTENT(typeDef) &&
19665       xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19666         XML_SCHEMAS_ID)))) {
19667 
19668     ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19669     xmlSchemaPCustomErr(pctxt,
19670         XML_SCHEMAP_E_PROPS_CORRECT_5,
19671         WXS_BASIC_CAST elemDecl, NULL,
19672         "The type definition (or type definition's content type) is or "
19673         "is derived from ID; value constraints are not allowed in "
19674         "conjunction with such a type definition", NULL);
19675     } else if (elemDecl->value != NULL) {
19676     int vcret;
19677     xmlNodePtr node = NULL;
19678 
19679     /*
19680     * SPEC (2) "If there is a {value constraint}, the canonical lexical
19681     * representation of its value must be �valid� with respect to the
19682     * {type definition} as defined in Element Default Valid (Immediate)
19683     * (�3.3.6)."
19684     */
19685     if (typeDef == NULL) {
19686         xmlSchemaPErr(pctxt, elemDecl->node,
19687         XML_SCHEMAP_INTERNAL,
19688         "Internal error: xmlSchemaCheckElemPropsCorrect, "
19689         "type is missing... skipping validation of "
19690         "the value constraint", NULL, NULL);
19691         return (-1);
19692     }
19693     if (elemDecl->node != NULL) {
19694         if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19695         node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19696             BAD_CAST "fixed");
19697         else
19698         node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19699             BAD_CAST "default");
19700     }
19701     vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19702         typeDef, elemDecl->value, &(elemDecl->defVal));
19703     if (vcret != 0) {
19704         if (vcret < 0) {
19705         PERROR_INT("xmlSchemaElemCheckValConstr",
19706             "failed to validate the value constraint of an "
19707             "element declaration");
19708         return (-1);
19709         }
19710         return (vcret);
19711     }
19712     }
19713 
19714     return (ret);
19715 }
19716 
19736 static void
19737 xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19738                  xmlSchemaElementPtr elemDecl)
19739 {
19740     if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
19741     /* SPEC (1) "Its {abstract} is false." */
19742     (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19743     return;
19744     {
19745     xmlSchemaElementPtr head;
19746     xmlSchemaTypePtr headType, type;
19747     int set, methSet;
19748     /*
19749     * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19750     * {disallowed substitutions} as the blocking constraint, as defined in
19751     * Substitution Group OK (Transitive) (�3.3.6)."
19752     */
19753     for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19754         head = WXS_SUBST_HEAD(head)) {
19755         set = 0;
19756         methSet = 0;
19757         /*
19758         * The blocking constraints.
19759         */
19760         if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19761         continue;
19762         headType = head->subtypes;
19763         type = elemDecl->subtypes;
19764         if (headType == type)
19765         goto add_member;
19766         if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19767         set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19768         if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19769         set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19770         /*
19771         * SPEC: Substitution Group OK (Transitive) (2.3)
19772         * "The set of all {derivation method}s involved in the
19773         * derivation of D's {type definition} from C's {type definition}
19774         * does not intersect with the union of the blocking constraint,
19775         * C's {prohibited substitutions} (if C is complex, otherwise the
19776         * empty set) and the {prohibited substitutions} (respectively the
19777         * empty set) of any intermediate {type definition}s in the
19778         * derivation of D's {type definition} from C's {type definition}."
19779         */
19780         /*
19781         * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19782         * subst.head axis, the methSet does not need to be computed for
19783         * the full depth over and over.
19784         */
19785         /*
19786         * The set of all {derivation method}s involved in the derivation
19787         */
19788         while ((type != NULL) && (type != headType)) {
19789         if ((WXS_IS_EXTENSION(type)) &&
19790             ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19791             methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19792 
19793         if (WXS_IS_RESTRICTION(type) &&
19794             ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19795             methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19796 
19797         type = type->baseType;
19798         }
19799         /*
19800         * The {prohibited substitutions} of all intermediate types +
19801         * the head's type.
19802         */
19803         type = elemDecl->subtypes->baseType;
19804         while (type != NULL) {
19805         if (WXS_IS_COMPLEX(type)) {
19806             if ((type->flags &
19807                 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19808             ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19809             set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19810             if ((type->flags &
19811                 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19812             ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19813             set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19814         } else
19815             break;
19816         if (type == headType)
19817             break;
19818         type = type->baseType;
19819         }
19820         if ((set != 0) &&
19821         (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19822         (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19823         ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19824         (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19825         continue;
19826         }
19827 add_member:
19828         xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19829         if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19830         head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19831     }
19832     }
19833 }
19834 
19835 #ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */
19836 
19845 static int
19846 xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,
19847                     xmlSchemaBasicItemPtr ctxtComponent,
19848                     xmlSchemaParticlePtr ctxtParticle,
19849                     xmlSchemaParticlePtr searchParticle,
19850                     xmlSchemaParticlePtr curParticle,
19851                     int search)
19852 {
19853     return(0);
19854 
19855     int ret = 0;
19856     xmlSchemaParticlePtr cur = curParticle;
19857     if (curParticle == NULL) {
19858     return(0);
19859     }
19860     if (WXS_PARTICLE_TERM(curParticle) == NULL) {
19861     /*
19862     * Just return in this case. A missing "term" of the particle
19863     * might arise due to an invalid "term" component.
19864     */
19865     return(0);
19866     }
19867     while (cur != NULL) {
19868     switch (WXS_PARTICLE_TERM(cur)->type) {
19869         case XML_SCHEMA_TYPE_ANY:
19870         break;
19871         case XML_SCHEMA_TYPE_ELEMENT:
19872         if (search == 0) {
19873             ret = xmlSchemaCheckElementDeclConsistent(pctxt,
19874             ctxtComponent, ctxtParticle, cur, ctxtParticle, 1);
19875             if (ret != 0)
19876             return(ret);
19877         } else {
19878             xmlSchemaElementPtr elem =
19879             WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur));
19880             /*
19881             * SPEC Element Declarations Consistent:
19882             * "If the {particles} contains, either directly,
19883             * indirectly (that is, within the {particles} of a
19884             * contained model group, recursively) or �implicitly�
19885             * two or more element declaration particles with
19886             * the same {name} and {target namespace}, then
19887             * all their type definitions must be the same
19888             * top-level definition [...]"
19889             */
19890             if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name,
19891                 WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) &&
19892             xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19893                 WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace))
19894             {
19895             xmlChar *strA = NULL, *strB = NULL;
19896 
19897             xmlSchemaCustomErr(ACTXT_CAST pctxt,
19898                 /* TODO: error code */
19899                 XML_SCHEMAP_COS_NONAMBIG,
19900                 WXS_ITEM_NODE(cur), NULL,
19901                 "In the content model of %s, there are multiple "
19902                 "element declarations for '%s' with different "
19903                 "type definitions",
19904                 xmlSchemaGetComponentDesignation(&strA,
19905                 ctxtComponent),
19906                 xmlSchemaFormatQName(&strB,
19907                 WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19908                 WXS_PARTICLE_TERM_AS_ELEM(cur)->name));
19909             FREE_AND_NULL(strA);
19910             FREE_AND_NULL(strB);
19911             return(XML_SCHEMAP_COS_NONAMBIG);
19912             }
19913         }
19914         break;
19915         case XML_SCHEMA_TYPE_SEQUENCE: {
19916         break;
19917         }
19918         case XML_SCHEMA_TYPE_CHOICE:{
19919         /*
19920         xmlSchemaTreeItemPtr sub;
19921 
19922         sub = WXS_PARTICLE_TERM(particle)->children;  (xmlSchemaParticlePtr)
19923         while (sub != NULL) {
19924             ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent,
19925             ctxtParticle, ctxtElem);
19926             if (ret != 0)
19927             return(ret);
19928             sub = sub->next;
19929         }
19930         */
19931         break;
19932         }
19933         case XML_SCHEMA_TYPE_ALL:
19934         break;
19935         case XML_SCHEMA_TYPE_GROUP:
19936         break;
19937         default:
19938         xmlSchemaInternalErr2(ACTXT_CAST pctxt,
19939             "xmlSchemaCheckElementDeclConsistent",
19940             "found unexpected term of type '%s' in content model",
19941             WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL);
19942         return(-1);
19943     }
19944     cur = (xmlSchemaParticlePtr) cur->next;
19945     }
19946 
19947 exit:
19948     return(ret);
19949 }
19950 #endif
19951 
19961 static void
19962 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
19963                    xmlSchemaParserCtxtPtr ctxt)
19964 {
19965     if (elemDecl == NULL)
19966     return;
19967     if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
19968     return;
19969     elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
19970     if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) {
19971     /*
19972     * Adds substitution group members.
19973     */
19974     xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
19975     }
19976 }
19977 
19986 static void
19987 xmlSchemaResolveModelGroupParticleReferences(
19988     xmlSchemaParserCtxtPtr ctxt,
19989     xmlSchemaModelGroupPtr mg)
19990 {
19991     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19992     xmlSchemaQNameRefPtr ref;
19993     xmlSchemaBasicItemPtr refItem;
19994 
19995     /*
19996     * URGENT TODO: Test this.
19997     */
19998     while (particle != NULL) {
19999     if ((WXS_PARTICLE_TERM(particle) == NULL) ||
20000         ((WXS_PARTICLE_TERM(particle))->type !=
20001         XML_SCHEMA_EXTRA_QNAMEREF))
20002     {
20003         goto next_particle;
20004     }
20005     ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
20006     /*
20007     * Resolve the reference.
20008     * NULL the {term} by default.
20009     */
20010     particle->children = NULL;
20011 
20012     refItem = xmlSchemaGetNamedComponent(ctxt->schema,
20013         ref->itemType, ref->name, ref->targetNamespace);
20014     if (refItem == NULL) {
20015         xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
20016         NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
20017         ref->targetNamespace, ref->itemType, NULL);
20018         /* TODO: remove the particle. */
20019         goto next_particle;
20020     }
20021     if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
20022         if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
20023         /* TODO: remove the particle. */
20024         goto next_particle;
20025         /*
20026         * NOTE that we will assign the model group definition
20027         * itself to the "term" of the particle. This will ease
20028         * the check for circular model group definitions. After
20029         * that the "term" will be assigned the model group of the
20030         * model group definition.
20031         */
20032         if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
20033             XML_SCHEMA_TYPE_ALL) {
20034         /*
20035         * SPEC cos-all-limited (1)
20036         * SPEC cos-all-limited (1.2)
20037         * "It appears only as the value of one or both of the
20038         * following properties:"
20039         * (1.1) "the {model group} property of a model group
20040         *        definition."
20041         * (1.2) "the {term} property of a particle [... of] the "
20042         * {content type} of a complex type definition."
20043         */
20044         xmlSchemaCustomErr(ACTXT_CAST ctxt,
20045             /* TODO: error code */
20046             XML_SCHEMAP_COS_ALL_LIMITED,
20047             WXS_ITEM_NODE(particle), NULL,
20048             "A model group definition is referenced, but "
20049             "it contains an 'all' model group, which "
20050             "cannot be contained by model groups",
20051             NULL, NULL);
20052         /* TODO: remove the particle. */
20053         goto next_particle;
20054         }
20055         particle->children = (xmlSchemaTreeItemPtr) refItem;
20056     } else {
20057         /*
20058         * TODO: Are referenced element declarations the only
20059         * other components we expect here?
20060         */
20061         particle->children = (xmlSchemaTreeItemPtr) refItem;
20062     }
20063 next_particle:
20064     particle = WXS_PTC_CAST particle->next;
20065     }
20066 }
20067 
20068 static int
20069 xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
20070                xmlSchemaValPtr y)
20071 {
20072     xmlSchemaTypePtr tx, ty, ptx, pty;
20073     int ret;
20074 
20075     while (x != NULL) {
20076     /* Same types. */
20077     tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
20078     ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
20079     ptx = xmlSchemaGetPrimitiveType(tx);
20080     pty = xmlSchemaGetPrimitiveType(ty);
20081     /*
20082     * (1) if a datatype T' is �derived� by �restriction� from an
20083     * atomic datatype T then the �value space� of T' is a subset of
20084     * the �value space� of T. */
20085     /*
20086     * (2) if datatypes T' and T'' are �derived� by �restriction�
20087     * from a common atomic ancestor T then the �value space�s of T'
20088     * and T'' may overlap.
20089     */
20090     if (ptx != pty)
20091         return(0);
20092     /*
20093     * We assume computed values to be normalized, so do a fast
20094     * string comparison for string based types.
20095     */
20096     if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
20097         WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
20098         if (! xmlStrEqual(
20099         xmlSchemaValueGetAsString(x),
20100         xmlSchemaValueGetAsString(y)))
20101         return (0);
20102     } else {
20103         ret = xmlSchemaCompareValuesWhtsp(
20104         x, XML_SCHEMA_WHITESPACE_PRESERVE,
20105         y, XML_SCHEMA_WHITESPACE_PRESERVE);
20106         if (ret == -2)
20107         return(-1);
20108         if (ret != 0)
20109         return(0);
20110     }
20111     /*
20112     * Lists.
20113     */
20114     x = xmlSchemaValueGetNext(x);
20115     if (x != NULL) {
20116         y = xmlSchemaValueGetNext(y);
20117         if (y == NULL)
20118         return (0);
20119     } else if (xmlSchemaValueGetNext(y) != NULL)
20120         return (0);
20121     else
20122         return (1);
20123     }
20124     return (0);
20125 }
20126 
20134 static int
20135 xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
20136                   xmlSchemaParserCtxtPtr ctxt)
20137 {
20138     if ((ctxt == NULL) || (ause == NULL))
20139     return(-1);
20140     if ((ause->attrDecl == NULL) ||
20141     (ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
20142     return(0);
20143 
20144     {
20145     xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
20146 
20147     /*
20148     * TODO: Evaluate, what errors could occur if the declaration is not
20149     * found.
20150     */
20151     ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
20152         ref->name, ref->targetNamespace);
20153         if (ause->attrDecl == NULL) {
20154         xmlSchemaPResCompAttrErr(ctxt,
20155             XML_SCHEMAP_SRC_RESOLVE,
20156         WXS_BASIC_CAST ause, ause->node,
20157         "ref", ref->name, ref->targetNamespace,
20158         XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20159             return(ctxt->err);;
20160         }
20161     }
20162     return(0);
20163 }
20164 
20174 static int
20175 xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
20176                  xmlSchemaAttributeUsePtr use)
20177 {
20178     if ((ctxt == NULL) || (use == NULL))
20179     return(-1);
20180     if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
20181     ((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
20182     return(0);
20183 
20184     /*
20185     * SPEC au-props-correct (1)
20186     * "The values of the properties of an attribute use must be as
20187     * described in the property tableau in The Attribute Use Schema
20188     * Component (�3.5.1), modulo the impact of Missing
20189     * Sub-components (�5.3)."
20190     */
20191 
20192     if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
20193     ((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
20194         ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20195     {
20196     xmlSchemaPCustomErr(ctxt,
20197         XML_SCHEMAP_AU_PROPS_CORRECT_2,
20198         WXS_BASIC_CAST use, NULL,
20199         "The attribute declaration has a 'fixed' value constraint "
20200         ", thus the attribute use must also have a 'fixed' value "
20201         "constraint",
20202         NULL);
20203     return(ctxt->err);
20204     }
20205     /*
20206     * Compute and check the value constraint's value.
20207     */
20208     if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
20209     int ret;
20210     /*
20211     * TODO: The spec seems to be missing a check of the
20212     * value constraint of the attribute use. We will do it here.
20213     */
20214     /*
20215     * SPEC a-props-correct (3)
20216     */
20217     if (xmlSchemaIsDerivedFromBuiltInType(
20218         WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20219     {
20220         xmlSchemaCustomErr(ACTXT_CAST ctxt,
20221         XML_SCHEMAP_AU_PROPS_CORRECT,
20222         NULL, WXS_BASIC_CAST use,
20223         "Value constraints are not allowed if the type definition "
20224         "is or is derived from xs:ID",
20225         NULL, NULL);
20226         return(ctxt->err);
20227     }
20228 
20229     ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20230         use->node, WXS_ATTRUSE_TYPEDEF(use),
20231         use->defValue, &(use->defVal),
20232         1, 1, 0);
20233     if (ret != 0) {
20234         if (ret < 0) {
20235         PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20236             "calling xmlSchemaVCheckCVCSimpleType()");
20237         return(-1);
20238         }
20239         xmlSchemaCustomErr(ACTXT_CAST ctxt,
20240         XML_SCHEMAP_AU_PROPS_CORRECT,
20241         NULL, WXS_BASIC_CAST use,
20242         "The value of the value constraint is not valid",
20243         NULL, NULL);
20244         return(ctxt->err);
20245     }
20246     }
20247     /*
20248     * SPEC au-props-correct (2)
20249     * "If the {attribute declaration} has a fixed
20250     * {value constraint}, then if the attribute use itself has a
20251     * {value constraint}, it must also be fixed and its value must match
20252     * that of the {attribute declaration}'s {value constraint}."
20253     */
20254     if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20255     (((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20256     {
20257     if (! xmlSchemaAreValuesEqual(use->defVal,
20258         (WXS_ATTRUSE_DECL(use))->defVal))
20259     {
20260         xmlSchemaPCustomErr(ctxt,
20261         XML_SCHEMAP_AU_PROPS_CORRECT_2,
20262         WXS_BASIC_CAST use, NULL,
20263         "The 'fixed' value constraint of the attribute use "
20264         "must match the attribute declaration's value "
20265         "constraint '%s'",
20266         (WXS_ATTRUSE_DECL(use))->defValue);
20267     }
20268     return(ctxt->err);
20269     }
20270     return(0);
20271 }
20272 
20273 
20274 
20275 
20283 static int
20284 xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20285                    xmlSchemaParserCtxtPtr ctxt)
20286 {
20287     /*
20288     * The simple type definition corresponding to the <simpleType> element
20289     * information item in the [children], if present, otherwise the simple
20290     * type definition �resolved� to by the �actual value� of the type
20291     * [attribute], if present, otherwise the �simple ur-type definition�.
20292     */
20293     if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
20294     return(0);
20295     item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20296     if (item->subtypes != NULL)
20297         return(0);
20298     if (item->typeName != NULL) {
20299         xmlSchemaTypePtr type;
20300 
20301     type = xmlSchemaGetType(ctxt->schema, item->typeName,
20302         item->typeNs);
20303     if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
20304         xmlSchemaPResCompAttrErr(ctxt,
20305         XML_SCHEMAP_SRC_RESOLVE,
20306         WXS_BASIC_CAST item, item->node,
20307         "type", item->typeName, item->typeNs,
20308         XML_SCHEMA_TYPE_SIMPLE, NULL);
20309         return(ctxt->err);
20310     } else
20311         item->subtypes = type;
20312 
20313     } else {
20314     /*
20315     * The type defaults to the xs:anySimpleType.
20316     */
20317     item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20318     }
20319     return(0);
20320 }
20321 
20332 static int
20333 xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
20334               xmlSchemaParserCtxtPtr pctxt)
20335 {
20336     if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
20337         return(0);
20338     if (idc->ref->name != NULL) {
20339     idc->ref->item = (xmlSchemaBasicItemPtr)
20340         xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20341         idc->ref->targetNamespace);
20342         if (idc->ref->item == NULL) {
20343         /*
20344         * TODO: It is actually not an error to fail to resolve
20345         * at this stage. BUT we need to be that strict!
20346         */
20347         xmlSchemaPResCompAttrErr(pctxt,
20348         XML_SCHEMAP_SRC_RESOLVE,
20349         WXS_BASIC_CAST idc, idc->node,
20350         "refer", idc->ref->name,
20351         idc->ref->targetNamespace,
20352         XML_SCHEMA_TYPE_IDC_KEY, NULL);
20353             return(pctxt->err);
20354     } else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20355         /*
20356         * SPEC c-props-correct (1)
20357         */
20358         xmlSchemaCustomErr(ACTXT_CAST pctxt,
20359         XML_SCHEMAP_C_PROPS_CORRECT,
20360         NULL, WXS_BASIC_CAST idc,
20361         "The keyref references a keyref",
20362         NULL, NULL);
20363         idc->ref->item = NULL;
20364         return(pctxt->err);
20365     } else {
20366         if (idc->nbFields !=
20367         ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20368         xmlChar *str = NULL;
20369         xmlSchemaIDCPtr refer;
20370 
20371         refer = (xmlSchemaIDCPtr) idc->ref->item;
20372         /*
20373         * SPEC c-props-correct(2)
20374         * "If the {identity-constraint category} is keyref,
20375         * the cardinality of the {fields} must equal that of
20376         * the {fields} of the {referenced key}.
20377         */
20378         xmlSchemaCustomErr(ACTXT_CAST pctxt,
20379             XML_SCHEMAP_C_PROPS_CORRECT,
20380             NULL, WXS_BASIC_CAST idc,
20381             "The cardinality of the keyref differs from the "
20382             "cardinality of the referenced key/unique '%s'",
20383             xmlSchemaFormatQName(&str, refer->targetNamespace,
20384             refer->name),
20385             NULL);
20386         FREE_AND_NULL(str)
20387         return(pctxt->err);
20388         }
20389     }
20390     }
20391     return(0);
20392 }
20393 
20394 static int
20395 xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20396                        xmlSchemaParserCtxtPtr pctxt)
20397 {
20398     if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20399     prohib->targetNamespace) == NULL) {
20400 
20401     xmlSchemaPResCompAttrErr(pctxt,
20402         XML_SCHEMAP_SRC_RESOLVE,
20403         NULL, prohib->node,
20404         "ref", prohib->name, prohib->targetNamespace,
20405         XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20406     return(XML_SCHEMAP_SRC_RESOLVE);
20407     }
20408     return(0);
20409 }
20410 
20411 #define WXS_REDEFINED_TYPE(c) \
20412 (((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20413 
20414 #define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20415 (((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20416 
20417 #define WXS_REDEFINED_ATTR_GROUP(c) \
20418 (((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20419 
20420 static int
20421 xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20422 {
20423     int err = 0;
20424     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20425     xmlSchemaBasicItemPtr prev, item;
20426     int wasRedefined;
20427 
20428     if (redef == NULL)
20429     return(0);
20430 
20431     do {
20432     item = redef->item;
20433     /*
20434     * First try to locate the redefined component in the
20435     * schema graph starting with the redefined schema.
20436     * NOTE: According to this schema bug entry:
20437     *   http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20438     *   it's not clear if the referenced component needs to originate
20439     *   from the <redefine>d schema _document_ or the schema; the latter
20440     *   would include all imported and included sub-schemas of the
20441     *   <redefine>d schema. Currenlty we latter approach is used.
20442     *   SUPPLEMENT: It seems that the WG moves towards the latter
20443     *   approach, so we are doing it right.
20444     *
20445     */
20446     prev = xmlSchemaFindRedefCompInGraph(
20447         redef->targetBucket, item->type,
20448         redef->refName, redef->refTargetNs);
20449     if (prev == NULL) {
20450         xmlChar *str = NULL;
20451         xmlNodePtr node;
20452 
20453         /*
20454         * SPEC src-redefine:
20455         * (6.2.1) "The �actual value� of its own name attribute plus
20456         * target namespace must successfully �resolve� to a model
20457         * group definition in I."
20458         * (7.2.1) "The �actual value� of its own name attribute plus
20459         * target namespace must successfully �resolve� to an attribute
20460         * group definition in I."
20461 
20462         *
20463         * Note that, if we are redefining with the use of references
20464         * to components, the spec assumes the src-resolve to be used;
20465         * but this won't assure that we search only *inside* the
20466         * redefined schema.
20467         */
20468         if (redef->reference)
20469         node = WXS_ITEM_NODE(redef->reference);
20470         else
20471         node = WXS_ITEM_NODE(item);
20472         xmlSchemaCustomErr(ACTXT_CAST pctxt,
20473         /*
20474         * TODO: error code.
20475         * Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20476         * reference kind.
20477         */
20478         XML_SCHEMAP_SRC_REDEFINE, node, NULL,
20479         "The %s '%s' to be redefined could not be found in "
20480         "the redefined schema",
20481         WXS_ITEM_TYPE_NAME(item),
20482         xmlSchemaFormatQName(&str, redef->refTargetNs,
20483             redef->refName));
20484         FREE_AND_NULL(str);
20485         err = pctxt->err;
20486         redef = redef->next;
20487         continue;
20488     }
20489     /*
20490     * TODO: Obtaining and setting the redefinition state is really
20491     * clumsy.
20492     */
20493     wasRedefined = 0;
20494     switch (item->type) {
20495         case XML_SCHEMA_TYPE_COMPLEX:
20496         case XML_SCHEMA_TYPE_SIMPLE:
20497         if ((WXS_TYPE_CAST prev)->flags &
20498             XML_SCHEMAS_TYPE_REDEFINED)
20499         {
20500             wasRedefined = 1;
20501             break;
20502         }
20503         /* Mark it as redefined. */
20504         (WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20505         /*
20506         * Assign the redefined type to the
20507         * base type of the redefining type.
20508         * TODO: How
20509         */
20510         ((xmlSchemaTypePtr) item)->baseType =
20511             (xmlSchemaTypePtr) prev;
20512         break;
20513         case XML_SCHEMA_TYPE_GROUP:
20514         if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20515             XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20516         {
20517             wasRedefined = 1;
20518             break;
20519         }
20520         /* Mark it as redefined. */
20521         (WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20522             XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20523         if (redef->reference != NULL) {
20524             /*
20525             * Overwrite the QName-reference with the
20526             * referenced model group def.
20527             */
20528             (WXS_PTC_CAST redef->reference)->children =
20529             WXS_TREE_CAST prev;
20530         }
20531         redef->target = prev;
20532         break;
20533         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20534         if ((WXS_ATTR_GROUP_CAST prev)->flags &
20535             XML_SCHEMAS_ATTRGROUP_REDEFINED)
20536         {
20537             wasRedefined = 1;
20538             break;
20539         }
20540         (WXS_ATTR_GROUP_CAST prev)->flags |=
20541             XML_SCHEMAS_ATTRGROUP_REDEFINED;
20542         if (redef->reference != NULL) {
20543             /*
20544             * Assign the redefined attribute group to the
20545             * QName-reference component.
20546             * This is the easy case, since we will just
20547             * expand the redefined group.
20548             */
20549             (WXS_QNAME_CAST redef->reference)->item = prev;
20550             redef->target = NULL;
20551         } else {
20552             /*
20553             * This is the complicated case: we need
20554             * to apply src-redefine (7.2.2) at a later
20555             * stage, i.e. when attribute group references
20556             * have beed expanded and simple types have
20557             * beed fixed.
20558             */
20559             redef->target = prev;
20560         }
20561         break;
20562         default:
20563         PERROR_INT("xmlSchemaResolveRedefReferences",
20564             "Unexpected redefined component type");
20565         return(-1);
20566     }
20567     if (wasRedefined) {
20568         xmlChar *str = NULL;
20569         xmlNodePtr node;
20570 
20571         if (redef->reference)
20572         node = WXS_ITEM_NODE(redef->reference);
20573         else
20574         node = WXS_ITEM_NODE(redef->item);
20575 
20576         xmlSchemaCustomErr(ACTXT_CAST pctxt,
20577         /* TODO: error code. */
20578         XML_SCHEMAP_SRC_REDEFINE,
20579         node, NULL,
20580         "The referenced %s was already redefined. Multiple "
20581         "redefinition of the same component is not supported",
20582         xmlSchemaGetComponentDesignation(&str, prev),
20583         NULL);
20584         FREE_AND_NULL(str)
20585         err = pctxt->err;
20586         redef = redef->next;
20587         continue;
20588     }
20589     redef = redef->next;
20590     } while (redef != NULL);
20591 
20592     return(err);
20593 }
20594 
20595 static int
20596 xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20597 {
20598     int err = 0;
20599     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20600     xmlSchemaBasicItemPtr item;
20601 
20602     if (redef == NULL)
20603     return(0);
20604 
20605     do {
20606     if (redef->target == NULL) {
20607         redef = redef->next;
20608         continue;
20609     }
20610     item = redef->item;
20611 
20612     switch (item->type) {
20613         case XML_SCHEMA_TYPE_SIMPLE:
20614         case XML_SCHEMA_TYPE_COMPLEX:
20615         /*
20616         * Since the spec wants the {name} of the redefined
20617         * type to be 'absent', we'll NULL it.
20618         */
20619         (WXS_TYPE_CAST redef->target)->name = NULL;
20620 
20621         /*
20622         * TODO: Seems like there's nothing more to do. The normal
20623         * inheritance mechanism is used. But not 100% sure.
20624         */
20625         break;
20626         case XML_SCHEMA_TYPE_GROUP:
20627         /*
20628         * URGENT TODO:
20629         * SPEC src-redefine:
20630         * (6.2.2) "The {model group} of the model group definition
20631         * which corresponds to it per XML Representation of Model
20632         * Group Definition Schema Components (�3.7.2) must be a
20633         * �valid restriction� of the {model group} of that model
20634         * group definition in I, as defined in Particle Valid
20635         * (Restriction) (�3.9.6)."
20636         */
20637         break;
20638         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20639         /*
20640         * SPEC src-redefine:
20641         * (7.2.2) "The {attribute uses} and {attribute wildcard} of
20642         * the attribute group definition which corresponds to it
20643         * per XML Representation of Attribute Group Definition Schema
20644         * Components (�3.6.2) must be �valid restrictions� of the
20645         * {attribute uses} and {attribute wildcard} of that attribute
20646         * group definition in I, as defined in clause 2, clause 3 and
20647         * clause 4 of Derivation Valid (Restriction, Complex)
20648         * (�3.4.6) (where references to the base type definition are
20649         * understood as references to the attribute group definition
20650         * in I)."
20651         */
20652         err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20653             XML_SCHEMA_ACTION_REDEFINE,
20654             item, redef->target,
20655             (WXS_ATTR_GROUP_CAST item)->attrUses,
20656             (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20657             (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20658             (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20659         if (err == -1)
20660             return(-1);
20661         break;
20662         default:
20663         break;
20664     }
20665     redef = redef->next;
20666     } while (redef != NULL);
20667     return(0);
20668 }
20669 
20670 
20671 static int
20672 xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20673                xmlSchemaBucketPtr bucket)
20674 {
20675     xmlSchemaBasicItemPtr item;
20676     int err;
20677     xmlHashTablePtr *table;
20678     const xmlChar *name;
20679     int i;
20680 
20681 #define WXS_GET_GLOBAL_HASH(c, slot) { \
20682     if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20683     table = &(WXS_IMPBUCKET((c))->schema->slot); \
20684     else \
20685     table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20686 
20687     /*
20688     * Add global components to the schema's hash tables.
20689     * This is the place where duplicate components will be
20690     * detected.
20691     * TODO: I think normally we should support imports of the
20692     *   same namespace from multiple locations. We don't do currently,
20693     *   but if we do then according to:
20694     *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20695     *   we would need, if imported directly, to import redefined
20696     *   components as well to be able to catch clashing components.
20697     *   (I hope I'll still know what this means after some months :-()
20698     */
20699     if (bucket == NULL)
20700     return(-1);
20701     if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20702     return(0);
20703     bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20704 
20705     for (i = 0; i < bucket->globals->nbItems; i++) {
20706     item = bucket->globals->items[i];
20707     table = NULL;
20708     switch (item->type) {
20709         case XML_SCHEMA_TYPE_COMPLEX:
20710         case XML_SCHEMA_TYPE_SIMPLE:
20711         if (WXS_REDEFINED_TYPE(item))
20712             continue;
20713         name = (WXS_TYPE_CAST item)->name;
20714         WXS_GET_GLOBAL_HASH(bucket, typeDecl)
20715         break;
20716         case XML_SCHEMA_TYPE_ELEMENT:
20717         name = (WXS_ELEM_CAST item)->name;
20718         WXS_GET_GLOBAL_HASH(bucket, elemDecl)
20719         break;
20720         case XML_SCHEMA_TYPE_ATTRIBUTE:
20721         name = (WXS_ATTR_CAST item)->name;
20722         WXS_GET_GLOBAL_HASH(bucket, attrDecl)
20723         break;
20724         case XML_SCHEMA_TYPE_GROUP:
20725         if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20726             continue;
20727         name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20728         WXS_GET_GLOBAL_HASH(bucket, groupDecl)
20729         break;
20730         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20731         if (WXS_REDEFINED_ATTR_GROUP(item))
20732             continue;
20733         name = (WXS_ATTR_GROUP_CAST item)->name;
20734         WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
20735         break;
20736         case XML_SCHEMA_TYPE_IDC_KEY:
20737         case XML_SCHEMA_TYPE_IDC_UNIQUE:
20738         case XML_SCHEMA_TYPE_IDC_KEYREF:
20739         name = (WXS_IDC_CAST item)->name;
20740         WXS_GET_GLOBAL_HASH(bucket, idcDef)
20741         break;
20742         case XML_SCHEMA_TYPE_NOTATION:
20743         name = ((xmlSchemaNotationPtr) item)->name;
20744         WXS_GET_GLOBAL_HASH(bucket, notaDecl)
20745         break;
20746         default:
20747         PERROR_INT("xmlSchemaAddComponents",
20748             "Unexpected global component type");
20749         continue;
20750     }
20751     if (*table == NULL) {
20752         *table = xmlHashCreateDict(10, pctxt->dict);
20753         if (*table == NULL) {
20754         PERROR_INT("xmlSchemaAddComponents",
20755             "failed to create a component hash table");
20756         return(-1);
20757         }
20758     }
20759     err = xmlHashAddEntry(*table, name, item);
20760     if (err != 0) {
20761         xmlChar *str = NULL;
20762 
20763         xmlSchemaCustomErr(ACTXT_CAST pctxt,
20764         XML_SCHEMAP_REDEFINED_TYPE,
20765         WXS_ITEM_NODE(item),
20766         WXS_BASIC_CAST item,
20767         "A global %s '%s' does already exist",
20768         WXS_ITEM_TYPE_NAME(item),
20769         xmlSchemaGetComponentQName(&str, item));
20770         FREE_AND_NULL(str);
20771     }
20772     }
20773     /*
20774     * Process imported/included schemas.
20775     */
20776     if (bucket->relations != NULL) {
20777     xmlSchemaSchemaRelationPtr rel = bucket->relations;
20778     do {
20779         if ((rel->bucket != NULL) &&
20780         ((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20781         if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20782             return(-1);
20783         }
20784         rel = rel->next;
20785     } while (rel != NULL);
20786     }
20787     return(0);
20788 }
20789 
20790 static int
20791 xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20792              xmlSchemaBucketPtr rootBucket)
20793 {
20794     xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20795     xmlSchemaTreeItemPtr item, *items;
20796     int nbItems, i, ret = 0;
20797     xmlSchemaBucketPtr oldbucket = con->bucket;
20798     xmlSchemaElementPtr elemDecl;
20799 
20800 #define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20801 
20802     if ((con->pending == NULL) ||
20803     (con->pending->nbItems == 0))
20804     return(0);
20805 
20806     /*
20807     * Since xmlSchemaFixupComplexType() will create new particles
20808     * (local components), and those particle components need a bucket
20809     * on the constructor, we'll assure here that the constructor has
20810     * a bucket.
20811     * TODO: Think about storing locals _only_ on the main bucket.
20812     */
20813     if (con->bucket == NULL)
20814     con->bucket = rootBucket;
20815 
20816     /* TODO:
20817     * SPEC (src-redefine):
20818     * (6.2) "If it has no such self-reference, then all of the
20819     * following must be true:"
20820 
20821     * (6.2.2) The {model group} of the model group definition which
20822     * corresponds to it per XML Representation of Model Group
20823     * Definition Schema Components (�3.7.2) must be a �valid
20824     * restriction� of the {model group} of that model group definition
20825     * in I, as defined in Particle Valid (Restriction) (�3.9.6)."
20826     */
20827     xmlSchemaCheckSRCRedefineFirst(pctxt);
20828 
20829     /*
20830     * Add global components to the schemata's hash tables.
20831     */
20832     xmlSchemaAddComponents(pctxt, rootBucket);
20833 
20834     pctxt->ctxtType = NULL;
20835     items = (xmlSchemaTreeItemPtr *) con->pending->items;
20836     nbItems = con->pending->nbItems;
20837     /*
20838     * Now that we have parsed *all* the schema document(s) and converted
20839     * them to schema components, we can resolve references, apply component
20840     * constraints, create the FSA from the content model, etc.
20841     */
20842     /*
20843     * Resolve references of..
20844     *
20845     * 1. element declarations:
20846     *   - the type definition
20847     *   - the substitution group affiliation
20848     * 2. simple/complex types:
20849     *   - the base type definition
20850     *   - the memberTypes of union types
20851     *   - the itemType of list types
20852     * 3. attributes declarations and attribute uses:
20853     *   - the type definition
20854     *   - if an attribute use, then the attribute declaration
20855     * 4. attribute group references:
20856     *   - the attribute group definition
20857     * 5. particles:
20858     *   - the term of the particle (e.g. a model group)
20859     * 6. IDC key-references:
20860     *   - the referenced IDC 'key' or 'unique' definition
20861     * 7. Attribute prohibitions which had a "ref" attribute.
20862     */
20863     for (i = 0; i < nbItems; i++) {
20864     item = items[i];
20865     switch (item->type) {
20866         case XML_SCHEMA_TYPE_ELEMENT:
20867         xmlSchemaResolveElementReferences(
20868             (xmlSchemaElementPtr) item, pctxt);
20869         FIXHFAILURE;
20870         break;
20871         case XML_SCHEMA_TYPE_COMPLEX:
20872         case XML_SCHEMA_TYPE_SIMPLE:
20873         xmlSchemaResolveTypeReferences(
20874             (xmlSchemaTypePtr) item, pctxt);
20875         FIXHFAILURE;
20876         break;
20877         case XML_SCHEMA_TYPE_ATTRIBUTE:
20878         xmlSchemaResolveAttrTypeReferences(
20879             (xmlSchemaAttributePtr) item, pctxt);
20880         FIXHFAILURE;
20881         break;
20882         case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20883         xmlSchemaResolveAttrUseReferences(
20884             (xmlSchemaAttributeUsePtr) item, pctxt);
20885         FIXHFAILURE;
20886         break;
20887         case XML_SCHEMA_EXTRA_QNAMEREF:
20888         if ((WXS_QNAME_CAST item)->itemType ==
20889             XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20890         {
20891             xmlSchemaResolveAttrGroupReferences(
20892             WXS_QNAME_CAST item, pctxt);
20893         }
20894         FIXHFAILURE;
20895         break;
20896         case XML_SCHEMA_TYPE_SEQUENCE:
20897         case XML_SCHEMA_TYPE_CHOICE:
20898         case XML_SCHEMA_TYPE_ALL:
20899         xmlSchemaResolveModelGroupParticleReferences(pctxt,
20900             WXS_MODEL_GROUP_CAST item);
20901         FIXHFAILURE;
20902         break;
20903         case XML_SCHEMA_TYPE_IDC_KEY:
20904         case XML_SCHEMA_TYPE_IDC_UNIQUE:
20905         case XML_SCHEMA_TYPE_IDC_KEYREF:
20906         xmlSchemaResolveIDCKeyReferences(
20907             (xmlSchemaIDCPtr) item, pctxt);
20908         FIXHFAILURE;
20909         break;
20910         case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20911         /*
20912         * Handle attribue prohibition which had a
20913         * "ref" attribute.
20914         */
20915         xmlSchemaResolveAttrUseProhibReferences(
20916             WXS_ATTR_PROHIB_CAST item, pctxt);
20917         FIXHFAILURE;
20918         break;
20919         default:
20920         break;
20921     }
20922     }
20923     if (pctxt->nberrors != 0)
20924     goto exit_error;
20925 
20926     /*
20927     * Now that all references are resolved we
20928     * can check for circularity of...
20929     * 1. the base axis of type definitions
20930     * 2. nested model group definitions
20931     * 3. nested attribute group definitions
20932     * TODO: check for circual substitution groups.
20933     */
20934     for (i = 0; i < nbItems; i++) {
20935     item = items[i];
20936     /*
20937     * Let's better stop on the first error here.
20938     */
20939     switch (item->type) {
20940         case XML_SCHEMA_TYPE_COMPLEX:
20941         case XML_SCHEMA_TYPE_SIMPLE:
20942         xmlSchemaCheckTypeDefCircular(
20943             (xmlSchemaTypePtr) item, pctxt);
20944         FIXHFAILURE;
20945         if (pctxt->nberrors != 0)
20946             goto exit_error;
20947         break;
20948         case XML_SCHEMA_TYPE_GROUP:
20949         xmlSchemaCheckGroupDefCircular(
20950             (xmlSchemaModelGroupDefPtr) item, pctxt);
20951         FIXHFAILURE;
20952         if (pctxt->nberrors != 0)
20953             goto exit_error;
20954         break;
20955         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20956         xmlSchemaCheckAttrGroupCircular(
20957             (xmlSchemaAttributeGroupPtr) item, pctxt);
20958         FIXHFAILURE;
20959         if (pctxt->nberrors != 0)
20960             goto exit_error;
20961         break;
20962         default:
20963         break;
20964     }
20965     }
20966     if (pctxt->nberrors != 0)
20967     goto exit_error;
20968     /*
20969     * Model group definition references:
20970     * Such a reference is reflected by a particle at the component
20971     * level. Until now the 'term' of such particles pointed
20972     * to the model group definition; this was done, in order to
20973     * ease circularity checks. Now we need to set the 'term' of
20974     * such particles to the model group of the model group definition.
20975     */
20976     for (i = 0; i < nbItems; i++) {
20977     item = items[i];
20978     switch (item->type) {
20979         case XML_SCHEMA_TYPE_SEQUENCE:
20980         case XML_SCHEMA_TYPE_CHOICE:
20981         xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
20982             WXS_MODEL_GROUP_CAST item);
20983         break;
20984         default:
20985         break;
20986     }
20987     }
20988     if (pctxt->nberrors != 0)
20989     goto exit_error;
20990     /*
20991     * Expand attribute group references of attribute group definitions.
20992     */
20993     for (i = 0; i < nbItems; i++) {
20994     item = items[i];
20995     switch (item->type) {
20996             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20997         if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
20998             WXS_ATTR_GROUP_HAS_REFS(item))
20999         {
21000             xmlSchemaAttributeGroupExpandRefs(pctxt,
21001             WXS_ATTR_GROUP_CAST item);
21002             FIXHFAILURE;
21003         }
21004         break;
21005         default:
21006         break;
21007     }
21008     }
21009     if (pctxt->nberrors != 0)
21010     goto exit_error;
21011     /*
21012     * First compute the variety of simple types. This is needed as
21013     * a seperate step, since otherwise we won't be able to detect
21014     * circular union types in all cases.
21015     */
21016     for (i = 0; i < nbItems; i++) {
21017     item = items[i];
21018     switch (item->type) {
21019             case XML_SCHEMA_TYPE_SIMPLE:
21020         if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
21021             xmlSchemaFixupSimpleTypeStageOne(pctxt,
21022             (xmlSchemaTypePtr) item);
21023             FIXHFAILURE;
21024         }
21025         break;
21026         default:
21027         break;
21028     }
21029     }
21030     if (pctxt->nberrors != 0)
21031     goto exit_error;
21032     /*
21033     * Detect circular union types. Note that this needs the variety to
21034     * be already computed.
21035     */
21036     for (i = 0; i < nbItems; i++) {
21037     item = items[i];
21038     switch (item->type) {
21039             case XML_SCHEMA_TYPE_SIMPLE:
21040         if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
21041             xmlSchemaCheckUnionTypeDefCircular(pctxt,
21042             (xmlSchemaTypePtr) item);
21043             FIXHFAILURE;
21044         }
21045         break;
21046         default:
21047         break;
21048     }
21049     }
21050     if (pctxt->nberrors != 0)
21051     goto exit_error;
21052 
21053     /*
21054     * Do the complete type fixup for simple types.
21055     */
21056     for (i = 0; i < nbItems; i++) {
21057     item = items[i];
21058     switch (item->type) {
21059             case XML_SCHEMA_TYPE_SIMPLE:
21060         if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21061             xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
21062             FIXHFAILURE;
21063         }
21064         break;
21065         default:
21066         break;
21067     }
21068     }
21069     if (pctxt->nberrors != 0)
21070     goto exit_error;
21071     /*
21072     * At this point we need build and check all simple types.
21073     */
21074     /*
21075     * Apply contraints for attribute declarations.
21076     */
21077     for (i = 0; i < nbItems; i++) {
21078     item = items[i];
21079     switch (item->type) {
21080         case XML_SCHEMA_TYPE_ATTRIBUTE:
21081         xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
21082         FIXHFAILURE;
21083         break;
21084         default:
21085         break;
21086     }
21087     }
21088     if (pctxt->nberrors != 0)
21089     goto exit_error;
21090     /*
21091     * Apply constraints for attribute uses.
21092     */
21093     for (i = 0; i < nbItems; i++) {
21094     item = items[i];
21095     switch (item->type) {
21096         case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21097         if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
21098             xmlSchemaCheckAttrUsePropsCorrect(pctxt,
21099             WXS_ATTR_USE_CAST item);
21100             FIXHFAILURE;
21101         }
21102         break;
21103         default:
21104         break;
21105     }
21106     }
21107     if (pctxt->nberrors != 0)
21108     goto exit_error;
21109 
21110     /*
21111     * Apply constraints for attribute group definitions.
21112     */
21113     for (i = 0; i < nbItems; i++) {
21114     item = items[i];
21115     switch (item->type) {
21116     case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21117         if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
21118         ( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
21119         {
21120         xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
21121         FIXHFAILURE;
21122         }
21123         break;
21124     default:
21125         break;
21126     }
21127     }
21128     if (pctxt->nberrors != 0)
21129     goto exit_error;
21130 
21131     /*
21132     * Apply constraints for redefinitions.
21133     */
21134     if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
21135     xmlSchemaCheckSRCRedefineSecond(pctxt);
21136     if (pctxt->nberrors != 0)
21137     goto exit_error;
21138 
21139     /*
21140     * Complex types are builded and checked.
21141     */
21142     for (i = 0; i < nbItems; i++) {
21143     item = con->pending->items[i];
21144     switch (item->type) {
21145         case XML_SCHEMA_TYPE_COMPLEX:
21146         if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21147             xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
21148             FIXHFAILURE;
21149         }
21150         break;
21151         default:
21152         break;
21153     }
21154     }
21155     if (pctxt->nberrors != 0)
21156     goto exit_error;
21157 
21158     /*
21159     * The list could have changed, since xmlSchemaFixupComplexType()
21160     * will create particles and model groups in some cases.
21161     */
21162     items = (xmlSchemaTreeItemPtr *) con->pending->items;
21163     nbItems = con->pending->nbItems;
21164 
21165     /*
21166     * Apply some constraints for element declarations.
21167     */
21168     for (i = 0; i < nbItems; i++) {
21169     item = items[i];
21170     switch (item->type) {
21171         case XML_SCHEMA_TYPE_ELEMENT:
21172         elemDecl = (xmlSchemaElementPtr) item;
21173 
21174         if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
21175         {
21176             xmlSchemaCheckElementDeclComponent(
21177             (xmlSchemaElementPtr) elemDecl, pctxt);
21178             FIXHFAILURE;
21179         }
21180 
21181 #ifdef WXS_ELEM_DECL_CONS_ENABLED
21182         /*
21183         * Schema Component Constraint: Element Declarations Consistent
21184         * Apply this constraint to local types of element declarations.
21185         */
21186         if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
21187             (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
21188             (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
21189         {
21190             xmlSchemaCheckElementDeclConsistent(pctxt,
21191             WXS_BASIC_CAST elemDecl,
21192             WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
21193             NULL, NULL, 0);
21194         }
21195 #endif
21196         break;
21197         default:
21198         break;
21199     }
21200     }
21201     if (pctxt->nberrors != 0)
21202     goto exit_error;
21203 
21204     /*
21205     * Finally we can build the automaton from the content model of
21206     * complex types.
21207     */
21208 
21209     for (i = 0; i < nbItems; i++) {
21210     item = items[i];
21211     switch (item->type) {
21212         case XML_SCHEMA_TYPE_COMPLEX:
21213         xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
21214         /* FIXHFAILURE; */
21215         break;
21216         default:
21217         break;
21218     }
21219     }
21220     if (pctxt->nberrors != 0)
21221     goto exit_error;
21222     /*
21223     * URGENT TODO: cos-element-consistent
21224     */
21225     goto exit;
21226 
21227 exit_error:
21228     ret = pctxt->err;
21229     goto exit;
21230 
21231 exit_failure:
21232     ret = -1;
21233 
21234 exit:
21235     /*
21236     * Reset the constructor. This is needed for XSI acquisition, since
21237     * those items will be processed over and over again for every XSI
21238     * if not cleared here.
21239     */
21240     con->bucket = oldbucket;
21241     con->pending->nbItems = 0;
21242     if (con->substGroups != NULL) {
21243     xmlHashFree(con->substGroups,
21244         (xmlHashDeallocator) xmlSchemaSubstGroupFree);
21245     con->substGroups = NULL;
21246     }
21247     if (con->redefs != NULL) {
21248     xmlSchemaRedefListFree(con->redefs);
21249     con->redefs = NULL;
21250     }
21251     return(ret);
21252 }
21263 xmlSchemaPtr
21264 xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21265 {
21266     xmlSchemaPtr mainSchema = NULL;
21267     xmlSchemaBucketPtr bucket = NULL;
21268     int res;
21269 
21270     /*
21271     * This one is used if the schema to be parsed was specified via
21272     * the API; i.e. not automatically by the validated instance document.
21273     */
21274 
21275     xmlSchemaInitTypes();
21276 
21277     if (ctxt == NULL)
21278         return (NULL);
21279 
21280     /* TODO: Init the context. Is this all we need?*/
21281     ctxt->nberrors = 0;
21282     ctxt->err = 0;
21283     ctxt->counter = 0;
21284 
21285     /* Create the *main* schema. */
21286     mainSchema = xmlSchemaNewSchema(ctxt);
21287     if (mainSchema == NULL)
21288     goto exit_failure;
21289     /*
21290     * Create the schema constructor.
21291     */
21292     if (ctxt->constructor == NULL) {
21293     ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21294     if (ctxt->constructor == NULL)
21295         return(NULL);
21296     /* Take ownership of the constructor to be able to free it. */
21297     ctxt->ownsConstructor = 1;
21298     }
21299     ctxt->constructor->mainSchema = mainSchema;
21300     /*
21301     * Locate and add the schema document.
21302     */
21303     res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21304     ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21305     NULL, NULL, &bucket);
21306     if (res == -1)
21307     goto exit_failure;
21308     if (res != 0)
21309     goto exit;
21310 
21311     if (bucket == NULL) {
21312     /* TODO: Error code, actually we failed to *locate* the schema. */
21313     if (ctxt->URL)
21314         xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21315         NULL, NULL,
21316         "Failed to locate the main schema resource at '%s'",
21317         ctxt->URL, NULL);
21318     else
21319         xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21320         NULL, NULL,
21321         "Failed to locate the main schema resource",
21322             NULL, NULL);
21323     goto exit;
21324     }
21325     /* Then do the parsing for good. */
21326     if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
21327     goto exit_failure;
21328     if (ctxt->nberrors != 0)
21329     goto exit;
21330 
21331     mainSchema->doc = bucket->doc;
21332     mainSchema->preserve = ctxt->preserve;
21333 
21334     ctxt->schema = mainSchema;
21335 
21336     if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
21337     goto exit_failure;
21338 
21339     /*
21340     * TODO: This is not nice, since we cannot distinguish from the
21341     * result if there was an internal error or not.
21342     */
21343 exit:
21344     if (ctxt->nberrors != 0) {
21345     if (mainSchema) {
21346         xmlSchemaFree(mainSchema);
21347         mainSchema = NULL;
21348     }
21349     if (ctxt->constructor) {
21350         xmlSchemaConstructionCtxtFree(ctxt->constructor);
21351         ctxt->constructor = NULL;
21352         ctxt->ownsConstructor = 0;
21353     }
21354     }
21355     ctxt->schema = NULL;
21356     return(mainSchema);
21357 exit_failure:
21358     /*
21359     * Quite verbose, but should catch internal errors, which were
21360     * not communitated.
21361     */
21362     if (mainSchema) {
21363         xmlSchemaFree(mainSchema);
21364     mainSchema = NULL;
21365     }
21366     if (ctxt->constructor) {
21367     xmlSchemaConstructionCtxtFree(ctxt->constructor);
21368     ctxt->constructor = NULL;
21369     ctxt->ownsConstructor = 0;
21370     }
21371     PERROR_INT2("xmlSchemaParse",
21372     "An internal error occured");
21373     ctxt->schema = NULL;
21374     return(NULL);
21375 }
21376 
21386 void
21387 xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21388                          xmlSchemaValidityErrorFunc err,
21389                          xmlSchemaValidityWarningFunc warn, void *ctx)
21390 {
21391     if (ctxt == NULL)
21392         return;
21393     ctxt->error = err;
21394     ctxt->warning = warn;
21395     ctxt->errCtxt = ctx;
21396     if (ctxt->vctxt != NULL)
21397     xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21398 }
21399 
21408 void
21409 xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21410                    xmlStructuredErrorFunc serror,
21411                    void *ctx)
21412 {
21413     if (ctxt == NULL)
21414     return;
21415     ctxt->serror = serror;
21416     ctxt->errCtxt = ctx;
21417     if (ctxt->vctxt != NULL)
21418     xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
21419 }
21420 
21432 int
21433 xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21434              xmlSchemaValidityErrorFunc * err,
21435              xmlSchemaValidityWarningFunc * warn, void **ctx)
21436 {
21437     if (ctxt == NULL)
21438         return(-1);
21439     if (err != NULL)
21440         *err = ctxt->error;
21441     if (warn != NULL)
21442         *warn = ctxt->warning;
21443     if (ctx != NULL)
21444         *ctx = ctxt->errCtxt;
21445     return(0);
21446 }
21447 
21457 static const xmlChar *
21458 xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21459 {
21460     switch (type) {
21461         case XML_SCHEMA_FACET_PATTERN:
21462             return (BAD_CAST "pattern");
21463         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
21464             return (BAD_CAST "maxExclusive");
21465         case XML_SCHEMA_FACET_MAXINCLUSIVE:
21466             return (BAD_CAST "maxInclusive");
21467         case XML_SCHEMA_FACET_MINEXCLUSIVE:
21468             return (BAD_CAST "minExclusive");
21469         case XML_SCHEMA_FACET_MININCLUSIVE:
21470             return (BAD_CAST "minInclusive");
21471         case XML_SCHEMA_FACET_WHITESPACE:
21472             return (BAD_CAST "whiteSpace");
21473         case XML_SCHEMA_FACET_ENUMERATION:
21474             return (BAD_CAST "enumeration");
21475         case XML_SCHEMA_FACET_LENGTH:
21476             return (BAD_CAST "length");
21477         case XML_SCHEMA_FACET_MAXLENGTH:
21478             return (BAD_CAST "maxLength");
21479         case XML_SCHEMA_FACET_MINLENGTH:
21480             return (BAD_CAST "minLength");
21481         case XML_SCHEMA_FACET_TOTALDIGITS:
21482             return (BAD_CAST "totalDigits");
21483         case XML_SCHEMA_FACET_FRACTIONDIGITS:
21484             return (BAD_CAST "fractionDigits");
21485         default:
21486             break;
21487     }
21488     return (BAD_CAST "Internal Error");
21489 }
21490 
21491 static xmlSchemaWhitespaceValueType
21492 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21493 {
21494     /*
21495     * The normalization type can be changed only for types which are derived
21496     * from xsd:string.
21497     */
21498     if (type->type == XML_SCHEMA_TYPE_BASIC) {
21499     /*
21500     * Note that we assume a whitespace of preserve for anySimpleType.
21501     */
21502     if ((type->builtInType == XML_SCHEMAS_STRING) ||
21503         (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21504         return(XML_SCHEMA_WHITESPACE_PRESERVE);
21505     else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
21506         return(XML_SCHEMA_WHITESPACE_REPLACE);
21507     else {
21508         /*
21509         * For all �atomic� datatypes other than string (and types �derived�
21510         * by �restriction� from it) the value of whiteSpace is fixed to
21511         * collapse
21512         * Note that this includes built-in list datatypes.
21513         */
21514         return(XML_SCHEMA_WHITESPACE_COLLAPSE);
21515     }
21516     } else if (WXS_IS_LIST(type)) {
21517     /*
21518     * For list types the facet "whiteSpace" is fixed to "collapse".
21519     */
21520     return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21521     } else if (WXS_IS_UNION(type)) {
21522     return (XML_SCHEMA_WHITESPACE_UNKNOWN);
21523     } else if (WXS_IS_ATOMIC(type)) {
21524     if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21525         return (XML_SCHEMA_WHITESPACE_PRESERVE);
21526     else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21527         return (XML_SCHEMA_WHITESPACE_REPLACE);
21528     else
21529         return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21530     }
21531     return (-1);
21532 }
21533 
21534 /************************************************************************
21535  *                                  *
21536  *          Simple type validation              *
21537  *                                  *
21538  ************************************************************************/
21539 
21540 
21541 /************************************************************************
21542  *                                  *
21543  *          DOM Validation code             *
21544  *                                  *
21545  ************************************************************************/
21546 
21561 static int
21562 xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
21563                 xmlSchemaPtr schema,
21564                 xmlNodePtr node,
21565                 const xmlChar *nsName,
21566                 const xmlChar *location)
21567 {
21568     int ret = 0;
21569     xmlSchemaParserCtxtPtr pctxt;
21570     xmlSchemaBucketPtr bucket = NULL;
21571 
21572     if ((vctxt == NULL) || (schema == NULL))
21573     return (-1);
21574 
21575     if (vctxt->pctxt == NULL) {
21576     VERROR_INT("xmlSchemaAssembleByLocation",
21577         "no parser context available");
21578     return(-1);
21579     }
21580     pctxt = vctxt->pctxt;
21581     if (pctxt->constructor == NULL) {
21582     PERROR_INT("xmlSchemaAssembleByLocation",
21583         "no constructor");
21584     return(-1);
21585     }
21586     /*
21587     * Acquire the schema document.
21588     */
21589     location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21590     location, node);
21591     /*
21592     * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21593     * the process will automatically change this to
21594     * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21595     */
21596     ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21597     location, NULL, NULL, 0, node, NULL, nsName,
21598     &bucket);
21599     if (ret != 0)
21600     return(ret);
21601     if (bucket == NULL) {
21602     /*
21603     * Generate a warning that the document could not be located.
21604     */
21605     xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21606         node, NULL,
21607         "The document at location '%s' could not be acquired",
21608         location, NULL, NULL);
21609     return(ret);
21610     }
21611     /*
21612     * The first located schema will be handled as if all other
21613     * schemas imported by XSI were imported by this first schema.
21614     */
21615     if ((bucket != NULL) &&
21616     (WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21617     WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21618     /*
21619     * TODO: Is this handled like an import? I.e. is it not an error
21620     * if the schema cannot be located?
21621     */
21622     if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21623     return(0);
21624     /*
21625     * We will reuse the parser context for every schema imported
21626     * directly via XSI. So reset the context.
21627     */
21628     pctxt->nberrors = 0;
21629     pctxt->err = 0;
21630     pctxt->doc = bucket->doc;
21631 
21632     ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21633     if (ret == -1) {
21634     pctxt->doc = NULL;
21635     goto exit_failure;
21636     }
21637     /* Paranoid error channelling. */
21638     if ((ret == 0) && (pctxt->nberrors != 0))
21639     ret = pctxt->err;
21640     if (pctxt->nberrors == 0) {
21641     /*
21642     * Only bother to fixup pending components, if there was
21643     * no error yet.
21644     * For every XSI acquired schema (and its sub-schemata) we will
21645     * fixup the components.
21646     */
21647     xmlSchemaFixupComponents(pctxt, bucket);
21648     ret = pctxt->err;
21649     /*
21650     * Not nice, but we need somehow to channel the schema parser
21651     * error to the validation context.
21652     */
21653     if ((ret != 0) && (vctxt->err == 0))
21654         vctxt->err = ret;
21655     vctxt->nberrors += pctxt->nberrors;
21656     } else {
21657     /* Add to validation error sum. */
21658     vctxt->nberrors += pctxt->nberrors;
21659     }
21660     pctxt->doc = NULL;
21661     return(ret);
21662 exit_failure:
21663     pctxt->doc = NULL;
21664     return (-1);
21665 }
21666 
21667 static xmlSchemaAttrInfoPtr
21668 xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21669              int metaType)
21670 {
21671     if (vctxt->nbAttrInfos == 0)
21672     return (NULL);
21673     {
21674     int i;
21675     xmlSchemaAttrInfoPtr iattr;
21676 
21677     for (i = 0; i < vctxt->nbAttrInfos; i++) {
21678         iattr = vctxt->attrInfos[i];
21679         if (iattr->metaType == metaType)
21680         return (iattr);
21681     }
21682 
21683     }
21684     return (NULL);
21685 }
21686 
21699 static int
21700 xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
21701 {
21702     const xmlChar *cur, *end;
21703     const xmlChar *nsname = NULL, *location;
21704     int count = 0;
21705     int ret = 0;
21706     xmlSchemaAttrInfoPtr iattr;
21707 
21708     /*
21709     * Parse the value; we will assume an even number of values
21710     * to be given (this is how Xerces and XSV work).
21711     *
21712     * URGENT TODO: !! This needs to work for both
21713     * @noNamespaceSchemaLocation AND @schemaLocation on the same
21714     * element !!
21715     */
21716     iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21717     XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21718     if (iattr == NULL)
21719     iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21720     XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21721     if (iattr == NULL)
21722     return (0);
21723     cur = iattr->value;
21724     do {
21725     /*
21726     * TODO: Move the string parsing mechanism away from here.
21727     */
21728     if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
21729         /*
21730         * Get the namespace name.
21731         */
21732         while (IS_BLANK_CH(*cur))
21733         cur++;
21734         end = cur;
21735         while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21736         end++;
21737         if (end == cur)
21738         break;
21739         count++; /* TODO: Don't use the schema's dict. */
21740         nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21741         cur = end;
21742     }
21743     /*
21744     * Get the URI.
21745     */
21746     while (IS_BLANK_CH(*cur))
21747         cur++;
21748     end = cur;
21749     while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21750         end++;
21751     if (end == cur) {
21752         if (iattr->metaType ==
21753         XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21754         {
21755         /*
21756         * If using @schemaLocation then tuples are expected.
21757         * I.e. the namespace name *and* the document's URI.
21758         */
21759         xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21760             iattr->node, NULL,
21761             "The value must consist of tuples: the target namespace "
21762             "name and the document's URI", NULL, NULL, NULL);
21763         }
21764         break;
21765     }
21766     count++; /* TODO: Don't use the schema's dict. */
21767     location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21768     cur = end;
21769     ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21770         iattr->node, nsname, location);
21771     if (ret == -1) {
21772         VERROR_INT("xmlSchemaAssembleByXSI",
21773         "assembling schemata");
21774         return (-1);
21775     }
21776     } while (*cur != 0);
21777     return (ret);
21778 }
21779 
21780 static const xmlChar *
21781 xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21782              const xmlChar *prefix)
21783 {
21784     if (vctxt->sax != NULL) {
21785     int i, j;
21786     xmlSchemaNodeInfoPtr inode;
21787 
21788     for (i = vctxt->depth; i >= 0; i--) {
21789         if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21790         inode = vctxt->elemInfos[i];
21791         for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21792             if (((prefix == NULL) &&
21793                 (inode->nsBindings[j] == NULL)) ||
21794             ((prefix != NULL) && xmlStrEqual(prefix,
21795                 inode->nsBindings[j]))) {
21796 
21797             /*
21798             * Note that the namespace bindings are already
21799             * in a string dict.
21800             */
21801             return (inode->nsBindings[j+1]);
21802             }
21803         }
21804         }
21805     }
21806     return (NULL);
21807 #ifdef LIBXML_READER_ENABLED
21808     } else if (vctxt->reader != NULL) {
21809     xmlChar *nsName;
21810 
21811     nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21812     if (nsName != NULL) {
21813         const xmlChar *ret;
21814 
21815         ret = xmlDictLookup(vctxt->dict, nsName, -1);
21816         xmlFree(nsName);
21817         return (ret);
21818     } else
21819         return (NULL);
21820 #endif
21821     } else {
21822     xmlNsPtr ns;
21823 
21824     if ((vctxt->inode->node == NULL) ||
21825         (vctxt->inode->node->doc == NULL)) {
21826         VERROR_INT("xmlSchemaLookupNamespace",
21827         "no node or node's doc avaliable");
21828         return (NULL);
21829     }
21830     ns = xmlSearchNs(vctxt->inode->node->doc,
21831         vctxt->inode->node, prefix);
21832     if (ns != NULL)
21833         return (ns->href);
21834     return (NULL);
21835     }
21836 }
21837 
21838 /*
21839 * This one works on the schema of the validation context.
21840 */
21841 static int
21842 xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21843               xmlSchemaPtr schema,
21844               xmlNodePtr node,
21845               const xmlChar *value,
21846               xmlSchemaValPtr *val,
21847               int valNeeded)
21848 {
21849     int ret;
21850 
21851     if (vctxt && (vctxt->schema == NULL)) {
21852     VERROR_INT("xmlSchemaValidateNotation",
21853         "a schema is needed on the validation context");
21854     return (-1);
21855     }
21856     ret = xmlValidateQName(value, 1);
21857     if (ret != 0)
21858     return (ret);
21859     {
21860     xmlChar *localName = NULL;
21861     xmlChar *prefix = NULL;
21862 
21863     localName = xmlSplitQName2(value, &prefix);
21864     if (prefix != NULL) {
21865         const xmlChar *nsName = NULL;
21866 
21867         if (vctxt != NULL)
21868         nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21869         else if (node != NULL) {
21870         xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21871         if (ns != NULL)
21872             nsName = ns->href;
21873         } else {
21874         xmlFree(prefix);
21875         xmlFree(localName);
21876         return (1);
21877         }
21878         if (nsName == NULL) {
21879         xmlFree(prefix);
21880         xmlFree(localName);
21881         return (1);
21882         }
21883         if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
21884         if ((valNeeded) && (val != NULL)) {
21885             (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName),
21886                                xmlStrdup(nsName));
21887             if (*val == NULL)
21888             ret = -1;
21889         }
21890         } else
21891         ret = 1;
21892         xmlFree(prefix);
21893         xmlFree(localName);
21894     } else {
21895         if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
21896         if (valNeeded && (val != NULL)) {
21897             (*val) = xmlSchemaNewNOTATIONValue(
21898             BAD_CAST xmlStrdup(value), NULL);
21899             if (*val == NULL)
21900             ret = -1;
21901         }
21902         } else
21903         return (1);
21904     }
21905     }
21906     return (ret);
21907 }
21908 
21909 static int
21910 xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21911                const xmlChar* lname,
21912                const xmlChar* nsname)
21913 {
21914     int i;
21915 
21916     lname = xmlDictLookup(vctxt->dict, lname, -1);
21917     if (lname == NULL)
21918     return(-1);
21919     if (nsname != NULL) {
21920     nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21921     if (nsname == NULL)
21922         return(-1);
21923     }
21924     for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21925     if ((vctxt->nodeQNames->items [i] == lname) &&
21926         (vctxt->nodeQNames->items[i +1] == nsname))
21927         /* Already there */
21928         return(i);
21929     }
21930     /* Add new entry. */
21931     i = vctxt->nodeQNames->nbItems;
21932     xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21933     xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21934     return(i);
21935 }
21936 
21937 /************************************************************************
21938  *                                  *
21939  *  Validation of identity-constraints (IDC)                            *
21940  *                                  *
21941  ************************************************************************/
21942 
21951 static void
21952 xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
21953             xmlSchemaValidCtxtPtr vctxt)
21954 {
21955     xmlSchemaIDCAugPtr aidc;
21956 
21957     aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
21958     if (aidc == NULL) {
21959     xmlSchemaVErrMemory(vctxt,
21960         "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
21961         NULL);
21962     return;
21963     }
21964     aidc->keyrefDepth = -1;
21965     aidc->def = idcDef;
21966     aidc->next = NULL;
21967     if (vctxt->aidcs == NULL)
21968     vctxt->aidcs = aidc;
21969     else {
21970     aidc->next = vctxt->aidcs;
21971     vctxt->aidcs = aidc;
21972     }
21973     /*
21974     * Save if we have keyrefs at all.
21975     */
21976     if ((vctxt->hasKeyrefs == 0) &&
21977     (idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
21978     vctxt->hasKeyrefs = 1;
21979 }
21980 
21987 static void
21988 xmlSchemaAugmentImportedIDC(xmlSchemaImportPtr imported, xmlSchemaValidCtxtPtr vctxt) {
21989     if (imported->schema->idcDef != NULL) {
21990         xmlHashScan(imported->schema->idcDef ,
21991         (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
21992     }
21993 }
21994 
22003 static xmlSchemaPSVIIDCBindingPtr
22004 xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
22005 {
22006     xmlSchemaPSVIIDCBindingPtr ret;
22007 
22008     ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
22009         sizeof(xmlSchemaPSVIIDCBinding));
22010     if (ret == NULL) {
22011     xmlSchemaVErrMemory(NULL,
22012         "allocating a PSVI IDC binding item", NULL);
22013     return (NULL);
22014     }
22015     memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
22016     ret->definition = idcDef;
22017     return (ret);
22018 }
22019 
22031 static int
22032 xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
22033                    xmlSchemaPSVIIDCNodePtr item)
22034 {
22035     /*
22036     * Add to gobal list.
22037     */
22038     if (vctxt->idcNodes == NULL) {
22039     vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22040         xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
22041     if (vctxt->idcNodes == NULL) {
22042         xmlSchemaVErrMemory(vctxt,
22043         "allocating the IDC node table item list", NULL);
22044         return (-1);
22045     }
22046     vctxt->sizeIdcNodes = 20;
22047     } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
22048     vctxt->sizeIdcNodes *= 2;
22049     vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22050         xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
22051         sizeof(xmlSchemaPSVIIDCNodePtr));
22052     if (vctxt->idcNodes == NULL) {
22053         xmlSchemaVErrMemory(vctxt,
22054         "re-allocating the IDC node table item list", NULL);
22055         return (-1);
22056     }
22057     }
22058     vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
22059 
22060     return (0);
22061 }
22062 
22072 static int
22073 xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
22074              xmlSchemaPSVIIDCKeyPtr key)
22075 {
22076     /*
22077     * Add to gobal list.
22078     */
22079     if (vctxt->idcKeys == NULL) {
22080     vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22081         xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
22082     if (vctxt->idcKeys == NULL) {
22083         xmlSchemaVErrMemory(vctxt,
22084         "allocating the IDC key storage list", NULL);
22085         return (-1);
22086     }
22087     vctxt->sizeIdcKeys = 40;
22088     } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
22089     vctxt->sizeIdcKeys *= 2;
22090     vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22091         xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
22092         sizeof(xmlSchemaPSVIIDCKeyPtr));
22093     if (vctxt->idcKeys == NULL) {
22094         xmlSchemaVErrMemory(vctxt,
22095         "re-allocating the IDC key storage list", NULL);
22096         return (-1);
22097     }
22098     }
22099     vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
22100 
22101     return (0);
22102 }
22103 
22113 static int
22114 xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
22115                 xmlSchemaPSVIIDCNodePtr ntItem)
22116 {
22117     if (bind->nodeTable == NULL) {
22118     bind->sizeNodes = 10;
22119     bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22120         xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
22121     if (bind->nodeTable == NULL) {
22122         xmlSchemaVErrMemory(NULL,
22123         "allocating an array of IDC node-table items", NULL);
22124         return(-1);
22125     }
22126     } else if (bind->sizeNodes <= bind->nbNodes) {
22127     bind->sizeNodes *= 2;
22128     bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22129         xmlRealloc(bind->nodeTable, bind->sizeNodes *
22130         sizeof(xmlSchemaPSVIIDCNodePtr));
22131     if (bind->nodeTable == NULL) {
22132         xmlSchemaVErrMemory(NULL,
22133         "re-allocating an array of IDC node-table items", NULL);
22134         return(-1);
22135     }
22136     }
22137     bind->nodeTable[bind->nbNodes++] = ntItem;
22138     return(0);
22139 }
22140 
22152 static xmlSchemaPSVIIDCBindingPtr
22153 xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
22154               xmlSchemaIDCMatcherPtr matcher)
22155 {
22156     xmlSchemaNodeInfoPtr ielem;
22157 
22158     ielem = vctxt->elemInfos[matcher->depth];
22159 
22160     if (ielem->idcTable == NULL) {
22161     ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
22162     if (ielem->idcTable == NULL)
22163         return (NULL);
22164     return(ielem->idcTable);
22165     } else {
22166     xmlSchemaPSVIIDCBindingPtr bind = NULL;
22167 
22168     bind = ielem->idcTable;
22169     do {
22170         if (bind->definition == matcher->aidc->def)
22171         return(bind);
22172         if (bind->next == NULL) {
22173         bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
22174         if (bind->next == NULL)
22175             return (NULL);
22176         return(bind->next);
22177         }
22178         bind = bind->next;
22179     } while (bind != NULL);
22180     }
22181     return (NULL);
22182 }
22183 
22184 static xmlSchemaItemListPtr
22185 xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22186                  xmlSchemaIDCMatcherPtr matcher)
22187 {
22188     if (matcher->targets == NULL)
22189     matcher->targets = xmlSchemaItemListCreate();
22190     return(matcher->targets);
22191 }
22192 
22199 static void
22200 xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
22201 {
22202     if (key->val != NULL)
22203     xmlSchemaFreeValue(key->val);
22204     xmlFree(key);
22205 }
22206 
22213 static void
22214 xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
22215 {
22216     if (bind->nodeTable != NULL)
22217     xmlFree(bind->nodeTable);
22218     if (bind->dupls != NULL)
22219     xmlSchemaItemListFree(bind->dupls);
22220     xmlFree(bind);
22221 }
22222 
22229 static void
22230 xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
22231 {
22232     xmlSchemaPSVIIDCBindingPtr prev;
22233 
22234     while (bind != NULL) {
22235     prev = bind;
22236     bind = bind->next;
22237     xmlSchemaIDCFreeBinding(prev);
22238     }
22239 }
22240 
22247 static void
22248 xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22249 {
22250     xmlSchemaIDCMatcherPtr next;
22251 
22252     while (matcher != NULL) {
22253     next = matcher->next;
22254     if (matcher->keySeqs != NULL) {
22255         int i;
22256         for (i = 0; i < matcher->sizeKeySeqs; i++)
22257         if (matcher->keySeqs[i] != NULL)
22258             xmlFree(matcher->keySeqs[i]);
22259         xmlFree(matcher->keySeqs);
22260     }
22261     if (matcher->targets != NULL) {
22262         if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22263         int i;
22264         xmlSchemaPSVIIDCNodePtr idcNode;
22265         /*
22266         * Node-table items for keyrefs are not stored globally
22267         * to the validation context, since they are not bubbled.
22268         * We need to free them here.
22269         */
22270         for (i = 0; i < matcher->targets->nbItems; i++) {
22271             idcNode =
22272             (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22273             xmlFree(idcNode->keys);
22274             xmlFree(idcNode);
22275         }
22276         }
22277         xmlSchemaItemListFree(matcher->targets);
22278     }
22279     xmlFree(matcher);
22280     matcher = next;
22281     }
22282 }
22283 
22291 static void
22292 xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
22293                    xmlSchemaIDCMatcherPtr matcher)
22294 {
22295     xmlSchemaIDCMatcherPtr next;
22296 
22297     while (matcher != NULL) {
22298     next = matcher->next;
22299     if (matcher->keySeqs != NULL) {
22300         int i;
22301         /*
22302         * Don't free the array, but only the content.
22303         */
22304         for (i = 0; i < matcher->sizeKeySeqs; i++)
22305         if (matcher->keySeqs[i] != NULL) {
22306             xmlFree(matcher->keySeqs[i]);
22307             matcher->keySeqs[i] = NULL;
22308         }
22309     }
22310     if (matcher->targets) {
22311         if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22312         int i;
22313         xmlSchemaPSVIIDCNodePtr idcNode;
22314         /*
22315         * Node-table items for keyrefs are not stored globally
22316         * to the validation context, since they are not bubbled.
22317         * We need to free them here.
22318         */
22319         for (i = 0; i < matcher->targets->nbItems; i++) {
22320             idcNode =
22321             (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22322             xmlFree(idcNode->keys);
22323             xmlFree(idcNode);
22324         }
22325         }
22326         xmlSchemaItemListFree(matcher->targets);
22327         matcher->targets = NULL;
22328     }
22329     matcher->next = NULL;
22330     /*
22331     * Cache the matcher.
22332     */
22333     if (vctxt->idcMatcherCache != NULL)
22334         matcher->nextCached = vctxt->idcMatcherCache;
22335     vctxt->idcMatcherCache = matcher;
22336 
22337     matcher = next;
22338     }
22339 }
22340 
22355 static int
22356 xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22357             xmlSchemaIDCMatcherPtr matcher,
22358             xmlSchemaIDCSelectPtr sel,
22359             int type)
22360 {
22361     xmlSchemaIDCStateObjPtr sto;
22362 
22363     /*
22364     * Reuse the state objects from the pool.
22365     */
22366     if (vctxt->xpathStatePool != NULL) {
22367     sto = vctxt->xpathStatePool;
22368     vctxt->xpathStatePool = sto->next;
22369     sto->next = NULL;
22370     } else {
22371     /*
22372     * Create a new state object.
22373     */
22374     sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22375     if (sto == NULL) {
22376         xmlSchemaVErrMemory(NULL,
22377         "allocating an IDC state object", NULL);
22378         return (-1);
22379     }
22380     memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22381     }
22382     /*
22383     * Add to global list.
22384     */
22385     if (vctxt->xpathStates != NULL)
22386     sto->next = vctxt->xpathStates;
22387     vctxt->xpathStates = sto;
22388 
22389     /*
22390     * Free the old xpath validation context.
22391     */
22392     if (sto->xpathCtxt != NULL)
22393     xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22394 
22395     /*
22396     * Create a new XPath (pattern) validation context.
22397     */
22398     sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22399     (xmlPatternPtr) sel->xpathComp);
22400     if (sto->xpathCtxt == NULL) {
22401     VERROR_INT("xmlSchemaIDCAddStateObject",
22402         "failed to create an XPath validation context");
22403     return (-1);
22404     }
22405     sto->type = type;
22406     sto->depth = vctxt->depth;
22407     sto->matcher = matcher;
22408     sto->sel = sel;
22409     sto->nbHistory = 0;
22410 
22411 #ifdef DEBUG_IDC
22412     xmlGenericError(xmlGenericErrorContext, "IDC:   STO push '%s'\n",
22413     sto->sel->xpath);
22414 #endif
22415     return (0);
22416 }
22417 
22428 static int
22429 xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
22430                xmlElementType nodeType)
22431 {
22432     xmlSchemaIDCStateObjPtr sto, head = NULL, first;
22433     int res, resolved = 0, depth = vctxt->depth;
22434 
22435     if (vctxt->xpathStates == NULL)
22436     return (0);
22437 
22438     if (nodeType == XML_ATTRIBUTE_NODE)
22439     depth++;
22440 #ifdef DEBUG_IDC
22441     {
22442     xmlChar *str = NULL;
22443     xmlGenericError(xmlGenericErrorContext,
22444         "IDC: EVAL on %s, depth %d, type %d\n",
22445         xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22446         vctxt->inode->localName), depth, nodeType);
22447     FREE_AND_NULL(str)
22448     }
22449 #endif
22450     /*
22451     * Process all active XPath state objects.
22452     */
22453     first = vctxt->xpathStates;
22454     sto = first;
22455     while (sto != head) {
22456 #ifdef DEBUG_IDC
22457     if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
22458         xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] selector '%s'\n",
22459         sto->matcher->aidc->def->name, sto->sel->xpath);
22460     else
22461         xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] field '%s'\n",
22462         sto->matcher->aidc->def->name, sto->sel->xpath);
22463 #endif
22464     if (nodeType == XML_ELEMENT_NODE)
22465         res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
22466         vctxt->inode->localName, vctxt->inode->nsName);
22467     else
22468         res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
22469         vctxt->inode->localName, vctxt->inode->nsName);
22470 
22471     if (res == -1) {
22472         VERROR_INT("xmlSchemaXPathEvaluate",
22473         "calling xmlStreamPush()");
22474         return (-1);
22475     }
22476     if (res == 0)
22477         goto next_sto;
22478     /*
22479     * Full match.
22480     */
22481 #ifdef DEBUG_IDC
22482     xmlGenericError(xmlGenericErrorContext, "IDC:     "
22483         "MATCH\n");
22484 #endif
22485     /*
22486     * Register a match in the state object history.
22487     */
22488     if (sto->history == NULL) {
22489         sto->history = (int *) xmlMalloc(5 * sizeof(int));
22490         if (sto->history == NULL) {
22491         xmlSchemaVErrMemory(NULL,
22492             "allocating the state object history", NULL);
22493         return(-1);
22494         }
22495         sto->sizeHistory = 5;
22496     } else if (sto->sizeHistory <= sto->nbHistory) {
22497         sto->sizeHistory *= 2;
22498         sto->history = (int *) xmlRealloc(sto->history,
22499         sto->sizeHistory * sizeof(int));
22500         if (sto->history == NULL) {
22501         xmlSchemaVErrMemory(NULL,
22502             "re-allocating the state object history", NULL);
22503         return(-1);
22504         }
22505     }
22506     sto->history[sto->nbHistory++] = depth;
22507 
22508 #ifdef DEBUG_IDC
22509     xmlGenericError(xmlGenericErrorContext, "IDC:       push match '%d'\n",
22510         vctxt->depth);
22511 #endif
22512 
22513     if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22514         xmlSchemaIDCSelectPtr sel;
22515         /*
22516         * Activate state objects for the IDC fields of
22517         * the IDC selector.
22518         */
22519 #ifdef DEBUG_IDC
22520         xmlGenericError(xmlGenericErrorContext, "IDC:     "
22521         "activating field states\n");
22522 #endif
22523         sel = sto->matcher->aidc->def->fields;
22524         while (sel != NULL) {
22525         if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22526             sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22527             return (-1);
22528         sel = sel->next;
22529         }
22530     } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22531         /*
22532         * An IDC key node was found by the IDC field.
22533         */
22534 #ifdef DEBUG_IDC
22535         xmlGenericError(xmlGenericErrorContext,
22536         "IDC:     key found\n");
22537 #endif
22538         /*
22539         * Notify that the character value of this node is
22540         * needed.
22541         */
22542         if (resolved == 0) {
22543         if ((vctxt->inode->flags &
22544             XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22545         vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22546         }
22547         resolved++;
22548     }
22549 next_sto:
22550     if (sto->next == NULL) {
22551         /*
22552         * Evaluate field state objects created on this node as well.
22553         */
22554         head = first;
22555         sto = vctxt->xpathStates;
22556     } else
22557         sto = sto->next;
22558     }
22559     return (resolved);
22560 }
22561 
22562 static const xmlChar *
22563 xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
22564                   xmlChar **buf,
22565                   xmlSchemaPSVIIDCKeyPtr *seq,
22566                   int count)
22567 {
22568     int i, res;
22569     xmlChar *value = NULL;
22570 
22571     *buf = xmlStrdup(BAD_CAST "[");
22572     for (i = 0; i < count; i++) {
22573     *buf = xmlStrcat(*buf, BAD_CAST "'");
22574     res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22575         xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22576         &value);
22577     if (res == 0)
22578         *buf = xmlStrcat(*buf, BAD_CAST value);
22579     else {
22580         VERROR_INT("xmlSchemaFormatIDCKeySequence",
22581         "failed to compute a canonical value");
22582         *buf = xmlStrcat(*buf, BAD_CAST "???");
22583     }
22584     if (i < count -1)
22585         *buf = xmlStrcat(*buf, BAD_CAST "', ");
22586     else
22587         *buf = xmlStrcat(*buf, BAD_CAST "'");
22588     if (value != NULL) {
22589         xmlFree(value);
22590         value = NULL;
22591     }
22592     }
22593     *buf = xmlStrcat(*buf, BAD_CAST "]");
22594 
22595     return (BAD_CAST *buf);
22596 }
22597 
22606 static int
22607 xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22608 {
22609     xmlSchemaIDCStateObjPtr sto;
22610     int res;
22611 
22612     if (vctxt->xpathStates == NULL)
22613     return(0);
22614     sto = vctxt->xpathStates;
22615     do {
22616     res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22617     if (res == -1)
22618         return (-1);
22619     sto = sto->next;
22620     } while (sto != NULL);
22621     return(0);
22622 }
22623 
22635 static int
22636 xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
22637                  int depth)
22638 {
22639     xmlSchemaIDCStateObjPtr sto, nextsto;
22640     int res, matchDepth;
22641     xmlSchemaPSVIIDCKeyPtr key = NULL;
22642     xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
22643 
22644     if (vctxt->xpathStates == NULL)
22645     return (0);
22646     sto = vctxt->xpathStates;
22647 
22648 #ifdef DEBUG_IDC
22649     {
22650     xmlChar *str = NULL;
22651     xmlGenericError(xmlGenericErrorContext,
22652         "IDC: BACK on %s, depth %d\n",
22653         xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22654         vctxt->inode->localName), vctxt->depth);
22655     FREE_AND_NULL(str)
22656     }
22657 #endif
22658     /*
22659     * Evaluate the state objects.
22660     */
22661     while (sto != NULL) {
22662     res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22663     if (res == -1) {
22664         VERROR_INT("xmlSchemaXPathProcessHistory",
22665         "calling xmlStreamPop()");
22666         return (-1);
22667     }
22668 #ifdef DEBUG_IDC
22669     xmlGenericError(xmlGenericErrorContext, "IDC:   stream pop '%s'\n",
22670         sto->sel->xpath);
22671 #endif
22672     if (sto->nbHistory == 0)
22673         goto deregister_check;
22674 
22675     matchDepth = sto->history[sto->nbHistory -1];
22676 
22677     /*
22678     * Only matches at the current depth are of interest.
22679     */
22680     if (matchDepth != depth) {
22681         sto = sto->next;
22682         continue;
22683     }
22684     if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22685         /*
22686         * NOTE: According to
22687         *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22688         *   ... the simple-content of complex types is also allowed.
22689         */
22690 
22691         if (WXS_IS_COMPLEX(type)) {
22692         if (WXS_HAS_SIMPLE_CONTENT(type)) {
22693             /*
22694             * Sanity check for complex types with simple content.
22695             */
22696             simpleType = type->contentTypeDef;
22697             if (simpleType == NULL) {
22698             VERROR_INT("xmlSchemaXPathProcessHistory",
22699                 "field resolves to a CT with simple content "
22700                 "but the CT is missing the ST definition");
22701             return (-1);
22702             }
22703         } else
22704             simpleType = NULL;
22705         } else
22706         simpleType = type;
22707         if (simpleType == NULL) {
22708         xmlChar *str = NULL;
22709 
22710         /*
22711         * Not qualified if the field resolves to a node of non
22712         * simple type.
22713         */
22714         xmlSchemaCustomErr(ACTXT_CAST vctxt,
22715             XML_SCHEMAV_CVC_IDC, NULL,
22716             WXS_BASIC_CAST sto->matcher->aidc->def,
22717             "The XPath '%s' of a field of %s does evaluate to a node of "
22718             "non-simple type",
22719             sto->sel->xpath,
22720             xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22721         FREE_AND_NULL(str);
22722         sto->nbHistory--;
22723         goto deregister_check;
22724         }
22725 
22726         if ((key == NULL) && (vctxt->inode->val == NULL)) {
22727         /*
22728         * Failed to provide the normalized value; maybe
22729         * the value was invalid.
22730         */
22731         VERROR(XML_SCHEMAV_CVC_IDC,
22732             WXS_BASIC_CAST sto->matcher->aidc->def,
22733             "Warning: No precomputed value available, the value "
22734             "was either invalid or something strange happend");
22735         sto->nbHistory--;
22736         goto deregister_check;
22737         } else {
22738         xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22739         xmlSchemaPSVIIDCKeyPtr *keySeq;
22740         int pos, idx;
22741 
22742         /*
22743         * The key will be anchored on the matcher's list of
22744         * key-sequences. The position in this list is determined
22745         * by the target node's depth relative to the matcher's
22746         * depth of creation (i.e. the depth of the scope element).
22747         *
22748         * Element        Depth    Pos   List-entries
22749         * <scope>          0              NULL
22750         *   <bar>          1              NULL
22751         *     <target/>    2       2      target
22752         *   <bar>
22753                 * </scope>
22754         *
22755         * The size of the list is only dependant on the depth of
22756         * the tree.
22757         * An entry will be NULLed in selector_leave, i.e. when
22758         * we hit the target's
22759         */
22760         pos = sto->depth - matcher->depth;
22761         idx = sto->sel->index;
22762 
22763         /*
22764         * Create/grow the array of key-sequences.
22765         */
22766         if (matcher->keySeqs == NULL) {
22767             if (pos > 9)
22768             matcher->sizeKeySeqs = pos * 2;
22769             else
22770             matcher->sizeKeySeqs = 10;
22771             matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22772             xmlMalloc(matcher->sizeKeySeqs *
22773             sizeof(xmlSchemaPSVIIDCKeyPtr *));
22774             if (matcher->keySeqs == NULL) {
22775             xmlSchemaVErrMemory(NULL,
22776                 "allocating an array of key-sequences",
22777                 NULL);
22778             return(-1);
22779             }
22780             memset(matcher->keySeqs, 0,
22781             matcher->sizeKeySeqs *
22782             sizeof(xmlSchemaPSVIIDCKeyPtr *));
22783         } else if (pos >= matcher->sizeKeySeqs) {
22784             int i = matcher->sizeKeySeqs;
22785 
22786             matcher->sizeKeySeqs *= 2;
22787             matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22788             xmlRealloc(matcher->keySeqs,
22789             matcher->sizeKeySeqs *
22790             sizeof(xmlSchemaPSVIIDCKeyPtr *));
22791             if (matcher->keySeqs == NULL) {
22792             xmlSchemaVErrMemory(NULL,
22793                 "reallocating an array of key-sequences",
22794                 NULL);
22795             return (-1);
22796             }
22797             /*
22798             * The array needs to be NULLed.
22799             * TODO: Use memset?
22800             */
22801             for (; i < matcher->sizeKeySeqs; i++)
22802             matcher->keySeqs[i] = NULL;
22803         }
22804 
22805         /*
22806         * Get/create the key-sequence.
22807         */
22808         keySeq = matcher->keySeqs[pos];
22809         if (keySeq == NULL) {
22810             goto create_sequence;
22811         } else if (keySeq[idx] != NULL) {
22812             xmlChar *str = NULL;
22813             /*
22814             * cvc-identity-constraint:
22815             * 3 For each node in the �target node set� all
22816             * of the {fields}, with that node as the context
22817             * node, evaluate to either an empty node-set or
22818             * a node-set with exactly one member, which must
22819             * have a simple type.
22820             *
22821             * The key was already set; report an error.
22822             */
22823             xmlSchemaCustomErr(ACTXT_CAST vctxt,
22824             XML_SCHEMAV_CVC_IDC, NULL,
22825             WXS_BASIC_CAST matcher->aidc->def,
22826             "The XPath '%s' of a field of %s evaluates to a "
22827             "node-set with more than one member",
22828             sto->sel->xpath,
22829             xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22830             FREE_AND_NULL(str);
22831             sto->nbHistory--;
22832             goto deregister_check;
22833         } else
22834             goto create_key;
22835 
22836 create_sequence:
22837         /*
22838         * Create a key-sequence.
22839         */
22840         keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22841             matcher->aidc->def->nbFields *
22842             sizeof(xmlSchemaPSVIIDCKeyPtr));
22843         if (keySeq == NULL) {
22844             xmlSchemaVErrMemory(NULL,
22845             "allocating an IDC key-sequence", NULL);
22846             return(-1);
22847         }
22848         memset(keySeq, 0, matcher->aidc->def->nbFields *
22849             sizeof(xmlSchemaPSVIIDCKeyPtr));
22850         matcher->keySeqs[pos] = keySeq;
22851 create_key:
22852         /*
22853         * Create a key once per node only.
22854         */
22855         if (key == NULL) {
22856             key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22857             sizeof(xmlSchemaPSVIIDCKey));
22858             if (key == NULL) {
22859             xmlSchemaVErrMemory(NULL,
22860                 "allocating a IDC key", NULL);
22861             xmlFree(keySeq);
22862             matcher->keySeqs[pos] = NULL;
22863             return(-1);
22864             }
22865             /*
22866             * Consume the compiled value.
22867             */
22868             key->type = simpleType;
22869             key->val = vctxt->inode->val;
22870             vctxt->inode->val = NULL;
22871             /*
22872             * Store the key in a global list.
22873             */
22874             if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22875             xmlSchemaIDCFreeKey(key);
22876             return (-1);
22877             }
22878         }
22879         keySeq[idx] = key;
22880         }
22881     } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22882 
22883         xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
22884         /* xmlSchemaPSVIIDCBindingPtr bind; */
22885         xmlSchemaPSVIIDCNodePtr ntItem;
22886         xmlSchemaIDCMatcherPtr matcher;
22887         xmlSchemaIDCPtr idc;
22888         xmlSchemaItemListPtr targets;
22889         int pos, i, j, nbKeys;
22890         /*
22891         * Here we have the following scenario:
22892         * An IDC 'selector' state object resolved to a target node,
22893         * during the time this target node was in the
22894         * ancestor-or-self axis, the 'field' state object(s) looked
22895         * out for matching nodes to create a key-sequence for this
22896         * target node. Now we are back to this target node and need
22897         * to put the key-sequence, together with the target node
22898         * itself, into the node-table of the corresponding IDC
22899         * binding.
22900         */
22901         matcher = sto->matcher;
22902         idc = matcher->aidc->def;
22903         nbKeys = idc->nbFields;
22904         pos = depth - matcher->depth;
22905         /*
22906         * Check if the matcher has any key-sequences at all, plus
22907         * if it has a key-sequence for the current target node.
22908         */
22909         if ((matcher->keySeqs == NULL) ||
22910         (matcher->sizeKeySeqs <= pos)) {
22911         if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22912             goto selector_key_error;
22913         else
22914             goto selector_leave;
22915         }
22916 
22917         keySeq = &(matcher->keySeqs[pos]);
22918         if (*keySeq == NULL) {
22919         if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22920             goto selector_key_error;
22921         else
22922             goto selector_leave;
22923         }
22924 
22925         for (i = 0; i < nbKeys; i++) {
22926         if ((*keySeq)[i] == NULL) {
22927             /*
22928             * Not qualified, if not all fields did resolve.
22929             */
22930             if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22931             /*
22932             * All fields of a "key" IDC must resolve.
22933             */
22934             goto selector_key_error;
22935             }
22936             goto selector_leave;
22937         }
22938         }
22939         /*
22940         * All fields did resolve.
22941         */
22942 
22943         /*
22944         * 4.1 If the {identity-constraint category} is unique(/key),
22945         * then no two members of the �qualified node set� have
22946         * �key-sequences� whose members are pairwise equal, as
22947         * defined by Equal in [XML Schemas: Datatypes].
22948         *
22949         * Get the IDC binding from the matcher and check for
22950         * duplicate key-sequences.
22951         */
22952 #if 0
22953         bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22954 #endif
22955         targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
22956         if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
22957         (targets->nbItems != 0)) {
22958         xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
22959 
22960         i = 0;
22961         res = 0;
22962         /*
22963         * Compare the key-sequences, key by key.
22964         */
22965         do {
22966             bkeySeq =
22967             ((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys;
22968             for (j = 0; j < nbKeys; j++) {
22969             ckey = (*keySeq)[j];
22970             bkey = bkeySeq[j];
22971             res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
22972             if (res == -1) {
22973                 return (-1);
22974             } else if (res == 0) {
22975                 /*
22976                 * One of the keys differs, so the key-sequence
22977                 * won't be equal; get out.
22978                 */
22979                 break;
22980             }
22981             }
22982             if (res == 1) {
22983             /*
22984             * Duplicate key-sequence found.
22985             */
22986             break;
22987             }
22988             i++;
22989         } while (i < targets->nbItems);
22990         if (i != targets->nbItems) {
22991             xmlChar *str = NULL, *strB = NULL;
22992             /*
22993             * TODO: Try to report the key-sequence.
22994             */
22995             xmlSchemaCustomErr(ACTXT_CAST vctxt,
22996             XML_SCHEMAV_CVC_IDC, NULL,
22997             WXS_BASIC_CAST idc,
22998             "Duplicate key-sequence %s in %s",
22999             xmlSchemaFormatIDCKeySequence(vctxt, &str,
23000                 (*keySeq), nbKeys),
23001             xmlSchemaGetIDCDesignation(&strB, idc));
23002             FREE_AND_NULL(str);
23003             FREE_AND_NULL(strB);
23004             goto selector_leave;
23005         }
23006         }
23007         /*
23008         * Add a node-table item to the IDC binding.
23009         */
23010         ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
23011         sizeof(xmlSchemaPSVIIDCNode));
23012         if (ntItem == NULL) {
23013         xmlSchemaVErrMemory(NULL,
23014             "allocating an IDC node-table item", NULL);
23015         xmlFree(*keySeq);
23016         *keySeq = NULL;
23017         return(-1);
23018         }
23019         memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
23020 
23021         /*
23022         * Store the node-table item in a global list.
23023         */
23024         if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23025         if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
23026             xmlFree(ntItem);
23027             xmlFree(*keySeq);
23028             *keySeq = NULL;
23029             return (-1);
23030         }
23031         ntItem->nodeQNameID = -1;
23032         } else {
23033         /*
23034         * Save a cached QName for this node on the IDC node, to be
23035         * able to report it, even if the node is not saved.
23036         */
23037         ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
23038             vctxt->inode->localName, vctxt->inode->nsName);
23039         if (ntItem->nodeQNameID == -1) {
23040             xmlFree(ntItem);
23041             xmlFree(*keySeq);
23042             *keySeq = NULL;
23043             return (-1);
23044         }
23045         }
23046         /*
23047         * Init the node-table item: Save the node, position and
23048         * consume the key-sequence.
23049         */
23050         ntItem->node = vctxt->node;
23051         ntItem->nodeLine = vctxt->inode->nodeLine;
23052         ntItem->keys = *keySeq;
23053         *keySeq = NULL;
23054 #if 0
23055         if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1)
23056 #endif
23057         if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
23058         if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23059             /*
23060             * Free the item, since keyref items won't be
23061             * put on a global list.
23062             */
23063             xmlFree(ntItem->keys);
23064             xmlFree(ntItem);
23065         }
23066         return (-1);
23067         }
23068 
23069         goto selector_leave;
23070 selector_key_error:
23071         {
23072         xmlChar *str = NULL;
23073         /*
23074         * 4.2.1 (KEY) The �target node set� and the
23075         * �qualified node set� are equal, that is, every
23076         * member of the �target node set� is also a member
23077         * of the �qualified node set� and vice versa.
23078         */
23079         xmlSchemaCustomErr(ACTXT_CAST vctxt,
23080             XML_SCHEMAV_CVC_IDC, NULL,
23081             WXS_BASIC_CAST idc,
23082             "Not all fields of %s evaluate to a node",
23083             xmlSchemaGetIDCDesignation(&str, idc), NULL);
23084         FREE_AND_NULL(str);
23085         }
23086 selector_leave:
23087         /*
23088         * Free the key-sequence if not added to the IDC table.
23089         */
23090         if ((keySeq != NULL) && (*keySeq != NULL)) {
23091         xmlFree(*keySeq);
23092         *keySeq = NULL;
23093         }
23094     } /* if selector */
23095 
23096     sto->nbHistory--;
23097 
23098 deregister_check:
23099     /*
23100     * Deregister state objects if they reach the depth of creation.
23101     */
23102     if ((sto->nbHistory == 0) && (sto->depth == depth)) {
23103 #ifdef DEBUG_IDC
23104         xmlGenericError(xmlGenericErrorContext, "IDC:   STO pop '%s'\n",
23105         sto->sel->xpath);
23106 #endif
23107         if (vctxt->xpathStates != sto) {
23108         VERROR_INT("xmlSchemaXPathProcessHistory",
23109             "The state object to be removed is not the first "
23110             "in the list");
23111         }
23112         nextsto = sto->next;
23113         /*
23114         * Unlink from the list of active XPath state objects.
23115         */
23116         vctxt->xpathStates = sto->next;
23117         sto->next = vctxt->xpathStatePool;
23118         /*
23119         * Link it to the pool of reusable state objects.
23120         */
23121         vctxt->xpathStatePool = sto;
23122         sto = nextsto;
23123     } else
23124         sto = sto->next;
23125     } /* while (sto != NULL) */
23126     return (0);
23127 }
23128 
23139 static int
23140 xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
23141                  xmlSchemaElementPtr elemDecl)
23142 {
23143     xmlSchemaIDCMatcherPtr matcher, last = NULL;
23144     xmlSchemaIDCPtr idc, refIdc;
23145     xmlSchemaIDCAugPtr aidc;
23146 
23147     idc = (xmlSchemaIDCPtr) elemDecl->idcs;
23148     if (idc == NULL)
23149     return (0);
23150 
23151 #ifdef DEBUG_IDC
23152     {
23153     xmlChar *str = NULL;
23154     xmlGenericError(xmlGenericErrorContext,
23155         "IDC: REGISTER on %s, depth %d\n",
23156         (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
23157         vctxt->inode->localName), vctxt->depth);
23158     FREE_AND_NULL(str)
23159     }
23160 #endif
23161     if (vctxt->inode->idcMatchers != NULL) {
23162     VERROR_INT("xmlSchemaIDCRegisterMatchers",
23163         "The chain of IDC matchers is expected to be empty");
23164     return (-1);
23165     }
23166     do {
23167     if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23168         /*
23169         * Since IDCs bubbles are expensive we need to know the
23170         * depth at which the bubbles should stop; this will be
23171         * the depth of the top-most keyref IDC. If no keyref
23172         * references a key/unique IDC, the keyrefDepth will
23173         * be -1, indicating that no bubbles are needed.
23174         */
23175         refIdc = (xmlSchemaIDCPtr) idc->ref->item;
23176         if (refIdc != NULL) {
23177         /*
23178         * Remember that we have keyrefs on this node.
23179         */
23180         vctxt->inode->hasKeyrefs = 1;
23181         /*
23182         * Lookup the referenced augmented IDC info.
23183         */
23184         aidc = vctxt->aidcs;
23185         while (aidc != NULL) {
23186             if (aidc->def == refIdc)
23187             break;
23188             aidc = aidc->next;
23189         }
23190         if (aidc == NULL) {
23191             VERROR_INT("xmlSchemaIDCRegisterMatchers",
23192             "Could not find an augmented IDC item for an IDC "
23193             "definition");
23194             return (-1);
23195         }
23196         if ((aidc->keyrefDepth == -1) ||
23197             (vctxt->depth < aidc->keyrefDepth))
23198             aidc->keyrefDepth = vctxt->depth;
23199         }
23200     }
23201     /*
23202     * Lookup the augmented IDC item for the IDC definition.
23203     */
23204     aidc = vctxt->aidcs;
23205     while (aidc != NULL) {
23206         if (aidc->def == idc)
23207         break;
23208         aidc = aidc->next;
23209     }
23210     if (aidc == NULL) {
23211         VERROR_INT("xmlSchemaIDCRegisterMatchers",
23212         "Could not find an augmented IDC item for an IDC definition");
23213         return (-1);
23214     }
23215     /*
23216     * Create an IDC matcher for every IDC definition.
23217     */
23218     if (vctxt->idcMatcherCache != NULL) {
23219         /*
23220         * Reuse a cached matcher.
23221         */
23222         matcher = vctxt->idcMatcherCache;
23223         vctxt->idcMatcherCache = matcher->nextCached;
23224         matcher->nextCached = NULL;
23225     } else {
23226         matcher = (xmlSchemaIDCMatcherPtr)
23227         xmlMalloc(sizeof(xmlSchemaIDCMatcher));
23228         if (matcher == NULL) {
23229         xmlSchemaVErrMemory(vctxt,
23230             "allocating an IDC matcher", NULL);
23231         return (-1);
23232         }
23233         memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
23234     }
23235     if (last == NULL)
23236         vctxt->inode->idcMatchers = matcher;
23237     else
23238         last->next = matcher;
23239     last = matcher;
23240 
23241     matcher->type = IDC_MATCHER;
23242     matcher->depth = vctxt->depth;
23243     matcher->aidc = aidc;
23244     matcher->idcType = aidc->def->type;
23245 #ifdef DEBUG_IDC
23246     xmlGenericError(xmlGenericErrorContext, "IDC:   register matcher\n");
23247 #endif
23248     /*
23249     * Init the automaton state object.
23250     */
23251     if (xmlSchemaIDCAddStateObject(vctxt, matcher,
23252         idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
23253         return (-1);
23254 
23255     idc = idc->next;
23256     } while (idc != NULL);
23257     return (0);
23258 }
23259 
23260 static int
23261 xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
23262                xmlSchemaNodeInfoPtr ielem)
23263 {
23264     xmlSchemaPSVIIDCBindingPtr bind;
23265     int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
23266     xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
23267     xmlSchemaPSVIIDCNodePtr *targets, *dupls;
23268 
23269     xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
23270     /* vctxt->createIDCNodeTables */
23271     while (matcher != NULL) {
23272     /*
23273     * Skip keyref IDCs and empty IDC target-lists.
23274     */
23275     if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
23276         WXS_ILIST_IS_EMPTY(matcher->targets))
23277     {
23278         matcher = matcher->next;
23279         continue;
23280     }
23281     /*
23282     * If we _want_ the IDC node-table to be created in any case
23283     * then do so. Otherwise create them only if keyrefs need them.
23284     */
23285     if ((! vctxt->createIDCNodeTables) &&
23286         ((matcher->aidc->keyrefDepth == -1) ||
23287          (matcher->aidc->keyrefDepth > vctxt->depth)))
23288     {
23289         matcher = matcher->next;
23290         continue;
23291     }
23292     /*
23293     * Get/create the IDC binding on this element for the IDC definition.
23294     */
23295     bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23296 
23297     if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
23298         dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23299         nbDupls = bind->dupls->nbItems;
23300     } else {
23301         dupls = NULL;
23302         nbDupls = 0;
23303     }
23304     if (bind->nodeTable != NULL) {
23305         nbNodeTable = bind->nbNodes;
23306     } else {
23307         nbNodeTable = 0;
23308     }
23309 
23310     if ((nbNodeTable == 0) && (nbDupls == 0)) {
23311         /*
23312         * Transfer all IDC target-nodes to the IDC node-table.
23313         */
23314         bind->nodeTable =
23315         (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23316         bind->sizeNodes = matcher->targets->sizeItems;
23317         bind->nbNodes = matcher->targets->nbItems;
23318 
23319         matcher->targets->items = NULL;
23320         matcher->targets->sizeItems = 0;
23321         matcher->targets->nbItems = 0;
23322     } else {
23323         /*
23324         * Compare the key-sequences and add to the IDC node-table.
23325         */
23326         nbTargets = matcher->targets->nbItems;
23327         targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23328         nbFields = matcher->aidc->def->nbFields;
23329         i = 0;
23330         do {
23331         keys = targets[i]->keys;
23332         if (nbDupls) {
23333             /*
23334             * Search in already found duplicates first.
23335             */
23336             j = 0;
23337             do {
23338             if (nbFields == 1) {
23339                 res = xmlSchemaAreValuesEqual(keys[0]->val,
23340                 dupls[j]->keys[0]->val);
23341                 if (res == -1)
23342                 goto internal_error;
23343                 if (res == 1) {
23344                 /*
23345                 * Equal key-sequence.
23346                 */
23347                 goto next_target;
23348                 }
23349             } else {
23350                 res = 0;
23351                 ntkeys = dupls[j]->keys;
23352                 for (k = 0; k < nbFields; k++) {
23353                 res = xmlSchemaAreValuesEqual(keys[k]->val,
23354                     ntkeys[k]->val);
23355                 if (res == -1)
23356                     goto internal_error;
23357                 if (res == 0) {
23358                     /*
23359                     * One of the keys differs.
23360                     */
23361                     break;
23362                 }
23363                 }
23364                 if (res == 1) {
23365                 /*
23366                 * Equal key-sequence found.
23367                 */
23368                 goto next_target;
23369                 }
23370             }
23371             j++;
23372             } while (j < nbDupls);
23373         }
23374         if (nbNodeTable) {
23375             j = 0;
23376             do {
23377             if (nbFields == 1) {
23378                 res = xmlSchemaAreValuesEqual(keys[0]->val,
23379                 bind->nodeTable[j]->keys[0]->val);
23380                 if (res == -1)
23381                 goto internal_error;
23382                 if (res == 0) {
23383                 /*
23384                 * The key-sequence differs.
23385                 */
23386                 goto next_node_table_entry;
23387                 }
23388             } else {
23389                 res = 0;
23390                 ntkeys = bind->nodeTable[j]->keys;
23391                 for (k = 0; k < nbFields; k++) {
23392                 res = xmlSchemaAreValuesEqual(keys[k]->val,
23393                     ntkeys[k]->val);
23394                 if (res == -1)
23395                     goto internal_error;
23396                 if (res == 0) {
23397                     /*
23398                     * One of the keys differs.
23399                     */
23400                     goto next_node_table_entry;
23401                 }
23402                 }
23403             }
23404             /*
23405             * Add the duplicate to the list of duplicates.
23406             */
23407             if (bind->dupls == NULL) {
23408                 bind->dupls = xmlSchemaItemListCreate();
23409                 if (bind->dupls == NULL)
23410                 goto internal_error;
23411             }
23412             if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23413                 goto internal_error;
23414             /*
23415             * Remove the duplicate entry from the IDC node-table.
23416             */
23417             bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23418             bind->nbNodes--;
23419 
23420             goto next_target;
23421 
23422 next_node_table_entry:
23423             j++;
23424             } while (j < nbNodeTable);
23425         }
23426         /*
23427         * If everything is fine, then add the IDC target-node to
23428         * the IDC node-table.
23429         */
23430         if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23431             goto internal_error;
23432 
23433 next_target:
23434         i++;
23435         } while (i < nbTargets);
23436     }
23437     matcher = matcher->next;
23438     }
23439     return(0);
23440 
23441 internal_error:
23442     return(-1);
23443 }
23444 
23456 static int
23457 xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23458 {
23459     xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
23460     xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23461     xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
23462     xmlSchemaIDCAugPtr aidc;
23463     int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
23464 
23465     bind = vctxt->inode->idcTable;
23466     if (bind == NULL) {
23467     /* Fine, no table, no bubbles. */
23468     return (0);
23469     }
23470 
23471     parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23472     /*
23473     * Walk all bindings; create new or add to existing bindings.
23474     * Remove duplicate key-sequences.
23475     */
23476     while (bind != NULL) {
23477 
23478     if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23479         goto next_binding;
23480     /*
23481     * Check if the key/unique IDC table needs to be bubbled.
23482     */
23483     if (! vctxt->createIDCNodeTables) {
23484         aidc = vctxt->aidcs;
23485         do {
23486         if (aidc->def == bind->definition) {
23487             if ((aidc->keyrefDepth == -1) ||
23488             (aidc->keyrefDepth >= vctxt->depth)) {
23489             goto next_binding;
23490             }
23491             break;
23492         }
23493         aidc = aidc->next;
23494         } while (aidc != NULL);
23495     }
23496 
23497     if (parTable != NULL)
23498         parBind = *parTable;
23499     /*
23500     * Search a matching parent binding for the
23501     * IDC definition.
23502     */
23503     while (parBind != NULL) {
23504         if (parBind->definition == bind->definition)
23505         break;
23506         parBind = parBind->next;
23507     }
23508 
23509     if (parBind != NULL) {
23510         /*
23511         * Compare every node-table entry of the child node,
23512         * i.e. the key-sequence within, ...
23513         */
23514         oldNum = parBind->nbNodes; /* Skip newly added items. */
23515 
23516         if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23517         oldDupls = parBind->dupls->nbItems;
23518         dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23519         } else {
23520         dupls = NULL;
23521         oldDupls = 0;
23522         }
23523 
23524         parNodes = parBind->nodeTable;
23525         nbFields = bind->definition->nbFields;
23526 
23527         for (i = 0; i < bind->nbNodes; i++) {
23528         node = bind->nodeTable[i];
23529         if (node == NULL)
23530             continue;
23531         /*
23532         * ...with every key-sequence of the parent node, already
23533         * evaluated to be a duplicate key-sequence.
23534         */
23535         if (oldDupls) {
23536             j = 0;
23537             while (j < oldDupls) {
23538             if (nbFields == 1) {
23539                 ret = xmlSchemaAreValuesEqual(
23540                 node->keys[0]->val,
23541                 dupls[j]->keys[0]->val);
23542                 if (ret == -1)
23543                 goto internal_error;
23544                 if (ret == 0) {
23545                 j++;
23546                 continue;
23547                 }
23548             } else {
23549                 parNode = dupls[j];
23550                 for (k = 0; k < nbFields; k++) {
23551                 ret = xmlSchemaAreValuesEqual(
23552                     node->keys[k]->val,
23553                     parNode->keys[k]->val);
23554                 if (ret == -1)
23555                     goto internal_error;
23556                 if (ret == 0)
23557                     break;
23558                 }
23559             }
23560             if (ret == 1)
23561                 /* Duplicate found. */
23562                 break;
23563             j++;
23564             }
23565             if (j != oldDupls) {
23566             /* Duplicate found. Skip this entry. */
23567             continue;
23568             }
23569         }
23570         /*
23571         * ... and with every key-sequence of the parent node.
23572         */
23573         if (oldNum) {
23574             j = 0;
23575             while (j < oldNum) {
23576             parNode = parNodes[j];
23577             if (nbFields == 1) {
23578                 ret = xmlSchemaAreValuesEqual(
23579                 node->keys[0]->val,
23580                 parNode->keys[0]->val);
23581                 if (ret == -1)
23582                 goto internal_error;
23583                 if (ret == 0) {
23584                 j++;
23585                 continue;
23586                 }
23587             } else {
23588                 for (k = 0; k < nbFields; k++) {
23589                 ret = xmlSchemaAreValuesEqual(
23590                     node->keys[k]->val,
23591                     parNode->keys[k]->val);
23592                 if (ret == -1)
23593                     goto internal_error;
23594                 if (ret == 0)
23595                     break;
23596                 }
23597             }
23598             if (ret == 1)
23599                 /* Duplicate found. */
23600                 break;
23601             j++;
23602             }
23603             if (j != oldNum) {
23604             /*
23605             * Handle duplicates. Move the duplicate in
23606             * the parent's node-table to the list of
23607             * duplicates.
23608             */
23609             oldNum--;
23610             parBind->nbNodes--;
23611             /*
23612             * Move last old item to pos of duplicate.
23613             */
23614             parNodes[j] = parNodes[oldNum];
23615 
23616             if (parBind->nbNodes != oldNum) {
23617                 /*
23618                 * If new items exist, move last new item to
23619                 * last of old items.
23620                 */
23621                 parNodes[oldNum] =
23622                 parNodes[parBind->nbNodes];
23623             }
23624             if (parBind->dupls == NULL) {
23625                 parBind->dupls = xmlSchemaItemListCreate();
23626                 if (parBind->dupls == NULL)
23627                 goto internal_error;
23628             }
23629             xmlSchemaItemListAdd(parBind->dupls, parNode);
23630             } else {
23631             /*
23632             * Add the node-table entry (node and key-sequence) of
23633             * the child node to the node table of the parent node.
23634             */
23635             if (parBind->nodeTable == NULL) {
23636                 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23637                 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
23638                 if (parBind->nodeTable == NULL) {
23639                 xmlSchemaVErrMemory(NULL,
23640                     "allocating IDC list of node-table items", NULL);
23641                 goto internal_error;
23642                 }
23643                 parBind->sizeNodes = 1;
23644             } else if (parBind->nbNodes >= parBind->sizeNodes) {
23645                 parBind->sizeNodes *= 2;
23646                 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23647                 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23648                 sizeof(xmlSchemaPSVIIDCNodePtr));
23649                 if (parBind->nodeTable == NULL) {
23650                 xmlSchemaVErrMemory(NULL,
23651                     "re-allocating IDC list of node-table items", NULL);
23652                 goto internal_error;
23653                 }
23654             }
23655             parNodes = parBind->nodeTable;
23656             /*
23657             * Append the new node-table entry to the 'new node-table
23658             * entries' section.
23659             */
23660             parNodes[parBind->nbNodes++] = node;
23661             }
23662 
23663         }
23664 
23665         }
23666     } else {
23667         /*
23668         * No binding for the IDC was found: create a new one and
23669         * copy all node-tables.
23670         */
23671         parBind = xmlSchemaIDCNewBinding(bind->definition);
23672         if (parBind == NULL)
23673         goto internal_error;
23674 
23675         /*
23676         * TODO: Hmm, how to optimize the initial number of
23677         * allocated entries?
23678         */
23679         if (bind->nbNodes != 0) {
23680         /*
23681         * Add all IDC node-table entries.
23682         */
23683         if (! vctxt->psviExposeIDCNodeTables) {
23684             /*
23685             * Just move the entries.
23686             * NOTE: this is quite save here, since
23687             * all the keyref lookups have already been
23688             * performed.
23689             */
23690             parBind->nodeTable = bind->nodeTable;
23691             bind->nodeTable = NULL;
23692             parBind->sizeNodes = bind->sizeNodes;
23693             bind->sizeNodes = 0;
23694             parBind->nbNodes = bind->nbNodes;
23695             bind->nbNodes = 0;
23696         } else {
23697             /*
23698             * Copy the entries.
23699             */
23700             parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23701             xmlMalloc(bind->nbNodes *
23702             sizeof(xmlSchemaPSVIIDCNodePtr));
23703             if (parBind->nodeTable == NULL) {
23704             xmlSchemaVErrMemory(NULL,
23705                 "allocating an array of IDC node-table "
23706                 "items", NULL);
23707             xmlSchemaIDCFreeBinding(parBind);
23708             goto internal_error;
23709             }
23710             parBind->sizeNodes = bind->nbNodes;
23711             parBind->nbNodes = bind->nbNodes;
23712             memcpy(parBind->nodeTable, bind->nodeTable,
23713             bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23714         }
23715         }
23716         if (bind->dupls) {
23717         /*
23718         * Move the duplicates.
23719         */
23720         if (parBind->dupls != NULL)
23721             xmlSchemaItemListFree(parBind->dupls);
23722         parBind->dupls = bind->dupls;
23723         bind->dupls = NULL;
23724         }
23725             if (parTable != NULL) {
23726                 if (*parTable == NULL)
23727                     *parTable = parBind;
23728                 else {
23729                     parBind->next = *parTable;
23730                     *parTable = parBind;
23731                 }
23732             }
23733     }
23734 
23735 next_binding:
23736     bind = bind->next;
23737     }
23738     return (0);
23739 
23740 internal_error:
23741     return(-1);
23742 }
23743 
23751 static int
23752 xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23753 {
23754     xmlSchemaIDCMatcherPtr matcher;
23755     xmlSchemaPSVIIDCBindingPtr bind;
23756 
23757     matcher = vctxt->inode->idcMatchers;
23758     /*
23759     * Find a keyref.
23760     */
23761     while (matcher != NULL) {
23762     if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23763         matcher->targets &&
23764         matcher->targets->nbItems)
23765     {
23766         int i, j, k, res, nbFields, hasDupls;
23767         xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
23768         xmlSchemaPSVIIDCNodePtr refNode = NULL;
23769 
23770         nbFields = matcher->aidc->def->nbFields;
23771 
23772         /*
23773         * Find the IDC node-table for the referenced IDC key/unique.
23774         */
23775         bind = vctxt->inode->idcTable;
23776         while (bind != NULL) {
23777         if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
23778             bind->definition)
23779             break;
23780         bind = bind->next;
23781         }
23782         hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
23783         /*
23784         * Search for a matching key-sequences.
23785         */
23786         for (i = 0; i < matcher->targets->nbItems; i++) {
23787         res = 0;
23788         refNode = matcher->targets->items[i];
23789         if (bind != NULL) {
23790             refKeys = refNode->keys;
23791             for (j = 0; j < bind->nbNodes; j++) {
23792             keys = bind->nodeTable[j]->keys;
23793             for (k = 0; k < nbFields; k++) {
23794                 res = xmlSchemaAreValuesEqual(keys[k]->val,
23795                 refKeys[k]->val);
23796                 if (res == 0)
23797                 break;
23798                 else if (res == -1) {
23799                 return (-1);
23800                 }
23801             }
23802             if (res == 1) {
23803                 /*
23804                 * Match found.
23805                 */
23806                 break;
23807             }
23808             }
23809             if ((res == 0) && hasDupls) {
23810             /*
23811             * Search in duplicates
23812             */
23813             for (j = 0; j < bind->dupls->nbItems; j++) {
23814                 keys = ((xmlSchemaPSVIIDCNodePtr)
23815                 bind->dupls->items[j])->keys;
23816                 for (k = 0; k < nbFields; k++) {
23817                 res = xmlSchemaAreValuesEqual(keys[k]->val,
23818                     refKeys[k]->val);
23819                 if (res == 0)
23820                     break;
23821                 else if (res == -1) {
23822                     return (-1);
23823                 }
23824                 }
23825                 if (res == 1) {
23826                 /*
23827                 * Match in duplicates found.
23828                 */
23829                 xmlChar *str = NULL, *strB = NULL;
23830                 xmlSchemaKeyrefErr(vctxt,
23831                     XML_SCHEMAV_CVC_IDC, refNode,
23832                     (xmlSchemaTypePtr) matcher->aidc->def,
23833                     "More than one match found for "
23834                     "key-sequence %s of keyref '%s'",
23835                     xmlSchemaFormatIDCKeySequence(vctxt, &str,
23836                     refNode->keys, nbFields),
23837                     xmlSchemaGetComponentQName(&strB,
23838                     matcher->aidc->def));
23839                 FREE_AND_NULL(str);
23840                 FREE_AND_NULL(strB);
23841                 break;
23842                 }
23843             }
23844             }
23845         }
23846 
23847         if (res == 0) {
23848             xmlChar *str = NULL, *strB = NULL;
23849             xmlSchemaKeyrefErr(vctxt,
23850             XML_SCHEMAV_CVC_IDC, refNode,
23851             (xmlSchemaTypePtr) matcher->aidc->def,
23852             "No match found for key-sequence %s of keyref '%s'",
23853             xmlSchemaFormatIDCKeySequence(vctxt, &str,
23854                 refNode->keys, nbFields),
23855             xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
23856             FREE_AND_NULL(str);
23857             FREE_AND_NULL(strB);
23858         }
23859         }
23860     }
23861     matcher = matcher->next;
23862     }
23863     /* TODO: Return an error if any error encountered. */
23864     return (0);
23865 }
23866 
23867 /************************************************************************
23868  *                                  *
23869  *          XML Reader validation code                      *
23870  *                                  *
23871  ************************************************************************/
23872 
23873 static xmlSchemaAttrInfoPtr
23874 xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
23875 {
23876     xmlSchemaAttrInfoPtr iattr;
23877     /*
23878     * Grow/create list of attribute infos.
23879     */
23880     if (vctxt->attrInfos == NULL) {
23881     vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23882         xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23883     vctxt->sizeAttrInfos = 1;
23884     if (vctxt->attrInfos == NULL) {
23885         xmlSchemaVErrMemory(vctxt,
23886         "allocating attribute info list", NULL);
23887         return (NULL);
23888     }
23889     } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23890     vctxt->sizeAttrInfos++;
23891     vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23892         xmlRealloc(vctxt->attrInfos,
23893         vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23894     if (vctxt->attrInfos == NULL) {
23895         xmlSchemaVErrMemory(vctxt,
23896         "re-allocating attribute info list", NULL);
23897         return (NULL);
23898     }
23899     } else {
23900     iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23901     if (iattr->localName != NULL) {
23902         VERROR_INT("xmlSchemaGetFreshAttrInfo",
23903         "attr info not cleared");
23904         return (NULL);
23905     }
23906     iattr->nodeType = XML_ATTRIBUTE_NODE;
23907     return (iattr);
23908     }
23909     /*
23910     * Create an attribute info.
23911     */
23912     iattr = (xmlSchemaAttrInfoPtr)
23913     xmlMalloc(sizeof(xmlSchemaAttrInfo));
23914     if (iattr == NULL) {
23915     xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
23916     return (NULL);
23917     }
23918     memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23919     iattr->nodeType = XML_ATTRIBUTE_NODE;
23920     vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23921 
23922     return (iattr);
23923 }
23924 
23925 static int
23926 xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23927             xmlNodePtr attrNode,
23928             int nodeLine,
23929             const xmlChar *localName,
23930             const xmlChar *nsName,
23931             int ownedNames,
23932             xmlChar *value,
23933             int ownedValue)
23934 {
23935     xmlSchemaAttrInfoPtr attr;
23936 
23937     attr = xmlSchemaGetFreshAttrInfo(vctxt);
23938     if (attr == NULL) {
23939     VERROR_INT("xmlSchemaPushAttribute",
23940         "calling xmlSchemaGetFreshAttrInfo()");
23941     return (-1);
23942     }
23943     attr->node = attrNode;
23944     attr->nodeLine = nodeLine;
23945     attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23946     attr->localName = localName;
23947     attr->nsName = nsName;
23948     if (ownedNames)
23949     attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23950     /*
23951     * Evaluate if it's an XSI attribute.
23952     */
23953     if (nsName != NULL) {
23954     if (xmlStrEqual(localName, BAD_CAST "nil")) {
23955         if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23956         attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
23957         }
23958     } else if (xmlStrEqual(localName, BAD_CAST "type")) {
23959         if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23960         attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
23961         }
23962     } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
23963         if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23964         attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
23965         }
23966     } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
23967         if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23968         attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
23969         }
23970     } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
23971         attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
23972     }
23973     }
23974     attr->value = value;
23975     if (ownedValue)
23976     attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23977     if (attr->metaType != 0)
23978     attr->state = XML_SCHEMAS_ATTR_META;
23979     return (0);
23980 }
23981 
23987 static void
23988 xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,
23989                xmlSchemaNodeInfoPtr ielem)
23990 {
23991     ielem->hasKeyrefs = 0;
23992     ielem->appliedXPath = 0;
23993     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
23994     FREE_AND_NULL(ielem->localName);
23995     FREE_AND_NULL(ielem->nsName);
23996     } else {
23997     ielem->localName = NULL;
23998     ielem->nsName = NULL;
23999     }
24000     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24001     FREE_AND_NULL(ielem->value);
24002     } else {
24003     ielem->value = NULL;
24004     }
24005     if (ielem->val != NULL) {
24006     /*
24007     * PSVI TODO: Be careful not to free it when the value is
24008     * exposed via PSVI.
24009     */
24010     xmlSchemaFreeValue(ielem->val);
24011     ielem->val = NULL;
24012     }
24013     if (ielem->idcMatchers != NULL) {
24014     /*
24015     * REVISIT OPTIMIZE TODO: Use a pool of IDC matchers.
24016     *   Does it work?
24017     */
24018     xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers);
24019 #if 0
24020     xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
24021 #endif
24022     ielem->idcMatchers = NULL;
24023     }
24024     if (ielem->idcTable != NULL) {
24025     /*
24026     * OPTIMIZE TODO: Use a pool of IDC tables??.
24027     */
24028     xmlSchemaIDCFreeIDCTable(ielem->idcTable);
24029     ielem->idcTable = NULL;
24030     }
24031     if (ielem->regexCtxt != NULL) {
24032     xmlRegFreeExecCtxt(ielem->regexCtxt);
24033     ielem->regexCtxt = NULL;
24034     }
24035     if (ielem->nsBindings != NULL) {
24036     xmlFree((xmlChar **)ielem->nsBindings);
24037     ielem->nsBindings = NULL;
24038     ielem->nbNsBindings = 0;
24039     ielem->sizeNsBindings = 0;
24040     }
24041 }
24042 
24052 static xmlSchemaNodeInfoPtr
24053 xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
24054 {
24055     xmlSchemaNodeInfoPtr info = NULL;
24056 
24057     if (vctxt->depth > vctxt->sizeElemInfos) {
24058     VERROR_INT("xmlSchemaGetFreshElemInfo",
24059         "inconsistent depth encountered");
24060     return (NULL);
24061     }
24062     if (vctxt->elemInfos == NULL) {
24063     vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24064         xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
24065     if (vctxt->elemInfos == NULL) {
24066         xmlSchemaVErrMemory(vctxt,
24067         "allocating the element info array", NULL);
24068         return (NULL);
24069     }
24070     memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
24071     vctxt->sizeElemInfos = 10;
24072     } else if (vctxt->sizeElemInfos <= vctxt->depth) {
24073     int i = vctxt->sizeElemInfos;
24074 
24075     vctxt->sizeElemInfos *= 2;
24076     vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24077         xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
24078         sizeof(xmlSchemaNodeInfoPtr));
24079     if (vctxt->elemInfos == NULL) {
24080         xmlSchemaVErrMemory(vctxt,
24081         "re-allocating the element info array", NULL);
24082         return (NULL);
24083     }
24084     /*
24085     * We need the new memory to be NULLed.
24086     * TODO: Use memset instead?
24087     */
24088     for (; i < vctxt->sizeElemInfos; i++)
24089         vctxt->elemInfos[i] = NULL;
24090     } else
24091     info = vctxt->elemInfos[vctxt->depth];
24092 
24093     if (info == NULL) {
24094     info = (xmlSchemaNodeInfoPtr)
24095         xmlMalloc(sizeof(xmlSchemaNodeInfo));
24096     if (info == NULL) {
24097         xmlSchemaVErrMemory(vctxt,
24098         "allocating an element info", NULL);
24099         return (NULL);
24100     }
24101     vctxt->elemInfos[vctxt->depth] = info;
24102     } else {
24103     if (info->localName != NULL) {
24104         VERROR_INT("xmlSchemaGetFreshElemInfo",
24105         "elem info has not been cleared");
24106         return (NULL);
24107     }
24108     }
24109     memset(info, 0, sizeof(xmlSchemaNodeInfo));
24110     info->nodeType = XML_ELEMENT_NODE;
24111     info->depth = vctxt->depth;
24112 
24113     return (info);
24114 }
24115 
24116 #define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
24117 #define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
24118 #define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
24119 
24120 static int
24121 xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
24122             xmlNodePtr node,
24123             xmlSchemaTypePtr type,
24124             xmlSchemaValType valType,
24125             const xmlChar * value,
24126             xmlSchemaValPtr val,
24127             unsigned long length,
24128             int fireErrors)
24129 {
24130     int ret, error = 0;
24131 
24132     xmlSchemaTypePtr tmpType;
24133     xmlSchemaFacetLinkPtr facetLink;
24134     xmlSchemaFacetPtr facet;
24135     unsigned long len = 0;
24136     xmlSchemaWhitespaceValueType ws;
24137 
24138     /*
24139     * In Libxml2, derived built-in types have currently no explicit facets.
24140     */
24141     if (type->type == XML_SCHEMA_TYPE_BASIC)
24142     return (0);
24143 
24144     /*
24145     * NOTE: Do not jump away, if the facetSet of the given type is
24146     * empty: until now, "pattern" and "enumeration" facets of the
24147     * *base types* need to be checked as well.
24148     */
24149     if (type->facetSet == NULL)
24150     goto pattern_and_enum;
24151 
24152     if (! WXS_IS_ATOMIC(type)) {
24153     if (WXS_IS_LIST(type))
24154         goto WXS_IS_LIST;
24155     else
24156         goto pattern_and_enum;
24157     }
24158     /*
24159     * Whitespace handling is only of importance for string-based
24160     * types.
24161     */
24162     tmpType = xmlSchemaGetPrimitiveType(type);
24163     if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
24164     WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
24165     ws = xmlSchemaGetWhiteSpaceFacetValue(type);
24166     } else
24167     ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
24168     /*
24169     * If the value was not computed (for string or
24170     * anySimpleType based types), then use the provided
24171     * type.
24172     */
24173     if (val == NULL)
24174     valType = valType;
24175     else
24176     valType = xmlSchemaGetValType(val);
24177 
24178     ret = 0;
24179     for (facetLink = type->facetSet; facetLink != NULL;
24180     facetLink = facetLink->next) {
24181     /*
24182     * Skip the pattern "whiteSpace": it is used to
24183     * format the character content beforehand.
24184     */
24185     switch (facetLink->facet->type) {
24186         case XML_SCHEMA_FACET_WHITESPACE:
24187         case XML_SCHEMA_FACET_PATTERN:
24188         case XML_SCHEMA_FACET_ENUMERATION:
24189         continue;
24190         case XML_SCHEMA_FACET_LENGTH:
24191         case XML_SCHEMA_FACET_MINLENGTH:
24192         case XML_SCHEMA_FACET_MAXLENGTH:
24193         ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
24194             valType, value, val, &len, ws);
24195         break;
24196         default:
24197         ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
24198             valType, value, val, ws);
24199         break;
24200     }
24201     if (ret < 0) {
24202         AERROR_INT("xmlSchemaValidateFacets",
24203         "validating against a atomic type facet");
24204         return (-1);
24205     } else if (ret > 0) {
24206         if (fireErrors)
24207         xmlSchemaFacetErr(actxt, ret, node,
24208         value, len, type, facetLink->facet, NULL, NULL, NULL);
24209         else
24210         return (ret);
24211         if (error == 0)
24212         error = ret;
24213     }
24214     ret = 0;
24215     }
24216 
24217 WXS_IS_LIST:
24218     if (! WXS_IS_LIST(type))
24219     goto pattern_and_enum;
24220     /*
24221     * "length", "minLength" and "maxLength" of list types.
24222     */
24223     ret = 0;
24224     for (facetLink = type->facetSet; facetLink != NULL;
24225     facetLink = facetLink->next) {
24226 
24227     switch (facetLink->facet->type) {
24228         case XML_SCHEMA_FACET_LENGTH:
24229         case XML_SCHEMA_FACET_MINLENGTH:
24230         case XML_SCHEMA_FACET_MAXLENGTH:
24231         ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
24232             value, length, NULL);
24233         break;
24234         default:
24235         continue;
24236     }
24237     if (ret < 0) {
24238         AERROR_INT("xmlSchemaValidateFacets",
24239         "validating against a list type facet");
24240         return (-1);
24241     } else if (ret > 0) {
24242         if (fireErrors)
24243         xmlSchemaFacetErr(actxt, ret, node,
24244         value, length, type, facetLink->facet, NULL, NULL, NULL);
24245         else
24246         return (ret);
24247         if (error == 0)
24248         error = ret;
24249     }
24250     ret = 0;
24251     }
24252 
24253 pattern_and_enum:
24254     if (error >= 0) {
24255     int found = 0;
24256     /*
24257     * Process enumerations. Facet values are in the value space
24258     * of the defining type's base type. This seems to be a bug in the
24259     * XML Schema 1.0 spec. Use the whitespace type of the base type.
24260     * Only the first set of enumerations in the ancestor-or-self axis
24261     * is used for validation.
24262     */
24263     ret = 0;
24264     tmpType = type;
24265     do {
24266         for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
24267         if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
24268             continue;
24269         found = 1;
24270         ret = xmlSchemaAreValuesEqual(facet->val, val);
24271         if (ret == 1)
24272             break;
24273         else if (ret < 0) {
24274             AERROR_INT("xmlSchemaValidateFacets",
24275             "validating against an enumeration facet");
24276             return (-1);
24277         }
24278         }
24279         if (ret != 0)
24280         break;
24281         /*
24282         * Break on the first set of enumerations. Any additional
24283         *  enumerations which might be existent on the ancestors
24284         *  of the current type are restricted by this set; thus
24285         *  *must* *not* be taken into account.
24286         */
24287         if (found)
24288         break;
24289         tmpType = tmpType->baseType;
24290     } while ((tmpType != NULL) &&
24291         (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24292     if (found && (ret == 0)) {
24293         ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
24294         if (fireErrors) {
24295         xmlSchemaFacetErr(actxt, ret, node,
24296             value, 0, type, NULL, NULL, NULL, NULL);
24297         } else
24298         return (ret);
24299         if (error == 0)
24300         error = ret;
24301     }
24302     }
24303 
24304     if (error >= 0) {
24305     int found;
24306     /*
24307     * Process patters. Pattern facets are ORed at type level
24308     * and ANDed if derived. Walk the base type axis.
24309     */
24310     tmpType = type;
24311     facet = NULL;
24312     do {
24313         found = 0;
24314         for (facetLink = tmpType->facetSet; facetLink != NULL;
24315         facetLink = facetLink->next) {
24316         if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
24317             continue;
24318         found = 1;
24319         /*
24320         * NOTE that for patterns, @value needs to be the
24321         * normalized vaule.
24322         */
24323         ret = xmlRegexpExec(facetLink->facet->regexp, value);
24324         if (ret == 1)
24325             break;
24326         else if (ret < 0) {
24327             AERROR_INT("xmlSchemaValidateFacets",
24328             "validating against a pattern facet");
24329             return (-1);
24330         } else {
24331             /*
24332             * Save the last non-validating facet.
24333             */
24334             facet = facetLink->facet;
24335         }
24336         }
24337         if (found && (ret != 1)) {
24338         ret = XML_SCHEMAV_CVC_PATTERN_VALID;
24339         if (fireErrors) {
24340             xmlSchemaFacetErr(actxt, ret, node,
24341             value, 0, type, facet, NULL, NULL, NULL);
24342         } else
24343             return (ret);
24344         if (error == 0)
24345             error = ret;
24346         break;
24347         }
24348         tmpType = tmpType->baseType;
24349     } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24350     }
24351 
24352     return (error);
24353 }
24354 
24355 static xmlChar *
24356 xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24357             const xmlChar *value)
24358 {
24359     switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
24360     case XML_SCHEMA_WHITESPACE_COLLAPSE:
24361         return (xmlSchemaCollapseString(value));
24362     case XML_SCHEMA_WHITESPACE_REPLACE:
24363         return (xmlSchemaWhiteSpaceReplace(value));
24364     default:
24365         return (NULL);
24366     }
24367 }
24368 
24369 static int
24370 xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24371                const xmlChar *value,
24372                xmlSchemaValPtr *val,
24373                int valNeeded)
24374 {
24375     int ret;
24376     const xmlChar *nsName;
24377     xmlChar *local, *prefix = NULL;
24378 
24379     ret = xmlValidateQName(value, 1);
24380     if (ret != 0) {
24381     if (ret == -1) {
24382         VERROR_INT("xmlSchemaValidateQName",
24383         "calling xmlValidateQName()");
24384         return (-1);
24385     }
24386     return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24387     }
24388     /*
24389     * NOTE: xmlSplitQName2 will always return a duplicated
24390     * strings.
24391     */
24392     local = xmlSplitQName2(value, &prefix);
24393     if (local == NULL)
24394     local = xmlStrdup(value);
24395     /*
24396     * OPTIMIZE TODO: Use flags for:
24397     *  - is there any namespace binding?
24398     *  - is there a default namespace?
24399     */
24400     nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24401 
24402     if (prefix != NULL) {
24403     xmlFree(prefix);
24404     /*
24405     * A namespace must be found if the prefix is
24406     * NOT NULL.
24407     */
24408     if (nsName == NULL) {
24409         ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24410         xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
24411         WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24412         "The QName value '%s' has no "
24413         "corresponding namespace declaration in "
24414         "scope", value, NULL);
24415         if (local != NULL)
24416         xmlFree(local);
24417         return (ret);
24418     }
24419     }
24420     if (valNeeded && val) {
24421     if (nsName != NULL)
24422         *val = xmlSchemaNewQNameValue(
24423         BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24424     else
24425         *val = xmlSchemaNewQNameValue(NULL,
24426         BAD_CAST local);
24427     } else
24428     xmlFree(local);
24429     return (0);
24430 }
24431 
24432 /*
24433 * cvc-simple-type
24434 */
24435 static int
24436 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24437                  xmlNodePtr node,
24438                  xmlSchemaTypePtr type,
24439                  const xmlChar *value,
24440                  xmlSchemaValPtr *retVal,
24441                  int fireErrors,
24442                  int normalize,
24443                  int isNormalized)
24444 {
24445     int ret = 0, valNeeded = (retVal) ? 1 : 0;
24446     xmlSchemaValPtr val = NULL;
24447     /* xmlSchemaWhitespaceValueType ws; */
24448     xmlChar *normValue = NULL;
24449 
24450 #define NORMALIZE(atype) \
24451     if ((! isNormalized) && \
24452     (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24453     normValue = xmlSchemaNormalizeValue(atype, value); \
24454     if (normValue != NULL) \
24455         value = normValue; \
24456     isNormalized = 1; \
24457     }
24458 
24459     if ((retVal != NULL) && (*retVal != NULL)) {
24460     xmlSchemaFreeValue(*retVal);
24461     *retVal = NULL;
24462     }
24463     /*
24464     * 3.14.4 Simple Type Definition Validation Rules
24465     * Validation Rule: String Valid
24466     */
24467     /*
24468     * 1 It is schema-valid with respect to that definition as defined
24469     * by Datatype Valid in [XML Schemas: Datatypes].
24470     */
24471     /*
24472     * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24473     * the empty set, as defined in Type Derivation OK (Simple) (�3.14.6), then
24474     * the string must be a �declared entity name�.
24475     */
24476     /*
24477     * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24478     * given the empty set, as defined in Type Derivation OK (Simple) (�3.14.6),
24479     * then every whitespace-delimited substring of the string must be a �declared
24480     * entity name�.
24481     */
24482     /*
24483     * 2.3 otherwise no further condition applies.
24484     */
24485     if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24486     valNeeded = 1;
24487     if (value == NULL)
24488     value = BAD_CAST "";
24489     if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
24490     xmlSchemaTypePtr biType; /* The built-in type. */
24491     /*
24492     * SPEC (1.2.1) "if {variety} is �atomic� then the string must �match�
24493     * a literal in the �lexical space� of {base type definition}"
24494     */
24495     /*
24496     * Whitespace-normalize.
24497     */
24498     NORMALIZE(type);
24499     if (type->type != XML_SCHEMA_TYPE_BASIC) {
24500         /*
24501         * Get the built-in type.
24502         */
24503         biType = type->baseType;
24504         while ((biType != NULL) &&
24505         (biType->type != XML_SCHEMA_TYPE_BASIC))
24506         biType = biType->baseType;
24507 
24508         if (biType == NULL) {
24509         AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24510             "could not get the built-in type");
24511         goto internal_error;
24512         }
24513     } else
24514         biType = type;
24515     /*
24516     * NOTATIONs need to be processed here, since they need
24517     * to lookup in the hashtable of NOTATION declarations of the schema.
24518     */
24519     if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24520         switch (biType->builtInType) {
24521         case XML_SCHEMAS_NOTATION:
24522             ret = xmlSchemaValidateNotation(
24523             (xmlSchemaValidCtxtPtr) actxt,
24524             ((xmlSchemaValidCtxtPtr) actxt)->schema,
24525             NULL, value, &val, valNeeded);
24526             break;
24527         case XML_SCHEMAS_QNAME:
24528             ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24529             value, &val, valNeeded);
24530             break;
24531         default:
24532             /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24533             if (valNeeded)
24534             ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24535                 value, &val, node);
24536             else
24537             ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24538                 value, NULL, node);
24539             break;
24540         }
24541     } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24542         switch (biType->builtInType) {
24543         case XML_SCHEMAS_NOTATION:
24544             ret = xmlSchemaValidateNotation(NULL,
24545             ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24546             value, &val, valNeeded);
24547             break;
24548         default:
24549             /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24550             if (valNeeded)
24551             ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24552                 value, &val, node);
24553             else
24554             ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24555                 value, NULL, node);
24556             break;
24557         }
24558     } else {
24559         /*
24560         * Validation via a public API is not implemented yet.
24561         */
24562         TODO
24563         goto internal_error;
24564     }
24565     if (ret != 0) {
24566         if (ret < 0) {
24567         AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24568             "validating against a built-in type");
24569         goto internal_error;
24570         }
24571         if (WXS_IS_LIST(type))
24572         ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24573         else
24574         ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24575     }
24576     if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24577         /*
24578         * Check facets.
24579         */
24580         ret = xmlSchemaValidateFacets(actxt, node, type,
24581         (xmlSchemaValType) biType->builtInType, value, val,
24582         0, fireErrors);
24583         if (ret != 0) {
24584         if (ret < 0) {
24585             AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24586             "validating facets of atomic simple type");
24587             goto internal_error;
24588         }
24589         if (WXS_IS_LIST(type))
24590             ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24591         else
24592             ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24593         }
24594     }
24595     if (fireErrors && (ret > 0))
24596         xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24597     } else if (WXS_IS_LIST(type)) {
24598 
24599     xmlSchemaTypePtr itemType;
24600     const xmlChar *cur, *end;
24601     xmlChar *tmpValue = NULL;
24602     unsigned long len = 0;
24603     xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24604     /* 1.2.2 if {variety} is �list� then the string must be a sequence
24605     * of white space separated tokens, each of which �match�es a literal
24606     * in the �lexical space� of {item type definition}
24607     */
24608     /*
24609     * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24610     * the list type has an enum or pattern facet.
24611     */
24612     NORMALIZE(type);
24613     /*
24614     * VAL TODO: Optimize validation of empty values.
24615     * VAL TODO: We do not have computed values for lists.
24616     */
24617     itemType = WXS_LIST_ITEMTYPE(type);
24618     cur = value;
24619     do {
24620         while (IS_BLANK_CH(*cur))
24621         cur++;
24622         end = cur;
24623         while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24624         end++;
24625         if (end == cur)
24626         break;
24627         tmpValue = xmlStrndup(cur, end - cur);
24628         len++;
24629 
24630         if (valNeeded)
24631         ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24632             tmpValue, &curVal, fireErrors, 0, 1);
24633         else
24634         ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24635             tmpValue, NULL, fireErrors, 0, 1);
24636         FREE_AND_NULL(tmpValue);
24637         if (curVal != NULL) {
24638         /*
24639         * Add to list of computed values.
24640         */
24641         if (val == NULL)
24642             val = curVal;
24643         else
24644             xmlSchemaValueAppend(prevVal, curVal);
24645         prevVal = curVal;
24646         curVal = NULL;
24647         }
24648         if (ret != 0) {
24649         if (ret < 0) {
24650             AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24651             "validating an item of list simple type");
24652             goto internal_error;
24653         }
24654         ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24655         break;
24656         }
24657         cur = end;
24658     } while (*cur != 0);
24659     FREE_AND_NULL(tmpValue);
24660     if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24661         /*
24662         * Apply facets (pattern, enumeration).
24663         */
24664         ret = xmlSchemaValidateFacets(actxt, node, type,
24665         XML_SCHEMAS_UNKNOWN, value, val,
24666         len, fireErrors);
24667         if (ret != 0) {
24668         if (ret < 0) {
24669             AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24670             "validating facets of list simple type");
24671             goto internal_error;
24672         }
24673         ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24674         }
24675     }
24676     if (fireErrors && (ret > 0)) {
24677         /*
24678         * Report the normalized value.
24679         */
24680         normalize = 1;
24681         NORMALIZE(type);
24682         xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24683     }
24684     } else if (WXS_IS_UNION(type)) {
24685     xmlSchemaTypeLinkPtr memberLink;
24686     /*
24687     * TODO: For all datatypes �derived� by �union�  whiteSpace does
24688     * not apply directly; however, the normalization behavior of �union�
24689     * types is controlled by the value of whiteSpace on that one of the
24690     * �memberTypes� against which the �union� is successfully validated.
24691     *
24692     * This means that the value is normalized by the first validating
24693     * member type, then the facets of the union type are applied. This
24694     * needs changing of the value!
24695     */
24696 
24697     /*
24698     * 1.2.3 if {variety} is �union� then the string must �match� a
24699     * literal in the �lexical space� of at least one member of
24700     * {member type definitions}
24701     */
24702     memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24703     if (memberLink == NULL) {
24704         AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24705         "union simple type has no member types");
24706         goto internal_error;
24707     }
24708     /*
24709     * Always normalize union type values, since we currently
24710     * cannot store the whitespace information with the value
24711     * itself; otherwise a later value-comparison would be
24712     * not possible.
24713     */
24714     while (memberLink != NULL) {
24715         if (valNeeded)
24716         ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24717             memberLink->type, value, &val, 0, 1, 0);
24718         else
24719         ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24720             memberLink->type, value, NULL, 0, 1, 0);
24721         if (ret <= 0)
24722         break;
24723         memberLink = memberLink->next;
24724     }
24725     if (ret != 0) {
24726         if (ret < 0) {
24727         AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24728             "validating members of union simple type");
24729         goto internal_error;
24730         }
24731         ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24732     }
24733     /*
24734     * Apply facets (pattern, enumeration).
24735     */
24736     if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24737         /*
24738         * The normalization behavior of �union� types is controlled by
24739         * the value of whiteSpace on that one of the �memberTypes�
24740         * against which the �union� is successfully validated.
24741         */
24742         NORMALIZE(memberLink->type);
24743         ret = xmlSchemaValidateFacets(actxt, node, type,
24744         XML_SCHEMAS_UNKNOWN, value, val,
24745         0, fireErrors);
24746         if (ret != 0) {
24747         if (ret < 0) {
24748             AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24749             "validating facets of union simple type");
24750             goto internal_error;
24751         }
24752         ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24753         }
24754     }
24755     if (fireErrors && (ret > 0))
24756         xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24757     }
24758 
24759     if (normValue != NULL)
24760     xmlFree(normValue);
24761     if (ret == 0) {
24762     if (retVal != NULL)
24763         *retVal = val;
24764     else if (val != NULL)
24765         xmlSchemaFreeValue(val);
24766     } else if (val != NULL)
24767     xmlSchemaFreeValue(val);
24768     return (ret);
24769 internal_error:
24770     if (normValue != NULL)
24771     xmlFree(normValue);
24772     if (val != NULL)
24773     xmlSchemaFreeValue(val);
24774     return (-1);
24775 }
24776 
24777 static int
24778 xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24779                const xmlChar *value,
24780                const xmlChar **nsName,
24781                const xmlChar **localName)
24782 {
24783     int ret = 0;
24784 
24785     if ((nsName == NULL) || (localName == NULL))
24786     return (-1);
24787     *nsName = NULL;
24788     *localName = NULL;
24789 
24790     ret = xmlValidateQName(value, 1);
24791     if (ret == -1)
24792     return (-1);
24793     if (ret > 0) {
24794     xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
24795         XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24796         value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24797     return (1);
24798     }
24799     {
24800     xmlChar *local = NULL;
24801     xmlChar *prefix;
24802 
24803     /*
24804     * NOTE: xmlSplitQName2 will return a duplicated
24805     * string.
24806     */
24807     local = xmlSplitQName2(value, &prefix);
24808     if (local == NULL)
24809         *localName = xmlDictLookup(vctxt->dict, value, -1);
24810     else {
24811         *localName = xmlDictLookup(vctxt->dict, local, -1);
24812         xmlFree(local);
24813     }
24814 
24815     *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24816 
24817     if (prefix != NULL) {
24818         xmlFree(prefix);
24819         /*
24820         * A namespace must be found if the prefix is NOT NULL.
24821         */
24822         if (*nsName == NULL) {
24823         xmlSchemaCustomErr(ACTXT_CAST vctxt,
24824             XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24825             WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24826             "The QName value '%s' has no "
24827             "corresponding namespace declaration in scope",
24828             value, NULL);
24829         return (2);
24830         }
24831     }
24832     }
24833     return (0);
24834 }
24835 
24836 static int
24837 xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24838             xmlSchemaAttrInfoPtr iattr,
24839             xmlSchemaTypePtr *localType,
24840             xmlSchemaElementPtr elemDecl)
24841 {
24842     int ret = 0;
24843     /*
24844     * cvc-elt (3.3.4) : (4)
24845     * AND
24846     * Schema-Validity Assessment (Element) (cvc-assess-elt)
24847     *   (1.2.1.2.1) - (1.2.1.2.4)
24848     * Handle 'xsi:type'.
24849     */
24850     if (localType == NULL)
24851     return (-1);
24852     *localType = NULL;
24853     if (iattr == NULL)
24854     return (0);
24855     else {
24856     const xmlChar *nsName = NULL, *local = NULL;
24857     /*
24858     * TODO: We should report a *warning* that the type was overriden
24859     * by the instance.
24860     */
24861     ACTIVATE_ATTRIBUTE(iattr);
24862     /*
24863     * (cvc-elt) (3.3.4) : (4.1)
24864     * (cvc-assess-elt) (1.2.1.2.2)
24865     */
24866     ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24867         &nsName, &local);
24868     if (ret != 0) {
24869         if (ret < 0) {
24870         VERROR_INT("xmlSchemaValidateElementByDeclaration",
24871             "calling xmlSchemaQNameExpand() to validate the "
24872             "attribute 'xsi:type'");
24873         goto internal_error;
24874         }
24875         goto exit;
24876     }
24877     /*
24878     * (cvc-elt) (3.3.4) : (4.2)
24879     * (cvc-assess-elt) (1.2.1.2.3)
24880     */
24881     *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24882     if (*localType == NULL) {
24883         xmlChar *str = NULL;
24884 
24885         xmlSchemaCustomErr(ACTXT_CAST vctxt,
24886         XML_SCHEMAV_CVC_ELT_4_2, NULL,
24887         WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24888         "The QName value '%s' of the xsi:type attribute does not "
24889         "resolve to a type definition",
24890         xmlSchemaFormatQName(&str, nsName, local), NULL);
24891         FREE_AND_NULL(str);
24892         ret = vctxt->err;
24893         goto exit;
24894     }
24895     if (elemDecl != NULL) {
24896         int set = 0;
24897 
24898         /*
24899         * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
24900         * "The �local type definition� must be validly
24901         * derived from the {type definition} given the union of
24902         * the {disallowed substitutions} and the {type definition}'s
24903         * {prohibited substitutions}, as defined in
24904         * Type Derivation OK (Complex) (�3.4.6)
24905         * (if it is a complex type definition),
24906         * or given {disallowed substitutions} as defined in Type
24907         * Derivation OK (Simple) (�3.14.6) (if it is a simple type
24908         * definition)."
24909         *
24910         * {disallowed substitutions}: the "block" on the element decl.
24911         * {prohibited substitutions}: the "block" on the type def.
24912         */
24913         /*
24914         * OPTIMIZE TODO: We could map types already evaluated
24915         * to be validly derived from other types to avoid checking
24916         * this over and over for the same types.
24917         */
24918         if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24919         (elemDecl->subtypes->flags &
24920             XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24921         set |= SUBSET_EXTENSION;
24922 
24923         if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24924         (elemDecl->subtypes->flags &
24925             XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24926         set |= SUBSET_RESTRICTION;
24927 
24928         /*
24929         * REMOVED and CHANGED since this produced a parser context
24930         * which adds to the string dict of the schema. So this would
24931         * change the schema and we don't want this. We don't need
24932         * the parser context anymore.
24933         *
24934         * if ((vctxt->pctxt == NULL) &&
24935         *   (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24936         *       return (-1);
24937         */
24938 
24939         if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
24940         elemDecl->subtypes, set) != 0) {
24941         xmlChar *str = NULL;
24942 
24943         xmlSchemaCustomErr(ACTXT_CAST vctxt,
24944             XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24945             "The type definition '%s', specified by xsi:type, is "
24946             "blocked or not validly derived from the type definition "
24947             "of the element declaration",
24948             xmlSchemaFormatQName(&str,
24949             (*localType)->targetNamespace,
24950             (*localType)->name),
24951             NULL);
24952         FREE_AND_NULL(str);
24953         ret = vctxt->err;
24954         *localType = NULL;
24955         }
24956     }
24957     }
24958 exit:
24959     ACTIVATE_ELEM;
24960     return (ret);
24961 internal_error:
24962     ACTIVATE_ELEM;
24963     return (-1);
24964 }
24965 
24966 static int
24967 xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
24968 {
24969     xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
24970     xmlSchemaTypePtr actualType;
24971 
24972     /*
24973     * cvc-elt (3.3.4) : 1
24974     */
24975     if (elemDecl == NULL) {
24976     VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
24977         "No matching declaration available");
24978         return (vctxt->err);
24979     }
24980     actualType = WXS_ELEM_TYPEDEF(elemDecl);
24981     /*
24982     * cvc-elt (3.3.4) : 2
24983     */
24984     if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
24985     VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
24986         "The element declaration is abstract");
24987         return (vctxt->err);
24988     }
24989     if (actualType == NULL) {
24990         VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24991             "The type definition is absent");
24992         return (XML_SCHEMAV_CVC_TYPE_1);
24993     }
24994     if (vctxt->nbAttrInfos != 0) {
24995     int ret;
24996     xmlSchemaAttrInfoPtr iattr;
24997     /*
24998     * cvc-elt (3.3.4) : 3
24999     * Handle 'xsi:nil'.
25000     */
25001     iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25002         XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
25003     if (iattr) {
25004         ACTIVATE_ATTRIBUTE(iattr);
25005         /*
25006         * Validate the value.
25007         */
25008         ret = xmlSchemaVCheckCVCSimpleType(
25009         ACTXT_CAST vctxt, NULL,
25010         xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
25011         iattr->value, &(iattr->val), 1, 0, 0);
25012         ACTIVATE_ELEM;
25013         if (ret < 0) {
25014         VERROR_INT("xmlSchemaValidateElemDecl",
25015             "calling xmlSchemaVCheckCVCSimpleType() to "
25016             "validate the attribute 'xsi:nil'");
25017         return (-1);
25018         }
25019         if (ret == 0) {
25020         if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
25021             /*
25022             * cvc-elt (3.3.4) : 3.1
25023             */
25024             VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
25025             "The element is not 'nillable'");
25026             /* Does not return an error on purpose. */
25027         } else {
25028             if (xmlSchemaValueGetAsBoolean(iattr->val)) {
25029             /*
25030             * cvc-elt (3.3.4) : 3.2.2
25031             */
25032             if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
25033                 (elemDecl->value != NULL)) {
25034                 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
25035                 "The element cannot be 'nilled' because "
25036                 "there is a fixed value constraint defined "
25037                 "for it");
25038                  /* Does not return an error on purpose. */
25039             } else
25040                 vctxt->inode->flags |=
25041                 XML_SCHEMA_ELEM_INFO_NILLED;
25042             }
25043         }
25044         }
25045     }
25046     /*
25047     * cvc-elt (3.3.4) : 4
25048     * Handle 'xsi:type'.
25049     */
25050     iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25051         XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25052     if (iattr) {
25053         xmlSchemaTypePtr localType = NULL;
25054 
25055         ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
25056         elemDecl);
25057         if (ret != 0) {
25058         if (ret == -1) {
25059             VERROR_INT("xmlSchemaValidateElemDecl",
25060             "calling xmlSchemaProcessXSIType() to "
25061             "process the attribute 'xsi:type'");
25062             return (-1);
25063         }
25064         /* Does not return an error on purpose. */
25065         }
25066         if (localType != NULL) {
25067         vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
25068         actualType = localType;
25069         }
25070     }
25071     }
25072     /*
25073     * IDC: Register identity-constraint XPath matchers.
25074     */
25075     if ((elemDecl->idcs != NULL) &&
25076     (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
25077         return (-1);
25078     /*
25079     * No actual type definition.
25080     */
25081     if (actualType == NULL) {
25082         VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25083             "The type definition is absent");
25084         return (XML_SCHEMAV_CVC_TYPE_1);
25085     }
25086     /*
25087     * Remember the actual type definition.
25088     */
25089     vctxt->inode->typeDef = actualType;
25090 
25091     return (0);
25092 }
25093 
25094 static int
25095 xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
25096 {
25097     xmlSchemaAttrInfoPtr iattr;
25098     int ret = 0, i;
25099 
25100     /*
25101     * SPEC cvc-type (3.1.1)
25102     * "The attributes of must be empty, excepting those whose namespace
25103     * name is identical to http://www.w3.org/2001/XMLSchema-instance and
25104     * whose local name is one of type, nil, schemaLocation or
25105     * noNamespaceSchemaLocation."
25106     */
25107     if (vctxt->nbAttrInfos == 0)
25108     return (0);
25109     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25110     iattr = vctxt->attrInfos[i];
25111     if (! iattr->metaType) {
25112         ACTIVATE_ATTRIBUTE(iattr)
25113         xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25114         XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
25115         ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
25116         }
25117     }
25118     ACTIVATE_ELEM
25119     return (ret);
25120 }
25121 
25122 /*
25123 * Cleanup currently used attribute infos.
25124 */
25125 static void
25126 xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
25127 {
25128     int i;
25129     xmlSchemaAttrInfoPtr attr;
25130 
25131     if (vctxt->nbAttrInfos == 0)
25132     return;
25133     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25134     attr = vctxt->attrInfos[i];
25135     if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
25136         if (attr->localName != NULL)
25137         xmlFree((xmlChar *) attr->localName);
25138         if (attr->nsName != NULL)
25139         xmlFree((xmlChar *) attr->nsName);
25140     }
25141     if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
25142         if (attr->value != NULL)
25143         xmlFree((xmlChar *) attr->value);
25144     }
25145     if (attr->val != NULL) {
25146         xmlSchemaFreeValue(attr->val);
25147         attr->val = NULL;
25148     }
25149     memset(attr, 0, sizeof(xmlSchemaAttrInfo));
25150     }
25151     vctxt->nbAttrInfos = 0;
25152 }
25153 
25154 /*
25155 * 3.4.4 Complex Type Definition Validation Rules
25156 *   Element Locally Valid (Complex Type) (cvc-complex-type)
25157 * 3.2.4 Attribute Declaration Validation Rules
25158 *   Validation Rule: Attribute Locally Valid (cvc-attribute)
25159 *   Attribute Locally Valid (Use) (cvc-au)
25160 *
25161 * Only "assessed" attribute information items will be visible to
25162 * IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
25163 */
25164 static int
25165 xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
25166 {
25167     xmlSchemaTypePtr type = vctxt->inode->typeDef;
25168     xmlSchemaItemListPtr attrUseList;
25169     xmlSchemaAttributeUsePtr attrUse = NULL;
25170     xmlSchemaAttributePtr attrDecl = NULL;
25171     xmlSchemaAttrInfoPtr iattr, tmpiattr;
25172     int i, j, found, nbAttrs, nbUses;
25173     int xpathRes = 0, res, wildIDs = 0, fixed;
25174     xmlNodePtr defAttrOwnerElem = NULL;
25175 
25176     /*
25177     * SPEC (cvc-attribute)
25178     * (1) "The declaration must not be �absent� (see Missing
25179     * Sub-components (�5.3) for how this can fail to be
25180     * the case)."
25181     * (2) "Its {type definition} must not be absent."
25182     *
25183     * NOTE (1) + (2): This is not handled here, since we currently do not
25184     * allow validation against schemas which have missing sub-components.
25185     *
25186     * SPEC (cvc-complex-type)
25187     * (3) "For each attribute information item in the element information
25188     * item's [attributes] excepting those whose [namespace name] is
25189     * identical to http://www.w3.org/2001/XMLSchema-instance and whose
25190     * [local name] is one of type, nil, schemaLocation or
25191     * noNamespaceSchemaLocation, the appropriate case among the following
25192     * must be true:
25193     *
25194     */
25195     attrUseList = (xmlSchemaItemListPtr) type->attrUses;
25196     /*
25197     * @nbAttrs is the number of attributes present in the instance.
25198     */
25199     nbAttrs = vctxt->nbAttrInfos;
25200     if (attrUseList != NULL)
25201     nbUses = attrUseList->nbItems;
25202     else
25203     nbUses = 0;
25204     for (i = 0; i < nbUses; i++) {
25205         found = 0;
25206     attrUse = attrUseList->items[i];
25207     attrDecl = WXS_ATTRUSE_DECL(attrUse);
25208         for (j = 0; j < nbAttrs; j++) {
25209         iattr = vctxt->attrInfos[j];
25210         /*
25211         * SPEC (cvc-complex-type) (3)
25212         * Skip meta attributes.
25213         */
25214         if (iattr->metaType)
25215         continue;
25216         if (iattr->localName[0] != attrDecl->name[0])
25217         continue;
25218         if (!xmlStrEqual(iattr->localName, attrDecl->name))
25219         continue;
25220         if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
25221         continue;
25222         found = 1;
25223         /*
25224         * SPEC (cvc-complex-type)
25225         * (3.1) "If there is among the {attribute uses} an attribute
25226         * use with an {attribute declaration} whose {name} matches
25227         * the attribute information item's [local name] and whose
25228         * {target namespace} is identical to the attribute information
25229         * item's [namespace name] (where an �absent� {target namespace}
25230         * is taken to be identical to a [namespace name] with no value),
25231         * then the attribute information must be �valid� with respect
25232         * to that attribute use as per Attribute Locally Valid (Use)
25233         * (�3.5.4). In this case the {attribute declaration} of that
25234         * attribute use is the �context-determined declaration� for the
25235         * attribute information item with respect to Schema-Validity
25236         * Assessment (Attribute) (�3.2.4) and
25237         * Assessment Outcome (Attribute) (�3.2.5).
25238         */
25239         iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25240         iattr->use = attrUse;
25241         /*
25242         * Context-determined declaration.
25243         */
25244         iattr->decl = attrDecl;
25245         iattr->typeDef = attrDecl->subtypes;
25246         break;
25247     }
25248 
25249     if (found)
25250         continue;
25251 
25252     if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
25253         /*
25254         * Handle non-existent, required attributes.
25255         *
25256         * SPEC (cvc-complex-type)
25257         * (4) "The {attribute declaration} of each attribute use in
25258         * the {attribute uses} whose {required} is true matches one
25259         * of the attribute information items in the element information
25260         * item's [attributes] as per clause 3.1 above."
25261         */
25262         tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25263         if (tmpiattr == NULL) {
25264         VERROR_INT(
25265             "xmlSchemaVAttributesComplex",
25266             "calling xmlSchemaGetFreshAttrInfo()");
25267         return (-1);
25268         }
25269         tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
25270         tmpiattr->use = attrUse;
25271         tmpiattr->decl = attrDecl;
25272     } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
25273         ((attrUse->defValue != NULL) ||
25274          (attrDecl->defValue != NULL))) {
25275         /*
25276         * Handle non-existent, optional, default/fixed attributes.
25277         */
25278         tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25279         if (tmpiattr == NULL) {
25280         VERROR_INT(
25281             "xmlSchemaVAttributesComplex",
25282             "calling xmlSchemaGetFreshAttrInfo()");
25283         return (-1);
25284         }
25285         tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
25286         tmpiattr->use = attrUse;
25287         tmpiattr->decl = attrDecl;
25288         tmpiattr->typeDef = attrDecl->subtypes;
25289         tmpiattr->localName = attrDecl->name;
25290         tmpiattr->nsName = attrDecl->targetNamespace;
25291     }
25292     }
25293 
25294     if (vctxt->nbAttrInfos == 0)
25295     return (0);
25296     /*
25297     * Validate against the wildcard.
25298     */
25299     if (type->attributeWildcard != NULL) {
25300     /*
25301     * SPEC (cvc-complex-type)
25302     * (3.2.1) "There must be an {attribute wildcard}."
25303     */
25304     for (i = 0; i < nbAttrs; i++) {
25305         iattr = vctxt->attrInfos[i];
25306         /*
25307         * SPEC (cvc-complex-type) (3)
25308         * Skip meta attributes.
25309         */
25310         if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
25311         continue;
25312         /*
25313         * SPEC (cvc-complex-type)
25314         * (3.2.2) "The attribute information item must be �valid� with
25315         * respect to it as defined in Item Valid (Wildcard) (�3.10.4)."
25316         *
25317         * SPEC Item Valid (Wildcard) (cvc-wildcard)
25318         * "... its [namespace name] must be �valid� with respect to
25319         * the wildcard constraint, as defined in Wildcard allows
25320         * Namespace Name (�3.10.4)."
25321         */
25322         if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
25323             iattr->nsName) == 0) {
25324         /*
25325         * Handle processContents.
25326         *
25327         * SPEC (cvc-wildcard):
25328         * processContents | context-determined declaration:
25329         * "strict"          "mustFind"
25330         * "lax"             "none"
25331         * "skip"            "skip"
25332         */
25333         if (type->attributeWildcard->processContents ==
25334             XML_SCHEMAS_ANY_SKIP) {
25335              /*
25336             * context-determined declaration = "skip"
25337             *
25338             * SPEC PSVI Assessment Outcome (Attribute)
25339             * [validity] = "notKnown"
25340             * [validation attempted] = "none"
25341             */
25342             iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
25343             continue;
25344         }
25345         /*
25346         * Find an attribute declaration.
25347         */
25348         iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25349             iattr->localName, iattr->nsName);
25350         if (iattr->decl != NULL) {
25351             iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25352             /*
25353             * SPEC (cvc-complex-type)
25354             * (5) "Let [Definition:]  the wild IDs be the set of
25355             * all attribute information item to which clause 3.2
25356             * applied and whose �validation� resulted in a
25357             * �context-determined declaration� of mustFind or no
25358             * �context-determined declaration� at all, and whose
25359             * [local name] and [namespace name] resolve (as
25360             * defined by QName resolution (Instance) (�3.15.4)) to
25361             * an attribute declaration whose {type definition} is
25362             * or is derived from ID. Then all of the following
25363             * must be true:"
25364             */
25365             iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
25366             if (xmlSchemaIsDerivedFromBuiltInType(
25367             iattr->typeDef, XML_SCHEMAS_ID)) {
25368             /*
25369             * SPEC (5.1) "There must be no more than one
25370             * item in �wild IDs�."
25371             */
25372             if (wildIDs != 0) {
25373                 /* VAL TODO */
25374                 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
25375                 TODO
25376                 continue;
25377             }
25378             wildIDs++;
25379             /*
25380             * SPEC (cvc-complex-type)
25381             * (5.2) "If �wild IDs� is non-empty, there must not
25382             * be any attribute uses among the {attribute uses}
25383             * whose {attribute declaration}'s {type definition}
25384             * is or is derived from ID."
25385             */
25386                         if (attrUseList != NULL) {
25387                             for (j = 0; j < attrUseList->nbItems; j++) {
25388                                 if (xmlSchemaIsDerivedFromBuiltInType(
25389                                     WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25390                                     XML_SCHEMAS_ID)) {
25391                                     /* URGENT VAL TODO: implement */
25392                             iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25393                                     TODO
25394                                     break;
25395                                 }
25396                             }
25397                         }
25398             }
25399         } else if (type->attributeWildcard->processContents ==
25400             XML_SCHEMAS_ANY_LAX) {
25401             iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
25402             /*
25403             * SPEC PSVI Assessment Outcome (Attribute)
25404             * [validity] = "notKnown"
25405             * [validation attempted] = "none"
25406             */
25407         } else {
25408             iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
25409         }
25410         }
25411     }
25412     }
25413 
25414     if (vctxt->nbAttrInfos == 0)
25415     return (0);
25416 
25417     /*
25418     * Get the owner element; needed for creation of default attributes.
25419     * This fixes bug #341337, reported by David Grohmann.
25420     */
25421     if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25422     xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25423     if (ielem && ielem->node && ielem->node->doc)
25424         defAttrOwnerElem = ielem->node;
25425     }
25426     /*
25427     * Validate values, create default attributes, evaluate IDCs.
25428     */
25429     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25430     iattr = vctxt->attrInfos[i];
25431     /*
25432     * VAL TODO: Note that we won't try to resolve IDCs to
25433     * "lax" and "skip" validated attributes. Check what to
25434     * do in this case.
25435     */
25436     if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25437         (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
25438         continue;
25439     /*
25440     * VAL TODO: What to do if the type definition is missing?
25441     */
25442     if (iattr->typeDef == NULL) {
25443         iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
25444         continue;
25445     }
25446 
25447     ACTIVATE_ATTRIBUTE(iattr);
25448     fixed = 0;
25449     xpathRes = 0;
25450 
25451     if (vctxt->xpathStates != NULL) {
25452         /*
25453         * Evaluate IDCs.
25454         */
25455         xpathRes = xmlSchemaXPathEvaluate(vctxt,
25456         XML_ATTRIBUTE_NODE);
25457         if (xpathRes == -1) {
25458         VERROR_INT("xmlSchemaVAttributesComplex",
25459             "calling xmlSchemaXPathEvaluate()");
25460         goto internal_error;
25461         }
25462     }
25463 
25464     if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
25465         /*
25466         * Default/fixed attributes.
25467         * We need the value only if we need to resolve IDCs or
25468         * will create default attributes.
25469         */
25470         if ((xpathRes) || (defAttrOwnerElem)) {
25471         if (iattr->use->defValue != NULL) {
25472             iattr->value = (xmlChar *) iattr->use->defValue;
25473             iattr->val = iattr->use->defVal;
25474         } else {
25475             iattr->value = (xmlChar *) iattr->decl->defValue;
25476             iattr->val = iattr->decl->defVal;
25477         }
25478         /*
25479         * IDCs will consume the precomputed default value,
25480         * so we need to clone it.
25481         */
25482         if (iattr->val == NULL) {
25483             VERROR_INT("xmlSchemaVAttributesComplex",
25484             "default/fixed value on an attribute use was "
25485             "not precomputed");
25486             goto internal_error;
25487         }
25488         iattr->val = xmlSchemaCopyValue(iattr->val);
25489         if (iattr->val == NULL) {
25490             VERROR_INT("xmlSchemaVAttributesComplex",
25491             "calling xmlSchemaCopyValue()");
25492             goto internal_error;
25493         }
25494         }
25495         /*
25496         * PSVI: Add the default attribute to the current element.
25497         * VAL TODO: Should we use the *normalized* value? This currently
25498         *   uses the *initial* value.
25499         */
25500 
25501         if (defAttrOwnerElem) {
25502         xmlChar *normValue;
25503         const xmlChar *value;
25504 
25505         value = iattr->value;
25506         /*
25507         * Normalize the value.
25508         */
25509         normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25510             iattr->value);
25511         if (normValue != NULL)
25512             value = BAD_CAST normValue;
25513 
25514         if (iattr->nsName == NULL) {
25515             if (xmlNewProp(defAttrOwnerElem,
25516             iattr->localName, value) == NULL) {
25517             VERROR_INT("xmlSchemaVAttributesComplex",
25518                 "callling xmlNewProp()");
25519             if (normValue != NULL)
25520                 xmlFree(normValue);
25521             goto internal_error;
25522             }
25523         } else {
25524             xmlNsPtr ns;
25525 
25526             ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25527             defAttrOwnerElem, iattr->nsName);
25528             if (ns == NULL) {
25529             xmlChar prefix[12];
25530             int counter = 0;
25531 
25532             /*
25533             * Create a namespace declaration on the validation
25534             * root node if no namespace declaration is in scope.
25535             */
25536             do {
25537                 snprintf((char *) prefix, 12, "p%d", counter++);
25538                 ns = xmlSearchNs(defAttrOwnerElem->doc,
25539                 defAttrOwnerElem, BAD_CAST prefix);
25540                 if (counter > 1000) {
25541                 VERROR_INT(
25542                     "xmlSchemaVAttributesComplex",
25543                     "could not compute a ns prefix for a "
25544                     "default/fixed attribute");
25545                 if (normValue != NULL)
25546                     xmlFree(normValue);
25547                 goto internal_error;
25548                 }
25549             } while (ns != NULL);
25550             ns = xmlNewNs(vctxt->validationRoot,
25551                 iattr->nsName, BAD_CAST prefix);
25552             }
25553             /*
25554             * TODO:
25555             * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25556             * If we have QNames: do we need to ensure there's a
25557             * prefix defined for the QName?
25558             */
25559             xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
25560         }
25561         if (normValue != NULL)
25562             xmlFree(normValue);
25563         }
25564         /*
25565         * Go directly to IDC evaluation.
25566         */
25567         goto eval_idcs;
25568     }
25569     /*
25570     * Validate the value.
25571     */
25572     if (vctxt->value != NULL) {
25573         /*
25574         * Free last computed value; just for safety reasons.
25575         */
25576         xmlSchemaFreeValue(vctxt->value);
25577         vctxt->value = NULL;
25578     }
25579     /*
25580     * Note that the attribute *use* can be unavailable, if
25581     * the attribute was a wild attribute.
25582     */
25583     if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25584         ((iattr->use != NULL) &&
25585          (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
25586         fixed = 1;
25587     else
25588         fixed = 0;
25589     /*
25590     * SPEC (cvc-attribute)
25591     * (3) "The item's �normalized value� must be locally �valid�
25592     * with respect to that {type definition} as per
25593     * String Valid (�3.14.4)."
25594     *
25595     * VAL TODO: Do we already have the
25596     * "normalized attribute value" here?
25597     */
25598     if (xpathRes || fixed) {
25599         iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
25600         /*
25601         * Request a computed value.
25602         */
25603         res = xmlSchemaVCheckCVCSimpleType(
25604         ACTXT_CAST vctxt,
25605         iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
25606         1, 1, 0);
25607     } else {
25608         res = xmlSchemaVCheckCVCSimpleType(
25609         ACTXT_CAST vctxt,
25610         iattr->node, iattr->typeDef, iattr->value, NULL,
25611         1, 0, 0);
25612     }
25613 
25614     if (res != 0) {
25615         if (res == -1) {
25616         VERROR_INT("xmlSchemaVAttributesComplex",
25617             "calling xmlSchemaStreamValidateSimpleTypeValue()");
25618         goto internal_error;
25619         }
25620         iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
25621         /*
25622         * SPEC PSVI Assessment Outcome (Attribute)
25623         * [validity] = "invalid"
25624         */
25625         goto eval_idcs;
25626     }
25627 
25628     if (fixed) {
25629         /*
25630         * SPEC Attribute Locally Valid (Use) (cvc-au)
25631         * "For an attribute information item to be�valid�
25632         * with respect to an attribute use its *normalized*
25633         * value� must match the *canonical* lexical
25634         * representation of the attribute use's {value
25635         * constraint}value, if it is present and fixed."
25636         *
25637         * VAL TODO: The requirement for the *canonical* value
25638         * will be removed in XML Schema 1.1.
25639         */
25640         /*
25641         * SPEC Attribute Locally Valid (cvc-attribute)
25642         * (4) "The item's *actual* value� must match the *value* of
25643         * the {value constraint}, if it is present and fixed."
25644         */
25645         if (iattr->val == NULL) {
25646         /* VAL TODO: A value was not precomputed. */
25647         TODO
25648         goto eval_idcs;
25649         }
25650         if ((iattr->use != NULL) &&
25651         (iattr->use->defValue != NULL)) {
25652         if (iattr->use->defVal == NULL) {
25653             /* VAL TODO: A default value was not precomputed. */
25654             TODO
25655             goto eval_idcs;
25656         }
25657         iattr->vcValue = iattr->use->defValue;
25658         /*
25659         if (xmlSchemaCompareValuesWhtsp(attr->val,
25660             (xmlSchemaWhitespaceValueType) ws,
25661             attr->use->defVal,
25662             (xmlSchemaWhitespaceValueType) ws) != 0) {
25663         */
25664         if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25665             iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25666         } else {
25667         if (iattr->decl->defVal == NULL) {
25668             /* VAL TODO: A default value was not precomputed. */
25669             TODO
25670             goto eval_idcs;
25671         }
25672         iattr->vcValue = iattr->decl->defValue;
25673         /*
25674         if (xmlSchemaCompareValuesWhtsp(attr->val,
25675             (xmlSchemaWhitespaceValueType) ws,
25676             attrDecl->defVal,
25677             (xmlSchemaWhitespaceValueType) ws) != 0) {
25678         */
25679         if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25680             iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25681         }
25682         /*
25683         * [validity] = "valid"
25684         */
25685     }
25686 eval_idcs:
25687     /*
25688     * Evaluate IDCs.
25689     */
25690     if (xpathRes) {
25691         if (xmlSchemaXPathProcessHistory(vctxt,
25692         vctxt->depth +1) == -1) {
25693         VERROR_INT("xmlSchemaVAttributesComplex",
25694             "calling xmlSchemaXPathEvaluate()");
25695         goto internal_error;
25696         }
25697     } else if (vctxt->xpathStates != NULL)
25698         xmlSchemaXPathPop(vctxt);
25699     }
25700 
25701     /*
25702     * Report errors.
25703     */
25704     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25705     iattr = vctxt->attrInfos[i];
25706     if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25707         (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25708         (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25709         (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
25710         continue;
25711     ACTIVATE_ATTRIBUTE(iattr);
25712     switch (iattr->state) {
25713         case XML_SCHEMAS_ATTR_ERR_MISSING: {
25714             xmlChar *str = NULL;
25715             ACTIVATE_ELEM;
25716             xmlSchemaCustomErr(ACTXT_CAST vctxt,
25717             XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25718             "The attribute '%s' is required but missing",
25719             xmlSchemaFormatQName(&str,
25720                 iattr->decl->targetNamespace,
25721                 iattr->decl->name),
25722             NULL);
25723             FREE_AND_NULL(str)
25724             break;
25725         }
25726         case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25727         VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25728             "The type definition is absent");
25729         break;
25730         case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
25731         xmlSchemaCustomErr(ACTXT_CAST vctxt,
25732             XML_SCHEMAV_CVC_AU, NULL, NULL,
25733             "The value '%s' does not match the fixed "
25734             "value constraint '%s'",
25735             iattr->value, iattr->vcValue);
25736         break;
25737         case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25738         VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25739             "No matching global attribute declaration available, but "
25740             "demanded by the strict wildcard");
25741         break;
25742         case XML_SCHEMAS_ATTR_UNKNOWN:
25743         if (iattr->metaType)
25744             break;
25745         /*
25746         * MAYBE VAL TODO: One might report different error messages
25747         * for the following errors.
25748         */
25749         if (type->attributeWildcard == NULL) {
25750             xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25751             XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
25752         } else {
25753             xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25754             XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
25755         }
25756         break;
25757         default:
25758         break;
25759     }
25760     }
25761 
25762     ACTIVATE_ELEM;
25763     return (0);
25764 internal_error:
25765     ACTIVATE_ELEM;
25766     return (-1);
25767 }
25768 
25769 static int
25770 xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25771                   int *skip)
25772 {
25773     xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25774     /*
25775     * The namespace of the element was already identified to be
25776     * matching the wildcard.
25777     */
25778     if ((skip == NULL) || (wild == NULL) ||
25779     (wild->type != XML_SCHEMA_TYPE_ANY)) {
25780     VERROR_INT("xmlSchemaValidateElemWildcard",
25781         "bad arguments");
25782     return (-1);
25783     }
25784     *skip = 0;
25785     if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25786     /*
25787     * URGENT VAL TODO: Either we need to position the stream to the
25788     * next sibling, or walk the whole subtree.
25789     */
25790     *skip = 1;
25791     return (0);
25792     }
25793     {
25794     xmlSchemaElementPtr decl = NULL;
25795 
25796     decl = xmlSchemaGetElem(vctxt->schema,
25797         vctxt->inode->localName, vctxt->inode->nsName);
25798     if (decl != NULL) {
25799         vctxt->inode->decl = decl;
25800         return (0);
25801     }
25802     }
25803     if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25804     /* VAL TODO: Change to proper error code. */
25805     VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
25806         "No matching global element declaration available, but "
25807         "demanded by the strict wildcard");
25808     return (vctxt->err);
25809     }
25810     if (vctxt->nbAttrInfos != 0) {
25811     xmlSchemaAttrInfoPtr iattr;
25812     /*
25813     * SPEC Validation Rule: Schema-Validity Assessment (Element)
25814     * (1.2.1.2.1) - (1.2.1.2.3 )
25815     *
25816     * Use the xsi:type attribute for the type definition.
25817     */
25818     iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25819         XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25820     if (iattr != NULL) {
25821         if (xmlSchemaProcessXSIType(vctxt, iattr,
25822         &(vctxt->inode->typeDef), NULL) == -1) {
25823         VERROR_INT("xmlSchemaValidateElemWildcard",
25824             "calling xmlSchemaProcessXSIType() to "
25825             "process the attribute 'xsi:nil'");
25826         return (-1);
25827         }
25828         /*
25829         * Don't return an error on purpose.
25830         */
25831         return (0);
25832     }
25833     }
25834     /*
25835     * SPEC Validation Rule: Schema-Validity Assessment (Element)
25836     *
25837     * Fallback to "anyType".
25838     */
25839     vctxt->inode->typeDef =
25840     xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25841     return (0);
25842 }
25843 
25844 /*
25845 * xmlSchemaCheckCOSValidDefault:
25846 *
25847 * This will be called if: not nilled, no content and a default/fixed
25848 * value is provided.
25849 */
25850 
25851 static int
25852 xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25853                   const xmlChar *value,
25854                   xmlSchemaValPtr *val)
25855 {
25856     int ret = 0;
25857     xmlSchemaNodeInfoPtr inode = vctxt->inode;
25858 
25859     /*
25860     * cos-valid-default:
25861     * Schema Component Constraint: Element Default Valid (Immediate)
25862     * For a string to be a valid default with respect to a type
25863     * definition the appropriate case among the following must be true:
25864     */
25865     if WXS_IS_COMPLEX(inode->typeDef) {
25866     /*
25867     * Complex type.
25868     *
25869     * SPEC (2.1) "its {content type} must be a simple type definition
25870     * or mixed."
25871     * SPEC (2.2.2) "If the {content type} is mixed, then the {content
25872     * type}'s particle must be �emptiable� as defined by
25873     * Particle Emptiable (�3.9.6)."
25874     */
25875     if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25876         ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25877          (! WXS_EMPTIABLE(inode->typeDef)))) {
25878         ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25879         /* NOTE that this covers (2.2.2) as well. */
25880         VERROR(ret, NULL,
25881         "For a string to be a valid default, the type definition "
25882         "must be a simple type or a complex type with simple content "
25883         "or mixed content and a particle emptiable");
25884         return(ret);
25885     }
25886     }
25887     /*
25888     * 1 If the type definition is a simple type definition, then the string
25889     * must be �valid� with respect to that definition as defined by String
25890     * Valid (�3.14.4).
25891     *
25892     * AND
25893     *
25894     * 2.2.1 If the {content type} is a simple type definition, then the
25895     * string must be �valid� with respect to that simple type definition
25896     * as defined by String Valid (�3.14.4).
25897     */
25898     if (WXS_IS_SIMPLE(inode->typeDef)) {
25899 
25900     ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25901         NULL, inode->typeDef, value, val, 1, 1, 0);
25902 
25903     } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
25904 
25905     ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25906         NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25907     }
25908     if (ret < 0) {
25909     VERROR_INT("xmlSchemaCheckCOSValidDefault",
25910         "calling xmlSchemaVCheckCVCSimpleType()");
25911     }
25912     return (ret);
25913 }
25914 
25915 static void
25916 xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
25917                    const xmlChar * name ATTRIBUTE_UNUSED,
25918                    xmlSchemaElementPtr item,
25919                    xmlSchemaNodeInfoPtr inode)
25920 {
25921     inode->decl = item;
25922 #ifdef DEBUG_CONTENT
25923     {
25924     xmlChar *str = NULL;
25925 
25926     if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
25927         xmlGenericError(xmlGenericErrorContext,
25928         "AUTOMATON callback for '%s' [declaration]\n",
25929         xmlSchemaFormatQName(&str,
25930         inode->localName, inode->nsName));
25931     } else {
25932         xmlGenericError(xmlGenericErrorContext,
25933             "AUTOMATON callback for '%s' [wildcard]\n",
25934             xmlSchemaFormatQName(&str,
25935             inode->localName, inode->nsName));
25936 
25937     }
25938     FREE_AND_NULL(str)
25939     }
25940 #endif
25941 }
25942 
25943 static int
25944 xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
25945 {
25946     vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25947     if (vctxt->inode == NULL) {
25948     VERROR_INT("xmlSchemaValidatorPushElem",
25949         "calling xmlSchemaGetFreshElemInfo()");
25950     return (-1);
25951     }
25952     vctxt->nbAttrInfos = 0;
25953     return (0);
25954 }
25955 
25956 static int
25957 xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
25958                  xmlSchemaNodeInfoPtr inode,
25959                  xmlSchemaTypePtr type,
25960                  const xmlChar *value)
25961 {
25962     if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
25963     return (xmlSchemaVCheckCVCSimpleType(
25964         ACTXT_CAST vctxt, NULL,
25965         type, value, &(inode->val), 1, 1, 0));
25966     else
25967     return (xmlSchemaVCheckCVCSimpleType(
25968         ACTXT_CAST vctxt, NULL,
25969         type, value, NULL, 1, 0, 0));
25970 }
25971 
25972 
25973 
25974 /*
25975 * Process END of element.
25976 */
25977 static int
25978 xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
25979 {
25980     int ret = 0;
25981     xmlSchemaNodeInfoPtr inode = vctxt->inode;
25982 
25983     if (vctxt->nbAttrInfos != 0)
25984     xmlSchemaClearAttrInfos(vctxt);
25985     if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
25986     /*
25987     * This element was not expected;
25988     * we will not validate child elements of broken parents.
25989     * Skip validation of all content of the parent.
25990     */
25991     vctxt->skipDepth = vctxt->depth -1;
25992     goto end_elem;
25993     }
25994     if ((inode->typeDef == NULL) ||
25995     (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
25996     /*
25997     * 1. the type definition might be missing if the element was
25998     *    error prone
25999     * 2. it might be abstract.
26000     */
26001     goto end_elem;
26002     }
26003     /*
26004     * Check the content model.
26005     */
26006     if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
26007     (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
26008 
26009     /*
26010     * Workaround for "anyType".
26011     */
26012     if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
26013         goto character_content;
26014 
26015     if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
26016         xmlChar *values[10];
26017         int terminal, nbval = 10, nbneg;
26018 
26019         if (inode->regexCtxt == NULL) {
26020         /*
26021         * Create the regex context.
26022         */
26023         inode->regexCtxt =
26024             xmlRegNewExecCtxt(inode->typeDef->contModel,
26025             (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26026             vctxt);
26027         if (inode->regexCtxt == NULL) {
26028             VERROR_INT("xmlSchemaValidatorPopElem",
26029             "failed to create a regex context");
26030             goto internal_error;
26031         }
26032 #ifdef DEBUG_AUTOMATA
26033         xmlGenericError(xmlGenericErrorContext,
26034             "AUTOMATON create on '%s'\n", inode->localName);
26035 #endif
26036         }
26037         /*
26038         * Get hold of the still expected content, since a further
26039         * call to xmlRegExecPushString() will loose this information.
26040         */
26041         xmlRegExecNextValues(inode->regexCtxt,
26042         &nbval, &nbneg, &values[0], &terminal);
26043         ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
26044         if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) {
26045         /*
26046         * Still missing something.
26047         */
26048         ret = 1;
26049         inode->flags |=
26050             XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26051         xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26052             XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
26053             "Missing child element(s)",
26054             nbval, nbneg, values);
26055 #ifdef DEBUG_AUTOMATA
26056         xmlGenericError(xmlGenericErrorContext,
26057             "AUTOMATON missing ERROR on '%s'\n",
26058             inode->localName);
26059 #endif
26060         } else {
26061         /*
26062         * Content model is satisfied.
26063         */
26064         ret = 0;
26065 #ifdef DEBUG_AUTOMATA
26066         xmlGenericError(xmlGenericErrorContext,
26067             "AUTOMATON succeeded on '%s'\n",
26068             inode->localName);
26069 #endif
26070         }
26071 
26072     }
26073     }
26074     if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
26075     goto end_elem;
26076 
26077 character_content:
26078 
26079     if (vctxt->value != NULL) {
26080     xmlSchemaFreeValue(vctxt->value);
26081     vctxt->value = NULL;
26082     }
26083     /*
26084     * Check character content.
26085     */
26086     if (inode->decl == NULL) {
26087     /*
26088     * Speedup if no declaration exists.
26089     */
26090     if (WXS_IS_SIMPLE(inode->typeDef)) {
26091         ret = xmlSchemaVCheckINodeDataType(vctxt,
26092         inode, inode->typeDef, inode->value);
26093     } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26094         ret = xmlSchemaVCheckINodeDataType(vctxt,
26095         inode, inode->typeDef->contentTypeDef,
26096         inode->value);
26097     }
26098     if (ret < 0) {
26099         VERROR_INT("xmlSchemaValidatorPopElem",
26100         "calling xmlSchemaVCheckCVCSimpleType()");
26101         goto internal_error;
26102     }
26103     goto end_elem;
26104     }
26105     /*
26106     * cvc-elt (3.3.4) : 5
26107     * The appropriate case among the following must be true:
26108     */
26109     /*
26110     * cvc-elt (3.3.4) : 5.1
26111     * If the declaration has a {value constraint},
26112     * the item has neither element nor character [children] and
26113     * clause 3.2 has not applied, then all of the following must be true:
26114     */
26115     if ((inode->decl->value != NULL) &&
26116     (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
26117     (! INODE_NILLED(inode))) {
26118     /*
26119     * cvc-elt (3.3.4) : 5.1.1
26120     * If the �actual type definition� is a �local type definition�
26121     * then the canonical lexical representation of the {value constraint}
26122     * value must be a valid default for the �actual type definition� as
26123     * defined in Element Default Valid (Immediate) (�3.3.6).
26124     */
26125     /*
26126     * NOTE: 'local' above means types acquired by xsi:type.
26127     * NOTE: Although the *canonical* value is stated, it is not
26128     * relevant if canonical or not. Additionally XML Schema 1.1
26129     * will removed this requirement as well.
26130     */
26131     if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
26132 
26133         ret = xmlSchemaCheckCOSValidDefault(vctxt,
26134         inode->decl->value, &(inode->val));
26135         if (ret != 0) {
26136         if (ret < 0) {
26137             VERROR_INT("xmlSchemaValidatorPopElem",
26138             "calling xmlSchemaCheckCOSValidDefault()");
26139             goto internal_error;
26140         }
26141         goto end_elem;
26142         }
26143         /*
26144         * Stop here, to avoid redundant validation of the value
26145         * (see following).
26146         */
26147         goto default_psvi;
26148     }
26149     /*
26150     * cvc-elt (3.3.4) : 5.1.2
26151     * The element information item with the canonical lexical
26152     * representation of the {value constraint} value used as its
26153     * �normalized value� must be �valid� with respect to the
26154     * �actual type definition� as defined by Element Locally Valid (Type)
26155     * (�3.3.4).
26156     */
26157     if (WXS_IS_SIMPLE(inode->typeDef)) {
26158         ret = xmlSchemaVCheckINodeDataType(vctxt,
26159         inode, inode->typeDef, inode->decl->value);
26160     } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26161         ret = xmlSchemaVCheckINodeDataType(vctxt,
26162         inode, inode->typeDef->contentTypeDef,
26163         inode->decl->value);
26164     }
26165     if (ret != 0) {
26166         if (ret < 0) {
26167         VERROR_INT("xmlSchemaValidatorPopElem",
26168             "calling xmlSchemaVCheckCVCSimpleType()");
26169         goto internal_error;
26170         }
26171         goto end_elem;
26172     }
26173 
26174 default_psvi:
26175     /*
26176     * PSVI: Create a text node on the instance element.
26177     */
26178     if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
26179         (inode->node != NULL)) {
26180         xmlNodePtr textChild;
26181         xmlChar *normValue;
26182         /*
26183         * VAL TODO: Normalize the value.
26184         */
26185         normValue = xmlSchemaNormalizeValue(inode->typeDef,
26186         inode->decl->value);
26187         if (normValue != NULL) {
26188         textChild = xmlNewText(BAD_CAST normValue);
26189         xmlFree(normValue);
26190         } else
26191         textChild = xmlNewText(inode->decl->value);
26192         if (textChild == NULL) {
26193         VERROR_INT("xmlSchemaValidatorPopElem",
26194             "calling xmlNewText()");
26195         goto internal_error;
26196         } else
26197         xmlAddChild(inode->node, textChild);
26198     }
26199 
26200     } else if (! INODE_NILLED(inode)) {
26201     /*
26202     * 5.2.1 The element information item must be �valid� with respect
26203     * to the �actual type definition� as defined by Element Locally
26204     * Valid (Type) (�3.3.4).
26205     */
26206     if (WXS_IS_SIMPLE(inode->typeDef)) {
26207          /*
26208         * SPEC (cvc-type) (3.1)
26209         * "If the type definition is a simple type definition, ..."
26210         * (3.1.3) "If clause 3.2 of Element Locally Valid
26211         * (Element) (�3.3.4) did not apply, then the �normalized value�
26212         * must be �valid� with respect to the type definition as defined
26213         * by String Valid (�3.14.4).
26214         */
26215         ret = xmlSchemaVCheckINodeDataType(vctxt,
26216             inode, inode->typeDef, inode->value);
26217     } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26218         /*
26219         * SPEC (cvc-type) (3.2) "If the type definition is a complex type
26220         * definition, then the element information item must be
26221         * �valid� with respect to the type definition as per
26222         * Element Locally Valid (Complex Type) (�3.4.4);"
26223         *
26224         * SPEC (cvc-complex-type) (2.2)
26225         * "If the {content type} is a simple type definition, ...
26226         * the �normalized value� of the element information item is
26227         * �valid� with respect to that simple type definition as
26228         * defined by String Valid (�3.14.4)."
26229         */
26230         ret = xmlSchemaVCheckINodeDataType(vctxt,
26231         inode, inode->typeDef->contentTypeDef, inode->value);
26232     }
26233     if (ret != 0) {
26234         if (ret < 0) {
26235         VERROR_INT("xmlSchemaValidatorPopElem",
26236             "calling xmlSchemaVCheckCVCSimpleType()");
26237         goto internal_error;
26238         }
26239         goto end_elem;
26240     }
26241     /*
26242     * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
26243     * not applied, all of the following must be true:
26244     */
26245     if ((inode->decl->value != NULL) &&
26246         (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
26247 
26248         /*
26249         * TODO: We will need a computed value, when comparison is
26250         * done on computed values.
26251         */
26252         /*
26253         * 5.2.2.1 The element information item must have no element
26254         * information item [children].
26255         */
26256         if (inode->flags &
26257             XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
26258         ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
26259         VERROR(ret, NULL,
26260             "The content must not containt element nodes since "
26261             "there is a fixed value constraint");
26262         goto end_elem;
26263         } else {
26264         /*
26265         * 5.2.2.2 The appropriate case among the following must
26266         * be true:
26267         */
26268         if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
26269             /*
26270             * 5.2.2.2.1 If the {content type} of the �actual type
26271             * definition� is mixed, then the *initial value* of the
26272             * item must match the canonical lexical representation
26273             * of the {value constraint} value.
26274             *
26275             * ... the *initial value* of an element information
26276             * item is the string composed of, in order, the
26277             * [character code] of each character information item in
26278             * the [children] of that element information item.
26279             */
26280             if (! xmlStrEqual(inode->value, inode->decl->value)){
26281             /*
26282             * VAL TODO: Report invalid & expected values as well.
26283             * VAL TODO: Implement the canonical stuff.
26284             */
26285             ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
26286             xmlSchemaCustomErr(ACTXT_CAST vctxt,
26287                 ret, NULL, NULL,
26288                 "The initial value '%s' does not match the fixed "
26289                 "value constraint '%s'",
26290                 inode->value, inode->decl->value);
26291             goto end_elem;
26292             }
26293         } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26294             /*
26295             * 5.2.2.2.2 If the {content type} of the �actual type
26296             * definition� is a simple type definition, then the
26297             * *actual value* of the item must match the canonical
26298             * lexical representation of the {value constraint} value.
26299             */
26300             /*
26301             * VAL TODO: *actual value* is the normalized value, impl.
26302             *           this.
26303             * VAL TODO: Report invalid & expected values as well.
26304             * VAL TODO: Implement a comparison with the computed values.
26305             */
26306             if (! xmlStrEqual(inode->value,
26307                 inode->decl->value)) {
26308             ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
26309             xmlSchemaCustomErr(ACTXT_CAST vctxt,
26310                 ret, NULL, NULL,
26311                 "The actual value '%s' does not match the fixed "
26312                 "value constraint '%s'",
26313                 inode->value,
26314                 inode->decl->value);
26315             goto end_elem;
26316             }
26317         }
26318         }
26319     }
26320     }
26321 
26322 end_elem:
26323     if (vctxt->depth < 0) {
26324     /* TODO: raise error? */
26325     return (0);
26326     }
26327     if (vctxt->depth == vctxt->skipDepth)
26328     vctxt->skipDepth = -1;
26329     /*
26330     * Evaluate the history of XPath state objects.
26331     */
26332     if (inode->appliedXPath &&
26333     (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
26334     goto internal_error;
26335     /*
26336     * MAYBE TODO:
26337     * SPEC (6) "The element information item must be �valid� with
26338     * respect to each of the {identity-constraint definitions} as per
26339     * Identity-constraint Satisfied (�3.11.4)."
26340     */
26341     /*
26342     * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26343     *   need to be built in any case.
26344     *   We will currently build IDC node-tables and bubble them only if
26345     *   keyrefs do exist.
26346     */
26347 
26348     /*
26349     * Add the current IDC target-nodes to the IDC node-tables.
26350     */
26351     if ((inode->idcMatchers != NULL) &&
26352     (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26353     {
26354     if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26355         goto internal_error;
26356     }
26357     /*
26358     * Validate IDC keyrefs.
26359     */
26360     if (vctxt->inode->hasKeyrefs)
26361     if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26362         goto internal_error;
26363     /*
26364     * Merge/free the IDC table.
26365     */
26366     if (inode->idcTable != NULL) {
26367 #ifdef DEBUG_IDC_NODE_TABLE
26368     xmlSchemaDebugDumpIDCTable(stdout,
26369         inode->nsName,
26370         inode->localName,
26371         inode->idcTable);
26372 #endif
26373     if ((vctxt->depth > 0) &&
26374         (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26375     {
26376         /*
26377         * Merge the IDC node table with the table of the parent node.
26378         */
26379         if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26380         goto internal_error;
26381     }
26382     }
26383     /*
26384     * Clear the current ielem.
26385     * VAL TODO: Don't free the PSVI IDC tables if they are
26386     * requested for the PSVI.
26387     */
26388     xmlSchemaClearElemInfo(vctxt, inode);
26389     /*
26390     * Skip further processing if we are on the validation root.
26391     */
26392     if (vctxt->depth == 0) {
26393     vctxt->depth--;
26394     vctxt->inode = NULL;
26395     return (0);
26396     }
26397     /*
26398     * Reset the keyrefDepth if needed.
26399     */
26400     if (vctxt->aidcs != NULL) {
26401     xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26402     do {
26403         if (aidc->keyrefDepth == vctxt->depth) {
26404         /*
26405         * A 'keyrefDepth' of a key/unique IDC matches the current
26406         * depth, this means that we are leaving the scope of the
26407         * top-most keyref IDC which refers to this IDC.
26408         */
26409         aidc->keyrefDepth = -1;
26410         }
26411         aidc = aidc->next;
26412     } while (aidc != NULL);
26413     }
26414     vctxt->depth--;
26415     vctxt->inode = vctxt->elemInfos[vctxt->depth];
26416     /*
26417     * VAL TODO: 7 If the element information item is the �validation root�, it must be
26418     * �valid� per Validation Root Valid (ID/IDREF) (�3.3.4).
26419     */
26420     return (ret);
26421 
26422 internal_error:
26423     vctxt->err = -1;
26424     return (-1);
26425 }
26426 
26427 /*
26428 * 3.4.4 Complex Type Definition Validation Rules
26429 * Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26430 */
26431 static int
26432 xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
26433 {
26434     xmlSchemaNodeInfoPtr pielem;
26435     xmlSchemaTypePtr ptype;
26436     int ret = 0;
26437 
26438     if (vctxt->depth <= 0) {
26439     VERROR_INT("xmlSchemaValidateChildElem",
26440         "not intended for the validation root");
26441     return (-1);
26442     }
26443     pielem = vctxt->elemInfos[vctxt->depth -1];
26444     if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26445     pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26446     /*
26447     * Handle 'nilled' elements.
26448     */
26449     if (INODE_NILLED(pielem)) {
26450     /*
26451     * SPEC (cvc-elt) (3.3.4) : (3.2.1)
26452     */
26453     ACTIVATE_PARENT_ELEM;
26454     ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26455     VERROR(ret, NULL,
26456         "Neither character nor element content is allowed, "
26457         "because the element was 'nilled'");
26458     ACTIVATE_ELEM;
26459     goto unexpected_elem;
26460     }
26461 
26462     ptype = pielem->typeDef;
26463 
26464     if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26465     /*
26466     * Workaround for "anyType": we have currently no content model
26467     * assigned for "anyType", so handle it explicitely.
26468     * "anyType" has an unbounded, lax "any" wildcard.
26469     */
26470     vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26471         vctxt->inode->localName,
26472         vctxt->inode->nsName);
26473 
26474     if (vctxt->inode->decl == NULL) {
26475         xmlSchemaAttrInfoPtr iattr;
26476         /*
26477         * Process "xsi:type".
26478         * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
26479         */
26480         iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26481         XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26482         if (iattr != NULL) {
26483         ret = xmlSchemaProcessXSIType(vctxt, iattr,
26484             &(vctxt->inode->typeDef), NULL);
26485         if (ret != 0) {
26486             if (ret == -1) {
26487             VERROR_INT("xmlSchemaValidateChildElem",
26488                 "calling xmlSchemaProcessXSIType() to "
26489                 "process the attribute 'xsi:nil'");
26490             return (-1);
26491             }
26492             return (ret);
26493         }
26494         } else {
26495          /*
26496          * Fallback to "anyType".
26497          *
26498          * SPEC (cvc-assess-elt)
26499          * "If the item cannot be �strictly assessed�, [...]
26500          * an element information item's schema validity may be laxly
26501          * assessed if its �context-determined declaration� is not
26502          * skip by �validating� with respect to the �ur-type
26503          * definition� as per Element Locally Valid (Type) (�3.3.4)."
26504         */
26505         vctxt->inode->typeDef =
26506             xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26507         }
26508     }
26509     return (0);
26510     }
26511 
26512     switch (ptype->contentType) {
26513     case XML_SCHEMA_CONTENT_EMPTY:
26514         /*
26515         * SPEC (2.1) "If the {content type} is empty, then the
26516         * element information item has no character or element
26517         * information item [children]."
26518         */
26519         ACTIVATE_PARENT_ELEM
26520         ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26521         VERROR(ret, NULL,
26522         "Element content is not allowed, "
26523         "because the content type is empty");
26524         ACTIVATE_ELEM
26525         goto unexpected_elem;
26526         break;
26527 
26528     case XML_SCHEMA_CONTENT_MIXED:
26529         case XML_SCHEMA_CONTENT_ELEMENTS: {
26530         xmlRegExecCtxtPtr regexCtxt;
26531         xmlChar *values[10];
26532         int terminal, nbval = 10, nbneg;
26533 
26534         /* VAL TODO: Optimized "anyType" validation.*/
26535 
26536         if (ptype->contModel == NULL) {
26537         VERROR_INT("xmlSchemaValidateChildElem",
26538             "type has elem content but no content model");
26539         return (-1);
26540         }
26541         /*
26542         * Safety belf for evaluation if the cont. model was already
26543         * examined to be invalid.
26544         */
26545         if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26546         VERROR_INT("xmlSchemaValidateChildElem",
26547             "validating elem, but elem content is already invalid");
26548         return (-1);
26549         }
26550 
26551         regexCtxt = pielem->regexCtxt;
26552         if (regexCtxt == NULL) {
26553         /*
26554         * Create the regex context.
26555         */
26556         regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26557             (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26558             vctxt);
26559         if (regexCtxt == NULL) {
26560             VERROR_INT("xmlSchemaValidateChildElem",
26561             "failed to create a regex context");
26562             return (-1);
26563         }
26564         pielem->regexCtxt = regexCtxt;
26565 #ifdef DEBUG_AUTOMATA
26566         xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26567             pielem->localName);
26568 #endif
26569         }
26570 
26571         /*
26572         * SPEC (2.4) "If the {content type} is element-only or mixed,
26573         * then the sequence of the element information item's
26574         * element information item [children], if any, taken in
26575         * order, is �valid� with respect to the {content type}'s
26576         * particle, as defined in Element Sequence Locally Valid
26577         * (Particle) (�3.9.4)."
26578         */
26579         ret = xmlRegExecPushString2(regexCtxt,
26580         vctxt->inode->localName,
26581         vctxt->inode->nsName,
26582         vctxt->inode);
26583 #ifdef DEBUG_AUTOMATA
26584         if (ret < 0)
26585         xmlGenericError(xmlGenericErrorContext,
26586         "AUTOMATON push ERROR for '%s' on '%s'\n",
26587         vctxt->inode->localName, pielem->localName);
26588         else
26589         xmlGenericError(xmlGenericErrorContext,
26590         "AUTOMATON push OK for '%s' on '%s'\n",
26591         vctxt->inode->localName, pielem->localName);
26592 #endif
26593         if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26594         VERROR_INT("xmlSchemaValidateChildElem",
26595             "calling xmlRegExecPushString2()");
26596         return (-1);
26597         }
26598         if (ret < 0) {
26599         xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26600             &values[0], &terminal);
26601         xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26602             XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26603             "This element is not expected",
26604             nbval, nbneg, values);
26605         ret = vctxt->err;
26606         goto unexpected_elem;
26607         } else
26608         ret = 0;
26609     }
26610         break;
26611     case XML_SCHEMA_CONTENT_SIMPLE:
26612     case XML_SCHEMA_CONTENT_BASIC:
26613         ACTIVATE_PARENT_ELEM
26614         if (WXS_IS_COMPLEX(ptype)) {
26615         /*
26616         * SPEC (cvc-complex-type) (2.2)
26617         * "If the {content type} is a simple type definition, then
26618         * the element information item has no element information
26619         * item [children], ..."
26620         */
26621         ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26622         VERROR(ret, NULL, "Element content is not allowed, "
26623             "because the content type is a simple type definition");
26624         } else {
26625         /*
26626         * SPEC (cvc-type) (3.1.2) "The element information item must
26627         * have no element information item [children]."
26628         */
26629         ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26630         VERROR(ret, NULL, "Element content is not allowed, "
26631             "because the type definition is simple");
26632         }
26633         ACTIVATE_ELEM
26634         ret = vctxt->err;
26635         goto unexpected_elem;
26636         break;
26637 
26638     default:
26639         break;
26640     }
26641     return (ret);
26642 unexpected_elem:
26643     /*
26644     * Pop this element and set the skipDepth to skip
26645     * all further content of the parent element.
26646     */
26647     vctxt->skipDepth = vctxt->depth;
26648     vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26649     pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26650     return (ret);
26651 }
26652 
26653 #define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26654 #define XML_SCHEMA_PUSH_TEXT_CREATED 2
26655 #define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26656 
26657 static int
26658 xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26659           int nodeType, const xmlChar *value, int len,
26660           int mode, int *consumed)
26661 {
26662     /*
26663     * Unfortunately we have to duplicate the text sometimes.
26664     * OPTIMIZE: Maybe we could skip it, if:
26665     *   1. content type is simple
26666     *   2. whitespace is "collapse"
26667     *   3. it consists of whitespace only
26668     *
26669     * Process character content.
26670     */
26671     if (consumed != NULL)
26672     *consumed = 0;
26673     if (INODE_NILLED(vctxt->inode)) {
26674     /*
26675     * SPEC cvc-elt (3.3.4 - 3.2.1)
26676     * "The element information item must have no character or
26677     * element information item [children]."
26678     */
26679     VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26680         "Neither character nor element content is allowed "
26681         "because the element is 'nilled'");
26682     return (vctxt->err);
26683     }
26684     /*
26685     * SPEC (2.1) "If the {content type} is empty, then the
26686     * element information item has no character or element
26687     * information item [children]."
26688     */
26689     if (vctxt->inode->typeDef->contentType ==
26690         XML_SCHEMA_CONTENT_EMPTY) {
26691     VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26692         "Character content is not allowed, "
26693         "because the content type is empty");
26694     return (vctxt->err);
26695     }
26696 
26697     if (vctxt->inode->typeDef->contentType ==
26698         XML_SCHEMA_CONTENT_ELEMENTS) {
26699     if ((nodeType != XML_TEXT_NODE) ||
26700         (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26701         /*
26702         * SPEC cvc-complex-type (2.3)
26703         * "If the {content type} is element-only, then the
26704         * element information item has no character information
26705         * item [children] other than those whose [character
26706         * code] is defined as a white space in [XML 1.0 (Second
26707         * Edition)]."
26708         */
26709         VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26710         "Character content other than whitespace is not allowed "
26711         "because the content type is 'element-only'");
26712         return (vctxt->err);
26713     }
26714     return (0);
26715     }
26716 
26717     if ((value == NULL) || (value[0] == 0))
26718     return (0);
26719     /*
26720     * Save the value.
26721     * NOTE that even if the content type is *mixed*, we need the
26722     * *initial value* for default/fixed value constraints.
26723     */
26724     if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26725     ((vctxt->inode->decl == NULL) ||
26726     (vctxt->inode->decl->value == NULL)))
26727     return (0);
26728 
26729     if (vctxt->inode->value == NULL) {
26730     /*
26731     * Set the value.
26732     */
26733     switch (mode) {
26734         case XML_SCHEMA_PUSH_TEXT_PERSIST:
26735         /*
26736         * When working on a tree.
26737         */
26738         vctxt->inode->value = value;
26739         break;
26740         case XML_SCHEMA_PUSH_TEXT_CREATED:
26741         /*
26742         * When working with the reader.
26743         * The value will be freed by the element info.
26744         */
26745         vctxt->inode->value = value;
26746         if (consumed != NULL)
26747             *consumed = 1;
26748         vctxt->inode->flags |=
26749             XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26750         break;
26751         case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26752         /*
26753         * When working with SAX.
26754         * The value will be freed by the element info.
26755         */
26756         if (len != -1)
26757             vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26758         else
26759             vctxt->inode->value = BAD_CAST xmlStrdup(value);
26760         vctxt->inode->flags |=
26761             XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26762         break;
26763         default:
26764         break;
26765     }
26766     } else {
26767     if (len < 0)
26768         len = xmlStrlen(value);
26769     /*
26770     * Concat the value.
26771     */
26772     if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
26773         vctxt->inode->value = BAD_CAST xmlStrncat(
26774         (xmlChar *) vctxt->inode->value, value, len);
26775     } else {
26776         vctxt->inode->value =
26777         BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
26778         vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26779     }
26780     }
26781 
26782     return (0);
26783 }
26784 
26785 static int
26786 xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
26787 {
26788     int ret = 0;
26789 
26790     if ((vctxt->skipDepth != -1) &&
26791     (vctxt->depth >= vctxt->skipDepth)) {
26792     VERROR_INT("xmlSchemaValidateElem",
26793         "in skip-state");
26794     goto internal_error;
26795     }
26796     if (vctxt->xsiAssemble) {
26797     /*
26798     * We will stop validation if there was an error during
26799     * dynamic schema construction.
26800     * Note that we simply set @skipDepth to 0, this could
26801     * mean that a streaming document via SAX would be
26802     * still read to the end but it won't be validated any more.
26803     * TODO: If we are sure how to stop the validation at once
26804     *   for all input scenarios, then this should be changed to
26805     *   instantly stop the validation.
26806     */
26807     ret = xmlSchemaAssembleByXSI(vctxt);
26808     if (ret != 0) {
26809         if (ret == -1)
26810         goto internal_error;
26811         vctxt->skipDepth = 0;
26812         return(ret);
26813     }
26814         /*
26815          * Augment the IDC definitions for the main schema and all imported ones
26816          * NOTE: main schema is the first in the imported list
26817          */
26818         xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt);
26819     }
26820     if (vctxt->depth > 0) {
26821     /*
26822     * Validate this element against the content model
26823     * of the parent.
26824     */
26825     ret = xmlSchemaValidateChildElem(vctxt);
26826     if (ret != 0) {
26827         if (ret < 0) {
26828         VERROR_INT("xmlSchemaValidateElem",
26829             "calling xmlSchemaStreamValidateChildElement()");
26830         goto internal_error;
26831         }
26832         goto exit;
26833     }
26834     if (vctxt->depth == vctxt->skipDepth)
26835         goto exit;
26836     if ((vctxt->inode->decl == NULL) &&
26837         (vctxt->inode->typeDef == NULL)) {
26838         VERROR_INT("xmlSchemaValidateElem",
26839         "the child element was valid but neither the "
26840         "declaration nor the type was set");
26841         goto internal_error;
26842     }
26843     } else {
26844     /*
26845     * Get the declaration of the validation root.
26846     */
26847     vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26848         vctxt->inode->localName,
26849         vctxt->inode->nsName);
26850     if (vctxt->inode->decl == NULL) {
26851         ret = XML_SCHEMAV_CVC_ELT_1;
26852         VERROR(ret, NULL,
26853         "No matching global declaration available "
26854         "for the validation root");
26855         goto exit;
26856     }
26857     }
26858 
26859     if (vctxt->inode->decl == NULL)
26860     goto type_validation;
26861 
26862     if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26863     int skip;
26864     /*
26865     * Wildcards.
26866     */
26867     ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26868     if (ret != 0) {
26869         if (ret < 0) {
26870         VERROR_INT("xmlSchemaValidateElem",
26871             "calling xmlSchemaValidateElemWildcard()");
26872         goto internal_error;
26873         }
26874         goto exit;
26875     }
26876     if (skip) {
26877         vctxt->skipDepth = vctxt->depth;
26878         goto exit;
26879     }
26880     /*
26881     * The declaration might be set by the wildcard validation,
26882     * when the processContents is "lax" or "strict".
26883     */
26884     if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26885         /*
26886         * Clear the "decl" field to not confuse further processing.
26887         */
26888         vctxt->inode->decl = NULL;
26889         goto type_validation;
26890     }
26891     }
26892     /*
26893     * Validate against the declaration.
26894     */
26895     ret = xmlSchemaValidateElemDecl(vctxt);
26896     if (ret != 0) {
26897     if (ret < 0) {
26898         VERROR_INT("xmlSchemaValidateElem",
26899         "calling xmlSchemaValidateElemDecl()");
26900         goto internal_error;
26901     }
26902     goto exit;
26903     }
26904     /*
26905     * Validate against the type definition.
26906     */
26907 type_validation:
26908 
26909     if (vctxt->inode->typeDef == NULL) {
26910     vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26911     ret = XML_SCHEMAV_CVC_TYPE_1;
26912         VERROR(ret, NULL,
26913             "The type definition is absent");
26914     goto exit;
26915     }
26916     if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26917     vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26918     ret = XML_SCHEMAV_CVC_TYPE_2;
26919             VERROR(ret, NULL,
26920             "The type definition is abstract");
26921     goto exit;
26922     }
26923     /*
26924     * Evaluate IDCs. Do it here, since new IDC matchers are registered
26925     * during validation against the declaration. This must be done
26926     * _before_ attribute validation.
26927     */
26928     if (vctxt->xpathStates != NULL) {
26929     ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
26930     vctxt->inode->appliedXPath = 1;
26931     if (ret == -1) {
26932         VERROR_INT("xmlSchemaValidateElem",
26933         "calling xmlSchemaXPathEvaluate()");
26934         goto internal_error;
26935     }
26936     }
26937     /*
26938     * Validate attributes.
26939     */
26940     if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
26941     if ((vctxt->nbAttrInfos != 0) ||
26942         (vctxt->inode->typeDef->attrUses != NULL)) {
26943 
26944         ret = xmlSchemaVAttributesComplex(vctxt);
26945     }
26946     } else if (vctxt->nbAttrInfos != 0) {
26947 
26948     ret = xmlSchemaVAttributesSimple(vctxt);
26949     }
26950     /*
26951     * Clear registered attributes.
26952     */
26953     if (vctxt->nbAttrInfos != 0)
26954     xmlSchemaClearAttrInfos(vctxt);
26955     if (ret == -1) {
26956     VERROR_INT("xmlSchemaValidateElem",
26957         "calling attributes validation");
26958     goto internal_error;
26959     }
26960     /*
26961     * Don't return an error if attributes are invalid on purpose.
26962     */
26963     ret = 0;
26964 
26965 exit:
26966     if (ret != 0)
26967     vctxt->skipDepth = vctxt->depth;
26968     return (ret);
26969 internal_error:
26970     return (-1);
26971 }
26972 
26973 #ifdef XML_SCHEMA_READER_ENABLED
26974 static int
26975 xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
26976 {
26977     const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
26978     int depth, nodeType, ret = 0, consumed;
26979     xmlSchemaNodeInfoPtr ielem;
26980 
26981     vctxt->depth = -1;
26982     ret = xmlTextReaderRead(vctxt->reader);
26983     /*
26984     * Move to the document element.
26985     */
26986     while (ret == 1) {
26987     nodeType = xmlTextReaderNodeType(vctxt->reader);
26988     if (nodeType == XML_ELEMENT_NODE)
26989         goto root_found;
26990     ret = xmlTextReaderRead(vctxt->reader);
26991     }
26992     goto exit;
26993 
26994 root_found:
26995 
26996     do {
26997     depth = xmlTextReaderDepth(vctxt->reader);
26998     nodeType = xmlTextReaderNodeType(vctxt->reader);
26999 
27000     if (nodeType == XML_ELEMENT_NODE) {
27001 
27002         vctxt->depth++;
27003         if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27004         VERROR_INT("xmlSchemaVReaderWalk",
27005             "calling xmlSchemaValidatorPushElem()");
27006         goto internal_error;
27007         }
27008         ielem = vctxt->inode;
27009         ielem->localName = xmlTextReaderLocalName(vctxt->reader);
27010         ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
27011         ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
27012         /*
27013         * Is the element empty?
27014         */
27015         ret = xmlTextReaderIsEmptyElement(vctxt->reader);
27016         if (ret == -1) {
27017         VERROR_INT("xmlSchemaVReaderWalk",
27018             "calling xmlTextReaderIsEmptyElement()");
27019         goto internal_error;
27020         }
27021         if (ret) {
27022         ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27023         }
27024         /*
27025         * Register attributes.
27026         */
27027         vctxt->nbAttrInfos = 0;
27028         ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
27029         if (ret == -1) {
27030         VERROR_INT("xmlSchemaVReaderWalk",
27031             "calling xmlTextReaderMoveToFirstAttribute()");
27032         goto internal_error;
27033         }
27034         if (ret == 1) {
27035         do {
27036             /*
27037             * VAL TODO: How do we know that the reader works on a
27038             * node tree, to be able to pass a node here?
27039             */
27040             if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
27041             (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
27042             xmlTextReaderNamespaceUri(vctxt->reader), 1,
27043             xmlTextReaderValue(vctxt->reader), 1) == -1) {
27044 
27045             VERROR_INT("xmlSchemaVReaderWalk",
27046                 "calling xmlSchemaValidatorPushAttribute()");
27047             goto internal_error;
27048             }
27049             ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
27050             if (ret == -1) {
27051             VERROR_INT("xmlSchemaVReaderWalk",
27052                 "calling xmlTextReaderMoveToFirstAttribute()");
27053             goto internal_error;
27054             }
27055         } while (ret == 1);
27056         /*
27057         * Back to element position.
27058         */
27059         ret = xmlTextReaderMoveToElement(vctxt->reader);
27060         if (ret == -1) {
27061             VERROR_INT("xmlSchemaVReaderWalk",
27062             "calling xmlTextReaderMoveToElement()");
27063             goto internal_error;
27064         }
27065         }
27066         /*
27067         * Validate the element.
27068         */
27069         ret= xmlSchemaValidateElem(vctxt);
27070         if (ret != 0) {
27071         if (ret == -1) {
27072             VERROR_INT("xmlSchemaVReaderWalk",
27073             "calling xmlSchemaValidateElem()");
27074             goto internal_error;
27075         }
27076         goto exit;
27077         }
27078         if (vctxt->depth == vctxt->skipDepth) {
27079         int curDepth;
27080         /*
27081         * Skip all content.
27082         */
27083         if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
27084             ret = xmlTextReaderRead(vctxt->reader);
27085             curDepth = xmlTextReaderDepth(vctxt->reader);
27086             while ((ret == 1) && (curDepth != depth)) {
27087             ret = xmlTextReaderRead(vctxt->reader);
27088             curDepth = xmlTextReaderDepth(vctxt->reader);
27089             }
27090             if (ret < 0) {
27091             /*
27092             * VAL TODO: A reader error occured; what to do here?
27093             */
27094             ret = 1;
27095             goto exit;
27096             }
27097         }
27098         goto leave_elem;
27099         }
27100         /*
27101         * READER VAL TODO: Is an END_ELEM really never called
27102         * if the elem is empty?
27103         */
27104         if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27105         goto leave_elem;
27106     } else if (nodeType == END_ELEM) {
27107         /*
27108         * Process END of element.
27109         */
27110 leave_elem:
27111         ret = xmlSchemaValidatorPopElem(vctxt);
27112         if (ret != 0) {
27113         if (ret < 0) {
27114             VERROR_INT("xmlSchemaVReaderWalk",
27115             "calling xmlSchemaValidatorPopElem()");
27116             goto internal_error;
27117         }
27118         goto exit;
27119         }
27120         if (vctxt->depth >= 0)
27121         ielem = vctxt->inode;
27122         else
27123         ielem = NULL;
27124     } else if ((nodeType == XML_TEXT_NODE) ||
27125         (nodeType == XML_CDATA_SECTION_NODE) ||
27126         (nodeType == WHTSP) ||
27127         (nodeType == SIGN_WHTSP)) {
27128         /*
27129         * Process character content.
27130         */
27131         xmlChar *value;
27132 
27133         if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
27134         nodeType = XML_TEXT_NODE;
27135 
27136         value = xmlTextReaderValue(vctxt->reader);
27137         ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
27138         -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
27139         if (! consumed)
27140         xmlFree(value);
27141         if (ret == -1) {
27142         VERROR_INT("xmlSchemaVReaderWalk",
27143             "calling xmlSchemaVPushText()");
27144         goto internal_error;
27145         }
27146     } else if ((nodeType == XML_ENTITY_NODE) ||
27147         (nodeType == XML_ENTITY_REF_NODE)) {
27148         /*
27149         * VAL TODO: What to do with entities?
27150         */
27151         TODO
27152     }
27153     /*
27154     * Read next node.
27155     */
27156     ret = xmlTextReaderRead(vctxt->reader);
27157     } while (ret == 1);
27158 
27159 exit:
27160     return (ret);
27161 internal_error:
27162     return (-1);
27163 }
27164 #endif
27165 
27166 /************************************************************************
27167  *                                  *
27168  *          SAX validation handlers             *
27169  *                                  *
27170  ************************************************************************/
27171 
27172 /*
27173 * Process text content.
27174 */
27175 static void
27176 xmlSchemaSAXHandleText(void *ctx,
27177                const xmlChar * ch,
27178                int len)
27179 {
27180     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27181 
27182     if (vctxt->depth < 0)
27183     return;
27184     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27185     return;
27186     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27187     vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27188     if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
27189     XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27190     VERROR_INT("xmlSchemaSAXHandleCDataSection",
27191         "calling xmlSchemaVPushText()");
27192     vctxt->err = -1;
27193     xmlStopParser(vctxt->parserCtxt);
27194     }
27195 }
27196 
27197 /*
27198 * Process CDATA content.
27199 */
27200 static void
27201 xmlSchemaSAXHandleCDataSection(void *ctx,
27202                  const xmlChar * ch,
27203                  int len)
27204 {
27205     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27206 
27207     if (vctxt->depth < 0)
27208     return;
27209     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27210     return;
27211     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27212     vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27213     if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
27214     XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27215     VERROR_INT("xmlSchemaSAXHandleCDataSection",
27216         "calling xmlSchemaVPushText()");
27217     vctxt->err = -1;
27218     xmlStopParser(vctxt->parserCtxt);
27219     }
27220 }
27221 
27222 static void
27223 xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
27224                 const xmlChar * name ATTRIBUTE_UNUSED)
27225 {
27226     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27227 
27228     if (vctxt->depth < 0)
27229     return;
27230     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27231     return;
27232     /* SAX VAL TODO: What to do here? */
27233     TODO
27234 }
27235 
27236 static void
27237 xmlSchemaSAXHandleStartElementNs(void *ctx,
27238                  const xmlChar * localname,
27239                  const xmlChar * prefix ATTRIBUTE_UNUSED,
27240                  const xmlChar * URI,
27241                  int nb_namespaces,
27242                  const xmlChar ** namespaces,
27243                  int nb_attributes,
27244                  int nb_defaulted ATTRIBUTE_UNUSED,
27245                  const xmlChar ** attributes)
27246 {
27247     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27248     int ret;
27249     xmlSchemaNodeInfoPtr ielem;
27250     int i, j;
27251 
27252     /*
27253     * SAX VAL TODO: What to do with nb_defaulted?
27254     */
27255     /*
27256     * Skip elements if inside a "skip" wildcard or invalid.
27257     */
27258     vctxt->depth++;
27259     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27260     return;
27261     /*
27262     * Push the element.
27263     */
27264     if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27265     VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27266         "calling xmlSchemaValidatorPushElem()");
27267     goto internal_error;
27268     }
27269     ielem = vctxt->inode;
27270     /*
27271     * TODO: Is this OK?
27272     */
27273     ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
27274     ielem->localName = localname;
27275     ielem->nsName = URI;
27276     ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27277     /*
27278     * Register namespaces on the elem info.
27279     */
27280     if (nb_namespaces != 0) {
27281     /*
27282     * Although the parser builds its own namespace list,
27283     * we have no access to it, so we'll use an own one.
27284     */
27285         for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
27286         /*
27287         * Store prefix and namespace name.
27288         */
27289         if (ielem->nsBindings == NULL) {
27290         ielem->nsBindings =
27291             (const xmlChar **) xmlMalloc(10 *
27292             sizeof(const xmlChar *));
27293         if (ielem->nsBindings == NULL) {
27294             xmlSchemaVErrMemory(vctxt,
27295             "allocating namespace bindings for SAX validation",
27296             NULL);
27297             goto internal_error;
27298         }
27299         ielem->nbNsBindings = 0;
27300         ielem->sizeNsBindings = 5;
27301         } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
27302         ielem->sizeNsBindings *= 2;
27303         ielem->nsBindings =
27304             (const xmlChar **) xmlRealloc(
27305             (void *) ielem->nsBindings,
27306             ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
27307         if (ielem->nsBindings == NULL) {
27308             xmlSchemaVErrMemory(vctxt,
27309             "re-allocating namespace bindings for SAX validation",
27310             NULL);
27311             goto internal_error;
27312         }
27313         }
27314 
27315         ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
27316         if (namespaces[j+1][0] == 0) {
27317         /*
27318         * Handle xmlns="".
27319         */
27320         ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
27321         } else
27322         ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
27323             namespaces[j+1];
27324         ielem->nbNsBindings++;
27325     }
27326     }
27327     /*
27328     * Register attributes.
27329     * SAX VAL TODO: We are not adding namespace declaration
27330     * attributes yet.
27331     */
27332     if (nb_attributes != 0) {
27333     xmlChar *value;
27334 
27335         for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27336         /*
27337         * Duplicate the value.
27338         */
27339         value = xmlStrndup(attributes[j+3],
27340         attributes[j+4] - attributes[j+3]);
27341         /*
27342         * TODO: Set the node line.
27343         */
27344         ret = xmlSchemaValidatorPushAttribute(vctxt,
27345         NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
27346         value, 1);
27347         if (ret == -1) {
27348         VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27349             "calling xmlSchemaValidatorPushAttribute()");
27350         goto internal_error;
27351         }
27352     }
27353     }
27354     /*
27355     * Validate the element.
27356     */
27357     ret = xmlSchemaValidateElem(vctxt);
27358     if (ret != 0) {
27359     if (ret == -1) {
27360         VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27361         "calling xmlSchemaValidateElem()");
27362         goto internal_error;
27363     }
27364     goto exit;
27365     }
27366 
27367 exit:
27368     return;
27369 internal_error:
27370     vctxt->err = -1;
27371     xmlStopParser(vctxt->parserCtxt);
27372     return;
27373 }
27374 
27375 static void
27376 xmlSchemaSAXHandleEndElementNs(void *ctx,
27377                    const xmlChar * localname ATTRIBUTE_UNUSED,
27378                    const xmlChar * prefix ATTRIBUTE_UNUSED,
27379                    const xmlChar * URI ATTRIBUTE_UNUSED)
27380 {
27381     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27382     int res;
27383 
27384     /*
27385     * Skip elements if inside a "skip" wildcard or if invalid.
27386     */
27387     if (vctxt->skipDepth != -1) {
27388     if (vctxt->depth > vctxt->skipDepth) {
27389         vctxt->depth--;
27390         return;
27391     } else
27392         vctxt->skipDepth = -1;
27393     }
27394     /*
27395     * SAX VAL TODO: Just a temporary check.
27396     */
27397     if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27398     (!xmlStrEqual(vctxt->inode->nsName, URI))) {
27399     VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27400         "elem pop mismatch");
27401     }
27402     res = xmlSchemaValidatorPopElem(vctxt);
27403     if (res != 0) {
27404     if (res < 0) {
27405         VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27406         "calling xmlSchemaValidatorPopElem()");
27407         goto internal_error;
27408     }
27409     goto exit;
27410     }
27411 exit:
27412     return;
27413 internal_error:
27414     vctxt->err = -1;
27415     xmlStopParser(vctxt->parserCtxt);
27416     return;
27417 }
27418 
27419 /************************************************************************
27420  *                                  *
27421  *          Validation interfaces               *
27422  *                                  *
27423  ************************************************************************/
27424 
27433 xmlSchemaValidCtxtPtr
27434 xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27435 {
27436     xmlSchemaValidCtxtPtr ret;
27437 
27438     ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27439     if (ret == NULL) {
27440         xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
27441         return (NULL);
27442     }
27443     memset(ret, 0, sizeof(xmlSchemaValidCtxt));
27444     ret->type = XML_SCHEMA_CTXT_VALIDATOR;
27445     ret->dict = xmlDictCreate();
27446     ret->nodeQNames = xmlSchemaItemListCreate();
27447     ret->schema = schema;
27448     return (ret);
27449 }
27450 
27458 static void
27459 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27460 {
27461     if (vctxt == NULL)
27462         return;
27463 
27464     /*
27465     * TODO: Should we clear the flags?
27466     *   Might be problematic if one reuses the context
27467     *   and assumes that the options remain the same.
27468     */
27469     vctxt->flags = 0;
27470     vctxt->validationRoot = NULL;
27471     vctxt->doc = NULL;
27472 #ifdef LIBXML_READER_ENABLED
27473     vctxt->reader = NULL;
27474 #endif
27475     vctxt->hasKeyrefs = 0;
27476 
27477     if (vctxt->value != NULL) {
27478         xmlSchemaFreeValue(vctxt->value);
27479     vctxt->value = NULL;
27480     }
27481     /*
27482     * Augmented IDC information.
27483     */
27484     if (vctxt->aidcs != NULL) {
27485     xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27486     do {
27487         next = cur->next;
27488         xmlFree(cur);
27489         cur = next;
27490     } while (cur != NULL);
27491     vctxt->aidcs = NULL;
27492     }
27493     if (vctxt->idcMatcherCache != NULL) {
27494     xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp;
27495 
27496     while (matcher) {
27497         tmp = matcher;
27498         matcher = matcher->nextCached;
27499         xmlSchemaIDCFreeMatcherList(tmp);
27500     }
27501     vctxt->idcMatcherCache = NULL;
27502     }
27503 
27504 
27505     if (vctxt->idcNodes != NULL) {
27506     int i;
27507     xmlSchemaPSVIIDCNodePtr item;
27508 
27509     for (i = 0; i < vctxt->nbIdcNodes; i++) {
27510         item = vctxt->idcNodes[i];
27511         xmlFree(item->keys);
27512         xmlFree(item);
27513     }
27514     xmlFree(vctxt->idcNodes);
27515     vctxt->idcNodes = NULL;
27516     vctxt->nbIdcNodes = 0;
27517     vctxt->sizeIdcNodes = 0;
27518     }
27519     /*
27520     * Note that we won't delete the XPath state pool here.
27521     */
27522     if (vctxt->xpathStates != NULL) {
27523     xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27524     vctxt->xpathStates = NULL;
27525     }
27526     /*
27527     * Attribute info.
27528     */
27529     if (vctxt->nbAttrInfos != 0) {
27530     xmlSchemaClearAttrInfos(vctxt);
27531     }
27532     /*
27533     * Element info.
27534     */
27535     if (vctxt->elemInfos != NULL) {
27536     int i;
27537     xmlSchemaNodeInfoPtr ei;
27538 
27539     for (i = 0; i < vctxt->sizeElemInfos; i++) {
27540         ei = vctxt->elemInfos[i];
27541         if (ei == NULL)
27542         break;
27543         xmlSchemaClearElemInfo(vctxt, ei);
27544     }
27545     }
27546     xmlSchemaItemListClear(vctxt->nodeQNames);
27547     /* Recreate the dict. */
27548     xmlDictFree(vctxt->dict);
27549     /*
27550     * TODO: Is is save to recreate it? Do we have a scenario
27551     * where the user provides the dict?
27552     */
27553     vctxt->dict = xmlDictCreate();
27554 }
27555 
27562 void
27563 xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27564 {
27565     if (ctxt == NULL)
27566         return;
27567     if (ctxt->value != NULL)
27568         xmlSchemaFreeValue(ctxt->value);
27569     if (ctxt->pctxt != NULL)
27570     xmlSchemaFreeParserCtxt(ctxt->pctxt);
27571     if (ctxt->idcNodes != NULL) {
27572     int i;
27573     xmlSchemaPSVIIDCNodePtr item;
27574 
27575     for (i = 0; i < ctxt->nbIdcNodes; i++) {
27576         item = ctxt->idcNodes[i];
27577         xmlFree(item->keys);
27578         xmlFree(item);
27579     }
27580     xmlFree(ctxt->idcNodes);
27581     }
27582     if (ctxt->idcKeys != NULL) {
27583     int i;
27584     for (i = 0; i < ctxt->nbIdcKeys; i++)
27585         xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27586     xmlFree(ctxt->idcKeys);
27587     }
27588 
27589     if (ctxt->xpathStates != NULL) {
27590     xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27591     ctxt->xpathStates = NULL;
27592     }
27593     if (ctxt->xpathStatePool != NULL) {
27594     xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27595     ctxt->xpathStatePool = NULL;
27596     }
27597 
27598     /*
27599     * Augmented IDC information.
27600     */
27601     if (ctxt->aidcs != NULL) {
27602     xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27603     do {
27604         next = cur->next;
27605         xmlFree(cur);
27606         cur = next;
27607     } while (cur != NULL);
27608     }
27609     if (ctxt->attrInfos != NULL) {
27610     int i;
27611     xmlSchemaAttrInfoPtr attr;
27612 
27613     /* Just a paranoid call to the cleanup. */
27614     if (ctxt->nbAttrInfos != 0)
27615         xmlSchemaClearAttrInfos(ctxt);
27616     for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27617         attr = ctxt->attrInfos[i];
27618         xmlFree(attr);
27619     }
27620     xmlFree(ctxt->attrInfos);
27621     }
27622     if (ctxt->elemInfos != NULL) {
27623     int i;
27624     xmlSchemaNodeInfoPtr ei;
27625 
27626     for (i = 0; i < ctxt->sizeElemInfos; i++) {
27627         ei = ctxt->elemInfos[i];
27628         if (ei == NULL)
27629         break;
27630         xmlSchemaClearElemInfo(ctxt, ei);
27631         xmlFree(ei);
27632     }
27633     xmlFree(ctxt->elemInfos);
27634     }
27635     if (ctxt->nodeQNames != NULL)
27636     xmlSchemaItemListFree(ctxt->nodeQNames);
27637     if (ctxt->dict != NULL)
27638     xmlDictFree(ctxt->dict);
27639     xmlFree(ctxt);
27640 }
27641 
27651 int
27652 xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27653 {
27654     if (ctxt == NULL)
27655         return(-1);
27656     return(ctxt->err == 0);
27657 }
27658 
27668 void
27669 xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27670                         xmlSchemaValidityErrorFunc err,
27671                         xmlSchemaValidityWarningFunc warn, void *ctx)
27672 {
27673     if (ctxt == NULL)
27674         return;
27675     ctxt->error = err;
27676     ctxt->warning = warn;
27677     ctxt->errCtxt = ctx;
27678     if (ctxt->pctxt != NULL)
27679     xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
27680 }
27681 
27690 void
27691 xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
27692                   xmlStructuredErrorFunc serror, void *ctx)
27693 {
27694     if (ctxt == NULL)
27695         return;
27696     ctxt->serror = serror;
27697     ctxt->error = NULL;
27698     ctxt->warning = NULL;
27699     ctxt->errCtxt = ctx;
27700     if (ctxt->pctxt != NULL)
27701     xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
27702 }
27703 
27715 int
27716 xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27717             xmlSchemaValidityErrorFunc * err,
27718             xmlSchemaValidityWarningFunc * warn, void **ctx)
27719 {
27720     if (ctxt == NULL)
27721         return (-1);
27722     if (err != NULL)
27723         *err = ctxt->error;
27724     if (warn != NULL)
27725         *warn = ctxt->warning;
27726     if (ctx != NULL)
27727         *ctx = ctxt->errCtxt;
27728     return (0);
27729 }
27730 
27731 
27742 int
27743 xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27744              int options)
27745 
27746 {
27747     int i;
27748 
27749     if (ctxt == NULL)
27750     return (-1);
27751     /*
27752     * WARNING: Change the start value if adding to the
27753     * xmlSchemaValidOption.
27754     * TODO: Is there an other, more easy to maintain,
27755     * way?
27756     */
27757     for (i = 1; i < (int) sizeof(int) * 8; i++) {
27758         if (options & 1<<i)
27759         return (-1);
27760     }
27761     ctxt->options = options;
27762     return (0);
27763 }
27764 
27773 int
27774 xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
27775 
27776 {
27777     if (ctxt == NULL)
27778     return (-1);
27779     else
27780     return (ctxt->options);
27781 }
27782 
27783 static int
27784 xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27785 {
27786     xmlAttrPtr attr;
27787     int ret = 0;
27788     xmlSchemaNodeInfoPtr ielem = NULL;
27789     xmlNodePtr node, valRoot;
27790     const xmlChar *nsName;
27791 
27792     /* DOC VAL TODO: Move this to the start function. */
27793     valRoot = xmlDocGetRootElement(vctxt->doc);
27794     if (valRoot == NULL) {
27795     /* VAL TODO: Error code? */
27796     VERROR(1, NULL, "The document has no document element");
27797     return (1);
27798     }
27799     vctxt->depth = -1;
27800     vctxt->validationRoot = valRoot;
27801     node = valRoot;
27802     while (node != NULL) {
27803     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27804         goto next_sibling;
27805     if (node->type == XML_ELEMENT_NODE) {
27806 
27807         /*
27808         * Init the node-info.
27809         */
27810         vctxt->depth++;
27811         if (xmlSchemaValidatorPushElem(vctxt) == -1)
27812         goto internal_error;
27813         ielem = vctxt->inode;
27814         ielem->node = node;
27815         ielem->nodeLine = node->line;
27816         ielem->localName = node->name;
27817         if (node->ns != NULL)
27818         ielem->nsName = node->ns->href;
27819         ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27820         /*
27821         * Register attributes.
27822         * DOC VAL TODO: We do not register namespace declaration
27823         * attributes yet.
27824         */
27825         vctxt->nbAttrInfos = 0;
27826         if (node->properties != NULL) {
27827         attr = node->properties;
27828         do {
27829             if (attr->ns != NULL)
27830             nsName = attr->ns->href;
27831             else
27832             nsName = NULL;
27833             ret = xmlSchemaValidatorPushAttribute(vctxt,
27834             (xmlNodePtr) attr,
27835             /*
27836             * Note that we give it the line number of the
27837             * parent element.
27838             */
27839             ielem->nodeLine,
27840             attr->name, nsName, 0,
27841             xmlNodeListGetString(attr->doc, attr->children, 1), 1);
27842             if (ret == -1) {
27843             VERROR_INT("xmlSchemaDocWalk",
27844                 "calling xmlSchemaValidatorPushAttribute()");
27845             goto internal_error;
27846             }
27847             attr = attr->next;
27848         } while (attr);
27849         }
27850         /*
27851         * Validate the element.
27852         */
27853         ret = xmlSchemaValidateElem(vctxt);
27854         if (ret != 0) {
27855         if (ret == -1) {
27856             VERROR_INT("xmlSchemaDocWalk",
27857             "calling xmlSchemaValidateElem()");
27858             goto internal_error;
27859         }
27860         /*
27861         * Don't stop validation; just skip the content
27862         * of this element.
27863         */
27864         goto leave_node;
27865         }
27866         if ((vctxt->skipDepth != -1) &&
27867         (vctxt->depth >= vctxt->skipDepth))
27868         goto leave_node;
27869     } else if ((node->type == XML_TEXT_NODE) ||
27870         (node->type == XML_CDATA_SECTION_NODE)) {
27871         /*
27872         * Process character content.
27873         */
27874         if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
27875         ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27876         ret = xmlSchemaVPushText(vctxt, node->type, node->content,
27877         -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
27878         if (ret < 0) {
27879         VERROR_INT("xmlSchemaVDocWalk",
27880             "calling xmlSchemaVPushText()");
27881         goto internal_error;
27882         }
27883         /*
27884         * DOC VAL TODO: Should we skip further validation of the
27885         * element content here?
27886         */
27887     } else if ((node->type == XML_ENTITY_NODE) ||
27888         (node->type == XML_ENTITY_REF_NODE)) {
27889         /*
27890         * DOC VAL TODO: What to do with entities?
27891         */
27892         VERROR_INT("xmlSchemaVDocWalk",
27893         "there is at least one entity reference in the node-tree "
27894         "currently being validated. Processing of entities with "
27895         "this XML Schema processor is not supported (yet). Please "
27896         "substitute entities before validation.");
27897         goto internal_error;
27898     } else {
27899         goto leave_node;
27900         /*
27901         * DOC VAL TODO: XInclude nodes, etc.
27902         */
27903     }
27904     /*
27905     * Walk the doc.
27906     */
27907     if (node->children != NULL) {
27908         node = node->children;
27909         continue;
27910     }
27911 leave_node:
27912     if (node->type == XML_ELEMENT_NODE) {
27913         /*
27914         * Leaving the scope of an element.
27915         */
27916         if (node != vctxt->inode->node) {
27917         VERROR_INT("xmlSchemaVDocWalk",
27918             "element position mismatch");
27919         goto internal_error;
27920         }
27921         ret = xmlSchemaValidatorPopElem(vctxt);
27922         if (ret != 0) {
27923         if (ret < 0) {
27924             VERROR_INT("xmlSchemaVDocWalk",
27925             "calling xmlSchemaValidatorPopElem()");
27926             goto internal_error;
27927         }
27928         }
27929         if (node == valRoot)
27930         goto exit;
27931     }
27932 next_sibling:
27933     if (node->next != NULL)
27934         node = node->next;
27935     else {
27936         node = node->parent;
27937         goto leave_node;
27938     }
27939     }
27940 
27941 exit:
27942     return (ret);
27943 internal_error:
27944     return (-1);
27945 }
27946 
27947 static int
27948 xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
27949     /*
27950     * Some initialization.
27951     */
27952     vctxt->err = 0;
27953     vctxt->nberrors = 0;
27954     vctxt->depth = -1;
27955     vctxt->skipDepth = -1;
27956     vctxt->xsiAssemble = 0;
27957     vctxt->hasKeyrefs = 0;
27958 #ifdef ENABLE_IDC_NODE_TABLES_TEST
27959     vctxt->createIDCNodeTables = 1;
27960 #else
27961     vctxt->createIDCNodeTables = 0;
27962 #endif
27963     /*
27964     * Create a schema + parser if necessary.
27965     */
27966     if (vctxt->schema == NULL) {
27967     xmlSchemaParserCtxtPtr pctxt;
27968 
27969     vctxt->xsiAssemble = 1;
27970     /*
27971     * If not schema was given then we will create a schema
27972     * dynamically using XSI schema locations.
27973     *
27974     * Create the schema parser context.
27975     */
27976     if ((vctxt->pctxt == NULL) &&
27977        (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
27978        return (-1);
27979     pctxt = vctxt->pctxt;
27980     pctxt->xsiAssemble = 1;
27981     /*
27982     * Create the schema.
27983     */
27984     vctxt->schema = xmlSchemaNewSchema(pctxt);
27985     if (vctxt->schema == NULL)
27986         return (-1);
27987     /*
27988     * Create the schema construction context.
27989     */
27990     pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
27991     if (pctxt->constructor == NULL)
27992         return(-1);
27993     pctxt->constructor->mainSchema = vctxt->schema;
27994     /*
27995     * Take ownership of the constructor to be able to free it.
27996     */
27997     pctxt->ownsConstructor = 1;
27998     }
27999     /*
28000     * Augment the IDC definitions for the main schema and all imported ones
28001     * NOTE: main schema if the first in the imported list
28002     */
28003     xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt);
28004 
28005     return(0);
28006 }
28007 
28008 static void
28009 xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
28010     if (vctxt->xsiAssemble) {
28011     if (vctxt->schema != NULL) {
28012         xmlSchemaFree(vctxt->schema);
28013         vctxt->schema = NULL;
28014     }
28015     }
28016     xmlSchemaClearValidCtxt(vctxt);
28017 }
28018 
28019 static int
28020 xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
28021 {
28022     int ret = 0;
28023 
28024     if (xmlSchemaPreRun(vctxt) < 0)
28025         return(-1);
28026 
28027     if (vctxt->doc != NULL) {
28028     /*
28029      * Tree validation.
28030      */
28031     ret = xmlSchemaVDocWalk(vctxt);
28032 #ifdef LIBXML_READER_ENABLED
28033     } else if (vctxt->reader != NULL) {
28034     /*
28035      * XML Reader validation.
28036      */
28037 #ifdef XML_SCHEMA_READER_ENABLED
28038     ret = xmlSchemaVReaderWalk(vctxt);
28039 #endif
28040 #endif
28041     } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
28042     /*
28043      * SAX validation.
28044      */
28045     ret = xmlParseDocument(vctxt->parserCtxt);
28046     } else {
28047     VERROR_INT("xmlSchemaVStart",
28048         "no instance to validate");
28049     ret = -1;
28050     }
28051 
28052     xmlSchemaPostRun(vctxt);
28053     if (ret == 0)
28054     ret = vctxt->err;
28055     return (ret);
28056 }
28057 
28068 int
28069 xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
28070 {
28071     if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
28072     return (-1);
28073 
28074     if (ctxt->schema == NULL)
28075     return (-1);
28076 
28077     ctxt->doc = elem->doc;
28078     ctxt->node = elem;
28079     ctxt->validationRoot = elem;
28080     return(xmlSchemaVStart(ctxt));
28081 }
28082 
28093 int
28094 xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
28095 {
28096     if ((ctxt == NULL) || (doc == NULL))
28097         return (-1);
28098 
28099     ctxt->doc = doc;
28100     ctxt->node = xmlDocGetRootElement(doc);
28101     if (ctxt->node == NULL) {
28102         xmlSchemaCustomErr(ACTXT_CAST ctxt,
28103         XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
28104         (xmlNodePtr) doc, NULL,
28105         "The document has no document element", NULL, NULL);
28106         return (ctxt->err);
28107     }
28108     ctxt->validationRoot = ctxt->node;
28109     return (xmlSchemaVStart(ctxt));
28110 }
28111 
28112 
28113 /************************************************************************
28114  *                                  *
28115  *      Function and data for SAX streaming API         *
28116  *                                  *
28117  ************************************************************************/
28118 typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
28119 typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
28120 
28121 struct _xmlSchemaSplitSAXData {
28122     xmlSAXHandlerPtr      user_sax;
28123     void                 *user_data;
28124     xmlSchemaValidCtxtPtr ctxt;
28125     xmlSAXHandlerPtr      schemas_sax;
28126 };
28127 
28128 #define XML_SAX_PLUG_MAGIC 0xdc43ba21
28129 
28130 struct _xmlSchemaSAXPlug {
28131     unsigned int magic;
28132 
28133     /* the original callbacks informations */
28134     xmlSAXHandlerPtr     *user_sax_ptr;
28135     xmlSAXHandlerPtr      user_sax;
28136     void                **user_data_ptr;
28137     void                 *user_data;
28138 
28139     /* the block plugged back and validation informations */
28140     xmlSAXHandler         schemas_sax;
28141     xmlSchemaValidCtxtPtr ctxt;
28142 };
28143 
28144 /* All those functions just bounces to the user provided SAX handlers */
28145 static void
28146 internalSubsetSplit(void *ctx, const xmlChar *name,
28147            const xmlChar *ExternalID, const xmlChar *SystemID)
28148 {
28149     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28150     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28151         (ctxt->user_sax->internalSubset != NULL))
28152     ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
28153                                    SystemID);
28154 }
28155 
28156 static int
28157 isStandaloneSplit(void *ctx)
28158 {
28159     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28160     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28161         (ctxt->user_sax->isStandalone != NULL))
28162     return(ctxt->user_sax->isStandalone(ctxt->user_data));
28163     return(0);
28164 }
28165 
28166 static int
28167 hasInternalSubsetSplit(void *ctx)
28168 {
28169     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28170     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28171         (ctxt->user_sax->hasInternalSubset != NULL))
28172     return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
28173     return(0);
28174 }
28175 
28176 static int
28177 hasExternalSubsetSplit(void *ctx)
28178 {
28179     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28180     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28181         (ctxt->user_sax->hasExternalSubset != NULL))
28182     return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
28183     return(0);
28184 }
28185 
28186 static void
28187 externalSubsetSplit(void *ctx, const xmlChar *name,
28188            const xmlChar *ExternalID, const xmlChar *SystemID)
28189 {
28190     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28191     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28192         (ctxt->user_sax->externalSubset != NULL))
28193     ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID,
28194                                    SystemID);
28195 }
28196 
28197 static xmlParserInputPtr
28198 resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
28199 {
28200     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28201     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28202         (ctxt->user_sax->resolveEntity != NULL))
28203     return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
28204                                          systemId));
28205     return(NULL);
28206 }
28207 
28208 static xmlEntityPtr
28209 getEntitySplit(void *ctx, const xmlChar *name)
28210 {
28211     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28212     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28213         (ctxt->user_sax->getEntity != NULL))
28214     return(ctxt->user_sax->getEntity(ctxt->user_data, name));
28215     return(NULL);
28216 }
28217 
28218 static xmlEntityPtr
28219 getParameterEntitySplit(void *ctx, const xmlChar *name)
28220 {
28221     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28222     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28223         (ctxt->user_sax->getParameterEntity != NULL))
28224     return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
28225     return(NULL);
28226 }
28227 
28228 
28229 static void
28230 entityDeclSplit(void *ctx, const xmlChar *name, int type,
28231           const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
28232 {
28233     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28234     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28235         (ctxt->user_sax->entityDecl != NULL))
28236     ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
28237                                systemId, content);
28238 }
28239 
28240 static void
28241 attributeDeclSplit(void *ctx, const xmlChar * elem,
28242                    const xmlChar * name, int type, int def,
28243                    const xmlChar * defaultValue, xmlEnumerationPtr tree)
28244 {
28245     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28246     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28247         (ctxt->user_sax->attributeDecl != NULL)) {
28248     ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
28249                                   def, defaultValue, tree);
28250     } else {
28251     xmlFreeEnumeration(tree);
28252     }
28253 }
28254 
28255 static void
28256 elementDeclSplit(void *ctx, const xmlChar *name, int type,
28257         xmlElementContentPtr content)
28258 {
28259     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28260     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28261         (ctxt->user_sax->elementDecl != NULL))
28262     ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
28263 }
28264 
28265 static void
28266 notationDeclSplit(void *ctx, const xmlChar *name,
28267          const xmlChar *publicId, const xmlChar *systemId)
28268 {
28269     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28270     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28271         (ctxt->user_sax->notationDecl != NULL))
28272     ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
28273                                  systemId);
28274 }
28275 
28276 static void
28277 unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
28278            const xmlChar *publicId, const xmlChar *systemId,
28279            const xmlChar *notationName)
28280 {
28281     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28282     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28283         (ctxt->user_sax->unparsedEntityDecl != NULL))
28284     ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
28285                                        systemId, notationName);
28286 }
28287 
28288 static void
28289 setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
28290 {
28291     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28292     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28293         (ctxt->user_sax->setDocumentLocator != NULL))
28294     ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
28295 }
28296 
28297 static void
28298 startDocumentSplit(void *ctx)
28299 {
28300     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28301     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28302         (ctxt->user_sax->startDocument != NULL))
28303     ctxt->user_sax->startDocument(ctxt->user_data);
28304 }
28305 
28306 static void
28307 endDocumentSplit(void *ctx)
28308 {
28309     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28310     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28311         (ctxt->user_sax->endDocument != NULL))
28312     ctxt->user_sax->endDocument(ctxt->user_data);
28313 }
28314 
28315 static void
28316 processingInstructionSplit(void *ctx, const xmlChar *target,
28317                       const xmlChar *data)
28318 {
28319     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28320     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28321         (ctxt->user_sax->processingInstruction != NULL))
28322     ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
28323 }
28324 
28325 static void
28326 commentSplit(void *ctx, const xmlChar *value)
28327 {
28328     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28329     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28330         (ctxt->user_sax->comment != NULL))
28331     ctxt->user_sax->comment(ctxt->user_data, value);
28332 }
28333 
28334 /*
28335  * Varargs error callbacks to the user application, harder ...
28336  */
28337 
28338 static void XMLCDECL
28339 warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28340     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28341     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28342         (ctxt->user_sax->warning != NULL)) {
28343     TODO
28344     }
28345 }
28346 static void XMLCDECL
28347 errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28348     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28349     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28350         (ctxt->user_sax->error != NULL)) {
28351     TODO
28352     }
28353 }
28354 static void XMLCDECL
28355 fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28356     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28357     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28358         (ctxt->user_sax->fatalError != NULL)) {
28359     TODO
28360     }
28361 }
28362 
28363 /*
28364  * Those are function where both the user handler and the schemas handler
28365  * need to be called.
28366  */
28367 static void
28368 charactersSplit(void *ctx, const xmlChar *ch, int len)
28369 {
28370     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28371     if (ctxt == NULL)
28372         return;
28373     if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
28374     ctxt->user_sax->characters(ctxt->user_data, ch, len);
28375     if (ctxt->ctxt != NULL)
28376     xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28377 }
28378 
28379 static void
28380 ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
28381 {
28382     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28383     if (ctxt == NULL)
28384         return;
28385     if ((ctxt->user_sax != NULL) &&
28386         (ctxt->user_sax->ignorableWhitespace != NULL))
28387     ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
28388     if (ctxt->ctxt != NULL)
28389     xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28390 }
28391 
28392 static void
28393 cdataBlockSplit(void *ctx, const xmlChar *value, int len)
28394 {
28395     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28396     if (ctxt == NULL)
28397         return;
28398     if ((ctxt->user_sax != NULL) &&
28399         (ctxt->user_sax->cdataBlock != NULL))
28400     ctxt->user_sax->cdataBlock(ctxt->user_data, value, len);
28401     if (ctxt->ctxt != NULL)
28402     xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28403 }
28404 
28405 static void
28406 referenceSplit(void *ctx, const xmlChar *name)
28407 {
28408     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28409     if (ctxt == NULL)
28410         return;
28411     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28412         (ctxt->user_sax->reference != NULL))
28413     ctxt->user_sax->reference(ctxt->user_data, name);
28414     if (ctxt->ctxt != NULL)
28415         xmlSchemaSAXHandleReference(ctxt->user_data, name);
28416 }
28417 
28418 static void
28419 startElementNsSplit(void *ctx, const xmlChar * localname,
28420             const xmlChar * prefix, const xmlChar * URI,
28421             int nb_namespaces, const xmlChar ** namespaces,
28422             int nb_attributes, int nb_defaulted,
28423             const xmlChar ** attributes) {
28424     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28425     if (ctxt == NULL)
28426         return;
28427     if ((ctxt->user_sax != NULL) &&
28428         (ctxt->user_sax->startElementNs != NULL))
28429     ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28430                                    URI, nb_namespaces, namespaces,
28431                        nb_attributes, nb_defaulted,
28432                        attributes);
28433     if (ctxt->ctxt != NULL)
28434     xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28435                                      URI, nb_namespaces, namespaces,
28436                      nb_attributes, nb_defaulted,
28437                      attributes);
28438 }
28439 
28440 static void
28441 endElementNsSplit(void *ctx, const xmlChar * localname,
28442             const xmlChar * prefix, const xmlChar * URI) {
28443     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28444     if (ctxt == NULL)
28445         return;
28446     if ((ctxt->user_sax != NULL) &&
28447         (ctxt->user_sax->endElementNs != NULL))
28448     ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28449     if (ctxt->ctxt != NULL)
28450     xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28451 }
28452 
28466 xmlSchemaSAXPlugPtr
28467 xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28468          xmlSAXHandlerPtr *sax, void **user_data)
28469 {
28470     xmlSchemaSAXPlugPtr ret;
28471     xmlSAXHandlerPtr old_sax;
28472 
28473     if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28474         return(NULL);
28475 
28476     /*
28477      * We only allow to plug into SAX2 event streams
28478      */
28479     old_sax = *sax;
28480     if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28481         return(NULL);
28482     if ((old_sax != NULL) &&
28483         (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28484         ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28485         return(NULL);
28486 
28487     /*
28488      * everything seems right allocate the local data needed for that layer
28489      */
28490     ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28491     if (ret == NULL) {
28492         return(NULL);
28493     }
28494     memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28495     ret->magic = XML_SAX_PLUG_MAGIC;
28496     ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28497     ret->ctxt = ctxt;
28498     ret->user_sax_ptr = sax;
28499     ret->user_sax = old_sax;
28500     if (old_sax == NULL) {
28501         /*
28502      * go direct, no need for the split block and functions.
28503      */
28504     ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28505     ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28506     /*
28507      * Note that we use the same text-function for both, to prevent
28508      * the parser from testing for ignorable whitespace.
28509      */
28510     ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28511     ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28512 
28513     ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28514     ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28515 
28516     ret->user_data = ctxt;
28517     *user_data = ctxt;
28518     } else {
28519        /*
28520         * for each callback unused by Schemas initialize it to the Split
28521     * routine only if non NULL in the user block, this can speed up
28522     * things at the SAX level.
28523     */
28524         if (old_sax->internalSubset != NULL)
28525             ret->schemas_sax.internalSubset = internalSubsetSplit;
28526         if (old_sax->isStandalone != NULL)
28527             ret->schemas_sax.isStandalone = isStandaloneSplit;
28528         if (old_sax->hasInternalSubset != NULL)
28529             ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28530         if (old_sax->hasExternalSubset != NULL)
28531             ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28532         if (old_sax->resolveEntity != NULL)
28533             ret->schemas_sax.resolveEntity = resolveEntitySplit;
28534         if (old_sax->getEntity != NULL)
28535             ret->schemas_sax.getEntity = getEntitySplit;
28536         if (old_sax->entityDecl != NULL)
28537             ret->schemas_sax.entityDecl = entityDeclSplit;
28538         if (old_sax->notationDecl != NULL)
28539             ret->schemas_sax.notationDecl = notationDeclSplit;
28540         if (old_sax->attributeDecl != NULL)
28541             ret->schemas_sax.attributeDecl = attributeDeclSplit;
28542         if (old_sax->elementDecl != NULL)
28543             ret->schemas_sax.elementDecl = elementDeclSplit;
28544         if (old_sax->unparsedEntityDecl != NULL)
28545             ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28546         if (old_sax->setDocumentLocator != NULL)
28547             ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28548         if (old_sax->startDocument != NULL)
28549             ret->schemas_sax.startDocument = startDocumentSplit;
28550         if (old_sax->endDocument != NULL)
28551             ret->schemas_sax.endDocument = endDocumentSplit;
28552         if (old_sax->processingInstruction != NULL)
28553             ret->schemas_sax.processingInstruction = processingInstructionSplit;
28554         if (old_sax->comment != NULL)
28555             ret->schemas_sax.comment = commentSplit;
28556         if (old_sax->warning != NULL)
28557             ret->schemas_sax.warning = warningSplit;
28558         if (old_sax->error != NULL)
28559             ret->schemas_sax.error = errorSplit;
28560         if (old_sax->fatalError != NULL)
28561             ret->schemas_sax.fatalError = fatalErrorSplit;
28562         if (old_sax->getParameterEntity != NULL)
28563             ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28564         if (old_sax->externalSubset != NULL)
28565             ret->schemas_sax.externalSubset = externalSubsetSplit;
28566 
28567     /*
28568      * the 6 schemas callback have to go to the splitter functions
28569      * Note that we use the same text-function for ignorableWhitespace
28570      * if possible, to prevent the parser from testing for ignorable
28571      * whitespace.
28572      */
28573         ret->schemas_sax.characters = charactersSplit;
28574     if ((old_sax->ignorableWhitespace != NULL) &&
28575         (old_sax->ignorableWhitespace != old_sax->characters))
28576         ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28577     else
28578         ret->schemas_sax.ignorableWhitespace = charactersSplit;
28579         ret->schemas_sax.cdataBlock = cdataBlockSplit;
28580         ret->schemas_sax.reference = referenceSplit;
28581         ret->schemas_sax.startElementNs = startElementNsSplit;
28582         ret->schemas_sax.endElementNs = endElementNsSplit;
28583 
28584     ret->user_data_ptr = user_data;
28585     ret->user_data = *user_data;
28586     *user_data = ret;
28587     }
28588 
28589     /*
28590      * plug the pointers back.
28591      */
28592     *sax = &(ret->schemas_sax);
28593     ctxt->sax = *sax;
28594     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28595     xmlSchemaPreRun(ctxt);
28596     return(ret);
28597 }
28598 
28608 int
28609 xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28610 {
28611     xmlSAXHandlerPtr *sax;
28612     void **user_data;
28613 
28614     if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28615         return(-1);
28616     plug->magic = 0;
28617 
28618     xmlSchemaPostRun(plug->ctxt);
28619     /* restore the data */
28620     sax = plug->user_sax_ptr;
28621     *sax = plug->user_sax;
28622     if (plug->user_sax != NULL) {
28623     user_data = plug->user_data_ptr;
28624     *user_data = plug->user_data;
28625     }
28626 
28627     /* free and return */
28628     xmlFree(plug);
28629     return(0);
28630 }
28631 
28647 int
28648 xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
28649                         xmlParserInputBufferPtr input, xmlCharEncoding enc,
28650                         xmlSAXHandlerPtr sax, void *user_data)
28651 {
28652     xmlSchemaSAXPlugPtr plug = NULL;
28653     xmlSAXHandlerPtr old_sax = NULL;
28654     xmlParserCtxtPtr pctxt = NULL;
28655     xmlParserInputPtr inputStream = NULL;
28656     int ret;
28657 
28658     if ((ctxt == NULL) || (input == NULL))
28659         return (-1);
28660 
28661     /*
28662      * prepare the parser
28663      */
28664     pctxt = xmlNewParserCtxt();
28665     if (pctxt == NULL)
28666         return (-1);
28667     old_sax = pctxt->sax;
28668     pctxt->sax = sax;
28669     pctxt->userData = user_data;
28670 #if 0
28671     if (options)
28672         xmlCtxtUseOptions(pctxt, options);
28673 #endif
28674     pctxt->linenumbers = 1;
28675 
28676     inputStream = xmlNewIOInputStream(pctxt, input, enc);;
28677     if (inputStream == NULL) {
28678         ret = -1;
28679     goto done;
28680     }
28681     inputPush(pctxt, inputStream);
28682     ctxt->parserCtxt = pctxt;
28683     ctxt->input = input;
28684 
28685     /*
28686      * Plug the validation and launch the parsing
28687      */
28688     plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28689     if (plug == NULL) {
28690         ret = -1;
28691     goto done;
28692     }
28693     ctxt->input = input;
28694     ctxt->enc = enc;
28695     ctxt->sax = pctxt->sax;
28696     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28697     ret = xmlSchemaVStart(ctxt);
28698 
28699     if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28700     ret = ctxt->parserCtxt->errNo;
28701     if (ret == 0)
28702         ret = 1;
28703     }
28704 
28705 done:
28706     ctxt->parserCtxt = NULL;
28707     ctxt->sax = NULL;
28708     ctxt->input = NULL;
28709     if (plug != NULL) {
28710         xmlSchemaSAXUnplug(plug);
28711     }
28712     /* cleanup */
28713     if (pctxt != NULL) {
28714     pctxt->sax = old_sax;
28715     xmlFreeParserCtxt(pctxt);
28716     }
28717     return (ret);
28718 }
28719 
28732 int
28733 xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
28734                       const char * filename,
28735               int options ATTRIBUTE_UNUSED)
28736 {
28737     int ret;
28738     xmlParserInputBufferPtr input;
28739 
28740     if ((ctxt == NULL) || (filename == NULL))
28741         return (-1);
28742 
28743     input = xmlParserInputBufferCreateFilename(filename,
28744     XML_CHAR_ENCODING_NONE);
28745     if (input == NULL)
28746     return (-1);
28747     ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
28748     NULL, NULL);
28749     return (ret);
28750 }
28751 
28761 xmlParserCtxtPtr
28762 xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)
28763 {
28764     if (ctxt == NULL)
28765         return(NULL);
28766     return (ctxt->parserCtxt);
28767 }
28768 
28769 #define bottom_xmlschemas
28770 #include "elfgcchack.h"
28771 #endif /* LIBXML_SCHEMAS_ENABLED */

Generated on Sat May 26 2012 04:33:52 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.