Merge branch 'tizen_base' into tizen
[platform/upstream/libxml2.git] / xmlschemas.c
1 /*
2  * schemas.c : implementation of the XML Schema handling and
3  *             schema validity checking
4  *
5  * See Copyright for the status of this software.
6  *
7  * Daniel Veillard <veillard@redhat.com>
8  */
9
10 /*
11  * TODO:
12  *   - when types are redefined in includes, check that all
13  *     types in the redef list are equal
14  *     -> need a type equality operation.
15  *   - if we don't intend to use the schema for schemas, we
16  *     need to validate all schema attributes (ref, type, name)
17  *     against their types.
18  *   - Eliminate item creation for: ??
19  *
20  * URGENT TODO:
21  *   - For xsi-driven schema acquisition, augment the IDCs after every
22  *     acquisition episode (xmlSchemaAugmentIDC).
23  *
24  * NOTES:
25  *   - Elimated item creation for: <restriction>, <extension>,
26  *     <simpleContent>, <complexContent>, <list>, <union>
27  *
28  * PROBLEMS:
29  *   - http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0337.html
30  *     IDC XPath expression and chameleon includes: the targetNamespace is changed, so
31  *     XPath will have trouble to resolve to this namespace, since not known.
32  *
33  *
34  * CONSTRAINTS:
35  *
36  * Schema Component Constraint:
37  *   All Group Limited (cos-all-limited)
38  *   Status: complete
39  *   (1.2)
40  *     In xmlSchemaGroupDefReferenceTermFixup() and
41  *   (2)
42  *     In xmlSchemaParseModelGroup()
43  *     TODO: Actually this should go to component-level checks,
44  *     but is done here due to performance. Move it to an other layer
45  *     is schema construction via an API is implemented.
46  */
47
48 /* To avoid EBCDIC trouble when parsing on zOS */
49 #if defined(__MVS__)
50 #pragma convert("ISO8859-1")
51 #endif
52
53 #define IN_LIBXML
54 #include "libxml.h"
55
56 #ifdef LIBXML_SCHEMAS_ENABLED
57
58 #include <string.h>
59 #include <libxml/xmlmemory.h>
60 #include <libxml/parser.h>
61 #include <libxml/parserInternals.h>
62 #include <libxml/hash.h>
63 #include <libxml/uri.h>
64 #include <libxml/xmlschemas.h>
65 #include <libxml/schemasInternals.h>
66 #include <libxml/xmlschemastypes.h>
67 #include <libxml/xmlautomata.h>
68 #include <libxml/xmlregexp.h>
69 #include <libxml/dict.h>
70 #include <libxml/encoding.h>
71 #include <libxml/xmlIO.h>
72 #ifdef LIBXML_PATTERN_ENABLED
73 #include <libxml/pattern.h>
74 #endif
75 #ifdef LIBXML_READER_ENABLED
76 #include <libxml/xmlreader.h>
77 #endif
78
79 /* #define DEBUG 1 */
80
81 /* #define DEBUG_CONTENT 1 */
82
83 /* #define DEBUG_TYPE 1 */
84
85 /* #define DEBUG_CONTENT_REGEXP 1 */
86
87 /* #define DEBUG_AUTOMATA 1 */
88
89 /* #define DEBUG_IDC */
90
91 /* #define DEBUG_IDC_NODE_TABLE */
92
93 /* #define WXS_ELEM_DECL_CONS_ENABLED */
94
95 #ifdef DEBUG_IDC
96  #ifndef DEBUG_IDC_NODE_TABLE
97   #define DEBUG_IDC_NODE_TABLE
98  #endif
99 #endif
100
101 /* #define ENABLE_PARTICLE_RESTRICTION 1 */
102
103 #define ENABLE_REDEFINE
104
105 /* #define ENABLE_NAMED_LOCALS */
106
107 /* #define ENABLE_IDC_NODE_TABLES_TEST */
108
109 #define DUMP_CONTENT_MODEL
110
111 #ifdef LIBXML_READER_ENABLED
112 /* #define XML_SCHEMA_READER_ENABLED */
113 #endif
114
115 #define UNBOUNDED (1 << 30)
116 #define TODO                                                            \
117     xmlGenericError(xmlGenericErrorContext,                             \
118             "Unimplemented block at %s:%d\n",                           \
119             __FILE__, __LINE__);
120
121 #define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
122
123 /*
124  * The XML Schemas namespaces
125  */
126 static const xmlChar *xmlSchemaNs = (const xmlChar *)
127     "http://www.w3.org/2001/XMLSchema";
128
129 static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
130     "http://www.w3.org/2001/XMLSchema-instance";
131
132 static const xmlChar *xmlNamespaceNs = (const xmlChar *)
133     "http://www.w3.org/2000/xmlns/";
134
135 /*
136 * Come casting macros.
137 */
138 #define ACTXT_CAST (xmlSchemaAbstractCtxtPtr)
139 #define PCTXT_CAST (xmlSchemaParserCtxtPtr)
140 #define VCTXT_CAST (xmlSchemaValidCtxtPtr)
141 #define WXS_BASIC_CAST (xmlSchemaBasicItemPtr)
142 #define WXS_TREE_CAST (xmlSchemaTreeItemPtr)
143 #define WXS_PTC_CAST (xmlSchemaParticlePtr)
144 #define WXS_TYPE_CAST (xmlSchemaTypePtr)
145 #define WXS_ELEM_CAST (xmlSchemaElementPtr)
146 #define WXS_ATTR_GROUP_CAST (xmlSchemaAttributeGroupPtr)
147 #define WXS_ATTR_CAST (xmlSchemaAttributePtr)
148 #define WXS_ATTR_USE_CAST (xmlSchemaAttributeUsePtr)
149 #define WXS_ATTR_PROHIB_CAST (xmlSchemaAttributeUseProhibPtr)
150 #define WXS_MODEL_GROUPDEF_CAST (xmlSchemaModelGroupDefPtr)
151 #define WXS_MODEL_GROUP_CAST (xmlSchemaModelGroupPtr)
152 #define WXS_IDC_CAST (xmlSchemaIDCPtr)
153 #define WXS_QNAME_CAST (xmlSchemaQNameRefPtr)
154 #define WXS_LIST_CAST (xmlSchemaItemListPtr)
155
156 /*
157 * Macros to query common properties of components.
158 */
159 #define WXS_ITEM_NODE(i) xmlSchemaGetComponentNode(WXS_BASIC_CAST (i))
160
161 #define WXS_ITEM_TYPE_NAME(i) xmlSchemaGetComponentTypeStr(WXS_BASIC_CAST (i))
162 /*
163 * Macros for element declarations.
164 */
165 #define WXS_ELEM_TYPEDEF(e) (e)->subtypes
166
167 #define WXS_SUBST_HEAD(item) (item)->refDecl
168 /*
169 * Macros for attribute declarations.
170 */
171 #define WXS_ATTR_TYPEDEF(a) (a)->subtypes
172 /*
173 * Macros for attribute uses.
174 */
175 #define WXS_ATTRUSE_DECL(au) (WXS_ATTR_USE_CAST (au))->attrDecl
176
177 #define WXS_ATTRUSE_TYPEDEF(au) WXS_ATTR_TYPEDEF(WXS_ATTRUSE_DECL( WXS_ATTR_USE_CAST au))
178
179 #define WXS_ATTRUSE_DECL_NAME(au) (WXS_ATTRUSE_DECL(au))->name
180
181 #define WXS_ATTRUSE_DECL_TNS(au) (WXS_ATTRUSE_DECL(au))->targetNamespace
182 /*
183 * Macros for attribute groups.
184 */
185 #define WXS_ATTR_GROUP_HAS_REFS(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS)
186 #define WXS_ATTR_GROUP_EXPANDED(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED)
187 /*
188 * Macros for particles.
189 */
190 #define WXS_PARTICLE(p) WXS_PTC_CAST (p)
191
192 #define WXS_PARTICLE_TERM(p) (WXS_PARTICLE(p))->children
193
194 #define WXS_PARTICLE_TERM_AS_ELEM(p) (WXS_ELEM_CAST WXS_PARTICLE_TERM(p))
195
196 #define WXS_PARTICLE_MODEL(p) WXS_MODEL_GROUP_CAST WXS_PARTICLE(p)->children
197 /*
198 * Macros for model groups definitions.
199 */
200 #define WXS_MODELGROUPDEF_MODEL(mgd) (WXS_MODEL_GROUP_CAST (mgd))->children
201 /*
202 * Macros for model groups.
203 */
204 #define WXS_IS_MODEL_GROUP(i) \
205     (((i)->type == XML_SCHEMA_TYPE_SEQUENCE) || \
206      ((i)->type == XML_SCHEMA_TYPE_CHOICE) || \
207      ((i)->type == XML_SCHEMA_TYPE_ALL))
208
209 #define WXS_MODELGROUP_PARTICLE(mg) WXS_PTC_CAST (mg)->children
210 /*
211 * Macros for schema buckets.
212 */
213 #define WXS_IS_BUCKET_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \
214     ((t) == XML_SCHEMA_SCHEMA_REDEFINE))
215
216 #define WXS_IS_BUCKET_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \
217     ((t) == XML_SCHEMA_SCHEMA_IMPORT))
218
219 #define WXS_IMPBUCKET(b) ((xmlSchemaImportPtr) (b))
220
221 #define WXS_INCBUCKET(b) ((xmlSchemaIncludePtr) (b))
222 /*
223 * Macros for complex/simple types.
224 */
225 #define WXS_IS_ANYTYPE(i) \
226      (( (i)->type == XML_SCHEMA_TYPE_BASIC) && \
227       ( (WXS_TYPE_CAST (i))->builtInType == XML_SCHEMAS_ANYTYPE))
228
229 #define WXS_IS_COMPLEX(i) \
230     (((i)->type == XML_SCHEMA_TYPE_COMPLEX) || \
231      ((i)->builtInType == XML_SCHEMAS_ANYTYPE))
232
233 #define WXS_IS_SIMPLE(item) \
234     ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
235      ((item->type == XML_SCHEMA_TYPE_BASIC) && \
236       (item->builtInType != XML_SCHEMAS_ANYTYPE)))
237
238 #define WXS_IS_ANY_SIMPLE_TYPE(i) \
239     (((i)->type == XML_SCHEMA_TYPE_BASIC) && \
240       ((i)->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
241
242 #define WXS_IS_RESTRICTION(t) \
243     ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)
244
245 #define WXS_IS_EXTENSION(t) \
246     ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
247
248 #define WXS_IS_TYPE_NOT_FIXED(i) \
249     (((i)->type != XML_SCHEMA_TYPE_BASIC) && \
250      (((i)->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
251
252 #define WXS_IS_TYPE_NOT_FIXED_1(item) \
253     (((item)->type != XML_SCHEMA_TYPE_BASIC) && \
254      (((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0))
255
256 #define WXS_TYPE_IS_GLOBAL(t) ((t)->flags & XML_SCHEMAS_TYPE_GLOBAL)
257
258 #define WXS_TYPE_IS_LOCAL(t) (((t)->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0)
259 /*
260 * Macros for exclusively for complex types.
261 */
262 #define WXS_HAS_COMPLEX_CONTENT(item) \
263     ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
264      (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
265      (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
266
267 #define WXS_HAS_SIMPLE_CONTENT(item) \
268     ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
269      (item->contentType == XML_SCHEMA_CONTENT_BASIC))
270
271 #define WXS_HAS_MIXED_CONTENT(item) \
272     (item->contentType == XML_SCHEMA_CONTENT_MIXED)
273
274 #define WXS_EMPTIABLE(t) \
275     (xmlSchemaIsParticleEmptiable(WXS_PTC_CAST (t)->subtypes))
276
277 #define WXS_TYPE_CONTENTTYPE(t) (t)->subtypes
278
279 #define WXS_TYPE_PARTICLE(t) WXS_PTC_CAST (t)->subtypes
280
281 #define WXS_TYPE_PARTICLE_TERM(t) WXS_PARTICLE_TERM(WXS_TYPE_PARTICLE(t))
282 /*
283 * Macros for exclusively for simple types.
284 */
285 #define WXS_LIST_ITEMTYPE(t) (t)->subtypes
286
287 #define WXS_IS_ATOMIC(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
288
289 #define WXS_IS_LIST(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
290
291 #define WXS_IS_UNION(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
292 /*
293 * Misc parser context macros.
294 */
295 #define WXS_CONSTRUCTOR(ctx) (ctx)->constructor
296
297 #define WXS_HAS_BUCKETS(ctx) \
298 ( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \
299 (WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) )
300
301 #define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups
302
303 #define WXS_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket
304
305 #define WXS_SCHEMA(ctx) (ctx)->schema
306
307 #define WXS_ADD_LOCAL(ctx, item) \
308     xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, item)
309
310 #define WXS_ADD_GLOBAL(ctx, item) \
311     xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, item)
312
313 #define WXS_ADD_PENDING(ctx, item) \
314     xmlSchemaAddItemSize(&((ctx)->constructor->pending), 10, item)
315 /*
316 * xmlSchemaItemList macros.
317 */
318 #define WXS_ILIST_IS_EMPTY(l) ((l == NULL) || ((l)->nbItems == 0))
319 /*
320 * Misc macros.
321 */
322 #define IS_SCHEMA(node, type) \
323    ((node != NULL) && (node->ns != NULL) && \
324     (xmlStrEqual(node->name, (const xmlChar *) type)) && \
325     (xmlStrEqual(node->ns->href, xmlSchemaNs)))
326
327 #define FREE_AND_NULL(str) if ((str) != NULL) { xmlFree((xmlChar *) (str)); str = NULL; }
328
329 /*
330 * Since we put the default/fixed values into the dict, we can
331 * use pointer comparison for those values.
332 * REMOVED: (xmlStrEqual((v1), (v2)))
333 */
334 #define WXS_ARE_DEFAULT_STR_EQUAL(v1, v2) ((v1) == (v2))
335
336 #define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
337
338 #define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0))
339
340 #define HFAILURE if (res == -1) goto exit_failure;
341
342 #define HERROR if (res != 0) goto exit_error;
343
344 #define HSTOP(ctx) if ((ctx)->stop) goto exit;
345 /*
346 * Some flags used for various schema constraints.
347 */
348 #define SUBSET_RESTRICTION  1<<0
349 #define SUBSET_EXTENSION    1<<1
350 #define SUBSET_SUBSTITUTION 1<<2
351 #define SUBSET_LIST         1<<3
352 #define SUBSET_UNION        1<<4
353
354 typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
355 typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
356
357 typedef struct _xmlSchemaItemList xmlSchemaItemList;
358 typedef xmlSchemaItemList *xmlSchemaItemListPtr;
359 struct _xmlSchemaItemList {
360     void **items;  /* used for dynamic addition of schemata */
361     int nbItems; /* used for dynamic addition of schemata */
362     int sizeItems; /* used for dynamic addition of schemata */
363 };
364
365 #define XML_SCHEMA_CTXT_PARSER 1
366 #define XML_SCHEMA_CTXT_VALIDATOR 2
367
368 typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
369 typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
370 struct _xmlSchemaAbstractCtxt {
371     int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */
372     void *dummy; /* Fix alignment issues */
373 };
374
375 typedef struct _xmlSchemaBucket xmlSchemaBucket;
376 typedef xmlSchemaBucket *xmlSchemaBucketPtr;
377
378 #define XML_SCHEMA_SCHEMA_MAIN 0
379 #define XML_SCHEMA_SCHEMA_IMPORT 1
380 #define XML_SCHEMA_SCHEMA_INCLUDE 2
381 #define XML_SCHEMA_SCHEMA_REDEFINE 3
382
383 /**
384  * xmlSchemaSchemaRelation:
385  *
386  * Used to create a graph of schema relationships.
387  */
388 typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation;
389 typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr;
390 struct _xmlSchemaSchemaRelation {
391     xmlSchemaSchemaRelationPtr next;
392     int type; /* E.g. XML_SCHEMA_SCHEMA_IMPORT */
393     const xmlChar *importNamespace;
394     xmlSchemaBucketPtr bucket;
395 };
396
397 #define XML_SCHEMA_BUCKET_MARKED 1<<0
398 #define XML_SCHEMA_BUCKET_COMPS_ADDED 1<<1
399
400 struct _xmlSchemaBucket {
401     int type;
402     int flags;
403     const xmlChar *schemaLocation;
404     const xmlChar *origTargetNamespace;
405     const xmlChar *targetNamespace;
406     xmlDocPtr doc;
407     xmlSchemaSchemaRelationPtr relations;
408     int located;
409     int parsed;
410     int imported;
411     int preserveDoc;
412     xmlSchemaItemListPtr globals; /* Global components. */
413     xmlSchemaItemListPtr locals; /* Local components. */
414 };
415
416 /**
417  * xmlSchemaImport:
418  * (extends xmlSchemaBucket)
419  *
420  * Reflects a schema. Holds some information
421  * about the schema and its toplevel components. Duplicate
422  * toplevel components are not checked at this level.
423  */
424 typedef struct _xmlSchemaImport xmlSchemaImport;
425 typedef xmlSchemaImport *xmlSchemaImportPtr;
426 struct _xmlSchemaImport {
427     int type; /* Main OR import OR include. */
428     int flags;
429     const xmlChar *schemaLocation; /* The URI of the schema document. */
430     /* For chameleon includes, @origTargetNamespace will be NULL */
431     const xmlChar *origTargetNamespace;
432     /*
433     * For chameleon includes, @targetNamespace will be the
434     * targetNamespace of the including schema.
435     */
436     const xmlChar *targetNamespace;
437     xmlDocPtr doc; /* The schema node-tree. */
438     /* @relations will hold any included/imported/redefined schemas. */
439     xmlSchemaSchemaRelationPtr relations;
440     int located;
441     int parsed;
442     int imported;
443     int preserveDoc;
444     xmlSchemaItemListPtr globals;
445     xmlSchemaItemListPtr locals;
446     /* The imported schema. */
447     xmlSchemaPtr schema;
448 };
449
450 /*
451 * (extends xmlSchemaBucket)
452 */
453 typedef struct _xmlSchemaInclude xmlSchemaInclude;
454 typedef xmlSchemaInclude *xmlSchemaIncludePtr;
455 struct _xmlSchemaInclude {
456     int type;
457     int flags;
458     const xmlChar *schemaLocation;
459     const xmlChar *origTargetNamespace;
460     const xmlChar *targetNamespace;
461     xmlDocPtr doc;
462     xmlSchemaSchemaRelationPtr relations;
463     int located;
464     int parsed;
465     int imported;
466     int preserveDoc;
467     xmlSchemaItemListPtr globals; /* Global components. */
468     xmlSchemaItemListPtr locals; /* Local components. */
469
470     /* The owning main or import schema bucket. */
471     xmlSchemaImportPtr ownerImport;
472 };
473
474 /**
475  * xmlSchemaBasicItem:
476  *
477  * The abstract base type for schema components.
478  */
479 typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
480 typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
481 struct _xmlSchemaBasicItem {
482     xmlSchemaTypeType type;
483     void *dummy; /* Fix alignment issues */
484 };
485
486 /**
487  * xmlSchemaAnnotItem:
488  *
489  * The abstract base type for annotated schema components.
490  * (Extends xmlSchemaBasicItem)
491  */
492 typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
493 typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
494 struct _xmlSchemaAnnotItem {
495     xmlSchemaTypeType type;
496     xmlSchemaAnnotPtr annot;
497 };
498
499 /**
500  * xmlSchemaTreeItem:
501  *
502  * The abstract base type for tree-like structured schema components.
503  * (Extends xmlSchemaAnnotItem)
504  */
505 typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
506 typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
507 struct _xmlSchemaTreeItem {
508     xmlSchemaTypeType type;
509     xmlSchemaAnnotPtr annot;
510     xmlSchemaTreeItemPtr next;
511     xmlSchemaTreeItemPtr children;
512 };
513
514
515 #define XML_SCHEMA_ATTR_USE_FIXED 1<<0
516 /**
517  * xmlSchemaAttributeUsePtr:
518  *
519  * The abstract base type for tree-like structured schema components.
520  * (Extends xmlSchemaTreeItem)
521  */
522 typedef struct _xmlSchemaAttributeUse xmlSchemaAttributeUse;
523 typedef xmlSchemaAttributeUse *xmlSchemaAttributeUsePtr;
524 struct _xmlSchemaAttributeUse {
525     xmlSchemaTypeType type;
526     xmlSchemaAnnotPtr annot;
527     xmlSchemaAttributeUsePtr next; /* The next attr. use. */
528     /*
529     * The attr. decl. OR a QName-ref. to an attr. decl. OR
530     * a QName-ref. to an attribute group definition.
531     */
532     xmlSchemaAttributePtr attrDecl;
533
534     int flags;
535     xmlNodePtr node;
536     int occurs; /* required, optional */
537     const xmlChar * defValue;
538     xmlSchemaValPtr defVal;
539 };
540
541 /**
542  * xmlSchemaAttributeUseProhibPtr:
543  *
544  * A helper component to reflect attribute prohibitions.
545  * (Extends xmlSchemaBasicItem)
546  */
547 typedef struct _xmlSchemaAttributeUseProhib xmlSchemaAttributeUseProhib;
548 typedef xmlSchemaAttributeUseProhib *xmlSchemaAttributeUseProhibPtr;
549 struct _xmlSchemaAttributeUseProhib {
550     xmlSchemaTypeType type; /* == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB */
551     xmlNodePtr node;
552     const xmlChar *name;
553     const xmlChar *targetNamespace;
554     int isRef;
555 };
556
557 /**
558  * xmlSchemaRedef:
559  */
560 typedef struct _xmlSchemaRedef xmlSchemaRedef;
561 typedef xmlSchemaRedef *xmlSchemaRedefPtr;
562 struct _xmlSchemaRedef {
563     xmlSchemaRedefPtr next;
564     xmlSchemaBasicItemPtr item; /* The redefining component. */
565     xmlSchemaBasicItemPtr reference; /* The referencing component. */
566     xmlSchemaBasicItemPtr target; /* The to-be-redefined component. */
567     const xmlChar *refName; /* The name of the to-be-redefined component. */
568     const xmlChar *refTargetNs; /* The target namespace of the
569                                    to-be-redefined comp. */
570     xmlSchemaBucketPtr targetBucket; /* The redefined schema. */
571 };
572
573 /**
574  * xmlSchemaConstructionCtxt:
575  */
576 typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt;
577 typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr;
578 struct _xmlSchemaConstructionCtxt {
579     xmlSchemaPtr mainSchema; /* The main schema. */
580     xmlSchemaBucketPtr mainBucket; /* The main schema bucket */
581     xmlDictPtr dict;
582     xmlSchemaItemListPtr buckets; /* List of schema buckets. */
583     /* xmlSchemaItemListPtr relations; */ /* List of schema relations. */
584     xmlSchemaBucketPtr bucket; /* The current schema bucket */
585     xmlSchemaItemListPtr pending; /* All Components of all schemas that
586                                      need to be fixed. */
587     xmlHashTablePtr substGroups;
588     xmlSchemaRedefPtr redefs;
589     xmlSchemaRedefPtr lastRedef;
590 };
591
592 #define XML_SCHEMAS_PARSE_ERROR         1
593 #define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
594
595 struct _xmlSchemaParserCtxt {
596     int type;
597     void *errCtxt;             /* user specific error context */
598     xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */
599     xmlSchemaValidityWarningFunc warning;       /* the callback in case of warning */
600     int err;
601     int nberrors;
602     xmlStructuredErrorFunc serror;
603
604     xmlSchemaConstructionCtxtPtr constructor;
605     int ownsConstructor; /* TODO: Move this to parser *flags*. */
606
607     /* xmlSchemaPtr topschema;  */
608     /* xmlHashTablePtr namespaces;  */
609
610     xmlSchemaPtr schema;        /* The main schema in use */
611     int counter;
612
613     const xmlChar *URL;
614     xmlDocPtr doc;
615     int preserve;               /* Whether the doc should be freed  */
616
617     const char *buffer;
618     int size;
619
620     /*
621      * Used to build complex element content models
622      */
623     xmlAutomataPtr am;
624     xmlAutomataStatePtr start;
625     xmlAutomataStatePtr end;
626     xmlAutomataStatePtr state;
627
628     xmlDictPtr dict;            /* dictionary for interned string names */
629     xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
630     int options;
631     xmlSchemaValidCtxtPtr vctxt;
632     int isS4S;
633     int isRedefine;
634     int xsiAssemble;
635     int stop; /* If the parser should stop; i.e. a critical error. */
636     const xmlChar *targetNamespace;
637     xmlSchemaBucketPtr redefined; /* The schema to be redefined. */
638
639     xmlSchemaRedefPtr redef; /* Used for redefinitions. */
640     int redefCounter; /* Used for redefinitions. */
641     xmlSchemaItemListPtr attrProhibs;
642 };
643
644 /**
645  * xmlSchemaQNameRef:
646  *
647  * A component reference item (not a schema component)
648  * (Extends xmlSchemaBasicItem)
649  */
650 typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
651 typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
652 struct _xmlSchemaQNameRef {
653     xmlSchemaTypeType type;
654     xmlSchemaBasicItemPtr item; /* The resolved referenced item. */
655     xmlSchemaTypeType itemType;
656     const xmlChar *name;
657     const xmlChar *targetNamespace;
658     xmlNodePtr node;
659 };
660
661 /**
662  * xmlSchemaParticle:
663  *
664  * A particle component.
665  * (Extends xmlSchemaTreeItem)
666  */
667 typedef struct _xmlSchemaParticle xmlSchemaParticle;
668 typedef xmlSchemaParticle *xmlSchemaParticlePtr;
669 struct _xmlSchemaParticle {
670     xmlSchemaTypeType type;
671     xmlSchemaAnnotPtr annot;
672     xmlSchemaTreeItemPtr next; /* next particle */
673     xmlSchemaTreeItemPtr children; /* the "term" (e.g. a model group,
674         a group definition, a XML_SCHEMA_EXTRA_QNAMEREF (if a reference),
675         etc.) */
676     int minOccurs;
677     int maxOccurs;
678     xmlNodePtr node;
679 };
680
681 /**
682  * xmlSchemaModelGroup:
683  *
684  * A model group component.
685  * (Extends xmlSchemaTreeItem)
686  */
687 typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
688 typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
689 struct _xmlSchemaModelGroup {
690     xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
691     xmlSchemaAnnotPtr annot;
692     xmlSchemaTreeItemPtr next; /* not used */
693     xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
694     xmlNodePtr node;
695 };
696
697 #define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
698 #define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1
699 /**
700  * xmlSchemaModelGroupDef:
701  *
702  * A model group definition component.
703  * (Extends xmlSchemaTreeItem)
704  */
705 typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
706 typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
707 struct _xmlSchemaModelGroupDef {
708     xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
709     xmlSchemaAnnotPtr annot;
710     xmlSchemaTreeItemPtr next; /* not used */
711     xmlSchemaTreeItemPtr children; /* the "model group" */
712     const xmlChar *name;
713     const xmlChar *targetNamespace;
714     xmlNodePtr node;
715     int flags;
716 };
717
718 typedef struct _xmlSchemaIDC xmlSchemaIDC;
719 typedef xmlSchemaIDC *xmlSchemaIDCPtr;
720
721 /**
722  * xmlSchemaIDCSelect:
723  *
724  * The identity-constraint "field" and "selector" item, holding the
725  * XPath expression.
726  */
727 typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
728 typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
729 struct _xmlSchemaIDCSelect {
730     xmlSchemaIDCSelectPtr next;
731     xmlSchemaIDCPtr idc;
732     int index; /* an index position if significant for IDC key-sequences */
733     const xmlChar *xpath; /* the XPath expression */
734     void *xpathComp; /* the compiled XPath expression */
735 };
736
737 /**
738  * xmlSchemaIDC:
739  *
740  * The identity-constraint definition component.
741  * (Extends xmlSchemaAnnotItem)
742  */
743
744 struct _xmlSchemaIDC {
745     xmlSchemaTypeType type;
746     xmlSchemaAnnotPtr annot;
747     xmlSchemaIDCPtr next;
748     xmlNodePtr node;
749     const xmlChar *name;
750     const xmlChar *targetNamespace;
751     xmlSchemaIDCSelectPtr selector;
752     xmlSchemaIDCSelectPtr fields;
753     int nbFields;
754     xmlSchemaQNameRefPtr ref;
755 };
756
757 /**
758  * xmlSchemaIDCAug:
759  *
760  * The augmented IDC information used for validation.
761  */
762 typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
763 typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
764 struct _xmlSchemaIDCAug {
765     xmlSchemaIDCAugPtr next; /* next in a list */
766     xmlSchemaIDCPtr def; /* the IDC definition */
767     int keyrefDepth; /* the lowest tree level to which IDC
768                         tables need to be bubbled upwards */
769 };
770
771 /**
772  * xmlSchemaPSVIIDCKeySequence:
773  *
774  * The key sequence of a node table item.
775  */
776 typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
777 typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
778 struct _xmlSchemaPSVIIDCKey {
779     xmlSchemaTypePtr type;
780     xmlSchemaValPtr val;
781 };
782
783 /**
784  * xmlSchemaPSVIIDCNode:
785  *
786  * The node table item of a node table.
787  */
788 typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
789 typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
790 struct _xmlSchemaPSVIIDCNode {
791     xmlNodePtr node;
792     xmlSchemaPSVIIDCKeyPtr *keys;
793     int nodeLine;
794     int nodeQNameID;
795
796 };
797
798 /**
799  * xmlSchemaPSVIIDCBinding:
800  *
801  * The identity-constraint binding item of the [identity-constraint table].
802  */
803 typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
804 typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
805 struct _xmlSchemaPSVIIDCBinding {
806     xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
807     xmlSchemaIDCPtr definition; /* the IDC definition */
808     xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
809     int nbNodes; /* number of entries in the node table */
810     int sizeNodes; /* size of the node table */
811     xmlSchemaItemListPtr dupls;
812 };
813
814
815 #define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
816 #define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
817
818 #define XPATH_STATE_OBJ_MATCHES -2
819 #define XPATH_STATE_OBJ_BLOCKED -3
820
821 typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
822 typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
823
824 /**
825  * xmlSchemaIDCStateObj:
826  *
827  * The state object used to evaluate XPath expressions.
828  */
829 typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
830 typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
831 struct _xmlSchemaIDCStateObj {
832     int type;
833     xmlSchemaIDCStateObjPtr next; /* next if in a list */
834     int depth; /* depth of creation */
835     int *history; /* list of (depth, state-id) tuples */
836     int nbHistory;
837     int sizeHistory;
838     xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
839                                        matcher */
840     xmlSchemaIDCSelectPtr sel;
841     void *xpathCtxt;
842 };
843
844 #define IDC_MATCHER 0
845
846 /**
847  * xmlSchemaIDCMatcher:
848  *
849  * Used to evaluate IDC selectors (and fields).
850  */
851 struct _xmlSchemaIDCMatcher {
852     int type;
853     int depth; /* the tree depth at creation time */
854     xmlSchemaIDCMatcherPtr next; /* next in the list */
855     xmlSchemaIDCMatcherPtr nextCached; /* next in the cache list */
856     xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
857     int idcType;
858     xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
859                                          elements */
860     int sizeKeySeqs;
861     xmlSchemaItemListPtr targets; /* list of target-node
862                                      (xmlSchemaPSVIIDCNodePtr) entries */
863 };
864
865 /*
866 * Element info flags.
867 */
868 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES  1<<0
869 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
870 #define XML_SCHEMA_ELEM_INFO_NILLED            1<<2
871 #define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE        1<<3
872
873 #define XML_SCHEMA_NODE_INFO_VALUE_NEEDED      1<<4
874 #define XML_SCHEMA_ELEM_INFO_EMPTY             1<<5
875 #define XML_SCHEMA_ELEM_INFO_HAS_CONTENT       1<<6
876
877 #define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT  1<<7
878 #define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT  1<<8
879 #define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED  1<<9
880 #define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE  1<<10
881
882 /**
883  * xmlSchemaNodeInfo:
884  *
885  * Holds information of an element node.
886  */
887 struct _xmlSchemaNodeInfo {
888     int nodeType;
889     xmlNodePtr node;
890     int nodeLine;
891     const xmlChar *localName;
892     const xmlChar *nsName;
893     const xmlChar *value;
894     xmlSchemaValPtr val; /* the pre-computed value if any */
895     xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
896
897     int flags; /* combination of node info flags */
898
899     int valNeeded;
900     int normVal;
901
902     xmlSchemaElementPtr decl; /* the element/attribute declaration */
903     int depth;
904     xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
905                                             for the scope element*/
906     xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
907                                            element */
908     xmlRegExecCtxtPtr regexCtxt;
909
910     const xmlChar **nsBindings; /* Namespace bindings on this element */
911     int nbNsBindings;
912     int sizeNsBindings;
913
914     int hasKeyrefs;
915     int appliedXPath; /* Indicates that an XPath has been applied. */
916 };
917
918 #define XML_SCHEMAS_ATTR_UNKNOWN 1
919 #define XML_SCHEMAS_ATTR_ASSESSED 2
920 #define XML_SCHEMAS_ATTR_PROHIBITED 3
921 #define XML_SCHEMAS_ATTR_ERR_MISSING 4
922 #define XML_SCHEMAS_ATTR_INVALID_VALUE 5
923 #define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
924 #define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
925 #define XML_SCHEMAS_ATTR_DEFAULT 8
926 #define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
927 #define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
928 #define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
929 #define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
930 #define XML_SCHEMAS_ATTR_WILD_SKIP 13
931 #define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
932 #define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
933 #define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
934 #define XML_SCHEMAS_ATTR_META 17
935 /*
936 * @metaType values of xmlSchemaAttrInfo.
937 */
938 #define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
939 #define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
940 #define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
941 #define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
942 #define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
943
944 typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
945 typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
946 struct _xmlSchemaAttrInfo {
947     int nodeType;
948     xmlNodePtr node;
949     int nodeLine;
950     const xmlChar *localName;
951     const xmlChar *nsName;
952     const xmlChar *value;
953     xmlSchemaValPtr val; /* the pre-computed value if any */
954     xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
955     int flags; /* combination of node info flags */
956
957     xmlSchemaAttributePtr decl; /* the attribute declaration */
958     xmlSchemaAttributeUsePtr use;  /* the attribute use */
959     int state;
960     int metaType;
961     const xmlChar *vcValue; /* the value constraint value */
962     xmlSchemaNodeInfoPtr parent;
963 };
964
965
966 #define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
967 /**
968  * xmlSchemaValidCtxt:
969  *
970  * A Schemas validation context
971  */
972 struct _xmlSchemaValidCtxt {
973     int type;
974     void *errCtxt;             /* user specific data block */
975     xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */
976     xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
977     xmlStructuredErrorFunc serror;
978
979     xmlSchemaPtr schema;        /* The schema in use */
980     xmlDocPtr doc;
981     xmlParserInputBufferPtr input;
982     xmlCharEncoding enc;
983     xmlSAXHandlerPtr sax;
984     xmlParserCtxtPtr parserCtxt;
985     void *user_data; /* TODO: What is this for? */
986     char *filename;
987
988     int err;
989     int nberrors;
990
991     xmlNodePtr node;
992     xmlNodePtr cur;
993     /* xmlSchemaTypePtr type; */
994
995     xmlRegExecCtxtPtr regexp;
996     xmlSchemaValPtr value;
997
998     int valueWS;
999     int options;
1000     xmlNodePtr validationRoot;
1001     xmlSchemaParserCtxtPtr pctxt;
1002     int xsiAssemble;
1003
1004     int depth;
1005     xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
1006     int sizeElemInfos;
1007     xmlSchemaNodeInfoPtr inode; /* the current element information */
1008
1009     xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
1010
1011     xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
1012     xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
1013     xmlSchemaIDCMatcherPtr idcMatcherCache; /* Cache for IDC matcher objects. */
1014
1015     xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
1016     int nbIdcNodes;
1017     int sizeIdcNodes;
1018
1019     xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
1020     int nbIdcKeys;
1021     int sizeIdcKeys;
1022
1023     int flags;
1024
1025     xmlDictPtr dict;
1026
1027 #ifdef LIBXML_READER_ENABLED
1028     xmlTextReaderPtr reader;
1029 #endif
1030
1031     xmlSchemaAttrInfoPtr *attrInfos;
1032     int nbAttrInfos;
1033     int sizeAttrInfos;
1034
1035     int skipDepth;
1036     xmlSchemaItemListPtr nodeQNames;
1037     int hasKeyrefs;
1038     int createIDCNodeTables;
1039     int psviExposeIDCNodeTables;
1040
1041     /* Locator for error reporting in streaming mode */
1042     xmlSchemaValidityLocatorFunc locFunc;
1043     void *locCtxt;
1044 };
1045
1046 /**
1047  * xmlSchemaSubstGroup:
1048  *
1049  *
1050  */
1051 typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
1052 typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
1053 struct _xmlSchemaSubstGroup {
1054     xmlSchemaElementPtr head;
1055     xmlSchemaItemListPtr members;
1056 };
1057
1058 /************************************************************************
1059  *                                                                      *
1060  *                      Some predeclarations                            *
1061  *                                                                      *
1062  ************************************************************************/
1063
1064 static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
1065                                  xmlSchemaPtr schema,
1066                                  xmlNodePtr node);
1067 static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
1068                                  xmlSchemaPtr schema,
1069                                  xmlNodePtr node);
1070 static int
1071 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
1072                    xmlSchemaAbstractCtxtPtr ctxt);
1073 static const xmlChar *
1074 xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
1075 static int
1076 xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1077                      xmlNodePtr node);
1078 static int
1079 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
1080                        xmlSchemaParserCtxtPtr ctxt);
1081 static void
1082 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
1083 static xmlSchemaWhitespaceValueType
1084 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
1085 static xmlSchemaTreeItemPtr
1086 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1087                          xmlNodePtr node, xmlSchemaTypeType type,
1088                          int withParticle);
1089 static const xmlChar *
1090 xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item);
1091 static xmlSchemaTypeLinkPtr
1092 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
1093 static void
1094 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1095                      const char *funcName,
1096                      const char *message) LIBXML_ATTR_FORMAT(3,0);
1097 static int
1098 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt,
1099                              xmlSchemaTypePtr type,
1100                              xmlSchemaTypePtr baseType,
1101                              int subset);
1102 static void
1103 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
1104                                    xmlSchemaParserCtxtPtr ctxt);
1105 static void
1106 xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
1107 static xmlSchemaQNameRefPtr
1108 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
1109                                 xmlSchemaPtr schema,
1110                                 xmlNodePtr node);
1111
1112 /************************************************************************
1113  *                                                                      *
1114  *                      Helper functions                                *
1115  *                                                                      *
1116  ************************************************************************/
1117
1118 /**
1119  * xmlSchemaItemTypeToStr:
1120  * @type: the type of the schema item
1121  *
1122  * Returns the component name of a schema item.
1123  */
1124 static const xmlChar *
1125 xmlSchemaItemTypeToStr(xmlSchemaTypeType type)
1126 {
1127     switch (type) {
1128         case XML_SCHEMA_TYPE_BASIC:
1129             return(BAD_CAST "simple type definition");
1130         case XML_SCHEMA_TYPE_SIMPLE:
1131             return(BAD_CAST "simple type definition");
1132         case XML_SCHEMA_TYPE_COMPLEX:
1133             return(BAD_CAST "complex type definition");
1134         case XML_SCHEMA_TYPE_ELEMENT:
1135             return(BAD_CAST "element declaration");
1136         case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1137             return(BAD_CAST "attribute use");
1138         case XML_SCHEMA_TYPE_ATTRIBUTE:
1139             return(BAD_CAST "attribute declaration");
1140         case XML_SCHEMA_TYPE_GROUP:
1141             return(BAD_CAST "model group definition");
1142         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1143             return(BAD_CAST "attribute group definition");
1144         case XML_SCHEMA_TYPE_NOTATION:
1145             return(BAD_CAST "notation declaration");
1146         case XML_SCHEMA_TYPE_SEQUENCE:
1147             return(BAD_CAST "model group (sequence)");
1148         case XML_SCHEMA_TYPE_CHOICE:
1149             return(BAD_CAST "model group (choice)");
1150         case XML_SCHEMA_TYPE_ALL:
1151             return(BAD_CAST "model group (all)");
1152         case XML_SCHEMA_TYPE_PARTICLE:
1153             return(BAD_CAST "particle");
1154         case XML_SCHEMA_TYPE_IDC_UNIQUE:
1155             return(BAD_CAST "unique identity-constraint");
1156             /* return(BAD_CAST "IDC (unique)"); */
1157         case XML_SCHEMA_TYPE_IDC_KEY:
1158             return(BAD_CAST "key identity-constraint");
1159             /* return(BAD_CAST "IDC (key)"); */
1160         case XML_SCHEMA_TYPE_IDC_KEYREF:
1161             return(BAD_CAST "keyref identity-constraint");
1162             /* return(BAD_CAST "IDC (keyref)"); */
1163         case XML_SCHEMA_TYPE_ANY:
1164             return(BAD_CAST "wildcard (any)");
1165         case XML_SCHEMA_EXTRA_QNAMEREF:
1166             return(BAD_CAST "[helper component] QName reference");
1167         case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
1168             return(BAD_CAST "[helper component] attribute use prohibition");
1169         default:
1170             return(BAD_CAST "Not a schema component");
1171     }
1172 }
1173
1174 /**
1175  * xmlSchemaGetComponentTypeStr:
1176  * @type: the type of the schema item
1177  *
1178  * Returns the component name of a schema item.
1179  */
1180 static const xmlChar *
1181 xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)
1182 {
1183     switch (item->type) {
1184         case XML_SCHEMA_TYPE_BASIC:
1185             if (WXS_IS_COMPLEX(WXS_TYPE_CAST item))
1186                 return(BAD_CAST "complex type definition");
1187             else
1188                 return(BAD_CAST "simple type definition");
1189         default:
1190             return(xmlSchemaItemTypeToStr(item->type));
1191     }
1192 }
1193
1194 /**
1195  * xmlSchemaGetComponentNode:
1196  * @item: a schema component
1197  *
1198  * Returns node associated with the schema component.
1199  * NOTE that such a node need not be available; plus, a component's
1200  * node need not to reflect the component directly, since there is no
1201  * one-to-one relationship between the XML Schema representation and
1202  * the component representation.
1203  */
1204 static xmlNodePtr
1205 xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
1206 {
1207     switch (item->type) {
1208         case XML_SCHEMA_TYPE_ELEMENT:
1209             return (((xmlSchemaElementPtr) item)->node);
1210         case XML_SCHEMA_TYPE_ATTRIBUTE:
1211             return (((xmlSchemaAttributePtr) item)->node);
1212         case XML_SCHEMA_TYPE_COMPLEX:
1213         case XML_SCHEMA_TYPE_SIMPLE:
1214             return (((xmlSchemaTypePtr) item)->node);
1215         case XML_SCHEMA_TYPE_ANY:
1216         case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1217             return (((xmlSchemaWildcardPtr) item)->node);
1218         case XML_SCHEMA_TYPE_PARTICLE:
1219             return (((xmlSchemaParticlePtr) item)->node);
1220         case XML_SCHEMA_TYPE_SEQUENCE:
1221         case XML_SCHEMA_TYPE_CHOICE:
1222         case XML_SCHEMA_TYPE_ALL:
1223             return (((xmlSchemaModelGroupPtr) item)->node);
1224         case XML_SCHEMA_TYPE_GROUP:
1225             return (((xmlSchemaModelGroupDefPtr) item)->node);
1226         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1227             return (((xmlSchemaAttributeGroupPtr) item)->node);
1228         case XML_SCHEMA_TYPE_IDC_UNIQUE:
1229         case XML_SCHEMA_TYPE_IDC_KEY:
1230         case XML_SCHEMA_TYPE_IDC_KEYREF:
1231             return (((xmlSchemaIDCPtr) item)->node);
1232         case XML_SCHEMA_EXTRA_QNAMEREF:
1233             return(((xmlSchemaQNameRefPtr) item)->node);
1234         /* TODO: What to do with NOTATIONs?
1235         case XML_SCHEMA_TYPE_NOTATION:
1236             return (((xmlSchemaNotationPtr) item)->node);
1237         */
1238         case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1239             return (((xmlSchemaAttributeUsePtr) item)->node);
1240         default:
1241             return (NULL);
1242     }
1243 }
1244
1245 #if 0
1246 /**
1247  * xmlSchemaGetNextComponent:
1248  * @item: a schema component
1249  *
1250  * Returns the next sibling of the schema component.
1251  */
1252 static xmlSchemaBasicItemPtr
1253 xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1254 {
1255     switch (item->type) {
1256         case XML_SCHEMA_TYPE_ELEMENT:
1257             return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1258         case XML_SCHEMA_TYPE_ATTRIBUTE:
1259             return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1260         case XML_SCHEMA_TYPE_COMPLEX:
1261         case XML_SCHEMA_TYPE_SIMPLE:
1262             return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1263         case XML_SCHEMA_TYPE_ANY:
1264         case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1265             return (NULL);
1266         case XML_SCHEMA_TYPE_PARTICLE:
1267             return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1268         case XML_SCHEMA_TYPE_SEQUENCE:
1269         case XML_SCHEMA_TYPE_CHOICE:
1270         case XML_SCHEMA_TYPE_ALL:
1271             return (NULL);
1272         case XML_SCHEMA_TYPE_GROUP:
1273             return (NULL);
1274         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1275             return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1276         case XML_SCHEMA_TYPE_IDC_UNIQUE:
1277         case XML_SCHEMA_TYPE_IDC_KEY:
1278         case XML_SCHEMA_TYPE_IDC_KEYREF:
1279             return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1280         default:
1281             return (NULL);
1282     }
1283 }
1284 #endif
1285
1286
1287 /**
1288  * xmlSchemaFormatQName:
1289  * @buf: the string buffer
1290  * @namespaceName:  the namespace name
1291  * @localName: the local name
1292  *
1293  * Returns the given QName in the format "{namespaceName}localName" or
1294  * just "localName" if @namespaceName is NULL.
1295  *
1296  * Returns the localName if @namespaceName is NULL, a formatted
1297  * string otherwise.
1298  */
1299 static const xmlChar*
1300 xmlSchemaFormatQName(xmlChar **buf,
1301                      const xmlChar *namespaceName,
1302                      const xmlChar *localName)
1303 {
1304     FREE_AND_NULL(*buf)
1305     if (namespaceName != NULL) {
1306         *buf = xmlStrdup(BAD_CAST "{");
1307         *buf = xmlStrcat(*buf, namespaceName);
1308         *buf = xmlStrcat(*buf, BAD_CAST "}");
1309     }
1310     if (localName != NULL) {
1311         if (namespaceName == NULL)
1312             return(localName);
1313         *buf = xmlStrcat(*buf, localName);
1314     } else {
1315         *buf = xmlStrcat(*buf, BAD_CAST "(NULL)");
1316     }
1317     return ((const xmlChar *) *buf);
1318 }
1319
1320 static const xmlChar*
1321 xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
1322 {
1323     if (ns != NULL)
1324         return (xmlSchemaFormatQName(buf, ns->href, localName));
1325     else
1326         return (xmlSchemaFormatQName(buf, NULL, localName));
1327 }
1328
1329 static const xmlChar *
1330 xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1331 {
1332     switch (item->type) {
1333         case XML_SCHEMA_TYPE_ELEMENT:
1334             return (((xmlSchemaElementPtr) item)->name);
1335         case XML_SCHEMA_TYPE_ATTRIBUTE:
1336             return (((xmlSchemaAttributePtr) item)->name);
1337         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1338             return (((xmlSchemaAttributeGroupPtr) item)->name);
1339         case XML_SCHEMA_TYPE_BASIC:
1340         case XML_SCHEMA_TYPE_SIMPLE:
1341         case XML_SCHEMA_TYPE_COMPLEX:
1342             return (((xmlSchemaTypePtr) item)->name);
1343         case XML_SCHEMA_TYPE_GROUP:
1344             return (((xmlSchemaModelGroupDefPtr) item)->name);
1345         case XML_SCHEMA_TYPE_IDC_KEY:
1346         case XML_SCHEMA_TYPE_IDC_UNIQUE:
1347         case XML_SCHEMA_TYPE_IDC_KEYREF:
1348             return (((xmlSchemaIDCPtr) item)->name);
1349         case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1350             if (WXS_ATTRUSE_DECL(item) != NULL) {
1351                 return(xmlSchemaGetComponentName(
1352                     WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1353             } else
1354                 return(NULL);
1355         case XML_SCHEMA_EXTRA_QNAMEREF:
1356             return (((xmlSchemaQNameRefPtr) item)->name);
1357         case XML_SCHEMA_TYPE_NOTATION:
1358             return (((xmlSchemaNotationPtr) item)->name);
1359         default:
1360             /*
1361             * Other components cannot have names.
1362             */
1363             break;
1364     }
1365     return (NULL);
1366 }
1367
1368 #define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
1369 #define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
1370 /*
1371 static const xmlChar *
1372 xmlSchemaGetQNameRefName(void *ref)
1373 {
1374     return(((xmlSchemaQNameRefPtr) ref)->name);
1375 }
1376
1377 static const xmlChar *
1378 xmlSchemaGetQNameRefTargetNs(void *ref)
1379 {
1380     return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
1381 }
1382 */
1383
1384 static const xmlChar *
1385 xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1386 {
1387     switch (item->type) {
1388         case XML_SCHEMA_TYPE_ELEMENT:
1389             return (((xmlSchemaElementPtr) item)->targetNamespace);
1390         case XML_SCHEMA_TYPE_ATTRIBUTE:
1391             return (((xmlSchemaAttributePtr) item)->targetNamespace);
1392         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1393             return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1394         case XML_SCHEMA_TYPE_BASIC:
1395             return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1396         case XML_SCHEMA_TYPE_SIMPLE:
1397         case XML_SCHEMA_TYPE_COMPLEX:
1398             return (((xmlSchemaTypePtr) item)->targetNamespace);
1399         case XML_SCHEMA_TYPE_GROUP:
1400             return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1401         case XML_SCHEMA_TYPE_IDC_KEY:
1402         case XML_SCHEMA_TYPE_IDC_UNIQUE:
1403         case XML_SCHEMA_TYPE_IDC_KEYREF:
1404             return (((xmlSchemaIDCPtr) item)->targetNamespace);
1405         case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1406             if (WXS_ATTRUSE_DECL(item) != NULL) {
1407                 return(xmlSchemaGetComponentTargetNs(
1408                     WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1409             }
1410             /* TODO: Will returning NULL break something? */
1411             break;
1412         case XML_SCHEMA_EXTRA_QNAMEREF:
1413             return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
1414         case XML_SCHEMA_TYPE_NOTATION:
1415             return (((xmlSchemaNotationPtr) item)->targetNamespace);
1416         default:
1417             /*
1418             * Other components cannot have names.
1419             */
1420             break;
1421     }
1422     return (NULL);
1423 }
1424
1425 static const xmlChar*
1426 xmlSchemaGetComponentQName(xmlChar **buf,
1427                            void *item)
1428 {
1429     return (xmlSchemaFormatQName(buf,
1430         xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1431         xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1432 }
1433
1434 static const xmlChar*
1435 xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
1436 {
1437     xmlChar *str = NULL;
1438
1439     *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
1440     *buf = xmlStrcat(*buf, BAD_CAST " '");
1441     *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
1442         (xmlSchemaBasicItemPtr) item));
1443     *buf = xmlStrcat(*buf, BAD_CAST "'");
1444     FREE_AND_NULL(str);
1445     return(*buf);
1446 }
1447
1448 static const xmlChar*
1449 xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
1450 {
1451     return(xmlSchemaGetComponentDesignation(buf, idc));
1452 }
1453
1454 /**
1455  * xmlSchemaWildcardPCToString:
1456  * @pc: the type of processContents
1457  *
1458  * Returns a string representation of the type of
1459  * processContents.
1460  */
1461 static const xmlChar *
1462 xmlSchemaWildcardPCToString(int pc)
1463 {
1464     switch (pc) {
1465         case XML_SCHEMAS_ANY_SKIP:
1466             return (BAD_CAST "skip");
1467         case XML_SCHEMAS_ANY_LAX:
1468             return (BAD_CAST "lax");
1469         case XML_SCHEMAS_ANY_STRICT:
1470             return (BAD_CAST "strict");
1471         default:
1472             return (BAD_CAST "invalid process contents");
1473     }
1474 }
1475
1476 /**
1477  * xmlSchemaGetCanonValueWhtspExt:
1478  * @val: the precomputed value
1479  * @retValue: the returned value
1480  * @ws: the whitespace type of the value
1481  *
1482  * Get a the canonical representation of the value.
1483  * The caller has to free the returned retValue.
1484  *
1485  * Returns 0 if the value could be built and -1 in case of
1486  *         API errors or if the value type is not supported yet.
1487  */
1488 static int
1489 xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1490                                xmlSchemaWhitespaceValueType ws,
1491                                xmlChar **retValue)
1492 {
1493     int list;
1494     xmlSchemaValType valType;
1495     const xmlChar *value, *value2 = NULL;
1496
1497
1498     if ((retValue == NULL) || (val == NULL))
1499         return (-1);
1500     list = xmlSchemaValueGetNext(val) ? 1 : 0;
1501     *retValue = NULL;
1502     do {
1503         value = NULL;
1504         valType = xmlSchemaGetValType(val);
1505         switch (valType) {
1506             case XML_SCHEMAS_STRING:
1507             case XML_SCHEMAS_NORMSTRING:
1508             case XML_SCHEMAS_ANYSIMPLETYPE:
1509                 value = xmlSchemaValueGetAsString(val);
1510                 if (value != NULL) {
1511                     if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1512                         value2 = xmlSchemaCollapseString(value);
1513                     else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1514                         value2 = xmlSchemaWhiteSpaceReplace(value);
1515                     if (value2 != NULL)
1516                         value = value2;
1517                 }
1518                 break;
1519             default:
1520                 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1521                     if (value2 != NULL)
1522                         xmlFree((xmlChar *) value2);
1523                     goto internal_error;
1524                 }
1525                 value = value2;
1526         }
1527         if (*retValue == NULL)
1528             if (value == NULL) {
1529                 if (! list)
1530                     *retValue = xmlStrdup(BAD_CAST "");
1531             } else
1532                 *retValue = xmlStrdup(value);
1533         else if (value != NULL) {
1534             /* List. */
1535             *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1536             *retValue = xmlStrcat((xmlChar *) *retValue, value);
1537         }
1538         FREE_AND_NULL(value2)
1539         val = xmlSchemaValueGetNext(val);
1540     } while (val != NULL);
1541
1542     return (0);
1543 internal_error:
1544     if (*retValue != NULL)
1545         xmlFree((xmlChar *) (*retValue));
1546     if (value2 != NULL)
1547         xmlFree((xmlChar *) value2);
1548     return (-1);
1549 }
1550
1551 /**
1552  * xmlSchemaFormatItemForReport:
1553  * @buf: the string buffer
1554  * @itemDes: the designation of the item
1555  * @itemName: the name of the item
1556  * @item: the item as an object
1557  * @itemNode: the node of the item
1558  * @local: the local name
1559  * @parsing: if the function is used during the parse
1560  *
1561  * Returns a representation of the given item used
1562  * for error reports.
1563  *
1564  * The following order is used to build the resulting
1565  * designation if the arguments are not NULL:
1566  * 1a. If itemDes not NULL -> itemDes
1567  * 1b. If (itemDes not NULL) and (itemName not NULL)
1568  *     -> itemDes + itemName
1569  * 2. If the preceding was NULL and (item not NULL) -> item
1570  * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1571  *
1572  * If the itemNode is an attribute node, the name of the attribute
1573  * will be appended to the result.
1574  *
1575  * Returns the formatted string and sets @buf to the resulting value.
1576  */
1577 static xmlChar*
1578 xmlSchemaFormatItemForReport(xmlChar **buf,
1579                      const xmlChar *itemDes,
1580                      xmlSchemaBasicItemPtr item,
1581                      xmlNodePtr itemNode)
1582 {
1583     xmlChar *str = NULL;
1584     int named = 1;
1585
1586     if (*buf != NULL) {
1587         xmlFree(*buf);
1588         *buf = NULL;
1589     }
1590
1591     if (itemDes != NULL) {
1592         *buf = xmlStrdup(itemDes);
1593     } else if (item != NULL) {
1594         switch (item->type) {
1595         case XML_SCHEMA_TYPE_BASIC: {
1596             xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1597
1598             if (WXS_IS_ATOMIC(type))
1599                 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1600             else if (WXS_IS_LIST(type))
1601                 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
1602             else if (WXS_IS_UNION(type))
1603                 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1604             else
1605                 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1606             *buf = xmlStrcat(*buf, type->name);
1607             *buf = xmlStrcat(*buf, BAD_CAST "'");
1608             }
1609             break;
1610         case XML_SCHEMA_TYPE_SIMPLE: {
1611             xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1612
1613             if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1614                 *buf = xmlStrdup(BAD_CAST"");
1615             } else {
1616                 *buf = xmlStrdup(BAD_CAST "local ");
1617             }
1618             if (WXS_IS_ATOMIC(type))
1619                 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1620             else if (WXS_IS_LIST(type))
1621                 *buf = xmlStrcat(*buf, BAD_CAST "list type");
1622             else if (WXS_IS_UNION(type))
1623                 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1624             else
1625                 *buf = xmlStrcat(*buf, BAD_CAST "simple type");
1626             if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1627                 *buf = xmlStrcat(*buf, BAD_CAST " '");
1628                 *buf = xmlStrcat(*buf, type->name);
1629                 *buf = xmlStrcat(*buf, BAD_CAST "'");
1630             }
1631             }
1632             break;
1633         case XML_SCHEMA_TYPE_COMPLEX: {
1634             xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1635
1636             if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
1637                 *buf = xmlStrdup(BAD_CAST "");
1638             else
1639                 *buf = xmlStrdup(BAD_CAST "local ");
1640             *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1641             if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1642                 *buf = xmlStrcat(*buf, BAD_CAST " '");
1643                 *buf = xmlStrcat(*buf, type->name);
1644                 *buf = xmlStrcat(*buf, BAD_CAST "'");
1645             }
1646             }
1647             break;
1648         case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
1649                 xmlSchemaAttributeUsePtr ause;
1650
1651                 ause = WXS_ATTR_USE_CAST item;
1652                 *buf = xmlStrdup(BAD_CAST "attribute use ");
1653                 if (WXS_ATTRUSE_DECL(ause) != NULL) {
1654                     *buf = xmlStrcat(*buf, BAD_CAST "'");
1655                     *buf = xmlStrcat(*buf,
1656                         xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
1657                     FREE_AND_NULL(str)
1658                         *buf = xmlStrcat(*buf, BAD_CAST "'");
1659                 } else {
1660                     *buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
1661                 }
1662             }
1663             break;
1664         case XML_SCHEMA_TYPE_ATTRIBUTE: {
1665                 xmlSchemaAttributePtr attr;
1666
1667                 attr = (xmlSchemaAttributePtr) item;
1668                 *buf = xmlStrdup(BAD_CAST "attribute decl.");
1669                 *buf = xmlStrcat(*buf, BAD_CAST " '");
1670                 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1671                     attr->targetNamespace, attr->name));
1672                 FREE_AND_NULL(str)
1673                     *buf = xmlStrcat(*buf, BAD_CAST "'");
1674             }
1675             break;
1676         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1677             xmlSchemaGetComponentDesignation(buf, item);
1678             break;
1679         case XML_SCHEMA_TYPE_ELEMENT: {
1680                 xmlSchemaElementPtr elem;
1681
1682                 elem = (xmlSchemaElementPtr) item;
1683                 *buf = xmlStrdup(BAD_CAST "element decl.");
1684                 *buf = xmlStrcat(*buf, BAD_CAST " '");
1685                 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1686                     elem->targetNamespace, elem->name));
1687                 *buf = xmlStrcat(*buf, BAD_CAST "'");
1688             }
1689             break;
1690         case XML_SCHEMA_TYPE_IDC_UNIQUE:
1691         case XML_SCHEMA_TYPE_IDC_KEY:
1692         case XML_SCHEMA_TYPE_IDC_KEYREF:
1693             if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1694                 *buf = xmlStrdup(BAD_CAST "unique '");
1695             else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1696                 *buf = xmlStrdup(BAD_CAST "key '");
1697             else
1698                 *buf = xmlStrdup(BAD_CAST "keyRef '");
1699             *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1700             *buf = xmlStrcat(*buf, BAD_CAST "'");
1701             break;
1702         case XML_SCHEMA_TYPE_ANY:
1703         case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1704             *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1705                     ((xmlSchemaWildcardPtr) item)->processContents));
1706             *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1707             break;
1708         case XML_SCHEMA_FACET_MININCLUSIVE:
1709         case XML_SCHEMA_FACET_MINEXCLUSIVE:
1710         case XML_SCHEMA_FACET_MAXINCLUSIVE:
1711         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1712         case XML_SCHEMA_FACET_TOTALDIGITS:
1713         case XML_SCHEMA_FACET_FRACTIONDIGITS:
1714         case XML_SCHEMA_FACET_PATTERN:
1715         case XML_SCHEMA_FACET_ENUMERATION:
1716         case XML_SCHEMA_FACET_WHITESPACE:
1717         case XML_SCHEMA_FACET_LENGTH:
1718         case XML_SCHEMA_FACET_MAXLENGTH:
1719         case XML_SCHEMA_FACET_MINLENGTH:
1720             *buf = xmlStrdup(BAD_CAST "facet '");
1721             *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1722             *buf = xmlStrcat(*buf, BAD_CAST "'");
1723             break;
1724         case XML_SCHEMA_TYPE_GROUP: {
1725                 *buf = xmlStrdup(BAD_CAST "model group def.");
1726                 *buf = xmlStrcat(*buf, BAD_CAST " '");
1727                 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1728                 *buf = xmlStrcat(*buf, BAD_CAST "'");
1729                 FREE_AND_NULL(str)
1730             }
1731             break;
1732         case XML_SCHEMA_TYPE_SEQUENCE:
1733         case XML_SCHEMA_TYPE_CHOICE:
1734         case XML_SCHEMA_TYPE_ALL:
1735         case XML_SCHEMA_TYPE_PARTICLE:
1736             *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1737             break;
1738         case XML_SCHEMA_TYPE_NOTATION: {
1739                 *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1740                 *buf = xmlStrcat(*buf, BAD_CAST " '");
1741                 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1742                 *buf = xmlStrcat(*buf, BAD_CAST "'");
1743                 FREE_AND_NULL(str);
1744             }
1745             /* Falls through. */
1746         default:
1747             named = 0;
1748         }
1749     } else
1750         named = 0;
1751
1752     if ((named == 0) && (itemNode != NULL)) {
1753         xmlNodePtr elem;
1754
1755         if (itemNode->type == XML_ATTRIBUTE_NODE)
1756             elem = itemNode->parent;
1757         else
1758             elem = itemNode;
1759         *buf = xmlStrdup(BAD_CAST "Element '");
1760         if (elem->ns != NULL) {
1761             *buf = xmlStrcat(*buf,
1762                 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1763             FREE_AND_NULL(str)
1764         } else
1765             *buf = xmlStrcat(*buf, elem->name);
1766         *buf = xmlStrcat(*buf, BAD_CAST "'");
1767
1768     }
1769     if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1770         *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1771         if (itemNode->ns != NULL) {
1772             *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1773                 itemNode->ns->href, itemNode->name));
1774             FREE_AND_NULL(str)
1775         } else
1776             *buf = xmlStrcat(*buf, itemNode->name);
1777         *buf = xmlStrcat(*buf, BAD_CAST "'");
1778     }
1779     FREE_AND_NULL(str)
1780
1781     return (xmlEscapeFormatString(buf));
1782 }
1783
1784 /**
1785  * xmlSchemaFormatFacetEnumSet:
1786  * @buf: the string buffer
1787  * @type: the type holding the enumeration facets
1788  *
1789  * Builds a string consisting of all enumeration elements.
1790  *
1791  * Returns a string of all enumeration elements.
1792  */
1793 static const xmlChar *
1794 xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1795                             xmlChar **buf, xmlSchemaTypePtr type)
1796 {
1797     xmlSchemaFacetPtr facet;
1798     xmlSchemaWhitespaceValueType ws;
1799     xmlChar *value = NULL;
1800     int res, found = 0;
1801
1802     if (*buf != NULL)
1803         xmlFree(*buf);
1804     *buf = NULL;
1805
1806     do {
1807         /*
1808         * Use the whitespace type of the base type.
1809         */
1810         ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1811         for (facet = type->facets; facet != NULL; facet = facet->next) {
1812             if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1813                 continue;
1814             found = 1;
1815             res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1816                 ws, &value);
1817             if (res == -1) {
1818                 xmlSchemaInternalErr(actxt,
1819                     "xmlSchemaFormatFacetEnumSet",
1820                     "compute the canonical lexical representation");
1821                 if (*buf != NULL)
1822                     xmlFree(*buf);
1823                 *buf = NULL;
1824                 return (NULL);
1825             }
1826             if (*buf == NULL)
1827                 *buf = xmlStrdup(BAD_CAST "'");
1828             else
1829                 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1830             *buf = xmlStrcat(*buf, BAD_CAST value);
1831             *buf = xmlStrcat(*buf, BAD_CAST "'");
1832             if (value != NULL) {
1833                 xmlFree((xmlChar *)value);
1834                 value = NULL;
1835             }
1836         }
1837         /*
1838         * The enumeration facet of a type restricts the enumeration
1839         * facet of the ancestor type; i.e., such restricted enumerations
1840         * do not belong to the set of the given type. Thus we break
1841         * on the first found enumeration.
1842         */
1843         if (found)
1844             break;
1845         type = type->baseType;
1846     } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1847
1848     return ((const xmlChar *) *buf);
1849 }
1850
1851 /************************************************************************
1852  *                                                                      *
1853  *                      Error functions                                 *
1854  *                                                                      *
1855  ************************************************************************/
1856
1857 #if 0
1858 static void
1859 xmlSchemaErrMemory(const char *msg)
1860 {
1861     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1862                      msg);
1863 }
1864 #endif
1865
1866 static void
1867 xmlSchemaPSimpleErr(const char *msg)
1868 {
1869     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1870                      msg);
1871 }
1872
1873 /**
1874  * xmlSchemaPErrMemory:
1875  * @node: a context node
1876  * @extra:  extra informations
1877  *
1878  * Handle an out of memory condition
1879  */
1880 static void
1881 xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1882                     const char *extra, xmlNodePtr node)
1883 {
1884     if (ctxt != NULL)
1885         ctxt->nberrors++;
1886     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1887                      extra);
1888 }
1889
1890 /**
1891  * xmlSchemaPErr:
1892  * @ctxt: the parsing context
1893  * @node: the context node
1894  * @error: the error code
1895  * @msg: the error message
1896  * @str1: extra data
1897  * @str2: extra data
1898  *
1899  * Handle a parser error
1900  */
1901 static void LIBXML_ATTR_FORMAT(4,0)
1902 xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1903               const char *msg, const xmlChar * str1, const xmlChar * str2)
1904 {
1905     xmlGenericErrorFunc channel = NULL;
1906     xmlStructuredErrorFunc schannel = NULL;
1907     void *data = NULL;
1908
1909     if (ctxt != NULL) {
1910         ctxt->nberrors++;
1911         ctxt->err = error;
1912         channel = ctxt->error;
1913         data = ctxt->errCtxt;
1914         schannel = ctxt->serror;
1915     }
1916     __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1917                     error, XML_ERR_ERROR, NULL, 0,
1918                     (const char *) str1, (const char *) str2, NULL, 0, 0,
1919                     msg, str1, str2);
1920 }
1921
1922 /**
1923  * xmlSchemaPErr2:
1924  * @ctxt: the parsing context
1925  * @node: the context node
1926  * @node: the current child
1927  * @error: the error code
1928  * @msg: the error message
1929  * @str1: extra data
1930  * @str2: extra data
1931  *
1932  * Handle a parser error
1933  */
1934 static void LIBXML_ATTR_FORMAT(5,0)
1935 xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1936                xmlNodePtr child, int error,
1937                const char *msg, const xmlChar * str1, const xmlChar * str2)
1938 {
1939     if (child != NULL)
1940         xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1941     else
1942         xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1943 }
1944
1945
1946 /**
1947  * xmlSchemaPErrExt:
1948  * @ctxt: the parsing context
1949  * @node: the context node
1950  * @error: the error code
1951  * @strData1: extra data
1952  * @strData2: extra data
1953  * @strData3: extra data
1954  * @msg: the message
1955  * @str1:  extra parameter for the message display
1956  * @str2:  extra parameter for the message display
1957  * @str3:  extra parameter for the message display
1958  * @str4:  extra parameter for the message display
1959  * @str5:  extra parameter for the message display
1960  *
1961  * Handle a parser error
1962  */
1963 static void LIBXML_ATTR_FORMAT(7,0)
1964 xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1965                 const xmlChar * strData1, const xmlChar * strData2,
1966                 const xmlChar * strData3, const char *msg, const xmlChar * str1,
1967                 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1968                 const xmlChar * str5)
1969 {
1970
1971     xmlGenericErrorFunc channel = NULL;
1972     xmlStructuredErrorFunc schannel = NULL;
1973     void *data = NULL;
1974
1975     if (ctxt != NULL) {
1976         ctxt->nberrors++;
1977         ctxt->err = error;
1978         channel = ctxt->error;
1979         data = ctxt->errCtxt;
1980         schannel = ctxt->serror;
1981     }
1982     __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1983                     error, XML_ERR_ERROR, NULL, 0,
1984                     (const char *) strData1, (const char *) strData2,
1985                     (const char *) strData3, 0, 0, msg, str1, str2,
1986                     str3, str4, str5);
1987 }
1988
1989 /************************************************************************
1990  *                                                                      *
1991  *                      Allround error functions                        *
1992  *                                                                      *
1993  ************************************************************************/
1994
1995 /**
1996  * xmlSchemaVTypeErrMemory:
1997  * @node: a context node
1998  * @extra:  extra informations
1999  *
2000  * Handle an out of memory condition
2001  */
2002 static void
2003 xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
2004                     const char *extra, xmlNodePtr node)
2005 {
2006     if (ctxt != NULL) {
2007         ctxt->nberrors++;
2008         ctxt->err = XML_SCHEMAV_INTERNAL;
2009     }
2010     __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
2011                      extra);
2012 }
2013
2014 static void LIBXML_ATTR_FORMAT(2,0)
2015 xmlSchemaPSimpleInternalErr(xmlNodePtr node,
2016                             const char *msg, const xmlChar *str)
2017 {
2018      __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node,
2019          msg, (const char *) str);
2020 }
2021
2022 #define WXS_ERROR_TYPE_ERROR 1
2023 #define WXS_ERROR_TYPE_WARNING 2
2024 /**
2025  * xmlSchemaErr4Line:
2026  * @ctxt: the validation context
2027  * @errorLevel: the error level
2028  * @error: the error code
2029  * @node: the context node
2030  * @line: the line number
2031  * @msg: the error message
2032  * @str1: extra data
2033  * @str2: extra data
2034  * @str3: extra data
2035  * @str4: extra data
2036  *
2037  * Handle a validation error
2038  */
2039 static void LIBXML_ATTR_FORMAT(6,0)
2040 xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
2041                   xmlErrorLevel errorLevel,
2042                   int error, xmlNodePtr node, int line, const char *msg,
2043                   const xmlChar *str1, const xmlChar *str2,
2044                   const xmlChar *str3, const xmlChar *str4)
2045 {
2046     xmlStructuredErrorFunc schannel = NULL;
2047     xmlGenericErrorFunc channel = NULL;
2048     void *data = NULL;
2049
2050     if (ctxt != NULL) {
2051         if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2052             xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
2053             const char *file = NULL;
2054             int col = 0;
2055             if (errorLevel != XML_ERR_WARNING) {
2056                 vctxt->nberrors++;
2057                 vctxt->err = error;
2058                 channel = vctxt->error;
2059             } else {
2060                 channel = vctxt->warning;
2061             }
2062             schannel = vctxt->serror;
2063             data = vctxt->errCtxt;
2064
2065             /*
2066             * Error node. If we specify a line number, then
2067             * do not channel any node to the error function.
2068             */
2069             if (line == 0) {
2070                 if ((node == NULL) &&
2071                     (vctxt->depth >= 0) &&
2072                     (vctxt->inode != NULL)) {
2073                     node = vctxt->inode->node;
2074                 }
2075                 /*
2076                 * Get filename and line if no node-tree.
2077                 */
2078                 if ((node == NULL) &&
2079                     (vctxt->parserCtxt != NULL) &&
2080                     (vctxt->parserCtxt->input != NULL)) {
2081                     file = vctxt->parserCtxt->input->filename;
2082                     line = vctxt->parserCtxt->input->line;
2083                     col = vctxt->parserCtxt->input->col;
2084                 }
2085             } else {
2086                 /*
2087                 * Override the given node's (if any) position
2088                 * and channel only the given line number.
2089                 */
2090                 node = NULL;
2091                 /*
2092                 * Get filename.
2093                 */
2094                 if (vctxt->doc != NULL)
2095                     file = (const char *) vctxt->doc->URL;
2096                 else if ((vctxt->parserCtxt != NULL) &&
2097                     (vctxt->parserCtxt->input != NULL))
2098                     file = vctxt->parserCtxt->input->filename;
2099             }
2100             if (vctxt->locFunc != NULL) {
2101                 if ((file == NULL) || (line == 0)) {
2102                     unsigned long l;
2103                     const char *f;
2104                     vctxt->locFunc(vctxt->locCtxt, &f, &l);
2105                     if (file == NULL)
2106                         file = f;
2107                     if (line == 0)
2108                         line = (int) l;
2109                 }
2110             }
2111             if ((file == NULL) && (vctxt->filename != NULL))
2112                 file = vctxt->filename;
2113
2114             __xmlRaiseError(schannel, channel, data, ctxt,
2115                 node, XML_FROM_SCHEMASV,
2116                 error, errorLevel, file, line,
2117                 (const char *) str1, (const char *) str2,
2118                 (const char *) str3, 0, col, msg, str1, str2, str3, str4);
2119
2120         } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2121             xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
2122             if (errorLevel != XML_ERR_WARNING) {
2123                 pctxt->nberrors++;
2124                 pctxt->err = error;
2125                 channel = pctxt->error;
2126             } else {
2127                 channel = pctxt->warning;
2128             }
2129             schannel = pctxt->serror;
2130             data = pctxt->errCtxt;
2131             __xmlRaiseError(schannel, channel, data, ctxt,
2132                 node, XML_FROM_SCHEMASP, error,
2133                 errorLevel, NULL, 0,
2134                 (const char *) str1, (const char *) str2,
2135                 (const char *) str3, 0, 0, msg, str1, str2, str3, str4);
2136         } else {
2137             TODO
2138         }
2139     }
2140 }
2141
2142 /**
2143  * xmlSchemaErr3:
2144  * @ctxt: the validation context
2145  * @node: the context node
2146  * @error: the error code
2147  * @msg: the error message
2148  * @str1: extra data
2149  * @str2: extra data
2150  * @str3: extra data
2151  *
2152  * Handle a validation error
2153  */
2154 static void LIBXML_ATTR_FORMAT(4,0)
2155 xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
2156               int error, xmlNodePtr node, const char *msg,
2157               const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
2158 {
2159     xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2160         msg, str1, str2, str3, NULL);
2161 }
2162
2163 static void LIBXML_ATTR_FORMAT(4,0)
2164 xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
2165               int error, xmlNodePtr node, const char *msg,
2166               const xmlChar *str1, const xmlChar *str2,
2167               const xmlChar *str3, const xmlChar *str4)
2168 {
2169     xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2170         msg, str1, str2, str3, str4);
2171 }
2172
2173 static void LIBXML_ATTR_FORMAT(4,0)
2174 xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2175              int error, xmlNodePtr node, const char *msg,
2176              const xmlChar *str1, const xmlChar *str2)
2177 {
2178     xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
2179 }
2180
2181 static xmlChar *
2182 xmlSchemaFormatNodeForError(xmlChar ** msg,
2183                             xmlSchemaAbstractCtxtPtr actxt,
2184                             xmlNodePtr node)
2185 {
2186     xmlChar *str = NULL;
2187
2188     *msg = NULL;
2189     if ((node != NULL) &&
2190         (node->type != XML_ELEMENT_NODE) &&
2191         (node->type != XML_ATTRIBUTE_NODE))
2192     {
2193         /*
2194         * Don't try to format other nodes than element and
2195         * attribute nodes.
2196         * Play safe and return an empty string.
2197         */
2198         *msg = xmlStrdup(BAD_CAST "");
2199         return(*msg);
2200     }
2201     if (node != NULL) {
2202         /*
2203         * Work on tree nodes.
2204         */
2205         if (node->type == XML_ATTRIBUTE_NODE) {
2206             xmlNodePtr elem = node->parent;
2207
2208             *msg = xmlStrdup(BAD_CAST "Element '");
2209             if (elem->ns != NULL)
2210                 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2211                     elem->ns->href, elem->name));
2212             else
2213                 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2214                     NULL, elem->name));
2215             FREE_AND_NULL(str);
2216             *msg = xmlStrcat(*msg, BAD_CAST "', ");
2217             *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2218         } else {
2219             *msg = xmlStrdup(BAD_CAST "Element '");
2220         }
2221         if (node->ns != NULL)
2222             *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2223             node->ns->href, node->name));
2224         else
2225             *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2226             NULL, node->name));
2227         FREE_AND_NULL(str);
2228         *msg = xmlStrcat(*msg, BAD_CAST "': ");
2229     } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2230         xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2231         /*
2232         * Work on node infos.
2233         */
2234         if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2235             xmlSchemaNodeInfoPtr ielem =
2236                 vctxt->elemInfos[vctxt->depth];
2237
2238             *msg = xmlStrdup(BAD_CAST "Element '");
2239             *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2240                 ielem->nsName, ielem->localName));
2241             FREE_AND_NULL(str);
2242             *msg = xmlStrcat(*msg, BAD_CAST "', ");
2243             *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2244         } else {
2245             *msg = xmlStrdup(BAD_CAST "Element '");
2246         }
2247         *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2248             vctxt->inode->nsName, vctxt->inode->localName));
2249         FREE_AND_NULL(str);
2250         *msg = xmlStrcat(*msg, BAD_CAST "': ");
2251     } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
2252         /*
2253         * Hmm, no node while parsing?
2254         * Return an empty string, in case NULL will break something.
2255         */
2256         *msg = xmlStrdup(BAD_CAST "");
2257     } else {
2258         TODO
2259         return (NULL);
2260     }
2261
2262     /*
2263      * xmlSchemaFormatItemForReport() also returns an escaped format
2264      * string, so do this before calling it below (in the future).
2265      */
2266     xmlEscapeFormatString(msg);
2267
2268     /*
2269     * VAL TODO: The output of the given schema component is currently
2270     * disabled.
2271     */
2272 #if 0
2273     if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2274         *msg = xmlStrcat(*msg, BAD_CAST " [");
2275         *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2276             NULL, type, NULL, 0));
2277         FREE_AND_NULL(str)
2278         *msg = xmlStrcat(*msg, BAD_CAST "]");
2279     }
2280 #endif
2281     return (*msg);
2282 }
2283
2284 static void LIBXML_ATTR_FORMAT(3,0)
2285 xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
2286                      const char *funcName,
2287                      const char *message,
2288                      const xmlChar *str1,
2289                      const xmlChar *str2)
2290 {
2291     xmlChar *msg = NULL;
2292
2293     if (actxt == NULL)
2294         return;
2295     msg = xmlStrdup(BAD_CAST "Internal error: %s, ");
2296     msg = xmlStrcat(msg, BAD_CAST message);
2297     msg = xmlStrcat(msg, BAD_CAST ".\n");
2298
2299     if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2300         xmlSchemaErr3(actxt, XML_SCHEMAV_INTERNAL, NULL,
2301             (const char *) msg, (const xmlChar *) funcName, str1, str2);
2302     else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
2303         xmlSchemaErr3(actxt, XML_SCHEMAP_INTERNAL, NULL,
2304             (const char *) msg, (const xmlChar *) funcName, str1, str2);
2305
2306     FREE_AND_NULL(msg)
2307 }
2308
2309 static void LIBXML_ATTR_FORMAT(3,0)
2310 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2311                      const char *funcName,
2312                      const char *message)
2313 {
2314     xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2315 }
2316
2317 #if 0
2318 static void LIBXML_ATTR_FORMAT(3,0)
2319 xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2320                      const char *funcName,
2321                      const char *message,
2322                      const xmlChar *str1,
2323                      const xmlChar *str2)
2324 {
2325     xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
2326         str1, str2);
2327 }
2328 #endif
2329
2330 static void LIBXML_ATTR_FORMAT(5,0)
2331 xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2332                    xmlParserErrors error,
2333                    xmlNodePtr node,
2334                    xmlSchemaBasicItemPtr item,
2335                    const char *message,
2336                    const xmlChar *str1, const xmlChar *str2,
2337                    const xmlChar *str3, const xmlChar *str4)
2338 {
2339     xmlChar *msg = NULL;
2340
2341     if ((node == NULL) && (item != NULL) &&
2342         (actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2343         node = WXS_ITEM_NODE(item);
2344         xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2345         msg = xmlStrcat(msg, BAD_CAST ": ");
2346     } else
2347         xmlSchemaFormatNodeForError(&msg, actxt, node);
2348     msg = xmlStrcat(msg, (const xmlChar *) message);
2349     msg = xmlStrcat(msg, BAD_CAST ".\n");
2350     xmlSchemaErr4(actxt, error, node,
2351         (const char *) msg, str1, str2, str3, str4);
2352     FREE_AND_NULL(msg)
2353 }
2354
2355 static void LIBXML_ATTR_FORMAT(5,0)
2356 xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2357                    xmlParserErrors error,
2358                    xmlNodePtr node,
2359                    xmlSchemaBasicItemPtr item,
2360                    const char *message,
2361                    const xmlChar *str1,
2362                    const xmlChar *str2)
2363 {
2364     xmlSchemaCustomErr4(actxt, error, node, item,
2365         message, str1, str2, NULL, NULL);
2366 }
2367
2368
2369
2370 static void LIBXML_ATTR_FORMAT(5,0)
2371 xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2372                    xmlParserErrors error,
2373                    xmlNodePtr node,
2374                    xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2375                    const char *message,
2376                    const xmlChar *str1,
2377                    const xmlChar *str2,
2378                    const xmlChar *str3)
2379 {
2380     xmlChar *msg = NULL;
2381
2382     xmlSchemaFormatNodeForError(&msg, actxt, node);
2383     msg = xmlStrcat(msg, (const xmlChar *) message);
2384     msg = xmlStrcat(msg, BAD_CAST ".\n");
2385
2386     /* URGENT TODO: Set the error code to something sane. */
2387     xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2388         (const char *) msg, str1, str2, str3, NULL);
2389
2390     FREE_AND_NULL(msg)
2391 }
2392
2393
2394
2395 static void LIBXML_ATTR_FORMAT(5,0)
2396 xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2397                    xmlParserErrors error,
2398                    xmlSchemaPSVIIDCNodePtr idcNode,
2399                    xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2400                    const char *message,
2401                    const xmlChar *str1,
2402                    const xmlChar *str2)
2403 {
2404     xmlChar *msg = NULL, *qname = NULL;
2405
2406     msg = xmlStrdup(BAD_CAST "Element '%s': ");
2407     msg = xmlStrcat(msg, (const xmlChar *) message);
2408     msg = xmlStrcat(msg, BAD_CAST ".\n");
2409     xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
2410         error, NULL, idcNode->nodeLine, (const char *) msg,
2411         xmlSchemaFormatQName(&qname,
2412             vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2413             vctxt->nodeQNames->items[idcNode->nodeQNameID]),
2414         str1, str2, NULL);
2415     FREE_AND_NULL(qname);
2416     FREE_AND_NULL(msg);
2417 }
2418
2419 static int
2420 xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2421                            xmlNodePtr node)
2422 {
2423     if (node != NULL)
2424         return (node->type);
2425     if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2426         (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2427         return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2428     return (-1);
2429 }
2430
2431 static int
2432 xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2433 {
2434     switch (item->type) {
2435         case XML_SCHEMA_TYPE_COMPLEX:
2436         case XML_SCHEMA_TYPE_SIMPLE:
2437             if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2438                 return(1);
2439             break;
2440         case XML_SCHEMA_TYPE_GROUP:
2441             return (1);
2442         case XML_SCHEMA_TYPE_ELEMENT:
2443             if ( ((xmlSchemaElementPtr) item)->flags &
2444                 XML_SCHEMAS_ELEM_GLOBAL)
2445                 return(1);
2446             break;
2447         case XML_SCHEMA_TYPE_ATTRIBUTE:
2448             if ( ((xmlSchemaAttributePtr) item)->flags &
2449                 XML_SCHEMAS_ATTR_GLOBAL)
2450                 return(1);
2451             break;
2452         /* Note that attribute groups are always global. */
2453         default:
2454             return(1);
2455     }
2456     return (0);
2457 }
2458
2459 static void
2460 xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2461                        xmlParserErrors error,
2462                        xmlNodePtr node,
2463                        const xmlChar *value,
2464                        xmlSchemaTypePtr type,
2465                        int displayValue)
2466 {
2467     xmlChar *msg = NULL;
2468
2469     xmlSchemaFormatNodeForError(&msg, actxt, node);
2470
2471     if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2472             XML_ATTRIBUTE_NODE))
2473         msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2474     else
2475         msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2476             "value of ");
2477
2478     if (! xmlSchemaIsGlobalItem(type))
2479         msg = xmlStrcat(msg, BAD_CAST "the local ");
2480     else
2481         msg = xmlStrcat(msg, BAD_CAST "the ");
2482
2483     if (WXS_IS_ATOMIC(type))
2484         msg = xmlStrcat(msg, BAD_CAST "atomic type");
2485     else if (WXS_IS_LIST(type))
2486         msg = xmlStrcat(msg, BAD_CAST "list type");
2487     else if (WXS_IS_UNION(type))
2488         msg = xmlStrcat(msg, BAD_CAST "union type");
2489
2490     if (xmlSchemaIsGlobalItem(type)) {
2491         xmlChar *str = NULL;
2492         msg = xmlStrcat(msg, BAD_CAST " '");
2493         if (type->builtInType != 0) {
2494             msg = xmlStrcat(msg, BAD_CAST "xs:");
2495             str = xmlStrdup(type->name);
2496         } else {
2497             const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
2498             if (!str)
2499                 str = xmlStrdup(qName);
2500         }
2501         msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
2502         msg = xmlStrcat(msg, BAD_CAST "'");
2503         FREE_AND_NULL(str);
2504     }
2505     msg = xmlStrcat(msg, BAD_CAST ".\n");
2506     if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2507             XML_ATTRIBUTE_NODE))
2508         xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2509     else
2510         xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2511     FREE_AND_NULL(msg)
2512 }
2513
2514 static const xmlChar *
2515 xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2516                               xmlSchemaNodeInfoPtr ni,
2517                               xmlNodePtr node)
2518 {
2519     if (node != NULL) {
2520         if (node->ns != NULL)
2521             return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2522         else
2523             return (xmlSchemaFormatQName(str, NULL, node->name));
2524     } else if (ni != NULL)
2525         return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2526     return (NULL);
2527 }
2528
2529 static void
2530 xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2531                         xmlParserErrors error,
2532                         xmlSchemaAttrInfoPtr ni,
2533                         xmlNodePtr node)
2534 {
2535     xmlChar *msg = NULL, *str = NULL;
2536
2537     xmlSchemaFormatNodeForError(&msg, actxt, node);
2538     msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2539     xmlSchemaErr(actxt, error, node, (const char *) msg,
2540         xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2541         NULL);
2542     FREE_AND_NULL(str)
2543     FREE_AND_NULL(msg)
2544 }
2545
2546 static void LIBXML_ATTR_FORMAT(5,0)
2547 xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2548                         xmlParserErrors error,
2549                         xmlNodePtr node,
2550                         xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2551                         const char *message,
2552                         int nbval,
2553                         int nbneg,
2554                         xmlChar **values)
2555 {
2556     xmlChar *str = NULL, *msg = NULL;
2557     xmlChar *localName, *nsName;
2558     const xmlChar *cur, *end;
2559     int i;
2560
2561     xmlSchemaFormatNodeForError(&msg, actxt, node);
2562     msg = xmlStrcat(msg, (const xmlChar *) message);
2563     msg = xmlStrcat(msg, BAD_CAST ".");
2564     /*
2565     * Note that is does not make sense to report that we have a
2566     * wildcard here, since the wildcard might be unfolded into
2567     * multiple transitions.
2568     */
2569     if (nbval + nbneg > 0) {
2570         if (nbval + nbneg > 1) {
2571             str = xmlStrdup(BAD_CAST " Expected is one of ( ");
2572         } else
2573             str = xmlStrdup(BAD_CAST " Expected is ( ");
2574         nsName = NULL;
2575
2576         for (i = 0; i < nbval + nbneg; i++) {
2577             cur = values[i];
2578             if (cur == NULL)
2579                 continue;
2580             if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2581                 (cur[3] == ' ')) {
2582                 cur += 4;
2583                 str = xmlStrcat(str, BAD_CAST "##other");
2584             }
2585             /*
2586             * Get the local name.
2587             */
2588             localName = NULL;
2589
2590             end = cur;
2591             if (*end == '*') {
2592                 localName = xmlStrdup(BAD_CAST "*");
2593                 end++;
2594             } else {
2595                 while ((*end != 0) && (*end != '|'))
2596                     end++;
2597                 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
2598             }
2599             if (*end != 0) {
2600                 end++;
2601                 /*
2602                 * Skip "*|*" if they come with negated expressions, since
2603                 * they represent the same negated wildcard.
2604                 */
2605                 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2606                     /*
2607                     * Get the namespace name.
2608                     */
2609                     cur = end;
2610                     if (*end == '*') {
2611                         nsName = xmlStrdup(BAD_CAST "{*}");
2612                     } else {
2613                         while (*end != 0)
2614                             end++;
2615
2616                         if (i >= nbval)
2617                             nsName = xmlStrdup(BAD_CAST "{##other:");
2618                         else
2619                             nsName = xmlStrdup(BAD_CAST "{");
2620
2621                         nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2622                         nsName = xmlStrcat(nsName, BAD_CAST "}");
2623                     }
2624                     str = xmlStrcat(str, BAD_CAST nsName);
2625                     FREE_AND_NULL(nsName)
2626                 } else {
2627                     FREE_AND_NULL(localName);
2628                     continue;
2629                 }
2630             }
2631             str = xmlStrcat(str, BAD_CAST localName);
2632             FREE_AND_NULL(localName);
2633
2634             if (i < nbval + nbneg -1)
2635                 str = xmlStrcat(str, BAD_CAST ", ");
2636         }
2637         str = xmlStrcat(str, BAD_CAST " ).\n");
2638         msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
2639         FREE_AND_NULL(str)
2640     } else
2641       msg = xmlStrcat(msg, BAD_CAST "\n");
2642     xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2643     xmlFree(msg);
2644 }
2645
2646 static void LIBXML_ATTR_FORMAT(8,0)
2647 xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2648                   xmlParserErrors error,
2649                   xmlNodePtr node,
2650                   const xmlChar *value,
2651                   unsigned long length,
2652                   xmlSchemaTypePtr type,
2653                   xmlSchemaFacetPtr facet,
2654                   const char *message,
2655                   const xmlChar *str1,
2656                   const xmlChar *str2)
2657 {
2658     xmlChar *str = NULL, *msg = NULL;
2659     xmlSchemaTypeType facetType;
2660     int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2661
2662     xmlSchemaFormatNodeForError(&msg, actxt, node);
2663     if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2664         facetType = XML_SCHEMA_FACET_ENUMERATION;
2665         /*
2666         * If enumerations are validated, one must not expect the
2667         * facet to be given.
2668         */
2669     } else
2670         facetType = facet->type;
2671     msg = xmlStrcat(msg, BAD_CAST "[");
2672     msg = xmlStrcat(msg, BAD_CAST "facet '");
2673     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2674     msg = xmlStrcat(msg, BAD_CAST "'] ");
2675     if (message == NULL) {
2676         /*
2677         * Use a default message.
2678         */
2679         if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2680             (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2681             (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2682
2683             char len[25], actLen[25];
2684
2685             /* FIXME, TODO: What is the max expected string length of the
2686             * this value?
2687             */
2688             if (nodeType == XML_ATTRIBUTE_NODE)
2689                 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2690             else
2691                 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2692
2693             snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2694             snprintf(actLen, 24, "%lu", length);
2695
2696             if (facetType == XML_SCHEMA_FACET_LENGTH)
2697                 msg = xmlStrcat(msg,
2698                 BAD_CAST "this differs from the allowed length of '%s'.\n");
2699             else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2700                 msg = xmlStrcat(msg,
2701                 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2702             else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2703                 msg = xmlStrcat(msg,
2704                 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2705
2706             if (nodeType == XML_ATTRIBUTE_NODE)
2707                 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2708                     value, (const xmlChar *) actLen, (const xmlChar *) len);
2709             else
2710                 xmlSchemaErr(actxt, error, node, (const char *) msg,
2711                     (const xmlChar *) actLen, (const xmlChar *) len);
2712
2713         } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2714             msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2715                 "of the set {%s}.\n");
2716             xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2717                 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2718         } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2719             msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2720                 "by the pattern '%s'.\n");
2721             xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2722                 facet->value);
2723         } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2724             msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2725                 "minimum value allowed ('%s').\n");
2726             xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2727                 facet->value);
2728         } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2729             msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2730                 "maximum value allowed ('%s').\n");
2731             xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2732                 facet->value);
2733         } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2734             msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
2735                 "'%s'.\n");
2736             xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2737                 facet->value);
2738         } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2739             msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2740                 "'%s'.\n");
2741             xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2742                 facet->value);
2743         } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2744             msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2745                 "digits than are allowed ('%s').\n");
2746             xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2747                 facet->value);
2748         } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2749             msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2750                 "digits than are allowed ('%s').\n");
2751             xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2752                 facet->value);
2753         } else if (nodeType == XML_ATTRIBUTE_NODE) {
2754             msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2755             xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2756         } else {
2757             msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2758             xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2759         }
2760     } else {
2761         msg = xmlStrcat(msg, (const xmlChar *) message);
2762         msg = xmlStrcat(msg, BAD_CAST ".\n");
2763         xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2764     }
2765     FREE_AND_NULL(str)
2766     xmlFree(msg);
2767 }
2768
2769 #define VERROR(err, type, msg) \
2770     xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
2771
2772 #define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
2773
2774 #define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2775 #define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
2776
2777 #define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2778
2779
2780 /**
2781  * xmlSchemaPMissingAttrErr:
2782  * @ctxt: the schema validation context
2783  * @ownerDes: the designation of  the owner
2784  * @ownerName: the name of the owner
2785  * @ownerItem: the owner as a schema object
2786  * @ownerElem: the owner as an element node
2787  * @node: the parent element node of the missing attribute node
2788  * @type: the corresponding type of the attribute node
2789  *
2790  * Reports an illegal attribute.
2791  */
2792 static void
2793 xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
2794                          xmlParserErrors error,
2795                          xmlSchemaBasicItemPtr ownerItem,
2796                          xmlNodePtr ownerElem,
2797                          const char *name,
2798                          const char *message)
2799 {
2800     xmlChar *des = NULL;
2801
2802     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2803
2804     if (message != NULL)
2805         xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
2806     else
2807         xmlSchemaPErr(ctxt, ownerElem, error,
2808             "%s: The attribute '%s' is required but missing.\n",
2809             BAD_CAST des, BAD_CAST name);
2810     FREE_AND_NULL(des);
2811 }
2812
2813
2814 /**
2815  * xmlSchemaPResCompAttrErr:
2816  * @ctxt: the schema validation context
2817  * @error: the error code
2818  * @ownerDes: the designation of  the owner
2819  * @ownerItem: the owner as a schema object
2820  * @ownerElem: the owner as an element node
2821  * @name: the name of the attribute holding the QName
2822  * @refName: the referenced local name
2823  * @refURI: the referenced namespace URI
2824  * @message: optional message
2825  *
2826  * Used to report QName attribute values that failed to resolve
2827  * to schema components.
2828  */
2829 static void
2830 xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
2831                          xmlParserErrors error,
2832                          xmlSchemaBasicItemPtr ownerItem,
2833                          xmlNodePtr ownerElem,
2834                          const char *name,
2835                          const xmlChar *refName,
2836                          const xmlChar *refURI,
2837                          xmlSchemaTypeType refType,
2838                          const char *refTypeStr)
2839 {
2840     xmlChar *des = NULL, *strA = NULL;
2841
2842     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2843     if (refTypeStr == NULL)
2844         refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
2845         xmlSchemaPErrExt(ctxt, ownerElem, error,
2846             NULL, NULL, NULL,
2847             "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2848             "%s.\n", BAD_CAST des, BAD_CAST name,
2849             xmlSchemaFormatQName(&strA, refURI, refName),
2850             BAD_CAST refTypeStr, NULL);
2851     FREE_AND_NULL(des)
2852     FREE_AND_NULL(strA)
2853 }
2854
2855 /**
2856  * xmlSchemaPCustomAttrErr:
2857  * @ctxt: the schema parser context
2858  * @error: the error code
2859  * @ownerDes: the designation of the owner
2860  * @ownerItem: the owner as a schema object
2861  * @attr: the illegal attribute node
2862  *
2863  * Reports an illegal attribute during the parse.
2864  */
2865 static void
2866 xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
2867                         xmlParserErrors error,
2868                         xmlChar **ownerDes,
2869                         xmlSchemaBasicItemPtr ownerItem,
2870                         xmlAttrPtr attr,
2871                         const char *msg)
2872 {
2873     xmlChar *des = NULL;
2874
2875     if (ownerDes == NULL)
2876         xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
2877     else if (*ownerDes == NULL) {
2878         xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
2879         des = *ownerDes;
2880     } else
2881         des = *ownerDes;
2882     if (attr == NULL) {
2883         xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL,
2884             "%s, attribute '%s': %s.\n",
2885             BAD_CAST des, (const xmlChar *) "Unknown",
2886             (const xmlChar *) msg, NULL, NULL);
2887     } else {
2888         xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2889             "%s, attribute '%s': %s.\n",
2890             BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2891     }
2892     if (ownerDes == NULL)
2893         FREE_AND_NULL(des);
2894 }
2895
2896 /**
2897  * xmlSchemaPIllegalAttrErr:
2898  * @ctxt: the schema parser context
2899  * @error: the error code
2900  * @ownerDes: the designation of the attribute's owner
2901  * @ownerItem: the attribute's owner item
2902  * @attr: the illegal attribute node
2903  *
2904  * Reports an illegal attribute during the parse.
2905  */
2906 static void
2907 xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
2908                          xmlParserErrors error,
2909                          xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
2910                          xmlAttrPtr attr)
2911 {
2912     xmlChar *strA = NULL, *strB = NULL;
2913
2914     xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2915     xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2916         "%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2917         xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2918         NULL, NULL);
2919     FREE_AND_NULL(strA);
2920     FREE_AND_NULL(strB);
2921 }
2922
2923 /**
2924  * xmlSchemaPCustomErr:
2925  * @ctxt: the schema parser context
2926  * @error: the error code
2927  * @itemDes: the designation of the schema item
2928  * @item: the schema item
2929  * @itemElem: the node of the schema item
2930  * @message: the error message
2931  * @str1: an optional param for the error message
2932  * @str2: an optional param for the error message
2933  * @str3: an optional param for the error message
2934  *
2935  * Reports an error during parsing.
2936  */
2937 static void LIBXML_ATTR_FORMAT(5,0)
2938 xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
2939                     xmlParserErrors error,
2940                     xmlSchemaBasicItemPtr item,
2941                     xmlNodePtr itemElem,
2942                     const char *message,
2943                     const xmlChar *str1,
2944                     const xmlChar *str2,
2945                     const xmlChar *str3)
2946 {
2947     xmlChar *des = NULL, *msg = NULL;
2948
2949     xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
2950     msg = xmlStrdup(BAD_CAST "%s: ");
2951     msg = xmlStrcat(msg, (const xmlChar *) message);
2952     msg = xmlStrcat(msg, BAD_CAST ".\n");
2953     if ((itemElem == NULL) && (item != NULL))
2954         itemElem = WXS_ITEM_NODE(item);
2955     xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
2956         (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2957     FREE_AND_NULL(des);
2958     FREE_AND_NULL(msg);
2959 }
2960
2961 /**
2962  * xmlSchemaPCustomErr:
2963  * @ctxt: the schema parser context
2964  * @error: the error code
2965  * @itemDes: the designation of the schema item
2966  * @item: the schema item
2967  * @itemElem: the node of the schema item
2968  * @message: the error message
2969  * @str1: the optional param for the error message
2970  *
2971  * Reports an error during parsing.
2972  */
2973 static void LIBXML_ATTR_FORMAT(5,0)
2974 xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
2975                     xmlParserErrors error,
2976                     xmlSchemaBasicItemPtr item,
2977                     xmlNodePtr itemElem,
2978                     const char *message,
2979                     const xmlChar *str1)
2980 {
2981     xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
2982         str1, NULL, NULL);
2983 }
2984
2985 /**
2986  * xmlSchemaPAttrUseErr:
2987  * @ctxt: the schema parser context
2988  * @error: the error code
2989  * @itemDes: the designation of the schema type
2990  * @item: the schema type
2991  * @itemElem: the node of the schema type
2992  * @attr: the invalid schema attribute
2993  * @message: the error message
2994  * @str1: the optional param for the error message
2995  *
2996  * Reports an attribute use error during parsing.
2997  */
2998 static void LIBXML_ATTR_FORMAT(6,0)
2999 xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
3000                     xmlParserErrors error,
3001                     xmlNodePtr node,
3002                     xmlSchemaBasicItemPtr ownerItem,
3003                     const xmlSchemaAttributeUsePtr attruse,
3004                     const char *message,
3005                     const xmlChar *str1, const xmlChar *str2,
3006                     const xmlChar *str3,const xmlChar *str4)
3007 {
3008     xmlChar *str = NULL, *msg = NULL;
3009
3010     xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
3011     msg = xmlStrcat(msg, BAD_CAST ", ");
3012     msg = xmlStrcat(msg,
3013         BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
3014         WXS_BASIC_CAST attruse, NULL));
3015     FREE_AND_NULL(str);
3016     msg = xmlStrcat(msg, BAD_CAST ": ");
3017     msg = xmlStrcat(msg, (const xmlChar *) message);
3018     msg = xmlStrcat(msg, BAD_CAST ".\n");
3019     xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
3020         (const char *) msg, str1, str2, str3, str4);
3021     xmlFree(msg);
3022 }
3023
3024 /**
3025  * xmlSchemaPIllegalFacetAtomicErr:
3026  * @ctxt: the schema parser context
3027  * @error: the error code
3028  * @type: the schema type
3029  * @baseType: the base type of type
3030  * @facet: the illegal facet
3031  *
3032  * Reports an illegal facet for atomic simple types.
3033  */
3034 static void
3035 xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
3036                           xmlParserErrors error,
3037                           xmlSchemaTypePtr type,
3038                           xmlSchemaTypePtr baseType,
3039                           xmlSchemaFacetPtr facet)
3040 {
3041     xmlChar *des = NULL, *strT = NULL;
3042
3043     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
3044     xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
3045         "%s: The facet '%s' is not allowed on types derived from the "
3046         "type %s.\n",
3047         BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
3048         xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
3049         NULL, NULL);
3050     FREE_AND_NULL(des);
3051     FREE_AND_NULL(strT);
3052 }
3053
3054 /**
3055  * xmlSchemaPIllegalFacetListUnionErr:
3056  * @ctxt: the schema parser context
3057  * @error: the error code
3058  * @itemDes: the designation of the schema item involved
3059  * @item: the schema item involved
3060  * @facet: the illegal facet
3061  *
3062  * Reports an illegal facet for <list> and <union>.
3063  */
3064 static void
3065 xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
3066                           xmlParserErrors error,
3067                           xmlSchemaTypePtr type,
3068                           xmlSchemaFacetPtr facet)
3069 {
3070     xmlChar *des = NULL;
3071
3072     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3073         type->node);
3074     xmlSchemaPErr(ctxt, type->node, error,
3075         "%s: The facet '%s' is not allowed.\n",
3076         BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
3077     FREE_AND_NULL(des);
3078 }
3079
3080 /**
3081  * xmlSchemaPMutualExclAttrErr:
3082  * @ctxt: the schema validation context
3083  * @error: the error code
3084  * @elemDes: the designation of the parent element node
3085  * @attr: the bad attribute node
3086  * @type: the corresponding type of the attribute node
3087  *
3088  * Reports an illegal attribute.
3089  */
3090 static void
3091 xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3092                          xmlParserErrors error,
3093                          xmlSchemaBasicItemPtr ownerItem,
3094                          xmlAttrPtr attr,
3095                          const char *name1,
3096                          const char *name2)
3097 {
3098     xmlChar *des = NULL;
3099
3100     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
3101     xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
3102         "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
3103         BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
3104     FREE_AND_NULL(des);
3105 }
3106
3107 /**
3108  * xmlSchemaPSimpleTypeErr:
3109  * @ctxt:  the schema validation context
3110  * @error: the error code
3111  * @type: the type specifier
3112  * @ownerDes: the designation of the owner
3113  * @ownerItem: the schema object if existent
3114  * @node: the validated node
3115  * @value: the validated value
3116  *
3117  * Reports a simple type validation error.
3118  * TODO: Should this report the value of an element as well?
3119  */
3120 static void LIBXML_ATTR_FORMAT(8,0)
3121 xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3122                         xmlParserErrors error,
3123                         xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
3124                         xmlNodePtr node,
3125                         xmlSchemaTypePtr type,
3126                         const char *expected,
3127                         const xmlChar *value,
3128                         const char *message,
3129                         const xmlChar *str1,
3130                         const xmlChar *str2)
3131 {
3132     xmlChar *msg = NULL;
3133
3134     xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
3135     if (message == NULL) {
3136         /*
3137         * Use default messages.
3138         */
3139         if (type != NULL) {
3140             if (node->type == XML_ATTRIBUTE_NODE)
3141                 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3142             else
3143                 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3144                 "valid value of ");
3145             if (! xmlSchemaIsGlobalItem(type))
3146                 msg = xmlStrcat(msg, BAD_CAST "the local ");
3147             else
3148                 msg = xmlStrcat(msg, BAD_CAST "the ");
3149
3150             if (WXS_IS_ATOMIC(type))
3151                 msg = xmlStrcat(msg, BAD_CAST "atomic type");
3152             else if (WXS_IS_LIST(type))
3153                 msg = xmlStrcat(msg, BAD_CAST "list type");
3154             else if (WXS_IS_UNION(type))
3155                 msg = xmlStrcat(msg, BAD_CAST "union type");
3156
3157             if (xmlSchemaIsGlobalItem(type)) {
3158                 xmlChar *str = NULL;
3159                 msg = xmlStrcat(msg, BAD_CAST " '");
3160                 if (type->builtInType != 0) {
3161                     msg = xmlStrcat(msg, BAD_CAST "xs:");
3162                     str = xmlStrdup(type->name);
3163                 } else {
3164                     const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
3165                     if (!str)
3166                         str = xmlStrdup(qName);
3167                 }
3168                 msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
3169                 msg = xmlStrcat(msg, BAD_CAST "'.");
3170                 FREE_AND_NULL(str);
3171             }
3172         } else {
3173             if (node->type == XML_ATTRIBUTE_NODE)
3174                 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3175             else
3176                 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3177                 "valid.");
3178         }
3179         if (expected) {
3180             xmlChar *expectedEscaped = xmlCharStrdup(expected);
3181             msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3182             msg = xmlStrcat(msg, xmlEscapeFormatString(&expectedEscaped));
3183             FREE_AND_NULL(expectedEscaped);
3184             msg = xmlStrcat(msg, BAD_CAST "'.\n");
3185         } else
3186             msg = xmlStrcat(msg, BAD_CAST "\n");
3187         if (node->type == XML_ATTRIBUTE_NODE)
3188             xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3189         else
3190             xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3191     } else {
3192         msg = xmlStrcat(msg, BAD_CAST message);
3193         msg = xmlStrcat(msg, BAD_CAST ".\n");
3194         xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
3195              (const char*) msg, str1, str2, NULL, NULL, NULL);
3196     }
3197     /* Cleanup. */
3198     FREE_AND_NULL(msg)
3199 }
3200
3201 /**
3202  * xmlSchemaPContentErr:
3203  * @ctxt: the schema parser context
3204  * @error: the error code
3205  * @onwerDes: the designation of the holder of the content
3206  * @ownerItem: the owner item of the holder of the content
3207  * @ownerElem: the node of the holder of the content
3208  * @child: the invalid child node
3209  * @message: the optional error message
3210  * @content: the optional string describing the correct content
3211  *
3212  * Reports an error concerning the content of a schema element.
3213  */
3214 static void
3215 xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
3216                      xmlParserErrors error,
3217                      xmlSchemaBasicItemPtr ownerItem,
3218                      xmlNodePtr ownerElem,
3219                      xmlNodePtr child,
3220                      const char *message,
3221                      const char *content)
3222 {
3223     xmlChar *des = NULL;
3224
3225     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
3226     if (message != NULL)
3227         xmlSchemaPErr2(ctxt, ownerElem, child, error,
3228             "%s: %s.\n",
3229             BAD_CAST des, BAD_CAST message);
3230     else {
3231         if (content != NULL) {
3232             xmlSchemaPErr2(ctxt, ownerElem, child, error,
3233                 "%s: The content is not valid. Expected is %s.\n",
3234                 BAD_CAST des, BAD_CAST content);
3235         } else {
3236             xmlSchemaPErr2(ctxt, ownerElem, child, error,
3237                 "%s: The content is not valid.\n",
3238                 BAD_CAST des, NULL);
3239         }
3240     }
3241     FREE_AND_NULL(des)
3242 }
3243
3244 /************************************************************************
3245  *                                                                      *
3246  *                      Streamable error functions                      *
3247  *                                                                      *
3248  ************************************************************************/
3249
3250
3251
3252
3253 /************************************************************************
3254  *                                                                      *
3255  *                      Validation helper functions                     *
3256  *                                                                      *
3257  ************************************************************************/
3258
3259
3260 /************************************************************************
3261  *                                                                      *
3262  *                      Allocation functions                            *
3263  *                                                                      *
3264  ************************************************************************/
3265
3266 /**
3267  * xmlSchemaNewSchemaForParserCtxt:
3268  * @ctxt:  a schema validation context
3269  *
3270  * Allocate a new Schema structure.
3271  *
3272  * Returns the newly allocated structure or NULL in case or error
3273  */
3274 static xmlSchemaPtr
3275 xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3276 {
3277     xmlSchemaPtr ret;
3278
3279     ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3280     if (ret == NULL) {
3281         xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
3282         return (NULL);
3283     }
3284     memset(ret, 0, sizeof(xmlSchema));
3285     ret->dict = ctxt->dict;
3286     xmlDictReference(ret->dict);
3287
3288     return (ret);
3289 }
3290
3291 /**
3292  * xmlSchemaNewFacet:
3293  *
3294  * Allocate a new Facet structure.
3295  *
3296  * Returns the newly allocated structure or NULL in case or error
3297  */
3298 xmlSchemaFacetPtr
3299 xmlSchemaNewFacet(void)
3300 {
3301     xmlSchemaFacetPtr ret;
3302
3303     ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3304     if (ret == NULL) {
3305         return (NULL);
3306     }
3307     memset(ret, 0, sizeof(xmlSchemaFacet));
3308
3309     return (ret);
3310 }
3311
3312 /**
3313  * xmlSchemaNewAnnot:
3314  * @ctxt:  a schema validation context
3315  * @node:  a node
3316  *
3317  * Allocate a new annotation structure.
3318  *
3319  * Returns the newly allocated structure or NULL in case or error
3320  */
3321 static xmlSchemaAnnotPtr
3322 xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3323 {
3324     xmlSchemaAnnotPtr ret;
3325
3326     ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3327     if (ret == NULL) {
3328         xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
3329         return (NULL);
3330     }
3331     memset(ret, 0, sizeof(xmlSchemaAnnot));
3332     ret->content = node;
3333     return (ret);
3334 }
3335
3336 static xmlSchemaItemListPtr
3337 xmlSchemaItemListCreate(void)
3338 {
3339     xmlSchemaItemListPtr ret;
3340
3341     ret = xmlMalloc(sizeof(xmlSchemaItemList));
3342     if (ret == NULL) {
3343         xmlSchemaPErrMemory(NULL,
3344             "allocating an item list structure", NULL);
3345         return (NULL);
3346     }
3347     memset(ret, 0, sizeof(xmlSchemaItemList));
3348     return (ret);
3349 }
3350
3351 static void
3352 xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3353 {
3354     if (list->items != NULL) {
3355         xmlFree(list->items);
3356         list->items = NULL;
3357     }
3358     list->nbItems = 0;
3359     list->sizeItems = 0;
3360 }
3361
3362 static int
3363 xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3364 {
3365     if (list->items == NULL) {
3366         list->items = (void **) xmlMalloc(
3367             20 * sizeof(void *));
3368         if (list->items == NULL) {
3369             xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3370             return(-1);
3371         }
3372         list->sizeItems = 20;
3373     } else if (list->sizeItems <= list->nbItems) {
3374         list->sizeItems *= 2;
3375         list->items = (void **) xmlRealloc(list->items,
3376             list->sizeItems * sizeof(void *));
3377         if (list->items == NULL) {
3378             xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3379             list->sizeItems = 0;
3380             return(-1);
3381         }
3382     }
3383     list->items[list->nbItems++] = item;
3384     return(0);
3385 }
3386
3387 static int
3388 xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3389                          int initialSize,
3390                          void *item)
3391 {
3392     if (list->items == NULL) {
3393         if (initialSize <= 0)
3394             initialSize = 1;
3395         list->items = (void **) xmlMalloc(
3396             initialSize * sizeof(void *));
3397         if (list->items == NULL) {
3398             xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3399             return(-1);
3400         }
3401         list->sizeItems = initialSize;
3402     } else if (list->sizeItems <= list->nbItems) {
3403         list->sizeItems *= 2;
3404         list->items = (void **) xmlRealloc(list->items,
3405             list->sizeItems * sizeof(void *));
3406         if (list->items == NULL) {
3407             xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3408             list->sizeItems = 0;
3409             return(-1);
3410         }
3411     }
3412     list->items[list->nbItems++] = item;
3413     return(0);
3414 }
3415
3416 static int
3417 xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3418 {
3419     if (list->items == NULL) {
3420         list->items = (void **) xmlMalloc(
3421             20 * sizeof(void *));
3422         if (list->items == NULL) {
3423             xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3424             return(-1);
3425         }
3426         list->sizeItems = 20;
3427     } else if (list->sizeItems <= list->nbItems) {
3428         list->sizeItems *= 2;
3429         list->items = (void **) xmlRealloc(list->items,
3430             list->sizeItems * sizeof(void *));
3431         if (list->items == NULL) {
3432             xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3433             list->sizeItems = 0;
3434             return(-1);
3435         }
3436     }
3437     /*
3438     * Just append if the index is greater/equal than the item count.
3439     */
3440     if (idx >= list->nbItems) {
3441         list->items[list->nbItems++] = item;
3442     } else {
3443         int i;
3444         for (i = list->nbItems; i > idx; i--)
3445             list->items[i] = list->items[i-1];
3446         list->items[idx] = item;
3447         list->nbItems++;
3448     }
3449     return(0);
3450 }
3451
3452 #if 0 /* enable if ever needed */
3453 static int
3454 xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3455                             int initialSize,
3456                             void *item,
3457                             int idx)
3458 {
3459     if (list->items == NULL) {
3460         if (initialSize <= 0)
3461             initialSize = 1;
3462         list->items = (void **) xmlMalloc(
3463             initialSize * sizeof(void *));
3464         if (list->items == NULL) {
3465             xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3466             return(-1);
3467         }
3468         list->sizeItems = initialSize;
3469     } else if (list->sizeItems <= list->nbItems) {
3470         list->sizeItems *= 2;
3471         list->items = (void **) xmlRealloc(list->items,
3472             list->sizeItems * sizeof(void *));
3473         if (list->items == NULL) {
3474             xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3475             list->sizeItems = 0;
3476             return(-1);
3477         }
3478     }
3479     /*
3480     * Just append if the index is greater/equal than the item count.
3481     */
3482     if (idx >= list->nbItems) {
3483         list->items[list->nbItems++] = item;
3484     } else {
3485         int i;
3486         for (i = list->nbItems; i > idx; i--)
3487             list->items[i] = list->items[i-1];
3488         list->items[idx] = item;
3489         list->nbItems++;
3490     }
3491     return(0);
3492 }
3493 #endif
3494
3495 static int
3496 xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3497 {
3498     int i;
3499     if ((list->items == NULL) || (idx >= list->nbItems)) {
3500         xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3501             "index error.\n");
3502         return(-1);
3503     }
3504
3505     if (list->nbItems == 1) {
3506         /* TODO: Really free the list? */
3507         xmlFree(list->items);
3508         list->items = NULL;
3509         list->nbItems = 0;
3510         list->sizeItems = 0;
3511     } else if (list->nbItems -1 == idx) {
3512         list->nbItems--;
3513     } else {
3514         for (i = idx; i < list->nbItems -1; i++)
3515             list->items[i] = list->items[i+1];
3516         list->nbItems--;
3517     }
3518     return(0);
3519 }
3520
3521 /**
3522  * xmlSchemaItemListFree:
3523  * @annot:  a schema type structure
3524  *
3525  * Deallocate a annotation structure
3526  */
3527 static void
3528 xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3529 {
3530     if (list == NULL)
3531         return;
3532     if (list->items != NULL)
3533         xmlFree(list->items);
3534     xmlFree(list);
3535 }
3536
3537 static void
3538 xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
3539 {
3540     if (bucket == NULL)
3541         return;
3542     if (bucket->globals != NULL) {
3543         xmlSchemaComponentListFree(bucket->globals);
3544         xmlSchemaItemListFree(bucket->globals);
3545     }
3546     if (bucket->locals != NULL) {
3547         xmlSchemaComponentListFree(bucket->locals);
3548         xmlSchemaItemListFree(bucket->locals);
3549     }
3550     if (bucket->relations != NULL) {
3551         xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3552         do {
3553             prev = cur;
3554             cur = cur->next;
3555             xmlFree(prev);
3556         } while (cur != NULL);
3557     }
3558     if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3559         xmlFreeDoc(bucket->doc);
3560     }
3561     if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
3562         if (WXS_IMPBUCKET(bucket)->schema != NULL)
3563             xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
3564     }
3565     xmlFree(bucket);
3566 }
3567
3568 static xmlSchemaBucketPtr
3569 xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
3570                          int type, const xmlChar *targetNamespace)
3571 {
3572     xmlSchemaBucketPtr ret;
3573     int size;
3574     xmlSchemaPtr mainSchema;
3575
3576     if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
3577         PERROR_INT("xmlSchemaBucketCreate",
3578             "no main schema on constructor");
3579         return(NULL);
3580     }
3581     mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
3582     /* Create the schema bucket. */
3583     if (WXS_IS_BUCKET_INCREDEF(type))
3584         size = sizeof(xmlSchemaInclude);
3585     else
3586         size = sizeof(xmlSchemaImport);
3587     ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3588     if (ret == NULL) {
3589         xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3590         return(NULL);
3591     }
3592     memset(ret, 0, size);
3593     ret->targetNamespace = targetNamespace;
3594     ret->type = type;
3595     ret->globals = xmlSchemaItemListCreate();
3596     if (ret->globals == NULL) {
3597         xmlFree(ret);
3598         return(NULL);
3599     }
3600     ret->locals = xmlSchemaItemListCreate();
3601     if (ret->locals == NULL) {
3602         xmlFree(ret);
3603         return(NULL);
3604     }
3605     /*
3606     * The following will assure that only the first bucket is marked as
3607     * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3608     * For each following import buckets an xmlSchema will be created.
3609     * An xmlSchema will be created for every distinct targetNamespace.
3610     * We assign the targetNamespace to the schemata here.
3611     */
3612     if (! WXS_HAS_BUCKETS(pctxt)) {
3613         if (WXS_IS_BUCKET_INCREDEF(type)) {
3614             PERROR_INT("xmlSchemaBucketCreate",
3615                 "first bucket but it's an include or redefine");
3616             xmlSchemaBucketFree(ret);
3617             return(NULL);
3618         }
3619         /* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3620         ret->type = XML_SCHEMA_SCHEMA_MAIN;
3621         /* Point to the *main* schema. */
3622         WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3623         WXS_IMPBUCKET(ret)->schema = mainSchema;
3624         /*
3625         * Ensure that the main schema gets a targetNamespace.
3626         */
3627         mainSchema->targetNamespace = targetNamespace;
3628     } else {
3629         if (type == XML_SCHEMA_SCHEMA_MAIN) {
3630             PERROR_INT("xmlSchemaBucketCreate",
3631                 "main bucket but it's not the first one");
3632             xmlSchemaBucketFree(ret);
3633             return(NULL);
3634         } else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3635             /*
3636             * Create a schema for imports and assign the
3637             * targetNamespace.
3638             */
3639             WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3640             if (WXS_IMPBUCKET(ret)->schema == NULL) {
3641                 xmlSchemaBucketFree(ret);
3642                 return(NULL);
3643             }
3644             WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
3645         }
3646     }
3647     if (WXS_IS_BUCKET_IMPMAIN(type)) {
3648         int res;
3649         /*
3650         * Imports go into the "schemasImports" slot of the main *schema*.
3651         * Note that we create an import entry for the main schema as well; i.e.,
3652         * even if there's only one schema, we'll get an import.
3653         */
3654         if (mainSchema->schemasImports == NULL) {
3655             mainSchema->schemasImports = xmlHashCreateDict(5,
3656                 WXS_CONSTRUCTOR(pctxt)->dict);
3657             if (mainSchema->schemasImports == NULL) {
3658                 xmlSchemaBucketFree(ret);
3659                 return(NULL);
3660             }
3661         }
3662         if (targetNamespace == NULL)
3663             res = xmlHashAddEntry(mainSchema->schemasImports,
3664                 XML_SCHEMAS_NO_NAMESPACE, ret);
3665         else
3666             res = xmlHashAddEntry(mainSchema->schemasImports,
3667                 targetNamespace, ret);
3668         if (res != 0) {
3669             PERROR_INT("xmlSchemaBucketCreate",
3670                 "failed to add the schema bucket to the hash");
3671             xmlSchemaBucketFree(ret);
3672             return(NULL);
3673         }
3674     } else {
3675         /* Set the @ownerImport of an include bucket. */
3676         if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3677             WXS_INCBUCKET(ret)->ownerImport =
3678                 WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
3679         else
3680             WXS_INCBUCKET(ret)->ownerImport =
3681                 WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
3682
3683         /* Includes got into the "includes" slot of the *main* schema. */
3684         if (mainSchema->includes == NULL) {
3685             mainSchema->includes = xmlSchemaItemListCreate();
3686             if (mainSchema->includes == NULL) {
3687                 xmlSchemaBucketFree(ret);
3688                 return(NULL);
3689             }
3690         }
3691         xmlSchemaItemListAdd(mainSchema->includes, ret);
3692     }
3693     /*
3694     * Add to list of all buckets; this is used for lookup
3695     * during schema construction time only.
3696     */
3697     if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
3698         return(NULL);
3699     return(ret);
3700 }
3701
3702 static int
3703 xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
3704 {
3705     if (*list == NULL) {
3706         *list = xmlSchemaItemListCreate();
3707         if (*list == NULL)
3708             return(-1);
3709     }
3710     xmlSchemaItemListAddSize(*list, initialSize, item);
3711     return(0);
3712 }
3713
3714 /**
3715  * xmlSchemaFreeAnnot:
3716  * @annot:  a schema type structure
3717  *
3718  * Deallocate a annotation structure
3719  */
3720 static void
3721 xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3722 {
3723     if (annot == NULL)
3724         return;
3725     if (annot->next == NULL) {
3726         xmlFree(annot);
3727     } else {
3728         xmlSchemaAnnotPtr prev;
3729
3730         do {
3731             prev = annot;
3732             annot = annot->next;
3733             xmlFree(prev);
3734         } while (annot != NULL);
3735     }
3736 }
3737
3738 /**
3739  * xmlSchemaFreeNotation:
3740  * @schema:  a schema notation structure
3741  *
3742  * Deallocate a Schema Notation structure.
3743  */
3744 static void
3745 xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3746 {
3747     if (nota == NULL)
3748         return;
3749     xmlFree(nota);
3750 }
3751
3752 /**
3753  * xmlSchemaFreeAttribute:
3754  * @attr:  an attribute declaration
3755  *
3756  * Deallocates an attribute declaration structure.
3757  */
3758 static void
3759 xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3760 {
3761     if (attr == NULL)
3762         return;
3763     if (attr->annot != NULL)
3764         xmlSchemaFreeAnnot(attr->annot);
3765     if (attr->defVal != NULL)
3766         xmlSchemaFreeValue(attr->defVal);
3767     xmlFree(attr);
3768 }
3769
3770 /**
3771  * xmlSchemaFreeAttributeUse:
3772  * @use:  an attribute use
3773  *
3774  * Deallocates an attribute use structure.
3775  */
3776 static void
3777 xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3778 {
3779     if (use == NULL)
3780         return;
3781     if (use->annot != NULL)
3782         xmlSchemaFreeAnnot(use->annot);
3783     if (use->defVal != NULL)
3784         xmlSchemaFreeValue(use->defVal);
3785     xmlFree(use);
3786 }
3787
3788 /**
3789  * xmlSchemaFreeAttributeUseProhib:
3790  * @prohib:  an attribute use prohibition
3791  *
3792  * Deallocates an attribute use structure.
3793  */
3794 static void
3795 xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3796 {
3797     if (prohib == NULL)
3798         return;
3799     xmlFree(prohib);
3800 }
3801
3802 /**
3803  * xmlSchemaFreeWildcardNsSet:
3804  * set:  a schema wildcard namespace
3805  *
3806  * Deallocates a list of wildcard constraint structures.
3807  */
3808 static void
3809 xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3810 {
3811     xmlSchemaWildcardNsPtr next;
3812
3813     while (set != NULL) {
3814         next = set->next;
3815         xmlFree(set);
3816         set = next;
3817     }
3818 }
3819
3820 /**
3821  * xmlSchemaFreeWildcard:
3822  * @wildcard:  a wildcard structure
3823  *
3824  * Deallocates a wildcard structure.
3825  */
3826 void
3827 xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3828 {
3829     if (wildcard == NULL)
3830         return;
3831     if (wildcard->annot != NULL)
3832         xmlSchemaFreeAnnot(wildcard->annot);
3833     if (wildcard->nsSet != NULL)
3834         xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3835     if (wildcard->negNsSet != NULL)
3836         xmlFree(wildcard->negNsSet);
3837     xmlFree(wildcard);
3838 }
3839
3840 /**
3841  * xmlSchemaFreeAttributeGroup:
3842  * @schema:  a schema attribute group structure
3843  *
3844  * Deallocate a Schema Attribute Group structure.
3845  */
3846 static void
3847 xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
3848 {
3849     if (attrGr == NULL)
3850         return;
3851     if (attrGr->annot != NULL)
3852         xmlSchemaFreeAnnot(attrGr->annot);
3853     if (attrGr->attrUses != NULL)
3854         xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3855     xmlFree(attrGr);
3856 }
3857
3858 /**
3859  * xmlSchemaFreeQNameRef:
3860  * @item: a QName reference structure
3861  *
3862  * Deallocatea a QName reference structure.
3863  */
3864 static void
3865 xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3866 {
3867     xmlFree(item);
3868 }
3869
3870 /**
3871  * xmlSchemaFreeTypeLinkList:
3872  * @alink: a type link
3873  *
3874  * Deallocate a list of types.
3875  */
3876 static void
3877 xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3878 {
3879     xmlSchemaTypeLinkPtr next;
3880
3881     while (link != NULL) {
3882         next = link->next;
3883         xmlFree(link);
3884         link = next;
3885     }
3886 }
3887
3888 static void
3889 xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3890 {
3891     xmlSchemaIDCStateObjPtr next;
3892     while (sto != NULL) {
3893         next = sto->next;
3894         if (sto->history != NULL)
3895             xmlFree(sto->history);
3896         if (sto->xpathCtxt != NULL)
3897             xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3898         xmlFree(sto);
3899         sto = next;
3900     }
3901 }
3902
3903 /**
3904  * xmlSchemaFreeIDC:
3905  * @idc: a identity-constraint definition
3906  *
3907  * Deallocates an identity-constraint definition.
3908  */
3909 static void
3910 xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3911 {
3912     xmlSchemaIDCSelectPtr cur, prev;
3913
3914     if (idcDef == NULL)
3915         return;
3916     if (idcDef->annot != NULL)
3917         xmlSchemaFreeAnnot(idcDef->annot);
3918     /* Selector */
3919     if (idcDef->selector != NULL) {
3920         if (idcDef->selector->xpathComp != NULL)
3921             xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3922         xmlFree(idcDef->selector);
3923     }
3924     /* Fields */
3925     if (idcDef->fields != NULL) {
3926         cur = idcDef->fields;
3927         do {
3928             prev = cur;
3929             cur = cur->next;
3930             if (prev->xpathComp != NULL)
3931                 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
3932             xmlFree(prev);
3933         } while (cur != NULL);
3934     }
3935     xmlFree(idcDef);
3936 }
3937
3938 /**
3939  * xmlSchemaFreeElement:
3940  * @schema:  a schema element structure
3941  *
3942  * Deallocate a Schema Element structure.
3943  */
3944 static void
3945 xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3946 {
3947     if (elem == NULL)
3948         return;
3949     if (elem->annot != NULL)
3950         xmlSchemaFreeAnnot(elem->annot);
3951     if (elem->contModel != NULL)
3952         xmlRegFreeRegexp(elem->contModel);
3953     if (elem->defVal != NULL)
3954         xmlSchemaFreeValue(elem->defVal);
3955     xmlFree(elem);
3956 }
3957
3958 /**
3959  * xmlSchemaFreeFacet:
3960  * @facet:  a schema facet structure
3961  *
3962  * Deallocate a Schema Facet structure.
3963  */
3964 void
3965 xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3966 {
3967     if (facet == NULL)
3968         return;
3969     if (facet->val != NULL)
3970         xmlSchemaFreeValue(facet->val);
3971     if (facet->regexp != NULL)
3972         xmlRegFreeRegexp(facet->regexp);
3973     if (facet->annot != NULL)
3974         xmlSchemaFreeAnnot(facet->annot);
3975     xmlFree(facet);
3976 }
3977
3978 /**
3979  * xmlSchemaFreeType:
3980  * @type:  a schema type structure
3981  *
3982  * Deallocate a Schema Type structure.
3983  */
3984 void
3985 xmlSchemaFreeType(xmlSchemaTypePtr type)
3986 {
3987     if (type == NULL)
3988         return;
3989     if (type->annot != NULL)
3990         xmlSchemaFreeAnnot(type->annot);
3991     if (type->facets != NULL) {
3992         xmlSchemaFacetPtr facet, next;
3993
3994         facet = type->facets;
3995         while (facet != NULL) {
3996             next = facet->next;
3997             xmlSchemaFreeFacet(facet);
3998             facet = next;
3999         }
4000     }
4001     if (type->attrUses != NULL)
4002         xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
4003     if (type->memberTypes != NULL)
4004         xmlSchemaFreeTypeLinkList(type->memberTypes);
4005     if (type->facetSet != NULL) {
4006         xmlSchemaFacetLinkPtr next, link;
4007
4008         link = type->facetSet;
4009         do {
4010             next = link->next;
4011             xmlFree(link);
4012             link = next;
4013         } while (link != NULL);
4014     }
4015     if (type->contModel != NULL)
4016         xmlRegFreeRegexp(type->contModel);
4017     xmlFree(type);
4018 }
4019
4020 /**
4021  * xmlSchemaFreeModelGroupDef:
4022  * @item:  a schema model group definition
4023  *
4024  * Deallocates a schema model group definition.
4025  */
4026 static void
4027 xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
4028 {
4029     if (item->annot != NULL)
4030         xmlSchemaFreeAnnot(item->annot);
4031     xmlFree(item);
4032 }
4033
4034 /**
4035  * xmlSchemaFreeModelGroup:
4036  * @item:  a schema model group
4037  *
4038  * Deallocates a schema model group structure.
4039  */
4040 static void
4041 xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
4042 {
4043     if (item->annot != NULL)
4044         xmlSchemaFreeAnnot(item->annot);
4045     xmlFree(item);
4046 }
4047
4048 static void
4049 xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
4050 {
4051     if ((list == NULL) || (list->nbItems == 0))
4052         return;
4053     {
4054         xmlSchemaTreeItemPtr item;
4055         xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
4056         int i;
4057
4058         for (i = 0; i < list->nbItems; i++) {
4059             item = items[i];
4060             if (item == NULL)
4061                 continue;
4062             switch (item->type) {
4063                 case XML_SCHEMA_TYPE_SIMPLE:
4064                 case XML_SCHEMA_TYPE_COMPLEX:
4065                     xmlSchemaFreeType((xmlSchemaTypePtr) item);
4066                     break;
4067                 case XML_SCHEMA_TYPE_ATTRIBUTE:
4068                     xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
4069                     break;
4070                 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
4071                     xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
4072                     break;
4073                 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
4074                     xmlSchemaFreeAttributeUseProhib(
4075                         (xmlSchemaAttributeUseProhibPtr) item);
4076                     break;
4077                 case XML_SCHEMA_TYPE_ELEMENT:
4078                     xmlSchemaFreeElement((xmlSchemaElementPtr) item);
4079                     break;
4080                 case XML_SCHEMA_TYPE_PARTICLE:
4081                     if (item->annot != NULL)
4082                         xmlSchemaFreeAnnot(item->annot);
4083                     xmlFree(item);
4084                     break;
4085                 case XML_SCHEMA_TYPE_SEQUENCE:
4086                 case XML_SCHEMA_TYPE_CHOICE:
4087                 case XML_SCHEMA_TYPE_ALL:
4088                     xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4089                     break;
4090                 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4091                     xmlSchemaFreeAttributeGroup(
4092                         (xmlSchemaAttributeGroupPtr) item);
4093                     break;
4094                 case XML_SCHEMA_TYPE_GROUP:
4095                     xmlSchemaFreeModelGroupDef(
4096                         (xmlSchemaModelGroupDefPtr) item);
4097                     break;
4098                 case XML_SCHEMA_TYPE_ANY:
4099                 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4100                     xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4101                     break;
4102                 case XML_SCHEMA_TYPE_IDC_KEY:
4103                 case XML_SCHEMA_TYPE_IDC_UNIQUE:
4104                 case XML_SCHEMA_TYPE_IDC_KEYREF:
4105                     xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4106                     break;
4107                 case XML_SCHEMA_TYPE_NOTATION:
4108                     xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4109                     break;
4110                 case XML_SCHEMA_EXTRA_QNAMEREF:
4111                     xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4112                     break;
4113                 default: {
4114                     /* TODO: This should never be hit. */
4115                     xmlSchemaPSimpleInternalErr(NULL,
4116                         "Internal error: xmlSchemaComponentListFree, "
4117                         "unexpected component type '%s'\n",
4118                         (const xmlChar *) WXS_ITEM_TYPE_NAME(item));
4119                          }
4120                     break;
4121             }
4122         }
4123         list->nbItems = 0;
4124     }
4125 }
4126
4127 /**
4128  * xmlSchemaFree:
4129  * @schema:  a schema structure
4130  *
4131  * Deallocate a Schema structure.
4132  */
4133 void
4134 xmlSchemaFree(xmlSchemaPtr schema)
4135 {
4136     if (schema == NULL)
4137         return;
4138     /* @volatiles is not used anymore :-/ */
4139     if (schema->volatiles != NULL)
4140         TODO
4141     /*
4142     * Note that those slots are not responsible for freeing
4143     * schema components anymore; this will now be done by
4144     * the schema buckets.
4145     */
4146     if (schema->notaDecl != NULL)
4147         xmlHashFree(schema->notaDecl, NULL);
4148     if (schema->attrDecl != NULL)
4149         xmlHashFree(schema->attrDecl, NULL);
4150     if (schema->attrgrpDecl != NULL)
4151         xmlHashFree(schema->attrgrpDecl, NULL);
4152     if (schema->elemDecl != NULL)
4153         xmlHashFree(schema->elemDecl, NULL);
4154     if (schema->typeDecl != NULL)
4155         xmlHashFree(schema->typeDecl, NULL);
4156     if (schema->groupDecl != NULL)
4157         xmlHashFree(schema->groupDecl, NULL);
4158     if (schema->idcDef != NULL)
4159         xmlHashFree(schema->idcDef, NULL);
4160
4161     if (schema->schemasImports != NULL)
4162         xmlHashFree(schema->schemasImports,
4163                     (xmlHashDeallocator) xmlSchemaBucketFree);
4164     if (schema->includes != NULL) {
4165         xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4166         int i;
4167         for (i = 0; i < list->nbItems; i++) {
4168             xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4169         }
4170         xmlSchemaItemListFree(list);
4171     }
4172     if (schema->annot != NULL)
4173         xmlSchemaFreeAnnot(schema->annot);
4174     /* Never free the doc here, since this will be done by the buckets. */
4175
4176     xmlDictFree(schema->dict);
4177     xmlFree(schema);
4178 }
4179
4180 /************************************************************************
4181  *                                                                      *
4182  *                      Debug functions                                 *
4183  *                                                                      *
4184  ************************************************************************/
4185
4186 #ifdef LIBXML_OUTPUT_ENABLED
4187
4188 static void
4189 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4190
4191 /**
4192  * xmlSchemaElementDump:
4193  * @elem:  an element
4194  * @output:  the file output
4195  *
4196  * Dump the element
4197  */
4198 static void
4199 xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
4200                      const xmlChar * name ATTRIBUTE_UNUSED,
4201                      const xmlChar * namespace ATTRIBUTE_UNUSED,
4202                      const xmlChar * context ATTRIBUTE_UNUSED)
4203 {
4204     if (elem == NULL)
4205         return;
4206
4207
4208     fprintf(output, "Element");
4209     if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4210         fprintf(output, " (global)");
4211     fprintf(output, ": '%s' ", elem->name);
4212     if (namespace != NULL)
4213         fprintf(output, "ns '%s'", namespace);
4214     fprintf(output, "\n");
4215 #if 0
4216     if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
4217         fprintf(output, "  min %d ", elem->minOccurs);
4218         if (elem->maxOccurs >= UNBOUNDED)
4219             fprintf(output, "max: unbounded\n");
4220         else if (elem->maxOccurs != 1)
4221             fprintf(output, "max: %d\n", elem->maxOccurs);
4222         else
4223             fprintf(output, "\n");
4224     }
4225 #endif
4226     /*
4227     * Misc other properties.
4228     */
4229     if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4230         (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4231         (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
4232         (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
4233         fprintf(output, "  props: ");
4234         if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4235             fprintf(output, "[fixed] ");
4236         if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4237             fprintf(output, "[default] ");
4238         if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4239             fprintf(output, "[abstract] ");
4240         if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4241             fprintf(output, "[nillable] ");
4242         fprintf(output, "\n");
4243     }
4244     /*
4245     * Default/fixed value.
4246     */
4247     if (elem->value != NULL)
4248         fprintf(output, "  value: '%s'\n", elem->value);
4249     /*
4250     * Type.
4251     */
4252     if (elem->namedType != NULL) {
4253         fprintf(output, "  type: '%s' ", elem->namedType);
4254         if (elem->namedTypeNs != NULL)
4255             fprintf(output, "ns '%s'\n", elem->namedTypeNs);
4256         else
4257             fprintf(output, "\n");
4258     } else if (elem->subtypes != NULL) {
4259         /*
4260         * Dump local types.
4261         */
4262         xmlSchemaTypeDump(elem->subtypes, output);
4263     }
4264     /*
4265     * Substitution group.
4266     */
4267     if (elem->substGroup != NULL) {
4268         fprintf(output, "  substitutionGroup: '%s' ", elem->substGroup);
4269         if (elem->substGroupNs != NULL)
4270             fprintf(output, "ns '%s'\n", elem->substGroupNs);
4271         else
4272             fprintf(output, "\n");
4273     }
4274 }
4275
4276 /**
4277  * xmlSchemaAnnotDump:
4278  * @output:  the file output
4279  * @annot:  a annotation
4280  *
4281  * Dump the annotation
4282  */
4283 static void
4284 xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4285 {
4286     xmlChar *content;
4287
4288     if (annot == NULL)
4289         return;
4290
4291     content = xmlNodeGetContent(annot->content);
4292     if (content != NULL) {
4293         fprintf(output, "  Annot: %s\n", content);
4294         xmlFree(content);
4295     } else
4296         fprintf(output, "  Annot: empty\n");
4297 }
4298
4299 /**
4300  * xmlSchemaContentModelDump:
4301  * @particle: the schema particle
4302  * @output: the file output
4303  * @depth: the depth used for intentation
4304  *
4305  * Dump a SchemaType structure
4306  */
4307 static void
4308 xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4309 {
4310     xmlChar *str = NULL;
4311     xmlSchemaTreeItemPtr term;
4312     char shift[100];
4313     int i;
4314
4315     if (particle == NULL)
4316         return;
4317     for (i = 0;((i < depth) && (i < 25));i++)
4318         shift[2 * i] = shift[2 * i + 1] = ' ';
4319     shift[2 * i] = shift[2 * i + 1] = 0;
4320     fprintf(output, "%s", shift);
4321     if (particle->children == NULL) {
4322         fprintf(output, "MISSING particle term\n");
4323         return;
4324     }
4325     term = particle->children;
4326     if (term == NULL) {
4327         fprintf(output, "(NULL)");
4328     } else {
4329         switch (term->type) {
4330             case XML_SCHEMA_TYPE_ELEMENT:
4331                 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4332                     ((xmlSchemaElementPtr)term)->targetNamespace,
4333                     ((xmlSchemaElementPtr)term)->name));
4334                 FREE_AND_NULL(str);
4335                 break;
4336             case XML_SCHEMA_TYPE_SEQUENCE:
4337                 fprintf(output, "SEQUENCE");
4338                 break;
4339             case XML_SCHEMA_TYPE_CHOICE:
4340                 fprintf(output, "CHOICE");
4341                 break;
4342             case XML_SCHEMA_TYPE_ALL:
4343                 fprintf(output, "ALL");
4344                 break;
4345             case XML_SCHEMA_TYPE_ANY:
4346                 fprintf(output, "ANY");
4347                 break;
4348             default:
4349                 fprintf(output, "UNKNOWN\n");
4350                 return;
4351         }
4352     }
4353     if (particle->minOccurs != 1)
4354         fprintf(output, " min: %d", particle->minOccurs);
4355     if (particle->maxOccurs >= UNBOUNDED)
4356         fprintf(output, " max: unbounded");
4357     else if (particle->maxOccurs != 1)
4358         fprintf(output, " max: %d", particle->maxOccurs);
4359     fprintf(output, "\n");
4360     if (term &&
4361         ((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4362          (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4363          (term->type == XML_SCHEMA_TYPE_ALL)) &&
4364          (term->children != NULL)) {
4365         xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4366             output, depth +1);
4367     }
4368     if (particle->next != NULL)
4369         xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4370                 output, depth);
4371 }
4372
4373 /**
4374  * xmlSchemaAttrUsesDump:
4375  * @uses:  attribute uses list
4376  * @output:  the file output
4377  *
4378  * Dumps a list of attribute use components.
4379  */
4380 static void
4381 xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4382 {
4383     xmlSchemaAttributeUsePtr use;
4384     xmlSchemaAttributeUseProhibPtr prohib;
4385     xmlSchemaQNameRefPtr ref;
4386     const xmlChar *name, *tns;
4387     xmlChar *str = NULL;
4388     int i;
4389
4390     if ((uses == NULL) || (uses->nbItems == 0))
4391         return;
4392
4393     fprintf(output, "  attributes:\n");
4394     for (i = 0; i < uses->nbItems; i++) {
4395         use = uses->items[i];
4396         if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4397             fprintf(output, "  [prohibition] ");
4398             prohib = (xmlSchemaAttributeUseProhibPtr) use;
4399             name = prohib->name;
4400             tns = prohib->targetNamespace;
4401         } else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4402             fprintf(output, "  [reference] ");
4403             ref = (xmlSchemaQNameRefPtr) use;
4404             name = ref->name;
4405             tns = ref->targetNamespace;
4406         } else {
4407             fprintf(output, "  [use] ");
4408             name = WXS_ATTRUSE_DECL_NAME(use);
4409             tns = WXS_ATTRUSE_DECL_TNS(use);
4410         }
4411         fprintf(output, "'%s'\n",
4412             (const char *) xmlSchemaFormatQName(&str, tns, name));
4413         FREE_AND_NULL(str);
4414     }
4415 }
4416
4417 /**
4418  * xmlSchemaTypeDump:
4419  * @output:  the file output
4420  * @type:  a type structure
4421  *
4422  * Dump a SchemaType structure
4423  */
4424 static void
4425 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4426 {
4427     if (type == NULL) {
4428         fprintf(output, "Type: NULL\n");
4429         return;
4430     }
4431     fprintf(output, "Type: ");
4432     if (type->name != NULL)
4433         fprintf(output, "'%s' ", type->name);
4434     else
4435         fprintf(output, "(no name) ");
4436     if (type->targetNamespace != NULL)
4437         fprintf(output, "ns '%s' ", type->targetNamespace);
4438     switch (type->type) {
4439         case XML_SCHEMA_TYPE_BASIC:
4440             fprintf(output, "[basic] ");
4441             break;
4442         case XML_SCHEMA_TYPE_SIMPLE:
4443             fprintf(output, "[simple] ");
4444             break;
4445         case XML_SCHEMA_TYPE_COMPLEX:
4446             fprintf(output, "[complex] ");
4447             break;
4448         case XML_SCHEMA_TYPE_SEQUENCE:
4449             fprintf(output, "[sequence] ");
4450             break;
4451         case XML_SCHEMA_TYPE_CHOICE:
4452             fprintf(output, "[choice] ");
4453             break;
4454         case XML_SCHEMA_TYPE_ALL:
4455             fprintf(output, "[all] ");
4456             break;
4457         case XML_SCHEMA_TYPE_UR:
4458             fprintf(output, "[ur] ");
4459             break;
4460         case XML_SCHEMA_TYPE_RESTRICTION:
4461             fprintf(output, "[restriction] ");
4462             break;
4463         case XML_SCHEMA_TYPE_EXTENSION:
4464             fprintf(output, "[extension] ");
4465             break;
4466         default:
4467             fprintf(output, "[unknown type %d] ", type->type);
4468             break;
4469     }
4470     fprintf(output, "content: ");
4471     switch (type->contentType) {
4472         case XML_SCHEMA_CONTENT_UNKNOWN:
4473             fprintf(output, "[unknown] ");
4474             break;
4475         case XML_SCHEMA_CONTENT_EMPTY:
4476             fprintf(output, "[empty] ");
4477             break;
4478         case XML_SCHEMA_CONTENT_ELEMENTS:
4479             fprintf(output, "[element] ");
4480             break;
4481         case XML_SCHEMA_CONTENT_MIXED:
4482             fprintf(output, "[mixed] ");
4483             break;
4484         case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
4485         /* not used. */
4486             break;
4487         case XML_SCHEMA_CONTENT_BASIC:
4488             fprintf(output, "[basic] ");
4489             break;
4490         case XML_SCHEMA_CONTENT_SIMPLE:
4491             fprintf(output, "[simple] ");
4492             break;
4493         case XML_SCHEMA_CONTENT_ANY:
4494             fprintf(output, "[any] ");
4495             break;
4496     }
4497     fprintf(output, "\n");
4498     if (type->base != NULL) {
4499         fprintf(output, "  base type: '%s'", type->base);
4500         if (type->baseNs != NULL)
4501             fprintf(output, " ns '%s'\n", type->baseNs);
4502         else
4503             fprintf(output, "\n");
4504     }
4505     if (type->attrUses != NULL)
4506         xmlSchemaAttrUsesDump(type->attrUses, output);
4507     if (type->annot != NULL)
4508         xmlSchemaAnnotDump(output, type->annot);
4509 #ifdef DUMP_CONTENT_MODEL
4510     if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4511         (type->subtypes != NULL)) {
4512         xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4513             output, 1);
4514     }
4515 #endif
4516 }
4517
4518 /**
4519  * xmlSchemaDump:
4520  * @output:  the file output
4521  * @schema:  a schema structure
4522  *
4523  * Dump a Schema structure.
4524  */
4525 void
4526 xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4527 {
4528     if (output == NULL)
4529         return;
4530     if (schema == NULL) {
4531         fprintf(output, "Schemas: NULL\n");
4532         return;
4533     }
4534     fprintf(output, "Schemas: ");
4535     if (schema->name != NULL)
4536         fprintf(output, "%s, ", schema->name);
4537     else
4538         fprintf(output, "no name, ");
4539     if (schema->targetNamespace != NULL)
4540         fprintf(output, "%s", (const char *) schema->targetNamespace);
4541     else
4542         fprintf(output, "no target namespace");
4543     fprintf(output, "\n");
4544     if (schema->annot != NULL)
4545         xmlSchemaAnnotDump(output, schema->annot);
4546     xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
4547                 output);
4548     xmlHashScanFull(schema->elemDecl,
4549                     (xmlHashScannerFull) xmlSchemaElementDump, output);
4550 }
4551
4552 #ifdef DEBUG_IDC_NODE_TABLE
4553 /**
4554  * xmlSchemaDebugDumpIDCTable:
4555  * @vctxt: the WXS validation context
4556  *
4557  * Displays the current IDC table for debug purposes.
4558  */
4559 static void
4560 xmlSchemaDebugDumpIDCTable(FILE * output,
4561                            const xmlChar *namespaceName,
4562                            const xmlChar *localName,
4563                            xmlSchemaPSVIIDCBindingPtr bind)
4564 {
4565     xmlChar *str = NULL;
4566     const xmlChar *value;
4567     xmlSchemaPSVIIDCNodePtr tab;
4568     xmlSchemaPSVIIDCKeyPtr key;
4569     int i, j, res;
4570
4571     fprintf(output, "IDC: TABLES on '%s'\n",
4572         xmlSchemaFormatQName(&str, namespaceName, localName));
4573     FREE_AND_NULL(str)
4574
4575     if (bind == NULL)
4576         return;
4577     do {
4578         fprintf(output, "IDC:   BINDING '%s' (%d)\n",
4579             xmlSchemaGetComponentQName(&str,
4580                 bind->definition), bind->nbNodes);
4581         FREE_AND_NULL(str)
4582         for (i = 0; i < bind->nbNodes; i++) {
4583             tab = bind->nodeTable[i];
4584             fprintf(output, "         ( ");
4585             for (j = 0; j < bind->definition->nbFields; j++) {
4586                 key = tab->keys[j];
4587                 if ((key != NULL) && (key->val != NULL)) {
4588                     res = xmlSchemaGetCanonValue(key->val, &value);
4589                     if (res >= 0)
4590                         fprintf(output, "'%s' ", value);
4591                     else
4592                         fprintf(output, "CANON-VALUE-FAILED ");
4593                     if (res == 0)
4594                         FREE_AND_NULL(value)
4595                 } else if (key != NULL)
4596                     fprintf(output, "(no val), ");
4597                 else
4598                     fprintf(output, "(key missing), ");
4599             }
4600             fprintf(output, ")\n");
4601         }
4602         if (bind->dupls && bind->dupls->nbItems) {
4603             fprintf(output, "IDC:     dupls (%d):\n", bind->dupls->nbItems);
4604             for (i = 0; i < bind->dupls->nbItems; i++) {
4605                 tab = bind->dupls->items[i];
4606                 fprintf(output, "         ( ");
4607                 for (j = 0; j < bind->definition->nbFields; j++) {
4608                     key = tab->keys[j];
4609                     if ((key != NULL) && (key->val != NULL)) {
4610                         res = xmlSchemaGetCanonValue(key->val, &value);
4611                         if (res >= 0)
4612                             fprintf(output, "'%s' ", value);
4613                         else
4614                             fprintf(output, "CANON-VALUE-FAILED ");
4615                         if (res == 0)
4616                             FREE_AND_NULL(value)
4617                     } else if (key != NULL)
4618                     fprintf(output, "(no val), ");
4619                         else
4620                             fprintf(output, "(key missing), ");
4621                 }
4622                 fprintf(output, ")\n");
4623             }
4624         }
4625         bind = bind->next;
4626     } while (bind != NULL);
4627 }
4628 #endif /* DEBUG_IDC */
4629 #endif /* LIBXML_OUTPUT_ENABLED */
4630
4631 /************************************************************************
4632  *                                                                      *
4633  *                      Utilities                                       *
4634  *                                                                      *
4635  ************************************************************************/
4636
4637 /**
4638  * xmlSchemaGetPropNode:
4639  * @node: the element node
4640  * @name: the name of the attribute
4641  *
4642  * Seeks an attribute with a name of @name in
4643  * no namespace.
4644  *
4645  * Returns the attribute or NULL if not present.
4646  */
4647 static xmlAttrPtr
4648 xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
4649 {
4650     xmlAttrPtr prop;
4651
4652     if ((node == NULL) || (name == NULL))
4653         return(NULL);
4654     prop = node->properties;
4655     while (prop != NULL) {
4656         if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
4657             return(prop);
4658         prop = prop->next;
4659     }
4660     return (NULL);
4661 }
4662
4663 /**
4664  * xmlSchemaGetPropNodeNs:
4665  * @node: the element node
4666  * @uri: the uri
4667  * @name: the name of the attribute
4668  *
4669  * Seeks an attribute with a local name of @name and
4670  * a namespace URI of @uri.
4671  *
4672  * Returns the attribute or NULL if not present.
4673  */
4674 static xmlAttrPtr
4675 xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
4676 {
4677     xmlAttrPtr prop;
4678
4679     if ((node == NULL) || (name == NULL))
4680         return(NULL);
4681     prop = node->properties;
4682     while (prop != NULL) {
4683         if ((prop->ns != NULL) &&
4684             xmlStrEqual(prop->name, BAD_CAST name) &&
4685             xmlStrEqual(prop->ns->href, BAD_CAST uri))
4686             return(prop);
4687         prop = prop->next;
4688     }
4689     return (NULL);
4690 }
4691
4692 static const xmlChar *
4693 xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4694 {
4695     xmlChar *val;
4696     const xmlChar *ret;
4697
4698     val = xmlNodeGetContent(node);
4699     if (val == NULL)
4700         val = xmlStrdup((xmlChar *)"");
4701     ret = xmlDictLookup(ctxt->dict, val, -1);
4702     xmlFree(val);
4703     return(ret);
4704 }
4705
4706 static const xmlChar *
4707 xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4708 {
4709     return((const xmlChar*) xmlNodeGetContent(node));
4710 }
4711
4712 /**
4713  * xmlSchemaGetProp:
4714  * @ctxt: the parser context
4715  * @node: the node
4716  * @name: the property name
4717  *
4718  * Read a attribute value and internalize the string
4719  *
4720  * Returns the string or NULL if not present.
4721  */
4722 static const xmlChar *
4723 xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4724                  const char *name)
4725 {
4726     xmlChar *val;
4727     const xmlChar *ret;
4728
4729     val = xmlGetNoNsProp(node, BAD_CAST name);
4730     if (val == NULL)
4731         return(NULL);
4732     ret = xmlDictLookup(ctxt->dict, val, -1);
4733     xmlFree(val);
4734     return(ret);
4735 }
4736
4737 /************************************************************************
4738  *                                                                      *
4739  *                      Parsing functions                               *
4740  *                                                                      *
4741  ************************************************************************/
4742
4743 #define WXS_FIND_GLOBAL_ITEM(slot)                      \
4744     if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4745         ret = xmlHashLookup(schema->slot, name); \
4746         if (ret != NULL) goto exit; \
4747     } \
4748     if (xmlHashSize(schema->schemasImports) > 1) { \
4749         xmlSchemaImportPtr import; \
4750         if (nsName == NULL) \
4751             import = xmlHashLookup(schema->schemasImports, \
4752                 XML_SCHEMAS_NO_NAMESPACE); \
4753         else \
4754             import = xmlHashLookup(schema->schemasImports, nsName); \
4755         if (import == NULL) \
4756             goto exit; \
4757         ret = xmlHashLookup(import->schema->slot, name); \
4758     }
4759
4760 /**
4761  * xmlSchemaGetElem:
4762  * @schema:  the schema context
4763  * @name:  the element name
4764  * @ns:  the element namespace
4765  *
4766  * Lookup a global element declaration in the schema.
4767  *
4768  * Returns the element declaration or NULL if not found.
4769  */
4770 static xmlSchemaElementPtr
4771 xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
4772                  const xmlChar * nsName)
4773 {
4774     xmlSchemaElementPtr ret = NULL;
4775
4776     if ((name == NULL) || (schema == NULL))
4777         return(NULL);
4778     if (schema != NULL) {
4779         WXS_FIND_GLOBAL_ITEM(elemDecl)
4780     }
4781 exit:
4782 #ifdef DEBUG
4783     if (ret == NULL) {
4784         if (nsName == NULL)
4785             fprintf(stderr, "Unable to lookup element decl. %s", name);
4786         else
4787             fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
4788                     nsName);
4789     }
4790 #endif
4791     return (ret);
4792 }
4793
4794 /**
4795  * xmlSchemaGetType:
4796  * @schema:  the main schema
4797  * @name:  the type's name
4798  * nsName:  the type's namespace
4799  *
4800  * Lookup a type in the schemas or the predefined types
4801  *
4802  * Returns the group definition or NULL if not found.
4803  */
4804 static xmlSchemaTypePtr
4805 xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
4806                  const xmlChar * nsName)
4807 {
4808     xmlSchemaTypePtr ret = NULL;
4809
4810     if (name == NULL)
4811         return (NULL);
4812     /* First try the built-in types. */
4813     if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4814         ret = xmlSchemaGetPredefinedType(name, nsName);
4815         if (ret != NULL)
4816             goto exit;
4817         /*
4818         * Note that we try the parsed schemas as well here
4819         * since one might have parsed the S4S, which contain more
4820         * than the built-in types.
4821         * TODO: Can we optimize this?
4822         */
4823     }
4824     if (schema != NULL) {
4825         WXS_FIND_GLOBAL_ITEM(typeDecl)
4826     }
4827 exit:
4828
4829 #ifdef DEBUG
4830     if (ret == NULL) {
4831         if (nsName == NULL)
4832             fprintf(stderr, "Unable to lookup type %s", name);
4833         else
4834             fprintf(stderr, "Unable to lookup type %s:%s", name,
4835                     nsName);
4836     }
4837 #endif
4838     return (ret);
4839 }
4840
4841 /**
4842  * xmlSchemaGetAttributeDecl:
4843  * @schema:  the context of the schema
4844  * @name:  the name of the attribute
4845  * @ns:  the target namespace of the attribute
4846  *
4847  * Lookup a an attribute in the schema or imported schemas
4848  *
4849  * Returns the attribute declaration or NULL if not found.
4850  */
4851 static xmlSchemaAttributePtr
4852 xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
4853                  const xmlChar * nsName)
4854 {
4855     xmlSchemaAttributePtr ret = NULL;
4856
4857     if ((name == NULL) || (schema == NULL))
4858         return (NULL);
4859     if (schema != NULL) {
4860         WXS_FIND_GLOBAL_ITEM(attrDecl)
4861     }
4862 exit:
4863 #ifdef DEBUG
4864     if (ret == NULL) {
4865         if (nsName == NULL)
4866             fprintf(stderr, "Unable to lookup attribute %s", name);
4867         else
4868             fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4869                     nsName);
4870     }
4871 #endif
4872     return (ret);
4873 }
4874
4875 /**
4876  * xmlSchemaGetAttributeGroup:
4877  * @schema:  the context of the schema
4878  * @name:  the name of the attribute group
4879  * @ns:  the target namespace of the attribute group
4880  *
4881  * Lookup a an attribute group in the schema or imported schemas
4882  *
4883  * Returns the attribute group definition or NULL if not found.
4884  */
4885 static xmlSchemaAttributeGroupPtr
4886 xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4887                  const xmlChar * nsName)
4888 {
4889     xmlSchemaAttributeGroupPtr ret = NULL;
4890
4891     if ((name == NULL) || (schema == NULL))
4892         return (NULL);
4893     if (schema != NULL) {
4894         WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4895     }
4896 exit:
4897     /* TODO:
4898     if ((ret != NULL) && (ret->redef != NULL)) {
4899         * Return the last redefinition. *
4900         ret = ret->redef;
4901     }
4902     */
4903 #ifdef DEBUG
4904     if (ret == NULL) {
4905         if (nsName == NULL)
4906             fprintf(stderr, "Unable to lookup attribute group %s", name);
4907         else
4908             fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4909                     nsName);
4910     }
4911 #endif
4912     return (ret);
4913 }
4914
4915 /**
4916  * xmlSchemaGetGroup:
4917  * @schema:  the context of the schema
4918  * @name:  the name of the group
4919  * @ns:  the target namespace of the group
4920  *
4921  * Lookup a group in the schema or imported schemas
4922  *
4923  * Returns the group definition or NULL if not found.
4924  */
4925 static xmlSchemaModelGroupDefPtr
4926 xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4927                  const xmlChar * nsName)
4928 {
4929     xmlSchemaModelGroupDefPtr ret = NULL;
4930
4931     if ((name == NULL) || (schema == NULL))
4932         return (NULL);
4933     if (schema != NULL) {
4934         WXS_FIND_GLOBAL_ITEM(groupDecl)
4935     }
4936 exit:
4937
4938 #ifdef DEBUG
4939     if (ret == NULL) {
4940         if (nsName == NULL)
4941             fprintf(stderr, "Unable to lookup group %s", name);
4942         else
4943             fprintf(stderr, "Unable to lookup group %s:%s", name,
4944                     nsName);
4945     }
4946 #endif
4947     return (ret);
4948 }
4949
4950 static xmlSchemaNotationPtr
4951 xmlSchemaGetNotation(xmlSchemaPtr schema,
4952                      const xmlChar *name,
4953                      const xmlChar *nsName)
4954 {
4955     xmlSchemaNotationPtr ret = NULL;
4956
4957     if ((name == NULL) || (schema == NULL))
4958         return (NULL);
4959     if (schema != NULL) {
4960         WXS_FIND_GLOBAL_ITEM(notaDecl)
4961     }
4962 exit:
4963     return (ret);
4964 }
4965
4966 static xmlSchemaIDCPtr
4967 xmlSchemaGetIDC(xmlSchemaPtr schema,
4968                 const xmlChar *name,
4969                 const xmlChar *nsName)
4970 {
4971     xmlSchemaIDCPtr ret = NULL;
4972
4973     if ((name == NULL) || (schema == NULL))
4974         return (NULL);
4975     if (schema != NULL) {
4976         WXS_FIND_GLOBAL_ITEM(idcDef)
4977     }
4978 exit:
4979     return (ret);
4980 }
4981
4982 /**
4983  * xmlSchemaGetNamedComponent:
4984  * @schema:  the schema
4985  * @name:  the name of the group
4986  * @ns:  the target namespace of the group
4987  *
4988  * Lookup a group in the schema or imported schemas
4989  *
4990  * Returns the group definition or NULL if not found.
4991  */
4992 static xmlSchemaBasicItemPtr
4993 xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4994                            xmlSchemaTypeType itemType,
4995                            const xmlChar *name,
4996                            const xmlChar *targetNs)
4997 {
4998     switch (itemType) {
4999         case XML_SCHEMA_TYPE_GROUP:
5000             return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
5001                 name, targetNs));
5002         case XML_SCHEMA_TYPE_ELEMENT:
5003             return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
5004                 name, targetNs));
5005         default:
5006             TODO
5007             return (NULL);
5008     }
5009 }
5010
5011 /************************************************************************
5012  *                                                                      *
5013  *                      Parsing functions                               *
5014  *                                                                      *
5015  ************************************************************************/
5016
5017 #define IS_BLANK_NODE(n)                                                \
5018     (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
5019
5020 /**
5021  * xmlSchemaIsBlank:
5022  * @str:  a string
5023  * @len: the length of the string or -1
5024  *
5025  * Check if a string is ignorable
5026  *
5027  * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
5028  */
5029 static int
5030 xmlSchemaIsBlank(xmlChar * str, int len)
5031 {
5032     if (str == NULL)
5033         return (1);
5034     if (len < 0) {
5035         while (*str != 0) {
5036             if (!(IS_BLANK_CH(*str)))
5037                 return (0);
5038             str++;
5039         }
5040     } else while ((*str != 0) && (len != 0)) {
5041         if (!(IS_BLANK_CH(*str)))
5042             return (0);
5043         str++;
5044         len--;
5045     }
5046
5047     return (1);
5048 }
5049
5050 #define WXS_COMP_NAME(c, t) ((t) (c))->name
5051 #define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
5052 /*
5053 * xmlSchemaFindRedefCompInGraph:
5054 * ATTENTION TODO: This uses pointer comp. for strings.
5055 */
5056 static xmlSchemaBasicItemPtr
5057 xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
5058                               xmlSchemaTypeType type,
5059                               const xmlChar *name,
5060                               const xmlChar *nsName)
5061 {
5062     xmlSchemaBasicItemPtr ret;
5063     int i;
5064
5065     if ((bucket == NULL) || (name == NULL))
5066         return(NULL);
5067     if ((bucket->globals == NULL) ||
5068         (bucket->globals->nbItems == 0))
5069         goto subschemas;
5070     /*
5071     * Search in global components.
5072     */
5073     for (i = 0; i < bucket->globals->nbItems; i++) {
5074         ret = bucket->globals->items[i];
5075         if (ret->type == type) {
5076             switch (type) {
5077                 case XML_SCHEMA_TYPE_COMPLEX:
5078                 case XML_SCHEMA_TYPE_SIMPLE:
5079                     if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
5080                         (WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5081                         nsName))
5082                     {
5083                         return(ret);
5084                     }
5085                     break;
5086                 case XML_SCHEMA_TYPE_GROUP:
5087                     if ((WXS_COMP_NAME(ret,
5088                             xmlSchemaModelGroupDefPtr) == name) &&
5089                         (WXS_COMP_TNS(ret,
5090                             xmlSchemaModelGroupDefPtr) == nsName))
5091                     {
5092                         return(ret);
5093                     }
5094                     break;
5095                 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5096                     if ((WXS_COMP_NAME(ret,
5097                             xmlSchemaAttributeGroupPtr) == name) &&
5098                         (WXS_COMP_TNS(ret,
5099                             xmlSchemaAttributeGroupPtr) == nsName))
5100                     {
5101                         return(ret);
5102                     }
5103                     break;
5104                 default:
5105                     /* Should not be hit. */
5106                     return(NULL);
5107             }
5108         }
5109     }
5110 subschemas:
5111     /*
5112     * Process imported/included schemas.
5113     */
5114     if (bucket->relations != NULL) {
5115         xmlSchemaSchemaRelationPtr rel = bucket->relations;
5116
5117         /*
5118         * TODO: Marking the bucket will not avoid multiple searches
5119         * in the same schema, but avoids at least circularity.
5120         */
5121         bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5122         do {
5123             if ((rel->bucket != NULL) &&
5124                 ((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5125                 ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5126                     type, name, nsName);
5127                 if (ret != NULL)
5128                     return(ret);
5129             }
5130             rel = rel->next;
5131         } while (rel != NULL);
5132          bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5133     }
5134     return(NULL);
5135 }
5136
5137 /**
5138  * xmlSchemaAddNotation:
5139  * @ctxt:  a schema parser context
5140  * @schema:  the schema being built
5141  * @name:  the item name
5142  *
5143  * Add an XML schema annotation declaration
5144  * *WARNING* this interface is highly subject to change
5145  *
5146  * Returns the new struture or NULL in case of error
5147  */
5148 static xmlSchemaNotationPtr
5149 xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5150                      const xmlChar *name, const xmlChar *nsName,
5151                      xmlNodePtr node ATTRIBUTE_UNUSED)
5152 {
5153     xmlSchemaNotationPtr ret = NULL;
5154
5155     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5156         return (NULL);
5157
5158     ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5159     if (ret == NULL) {
5160         xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
5161         return (NULL);
5162     }
5163     memset(ret, 0, sizeof(xmlSchemaNotation));
5164     ret->type = XML_SCHEMA_TYPE_NOTATION;
5165     ret->name = name;
5166     ret->targetNamespace = nsName;
5167     /* TODO: do we need the node to be set?
5168     * ret->node = node;*/
5169     WXS_ADD_GLOBAL(ctxt, ret);
5170     return (ret);
5171 }
5172
5173 /**
5174  * xmlSchemaAddAttribute:
5175  * @ctxt:  a schema parser context
5176  * @schema:  the schema being built
5177  * @name:  the item name
5178  * @namespace:  the namespace
5179  *
5180  * Add an XML schema Attrribute declaration
5181  * *WARNING* this interface is highly subject to change
5182  *
5183  * Returns the new struture or NULL in case of error
5184  */
5185 static xmlSchemaAttributePtr
5186 xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5187                       const xmlChar * name, const xmlChar * nsName,
5188                       xmlNodePtr node, int topLevel)
5189 {
5190     xmlSchemaAttributePtr ret = NULL;
5191
5192     if ((ctxt == NULL) || (schema == NULL))
5193         return (NULL);
5194
5195     ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5196     if (ret == NULL) {
5197         xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
5198         return (NULL);
5199     }
5200     memset(ret, 0, sizeof(xmlSchemaAttribute));
5201     ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5202     ret->node = node;
5203     ret->name = name;
5204     ret->targetNamespace = nsName;
5205
5206     if (topLevel)
5207         WXS_ADD_GLOBAL(ctxt, ret);
5208     else
5209         WXS_ADD_LOCAL(ctxt, ret);
5210     WXS_ADD_PENDING(ctxt, ret);
5211     return (ret);
5212 }
5213
5214 /**
5215  * xmlSchemaAddAttributeUse:
5216  * @ctxt:  a schema parser context
5217  * @schema:  the schema being built
5218  * @name:  the item name
5219  * @namespace:  the namespace
5220  *
5221  * Add an XML schema Attrribute declaration
5222  * *WARNING* this interface is highly subject to change
5223  *
5224  * Returns the new struture or NULL in case of error
5225  */
5226 static xmlSchemaAttributeUsePtr
5227 xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5228                          xmlNodePtr node)
5229 {
5230     xmlSchemaAttributeUsePtr ret = NULL;
5231
5232     if (pctxt == NULL)
5233         return (NULL);
5234
5235     ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5236     if (ret == NULL) {
5237         xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5238         return (NULL);
5239     }
5240     memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5241     ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5242     ret->node = node;
5243
5244     WXS_ADD_LOCAL(pctxt, ret);
5245     return (ret);
5246 }
5247
5248 /*
5249 * xmlSchemaAddRedef:
5250 *
5251 * Adds a redefinition information. This is used at a later stage to:
5252 * resolve references to the redefined components and to check constraints.
5253 */
5254 static xmlSchemaRedefPtr
5255 xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5256                   xmlSchemaBucketPtr targetBucket,
5257                   void *item,
5258                   const xmlChar *refName,
5259                   const xmlChar *refTargetNs)
5260 {
5261     xmlSchemaRedefPtr ret;
5262
5263     ret = (xmlSchemaRedefPtr)
5264         xmlMalloc(sizeof(xmlSchemaRedef));
5265     if (ret == NULL) {
5266         xmlSchemaPErrMemory(pctxt,
5267             "allocating redefinition info", NULL);
5268         return (NULL);
5269     }
5270     memset(ret, 0, sizeof(xmlSchemaRedef));
5271     ret->item = item;
5272     ret->targetBucket = targetBucket;
5273     ret->refName = refName;
5274     ret->refTargetNs = refTargetNs;
5275     if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5276         WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5277     else
5278         WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5279     WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5280
5281     return (ret);
5282 }
5283
5284 /**
5285  * xmlSchemaAddAttributeGroupDefinition:
5286  * @ctxt:  a schema parser context
5287  * @schema:  the schema being built
5288  * @name:  the item name
5289  * @nsName:  the target namespace
5290  * @node: the corresponding node
5291  *
5292  * Add an XML schema Attrribute Group definition.
5293  *
5294  * Returns the new struture or NULL in case of error
5295  */
5296 static xmlSchemaAttributeGroupPtr
5297 xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5298                            xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5299                            const xmlChar *name,
5300                            const xmlChar *nsName,
5301                            xmlNodePtr node)
5302 {
5303     xmlSchemaAttributeGroupPtr ret = NULL;
5304
5305     if ((pctxt == NULL) || (name == NULL))
5306         return (NULL);
5307
5308     ret = (xmlSchemaAttributeGroupPtr)
5309         xmlMalloc(sizeof(xmlSchemaAttributeGroup));
5310     if (ret == NULL) {
5311         xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
5312         return (NULL);
5313     }
5314     memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
5315     ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5316     ret->name = name;
5317     ret->targetNamespace = nsName;
5318     ret->node = node;
5319
5320     /* TODO: Remove the flag. */
5321     ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5322     if (pctxt->isRedefine) {
5323         pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5324             ret, name, nsName);
5325         if (pctxt->redef == NULL) {
5326             xmlFree(ret);
5327             return(NULL);
5328         }
5329         pctxt->redefCounter = 0;
5330     }
5331     WXS_ADD_GLOBAL(pctxt, ret);
5332     WXS_ADD_PENDING(pctxt, ret);
5333     return (ret);
5334 }
5335
5336 /**
5337  * xmlSchemaAddElement:
5338  * @ctxt:  a schema parser context
5339  * @schema:  the schema being built
5340  * @name:  the type name
5341  * @namespace:  the type namespace
5342  *
5343  * Add an XML schema Element declaration
5344  * *WARNING* this interface is highly subject to change
5345  *
5346  * Returns the new struture or NULL in case of error
5347  */
5348 static xmlSchemaElementPtr
5349 xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
5350                     const xmlChar * name, const xmlChar * nsName,
5351                     xmlNodePtr node, int topLevel)
5352 {
5353     xmlSchemaElementPtr ret = NULL;
5354
5355     if ((ctxt == NULL) || (name == NULL))
5356         return (NULL);
5357
5358     ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5359     if (ret == NULL) {
5360         xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
5361         return (NULL);
5362     }
5363     memset(ret, 0, sizeof(xmlSchemaElement));
5364     ret->type = XML_SCHEMA_TYPE_ELEMENT;
5365     ret->name = name;
5366     ret->targetNamespace = nsName;
5367     ret->node = node;
5368
5369     if (topLevel)
5370         WXS_ADD_GLOBAL(ctxt, ret);
5371     else
5372         WXS_ADD_LOCAL(ctxt, ret);
5373     WXS_ADD_PENDING(ctxt, ret);
5374     return (ret);
5375 }
5376
5377 /**
5378  * xmlSchemaAddType:
5379  * @ctxt:  a schema parser context
5380  * @schema:  the schema being built
5381  * @name:  the item name
5382  * @namespace:  the namespace
5383  *
5384  * Add an XML schema item
5385  * *WARNING* this interface is highly subject to change
5386  *
5387  * Returns the new struture or NULL in case of error
5388  */
5389 static xmlSchemaTypePtr
5390 xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5391                  xmlSchemaTypeType type,
5392                  const xmlChar * name, const xmlChar * nsName,
5393                  xmlNodePtr node, int topLevel)
5394 {
5395     xmlSchemaTypePtr ret = NULL;
5396
5397     if ((ctxt == NULL) || (schema == NULL))
5398         return (NULL);
5399
5400     ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5401     if (ret == NULL) {
5402         xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
5403         return (NULL);
5404     }
5405     memset(ret, 0, sizeof(xmlSchemaType));
5406     ret->type = type;
5407     ret->name = name;
5408     ret->targetNamespace = nsName;
5409     ret->node = node;
5410     if (topLevel) {
5411         if (ctxt->isRedefine) {
5412             ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5413                 ret, name, nsName);
5414             if (ctxt->redef == NULL) {
5415                 xmlFree(ret);
5416                 return(NULL);
5417             }
5418             ctxt->redefCounter = 0;
5419         }
5420         WXS_ADD_GLOBAL(ctxt, ret);
5421     } else
5422         WXS_ADD_LOCAL(ctxt, ret);
5423     WXS_ADD_PENDING(ctxt, ret);
5424     return (ret);
5425 }
5426
5427 static xmlSchemaQNameRefPtr
5428 xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
5429                      xmlSchemaTypeType refType,
5430                      const xmlChar *refName,
5431                      const xmlChar *refNs)
5432 {
5433     xmlSchemaQNameRefPtr ret;
5434
5435     ret = (xmlSchemaQNameRefPtr)
5436         xmlMalloc(sizeof(xmlSchemaQNameRef));
5437     if (ret == NULL) {
5438         xmlSchemaPErrMemory(pctxt,
5439             "allocating QName reference item", NULL);
5440         return (NULL);
5441     }
5442     ret->node = NULL;
5443     ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5444     ret->name = refName;
5445     ret->targetNamespace = refNs;
5446     ret->item = NULL;
5447     ret->itemType = refType;
5448     /*
5449     * Store the reference item in the schema.
5450     */
5451     WXS_ADD_LOCAL(pctxt, ret);
5452     return (ret);
5453 }
5454
5455 static xmlSchemaAttributeUseProhibPtr
5456 xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5457 {
5458     xmlSchemaAttributeUseProhibPtr ret;
5459
5460     ret = (xmlSchemaAttributeUseProhibPtr)
5461         xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5462     if (ret == NULL) {
5463         xmlSchemaPErrMemory(pctxt,
5464             "allocating attribute use prohibition", NULL);
5465         return (NULL);
5466     }
5467     memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5468     ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5469     WXS_ADD_LOCAL(pctxt, ret);
5470     return (ret);
5471 }
5472
5473
5474 /**
5475  * xmlSchemaAddModelGroup:
5476  * @ctxt:  a schema parser context
5477  * @schema:  the schema being built
5478  * @type: the "compositor" type of the model group
5479  * @node: the node in the schema doc
5480  *
5481  * Adds a schema model group
5482  * *WARNING* this interface is highly subject to change
5483  *
5484  * Returns the new struture or NULL in case of error
5485  */
5486 static xmlSchemaModelGroupPtr
5487 xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5488                        xmlSchemaPtr schema,
5489                        xmlSchemaTypeType type,
5490                        xmlNodePtr node)
5491 {
5492     xmlSchemaModelGroupPtr ret = NULL;
5493
5494     if ((ctxt == NULL) || (schema == NULL))
5495         return (NULL);
5496
5497     ret = (xmlSchemaModelGroupPtr)
5498         xmlMalloc(sizeof(xmlSchemaModelGroup));
5499     if (ret == NULL) {
5500         xmlSchemaPErrMemory(ctxt, "allocating model group component",
5501             NULL);
5502         return (NULL);
5503     }
5504     memset(ret, 0, sizeof(xmlSchemaModelGroup));
5505     ret->type = type;
5506     ret->node = node;
5507     WXS_ADD_LOCAL(ctxt, ret);
5508     if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5509         (type == XML_SCHEMA_TYPE_CHOICE))
5510         WXS_ADD_PENDING(ctxt, ret);
5511     return (ret);
5512 }
5513
5514
5515 /**
5516  * xmlSchemaAddParticle:
5517  * @ctxt:  a schema parser context
5518  * @schema:  the schema being built
5519  * @node: the corresponding node in the schema doc
5520  * @min: the minOccurs
5521  * @max: the maxOccurs
5522  *
5523  * Adds an XML schema particle component.
5524  * *WARNING* this interface is highly subject to change
5525  *
5526  * Returns the new struture or NULL in case of error
5527  */
5528 static xmlSchemaParticlePtr
5529 xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
5530                      xmlNodePtr node, int min, int max)
5531 {
5532     xmlSchemaParticlePtr ret = NULL;
5533     if (ctxt == NULL)
5534         return (NULL);
5535
5536 #ifdef DEBUG
5537     fprintf(stderr, "Adding particle component\n");
5538 #endif
5539     ret = (xmlSchemaParticlePtr)
5540         xmlMalloc(sizeof(xmlSchemaParticle));
5541     if (ret == NULL) {
5542         xmlSchemaPErrMemory(ctxt, "allocating particle component",
5543             NULL);
5544         return (NULL);
5545     }
5546     ret->type = XML_SCHEMA_TYPE_PARTICLE;
5547     ret->annot = NULL;
5548     ret->node = node;
5549     ret->minOccurs = min;
5550     ret->maxOccurs = max;
5551     ret->next = NULL;
5552     ret->children = NULL;
5553
5554     WXS_ADD_LOCAL(ctxt, ret);
5555     /*
5556     * Note that addition to pending components will be done locally
5557     * to the specific parsing function, since the most particles
5558     * need not to be fixed up (i.e. the reference to be resolved).
5559     * REMOVED: WXS_ADD_PENDING(ctxt, ret);
5560     */
5561     return (ret);
5562 }
5563
5564 /**
5565  * xmlSchemaAddModelGroupDefinition:
5566  * @ctxt:  a schema validation context
5567  * @schema:  the schema being built
5568  * @name:  the group name
5569  *
5570  * Add an XML schema Group definition
5571  *
5572  * Returns the new struture or NULL in case of error
5573  */
5574 static xmlSchemaModelGroupDefPtr
5575 xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5576                                  xmlSchemaPtr schema,
5577                                  const xmlChar *name,
5578                                  const xmlChar *nsName,
5579                                  xmlNodePtr node)
5580 {
5581     xmlSchemaModelGroupDefPtr ret = NULL;
5582
5583     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5584         return (NULL);
5585
5586     ret = (xmlSchemaModelGroupDefPtr)
5587         xmlMalloc(sizeof(xmlSchemaModelGroupDef));
5588     if (ret == NULL) {
5589         xmlSchemaPErrMemory(ctxt, "adding group", NULL);
5590         return (NULL);
5591     }
5592     memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
5593     ret->name = name;
5594     ret->type = XML_SCHEMA_TYPE_GROUP;
5595     ret->node = node;
5596     ret->targetNamespace = nsName;
5597
5598     if (ctxt->isRedefine) {
5599         ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5600             ret, name, nsName);
5601         if (ctxt->redef == NULL) {
5602             xmlFree(ret);
5603             return(NULL);
5604         }
5605         ctxt->redefCounter = 0;
5606     }
5607     WXS_ADD_GLOBAL(ctxt, ret);
5608     WXS_ADD_PENDING(ctxt, ret);
5609     return (ret);
5610 }
5611
5612 /**
5613  * xmlSchemaNewWildcardNs:
5614  * @ctxt:  a schema validation context
5615  *
5616  * Creates a new wildcard namespace constraint.
5617  *
5618  * Returns the new struture or NULL in case of error
5619  */
5620 static xmlSchemaWildcardNsPtr
5621 xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5622 {
5623     xmlSchemaWildcardNsPtr ret;
5624
5625     ret = (xmlSchemaWildcardNsPtr)
5626         xmlMalloc(sizeof(xmlSchemaWildcardNs));
5627     if (ret == NULL) {
5628         xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
5629         return (NULL);
5630     }
5631     ret->value = NULL;
5632     ret->next = NULL;
5633     return (ret);
5634 }
5635
5636 static xmlSchemaIDCPtr
5637 xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5638                   const xmlChar *name, const xmlChar *nsName,
5639                   int category, xmlNodePtr node)
5640 {
5641     xmlSchemaIDCPtr ret = NULL;
5642
5643     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5644         return (NULL);
5645
5646     ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5647     if (ret == NULL) {
5648         xmlSchemaPErrMemory(ctxt,
5649             "allocating an identity-constraint definition", NULL);
5650         return (NULL);
5651     }
5652     memset(ret, 0, sizeof(xmlSchemaIDC));
5653     /* The target namespace of the parent element declaration. */
5654     ret->targetNamespace = nsName;
5655     ret->name = name;
5656     ret->type = category;
5657     ret->node = node;
5658
5659     WXS_ADD_GLOBAL(ctxt, ret);
5660     /*
5661     * Only keyrefs need to be fixup up.
5662     */
5663     if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
5664         WXS_ADD_PENDING(ctxt, ret);
5665     return (ret);
5666 }
5667
5668 /**
5669  * xmlSchemaAddWildcard:
5670  * @ctxt:  a schema validation context
5671  * @schema: a schema
5672  *
5673  * Adds a wildcard.
5674  * It corresponds to a xsd:anyAttribute and xsd:any.
5675  *
5676  * Returns the new struture or NULL in case of error
5677  */
5678 static xmlSchemaWildcardPtr
5679 xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5680                      xmlSchemaTypeType type, xmlNodePtr node)
5681 {
5682     xmlSchemaWildcardPtr ret = NULL;
5683
5684     if ((ctxt == NULL) || (schema == NULL))
5685         return (NULL);
5686
5687     ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5688     if (ret == NULL) {
5689         xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5690         return (NULL);
5691     }
5692     memset(ret, 0, sizeof(xmlSchemaWildcard));
5693     ret->type = type;
5694     ret->node = node;
5695     WXS_ADD_LOCAL(ctxt, ret);
5696     return (ret);
5697 }
5698
5699 static void
5700 xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5701 {
5702     if (group == NULL)
5703         return;
5704     if (group->members != NULL)
5705         xmlSchemaItemListFree(group->members);
5706     xmlFree(group);
5707 }
5708
5709 static xmlSchemaSubstGroupPtr
5710 xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5711                        xmlSchemaElementPtr head)
5712 {
5713     xmlSchemaSubstGroupPtr ret;
5714
5715     /* Init subst group hash. */
5716     if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5717         WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5718         if (WXS_SUBST_GROUPS(pctxt) == NULL)
5719             return(NULL);
5720     }
5721     /* Create a new substitution group. */
5722     ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5723     if (ret == NULL) {
5724         xmlSchemaPErrMemory(NULL,
5725             "allocating a substitution group container", NULL);
5726         return(NULL);
5727     }
5728     memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5729     ret->head = head;
5730     /* Create list of members. */
5731     ret->members = xmlSchemaItemListCreate();
5732     if (ret->members == NULL) {
5733         xmlSchemaSubstGroupFree(ret);
5734         return(NULL);
5735     }
5736     /* Add subst group to hash. */
5737     if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5738         head->name, head->targetNamespace, ret) != 0) {
5739         PERROR_INT("xmlSchemaSubstGroupAdd",
5740             "failed to add a new substitution container");
5741         xmlSchemaSubstGroupFree(ret);
5742         return(NULL);
5743     }
5744     return(ret);
5745 }
5746
5747 static xmlSchemaSubstGroupPtr
5748 xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5749                        xmlSchemaElementPtr head)
5750 {
5751     if (WXS_SUBST_GROUPS(pctxt) == NULL)
5752         return(NULL);
5753     return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5754         head->name, head->targetNamespace));
5755
5756 }
5757
5758 /**
5759  * xmlSchemaAddElementSubstitutionMember:
5760  * @pctxt:  a schema parser context
5761  * @head:  the head of the substitution group
5762  * @member: the new member of the substitution group
5763  *
5764  * Allocate a new annotation structure.
5765  *
5766  * Returns the newly allocated structure or NULL in case or error
5767  */
5768 static int
5769 xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5770                                       xmlSchemaElementPtr head,
5771                                       xmlSchemaElementPtr member)
5772 {
5773     xmlSchemaSubstGroupPtr substGroup = NULL;
5774
5775     if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5776         return (-1);
5777
5778     substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5779     if (substGroup == NULL)
5780         substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5781     if (substGroup == NULL)
5782         return(-1);
5783     if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5784         return(-1);
5785     return(0);
5786 }
5787
5788 /************************************************************************
5789  *                                                                      *
5790  *              Utilities for parsing                                   *
5791  *                                                                      *
5792  ************************************************************************/
5793
5794 /**
5795  * xmlSchemaPValAttrNodeQNameValue:
5796  * @ctxt:  a schema parser context
5797  * @schema: the schema context
5798  * @ownerDes: the designation of the parent element
5799  * @ownerItem: the parent as a schema object
5800  * @value:  the QName value
5801  * @local: the resulting local part if found, the attribute value otherwise
5802  * @uri:  the resulting namespace URI if found
5803  *
5804  * Extracts the local name and the URI of a QName value and validates it.
5805  * This one is intended to be used on attribute values that
5806  * should resolve to schema components.
5807  *
5808  * Returns 0, in case the QName is valid, a positive error code
5809  * if not valid and -1 if an internal error occurs.
5810  */
5811 static int
5812 xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
5813                                        xmlSchemaPtr schema,
5814                                        xmlSchemaBasicItemPtr ownerItem,
5815                                        xmlAttrPtr attr,
5816                                        const xmlChar *value,
5817                                        const xmlChar **uri,
5818                                        const xmlChar **local)
5819 {
5820     const xmlChar *pref;
5821     xmlNsPtr ns;
5822     int len, ret;
5823
5824     *uri = NULL;
5825     *local = NULL;
5826     ret = xmlValidateQName(value, 1);
5827     if (ret > 0) {
5828         xmlSchemaPSimpleTypeErr(ctxt,
5829             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5830             ownerItem, (xmlNodePtr) attr,
5831             xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5832             NULL, value, NULL, NULL, NULL);
5833         *local = value;
5834         return (ctxt->err);
5835     } else if (ret < 0)
5836         return (-1);
5837
5838     if (!strchr((char *) value, ':')) {
5839         ns = xmlSearchNs(attr->doc, attr->parent, NULL);
5840         if (ns)
5841             *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5842         else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5843             /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5844             * parser context. */
5845             /*
5846             * This one takes care of included schemas with no
5847             * target namespace.
5848             */
5849             *uri = ctxt->targetNamespace;
5850         }
5851         *local = xmlDictLookup(ctxt->dict, value, -1);
5852         return (0);
5853     }
5854     /*
5855     * At this point xmlSplitQName3 has to return a local name.
5856     */
5857     *local = xmlSplitQName3(value, &len);
5858     *local = xmlDictLookup(ctxt->dict, *local, -1);
5859     pref = xmlDictLookup(ctxt->dict, value, len);
5860     ns = xmlSearchNs(attr->doc, attr->parent, pref);
5861     if (ns == NULL) {
5862         xmlSchemaPSimpleTypeErr(ctxt,
5863             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5864             ownerItem, (xmlNodePtr) attr,
5865             xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5866             "The value '%s' of simple type 'xs:QName' has no "
5867             "corresponding namespace declaration in scope", value, NULL);
5868         return (ctxt->err);
5869     } else {
5870         *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5871     }
5872     return (0);
5873 }
5874
5875 /**
5876  * xmlSchemaPValAttrNodeQName:
5877  * @ctxt:  a schema parser context
5878  * @schema: the schema context
5879  * @ownerDes: the designation of the owner element
5880  * @ownerItem: the owner as a schema object
5881  * @attr:  the attribute node
5882  * @local: the resulting local part if found, the attribute value otherwise
5883  * @uri:  the resulting namespace URI if found
5884  *
5885  * Extracts and validates the QName of an attribute value.
5886  * This one is intended to be used on attribute values that
5887  * should resolve to schema components.
5888  *
5889  * Returns 0, in case the QName is valid, a positive error code
5890  * if not valid and -1 if an internal error occurs.
5891  */
5892 static int
5893 xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
5894                                        xmlSchemaPtr schema,
5895                                        xmlSchemaBasicItemPtr ownerItem,
5896                                        xmlAttrPtr attr,
5897                                        const xmlChar **uri,
5898                                        const xmlChar **local)
5899 {
5900     const xmlChar *value;
5901
5902     value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5903     return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5904         ownerItem, attr, value, uri, local));
5905 }
5906
5907 /**
5908  * xmlSchemaPValAttrQName:
5909  * @ctxt:  a schema parser context
5910  * @schema: the schema context
5911  * @ownerDes: the designation of the parent element
5912  * @ownerItem: the owner as a schema object
5913  * @ownerElem:  the parent node of the attribute
5914  * @name:  the name of the attribute
5915  * @local: the resulting local part if found, the attribute value otherwise
5916  * @uri:  the resulting namespace URI if found
5917  *
5918  * Extracts and validates the QName of an attribute value.
5919  *
5920  * Returns 0, in case the QName is valid, a positive error code
5921  * if not valid and -1 if an internal error occurs.
5922  */
5923 static int
5924 xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5925                                    xmlSchemaPtr schema,
5926                                    xmlSchemaBasicItemPtr ownerItem,
5927                                    xmlNodePtr ownerElem,
5928                                    const char *name,
5929                                    const xmlChar **uri,
5930                                    const xmlChar **local)
5931 {
5932     xmlAttrPtr attr;
5933
5934     attr = xmlSchemaGetPropNode(ownerElem, name);
5935     if (attr == NULL) {
5936         *local = NULL;
5937         *uri = NULL;
5938         return (0);
5939     }
5940     return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5941         ownerItem, attr, uri, local));
5942 }
5943
5944 /**
5945  * xmlSchemaPValAttrID:
5946  * @ctxt:  a schema parser context
5947  * @schema: the schema context
5948  * @ownerDes: the designation of the parent element
5949  * @ownerItem: the owner as a schema object
5950  * @ownerElem:  the parent node of the attribute
5951  * @name:  the name of the attribute
5952  *
5953  * Extracts and validates the ID of an attribute value.
5954  *
5955  * Returns 0, in case the ID is valid, a positive error code
5956  * if not valid and -1 if an internal error occurs.
5957  */
5958 static int
5959 xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
5960 {
5961     int ret;
5962     const xmlChar *value;
5963
5964     if (attr == NULL)
5965         return(0);
5966     value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
5967     ret = xmlValidateNCName(value, 1);
5968     if (ret == 0) {
5969         /*
5970         * NOTE: the IDness might have already be declared in the DTD
5971         */
5972         if (attr->atype != XML_ATTRIBUTE_ID) {
5973             xmlIDPtr res;
5974             xmlChar *strip;
5975
5976             /*
5977             * TODO: Use xmlSchemaStrip here; it's not exported at this
5978             * moment.
5979             */
5980             strip = xmlSchemaCollapseString(value);
5981             if (strip != NULL) {
5982                 xmlFree((xmlChar *) value);
5983                 value = strip;
5984             }
5985             res = xmlAddID(NULL, attr->doc, value, attr);
5986             if (res == NULL) {
5987                 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5988                 xmlSchemaPSimpleTypeErr(ctxt,
5989                     XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5990                     NULL, (xmlNodePtr) attr,
5991                     xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5992                     NULL, NULL, "Duplicate value '%s' of simple "
5993                     "type 'xs:ID'", value, NULL);
5994             } else
5995                 attr->atype = XML_ATTRIBUTE_ID;
5996         }
5997     } else if (ret > 0) {
5998         ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5999         xmlSchemaPSimpleTypeErr(ctxt,
6000             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6001             NULL, (xmlNodePtr) attr,
6002             xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
6003             NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
6004             "not a valid 'xs:NCName'",
6005             value, NULL);
6006     }
6007     if (value != NULL)
6008         xmlFree((xmlChar *)value);
6009
6010     return (ret);
6011 }
6012
6013 static int
6014 xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
6015                     xmlNodePtr ownerElem,
6016                     const xmlChar *name)
6017 {
6018     xmlAttrPtr attr;
6019
6020     attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
6021     if (attr == NULL)
6022         return(0);
6023     return(xmlSchemaPValAttrNodeID(ctxt, attr));
6024
6025 }
6026
6027 /**
6028  * xmlGetMaxOccurs:
6029  * @ctxt:  a schema validation context
6030  * @node:  a subtree containing XML Schema informations
6031  *
6032  * Get the maxOccurs property
6033  *
6034  * Returns the default if not found, or the value
6035  */
6036 static int
6037 xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6038                 int min, int max, int def, const char *expected)
6039 {
6040     const xmlChar *val, *cur;
6041     int ret = 0;
6042     xmlAttrPtr attr;
6043
6044     attr = xmlSchemaGetPropNode(node, "maxOccurs");
6045     if (attr == NULL)
6046         return (def);
6047     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6048
6049     if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
6050         if (max != UNBOUNDED) {
6051             xmlSchemaPSimpleTypeErr(ctxt,
6052                 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6053                 /* XML_SCHEMAP_INVALID_MINOCCURS, */
6054                 NULL, (xmlNodePtr) attr, NULL, expected,
6055                 val, NULL, NULL, NULL);
6056             return (def);
6057         } else
6058             return (UNBOUNDED);  /* encoding it with -1 might be another option */
6059     }
6060
6061     cur = val;
6062     while (IS_BLANK_CH(*cur))
6063         cur++;
6064     if (*cur == 0) {
6065         xmlSchemaPSimpleTypeErr(ctxt,
6066             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6067             /* XML_SCHEMAP_INVALID_MINOCCURS, */
6068             NULL, (xmlNodePtr) attr, NULL, expected,
6069             val, NULL, NULL, NULL);
6070         return (def);
6071     }
6072     while ((*cur >= '0') && (*cur <= '9')) {
6073         ret = ret * 10 + (*cur - '0');
6074         cur++;
6075     }
6076     while (IS_BLANK_CH(*cur))
6077         cur++;
6078     /*
6079     * TODO: Restrict the maximal value to Integer.
6080     */
6081     if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6082         xmlSchemaPSimpleTypeErr(ctxt,
6083             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6084             /* XML_SCHEMAP_INVALID_MINOCCURS, */
6085             NULL, (xmlNodePtr) attr, NULL, expected,
6086             val, NULL, NULL, NULL);
6087         return (def);
6088     }
6089     return (ret);
6090 }
6091
6092 /**
6093  * xmlGetMinOccurs:
6094  * @ctxt:  a schema validation context
6095  * @node:  a subtree containing XML Schema informations
6096  *
6097  * Get the minOccurs property
6098  *
6099  * Returns the default if not found, or the value
6100  */
6101 static int
6102 xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6103                 int min, int max, int def, const char *expected)
6104 {
6105     const xmlChar *val, *cur;
6106     int ret = 0;
6107     xmlAttrPtr attr;
6108
6109     attr = xmlSchemaGetPropNode(node, "minOccurs");
6110     if (attr == NULL)
6111         return (def);
6112     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6113     cur = val;
6114     while (IS_BLANK_CH(*cur))
6115         cur++;
6116     if (*cur == 0) {
6117         xmlSchemaPSimpleTypeErr(ctxt,
6118             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6119             /* XML_SCHEMAP_INVALID_MINOCCURS, */
6120             NULL, (xmlNodePtr) attr, NULL, expected,
6121             val, NULL, NULL, NULL);
6122         return (def);
6123     }
6124     while ((*cur >= '0') && (*cur <= '9')) {
6125         ret = ret * 10 + (*cur - '0');
6126         cur++;
6127     }
6128     while (IS_BLANK_CH(*cur))
6129         cur++;
6130     /*
6131     * TODO: Restrict the maximal value to Integer.
6132     */
6133     if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6134         xmlSchemaPSimpleTypeErr(ctxt,
6135             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6136             /* XML_SCHEMAP_INVALID_MINOCCURS, */
6137             NULL, (xmlNodePtr) attr, NULL, expected,
6138             val, NULL, NULL, NULL);
6139         return (def);
6140     }
6141     return (ret);
6142 }
6143
6144 /**
6145  * xmlSchemaPGetBoolNodeValue:
6146  * @ctxt:  a schema validation context
6147  * @ownerDes:  owner designation
6148  * @ownerItem:  the owner as a schema item
6149  * @node: the node holding the value
6150  *
6151  * Converts a boolean string value into 1 or 0.
6152  *
6153  * Returns 0 or 1.
6154  */
6155 static int
6156 xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
6157                            xmlSchemaBasicItemPtr ownerItem,
6158                            xmlNodePtr node)
6159 {
6160     xmlChar *value = NULL;
6161     int res = 0;
6162
6163     value = xmlNodeGetContent(node);
6164     /*
6165     * 3.2.2.1 Lexical representation
6166     * An instance of a datatype that is defined as `boolean`
6167     * can have the following legal literals {true, false, 1, 0}.
6168     */
6169     if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6170         res = 1;
6171     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6172         res = 0;
6173     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6174         res = 1;
6175     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
6176         res = 0;
6177     else {
6178         xmlSchemaPSimpleTypeErr(ctxt,
6179             XML_SCHEMAP_INVALID_BOOLEAN,
6180             ownerItem, node,
6181             xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6182             NULL, BAD_CAST value,
6183             NULL, NULL, NULL);
6184     }
6185     if (value != NULL)
6186         xmlFree(value);
6187     return (res);
6188 }
6189
6190 /**
6191  * xmlGetBooleanProp:
6192  * @ctxt:  a schema validation context
6193  * @node:  a subtree containing XML Schema informations
6194  * @name:  the attribute name
6195  * @def:  the default value
6196  *
6197  * Evaluate if a boolean property is set
6198  *
6199  * Returns the default if not found, 0 if found to be false,
6200  * 1 if found to be true
6201  */
6202 static int
6203 xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
6204                   xmlNodePtr node,
6205                   const char *name, int def)
6206 {
6207     const xmlChar *val;
6208
6209     val = xmlSchemaGetProp(ctxt, node, name);
6210     if (val == NULL)
6211         return (def);
6212     /*
6213     * 3.2.2.1 Lexical representation
6214     * An instance of a datatype that is defined as `boolean`
6215     * can have the following legal literals {true, false, 1, 0}.
6216     */
6217     if (xmlStrEqual(val, BAD_CAST "true"))
6218         def = 1;
6219     else if (xmlStrEqual(val, BAD_CAST "false"))
6220         def = 0;
6221     else if (xmlStrEqual(val, BAD_CAST "1"))
6222         def = 1;
6223     else if (xmlStrEqual(val, BAD_CAST "0"))
6224         def = 0;
6225     else {
6226         xmlSchemaPSimpleTypeErr(ctxt,
6227             XML_SCHEMAP_INVALID_BOOLEAN,
6228             NULL,
6229             (xmlNodePtr) xmlSchemaGetPropNode(node, name),
6230             xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6231             NULL, val, NULL, NULL, NULL);
6232     }
6233     return (def);
6234 }
6235
6236 /************************************************************************
6237  *                                                                      *
6238  *              Shema extraction from an Infoset                        *
6239  *                                                                      *
6240  ************************************************************************/
6241 static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6242                                                  ctxt, xmlSchemaPtr schema,
6243                                                  xmlNodePtr node,
6244                                                  int topLevel);
6245 static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6246                                                   ctxt,
6247                                                   xmlSchemaPtr schema,
6248                                                   xmlNodePtr node,
6249                                                   int topLevel);
6250 static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6251                                                   ctxt,
6252                                                   xmlSchemaPtr schema,
6253                                                   xmlNodePtr node,
6254                                                   xmlSchemaTypeType parentType);
6255 static xmlSchemaBasicItemPtr
6256 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6257                              xmlSchemaPtr schema,
6258                              xmlNodePtr node,
6259                              xmlSchemaItemListPtr uses,
6260                              int parentType);
6261 static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6262                                            xmlSchemaPtr schema,
6263                                            xmlNodePtr node);
6264 static xmlSchemaWildcardPtr
6265 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6266                            xmlSchemaPtr schema, xmlNodePtr node);
6267
6268 /**
6269  * xmlSchemaPValAttrNodeValue:
6270  *
6271  * @ctxt:  a schema parser context
6272  * @ownerDes: the designation of the parent element
6273  * @ownerItem: the schema object owner if existent
6274  * @attr:  the schema attribute node being validated
6275  * @value: the value
6276  * @type: the built-in type to be validated against
6277  *
6278  * Validates a value against the given built-in type.
6279  * This one is intended to be used internally for validation
6280  * of schema attribute values during parsing of the schema.
6281  *
6282  * Returns 0 if the value is valid, a positive error code
6283  * number otherwise and -1 in case of an internal or API error.
6284  */
6285 static int
6286 xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
6287                            xmlSchemaBasicItemPtr ownerItem,
6288                            xmlAttrPtr attr,
6289                            const xmlChar *value,
6290                            xmlSchemaTypePtr type)
6291 {
6292
6293     int ret = 0;
6294
6295     /*
6296     * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6297     * one is really meant to be used internally, so better not.
6298     */
6299     if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
6300         return (-1);
6301     if (type->type != XML_SCHEMA_TYPE_BASIC) {
6302         PERROR_INT("xmlSchemaPValAttrNodeValue",
6303             "the given type is not a built-in type");
6304         return (-1);
6305     }
6306     switch (type->builtInType) {
6307         case XML_SCHEMAS_NCNAME:
6308         case XML_SCHEMAS_QNAME:
6309         case XML_SCHEMAS_ANYURI:
6310         case XML_SCHEMAS_TOKEN:
6311         case XML_SCHEMAS_LANGUAGE:
6312             ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6313                 (xmlNodePtr) attr);
6314             break;
6315         default: {
6316             PERROR_INT("xmlSchemaPValAttrNodeValue",
6317                 "validation using the given type is not supported while "
6318                 "parsing a schema");
6319             return (-1);
6320         }
6321     }
6322     /*
6323     * TODO: Should we use the S4S error codes instead?
6324     */
6325     if (ret < 0) {
6326         PERROR_INT("xmlSchemaPValAttrNodeValue",
6327             "failed to validate a schema attribute value");
6328         return (-1);
6329     } else if (ret > 0) {
6330         if (WXS_IS_LIST(type))
6331             ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6332         else
6333             ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6334         xmlSchemaPSimpleTypeErr(pctxt,
6335             ret, ownerItem, (xmlNodePtr) attr,
6336             type, NULL, value, NULL, NULL, NULL);
6337     }
6338     return (ret);
6339 }
6340
6341 /**
6342  * xmlSchemaPValAttrNode:
6343  *
6344  * @ctxt:  a schema parser context
6345  * @ownerDes: the designation of the parent element
6346  * @ownerItem: the schema object owner if existent
6347  * @attr:  the schema attribute node being validated
6348  * @type: the built-in type to be validated against
6349  * @value: the resulting value if any
6350  *
6351  * Extracts and validates a value against the given built-in type.
6352  * This one is intended to be used internally for validation
6353  * of schema attribute values during parsing of the schema.
6354  *
6355  * Returns 0 if the value is valid, a positive error code
6356  * number otherwise and -1 in case of an internal or API error.
6357  */
6358 static int
6359 xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
6360                            xmlSchemaBasicItemPtr ownerItem,
6361                            xmlAttrPtr attr,
6362                            xmlSchemaTypePtr type,
6363                            const xmlChar **value)
6364 {
6365     const xmlChar *val;
6366
6367     if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
6368         return (-1);
6369
6370     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6371     if (value != NULL)
6372         *value = val;
6373
6374     return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
6375         val, type));
6376 }
6377
6378 /**
6379  * xmlSchemaPValAttr:
6380  *
6381  * @ctxt:  a schema parser context
6382  * @node: the element node of the attribute
6383  * @ownerDes: the designation of the parent element
6384  * @ownerItem: the schema object owner if existent
6385  * @ownerElem: the owner element node
6386  * @name:  the name of the schema attribute node
6387  * @type: the built-in type to be validated against
6388  * @value: the resulting value if any
6389  *
6390  * Extracts and validates a value against the given built-in type.
6391  * This one is intended to be used internally for validation
6392  * of schema attribute values during parsing of the schema.
6393  *
6394  * Returns 0 if the value is valid, a positive error code
6395  * number otherwise and -1 in case of an internal or API error.
6396  */
6397 static int
6398 xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6399                        xmlSchemaBasicItemPtr ownerItem,
6400                        xmlNodePtr ownerElem,
6401                        const char *name,
6402                        xmlSchemaTypePtr type,
6403                        const xmlChar **value)
6404 {
6405     xmlAttrPtr attr;
6406
6407     if ((ctxt == NULL) || (type == NULL)) {
6408         if (value != NULL)
6409             *value = NULL;
6410         return (-1);
6411     }
6412     if (type->type != XML_SCHEMA_TYPE_BASIC) {
6413         if (value != NULL)
6414             *value = NULL;
6415         xmlSchemaPErr(ctxt, ownerElem,
6416             XML_SCHEMAP_INTERNAL,
6417             "Internal error: xmlSchemaPValAttr, the given "
6418             "type '%s' is not a built-in type.\n",
6419             type->name, NULL);
6420         return (-1);
6421     }
6422     attr = xmlSchemaGetPropNode(ownerElem, name);
6423     if (attr == NULL) {
6424         if (value != NULL)
6425             *value = NULL;
6426         return (0);
6427     }
6428     return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
6429         type, value));
6430 }
6431
6432 static int
6433 xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
6434                   xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6435                   xmlNodePtr node,
6436                   xmlAttrPtr attr,
6437                   const xmlChar *namespaceName)
6438 {
6439     /* TODO: Pointer comparison instead? */
6440     if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
6441         return (0);
6442     if (xmlStrEqual(xmlSchemaNs, namespaceName))
6443         return (0);
6444     /*
6445     * Check if the referenced namespace was <import>ed.
6446     */
6447     if (WXS_BUCKET(pctxt)->relations != NULL) {
6448         xmlSchemaSchemaRelationPtr rel;
6449
6450         rel = WXS_BUCKET(pctxt)->relations;
6451         do {
6452             if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
6453                 xmlStrEqual(namespaceName, rel->importNamespace))
6454                 return (0);
6455             rel = rel->next;
6456         } while (rel != NULL);
6457     }
6458     /*
6459     * No matching <import>ed namespace found.
6460     */
6461     {
6462         xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6463
6464         if (namespaceName == NULL)
6465             xmlSchemaCustomErr(ACTXT_CAST pctxt,
6466                 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6467                 "References from this schema to components in no "
6468                 "namespace are not allowed, since not indicated by an "
6469                 "import statement", NULL, NULL);
6470         else
6471             xmlSchemaCustomErr(ACTXT_CAST pctxt,
6472                 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6473                 "References from this schema to components in the "
6474                 "namespace '%s' are not allowed, since not indicated by an "
6475                 "import statement", namespaceName, NULL);
6476     }
6477     return (XML_SCHEMAP_SRC_RESOLVE);
6478 }
6479
6480 /**
6481  * xmlSchemaParseLocalAttributes:
6482  * @ctxt:  a schema validation context
6483  * @schema:  the schema being built
6484  * @node:  a subtree containing XML Schema informations
6485  * @type:  the hosting type where the attributes will be anchored
6486  *
6487  * Parses attribute uses and attribute declarations and
6488  * attribute group references.
6489  */
6490 static int
6491 xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6492                         xmlNodePtr *child, xmlSchemaItemListPtr *list,
6493                         int parentType, int *hasRefs)
6494 {
6495     void *item;
6496
6497     while ((IS_SCHEMA((*child), "attribute")) ||
6498            (IS_SCHEMA((*child), "attributeGroup"))) {
6499         if (IS_SCHEMA((*child), "attribute")) {
6500             item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6501                 *list, parentType);
6502         } else {
6503             item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6504             if ((item != NULL) && (hasRefs != NULL))
6505                 *hasRefs = 1;
6506         }
6507         if (item != NULL) {
6508             if (*list == NULL) {
6509                 /* TODO: Customize grow factor. */
6510                 *list = xmlSchemaItemListCreate();
6511                 if (*list == NULL)
6512                     return(-1);
6513             }
6514             if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6515                 return(-1);
6516         }
6517         *child = (*child)->next;
6518     }
6519     return (0);
6520 }
6521
6522 /**
6523  * xmlSchemaParseAnnotation:
6524  * @ctxt:  a schema validation context
6525  * @schema:  the schema being built
6526  * @node:  a subtree containing XML Schema informations
6527  *
6528  * parse a XML schema Attrribute declaration
6529  * *WARNING* this interface is highly subject to change
6530  *
6531  * Returns -1 in case of error, 0 if the declaration is improper and
6532  *         1 in case of success.
6533  */
6534 static xmlSchemaAnnotPtr
6535 xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed)
6536 {
6537     xmlSchemaAnnotPtr ret;
6538     xmlNodePtr child = NULL;
6539     xmlAttrPtr attr;
6540     int barked = 0;
6541
6542     /*
6543     * INFO: S4S completed.
6544     */
6545     /*
6546     * id = ID
6547     * {any attributes with non-schema namespace . . .}>
6548     * Content: (appinfo | documentation)*
6549     */
6550     if ((ctxt == NULL) || (node == NULL))
6551         return (NULL);
6552     if (needed)
6553         ret = xmlSchemaNewAnnot(ctxt, node);
6554     else
6555         ret = NULL;
6556     attr = node->properties;
6557     while (attr != NULL) {
6558         if (((attr->ns == NULL) &&
6559             (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
6560             ((attr->ns != NULL) &&
6561             xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6562
6563             xmlSchemaPIllegalAttrErr(ctxt,
6564                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6565         }
6566         attr = attr->next;
6567     }
6568     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6569     /*
6570     * And now for the children...
6571     */
6572     child = node->children;
6573     while (child != NULL) {
6574         if (IS_SCHEMA(child, "appinfo")) {
6575             /* TODO: make available the content of "appinfo". */
6576             /*
6577             * source = anyURI
6578             * {any attributes with non-schema namespace . . .}>
6579             * Content: ({any})*
6580             */
6581             attr = child->properties;
6582             while (attr != NULL) {
6583                 if (((attr->ns == NULL) &&
6584                      (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
6585                      ((attr->ns != NULL) &&
6586                       xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6587
6588                     xmlSchemaPIllegalAttrErr(ctxt,
6589                         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6590                 }
6591                 attr = attr->next;
6592             }
6593             xmlSchemaPValAttr(ctxt, NULL, child, "source",
6594                 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
6595             child = child->next;
6596         } else if (IS_SCHEMA(child, "documentation")) {
6597             /* TODO: make available the content of "documentation". */
6598             /*
6599             * source = anyURI
6600             * {any attributes with non-schema namespace . . .}>
6601             * Content: ({any})*
6602             */
6603             attr = child->properties;
6604             while (attr != NULL) {
6605                 if (attr->ns == NULL) {
6606                     if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
6607                         xmlSchemaPIllegalAttrErr(ctxt,
6608                             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6609                     }
6610                 } else {
6611                     if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6612                         (xmlStrEqual(attr->name, BAD_CAST "lang") &&
6613                         (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
6614
6615                         xmlSchemaPIllegalAttrErr(ctxt,
6616                             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6617                     }
6618                 }
6619                 attr = attr->next;
6620             }
6621             /*
6622             * Attribute "xml:lang".
6623             */
6624             attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6625             if (attr != NULL)
6626                 xmlSchemaPValAttrNode(ctxt, NULL, attr,
6627                 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
6628             child = child->next;
6629         } else {
6630             if (!barked)
6631                 xmlSchemaPContentErr(ctxt,
6632                     XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6633                     NULL, node, child, NULL, "(appinfo | documentation)*");
6634             barked = 1;
6635             child = child->next;
6636         }
6637     }
6638
6639     return (ret);
6640 }
6641
6642 /**
6643  * xmlSchemaParseFacet:
6644  * @ctxt:  a schema validation context
6645  * @schema:  the schema being built
6646  * @node:  a subtree containing XML Schema informations
6647  *
6648  * parse a XML schema Facet declaration
6649  * *WARNING* this interface is highly subject to change
6650  *
6651  * Returns the new type structure or NULL in case of error
6652  */
6653 static xmlSchemaFacetPtr
6654 xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6655                     xmlNodePtr node)
6656 {
6657     xmlSchemaFacetPtr facet;
6658     xmlNodePtr child = NULL;
6659     const xmlChar *value;
6660
6661     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6662         return (NULL);
6663
6664     facet = xmlSchemaNewFacet();
6665     if (facet == NULL) {
6666         xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6667         return (NULL);
6668     }
6669     facet->node = node;
6670     value = xmlSchemaGetProp(ctxt, node, "value");
6671     if (value == NULL) {
6672         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6673                        "Facet %s has no value\n", node->name, NULL);
6674         xmlSchemaFreeFacet(facet);
6675         return (NULL);
6676     }
6677     if (IS_SCHEMA(node, "minInclusive")) {
6678         facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
6679     } else if (IS_SCHEMA(node, "minExclusive")) {
6680         facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
6681     } else if (IS_SCHEMA(node, "maxInclusive")) {
6682         facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
6683     } else if (IS_SCHEMA(node, "maxExclusive")) {
6684         facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
6685     } else if (IS_SCHEMA(node, "totalDigits")) {
6686         facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
6687     } else if (IS_SCHEMA(node, "fractionDigits")) {
6688         facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
6689     } else if (IS_SCHEMA(node, "pattern")) {
6690         facet->type = XML_SCHEMA_FACET_PATTERN;
6691     } else if (IS_SCHEMA(node, "enumeration")) {
6692         facet->type = XML_SCHEMA_FACET_ENUMERATION;
6693     } else if (IS_SCHEMA(node, "whiteSpace")) {
6694         facet->type = XML_SCHEMA_FACET_WHITESPACE;
6695     } else if (IS_SCHEMA(node, "length")) {
6696         facet->type = XML_SCHEMA_FACET_LENGTH;
6697     } else if (IS_SCHEMA(node, "maxLength")) {
6698         facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6699     } else if (IS_SCHEMA(node, "minLength")) {
6700         facet->type = XML_SCHEMA_FACET_MINLENGTH;
6701     } else {
6702         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6703                        "Unknown facet type %s\n", node->name, NULL);
6704         xmlSchemaFreeFacet(facet);
6705         return (NULL);
6706     }
6707     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6708     facet->value = value;
6709     if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6710         (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6711         const xmlChar *fixed;
6712
6713         fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6714         if (fixed != NULL) {
6715             if (xmlStrEqual(fixed, BAD_CAST "true"))
6716                 facet->fixed = 1;
6717         }
6718     }
6719     child = node->children;
6720
6721     if (IS_SCHEMA(child, "annotation")) {
6722         facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6723         child = child->next;
6724     }
6725     if (child != NULL) {
6726         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6727                        "Facet %s has unexpected child content\n",
6728                        node->name, NULL);
6729     }
6730     return (facet);
6731 }
6732
6733 /**
6734  * xmlSchemaParseWildcardNs:
6735  * @ctxt:  a schema parser context
6736  * @wildc:  the wildcard, already created
6737  * @node:  a subtree containing XML Schema informations
6738  *
6739  * Parses the attribute "processContents" and "namespace"
6740  * of a xsd:anyAttribute and xsd:any.
6741  * *WARNING* this interface is highly subject to change
6742  *
6743  * Returns 0 if everything goes fine, a positive error code
6744  * if something is not valid and -1 if an internal error occurs.
6745  */
6746 static int
6747 xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
6748                          xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6749                          xmlSchemaWildcardPtr wildc,
6750                          xmlNodePtr node)
6751 {
6752     const xmlChar *pc, *ns, *dictnsItem;
6753     int ret = 0;
6754     xmlChar *nsItem;
6755     xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6756     xmlAttrPtr attr;
6757
6758     pc = xmlSchemaGetProp(ctxt, node, "processContents");
6759     if ((pc == NULL)
6760         || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6761         wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6762     } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6763         wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6764     } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6765         wildc->processContents = XML_SCHEMAS_ANY_LAX;
6766     } else {
6767         xmlSchemaPSimpleTypeErr(ctxt,
6768             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6769             NULL, node,
6770             NULL, "(strict | skip | lax)", pc,
6771             NULL, NULL, NULL);
6772         wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6773         ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6774     }
6775     /*
6776      * Build the namespace constraints.
6777      */
6778     attr = xmlSchemaGetPropNode(node, "namespace");
6779     ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6780     if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
6781         wildc->any = 1;
6782     else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6783         wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6784         if (wildc->negNsSet == NULL) {
6785             return (-1);
6786         }
6787         wildc->negNsSet->value = ctxt->targetNamespace;
6788     } else {
6789         const xmlChar *end, *cur;
6790
6791         cur = ns;
6792         do {
6793             while (IS_BLANK_CH(*cur))
6794                 cur++;
6795             end = cur;
6796             while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6797                 end++;
6798             if (end == cur)
6799                 break;
6800             nsItem = xmlStrndup(cur, end - cur);
6801             if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6802                     (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
6803                 xmlSchemaPSimpleTypeErr(ctxt,
6804                     XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
6805                     NULL, (xmlNodePtr) attr,
6806                     NULL,
6807                     "((##any | ##other) | List of (xs:anyURI | "
6808                     "(##targetNamespace | ##local)))",
6809                     nsItem, NULL, NULL, NULL);
6810                 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6811             } else {
6812                 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
6813                     dictnsItem = ctxt->targetNamespace;
6814                 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6815                     dictnsItem = NULL;
6816                 } else {
6817                     /*
6818                     * Validate the item (anyURI).
6819                     */
6820                     xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
6821                         nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6822                     dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6823                 }
6824                 /*
6825                 * Avoid dublicate namespaces.
6826                 */
6827                 tmp = wildc->nsSet;
6828                 while (tmp != NULL) {
6829                     if (dictnsItem == tmp->value)
6830                         break;
6831                     tmp = tmp->next;
6832                 }
6833                 if (tmp == NULL) {
6834                     tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6835                     if (tmp == NULL) {
6836                         xmlFree(nsItem);
6837                         return (-1);
6838                     }
6839                     tmp->value = dictnsItem;
6840                     tmp->next = NULL;
6841                     if (wildc->nsSet == NULL)
6842                         wildc->nsSet = tmp;
6843                     else if (lastNs != NULL)
6844                         lastNs->next = tmp;
6845                     lastNs = tmp;
6846                 }
6847
6848             }
6849             xmlFree(nsItem);
6850             cur = end;
6851         } while (*cur != 0);
6852     }
6853     return (ret);
6854 }
6855
6856 static int
6857 xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6858                                  xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
6859                                  xmlNodePtr node,
6860                                  int minOccurs,
6861                                  int maxOccurs) {
6862
6863     if ((maxOccurs == 0) && ( minOccurs == 0))
6864         return (0);
6865     if (maxOccurs != UNBOUNDED) {
6866         /*
6867         * TODO: Maybe we should better not create the particle,
6868         * if min/max is invalid, since it could confuse the build of the
6869         * content model.
6870         */
6871         /*
6872         * 3.9.6 Schema Component Constraint: Particle Correct
6873         *
6874         */
6875         if (maxOccurs < 1) {
6876             /*
6877             * 2.2 {max occurs} must be greater than or equal to 1.
6878             */
6879             xmlSchemaPCustomAttrErr(ctxt,
6880                 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
6881                 NULL, NULL,
6882                 xmlSchemaGetPropNode(node, "maxOccurs"),
6883                 "The value must be greater than or equal to 1");
6884             return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6885         } else if (minOccurs > maxOccurs) {
6886             /*
6887             * 2.1 {min occurs} must not be greater than {max occurs}.
6888             */
6889             xmlSchemaPCustomAttrErr(ctxt,
6890                 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
6891                 NULL, NULL,
6892                 xmlSchemaGetPropNode(node, "minOccurs"),
6893                 "The value must not be greater than the value of 'maxOccurs'");
6894             return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6895         }
6896     }
6897     return (0);
6898 }
6899
6900 /**
6901  * xmlSchemaParseAny:
6902  * @ctxt:  a schema validation context
6903  * @schema:  the schema being built
6904  * @node:  a subtree containing XML Schema informations
6905  *
6906  * Parsea a XML schema <any> element. A particle and wildcard
6907  * will be created (except if minOccurs==maxOccurs==0, in this case
6908  * nothing will be created).
6909  * *WARNING* this interface is highly subject to change
6910  *
6911  * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
6912  */
6913 static xmlSchemaParticlePtr
6914 xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6915                   xmlNodePtr node)
6916 {
6917     xmlSchemaParticlePtr particle;
6918     xmlNodePtr child = NULL;
6919     xmlSchemaWildcardPtr wild;
6920     int min, max;
6921     xmlAttrPtr attr;
6922     xmlSchemaAnnotPtr annot = NULL;
6923
6924     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6925         return (NULL);
6926     /*
6927     * Check for illegal attributes.
6928     */
6929     attr = node->properties;
6930     while (attr != NULL) {
6931         if (attr->ns == NULL) {
6932             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6933                 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6934                 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6935                 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6936                 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
6937                 xmlSchemaPIllegalAttrErr(ctxt,
6938                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6939             }
6940         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6941             xmlSchemaPIllegalAttrErr(ctxt,
6942                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6943         }
6944         attr = attr->next;
6945     }
6946     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6947     /*
6948     * minOccurs/maxOccurs.
6949     */
6950     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6951         "(xs:nonNegativeInteger | unbounded)");
6952     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6953         "xs:nonNegativeInteger");
6954     xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6955     /*
6956     * Create & parse the wildcard.
6957     */
6958     wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6959     if (wild == NULL)
6960         return (NULL);
6961     xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
6962     /*
6963     * And now for the children...
6964     */
6965     child = node->children;
6966     if (IS_SCHEMA(child, "annotation")) {
6967         annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6968         child = child->next;
6969     }
6970     if (child != NULL) {
6971         xmlSchemaPContentErr(ctxt,
6972             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6973             NULL, node, child,
6974             NULL, "(annotation?)");
6975     }
6976     /*
6977     * No component if minOccurs==maxOccurs==0.
6978     */
6979     if ((min == 0) && (max == 0)) {
6980         /* Don't free the wildcard, since it's already on the list. */
6981         return (NULL);
6982     }
6983     /*
6984     * Create the particle.
6985     */
6986     particle = xmlSchemaAddParticle(ctxt, node, min, max);
6987     if (particle == NULL)
6988         return (NULL);
6989     particle->annot = annot;
6990     particle->children = (xmlSchemaTreeItemPtr) wild;
6991
6992     return (particle);
6993 }
6994
6995 /**
6996  * xmlSchemaParseNotation:
6997  * @ctxt:  a schema validation context
6998  * @schema:  the schema being built
6999  * @node:  a subtree containing XML Schema informations
7000  *
7001  * parse a XML schema Notation declaration
7002  *
7003  * Returns the new structure or NULL in case of error
7004  */
7005 static xmlSchemaNotationPtr
7006 xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
7007                        xmlNodePtr node)
7008 {
7009     const xmlChar *name;
7010     xmlSchemaNotationPtr ret;
7011     xmlNodePtr child = NULL;
7012
7013     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7014         return (NULL);
7015     name = xmlSchemaGetProp(ctxt, node, "name");
7016     if (name == NULL) {
7017         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
7018                        "Notation has no name\n", NULL, NULL);
7019         return (NULL);
7020     }
7021     ret = xmlSchemaAddNotation(ctxt, schema, name,
7022         ctxt->targetNamespace, node);
7023     if (ret == NULL)
7024         return (NULL);
7025     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7026
7027     child = node->children;
7028     if (IS_SCHEMA(child, "annotation")) {
7029         ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7030         child = child->next;
7031     }
7032     if (child != NULL) {
7033         xmlSchemaPContentErr(ctxt,
7034             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7035             NULL, node, child,
7036             NULL, "(annotation?)");
7037     }
7038
7039     return (ret);
7040 }
7041
7042 /**
7043  * xmlSchemaParseAnyAttribute:
7044  * @ctxt:  a schema validation context
7045  * @schema:  the schema being built
7046  * @node:  a subtree containing XML Schema informations
7047  *
7048  * parse a XML schema AnyAttrribute declaration
7049  * *WARNING* this interface is highly subject to change
7050  *
7051  * Returns a wildcard or NULL.
7052  */
7053 static xmlSchemaWildcardPtr
7054 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
7055                            xmlSchemaPtr schema, xmlNodePtr node)
7056 {
7057     xmlSchemaWildcardPtr ret;
7058     xmlNodePtr child = NULL;
7059     xmlAttrPtr attr;
7060
7061     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7062         return (NULL);
7063
7064     ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
7065         node);
7066     if (ret == NULL) {
7067         return (NULL);
7068     }
7069     /*
7070     * Check for illegal attributes.
7071     */
7072     attr = node->properties;
7073     while (attr != NULL) {
7074         if (attr->ns == NULL) {
7075             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7076                 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7077                 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
7078                 xmlSchemaPIllegalAttrErr(ctxt,
7079                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7080             }
7081         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7082             xmlSchemaPIllegalAttrErr(ctxt,
7083                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7084         }
7085         attr = attr->next;
7086     }
7087     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7088     /*
7089     * Parse the namespace list.
7090     */
7091     if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
7092         return (NULL);
7093     /*
7094     * And now for the children...
7095     */
7096     child = node->children;
7097     if (IS_SCHEMA(child, "annotation")) {
7098         ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7099         child = child->next;
7100     }
7101     if (child != NULL) {
7102         xmlSchemaPContentErr(ctxt,
7103             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7104             NULL, node, child,
7105             NULL, "(annotation?)");
7106     }
7107
7108     return (ret);
7109 }
7110
7111
7112 /**
7113  * xmlSchemaParseAttribute:
7114  * @ctxt:  a schema validation context
7115  * @schema:  the schema being built
7116  * @node:  a subtree containing XML Schema informations
7117  *
7118  * parse a XML schema Attrribute declaration
7119  * *WARNING* this interface is highly subject to change
7120  *
7121  * Returns the attribute declaration.
7122  */
7123 static xmlSchemaBasicItemPtr
7124 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7125                              xmlSchemaPtr schema,
7126                              xmlNodePtr node,
7127                              xmlSchemaItemListPtr uses,
7128                              int parentType)
7129 {
7130     const xmlChar *attrValue, *name = NULL, *ns = NULL;
7131     xmlSchemaAttributeUsePtr use = NULL;
7132     xmlNodePtr child = NULL;
7133     xmlAttrPtr attr;
7134     const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7135     int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7136     int nberrors, hasForm = 0, defValueType = 0;
7137
7138 #define WXS_ATTR_DEF_VAL_DEFAULT 1
7139 #define WXS_ATTR_DEF_VAL_FIXED 2
7140
7141     /*
7142      * 3.2.3 Constraints on XML Representations of Attribute Declarations
7143      */
7144
7145     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7146         return (NULL);
7147     attr = xmlSchemaGetPropNode(node, "ref");
7148     if (attr != NULL) {
7149         if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7150             NULL, attr, &tmpNs, &tmpName) != 0) {
7151             return (NULL);
7152         }
7153         if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7154             return(NULL);
7155         isRef = 1;
7156     }
7157     nberrors = pctxt->nberrors;
7158     /*
7159     * Check for illegal attributes.
7160     */
7161     attr = node->properties;
7162     while (attr != NULL) {
7163         if (attr->ns == NULL) {
7164             if (isRef) {
7165                 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7166                     xmlSchemaPValAttrNodeID(pctxt, attr);
7167                     goto attr_next;
7168                 } else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7169                     goto attr_next;
7170                 }
7171             } else {
7172                 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7173                     goto attr_next;
7174                 } else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7175                     xmlSchemaPValAttrNodeID(pctxt, attr);
7176                     goto attr_next;
7177                 } else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7178                     xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7179                         attr, &tmpNs, &tmpName);
7180                     goto attr_next;
7181                 } else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7182                     /*
7183                     * Evaluate the target namespace
7184                     */
7185                     hasForm = 1;
7186                     attrValue = xmlSchemaGetNodeContent(pctxt,
7187                         (xmlNodePtr) attr);
7188                     if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7189                         ns = pctxt->targetNamespace;
7190                     } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7191                     {
7192                         xmlSchemaPSimpleTypeErr(pctxt,
7193                             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7194                             NULL, (xmlNodePtr) attr,
7195                             NULL, "(qualified | unqualified)",
7196                             attrValue, NULL, NULL, NULL);
7197                     }
7198                     goto attr_next;
7199                 }
7200             }
7201             if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7202
7203                 attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7204                 /* TODO: Maybe we need to normalize the value beforehand. */
7205                 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7206                     occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7207                 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7208                     occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7209                 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7210                     occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7211                 else {
7212                     xmlSchemaPSimpleTypeErr(pctxt,
7213                         XML_SCHEMAP_INVALID_ATTR_USE,
7214                         NULL, (xmlNodePtr) attr,
7215                         NULL, "(optional | prohibited | required)",
7216                         attrValue, NULL, NULL, NULL);
7217                 }
7218                 goto attr_next;
7219             } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7220                 /*
7221                 * 3.2.3 : 1
7222                 * default and fixed must not both be present.
7223                 */
7224                 if (defValue) {
7225                     xmlSchemaPMutualExclAttrErr(pctxt,
7226                         XML_SCHEMAP_SRC_ATTRIBUTE_1,
7227                         NULL, attr, "default", "fixed");
7228                 } else {
7229                     defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7230                     defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7231                 }
7232                 goto attr_next;
7233             } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7234                 /*
7235                 * 3.2.3 : 1
7236                 * default and fixed must not both be present.
7237                 */
7238                 if (defValue) {
7239                     xmlSchemaPMutualExclAttrErr(pctxt,
7240                         XML_SCHEMAP_SRC_ATTRIBUTE_1,
7241                         NULL, attr, "default", "fixed");
7242                 } else {
7243                     defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7244                     defValueType = WXS_ATTR_DEF_VAL_FIXED;
7245                 }
7246                 goto attr_next;
7247             }
7248         } else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7249             goto attr_next;
7250
7251         xmlSchemaPIllegalAttrErr(pctxt,
7252             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7253
7254 attr_next:
7255         attr = attr->next;
7256     }
7257     /*
7258     * 3.2.3 : 2
7259     * If default and use are both present, use must have
7260     * the actual value optional.
7261     */
7262     if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7263         (occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7264         xmlSchemaPSimpleTypeErr(pctxt,
7265             XML_SCHEMAP_SRC_ATTRIBUTE_2,
7266             NULL, node, NULL,
7267             "(optional | prohibited | required)", NULL,
7268             "The value of the attribute 'use' must be 'optional' "
7269             "if the attribute 'default' is present",
7270             NULL, NULL);
7271     }
7272     /*
7273     * We want correct attributes.
7274     */
7275     if (nberrors != pctxt->nberrors)
7276         return(NULL);
7277     if (! isRef) {
7278         xmlSchemaAttributePtr attrDecl;
7279
7280         /* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7281         if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7282             ns = pctxt->targetNamespace;
7283         /*
7284         * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7285         * TODO: Move this to the component layer.
7286         */
7287         if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7288             xmlSchemaCustomErr(ACTXT_CAST pctxt,
7289                 XML_SCHEMAP_NO_XSI,
7290                 node, NULL,
7291                 "The target namespace must not match '%s'",
7292                 xmlSchemaInstanceNs, NULL);
7293         }
7294         attr = xmlSchemaGetPropNode(node, "name");
7295         if (attr == NULL) {
7296             xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7297                 NULL, node, "name", NULL);
7298             return (NULL);
7299         }
7300         if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7301             xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7302             return (NULL);
7303         }
7304         /*
7305         * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7306         * TODO: Move this to the component layer.
7307         */
7308         if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7309             xmlSchemaPSimpleTypeErr(pctxt,
7310                 XML_SCHEMAP_NO_XMLNS,
7311                 NULL, (xmlNodePtr) attr,
7312                 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7313                 "The value of the attribute must not match 'xmlns'",
7314                 NULL, NULL);
7315             return (NULL);
7316         }
7317         if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7318             goto check_children;
7319         /*
7320         * Create the attribute use component.
7321         */
7322         use = xmlSchemaAddAttributeUse(pctxt, node);
7323         if (use == NULL)
7324             return(NULL);
7325         use->occurs = occurs;
7326         /*
7327         * Create the attribute declaration.
7328         */
7329         attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7330         if (attrDecl == NULL)
7331             return (NULL);
7332         if (tmpName != NULL) {
7333             attrDecl->typeName = tmpName;
7334             attrDecl->typeNs = tmpNs;
7335         }
7336         use->attrDecl = attrDecl;
7337         /*
7338         * Value constraint.
7339         */
7340         if (defValue != NULL) {
7341             attrDecl->defValue = defValue;
7342             if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7343                 attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7344         }
7345     } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7346         xmlSchemaQNameRefPtr ref;
7347
7348         /*
7349         * Create the attribute use component.
7350         */
7351         use = xmlSchemaAddAttributeUse(pctxt, node);
7352         if (use == NULL)
7353             return(NULL);
7354         /*
7355         * We need to resolve the reference at later stage.
7356         */
7357         WXS_ADD_PENDING(pctxt, use);
7358         use->occurs = occurs;
7359         /*
7360         * Create a QName reference to the attribute declaration.
7361         */
7362         ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7363             tmpName, tmpNs);
7364         if (ref == NULL)
7365             return(NULL);
7366         /*
7367         * Assign the reference. This will be substituted for the
7368         * referenced attribute declaration when the QName is resolved.
7369         */
7370         use->attrDecl = WXS_ATTR_CAST ref;
7371         /*
7372         * Value constraint.
7373         */
7374         if (defValue != NULL)
7375             use->defValue = defValue;
7376             if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7377                 use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7378     }
7379
7380 check_children:
7381     /*
7382     * And now for the children...
7383     */
7384     child = node->children;
7385     if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7386         xmlSchemaAttributeUseProhibPtr prohib;
7387
7388         if (IS_SCHEMA(child, "annotation")) {
7389             xmlSchemaParseAnnotation(pctxt, child, 0);
7390             child = child->next;
7391         }
7392         if (child != NULL) {
7393             xmlSchemaPContentErr(pctxt,
7394                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7395                 NULL, node, child, NULL,
7396                 "(annotation?)");
7397         }
7398         /*
7399         * Check for pointlessness of attribute prohibitions.
7400         */
7401         if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7402             xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7403                 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7404                 node, NULL,
7405                 "Skipping attribute use prohibition, since it is "
7406                 "pointless inside an <attributeGroup>",
7407                 NULL, NULL, NULL);
7408             return(NULL);
7409         } else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7410             xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7411                 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7412                 node, NULL,
7413                 "Skipping attribute use prohibition, since it is "
7414                 "pointless when extending a type",
7415                 NULL, NULL, NULL);
7416             return(NULL);
7417         }
7418         if (! isRef) {
7419             tmpName = name;
7420             tmpNs = ns;
7421         }
7422         /*
7423         * Check for duplicate attribute prohibitions.
7424         */
7425         if (uses) {
7426             int i;
7427
7428             for (i = 0; i < uses->nbItems; i++) {
7429                 use = uses->items[i];
7430                 if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7431                     (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7432                     (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7433                 {
7434                     xmlChar *str = NULL;
7435
7436                     xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7437                         XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7438                         node, NULL,
7439                         "Skipping duplicate attribute use prohibition '%s'",
7440                         xmlSchemaFormatQName(&str, tmpNs, tmpName),
7441                         NULL, NULL);
7442                     FREE_AND_NULL(str)
7443                     return(NULL);
7444                 }
7445             }
7446         }
7447         /*
7448         * Create the attribute prohibition helper component.
7449         */
7450         prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7451         if (prohib == NULL)
7452             return(NULL);
7453         prohib->node = node;
7454         prohib->name = tmpName;
7455         prohib->targetNamespace = tmpNs;
7456         if (isRef) {
7457             /*
7458             * We need at least to resolve to the attribute declaration.
7459             */
7460             WXS_ADD_PENDING(pctxt, prohib);
7461         }
7462         return(WXS_BASIC_CAST prohib);
7463     } else {
7464         if (IS_SCHEMA(child, "annotation")) {
7465             /*
7466             * TODO: Should this go into the attr decl?
7467             */
7468             use->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7469             child = child->next;
7470         }
7471         if (isRef) {
7472             if (child != NULL) {
7473                 if (IS_SCHEMA(child, "simpleType"))
7474                     /*
7475                     * 3.2.3 : 3.2
7476                     * If ref is present, then all of <simpleType>,
7477                     * form and type must be absent.
7478                     */
7479                     xmlSchemaPContentErr(pctxt,
7480                         XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7481                         NULL, node, child, NULL,
7482                         "(annotation?)");
7483                 else
7484                     xmlSchemaPContentErr(pctxt,
7485                         XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7486                         NULL, node, child, NULL,
7487                         "(annotation?)");
7488             }
7489         } else {
7490             if (IS_SCHEMA(child, "simpleType")) {
7491                 if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7492                     /*
7493                     * 3.2.3 : 4
7494                     * type and <simpleType> must not both be present.
7495                     */
7496                     xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7497                         NULL, node, child,
7498                         "The attribute 'type' and the <simpleType> child "
7499                         "are mutually exclusive", NULL);
7500                 } else
7501                     WXS_ATTRUSE_TYPEDEF(use) =
7502                         xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7503                 child = child->next;
7504             }
7505             if (child != NULL)
7506                 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7507                 NULL, node, child, NULL,
7508                 "(annotation?, simpleType?)");
7509         }
7510     }
7511     return (WXS_BASIC_CAST use);
7512 }
7513
7514
7515 static xmlSchemaAttributePtr
7516 xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7517                               xmlSchemaPtr schema,
7518                               xmlNodePtr node)
7519 {
7520     const xmlChar *attrValue;
7521     xmlSchemaAttributePtr ret;
7522     xmlNodePtr child = NULL;
7523     xmlAttrPtr attr;
7524
7525     /*
7526      * Note that the w3c spec assumes the schema to be validated with schema
7527      * for schemas beforehand.
7528      *
7529      * 3.2.3 Constraints on XML Representations of Attribute Declarations
7530      */
7531     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7532         return (NULL);
7533     /*
7534     * 3.2.3 : 3.1
7535     * One of ref or name must be present, but not both
7536     */
7537     attr = xmlSchemaGetPropNode(node, "name");
7538     if (attr == NULL) {
7539         xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7540             NULL, node, "name", NULL);
7541         return (NULL);
7542     }
7543     if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7544         xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7545         return (NULL);
7546     }
7547     /*
7548     * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7549     * TODO: Move this to the component layer.
7550     */
7551     if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7552         xmlSchemaPSimpleTypeErr(pctxt,
7553             XML_SCHEMAP_NO_XMLNS,
7554             NULL, (xmlNodePtr) attr,
7555             xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7556             "The value of the attribute must not match 'xmlns'",
7557             NULL, NULL);
7558         return (NULL);
7559     }
7560     /*
7561     * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7562     * TODO: Move this to the component layer.
7563     *       Or better leave it here and add it to the component layer
7564     *       if we have a schema construction API.
7565     */
7566     if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7567         xmlSchemaCustomErr(ACTXT_CAST pctxt,
7568             XML_SCHEMAP_NO_XSI, node, NULL,
7569             "The target namespace must not match '%s'",
7570             xmlSchemaInstanceNs, NULL);
7571     }
7572
7573     ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7574         pctxt->targetNamespace, node, 1);
7575     if (ret == NULL)
7576         return (NULL);
7577     ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7578
7579     /*
7580     * Check for illegal attributes.
7581     */
7582     attr = node->properties;
7583     while (attr != NULL) {
7584         if (attr->ns == NULL) {
7585             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7586                 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7587                 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7588                 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7589                 (!xmlStrEqual(attr->name, BAD_CAST "type")))
7590             {
7591                 xmlSchemaPIllegalAttrErr(pctxt,
7592                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7593             }
7594         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7595             xmlSchemaPIllegalAttrErr(pctxt,
7596                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7597         }
7598         attr = attr->next;
7599     }
7600     xmlSchemaPValAttrQName(pctxt, schema, NULL,
7601         node, "type", &ret->typeNs, &ret->typeName);
7602
7603     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7604     /*
7605     * Attribute "fixed".
7606     */
7607     ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
7608     if (ret->defValue != NULL)
7609         ret->flags |= XML_SCHEMAS_ATTR_FIXED;
7610     /*
7611     * Attribute "default".
7612     */
7613     attr = xmlSchemaGetPropNode(node, "default");
7614     if (attr != NULL) {
7615         /*
7616         * 3.2.3 : 1
7617         * default and fixed must not both be present.
7618         */
7619         if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
7620             xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7621                 WXS_BASIC_CAST ret, attr, "default", "fixed");
7622         } else
7623             ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7624     }
7625     /*
7626     * And now for the children...
7627     */
7628     child = node->children;
7629     if (IS_SCHEMA(child, "annotation")) {
7630         ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7631         child = child->next;
7632     }
7633     if (IS_SCHEMA(child, "simpleType")) {
7634         if (ret->typeName != NULL) {
7635             /*
7636             * 3.2.3 : 4
7637             * type and <simpleType> must not both be present.
7638             */
7639             xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7640                 NULL, node, child,
7641                 "The attribute 'type' and the <simpleType> child "
7642                 "are mutually exclusive", NULL);
7643         } else
7644             ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7645         child = child->next;
7646     }
7647     if (child != NULL)
7648         xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7649             NULL, node, child, NULL,
7650             "(annotation?, simpleType?)");
7651
7652     return (ret);
7653 }
7654
7655 /**
7656  * xmlSchemaParseAttributeGroupRef:
7657  * @ctxt:  a schema validation context
7658  * @schema:  the schema being built
7659  * @node:  a subtree containing XML Schema informations
7660  *
7661  * Parse an attribute group definition reference.
7662  * Note that a reference to an attribute group does not
7663  * correspond to any component at all.
7664  * *WARNING* this interface is highly subject to change
7665  *
7666  * Returns the attribute group or NULL in case of error.
7667  */
7668 static xmlSchemaQNameRefPtr
7669 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7670                                 xmlSchemaPtr schema,
7671                                 xmlNodePtr node)
7672 {
7673     xmlSchemaQNameRefPtr ret;
7674     xmlNodePtr child = NULL;
7675     xmlAttrPtr attr;
7676     const xmlChar *refNs = NULL, *ref = NULL;
7677
7678     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7679         return (NULL);
7680
7681     attr = xmlSchemaGetPropNode(node, "ref");
7682     if (attr == NULL) {
7683         xmlSchemaPMissingAttrErr(pctxt,
7684             XML_SCHEMAP_S4S_ATTR_MISSING,
7685             NULL, node, "ref", NULL);
7686         return (NULL);
7687     }
7688     xmlSchemaPValAttrNodeQName(pctxt, schema,
7689         NULL, attr, &refNs, &ref);
7690     if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7691         return(NULL);
7692
7693     /*
7694     * Check for illegal attributes.
7695     */
7696     attr = node->properties;
7697     while (attr != NULL) {
7698         if (attr->ns == NULL) {
7699             if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
7700                 (!xmlStrEqual(attr->name, BAD_CAST "id")))
7701             {
7702                 xmlSchemaPIllegalAttrErr(pctxt,
7703                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7704             }
7705         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7706             xmlSchemaPIllegalAttrErr(pctxt,
7707                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7708         }
7709         attr = attr->next;
7710     }
7711     /* Attribute ID */
7712     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7713
7714     /*
7715     * And now for the children...
7716     */
7717     child = node->children;
7718     if (IS_SCHEMA(child, "annotation")) {
7719         /*
7720         * TODO: We do not have a place to store the annotation, do we?
7721         */
7722         xmlSchemaParseAnnotation(pctxt, child, 0);
7723         child = child->next;
7724     }
7725     if (child != NULL) {
7726         xmlSchemaPContentErr(pctxt,
7727             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7728             NULL, node, child, NULL,
7729             "(annotation?)");
7730     }
7731
7732     /*
7733     * Handle attribute group redefinitions.
7734     */
7735     if (pctxt->isRedefine && pctxt->redef &&
7736         (pctxt->redef->item->type ==
7737             XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7738         (ref == pctxt->redef->refName) &&
7739         (refNs == pctxt->redef->refTargetNs))
7740     {
7741         /*
7742         * SPEC src-redefine:
7743         * (7.1) "If it has an <attributeGroup> among its contents
7744         * the `actual value` of whose ref [attribute] is the same
7745         * as the `actual value` of its own name attribute plus
7746         * target namespace, then it must have exactly one such group."
7747         */
7748         if (pctxt->redefCounter != 0) {
7749             xmlChar *str = NULL;
7750
7751             xmlSchemaCustomErr(ACTXT_CAST pctxt,
7752                 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7753                 "The redefining attribute group definition "
7754                 "'%s' must not contain more than one "
7755                 "reference to the redefined definition",
7756                 xmlSchemaFormatQName(&str, refNs, ref), NULL);
7757             FREE_AND_NULL(str);
7758             return(NULL);
7759         }
7760         pctxt->redefCounter++;
7761         /*
7762         * URGENT TODO: How to ensure that the reference will not be
7763         * handled by the normal component resolution mechanism?
7764         */
7765         ret = xmlSchemaNewQNameRef(pctxt,
7766             XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7767         if (ret == NULL)
7768             return(NULL);
7769         ret->node = node;
7770         pctxt->redef->reference = WXS_BASIC_CAST ret;
7771     } else {
7772         /*
7773         * Create a QName-reference helper component. We will substitute this
7774         * component for the attribute uses of the referenced attribute group
7775         * definition.
7776         */
7777         ret = xmlSchemaNewQNameRef(pctxt,
7778             XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7779         if (ret == NULL)
7780             return(NULL);
7781         ret->node = node;
7782         /* Add to pending items, to be able to resolve the reference. */
7783         WXS_ADD_PENDING(pctxt, ret);
7784     }
7785     return (ret);
7786 }
7787
7788 /**
7789  * xmlSchemaParseAttributeGroupDefinition:
7790  * @pctxt:  a schema validation context
7791  * @schema:  the schema being built
7792  * @node:  a subtree containing XML Schema informations
7793  *
7794  * parse a XML schema Attribute Group declaration
7795  * *WARNING* this interface is highly subject to change
7796  *
7797  * Returns the attribute group definition or NULL in case of error.
7798  */
7799 static xmlSchemaAttributeGroupPtr
7800 xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7801                                        xmlSchemaPtr schema,
7802                                        xmlNodePtr node)
7803 {
7804     const xmlChar *name;
7805     xmlSchemaAttributeGroupPtr ret;
7806     xmlNodePtr child = NULL;
7807     xmlAttrPtr attr;
7808     int hasRefs = 0;
7809
7810     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7811         return (NULL);
7812
7813     attr = xmlSchemaGetPropNode(node, "name");
7814     if (attr == NULL) {
7815         xmlSchemaPMissingAttrErr(pctxt,
7816             XML_SCHEMAP_S4S_ATTR_MISSING,
7817             NULL, node, "name", NULL);
7818         return (NULL);
7819     }
7820     /*
7821     * The name is crucial, exit if invalid.
7822     */
7823     if (xmlSchemaPValAttrNode(pctxt,
7824         NULL, attr,
7825         xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7826         return (NULL);
7827     }
7828     ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7829         name, pctxt->targetNamespace, node);
7830     if (ret == NULL)
7831         return (NULL);
7832     /*
7833     * Check for illegal attributes.
7834     */
7835     attr = node->properties;
7836     while (attr != NULL) {
7837         if (attr->ns == NULL) {
7838             if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7839                 (!xmlStrEqual(attr->name, BAD_CAST "id")))
7840             {
7841                 xmlSchemaPIllegalAttrErr(pctxt,
7842                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7843             }
7844         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7845             xmlSchemaPIllegalAttrErr(pctxt,
7846                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7847         }
7848         attr = attr->next;
7849     }
7850     /* Attribute ID */
7851     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7852     /*
7853     * And now for the children...
7854     */
7855     child = node->children;
7856     if (IS_SCHEMA(child, "annotation")) {
7857         ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7858         child = child->next;
7859     }
7860     /*
7861     * Parse contained attribute decls/refs.
7862     */
7863     if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7864         (xmlSchemaItemListPtr *) &(ret->attrUses),
7865         XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7866         return(NULL);
7867     if (hasRefs)
7868         ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7869     /*
7870     * Parse the attribute wildcard.
7871     */
7872     if (IS_SCHEMA(child, "anyAttribute")) {
7873         ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7874             schema, child);
7875         child = child->next;
7876     }
7877     if (child != NULL) {
7878         xmlSchemaPContentErr(pctxt,
7879             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7880             NULL, node, child, NULL,
7881             "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
7882     }
7883     return (ret);
7884 }
7885
7886 /**
7887  * xmlSchemaPValAttrFormDefault:
7888  * @value:  the value
7889  * @flags: the flags to be modified
7890  * @flagQualified: the specific flag for "qualified"
7891  *
7892  * Returns 0 if the value is valid, 1 otherwise.
7893  */
7894 static int
7895 xmlSchemaPValAttrFormDefault(const xmlChar *value,
7896                              int *flags,
7897                              int flagQualified)
7898 {
7899     if (xmlStrEqual(value, BAD_CAST "qualified")) {
7900         if  ((*flags & flagQualified) == 0)
7901             *flags |= flagQualified;
7902     } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
7903         return (1);
7904
7905     return (0);
7906 }
7907
7908 /**
7909  * xmlSchemaPValAttrBlockFinal:
7910  * @value:  the value
7911  * @flags: the flags to be modified
7912  * @flagAll: the specific flag for "#all"
7913  * @flagExtension: the specific flag for "extension"
7914  * @flagRestriction: the specific flag for "restriction"
7915  * @flagSubstitution: the specific flag for "substitution"
7916  * @flagList: the specific flag for "list"
7917  * @flagUnion: the specific flag for "union"
7918  *
7919  * Validates the value of the attribute "final" and "block". The value
7920  * is converted into the specified flag values and returned in @flags.
7921  *
7922  * Returns 0 if the value is valid, 1 otherwise.
7923  */
7924
7925 static int
7926 xmlSchemaPValAttrBlockFinal(const xmlChar *value,
7927                             int *flags,
7928                             int flagAll,
7929                             int flagExtension,
7930                             int flagRestriction,
7931                             int flagSubstitution,
7932                             int flagList,
7933                             int flagUnion)
7934 {
7935     int ret = 0;
7936
7937     /*
7938     * TODO: This does not check for dublicate entries.
7939     */
7940     if ((flags == NULL) || (value == NULL))
7941         return (-1);
7942     if (value[0] == 0)
7943         return (0);
7944     if (xmlStrEqual(value, BAD_CAST "#all")) {
7945         if (flagAll != -1)
7946             *flags |= flagAll;
7947         else {
7948             if (flagExtension != -1)
7949                 *flags |= flagExtension;
7950             if (flagRestriction != -1)
7951                 *flags |= flagRestriction;
7952             if (flagSubstitution != -1)
7953                 *flags |= flagSubstitution;
7954             if (flagList != -1)
7955                 *flags |= flagList;
7956             if (flagUnion != -1)
7957                 *flags |= flagUnion;
7958         }
7959     } else {
7960         const xmlChar *end, *cur = value;
7961         xmlChar *item;
7962
7963         do {
7964             while (IS_BLANK_CH(*cur))
7965                 cur++;
7966             end = cur;
7967             while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7968                 end++;
7969             if (end == cur)
7970                 break;
7971             item = xmlStrndup(cur, end - cur);
7972             if (xmlStrEqual(item, BAD_CAST "extension")) {
7973                 if (flagExtension != -1) {
7974                     if ((*flags & flagExtension) == 0)
7975                         *flags |= flagExtension;
7976                 } else
7977                     ret = 1;
7978             } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
7979                 if (flagRestriction != -1) {
7980                     if ((*flags & flagRestriction) == 0)
7981                         *flags |= flagRestriction;
7982                 } else
7983                     ret = 1;
7984             } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
7985                 if (flagSubstitution != -1) {
7986                     if ((*flags & flagSubstitution) == 0)
7987                         *flags |= flagSubstitution;
7988                 } else
7989                     ret = 1;
7990             } else if (xmlStrEqual(item, BAD_CAST "list")) {
7991                 if (flagList != -1) {
7992                     if ((*flags & flagList) == 0)
7993                         *flags |= flagList;
7994                 } else
7995                     ret = 1;
7996             } else if (xmlStrEqual(item, BAD_CAST "union")) {
7997                 if (flagUnion != -1) {
7998                     if ((*flags & flagUnion) == 0)
7999                         *flags |= flagUnion;
8000                 } else
8001                     ret = 1;
8002             } else
8003                 ret = 1;
8004             if (item != NULL)
8005                 xmlFree(item);
8006             cur = end;
8007         } while ((ret == 0) && (*cur != 0));
8008     }
8009
8010     return (ret);
8011 }
8012
8013 static int
8014 xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
8015                              xmlSchemaIDCPtr idc,
8016                              xmlSchemaIDCSelectPtr selector,
8017                              xmlAttrPtr attr,
8018                              int isField)
8019 {
8020     xmlNodePtr node;
8021
8022     /*
8023     * c-selector-xpath:
8024     * Schema Component Constraint: Selector Value OK
8025     *
8026     * TODO: 1 The {selector} must be a valid XPath expression, as defined
8027     * in [XPath].
8028     */
8029     if (selector == NULL) {
8030         xmlSchemaPErr(ctxt, idc->node,
8031             XML_SCHEMAP_INTERNAL,
8032             "Internal error: xmlSchemaCheckCSelectorXPath, "
8033             "the selector is not specified.\n", NULL, NULL);
8034         return (-1);
8035     }
8036     if (attr == NULL)
8037         node = idc->node;
8038     else
8039         node = (xmlNodePtr) attr;
8040     if (selector->xpath == NULL) {
8041         xmlSchemaPCustomErr(ctxt,
8042             /* TODO: Adjust error code. */
8043             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8044             NULL, node,
8045             "The XPath expression of the selector is not valid", NULL);
8046         return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8047     } else {
8048         const xmlChar **nsArray = NULL;
8049         xmlNsPtr *nsList = NULL;
8050         /*
8051         * Compile the XPath expression.
8052         */
8053         /*
8054         * TODO: We need the array of in-scope namespaces for compilation.
8055         * TODO: Call xmlPatterncompile with different options for selector/
8056         * field.
8057         */
8058         if (attr == NULL)
8059             nsList = NULL;
8060         else
8061             nsList = xmlGetNsList(attr->doc, attr->parent);
8062         /*
8063         * Build an array of prefixes and namespaces.
8064         */
8065         if (nsList != NULL) {
8066             int i, count = 0;
8067
8068             for (i = 0; nsList[i] != NULL; i++)
8069                 count++;
8070
8071             nsArray = (const xmlChar **) xmlMalloc(
8072                 (count * 2 + 1) * sizeof(const xmlChar *));
8073             if (nsArray == NULL) {
8074                 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
8075                     NULL);
8076                 xmlFree(nsList);
8077                 return (-1);
8078             }
8079             for (i = 0; i < count; i++) {
8080                 nsArray[2 * i] = nsList[i]->href;
8081                 nsArray[2 * i + 1] = nsList[i]->prefix;
8082             }
8083             nsArray[count * 2] = NULL;
8084             xmlFree(nsList);
8085         }
8086         /*
8087         * TODO: Differentiate between "selector" and "field".
8088         */
8089         if (isField)
8090             selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8091                 NULL, XML_PATTERN_XSFIELD, nsArray);
8092         else
8093             selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8094                 NULL, XML_PATTERN_XSSEL, nsArray);
8095         if (nsArray != NULL)
8096             xmlFree((xmlChar **) nsArray);
8097
8098         if (selector->xpathComp == NULL) {
8099             xmlSchemaPCustomErr(ctxt,
8100                 /* TODO: Adjust error code? */
8101                 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8102                 NULL, node,
8103                 "The XPath expression '%s' could not be "
8104                 "compiled", selector->xpath);
8105             return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8106         }
8107     }
8108     return (0);
8109 }
8110
8111 #define ADD_ANNOTATION(annot)   \
8112     xmlSchemaAnnotPtr cur = item->annot; \
8113     if (item->annot == NULL) {  \
8114         item->annot = annot;    \
8115         return (annot);         \
8116     }                           \
8117     cur = item->annot;          \
8118     if (cur->next != NULL) {    \
8119         cur = cur->next;        \
8120     }                           \
8121     cur->next = annot;
8122
8123 /**
8124  * xmlSchemaAssignAnnotation:
8125  * @item: the schema component
8126  * @annot: the annotation
8127  *
8128  * Adds the annotation to the given schema component.
8129  *
8130  * Returns the given annotaion.
8131  */
8132 static xmlSchemaAnnotPtr
8133 xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8134                        xmlSchemaAnnotPtr annot)
8135 {
8136     if ((annItem == NULL) || (annot == NULL))
8137         return (NULL);
8138     switch (annItem->type) {
8139         case XML_SCHEMA_TYPE_ELEMENT: {
8140                 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8141                 ADD_ANNOTATION(annot)
8142             }
8143             break;
8144         case XML_SCHEMA_TYPE_ATTRIBUTE: {
8145                 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8146                 ADD_ANNOTATION(annot)
8147             }
8148             break;
8149         case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8150         case XML_SCHEMA_TYPE_ANY: {
8151                 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8152                 ADD_ANNOTATION(annot)
8153             }
8154             break;
8155         case XML_SCHEMA_TYPE_PARTICLE:
8156         case XML_SCHEMA_TYPE_IDC_KEY:
8157         case XML_SCHEMA_TYPE_IDC_KEYREF:
8158         case XML_SCHEMA_TYPE_IDC_UNIQUE: {
8159                 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8160                 ADD_ANNOTATION(annot)
8161             }
8162             break;
8163         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8164                 xmlSchemaAttributeGroupPtr item =
8165                     (xmlSchemaAttributeGroupPtr) annItem;
8166                 ADD_ANNOTATION(annot)
8167             }
8168             break;
8169         case XML_SCHEMA_TYPE_NOTATION: {
8170                 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8171                 ADD_ANNOTATION(annot)
8172             }
8173             break;
8174         case XML_SCHEMA_FACET_MININCLUSIVE:
8175         case XML_SCHEMA_FACET_MINEXCLUSIVE:
8176         case XML_SCHEMA_FACET_MAXINCLUSIVE:
8177         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8178         case XML_SCHEMA_FACET_TOTALDIGITS:
8179         case XML_SCHEMA_FACET_FRACTIONDIGITS:
8180         case XML_SCHEMA_FACET_PATTERN:
8181         case XML_SCHEMA_FACET_ENUMERATION:
8182         case XML_SCHEMA_FACET_WHITESPACE:
8183         case XML_SCHEMA_FACET_LENGTH:
8184         case XML_SCHEMA_FACET_MAXLENGTH:
8185         case XML_SCHEMA_FACET_MINLENGTH: {
8186                 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8187                 ADD_ANNOTATION(annot)
8188             }
8189             break;
8190         case XML_SCHEMA_TYPE_SIMPLE:
8191         case XML_SCHEMA_TYPE_COMPLEX: {
8192                 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8193                 ADD_ANNOTATION(annot)
8194             }
8195             break;
8196         case XML_SCHEMA_TYPE_GROUP: {
8197                 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8198                 ADD_ANNOTATION(annot)
8199             }
8200             break;
8201         case XML_SCHEMA_TYPE_SEQUENCE:
8202         case XML_SCHEMA_TYPE_CHOICE:
8203         case XML_SCHEMA_TYPE_ALL: {
8204                 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8205                 ADD_ANNOTATION(annot)
8206             }
8207             break;
8208         default:
8209              xmlSchemaPCustomErr(NULL,
8210                 XML_SCHEMAP_INTERNAL,
8211                 NULL, NULL,
8212                 "Internal error: xmlSchemaAddAnnotation, "
8213                 "The item is not a annotated schema component", NULL);
8214              break;
8215     }
8216     return (annot);
8217 }
8218
8219 /**
8220  * xmlSchemaParseIDCSelectorAndField:
8221  * @ctxt:  a schema validation context
8222  * @schema:  the schema being built
8223  * @node:  a subtree containing XML Schema informations
8224  *
8225  * Parses a XML Schema identity-contraint definition's
8226  * <selector> and <field> elements.
8227  *
8228  * Returns the parsed identity-constraint definition.
8229  */
8230 static xmlSchemaIDCSelectPtr
8231 xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
8232                           xmlSchemaIDCPtr idc,
8233                           xmlNodePtr node,
8234                           int isField)
8235 {
8236     xmlSchemaIDCSelectPtr item;
8237     xmlNodePtr child = NULL;
8238     xmlAttrPtr attr;
8239
8240     /*
8241     * Check for illegal attributes.
8242     */
8243     attr = node->properties;
8244     while (attr != NULL) {
8245         if (attr->ns == NULL) {
8246             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8247                 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
8248                 xmlSchemaPIllegalAttrErr(ctxt,
8249                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8250             }
8251         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8252             xmlSchemaPIllegalAttrErr(ctxt,
8253                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8254         }
8255         attr = attr->next;
8256     }
8257     /*
8258     * Create the item.
8259     */
8260     item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8261     if (item == NULL) {
8262         xmlSchemaPErrMemory(ctxt,
8263             "allocating a 'selector' of an identity-constraint definition",
8264             NULL);
8265         return (NULL);
8266     }
8267     memset(item, 0, sizeof(xmlSchemaIDCSelect));
8268     /*
8269     * Attribute "xpath" (mandatory).
8270     */
8271     attr = xmlSchemaGetPropNode(node, "xpath");
8272     if (attr == NULL) {
8273         xmlSchemaPMissingAttrErr(ctxt,
8274             XML_SCHEMAP_S4S_ATTR_MISSING,
8275             NULL, node,
8276             "name", NULL);
8277     } else {
8278         item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8279         /*
8280         * URGENT TODO: "field"s have an other syntax than "selector"s.
8281         */
8282
8283         if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8284             isField) == -1) {
8285             xmlSchemaPErr(ctxt,
8286                 (xmlNodePtr) attr,
8287                 XML_SCHEMAP_INTERNAL,
8288                 "Internal error: xmlSchemaParseIDCSelectorAndField, "
8289                 "validating the XPath expression of a IDC selector.\n",
8290                 NULL, NULL);
8291         }
8292
8293     }
8294     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8295     /*
8296     * And now for the children...
8297     */
8298     child = node->children;
8299     if (IS_SCHEMA(child, "annotation")) {
8300         /*
8301         * Add the annotation to the parent IDC.
8302         */
8303         xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
8304             xmlSchemaParseAnnotation(ctxt, child, 1));
8305         child = child->next;
8306     }
8307     if (child != NULL) {
8308         xmlSchemaPContentErr(ctxt,
8309             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8310             NULL, node, child,
8311             NULL, "(annotation?)");
8312     }
8313
8314     return (item);
8315 }
8316
8317 /**
8318  * xmlSchemaParseIDC:
8319  * @ctxt:  a schema validation context
8320  * @schema:  the schema being built
8321  * @node:  a subtree containing XML Schema informations
8322  *
8323  * Parses a XML Schema identity-contraint definition.
8324  *
8325  * Returns the parsed identity-constraint definition.
8326  */
8327 static xmlSchemaIDCPtr
8328 xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
8329                   xmlSchemaPtr schema,
8330                   xmlNodePtr node,
8331                   xmlSchemaTypeType idcCategory,
8332                   const xmlChar *targetNamespace)
8333 {
8334     xmlSchemaIDCPtr item = NULL;
8335     xmlNodePtr child = NULL;
8336     xmlAttrPtr attr;
8337     const xmlChar *name = NULL;
8338     xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
8339
8340     /*
8341     * Check for illegal attributes.
8342     */
8343     attr = node->properties;
8344     while (attr != NULL) {
8345         if (attr->ns == NULL) {
8346             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8347                 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8348                 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8349                  (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
8350                 xmlSchemaPIllegalAttrErr(ctxt,
8351                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8352             }
8353         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8354             xmlSchemaPIllegalAttrErr(ctxt,
8355                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8356         }
8357         attr = attr->next;
8358     }
8359     /*
8360     * Attribute "name" (mandatory).
8361     */
8362     attr = xmlSchemaGetPropNode(node, "name");
8363     if (attr == NULL) {
8364         xmlSchemaPMissingAttrErr(ctxt,
8365             XML_SCHEMAP_S4S_ATTR_MISSING,
8366             NULL, node,
8367             "name", NULL);
8368         return (NULL);
8369     } else if (xmlSchemaPValAttrNode(ctxt,
8370         NULL, attr,
8371         xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8372         return (NULL);
8373     }
8374     /* Create the component. */
8375     item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8376         idcCategory, node);
8377     if (item == NULL)
8378         return(NULL);
8379
8380     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8381     if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8382         /*
8383         * Attribute "refer" (mandatory).
8384         */
8385         attr = xmlSchemaGetPropNode(node, "refer");
8386         if (attr == NULL) {
8387             xmlSchemaPMissingAttrErr(ctxt,
8388                 XML_SCHEMAP_S4S_ATTR_MISSING,
8389                 NULL, node,
8390                 "refer", NULL);
8391         } else {
8392             /*
8393             * Create a reference item.
8394             */
8395             item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
8396                 NULL, NULL);
8397             if (item->ref == NULL)
8398                 return (NULL);
8399             xmlSchemaPValAttrNodeQName(ctxt, schema,
8400                 NULL, attr,
8401                 &(item->ref->targetNamespace),
8402                 &(item->ref->name));
8403             xmlSchemaCheckReference(ctxt, schema, node, attr,
8404                 item->ref->targetNamespace);
8405         }
8406     }
8407     /*
8408     * And now for the children...
8409     */
8410     child = node->children;
8411     if (IS_SCHEMA(child, "annotation")) {
8412         item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8413         child = child->next;
8414     }
8415     if (child == NULL) {
8416         xmlSchemaPContentErr(ctxt,
8417                 XML_SCHEMAP_S4S_ELEM_MISSING,
8418                 NULL, node, child,
8419                 "A child element is missing",
8420                 "(annotation?, (selector, field+))");
8421     }
8422     /*
8423     * Child element <selector>.
8424     */
8425     if (IS_SCHEMA(child, "selector")) {
8426         item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
8427             item, child, 0);
8428         child = child->next;
8429         /*
8430         * Child elements <field>.
8431         */
8432         if (IS_SCHEMA(child, "field")) {
8433             do {
8434                 field = xmlSchemaParseIDCSelectorAndField(ctxt,
8435                     item, child, 1);
8436                 if (field != NULL) {
8437                     field->index = item->nbFields;
8438                     item->nbFields++;
8439                     if (lastField != NULL)
8440                         lastField->next = field;
8441                     else
8442                         item->fields = field;
8443                     lastField = field;
8444                 }
8445                 child = child->next;
8446             } while (IS_SCHEMA(child, "field"));
8447         } else {
8448             xmlSchemaPContentErr(ctxt,
8449                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8450                 NULL, node, child,
8451                 NULL, "(annotation?, (selector, field+))");
8452         }
8453     }
8454     if (child != NULL) {
8455         xmlSchemaPContentErr(ctxt,
8456             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8457             NULL, node, child,
8458             NULL, "(annotation?, (selector, field+))");
8459     }
8460
8461     return (item);
8462 }
8463
8464 /**
8465  * xmlSchemaParseElement:
8466  * @ctxt:  a schema validation context
8467  * @schema:  the schema being built
8468  * @node:  a subtree containing XML Schema informations
8469  * @topLevel: indicates if this is global declaration
8470  *
8471  * Parses a XML schema element declaration.
8472  * *WARNING* this interface is highly subject to change
8473  *
8474  * Returns the element declaration or a particle; NULL in case
8475  * of an error or if the particle has minOccurs==maxOccurs==0.
8476  */
8477 static xmlSchemaBasicItemPtr
8478 xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8479                       xmlNodePtr node, int *isElemRef, int topLevel)
8480 {
8481     xmlSchemaElementPtr decl = NULL;
8482     xmlSchemaParticlePtr particle = NULL;
8483     xmlSchemaAnnotPtr annot = NULL;
8484     xmlNodePtr child = NULL;
8485     xmlAttrPtr attr, nameAttr;
8486     int min, max, isRef = 0;
8487     xmlChar *des = NULL;
8488
8489     /* 3.3.3 Constraints on XML Representations of Element Declarations */
8490     /* TODO: Complete implementation of 3.3.6 */
8491
8492     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8493         return (NULL);
8494
8495     if (isElemRef != NULL)
8496         *isElemRef = 0;
8497     /*
8498     * If we get a "ref" attribute on a local <element> we will assume it's
8499     * a reference - even if there's a "name" attribute; this seems to be more
8500     * robust.
8501     */
8502     nameAttr = xmlSchemaGetPropNode(node, "name");
8503     attr = xmlSchemaGetPropNode(node, "ref");
8504     if ((topLevel) || (attr == NULL)) {
8505         if (nameAttr == NULL) {
8506             xmlSchemaPMissingAttrErr(ctxt,
8507                 XML_SCHEMAP_S4S_ATTR_MISSING,
8508                 NULL, node, "name", NULL);
8509             return (NULL);
8510         }
8511     } else
8512         isRef = 1;
8513
8514     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8515     child = node->children;
8516     if (IS_SCHEMA(child, "annotation")) {
8517         annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8518         child = child->next;
8519     }
8520     /*
8521     * Skip particle part if a global declaration.
8522     */
8523     if (topLevel)
8524         goto declaration_part;
8525     /*
8526     * The particle part ==================================================
8527     */
8528     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8529     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8530     xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
8531     particle = xmlSchemaAddParticle(ctxt, node, min, max);
8532     if (particle == NULL)
8533         goto return_null;
8534
8535     /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8536
8537     if (isRef) {
8538         const xmlChar *refNs = NULL, *ref = NULL;
8539         xmlSchemaQNameRefPtr refer = NULL;
8540         /*
8541         * The reference part =============================================
8542         */
8543         if (isElemRef != NULL)
8544             *isElemRef = 1;
8545
8546         xmlSchemaPValAttrNodeQName(ctxt, schema,
8547             NULL, attr, &refNs, &ref);
8548         xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
8549         /*
8550         * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
8551         */
8552         if (nameAttr != NULL) {
8553             xmlSchemaPMutualExclAttrErr(ctxt,
8554                 XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
8555         }
8556         /*
8557         * Check for illegal attributes.
8558         */
8559         attr = node->properties;
8560         while (attr != NULL) {
8561             if (attr->ns == NULL) {
8562                 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8563                     xmlStrEqual(attr->name, BAD_CAST "name") ||
8564                     xmlStrEqual(attr->name, BAD_CAST "id") ||
8565                     xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8566                     xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8567                 {
8568                     attr = attr->next;
8569                     continue;
8570                 } else {
8571                     /* SPEC (3.3.3 : 2.2) */
8572                     xmlSchemaPCustomAttrErr(ctxt,
8573                         XML_SCHEMAP_SRC_ELEMENT_2_2,
8574                         NULL, NULL, attr,
8575                         "Only the attributes 'minOccurs', 'maxOccurs' and "
8576                         "'id' are allowed in addition to 'ref'");
8577                     break;
8578                 }
8579             } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8580                 xmlSchemaPIllegalAttrErr(ctxt,
8581                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8582             }
8583             attr = attr->next;
8584         }
8585         /*
8586         * No children except <annotation> expected.
8587         */
8588         if (child != NULL) {
8589             xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8590                 NULL, node, child, NULL, "(annotation?)");
8591         }
8592         if ((min == 0) && (max == 0))
8593             goto return_null;
8594         /*
8595         * Create the reference item and attach it to the particle.
8596         */
8597         refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
8598             ref, refNs);
8599         if (refer == NULL)
8600             goto return_null;
8601         particle->children = (xmlSchemaTreeItemPtr) refer;
8602         particle->annot = annot;
8603         /*
8604         * Add the particle to pending components, since the reference
8605         * need to be resolved.
8606         */
8607         WXS_ADD_PENDING(ctxt, particle);
8608         return ((xmlSchemaBasicItemPtr) particle);
8609     }
8610     /*
8611     * The declaration part ===============================================
8612     */
8613 declaration_part:
8614     {
8615         const xmlChar *ns = NULL, *fixed, *name, *attrValue;
8616         xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8617
8618         if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
8619             xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
8620             goto return_null;
8621         /*
8622         * Evaluate the target namespace.
8623         */
8624         if (topLevel) {
8625             ns = ctxt->targetNamespace;
8626         } else {
8627             attr = xmlSchemaGetPropNode(node, "form");
8628             if (attr != NULL) {
8629                 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8630                 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
8631                     ns = ctxt->targetNamespace;
8632                 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
8633                     xmlSchemaPSimpleTypeErr(ctxt,
8634                         XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8635                         NULL, (xmlNodePtr) attr,
8636                         NULL, "(qualified | unqualified)",
8637                         attrValue, NULL, NULL, NULL);
8638                 }
8639             } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8640                 ns = ctxt->targetNamespace;
8641         }
8642         decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
8643         if (decl == NULL) {
8644             goto return_null;
8645         }
8646         /*
8647         * Check for illegal attributes.
8648         */
8649         attr = node->properties;
8650         while (attr != NULL) {
8651             if (attr->ns == NULL) {
8652                 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8653                     (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
8654                     (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8655                     (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
8656                     (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
8657                     (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
8658                     (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8659                 {
8660                     if (topLevel == 0) {
8661                         if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8662                             (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8663                             (!xmlStrEqual(attr->name, BAD_CAST "form")))
8664                         {
8665                             xmlSchemaPIllegalAttrErr(ctxt,
8666                                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8667                         }
8668                     } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8669                         (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
8670                         (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8671
8672                         xmlSchemaPIllegalAttrErr(ctxt,
8673                             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8674                     }
8675                 }
8676             } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8677
8678                 xmlSchemaPIllegalAttrErr(ctxt,
8679                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8680             }
8681             attr = attr->next;
8682         }
8683         /*
8684         * Extract/validate attributes.
8685         */
8686         if (topLevel) {
8687             /*
8688             * Process top attributes of global element declarations here.
8689             */
8690             decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8691             decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
8692             xmlSchemaPValAttrQName(ctxt, schema,
8693                 NULL, node, "substitutionGroup",
8694                 &(decl->substGroupNs), &(decl->substGroup));
8695             if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
8696                 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
8697             /*
8698             * Attribute "final".
8699             */
8700             attr = xmlSchemaGetPropNode(node, "final");
8701             if (attr == NULL) {
8702                 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8703                     decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8704                 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8705                     decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
8706             } else {
8707                 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8708                 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8709                     -1,
8710                     XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8711                     XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
8712                     xmlSchemaPSimpleTypeErr(ctxt,
8713                         XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8714                         NULL, (xmlNodePtr) attr,
8715                         NULL, "(#all | List of (extension | restriction))",
8716                         attrValue, NULL, NULL, NULL);
8717                 }
8718             }
8719         }
8720         /*
8721         * Attribute "block".
8722         */
8723         attr = xmlSchemaGetPropNode(node, "block");
8724         if (attr == NULL) {
8725             /*
8726             * Apply default "block" values.
8727             */
8728             if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8729                 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8730             if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8731                 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8732             if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8733                 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
8734         } else {
8735             attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8736             if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8737                 -1,
8738                 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
8739                 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
8740                 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8741                 xmlSchemaPSimpleTypeErr(ctxt,
8742                     XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8743                     NULL, (xmlNodePtr) attr,
8744                     NULL, "(#all | List of (extension | "
8745                     "restriction | substitution))", attrValue,
8746                     NULL, NULL, NULL);
8747             }
8748         }
8749         if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
8750             decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
8751
8752         attr = xmlSchemaGetPropNode(node, "type");
8753         if (attr != NULL) {
8754             xmlSchemaPValAttrNodeQName(ctxt, schema,
8755                 NULL, attr,
8756                 &(decl->namedTypeNs), &(decl->namedType));
8757             xmlSchemaCheckReference(ctxt, schema, node,
8758                 attr, decl->namedTypeNs);
8759         }
8760         decl->value = xmlSchemaGetProp(ctxt, node, "default");
8761         attr = xmlSchemaGetPropNode(node, "fixed");
8762         if (attr != NULL) {
8763             fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8764             if (decl->value != NULL) {
8765                 /*
8766                 * 3.3.3 : 1
8767                 * default and fixed must not both be present.
8768                 */
8769                 xmlSchemaPMutualExclAttrErr(ctxt,
8770                     XML_SCHEMAP_SRC_ELEMENT_1,
8771                     NULL, attr, "default", "fixed");
8772             } else {
8773                 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8774                 decl->value = fixed;
8775             }
8776         }
8777         /*
8778         * And now for the children...
8779         */
8780         if (IS_SCHEMA(child, "complexType")) {
8781             /*
8782             * 3.3.3 : 3
8783             * "type" and either <simpleType> or <complexType> are mutually
8784             * exclusive
8785             */
8786             if (decl->namedType != NULL) {
8787                 xmlSchemaPContentErr(ctxt,
8788                     XML_SCHEMAP_SRC_ELEMENT_3,
8789                     NULL, node, child,
8790                     "The attribute 'type' and the <complexType> child are "
8791                     "mutually exclusive", NULL);
8792             } else
8793                 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
8794             child = child->next;
8795         } else if (IS_SCHEMA(child, "simpleType")) {
8796             /*
8797             * 3.3.3 : 3
8798             * "type" and either <simpleType> or <complexType> are
8799             * mutually exclusive
8800             */
8801             if (decl->namedType != NULL) {
8802                 xmlSchemaPContentErr(ctxt,
8803                     XML_SCHEMAP_SRC_ELEMENT_3,
8804                     NULL, node, child,
8805                     "The attribute 'type' and the <simpleType> child are "
8806                     "mutually exclusive", NULL);
8807             } else
8808                 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8809             child = child->next;
8810         }
8811         while ((IS_SCHEMA(child, "unique")) ||
8812             (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
8813             if (IS_SCHEMA(child, "unique")) {
8814                 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8815                     XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
8816             } else if (IS_SCHEMA(child, "key")) {
8817                 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8818                     XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
8819             } else if (IS_SCHEMA(child, "keyref")) {
8820                 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8821                     XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
8822             }
8823             if (lastIDC != NULL)
8824                 lastIDC->next = curIDC;
8825             else
8826                 decl->idcs = (void *) curIDC;
8827             lastIDC = curIDC;
8828             child = child->next;
8829         }
8830         if (child != NULL) {
8831             xmlSchemaPContentErr(ctxt,
8832                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8833                 NULL, node, child,
8834                 NULL, "(annotation?, ((simpleType | complexType)?, "
8835                 "(unique | key | keyref)*))");
8836         }
8837         decl->annot = annot;
8838     }
8839     /*
8840     * NOTE: Element Declaration Representation OK 4. will be checked at a
8841     * different layer.
8842     */
8843     FREE_AND_NULL(des)
8844     if (topLevel)
8845         return ((xmlSchemaBasicItemPtr) decl);
8846     else {
8847         particle->children = (xmlSchemaTreeItemPtr) decl;
8848         return ((xmlSchemaBasicItemPtr) particle);
8849     }
8850
8851 return_null:
8852     FREE_AND_NULL(des);
8853     if (annot != NULL) {
8854         if (particle != NULL)
8855             particle->annot = NULL;
8856         if (decl != NULL)
8857             decl->annot = NULL;
8858         xmlSchemaFreeAnnot(annot);
8859     }
8860     return (NULL);
8861 }
8862
8863 /**
8864  * xmlSchemaParseUnion:
8865  * @ctxt:  a schema validation context
8866  * @schema:  the schema being built
8867  * @node:  a subtree containing XML Schema informations
8868  *
8869  * parse a XML schema Union definition
8870  * *WARNING* this interface is highly subject to change
8871  *
8872  * Returns -1 in case of internal error, 0 in case of success and a positive
8873  * error code otherwise.
8874  */
8875 static int
8876 xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8877                     xmlNodePtr node)
8878 {
8879     xmlSchemaTypePtr type;
8880     xmlNodePtr child = NULL;
8881     xmlAttrPtr attr;
8882     const xmlChar *cur = NULL;
8883
8884     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8885         return (-1);
8886     /* Not a component, don't create it. */
8887     type = ctxt->ctxtType;
8888     /*
8889     * Mark the simple type as being of variety "union".
8890     */
8891     type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
8892     /*
8893     * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8894     * then the `simple ur-type definition`."
8895     */
8896     type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8897     /*
8898     * Check for illegal attributes.
8899     */
8900     attr = node->properties;
8901     while (attr != NULL) {
8902         if (attr->ns == NULL) {
8903             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8904                 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
8905                 xmlSchemaPIllegalAttrErr(ctxt,
8906                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8907             }
8908         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8909             xmlSchemaPIllegalAttrErr(ctxt,
8910                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8911         }
8912         attr = attr->next;
8913     }
8914     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8915     /*
8916     * Attribute "memberTypes". This is a list of QNames.
8917     * TODO: Check the value to contain anything.
8918     */
8919     attr = xmlSchemaGetPropNode(node, "memberTypes");
8920     if (attr != NULL) {
8921         const xmlChar *end;
8922         xmlChar *tmp;
8923         const xmlChar *localName, *nsName;
8924         xmlSchemaTypeLinkPtr link, lastLink = NULL;
8925         xmlSchemaQNameRefPtr ref;
8926
8927         cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8928         type->base = cur;
8929         do {
8930             while (IS_BLANK_CH(*cur))
8931                 cur++;
8932             end = cur;
8933             while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8934                 end++;
8935             if (end == cur)
8936                 break;
8937             tmp = xmlStrndup(cur, end - cur);
8938             if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
8939                 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
8940                 /*
8941                 * Create the member type link.
8942                 */
8943                 link = (xmlSchemaTypeLinkPtr)
8944                     xmlMalloc(sizeof(xmlSchemaTypeLink));
8945                 if (link == NULL) {
8946                     xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8947                         "allocating a type link", NULL);
8948                     return (-1);
8949                 }
8950                 link->type = NULL;
8951                 link->next = NULL;
8952                 if (lastLink == NULL)
8953                     type->memberTypes = link;
8954                 else
8955                     lastLink->next = link;
8956                 lastLink = link;
8957                 /*
8958                 * Create a reference item.
8959                 */
8960                 ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
8961                     localName, nsName);
8962                 if (ref == NULL) {
8963                     FREE_AND_NULL(tmp)
8964                     return (-1);
8965                 }
8966                 /*
8967                 * Assign the reference to the link, it will be resolved
8968                 * later during fixup of the union simple type.
8969                 */
8970                 link->type = (xmlSchemaTypePtr) ref;
8971             }
8972             FREE_AND_NULL(tmp)
8973             cur = end;
8974         } while (*cur != 0);
8975
8976     }
8977     /*
8978     * And now for the children...
8979     */
8980     child = node->children;
8981     if (IS_SCHEMA(child, "annotation")) {
8982         /*
8983         * Add the annotation to the simple type ancestor.
8984         */
8985         xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8986             xmlSchemaParseAnnotation(ctxt, child, 1));
8987         child = child->next;
8988     }
8989     if (IS_SCHEMA(child, "simpleType")) {
8990         xmlSchemaTypePtr subtype, last = NULL;
8991
8992         /*
8993         * Anchor the member types in the "subtypes" field of the
8994         * simple type.
8995         */
8996         while (IS_SCHEMA(child, "simpleType")) {
8997             subtype = (xmlSchemaTypePtr)
8998                 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8999             if (subtype != NULL) {
9000                 if (last == NULL) {
9001                     type->subtypes = subtype;
9002                     last = subtype;
9003                 } else {
9004                     last->next = subtype;
9005                     last = subtype;
9006                 }
9007                 last->next = NULL;
9008             }
9009             child = child->next;
9010         }
9011     }
9012     if (child != NULL) {
9013         xmlSchemaPContentErr(ctxt,
9014             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9015             NULL, node, child, NULL, "(annotation?, simpleType*)");
9016     }
9017     if ((attr == NULL) && (type->subtypes == NULL)) {
9018          /*
9019         * src-union-memberTypes-or-simpleTypes
9020         * Either the memberTypes [attribute] of the <union> element must
9021         * be non-empty or there must be at least one simpleType [child].
9022         */
9023         xmlSchemaPCustomErr(ctxt,
9024             XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
9025             NULL, node,
9026             "Either the attribute 'memberTypes' or "
9027             "at least one <simpleType> child must be present", NULL);
9028     }
9029     return (0);
9030 }
9031
9032 /**
9033  * xmlSchemaParseList:
9034  * @ctxt:  a schema validation context
9035  * @schema:  the schema being built
9036  * @node:  a subtree containing XML Schema informations
9037  *
9038  * parse a XML schema List definition
9039  * *WARNING* this interface is highly subject to change
9040  *
9041  * Returns -1 in case of error, 0 if the declaration is improper and
9042  *         1 in case of success.
9043  */
9044 static xmlSchemaTypePtr
9045 xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9046                    xmlNodePtr node)
9047 {
9048     xmlSchemaTypePtr type;
9049     xmlNodePtr child = NULL;
9050     xmlAttrPtr attr;
9051
9052     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9053         return (NULL);
9054     /* Not a component, don't create it. */
9055     type = ctxt->ctxtType;
9056     /*
9057     * Mark the type as being of variety "list".
9058     */
9059     type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
9060     /*
9061     * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
9062     * then the `simple ur-type definition`."
9063     */
9064     type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
9065     /*
9066     * Check for illegal attributes.
9067     */
9068     attr = node->properties;
9069     while (attr != NULL) {
9070         if (attr->ns == NULL) {
9071             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9072                 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
9073                 xmlSchemaPIllegalAttrErr(ctxt,
9074                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9075             }
9076         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9077             xmlSchemaPIllegalAttrErr(ctxt,
9078                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9079         }
9080         attr = attr->next;
9081     }
9082
9083     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9084
9085     /*
9086     * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9087     * fields for holding the reference to the itemType.
9088     *
9089     * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9090     * the "ref" fields.
9091     */
9092     xmlSchemaPValAttrQName(ctxt, schema, NULL,
9093         node, "itemType", &(type->baseNs), &(type->base));
9094     /*
9095     * And now for the children...
9096     */
9097     child = node->children;
9098     if (IS_SCHEMA(child, "annotation")) {
9099         xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9100             xmlSchemaParseAnnotation(ctxt, child, 1));
9101         child = child->next;
9102     }
9103     if (IS_SCHEMA(child, "simpleType")) {
9104         /*
9105         * src-list-itemType-or-simpleType
9106         * Either the itemType [attribute] or the <simpleType> [child] of
9107         * the <list> element must be present, but not both.
9108         */
9109         if (type->base != NULL) {
9110             xmlSchemaPCustomErr(ctxt,
9111                 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9112                 NULL, node,
9113                 "The attribute 'itemType' and the <simpleType> child "
9114                 "are mutually exclusive", NULL);
9115         } else {
9116             type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9117         }
9118         child = child->next;
9119     } else if (type->base == NULL) {
9120         xmlSchemaPCustomErr(ctxt,
9121             XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9122             NULL, node,
9123             "Either the attribute 'itemType' or the <simpleType> child "
9124             "must be present", NULL);
9125     }
9126     if (child != NULL) {
9127         xmlSchemaPContentErr(ctxt,
9128             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9129             NULL, node, child, NULL, "(annotation?, simpleType?)");
9130     }
9131     if ((type->base == NULL) &&
9132         (type->subtypes == NULL) &&
9133         (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
9134         xmlSchemaPCustomErr(ctxt,
9135             XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9136             NULL, node,
9137             "Either the attribute 'itemType' or the <simpleType> child "
9138             "must be present", NULL);
9139     }
9140     return (NULL);
9141 }
9142
9143 /**
9144  * xmlSchemaParseSimpleType:
9145  * @ctxt:  a schema validation context
9146  * @schema:  the schema being built
9147  * @node:  a subtree containing XML Schema informations
9148  *
9149  * parse a XML schema Simple Type definition
9150  * *WARNING* this interface is highly subject to change
9151  *
9152  * Returns -1 in case of error, 0 if the declaration is improper and
9153  * 1 in case of success.
9154  */
9155 static xmlSchemaTypePtr
9156 xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9157                          xmlNodePtr node, int topLevel)
9158 {
9159     xmlSchemaTypePtr type, oldCtxtType;
9160     xmlNodePtr child = NULL;
9161     const xmlChar *attrValue = NULL;
9162     xmlAttrPtr attr;
9163     int hasRestriction = 0;
9164
9165     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9166         return (NULL);
9167
9168     if (topLevel) {
9169         attr = xmlSchemaGetPropNode(node, "name");
9170         if (attr == NULL) {
9171             xmlSchemaPMissingAttrErr(ctxt,
9172                 XML_SCHEMAP_S4S_ATTR_MISSING,
9173                 NULL, node,
9174                 "name", NULL);
9175             return (NULL);
9176         } else {
9177             if (xmlSchemaPValAttrNode(ctxt,
9178                 NULL, attr,
9179                 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9180                 return (NULL);
9181             /*
9182             * Skip built-in types.
9183             */
9184             if (ctxt->isS4S) {
9185                 xmlSchemaTypePtr biType;
9186
9187                 if (ctxt->isRedefine) {
9188                     /*
9189                     * REDEFINE: Disallow redefinition of built-in-types.
9190                     * TODO: It seems that the spec does not say anything
9191                     * about this case.
9192                     */
9193                     xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9194                         NULL, node,
9195                         "Redefinition of built-in simple types is not "
9196                         "supported", NULL);
9197                     return(NULL);
9198                 }
9199                 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9200                 if (biType != NULL)
9201                     return (biType);
9202             }
9203         }
9204     }
9205     /*
9206     * TargetNamespace:
9207     * SPEC "The `actual value` of the targetNamespace [attribute]
9208     * of the <schema> ancestor element information item if present,
9209     * otherwise `absent`.
9210     */
9211     if (topLevel == 0) {
9212 #ifdef ENABLE_NAMED_LOCALS
9213         char buf[40];
9214 #endif
9215         /*
9216         * Parse as local simple type definition.
9217         */
9218 #ifdef ENABLE_NAMED_LOCALS
9219         snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
9220         type = xmlSchemaAddType(ctxt, schema,
9221             XML_SCHEMA_TYPE_SIMPLE,
9222             xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
9223             ctxt->targetNamespace, node, 0);
9224 #else
9225         type = xmlSchemaAddType(ctxt, schema,
9226             XML_SCHEMA_TYPE_SIMPLE,
9227             NULL, ctxt->targetNamespace, node, 0);
9228 #endif
9229         if (type == NULL)
9230             return (NULL);
9231         type->type = XML_SCHEMA_TYPE_SIMPLE;
9232         type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9233         /*
9234         * Check for illegal attributes.
9235         */
9236         attr = node->properties;
9237         while (attr != NULL) {
9238             if (attr->ns == NULL) {
9239                 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
9240                     xmlSchemaPIllegalAttrErr(ctxt,
9241                         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9242                 }
9243             } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9244                     xmlSchemaPIllegalAttrErr(ctxt,
9245                         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9246             }
9247             attr = attr->next;
9248         }
9249     } else {
9250         /*
9251         * Parse as global simple type definition.
9252         *
9253         * Note that attrValue is the value of the attribute "name" here.
9254         */
9255         type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9256             attrValue, ctxt->targetNamespace, node, 1);
9257         if (type == NULL)
9258             return (NULL);
9259         type->type = XML_SCHEMA_TYPE_SIMPLE;
9260         type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9261         type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9262         /*
9263         * Check for illegal attributes.
9264         */
9265         attr = node->properties;
9266         while (attr != NULL) {
9267             if (attr->ns == NULL) {
9268                 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9269                     (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9270                     (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
9271                     xmlSchemaPIllegalAttrErr(ctxt,
9272                         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9273                 }
9274             } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9275                 xmlSchemaPIllegalAttrErr(ctxt,
9276                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9277             }
9278             attr = attr->next;
9279         }
9280         /*
9281         * Attribute "final".
9282         */
9283         attr = xmlSchemaGetPropNode(node, "final");
9284         if (attr == NULL) {
9285             if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9286                 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9287             if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9288                 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9289             if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9290                 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
9291         } else {
9292             attrValue = xmlSchemaGetProp(ctxt, node, "final");
9293             if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9294                 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
9295                 XML_SCHEMAS_TYPE_FINAL_LIST,
9296                 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9297
9298                 xmlSchemaPSimpleTypeErr(ctxt,
9299                     XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9300                     WXS_BASIC_CAST type, (xmlNodePtr) attr,
9301                     NULL, "(#all | List of (list | union | restriction)",
9302                     attrValue, NULL, NULL, NULL);
9303             }
9304         }
9305     }
9306     type->targetNamespace = ctxt->targetNamespace;
9307     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9308     /*
9309     * And now for the children...
9310     */
9311     oldCtxtType = ctxt->ctxtType;
9312
9313     ctxt->ctxtType = type;
9314
9315     child = node->children;
9316     if (IS_SCHEMA(child, "annotation")) {
9317         type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9318         child = child->next;
9319     }
9320     if (child == NULL) {
9321         xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
9322             NULL, node, child, NULL,
9323             "(annotation?, (restriction | list | union))");
9324     } else if (IS_SCHEMA(child, "restriction")) {
9325         xmlSchemaParseRestriction(ctxt, schema, child,
9326             XML_SCHEMA_TYPE_SIMPLE);
9327         hasRestriction = 1;
9328         child = child->next;
9329     } else if (IS_SCHEMA(child, "list")) {
9330         xmlSchemaParseList(ctxt, schema, child);
9331         child = child->next;
9332     } else if (IS_SCHEMA(child, "union")) {
9333         xmlSchemaParseUnion(ctxt, schema, child);
9334         child = child->next;
9335     }
9336     if (child != NULL) {
9337         xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9338             NULL, node, child, NULL,
9339             "(annotation?, (restriction | list | union))");
9340     }
9341     /*
9342     * REDEFINE: SPEC src-redefine (5)
9343     * "Within the [children], each <simpleType> must have a
9344     * <restriction> among its [children] ... the `actual value` of whose
9345     * base [attribute] must be the same as the `actual value` of its own
9346     * name attribute plus target namespace;"
9347     */
9348     if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9349         xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9350             NULL, node, "This is a redefinition, thus the "
9351             "<simpleType> must have a <restriction> child", NULL);
9352     }
9353
9354     ctxt->ctxtType = oldCtxtType;
9355     return (type);
9356 }
9357
9358 /**
9359  * xmlSchemaParseModelGroupDefRef:
9360  * @ctxt:  the parser context
9361  * @schema: the schema being built
9362  * @node:  the node
9363  *
9364  * Parses a reference to a model group definition.
9365  *
9366  * We will return a particle component with a qname-component or
9367  * NULL in case of an error.
9368  */
9369 static xmlSchemaTreeItemPtr
9370 xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9371                                xmlSchemaPtr schema,
9372                                xmlNodePtr node)
9373 {
9374     xmlSchemaParticlePtr item;
9375     xmlNodePtr child = NULL;
9376     xmlAttrPtr attr;
9377     const xmlChar *ref = NULL, *refNs = NULL;
9378     int min, max;
9379
9380     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9381         return (NULL);
9382
9383     attr = xmlSchemaGetPropNode(node, "ref");
9384     if (attr == NULL) {
9385         xmlSchemaPMissingAttrErr(ctxt,
9386             XML_SCHEMAP_S4S_ATTR_MISSING,
9387             NULL, node, "ref", NULL);
9388         return (NULL);
9389     } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
9390         attr, &refNs, &ref) != 0) {
9391         return (NULL);
9392     }
9393     xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
9394     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9395     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9396         "(xs:nonNegativeInteger | unbounded)");
9397     /*
9398     * Check for illegal attributes.
9399     */
9400     attr = node->properties;
9401     while (attr != NULL) {
9402         if (attr->ns == NULL) {
9403             if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
9404                 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9405                 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9406                 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
9407                 xmlSchemaPIllegalAttrErr(ctxt,
9408                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9409             }
9410         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9411             xmlSchemaPIllegalAttrErr(ctxt,
9412                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9413         }
9414         attr = attr->next;
9415     }
9416     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9417     item = xmlSchemaAddParticle(ctxt, node, min, max);
9418     if (item == NULL)
9419         return (NULL);
9420     /*
9421     * Create a qname-reference and set as the term; it will be substituted
9422     * for the model group after the reference has been resolved.
9423     */
9424     item->children = (xmlSchemaTreeItemPtr)
9425         xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
9426     xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9427     /*
9428     * And now for the children...
9429     */
9430     child = node->children;
9431     /* TODO: Is annotation even allowed for a model group reference? */
9432     if (IS_SCHEMA(child, "annotation")) {
9433         /*
9434         * TODO: What to do exactly with the annotation?
9435         */
9436         item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9437         child = child->next;
9438     }
9439     if (child != NULL) {
9440         xmlSchemaPContentErr(ctxt,
9441             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9442             NULL, node, child, NULL,
9443             "(annotation?)");
9444     }
9445     /*
9446     * Corresponds to no component at all if minOccurs==maxOccurs==0.
9447     */
9448     if ((min == 0) && (max == 0))
9449         return (NULL);
9450
9451     return ((xmlSchemaTreeItemPtr) item);
9452 }
9453
9454 /**
9455  * xmlSchemaParseModelGroupDefinition:
9456  * @ctxt:  a schema validation context
9457  * @schema:  the schema being built
9458  * @node:  a subtree containing XML Schema informations
9459  *
9460  * Parses a XML schema model group definition.
9461  *
9462  * Note that the contraint src-redefine (6.2) can't be applied until
9463  * references have been resolved. So we will do this at the
9464  * component fixup level.
9465  *
9466  * *WARNING* this interface is highly subject to change
9467  *
9468  * Returns -1 in case of error, 0 if the declaration is improper and
9469  *         1 in case of success.
9470  */
9471 static xmlSchemaModelGroupDefPtr
9472 xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9473                                    xmlSchemaPtr schema,
9474                                    xmlNodePtr node)
9475 {
9476     xmlSchemaModelGroupDefPtr item;
9477     xmlNodePtr child = NULL;
9478     xmlAttrPtr attr;
9479     const xmlChar *name;
9480
9481     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9482         return (NULL);
9483
9484     attr = xmlSchemaGetPropNode(node, "name");
9485     if (attr == NULL) {
9486         xmlSchemaPMissingAttrErr(ctxt,
9487             XML_SCHEMAP_S4S_ATTR_MISSING,
9488             NULL, node,
9489             "name", NULL);
9490         return (NULL);
9491     } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
9492         xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9493         return (NULL);
9494     }
9495     item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9496         ctxt->targetNamespace, node);
9497     if (item == NULL)
9498         return (NULL);
9499     /*
9500     * Check for illegal attributes.
9501     */
9502     attr = node->properties;
9503     while (attr != NULL) {
9504         if (attr->ns == NULL) {
9505             if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9506                 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
9507                 xmlSchemaPIllegalAttrErr(ctxt,
9508                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9509             }
9510         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9511             xmlSchemaPIllegalAttrErr(ctxt,
9512                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9513         }
9514         attr = attr->next;
9515     }
9516     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9517     /*
9518     * And now for the children...
9519     */
9520     child = node->children;
9521     if (IS_SCHEMA(child, "annotation")) {
9522         item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9523         child = child->next;
9524     }
9525     if (IS_SCHEMA(child, "all")) {
9526         item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9527             XML_SCHEMA_TYPE_ALL, 0);
9528         child = child->next;
9529     } else if (IS_SCHEMA(child, "choice")) {
9530         item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9531             XML_SCHEMA_TYPE_CHOICE, 0);
9532         child = child->next;
9533     } else if (IS_SCHEMA(child, "sequence")) {
9534         item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9535             XML_SCHEMA_TYPE_SEQUENCE, 0);
9536         child = child->next;
9537     }
9538
9539
9540
9541     if (child != NULL) {
9542         xmlSchemaPContentErr(ctxt,
9543             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9544             NULL, node, child, NULL,
9545             "(annotation?, (all | choice | sequence)?)");
9546     }
9547     return (item);
9548 }
9549
9550 /**
9551  * xmlSchemaCleanupDoc:
9552  * @ctxt:  a schema validation context
9553  * @node:  the root of the document.
9554  *
9555  * removes unwanted nodes in a schemas document tree
9556  */
9557 static void
9558 xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9559 {
9560     xmlNodePtr delete, cur;
9561
9562     if ((ctxt == NULL) || (root == NULL)) return;
9563
9564     /*
9565      * Remove all the blank text nodes
9566      */
9567     delete = NULL;
9568     cur = root;
9569     while (cur != NULL) {
9570         if (delete != NULL) {
9571             xmlUnlinkNode(delete);
9572             xmlFreeNode(delete);
9573             delete = NULL;
9574         }
9575         if (cur->type == XML_TEXT_NODE) {
9576             if (IS_BLANK_NODE(cur)) {
9577                 if (xmlNodeGetSpacePreserve(cur) != 1) {
9578                     delete = cur;
9579                 }
9580             }
9581         } else if ((cur->type != XML_ELEMENT_NODE) &&
9582                    (cur->type != XML_CDATA_SECTION_NODE)) {
9583             delete = cur;
9584             goto skip_children;
9585         }
9586
9587         /*
9588          * Skip to next node
9589          */
9590         if (cur->children != NULL) {
9591             if ((cur->children->type != XML_ENTITY_DECL) &&
9592                 (cur->children->type != XML_ENTITY_REF_NODE) &&
9593                 (cur->children->type != XML_ENTITY_NODE)) {
9594                 cur = cur->children;
9595                 continue;
9596             }
9597         }
9598       skip_children:
9599         if (cur->next != NULL) {
9600             cur = cur->next;
9601             continue;
9602         }
9603
9604         do {
9605             cur = cur->parent;
9606             if (cur == NULL)
9607                 break;
9608             if (cur == root) {
9609                 cur = NULL;
9610                 break;
9611             }
9612             if (cur->next != NULL) {
9613                 cur = cur->next;
9614                 break;
9615             }
9616         } while (cur != NULL);
9617     }
9618     if (delete != NULL) {
9619         xmlUnlinkNode(delete);
9620         xmlFreeNode(delete);
9621         delete = NULL;
9622     }
9623 }
9624
9625
9626 static void
9627 xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9628 {
9629     if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9630         schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9631
9632     if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9633         schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9634
9635     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9636         schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9637     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9638         schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9639     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9640         schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9641     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9642         schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9643
9644     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9645         schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9646     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9647         schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9648     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9649         schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9650 }
9651
9652 static int
9653 xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
9654                              xmlSchemaPtr schema,
9655                              xmlNodePtr node)
9656 {
9657     xmlAttrPtr attr;
9658     const xmlChar *val;
9659     int res = 0, oldErrs = ctxt->nberrors;
9660
9661     /*
9662     * Those flags should be moved to the parser context flags,
9663     * since they are not visible at the component level. I.e.
9664     * they are used if processing schema *documents* only.
9665     */
9666     res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9667     HFAILURE;
9668
9669     /*
9670     * Since the version is of type xs:token, we won't bother to
9671     * check it.
9672     */
9673     /* REMOVED:
9674     attr = xmlSchemaGetPropNode(node, "version");
9675     if (attr != NULL) {
9676         res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9677             xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9678         HFAILURE;
9679     }
9680     */
9681     attr = xmlSchemaGetPropNode(node, "targetNamespace");
9682     if (attr != NULL) {
9683         res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
9684             xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9685         HFAILURE;
9686         if (res != 0) {
9687             ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9688             goto exit;
9689         }
9690     }
9691     attr = xmlSchemaGetPropNode(node, "elementFormDefault");
9692     if (attr != NULL) {
9693         val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9694         res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9695             XML_SCHEMAS_QUALIF_ELEM);
9696         HFAILURE;
9697         if (res != 0) {
9698             xmlSchemaPSimpleTypeErr(ctxt,
9699                 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
9700                 NULL, (xmlNodePtr) attr, NULL,
9701                 "(qualified | unqualified)", val, NULL, NULL, NULL);
9702         }
9703     }
9704     attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
9705     if (attr != NULL) {
9706         val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9707         res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9708             XML_SCHEMAS_QUALIF_ATTR);
9709         HFAILURE;
9710         if (res != 0) {
9711             xmlSchemaPSimpleTypeErr(ctxt,
9712                 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
9713                 NULL, (xmlNodePtr) attr, NULL,
9714                 "(qualified | unqualified)", val, NULL, NULL, NULL);
9715         }
9716     }
9717     attr = xmlSchemaGetPropNode(node, "finalDefault");
9718     if (attr != NULL) {
9719         val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9720         res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9721             XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9722             XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9723             -1,
9724             XML_SCHEMAS_FINAL_DEFAULT_LIST,
9725             XML_SCHEMAS_FINAL_DEFAULT_UNION);
9726         HFAILURE;
9727         if (res != 0) {
9728             xmlSchemaPSimpleTypeErr(ctxt,
9729                 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9730                 NULL, (xmlNodePtr) attr, NULL,
9731                 "(#all | List of (extension | restriction | list | union))",
9732                 val, NULL, NULL, NULL);
9733         }
9734     }
9735     attr = xmlSchemaGetPropNode(node, "blockDefault");
9736     if (attr != NULL) {
9737         val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9738         res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9739             XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9740             XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
9741             XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9742         HFAILURE;
9743         if (res != 0) {
9744             xmlSchemaPSimpleTypeErr(ctxt,
9745                 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9746                 NULL, (xmlNodePtr) attr, NULL,
9747                 "(#all | List of (extension | restriction | substitution))",
9748                 val, NULL, NULL, NULL);
9749         }
9750     }
9751
9752 exit:
9753     if (oldErrs != ctxt->nberrors)
9754         res = ctxt->err;
9755     return(res);
9756 exit_failure:
9757     return(-1);
9758 }
9759
9760 /**
9761  * xmlSchemaParseSchemaTopLevel:
9762  * @ctxt:  a schema validation context
9763  * @schema:  the schemas
9764  * @nodes:  the list of top level nodes
9765  *
9766  * Returns the internal XML Schema structure built from the resource or
9767  *         NULL in case of error
9768  */
9769 static int
9770 xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9771                              xmlSchemaPtr schema, xmlNodePtr nodes)
9772 {
9773     xmlNodePtr child;
9774     xmlSchemaAnnotPtr annot;
9775     int res = 0, oldErrs, tmpOldErrs;
9776
9777     if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
9778         return(-1);
9779
9780     oldErrs = ctxt->nberrors;
9781     child = nodes;
9782     while ((IS_SCHEMA(child, "include")) ||
9783            (IS_SCHEMA(child, "import")) ||
9784            (IS_SCHEMA(child, "redefine")) ||
9785            (IS_SCHEMA(child, "annotation"))) {
9786         if (IS_SCHEMA(child, "annotation")) {
9787             annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9788             if (schema->annot == NULL)
9789                 schema->annot = annot;
9790             else
9791                 xmlSchemaFreeAnnot(annot);
9792         } else if (IS_SCHEMA(child, "import")) {
9793             tmpOldErrs = ctxt->nberrors;
9794             res = xmlSchemaParseImport(ctxt, schema, child);
9795             HFAILURE;
9796             HSTOP(ctxt);
9797             if (tmpOldErrs != ctxt->nberrors)
9798                 goto exit;
9799         } else if (IS_SCHEMA(child, "include")) {
9800             tmpOldErrs = ctxt->nberrors;
9801             res = xmlSchemaParseInclude(ctxt, schema, child);
9802             HFAILURE;
9803             HSTOP(ctxt);
9804             if (tmpOldErrs != ctxt->nberrors)
9805                 goto exit;
9806         } else if (IS_SCHEMA(child, "redefine")) {
9807             tmpOldErrs = ctxt->nberrors;
9808             res = xmlSchemaParseRedefine(ctxt, schema, child);
9809             HFAILURE;
9810             HSTOP(ctxt);
9811             if (tmpOldErrs != ctxt->nberrors)
9812                 goto exit;
9813         }
9814         child = child->next;
9815     }
9816     /*
9817     * URGENT TODO: Change the functions to return int results.
9818     * We need especially to catch internal errors.
9819     */
9820     while (child != NULL) {
9821         if (IS_SCHEMA(child, "complexType")) {
9822             xmlSchemaParseComplexType(ctxt, schema, child, 1);
9823             child = child->next;
9824         } else if (IS_SCHEMA(child, "simpleType")) {
9825             xmlSchemaParseSimpleType(ctxt, schema, child, 1);
9826             child = child->next;
9827         } else if (IS_SCHEMA(child, "element")) {
9828             xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
9829             child = child->next;
9830         } else if (IS_SCHEMA(child, "attribute")) {
9831             xmlSchemaParseGlobalAttribute(ctxt, schema, child);
9832             child = child->next;
9833         } else if (IS_SCHEMA(child, "attributeGroup")) {
9834             xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
9835             child = child->next;
9836         } else if (IS_SCHEMA(child, "group")) {
9837             xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
9838             child = child->next;
9839         } else if (IS_SCHEMA(child, "notation")) {
9840             xmlSchemaParseNotation(ctxt, schema, child);
9841             child = child->next;
9842         } else {
9843             xmlSchemaPContentErr(ctxt,
9844                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9845                 NULL, child->parent, child,
9846                 NULL, "((include | import | redefine | annotation)*, "
9847                 "(((simpleType | complexType | group | attributeGroup) "
9848                 "| element | attribute | notation), annotation*)*)");
9849             child = child->next;
9850         }
9851         while (IS_SCHEMA(child, "annotation")) {
9852             /*
9853             * TODO: We should add all annotations.
9854             */
9855             annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9856             if (schema->annot == NULL)
9857                 schema->annot = annot;
9858             else
9859                 xmlSchemaFreeAnnot(annot);
9860             child = child->next;
9861         }
9862     }
9863 exit:
9864     ctxt->ctxtType = NULL;
9865     if (oldErrs != ctxt->nberrors)
9866         res = ctxt->err;
9867     return(res);
9868 exit_failure:
9869     return(-1);
9870 }
9871
9872 static xmlSchemaSchemaRelationPtr
9873 xmlSchemaSchemaRelationCreate(void)
9874 {
9875     xmlSchemaSchemaRelationPtr ret;
9876
9877     ret = (xmlSchemaSchemaRelationPtr)
9878         xmlMalloc(sizeof(xmlSchemaSchemaRelation));
9879     if (ret == NULL) {
9880         xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
9881         return(NULL);
9882     }
9883     memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
9884     return(ret);
9885 }
9886
9887 #if 0
9888 static void
9889 xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
9890 {
9891     xmlFree(rel);
9892 }
9893 #endif
9894
9895 static void
9896 xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9897 {
9898     xmlSchemaRedefPtr prev;
9899
9900     while (redef != NULL) {
9901         prev = redef;
9902         redef = redef->next;
9903         xmlFree(prev);
9904     }
9905 }
9906
9907 static void
9908 xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9909 {
9910     /*
9911     * After the construction context has been freed, there will be
9912     * no schema graph available any more. Only the schema buckets
9913     * will stay alive, which are put into the "schemasImports" and
9914     * "includes" slots of the xmlSchema.
9915     */
9916     if (con->buckets != NULL)
9917         xmlSchemaItemListFree(con->buckets);
9918     if (con->pending != NULL)
9919         xmlSchemaItemListFree(con->pending);
9920     if (con->substGroups != NULL)
9921         xmlHashFree(con->substGroups,
9922             (xmlHashDeallocator) xmlSchemaSubstGroupFree);
9923     if (con->redefs != NULL)
9924         xmlSchemaRedefListFree(con->redefs);
9925     if (con->dict != NULL)
9926         xmlDictFree(con->dict);
9927     xmlFree(con);
9928 }
9929
9930 static xmlSchemaConstructionCtxtPtr
9931 xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9932 {
9933     xmlSchemaConstructionCtxtPtr ret;
9934
9935     ret = (xmlSchemaConstructionCtxtPtr)
9936         xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9937     if (ret == NULL) {
9938         xmlSchemaPErrMemory(NULL,
9939             "allocating schema construction context", NULL);
9940         return (NULL);
9941     }
9942     memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
9943
9944     ret->buckets = xmlSchemaItemListCreate();
9945     if (ret->buckets == NULL) {
9946         xmlSchemaPErrMemory(NULL,
9947             "allocating list of schema buckets", NULL);
9948         xmlFree(ret);
9949         return (NULL);
9950     }
9951     ret->pending = xmlSchemaItemListCreate();
9952     if (ret->pending == NULL) {
9953         xmlSchemaPErrMemory(NULL,
9954             "allocating list of pending global components", NULL);
9955         xmlSchemaConstructionCtxtFree(ret);
9956         return (NULL);
9957     }
9958     ret->dict = dict;
9959     xmlDictReference(dict);
9960     return(ret);
9961 }
9962
9963 static xmlSchemaParserCtxtPtr
9964 xmlSchemaParserCtxtCreate(void)
9965 {
9966     xmlSchemaParserCtxtPtr ret;
9967
9968     ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9969     if (ret == NULL) {
9970         xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9971                             NULL);
9972         return (NULL);
9973     }
9974     memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9975     ret->type = XML_SCHEMA_CTXT_PARSER;
9976     ret->attrProhibs = xmlSchemaItemListCreate();
9977     if (ret->attrProhibs == NULL) {
9978         xmlFree(ret);
9979         return(NULL);
9980     }
9981     return(ret);
9982 }
9983
9984 /**
9985  * xmlSchemaNewParserCtxtUseDict:
9986  * @URL:  the location of the schema
9987  * @dict: the dictionary to be used
9988  *
9989  * Create an XML Schemas parse context for that file/resource expected
9990  * to contain an XML Schemas file.
9991  *
9992  * Returns the parser context or NULL in case of error
9993  */
9994 static xmlSchemaParserCtxtPtr
9995 xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9996 {
9997     xmlSchemaParserCtxtPtr ret;
9998
9999     ret = xmlSchemaParserCtxtCreate();
10000     if (ret == NULL)
10001         return (NULL);
10002     ret->dict = dict;
10003     xmlDictReference(dict);
10004     if (URL != NULL)
10005         ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
10006     return (ret);
10007 }
10008
10009 static int
10010 xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
10011 {
10012     if (vctxt->pctxt == NULL) {
10013         if (vctxt->schema != NULL)
10014             vctxt->pctxt =
10015                 xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
10016         else
10017             vctxt->pctxt = xmlSchemaNewParserCtxt("*");
10018         if (vctxt->pctxt == NULL) {
10019             VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
10020                 "failed to create a temp. parser context");
10021             return (-1);
10022         }
10023         /* TODO: Pass user data. */
10024         xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
10025             vctxt->warning, vctxt->errCtxt);
10026         xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
10027             vctxt->errCtxt);
10028     }
10029     return (0);
10030 }
10031
10032 /**
10033  * xmlSchemaGetSchemaBucket:
10034  * @pctxt: the schema parser context
10035  * @schemaLocation: the URI of the schema document
10036  *
10037  * Returns a schema bucket if it was already parsed.
10038  *
10039  * Returns a schema bucket if it was already parsed from
10040  *         @schemaLocation, NULL otherwise.
10041  */
10042 static xmlSchemaBucketPtr
10043 xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10044                             const xmlChar *schemaLocation)
10045 {
10046     xmlSchemaBucketPtr cur;
10047     xmlSchemaItemListPtr list;
10048
10049     list = pctxt->constructor->buckets;
10050     if (list->nbItems == 0)
10051         return(NULL);
10052     else {
10053         int i;
10054         for (i = 0; i < list->nbItems; i++) {
10055             cur = (xmlSchemaBucketPtr) list->items[i];
10056             /* Pointer comparison! */
10057             if (cur->schemaLocation == schemaLocation)
10058                 return(cur);
10059         }
10060     }
10061     return(NULL);
10062 }
10063
10064 static xmlSchemaBucketPtr
10065 xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10066                                      const xmlChar *schemaLocation,
10067                                      const xmlChar *targetNamespace)
10068 {
10069     xmlSchemaBucketPtr cur;
10070     xmlSchemaItemListPtr list;
10071
10072     list = pctxt->constructor->buckets;
10073     if (list->nbItems == 0)
10074         return(NULL);
10075     else {
10076         int i;
10077         for (i = 0; i < list->nbItems; i++) {
10078             cur = (xmlSchemaBucketPtr) list->items[i];
10079             /* Pointer comparison! */
10080             if ((cur->origTargetNamespace == NULL) &&
10081                 (cur->schemaLocation == schemaLocation) &&
10082                 (cur->targetNamespace == targetNamespace))
10083                 return(cur);
10084         }
10085     }
10086     return(NULL);
10087 }
10088
10089
10090 #define IS_BAD_SCHEMA_DOC(b) \
10091     (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10092
10093 static xmlSchemaBucketPtr
10094 xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10095                                  const xmlChar *targetNamespace,
10096                                  int imported)
10097 {
10098     xmlSchemaBucketPtr cur;
10099     xmlSchemaItemListPtr list;
10100
10101     list = pctxt->constructor->buckets;
10102     if (list->nbItems == 0)
10103         return(NULL);
10104     else {
10105         int i;
10106         for (i = 0; i < list->nbItems; i++) {
10107             cur = (xmlSchemaBucketPtr) list->items[i];
10108             if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10109                 (cur->origTargetNamespace == targetNamespace) &&
10110                 ((imported && cur->imported) ||
10111                  ((!imported) && (!cur->imported))))
10112                 return(cur);
10113         }
10114     }
10115     return(NULL);
10116 }
10117
10118 static int
10119 xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10120                      xmlSchemaPtr schema,
10121                      xmlSchemaBucketPtr bucket)
10122 {
10123     int oldFlags;
10124     xmlDocPtr oldDoc;
10125     xmlNodePtr node;
10126     int ret, oldErrs;
10127     xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10128
10129     /*
10130     * Save old values; reset the *main* schema.
10131     * URGENT TODO: This is not good; move the per-document information
10132     * to the parser. Get rid of passing the main schema to the
10133     * parsing functions.
10134     */
10135     oldFlags = schema->flags;
10136     oldDoc = schema->doc;
10137     if (schema->flags != 0)
10138         xmlSchemaClearSchemaDefaults(schema);
10139     schema->doc = bucket->doc;
10140     pctxt->schema = schema;
10141     /*
10142     * Keep the current target namespace on the parser *not* on the
10143     * main schema.
10144     */
10145     pctxt->targetNamespace = bucket->targetNamespace;
10146     WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
10147
10148     if ((bucket->targetNamespace != NULL) &&
10149         xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
10150         /*
10151         * We are parsing the schema for schemas!
10152         */
10153         pctxt->isS4S = 1;
10154     }
10155     /* Mark it as parsed, even if parsing fails. */
10156     bucket->parsed++;
10157     /* Compile the schema doc. */
10158     node = xmlDocGetRootElement(bucket->doc);
10159     ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10160     if (ret != 0)
10161         goto exit;
10162     /* An empty schema; just get out. */
10163     if (node->children == NULL)
10164         goto exit;
10165     oldErrs = pctxt->nberrors;
10166     ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10167     if (ret != 0)
10168         goto exit;
10169     /*
10170     * TODO: Not nice, but I'm not 100% sure we will get always an error
10171     * as a result of the obove functions; so better rely on pctxt->err
10172     * as well.
10173     */
10174     if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10175         ret = pctxt->err;
10176         goto exit;
10177     }
10178
10179 exit:
10180     WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10181     /* Restore schema values. */
10182     schema->doc = oldDoc;
10183     schema->flags = oldFlags;
10184     return(ret);
10185 }
10186
10187 static int
10188 xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10189                      xmlSchemaPtr schema,
10190                      xmlSchemaBucketPtr bucket)
10191 {
10192     xmlSchemaParserCtxtPtr newpctxt;
10193     int res = 0;
10194
10195     if (bucket == NULL)
10196         return(0);
10197     if (bucket->parsed) {
10198         PERROR_INT("xmlSchemaParseNewDoc",
10199             "reparsing a schema doc");
10200         return(-1);
10201     }
10202     if (bucket->doc == NULL) {
10203         PERROR_INT("xmlSchemaParseNewDoc",
10204             "parsing a schema doc, but there's no doc");
10205         return(-1);
10206     }
10207     if (pctxt->constructor == NULL) {
10208         PERROR_INT("xmlSchemaParseNewDoc",
10209             "no constructor");
10210         return(-1);
10211     }
10212     /* Create and init the temporary parser context. */
10213     newpctxt = xmlSchemaNewParserCtxtUseDict(
10214         (const char *) bucket->schemaLocation, pctxt->dict);
10215     if (newpctxt == NULL)
10216         return(-1);
10217     newpctxt->constructor = pctxt->constructor;
10218     /*
10219     * TODO: Can we avoid that the parser knows about the main schema?
10220     * It would be better if he knows about the current schema bucket
10221     * only.
10222     */
10223     newpctxt->schema = schema;
10224     xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
10225         pctxt->errCtxt);
10226     xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10227         pctxt->errCtxt);
10228     newpctxt->counter = pctxt->counter;
10229
10230
10231     res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10232
10233     /* Channel back errors and cleanup the temporary parser context. */
10234     if (res != 0)
10235         pctxt->err = res;
10236     pctxt->nberrors += newpctxt->nberrors;
10237     pctxt->counter = newpctxt->counter;
10238     newpctxt->constructor = NULL;
10239     /* Free the parser context. */
10240     xmlSchemaFreeParserCtxt(newpctxt);
10241     return(res);
10242 }
10243
10244 static void
10245 xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10246                                 xmlSchemaSchemaRelationPtr rel)
10247 {
10248     xmlSchemaSchemaRelationPtr cur = bucket->relations;
10249
10250     if (cur == NULL) {
10251         bucket->relations = rel;
10252         return;
10253     }
10254     while (cur->next != NULL)
10255         cur = cur->next;
10256     cur->next = rel;
10257 }
10258
10259
10260 static const xmlChar *
10261 xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10262                           xmlNodePtr ctxtNode)
10263 {
10264     /*
10265     * Build an absolue location URI.
10266     */
10267     if (location != NULL) {
10268         if (ctxtNode == NULL)
10269             return(location);
10270         else {
10271             xmlChar *base, *URI;
10272             const xmlChar *ret = NULL;
10273
10274             base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10275             if (base == NULL) {
10276                 URI = xmlBuildURI(location, ctxtNode->doc->URL);
10277             } else {
10278                 URI = xmlBuildURI(location, base);
10279                 xmlFree(base);
10280             }
10281             if (URI != NULL) {
10282                 ret = xmlDictLookup(dict, URI, -1);
10283                 xmlFree(URI);
10284                 return(ret);
10285             }
10286         }
10287     }
10288     return(NULL);
10289 }
10290
10291
10292
10293 /**
10294  * xmlSchemaAddSchemaDoc:
10295  * @pctxt:  a schema validation context
10296  * @schema:  the schema being built
10297  * @node:  a subtree containing XML Schema informations
10298  *
10299  * Parse an included (and to-be-redefined) XML schema document.
10300  *
10301  * Returns 0 on success, a positive error code on errors and
10302  *         -1 in case of an internal or API error.
10303  */
10304
10305 static int
10306 xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10307                 int type, /* import or include or redefine */
10308                 const xmlChar *schemaLocation,
10309                 xmlDocPtr schemaDoc,
10310                 const char *schemaBuffer,
10311                 int schemaBufferLen,
10312                 xmlNodePtr invokingNode,
10313                 const xmlChar *sourceTargetNamespace,
10314                 const xmlChar *importNamespace,
10315                 xmlSchemaBucketPtr *bucket)
10316 {
10317     const xmlChar *targetNamespace = NULL;
10318     xmlSchemaSchemaRelationPtr relation = NULL;
10319     xmlDocPtr doc = NULL;
10320     int res = 0, err = 0, located = 0, preserveDoc = 0;
10321     xmlSchemaBucketPtr bkt = NULL;
10322
10323     if (bucket != NULL)
10324         *bucket = NULL;
10325
10326     switch (type) {
10327         case XML_SCHEMA_SCHEMA_IMPORT:
10328         case XML_SCHEMA_SCHEMA_MAIN:
10329             err = XML_SCHEMAP_SRC_IMPORT;
10330             break;
10331         case XML_SCHEMA_SCHEMA_INCLUDE:
10332             err = XML_SCHEMAP_SRC_INCLUDE;
10333             break;
10334         case XML_SCHEMA_SCHEMA_REDEFINE:
10335             err = XML_SCHEMAP_SRC_REDEFINE;
10336             break;
10337     }
10338
10339
10340     /* Special handling for the main schema:
10341     * skip the location and relation logic and just parse the doc.
10342     * We need just a bucket to be returned in this case.
10343     */
10344     if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10345         goto doc_load;
10346
10347     /* Note that we expect the location to be an absulute URI. */
10348     if (schemaLocation != NULL) {
10349         bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10350         if ((bkt != NULL) &&
10351             (pctxt->constructor->bucket == bkt)) {
10352             /* Report self-imports/inclusions/redefinitions. */
10353
10354             xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10355                 invokingNode, NULL,
10356                 "The schema must not import/include/redefine itself",
10357                 NULL, NULL);
10358             goto exit;
10359         }
10360     }
10361     /*
10362     * Create a relation for the graph of schemas.
10363     */
10364     relation = xmlSchemaSchemaRelationCreate();
10365     if (relation == NULL)
10366         return(-1);
10367     xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10368         relation);
10369     relation->type = type;
10370
10371     /*
10372     * Save the namespace import information.
10373     */
10374     if (WXS_IS_BUCKET_IMPMAIN(type)) {
10375         relation->importNamespace = importNamespace;
10376         if (schemaLocation == NULL) {
10377             /*
10378             * No location; this is just an import of the namespace.
10379             * Note that we don't assign a bucket to the relation
10380             * in this case.
10381             */
10382             goto exit;
10383         }
10384         targetNamespace = importNamespace;
10385     }
10386
10387     /* Did we already fetch the doc? */
10388     if (bkt != NULL) {
10389         if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
10390             /*
10391             * We included/redefined and then try to import a schema,
10392             * but the new location provided for import was different.
10393             */
10394             if (schemaLocation == NULL)
10395                 schemaLocation = BAD_CAST "in_memory_buffer";
10396             if (!xmlStrEqual(schemaLocation,
10397                 bkt->schemaLocation)) {
10398                 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10399                     invokingNode, NULL,
10400                     "The schema document '%s' cannot be imported, since "
10401                     "it was already included or redefined",
10402                     schemaLocation, NULL);
10403                 goto exit;
10404             }
10405         } else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
10406             /*
10407             * We imported and then try to include/redefine a schema,
10408             * but the new location provided for the include/redefine
10409             * was different.
10410             */
10411             if (schemaLocation == NULL)
10412                 schemaLocation = BAD_CAST "in_memory_buffer";
10413             if (!xmlStrEqual(schemaLocation,
10414                 bkt->schemaLocation)) {
10415                 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10416                     invokingNode, NULL,
10417                     "The schema document '%s' cannot be included or "
10418                     "redefined, since it was already imported",
10419                     schemaLocation, NULL);
10420                 goto exit;
10421             }
10422         }
10423     }
10424
10425     if (WXS_IS_BUCKET_IMPMAIN(type)) {
10426         /*
10427         * Given that the schemaLocation [attribute] is only a hint, it is open
10428         * to applications to ignore all but the first <import> for a given
10429         * namespace, regardless of the `actual value` of schemaLocation, but
10430         * such a strategy risks missing useful information when new
10431         * schemaLocations are offered.
10432         *
10433         * We will use the first <import> that comes with a location.
10434         * Further <import>s *with* a location, will result in an error.
10435         * TODO: Better would be to just report a warning here, but
10436         * we'll try it this way until someone complains.
10437         *
10438         * Schema Document Location Strategy:
10439         * 3 Based on the namespace name, identify an existing schema document,
10440         * either as a resource which is an XML document or a <schema> element
10441         * information item, in some local schema repository;
10442         * 5 Attempt to resolve the namespace name to locate such a resource.
10443         *
10444         * NOTE: (3) and (5) are not supported.
10445         */
10446         if (bkt != NULL) {
10447             relation->bucket = bkt;
10448             goto exit;
10449         }
10450         bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10451             importNamespace, 1);
10452
10453         if (bkt != NULL) {
10454             relation->bucket = bkt;
10455             if (bkt->schemaLocation == NULL) {
10456                 /* First given location of the schema; load the doc. */
10457                 bkt->schemaLocation = schemaLocation;
10458             } else {
10459                 if (!xmlStrEqual(schemaLocation,
10460                     bkt->schemaLocation)) {
10461                     /*
10462                     * Additional location given; just skip it.
10463                     * URGENT TODO: We should report a warning here.
10464                     * res = XML_SCHEMAP_SRC_IMPORT;
10465                     */
10466                     if (schemaLocation == NULL)
10467                         schemaLocation = BAD_CAST "in_memory_buffer";
10468
10469                     xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10470                         XML_SCHEMAP_WARN_SKIP_SCHEMA,
10471                         invokingNode, NULL,
10472                         "Skipping import of schema located at '%s' for the "
10473                         "namespace '%s', since this namespace was already "
10474                         "imported with the schema located at '%s'",
10475                         schemaLocation, importNamespace, bkt->schemaLocation);
10476                 }
10477                 goto exit;
10478             }
10479         }
10480         /*
10481         * No bucket + first location: load the doc and create a
10482         * bucket.
10483         */
10484     } else {
10485         /* <include> and <redefine> */
10486         if (bkt != NULL) {
10487
10488             if ((bkt->origTargetNamespace == NULL) &&
10489                 (bkt->targetNamespace != sourceTargetNamespace)) {
10490                 xmlSchemaBucketPtr chamel;
10491
10492                 /*
10493                 * Chameleon include/redefine: skip loading only if it was
10494                 * aleady build for the targetNamespace of the including
10495                 * schema.
10496                 */
10497                 /*
10498                 * URGENT TODO: If the schema is a chameleon-include then copy
10499                 * the components into the including schema and modify the
10500                 * targetNamespace of those components, do nothing otherwise.
10501                 * NOTE: This is currently worked-around by compiling the
10502                 * chameleon for every destinct including targetNamespace; thus
10503                 * not performant at the moment.
10504                 * TODO: Check when the namespace in wildcards for chameleons
10505                 * needs to be converted: before we built wildcard intersections
10506                 * or after.
10507                 *   Answer: after!
10508                 */
10509                 chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10510                     schemaLocation, sourceTargetNamespace);
10511                 if (chamel != NULL) {
10512                     /* A fitting chameleon was already parsed; NOP. */
10513                     relation->bucket = chamel;
10514                     goto exit;
10515                 }
10516                 /*
10517                 * We need to parse the chameleon again for a different
10518                 * targetNamespace.
10519                 * CHAMELEON TODO: Optimize this by only parsing the
10520                 * chameleon once, and then copying the components to
10521                 * the new targetNamespace.
10522                 */
10523                 bkt = NULL;
10524             } else {
10525                 relation->bucket = bkt;
10526                 goto exit;
10527             }
10528         }
10529     }
10530     if ((bkt != NULL) && (bkt->doc != NULL)) {
10531         PERROR_INT("xmlSchemaAddSchemaDoc",
10532             "trying to load a schema doc, but a doc is already "
10533             "assigned to the schema bucket");
10534         goto exit_failure;
10535     }
10536
10537 doc_load:
10538     /*
10539     * Load the document.
10540     */
10541     if (schemaDoc != NULL) {
10542         doc = schemaDoc;
10543         /* Don' free this one, since it was provided by the caller. */
10544         preserveDoc = 1;
10545         /* TODO: Does the context or the doc hold the location? */
10546         if (schemaDoc->URL != NULL)
10547             schemaLocation = xmlDictLookup(pctxt->dict,
10548                 schemaDoc->URL, -1);
10549         else
10550             schemaLocation = BAD_CAST "in_memory_buffer";
10551     } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10552         xmlParserCtxtPtr parserCtxt;
10553
10554         parserCtxt = xmlNewParserCtxt();
10555         if (parserCtxt == NULL) {
10556             xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10557                 "allocating a parser context", NULL);
10558             goto exit_failure;
10559         }
10560         if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10561             /*
10562             * TODO: Do we have to burden the schema parser dict with all
10563             * the content of the schema doc?
10564             */
10565             xmlDictFree(parserCtxt->dict);
10566             parserCtxt->dict = pctxt->dict;
10567             xmlDictReference(parserCtxt->dict);
10568         }
10569         if (schemaLocation != NULL) {
10570             /* Parse from file. */
10571             doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10572                 NULL, SCHEMAS_PARSE_OPTIONS);
10573         } else if (schemaBuffer != NULL) {
10574             /* Parse from memory buffer. */
10575             doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10576                 NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10577             schemaLocation = BAD_CAST "in_memory_buffer";
10578             if (doc != NULL)
10579                 doc->URL = xmlStrdup(schemaLocation);
10580         }
10581         /*
10582         * For <import>:
10583         * 2.1 The referent is (a fragment of) a resource which is an
10584         * XML document (see clause 1.1), which in turn corresponds to
10585         * a <schema> element information item in a well-formed information
10586         * set, which in turn corresponds to a valid schema.
10587         * TODO: (2.1) fragments of XML documents are not supported.
10588         *
10589         * 2.2 The referent is a <schema> element information item in
10590         * a well-formed information set, which in turn corresponds
10591         * to a valid schema.
10592         * TODO: (2.2) is not supported.
10593         */
10594         if (doc == NULL) {
10595             xmlErrorPtr lerr;
10596             lerr = xmlGetLastError();
10597             /*
10598             * Check if this a parser error, or if the document could
10599             * just not be located.
10600             * TODO: Try to find specific error codes to react only on
10601             * localisation failures.
10602             */
10603             if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10604                 /*
10605                 * We assume a parser error here.
10606                 */
10607                 located = 1;
10608                 /* TODO: Error code ?? */
10609                 res = XML_SCHEMAP_SRC_IMPORT_2_1;
10610                 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10611                     invokingNode, NULL,
10612                     "Failed to parse the XML resource '%s'",
10613                     schemaLocation, NULL);
10614             }
10615         }
10616         xmlFreeParserCtxt(parserCtxt);
10617         if ((doc == NULL) && located)
10618             goto exit_error;
10619     } else {
10620         xmlSchemaPErr(pctxt, NULL,
10621             XML_SCHEMAP_NOTHING_TO_PARSE,
10622             "No information for parsing was provided with the "
10623             "given schema parser context.\n",
10624             NULL, NULL);
10625         goto exit_failure;
10626     }
10627     /*
10628     * Preprocess the document.
10629     */
10630     if (doc != NULL) {
10631         xmlNodePtr docElem = NULL;
10632
10633         located = 1;
10634         docElem = xmlDocGetRootElement(doc);
10635         if (docElem == NULL) {
10636             xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10637                 invokingNode, NULL,
10638                 "The document '%s' has no document element",
10639                 schemaLocation, NULL);
10640             goto exit_error;
10641         }
10642         /*
10643         * Remove all the blank text nodes.
10644         */
10645         xmlSchemaCleanupDoc(pctxt, docElem);
10646         /*
10647         * Check the schema's top level element.
10648         */
10649         if (!IS_SCHEMA(docElem, "schema")) {
10650             xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10651                 invokingNode, NULL,
10652                 "The XML document '%s' is not a schema document",
10653                 schemaLocation, NULL);
10654             goto exit_error;
10655         }
10656         /*
10657         * Note that we don't apply a type check for the
10658         * targetNamespace value here.
10659         */
10660         targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10661             "targetNamespace");
10662     }
10663
10664 /* after_doc_loading: */
10665     if ((bkt == NULL) && located) {
10666         /* Only create a bucket if the schema was located. */
10667         bkt = xmlSchemaBucketCreate(pctxt, type,
10668             targetNamespace);
10669         if (bkt == NULL)
10670             goto exit_failure;
10671     }
10672     if (bkt != NULL) {
10673         bkt->schemaLocation = schemaLocation;
10674         bkt->located = located;
10675         if (doc != NULL) {
10676             bkt->doc = doc;
10677             bkt->targetNamespace = targetNamespace;
10678             bkt->origTargetNamespace = targetNamespace;
10679             if (preserveDoc)
10680                 bkt->preserveDoc = 1;
10681         }
10682         if (WXS_IS_BUCKET_IMPMAIN(type))
10683             bkt->imported++;
10684             /*
10685             * Add it to the graph of schemas.
10686             */
10687         if (relation != NULL)
10688             relation->bucket = bkt;
10689     }
10690
10691 exit:
10692     /*
10693     * Return the bucket explicitely; this is needed for the
10694     * main schema.
10695     */
10696     if (bucket != NULL)
10697         *bucket = bkt;
10698     return (0);
10699
10700 exit_error:
10701     if ((doc != NULL) && (! preserveDoc)) {
10702         xmlFreeDoc(doc);
10703         if (bkt != NULL)
10704             bkt->doc = NULL;
10705     }
10706     return(pctxt->err);
10707
10708 exit_failure:
10709     if ((doc != NULL) && (! preserveDoc)) {
10710         xmlFreeDoc(doc);
10711         if (bkt != NULL)
10712             bkt->doc = NULL;
10713     }
10714     return (-1);
10715 }
10716
10717 /**
10718  * xmlSchemaParseImport:
10719  * @ctxt:  a schema validation context
10720  * @schema:  the schema being built
10721  * @node:  a subtree containing XML Schema informations
10722  *
10723  * parse a XML schema Import definition
10724  * *WARNING* this interface is highly subject to change
10725  *
10726  * Returns 0 in case of success, a positive error code if
10727  * not valid and -1 in case of an internal error.
10728  */
10729 static int
10730 xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
10731                      xmlNodePtr node)
10732 {
10733     xmlNodePtr child;
10734     const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10735     const xmlChar *thisTargetNamespace;
10736     xmlAttrPtr attr;
10737     int ret = 0;
10738     xmlSchemaBucketPtr bucket = NULL;
10739
10740     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10741         return (-1);
10742
10743     /*
10744     * Check for illegal attributes.
10745     */
10746     attr = node->properties;
10747     while (attr != NULL) {
10748         if (attr->ns == NULL) {
10749             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10750                 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10751                 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10752                 xmlSchemaPIllegalAttrErr(pctxt,
10753                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10754             }
10755         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10756             xmlSchemaPIllegalAttrErr(pctxt,
10757                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10758         }
10759         attr = attr->next;
10760     }
10761     /*
10762     * Extract and validate attributes.
10763     */
10764     if (xmlSchemaPValAttr(pctxt, NULL, node,
10765         "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10766         &namespaceName) != 0) {
10767         xmlSchemaPSimpleTypeErr(pctxt,
10768             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10769             NULL, node,
10770             xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10771             NULL, namespaceName, NULL, NULL, NULL);
10772         return (pctxt->err);
10773     }
10774
10775     if (xmlSchemaPValAttr(pctxt, NULL, node,
10776         "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10777         &schemaLocation) != 0) {
10778         xmlSchemaPSimpleTypeErr(pctxt,
10779             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10780             NULL, node,
10781             xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10782             NULL, schemaLocation, NULL, NULL, NULL);
10783         return (pctxt->err);
10784     }
10785     /*
10786     * And now for the children...
10787     */
10788     child = node->children;
10789     if (IS_SCHEMA(child, "annotation")) {
10790         /*
10791          * the annotation here is simply discarded ...
10792          * TODO: really?
10793          */
10794         child = child->next;
10795     }
10796     if (child != NULL) {
10797         xmlSchemaPContentErr(pctxt,
10798             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10799             NULL, node, child, NULL,
10800             "(annotation?)");
10801     }
10802     /*
10803     * Apply additional constraints.
10804     *
10805     * Note that it is important to use the original @targetNamespace
10806     * (or none at all), to rule out imports of schemas _with_ a
10807     * @targetNamespace if the importing schema is a chameleon schema
10808     * (with no @targetNamespace).
10809     */
10810     thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
10811     if (namespaceName != NULL) {
10812         /*
10813         * 1.1 If the namespace [attribute] is present, then its `actual value`
10814         * must not match the `actual value` of the enclosing <schema>'s
10815         * targetNamespace [attribute].
10816         */
10817         if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
10818             xmlSchemaPCustomErr(pctxt,
10819                 XML_SCHEMAP_SRC_IMPORT_1_1,
10820                 NULL, node,
10821                 "The value of the attribute 'namespace' must not match "
10822                 "the target namespace '%s' of the importing schema",
10823                 thisTargetNamespace);
10824             return (pctxt->err);
10825         }
10826     } else {
10827         /*
10828         * 1.2 If the namespace [attribute] is not present, then the enclosing
10829         * <schema> must have a targetNamespace [attribute].
10830         */
10831         if (thisTargetNamespace == NULL) {
10832             xmlSchemaPCustomErr(pctxt,
10833                 XML_SCHEMAP_SRC_IMPORT_1_2,
10834                 NULL, node,
10835                 "The attribute 'namespace' must be existent if "
10836                 "the importing schema has no target namespace",
10837                 NULL);
10838             return (pctxt->err);
10839         }
10840     }
10841     /*
10842     * Locate and acquire the schema document.
10843     */
10844     if (schemaLocation != NULL)
10845         schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10846             schemaLocation, node);
10847     ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
10848         schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
10849         namespaceName, &bucket);
10850
10851     if (ret != 0)
10852         return(ret);
10853
10854     /*
10855     * For <import>: "It is *not* an error for the application
10856     * schema reference strategy to fail."
10857     * So just don't parse if no schema document was found.
10858     * Note that we will get no bucket if the schema could not be
10859     * located or if there was no schemaLocation.
10860     */
10861     if ((bucket == NULL) && (schemaLocation != NULL)) {
10862         xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10863             XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10864             node, NULL,
10865             "Failed to locate a schema at location '%s'. "
10866             "Skipping the import", schemaLocation, NULL, NULL);
10867     }
10868
10869     if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10870         ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10871     }
10872
10873     return (ret);
10874 }
10875
10876 static int
10877 xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10878                                      xmlSchemaPtr schema,
10879                                      xmlNodePtr node,
10880                                      xmlChar **schemaLocation,
10881                                      int type)
10882 {
10883     xmlAttrPtr attr;
10884
10885     if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10886         (schemaLocation == NULL))
10887         return (-1);
10888
10889     *schemaLocation = NULL;
10890     /*
10891     * Check for illegal attributes.
10892     * Applies for both <include> and <redefine>.
10893     */
10894     attr = node->properties;
10895     while (attr != NULL) {
10896         if (attr->ns == NULL) {
10897             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10898                 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10899                 xmlSchemaPIllegalAttrErr(pctxt,
10900                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10901             }
10902         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10903             xmlSchemaPIllegalAttrErr(pctxt,
10904                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10905         }
10906         attr = attr->next;
10907     }
10908     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
10909     /*
10910     * Preliminary step, extract the URI-Reference and make an URI
10911     * from the base.
10912     */
10913     /*
10914     * Attribute "schemaLocation" is mandatory.
10915     */
10916     attr = xmlSchemaGetPropNode(node, "schemaLocation");
10917     if (attr != NULL) {
10918         xmlChar *base = NULL;
10919         xmlChar *uri = NULL;
10920
10921         if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
10922             xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10923             (const xmlChar **) schemaLocation) != 0)
10924             goto exit_error;
10925         base = xmlNodeGetBase(node->doc, node);
10926         if (base == NULL) {
10927             uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10928         } else {
10929             uri = xmlBuildURI(*schemaLocation, base);
10930             xmlFree(base);
10931         }
10932         if (uri == NULL) {
10933             PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10934                 "could not build an URI from the schemaLocation")
10935             goto exit_failure;
10936         }
10937         (*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10938         xmlFree(uri);
10939     } else {
10940         xmlSchemaPMissingAttrErr(pctxt,
10941             XML_SCHEMAP_S4S_ATTR_MISSING,
10942             NULL, node, "schemaLocation", NULL);
10943         goto exit_error;
10944     }
10945     /*
10946     * Report self-inclusion and self-redefinition.
10947     */
10948     if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
10949         if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
10950             xmlSchemaPCustomErr(pctxt,
10951                 XML_SCHEMAP_SRC_REDEFINE,
10952                 NULL, node,
10953                 "The schema document '%s' cannot redefine itself.",
10954                 *schemaLocation);
10955         } else {
10956             xmlSchemaPCustomErr(pctxt,
10957                 XML_SCHEMAP_SRC_INCLUDE,
10958                 NULL, node,
10959                 "The schema document '%s' cannot include itself.",
10960                 *schemaLocation);
10961         }
10962         goto exit_error;
10963     }
10964
10965     return(0);
10966 exit_error:
10967     return(pctxt->err);
10968 exit_failure:
10969     return(-1);
10970 }
10971
10972 static int
10973 xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
10974                                 xmlSchemaPtr schema,
10975                                 xmlNodePtr node,
10976                                 int type)
10977 {
10978     xmlNodePtr child = NULL;
10979     const xmlChar *schemaLocation = NULL;
10980     int res = 0; /* hasRedefinitions = 0 */
10981     int isChameleon = 0, wasChameleon = 0;
10982     xmlSchemaBucketPtr bucket = NULL;
10983
10984     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10985         return (-1);
10986
10987     /*
10988     * Parse attributes. Note that the returned schemaLocation will
10989     * be already converted to an absolute URI.
10990     */
10991     res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
10992         node, (xmlChar **) (&schemaLocation), type);
10993     if (res != 0)
10994         return(res);
10995     /*
10996     * Load and add the schema document.
10997     */
10998     res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
10999         NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
11000     if (res != 0)
11001         return(res);
11002     /*
11003     * If we get no schema bucket back, then this means that the schema
11004     * document could not be located or was broken XML or was not
11005     * a schema document.
11006     */
11007     if ((bucket == NULL) || (bucket->doc == NULL)) {
11008         if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
11009             /*
11010             * WARNING for <include>:
11011             * We will raise an error if the schema cannot be located
11012             * for inclusions, since the that was the feedback from the
11013             * schema people. I.e. the following spec piece will *not* be
11014             * satisfied:
11015             * SPEC src-include: "It is not an error for the `actual value` of the
11016             * schemaLocation [attribute] to fail to resolve it all, in which
11017             * case no corresponding inclusion is performed.
11018             * So do we need a warning report here?"
11019             */
11020             res = XML_SCHEMAP_SRC_INCLUDE;
11021             xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
11022                 node, NULL,
11023                 "Failed to load the document '%s' for inclusion",
11024                 schemaLocation, NULL);
11025         } else {
11026             /*
11027             * NOTE: This was changed to raise an error even if no redefinitions
11028             * are specified.
11029             *
11030             * SPEC src-redefine (1)
11031             * "If there are any element information items among the [children]
11032             * other than <annotation> then the `actual value` of the
11033             * schemaLocation [attribute] must successfully resolve."
11034             * TODO: Ask the WG if a the location has always to resolve
11035             * here as well!
11036             */
11037             res = XML_SCHEMAP_SRC_REDEFINE;
11038             xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
11039                 node, NULL,
11040                 "Failed to load the document '%s' for redefinition",
11041                 schemaLocation, NULL);
11042         }
11043     } else {
11044         /*
11045         * Check targetNamespace sanity before parsing the new schema.
11046         * TODO: Note that we won't check further content if the
11047         * targetNamespace was bad.
11048         */
11049         if (bucket->origTargetNamespace != NULL) {
11050             /*
11051             * SPEC src-include (2.1)
11052             * "SII has a targetNamespace [attribute], and its `actual
11053             * value` is identical to the `actual value` of the targetNamespace
11054             * [attribute] of SII' (which must have such an [attribute])."
11055             */
11056             if (pctxt->targetNamespace == NULL) {
11057                 xmlSchemaCustomErr(ACTXT_CAST pctxt,
11058                     XML_SCHEMAP_SRC_INCLUDE,
11059                     node, NULL,
11060                     "The target namespace of the included/redefined schema "
11061                     "'%s' has to be absent, since the including/redefining "
11062                     "schema has no target namespace",
11063                     schemaLocation, NULL);
11064                 goto exit_error;
11065             } else if (!xmlStrEqual(bucket->origTargetNamespace,
11066                 pctxt->targetNamespace)) {
11067                 /* TODO: Change error function. */
11068                 xmlSchemaPCustomErrExt(pctxt,
11069                     XML_SCHEMAP_SRC_INCLUDE,
11070                     NULL, node,
11071                     "The target namespace '%s' of the included/redefined "
11072                     "schema '%s' differs from '%s' of the "
11073                     "including/redefining schema",
11074                     bucket->origTargetNamespace, schemaLocation,
11075                     pctxt->targetNamespace);
11076                 goto exit_error;
11077             }
11078         } else if (pctxt->targetNamespace != NULL) {
11079             /*
11080             * Chameleons: the original target namespace will
11081             * differ from the resulting namespace.
11082             */
11083             isChameleon = 1;
11084             if (bucket->parsed &&
11085                 bucket->origTargetNamespace != NULL) {
11086                 xmlSchemaCustomErr(ACTXT_CAST pctxt,
11087                     XML_SCHEMAP_SRC_INCLUDE,
11088                     node, NULL,
11089                     "The target namespace of the included/redefined schema "
11090                     "'%s' has to be absent or the same as the "
11091                     "including/redefining schema's target namespace",
11092                     schemaLocation, NULL);
11093                 goto exit_error;
11094             }
11095             bucket->targetNamespace = pctxt->targetNamespace;
11096         }
11097     }
11098     /*
11099     * Parse the schema.
11100     */
11101     if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11102         if (isChameleon) {
11103             /* TODO: Get rid of this flag on the schema itself. */
11104             if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11105                 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11106             } else
11107                 wasChameleon = 1;
11108         }
11109         xmlSchemaParseNewDoc(pctxt, schema, bucket);
11110         /* Restore chameleon flag. */
11111         if (isChameleon && (!wasChameleon))
11112             schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11113     }
11114     /*
11115     * And now for the children...
11116     */
11117     child = node->children;
11118     if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11119         /*
11120         * Parse (simpleType | complexType | group | attributeGroup))*
11121         */
11122         pctxt->redefined = bucket;
11123         /*
11124         * How to proceed if the redefined schema was not located?
11125         */
11126         pctxt->isRedefine = 1;
11127         while (IS_SCHEMA(child, "annotation") ||
11128             IS_SCHEMA(child, "simpleType") ||
11129             IS_SCHEMA(child, "complexType") ||
11130             IS_SCHEMA(child, "group") ||
11131             IS_SCHEMA(child, "attributeGroup")) {
11132             if (IS_SCHEMA(child, "annotation")) {
11133                 /*
11134                 * TODO: discard or not?
11135                 */
11136             } else if (IS_SCHEMA(child, "simpleType")) {
11137                 xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11138             } else if (IS_SCHEMA(child, "complexType")) {
11139                 xmlSchemaParseComplexType(pctxt, schema, child, 1);
11140                 /* hasRedefinitions = 1; */
11141             } else if (IS_SCHEMA(child, "group")) {
11142                 /* hasRedefinitions = 1; */
11143                 xmlSchemaParseModelGroupDefinition(pctxt,
11144                     schema, child);
11145             } else if (IS_SCHEMA(child, "attributeGroup")) {
11146                 /* hasRedefinitions = 1; */
11147                 xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11148                     child);
11149             }
11150             child = child->next;
11151         }
11152         pctxt->redefined = NULL;
11153         pctxt->isRedefine = 0;
11154     } else {
11155         if (IS_SCHEMA(child, "annotation")) {
11156             /*
11157             * TODO: discard or not?
11158             */
11159             child = child->next;
11160         }
11161     }
11162     if (child != NULL) {
11163         res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
11164         if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11165             xmlSchemaPContentErr(pctxt, res,
11166                 NULL, node, child, NULL,
11167                 "(annotation | (simpleType | complexType | group | attributeGroup))*");
11168         } else {
11169              xmlSchemaPContentErr(pctxt, res,
11170                 NULL, node, child, NULL,
11171                 "(annotation?)");
11172         }
11173     }
11174     return(res);
11175
11176 exit_error:
11177     return(pctxt->err);
11178 }
11179
11180 static int
11181 xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11182                        xmlNodePtr node)
11183 {
11184     int res;
11185 #ifndef ENABLE_REDEFINE
11186     TODO
11187     return(0);
11188 #endif
11189     res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11190         XML_SCHEMA_SCHEMA_REDEFINE);
11191     if (res != 0)
11192         return(res);
11193     return(0);
11194 }
11195
11196 static int
11197 xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11198                        xmlNodePtr node)
11199 {
11200     int res;
11201
11202     res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11203         XML_SCHEMA_SCHEMA_INCLUDE);
11204     if (res != 0)
11205         return(res);
11206     return(0);
11207 }
11208
11209 /**
11210  * xmlSchemaParseModelGroup:
11211  * @ctxt:  a schema validation context
11212  * @schema:  the schema being built
11213  * @node:  a subtree containing XML Schema informations
11214  * @type: the "compositor" type
11215  * @particleNeeded: if a a model group with a particle
11216  *
11217  * parse a XML schema Sequence definition.
11218  * Applies parts of:
11219  *   Schema Representation Constraint:
11220  *     Redefinition Constraints and Semantics (src-redefine)
11221  *     (6.1), (6.1.1), (6.1.2)
11222  *
11223  *   Schema Component Constraint:
11224  *     All Group Limited (cos-all-limited) (2)
11225  *     TODO: Actually this should go to component-level checks,
11226  *     but is done here due to performance. Move it to an other layer
11227  *     is schema construction via an API is implemented.
11228  *
11229  * *WARNING* this interface is highly subject to change
11230  *
11231  * Returns -1 in case of error, 0 if the declaration is improper and
11232  *         1 in case of success.
11233  */
11234 static xmlSchemaTreeItemPtr
11235 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11236                          xmlNodePtr node, xmlSchemaTypeType type,
11237                          int withParticle)
11238 {
11239     xmlSchemaModelGroupPtr item;
11240     xmlSchemaParticlePtr particle = NULL;
11241     xmlNodePtr child = NULL;
11242     xmlAttrPtr attr;
11243     int min = 1, max = 1, isElemRef, hasRefs = 0;
11244
11245     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11246         return (NULL);
11247     /*
11248     * Create a model group with the given compositor.
11249     */
11250     item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
11251     if (item == NULL)
11252         return (NULL);
11253
11254     if (withParticle) {
11255         if (type == XML_SCHEMA_TYPE_ALL) {
11256             min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
11257             max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
11258         } else {
11259             /* choice + sequence */
11260             min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11261             max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11262                 "(xs:nonNegativeInteger | unbounded)");
11263         }
11264         xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11265         /*
11266         * Create a particle
11267         */
11268         particle = xmlSchemaAddParticle(ctxt, node, min, max);
11269         if (particle == NULL)
11270             return (NULL);
11271         particle->children = (xmlSchemaTreeItemPtr) item;
11272         /*
11273         * Check for illegal attributes.
11274         */
11275         attr = node->properties;
11276         while (attr != NULL) {
11277             if (attr->ns == NULL) {
11278                 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11279                     (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11280                     (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
11281                     xmlSchemaPIllegalAttrErr(ctxt,
11282                         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11283                 }
11284             } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11285                 xmlSchemaPIllegalAttrErr(ctxt,
11286                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11287             }
11288             attr = attr->next;
11289         }
11290     } else {
11291         /*
11292         * Check for illegal attributes.
11293         */
11294         attr = node->properties;
11295         while (attr != NULL) {
11296             if (attr->ns == NULL) {
11297                 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
11298                     xmlSchemaPIllegalAttrErr(ctxt,
11299                         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11300                 }
11301             } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11302                 xmlSchemaPIllegalAttrErr(ctxt,
11303                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11304             }
11305             attr = attr->next;
11306         }
11307     }
11308
11309     /*
11310     * Extract and validate attributes.
11311     */
11312     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11313     /*
11314     * And now for the children...
11315     */
11316     child = node->children;
11317     if (IS_SCHEMA(child, "annotation")) {
11318         item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
11319         child = child->next;
11320     }
11321     if (type == XML_SCHEMA_TYPE_ALL) {
11322         xmlSchemaParticlePtr part, last = NULL;
11323
11324         while (IS_SCHEMA(child, "element")) {
11325             part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
11326                 schema, child, &isElemRef, 0);
11327             /*
11328             * SPEC cos-all-limited (2)
11329             * "The {max occurs} of all the particles in the {particles}
11330             * of the ('all') group must be 0 or 1.
11331             */
11332             if (part != NULL) {
11333                 if (isElemRef)
11334                     hasRefs++;
11335                 if (part->minOccurs > 1) {
11336                     xmlSchemaPCustomErr(ctxt,
11337                         XML_SCHEMAP_COS_ALL_LIMITED,
11338                         NULL, child,
11339                         "Invalid value for minOccurs (must be 0 or 1)",
11340                         NULL);
11341                     /* Reset to 1. */
11342                     part->minOccurs = 1;
11343                 }
11344                 if (part->maxOccurs > 1) {
11345                     xmlSchemaPCustomErr(ctxt,
11346                         XML_SCHEMAP_COS_ALL_LIMITED,
11347                         NULL, child,
11348                         "Invalid value for maxOccurs (must be 0 or 1)",
11349                         NULL);
11350                     /* Reset to 1. */
11351                     part->maxOccurs = 1;
11352                 }
11353                 if (last == NULL)
11354                     item->children = (xmlSchemaTreeItemPtr) part;
11355                 else
11356                     last->next = (xmlSchemaTreeItemPtr) part;
11357                 last = part;
11358             }
11359             child = child->next;
11360         }
11361         if (child != NULL) {
11362             xmlSchemaPContentErr(ctxt,
11363                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11364                 NULL, node, child, NULL,
11365                 "(annotation?, (annotation?, element*)");
11366         }
11367     } else {
11368         /* choice + sequence */
11369         xmlSchemaTreeItemPtr part = NULL, last = NULL;
11370
11371         while ((IS_SCHEMA(child, "element")) ||
11372             (IS_SCHEMA(child, "group")) ||
11373             (IS_SCHEMA(child, "any")) ||
11374             (IS_SCHEMA(child, "choice")) ||
11375             (IS_SCHEMA(child, "sequence"))) {
11376
11377             if (IS_SCHEMA(child, "element")) {
11378                 part = (xmlSchemaTreeItemPtr)
11379                     xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11380                 if (part && isElemRef)
11381                     hasRefs++;
11382             } else if (IS_SCHEMA(child, "group")) {
11383                 part =
11384                     xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11385                 if (part != NULL)
11386                     hasRefs++;
11387                 /*
11388                 * Handle redefinitions.
11389                 */
11390                 if (ctxt->isRedefine && ctxt->redef &&
11391                     (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11392                     part && part->children)
11393                 {
11394                     if ((xmlSchemaGetQNameRefName(part->children) ==
11395                             ctxt->redef->refName) &&
11396                         (xmlSchemaGetQNameRefTargetNs(part->children) ==
11397                             ctxt->redef->refTargetNs))
11398                     {
11399                         /*
11400                         * SPEC src-redefine:
11401                         * (6.1) "If it has a <group> among its contents at
11402                         * some level the `actual value` of whose ref
11403                         * [attribute] is the same as the `actual value` of
11404                         * its own name attribute plus target namespace, then
11405                         * all of the following must be true:"
11406                         * (6.1.1) "It must have exactly one such group."
11407                         */
11408                         if (ctxt->redefCounter != 0) {
11409                             xmlChar *str = NULL;
11410
11411                             xmlSchemaCustomErr(ACTXT_CAST ctxt,
11412                                 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11413                                 "The redefining model group definition "
11414                                 "'%s' must not contain more than one "
11415                                 "reference to the redefined definition",
11416                                 xmlSchemaFormatQName(&str,
11417                                     ctxt->redef->refTargetNs,
11418                                     ctxt->redef->refName),
11419                                 NULL);
11420                             FREE_AND_NULL(str)
11421                             part = NULL;
11422                         } else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11423                             ((WXS_PARTICLE(part))->maxOccurs != 1))
11424                         {
11425                             xmlChar *str = NULL;
11426                             /*
11427                             * SPEC src-redefine:
11428                             * (6.1.2) "The `actual value` of both that
11429                             * group's minOccurs and maxOccurs [attribute]
11430                             * must be 1 (or `absent`).
11431                             */
11432                             xmlSchemaCustomErr(ACTXT_CAST ctxt,
11433                                 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11434                                 "The redefining model group definition "
11435                                 "'%s' must not contain a reference to the "
11436                                 "redefined definition with a "
11437                                 "maxOccurs/minOccurs other than 1",
11438                                 xmlSchemaFormatQName(&str,
11439                                     ctxt->redef->refTargetNs,
11440                                     ctxt->redef->refName),
11441                                 NULL);
11442                             FREE_AND_NULL(str)
11443                             part = NULL;
11444                         }
11445                         ctxt->redef->reference = WXS_BASIC_CAST part;
11446                         ctxt->redefCounter++;
11447                     }
11448                 }
11449             } else if (IS_SCHEMA(child, "any")) {
11450                 part = (xmlSchemaTreeItemPtr)
11451                     xmlSchemaParseAny(ctxt, schema, child);
11452             } else if (IS_SCHEMA(child, "choice")) {
11453                 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11454                     XML_SCHEMA_TYPE_CHOICE, 1);
11455             } else if (IS_SCHEMA(child, "sequence")) {
11456                 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11457                     XML_SCHEMA_TYPE_SEQUENCE, 1);
11458             }
11459             if (part != NULL) {
11460                 if (last == NULL)
11461                     item->children = part;
11462                 else
11463                     last->next = part;
11464                 last = part;
11465             }
11466             child = child->next;
11467         }
11468         if (child != NULL) {
11469             xmlSchemaPContentErr(ctxt,
11470                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11471                 NULL, node, child, NULL,
11472                 "(annotation?, (element | group | choice | sequence | any)*)");
11473         }
11474     }
11475     if ((max == 0) && (min == 0))
11476         return (NULL);
11477     if (hasRefs) {
11478         /*
11479         * We need to resolve references.
11480         */
11481         WXS_ADD_PENDING(ctxt, item);
11482     }
11483     if (withParticle)
11484         return ((xmlSchemaTreeItemPtr) particle);
11485     else
11486         return ((xmlSchemaTreeItemPtr) item);
11487 }
11488
11489 /**
11490  * xmlSchemaParseRestriction:
11491  * @ctxt:  a schema validation context
11492  * @schema:  the schema being built
11493  * @node:  a subtree containing XML Schema informations
11494  *
11495  * parse a XML schema Restriction definition
11496  * *WARNING* this interface is highly subject to change
11497  *
11498  * Returns the type definition or NULL in case of error
11499  */
11500 static xmlSchemaTypePtr
11501 xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11502                           xmlNodePtr node, xmlSchemaTypeType parentType)
11503 {
11504     xmlSchemaTypePtr type;
11505     xmlNodePtr child = NULL;
11506     xmlAttrPtr attr;
11507
11508     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11509         return (NULL);
11510     /* Not a component, don't create it. */
11511     type = ctxt->ctxtType;
11512     type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
11513
11514     /*
11515     * Check for illegal attributes.
11516     */
11517     attr = node->properties;
11518     while (attr != NULL) {
11519         if (attr->ns == NULL) {
11520             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11521                 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11522                 xmlSchemaPIllegalAttrErr(ctxt,
11523                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11524             }
11525         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11526             xmlSchemaPIllegalAttrErr(ctxt,
11527                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11528         }
11529         attr = attr->next;
11530     }
11531     /*
11532     * Extract and validate attributes.
11533     */
11534     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11535     /*
11536     * Attribute
11537     */
11538     /*
11539     * Extract the base type. The "base" attribute is mandatory if inside
11540     * a complex type or if redefining.
11541     *
11542     * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
11543     * among its [children]), the simple type definition which is
11544     * the {content type} of the type definition `resolved` to by
11545     * the `actual value` of the base [attribute]"
11546     */
11547     if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
11548         &(type->baseNs), &(type->base)) == 0)
11549     {
11550         if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11551             xmlSchemaPMissingAttrErr(ctxt,
11552                 XML_SCHEMAP_S4S_ATTR_MISSING,
11553                 NULL, node, "base", NULL);
11554         } else if ((ctxt->isRedefine) &&
11555             (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11556         {
11557             if (type->base == NULL) {
11558                 xmlSchemaPMissingAttrErr(ctxt,
11559                     XML_SCHEMAP_S4S_ATTR_MISSING,
11560                     NULL, node, "base", NULL);
11561             } else if ((! xmlStrEqual(type->base, type->name)) ||
11562                 (! xmlStrEqual(type->baseNs, type->targetNamespace)))
11563             {
11564                 xmlChar *str1 = NULL, *str2 = NULL;
11565                 /*
11566                 * REDEFINE: SPEC src-redefine (5)
11567                 * "Within the [children], each <simpleType> must have a
11568                 * <restriction> among its [children] ... the `actual value` of
11569                 * whose base [attribute] must be the same as the `actual value`
11570                 * of its own name attribute plus target namespace;"
11571                 */
11572                 xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
11573                     NULL, node, "This is a redefinition, but the QName "
11574                     "value '%s' of the 'base' attribute does not match the "
11575                     "type's designation '%s'",
11576                     xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11577                     xmlSchemaFormatQName(&str2, type->targetNamespace,
11578                         type->name), NULL);
11579                 FREE_AND_NULL(str1);
11580                 FREE_AND_NULL(str2);
11581                 /* Avoid confusion and erase the values. */
11582                 type->base = NULL;
11583                 type->baseNs = NULL;
11584             }
11585         }
11586     }
11587     /*
11588     * And now for the children...
11589     */
11590     child = node->children;
11591     if (IS_SCHEMA(child, "annotation")) {
11592         /*
11593         * Add the annotation to the simple type ancestor.
11594         */
11595         xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11596             xmlSchemaParseAnnotation(ctxt, child, 1));
11597         child = child->next;
11598     }
11599     if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11600         /*
11601         * Corresponds to <simpleType><restriction><simpleType>.
11602         */
11603         if (IS_SCHEMA(child, "simpleType")) {
11604             if (type->base != NULL) {
11605                 /*
11606                 * src-restriction-base-or-simpleType
11607                 * Either the base [attribute] or the simpleType [child] of the
11608                 * <restriction> element must be present, but not both.
11609                 */
11610                 xmlSchemaPContentErr(ctxt,
11611                     XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11612                     NULL, node, child,
11613                     "The attribute 'base' and the <simpleType> child are "
11614                     "mutually exclusive", NULL);
11615             } else {
11616                 type->baseType = (xmlSchemaTypePtr)
11617                     xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11618             }
11619             child = child->next;
11620         } else if (type->base == NULL) {
11621             xmlSchemaPContentErr(ctxt,
11622                 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11623                 NULL, node, child,
11624                 "Either the attribute 'base' or a <simpleType> child "
11625                 "must be present", NULL);
11626         }
11627     } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11628         /*
11629         * Corresponds to <complexType><complexContent><restriction>...
11630         * followed by:
11631         *
11632         * Model groups <all>, <choice> and <sequence>.
11633         */
11634         if (IS_SCHEMA(child, "all")) {
11635             type->subtypes = (xmlSchemaTypePtr)
11636                 xmlSchemaParseModelGroup(ctxt, schema, child,
11637                     XML_SCHEMA_TYPE_ALL, 1);
11638             child = child->next;
11639         } else if (IS_SCHEMA(child, "choice")) {
11640             type->subtypes = (xmlSchemaTypePtr)
11641                 xmlSchemaParseModelGroup(ctxt,
11642                     schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11643             child = child->next;
11644         } else if (IS_SCHEMA(child, "sequence")) {
11645             type->subtypes = (xmlSchemaTypePtr)
11646                 xmlSchemaParseModelGroup(ctxt, schema, child,
11647                     XML_SCHEMA_TYPE_SEQUENCE, 1);
11648             child = child->next;
11649         /*
11650         * Model group reference <group>.
11651         */
11652         } else if (IS_SCHEMA(child, "group")) {
11653             type->subtypes = (xmlSchemaTypePtr)
11654                 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11655             /*
11656             * Note that the reference will be resolved in
11657             * xmlSchemaResolveTypeReferences();
11658             */
11659             child = child->next;
11660         }
11661     } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11662         /*
11663         * Corresponds to <complexType><simpleContent><restriction>...
11664         *
11665         * "1.1 the simple type definition corresponding to the <simpleType>
11666         * among the [children] of <restriction> if there is one;"
11667         */
11668         if (IS_SCHEMA(child, "simpleType")) {
11669             /*
11670             * We will store the to-be-restricted simple type in
11671             * type->contentTypeDef *temporarily*.
11672             */
11673             type->contentTypeDef = (xmlSchemaTypePtr)
11674                 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11675             if ( type->contentTypeDef == NULL)
11676                 return (NULL);
11677             child = child->next;
11678         }
11679     }
11680
11681     if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
11682         (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
11683         xmlSchemaFacetPtr facet, lastfacet = NULL;
11684         /*
11685         * Corresponds to <complexType><simpleContent><restriction>...
11686         * <simpleType><restriction>...
11687         */
11688
11689         /*
11690         * Add the facets to the simple type ancestor.
11691         */
11692         /*
11693         * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11694         * Simple Type Definition Schema Representation Constraint:
11695         * *Single Facet Value*
11696         */
11697         while ((IS_SCHEMA(child, "minInclusive")) ||
11698             (IS_SCHEMA(child, "minExclusive")) ||
11699             (IS_SCHEMA(child, "maxInclusive")) ||
11700             (IS_SCHEMA(child, "maxExclusive")) ||
11701             (IS_SCHEMA(child, "totalDigits")) ||
11702             (IS_SCHEMA(child, "fractionDigits")) ||
11703             (IS_SCHEMA(child, "pattern")) ||
11704             (IS_SCHEMA(child, "enumeration")) ||
11705             (IS_SCHEMA(child, "whiteSpace")) ||
11706             (IS_SCHEMA(child, "length")) ||
11707             (IS_SCHEMA(child, "maxLength")) ||
11708             (IS_SCHEMA(child, "minLength"))) {
11709             facet = xmlSchemaParseFacet(ctxt, schema, child);
11710             if (facet != NULL) {
11711                 if (lastfacet == NULL)
11712                     type->facets = facet;
11713                 else
11714                     lastfacet->next = facet;
11715                 lastfacet = facet;
11716                 lastfacet->next = NULL;
11717             }
11718             child = child->next;
11719         }
11720         /*
11721         * Create links for derivation and validation.
11722         */
11723         if (type->facets != NULL) {
11724             xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11725
11726             facet = type->facets;
11727             do {
11728                 facetLink = (xmlSchemaFacetLinkPtr)
11729                     xmlMalloc(sizeof(xmlSchemaFacetLink));
11730                 if (facetLink == NULL) {
11731                     xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
11732                     xmlFree(facetLink);
11733                     return (NULL);
11734                 }
11735                 facetLink->facet = facet;
11736                 facetLink->next = NULL;
11737                 if (lastFacetLink == NULL)
11738                     type->facetSet = facetLink;
11739                 else
11740                     lastFacetLink->next = facetLink;
11741                 lastFacetLink = facetLink;
11742                 facet = facet->next;
11743             } while (facet != NULL);
11744         }
11745     }
11746     if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11747         /*
11748         * Attribute uses/declarations.
11749         */
11750         if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11751             (xmlSchemaItemListPtr *) &(type->attrUses),
11752             XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11753             return(NULL);
11754         /*
11755         * Attribute wildcard.
11756         */
11757         if (IS_SCHEMA(child, "anyAttribute")) {
11758             type->attributeWildcard =
11759                 xmlSchemaParseAnyAttribute(ctxt, schema, child);
11760             child = child->next;
11761         }
11762     }
11763     if (child != NULL) {
11764         if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11765             xmlSchemaPContentErr(ctxt,
11766                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11767                 NULL, node, child, NULL,
11768                 "annotation?, (group | all | choice | sequence)?, "
11769                 "((attribute | attributeGroup)*, anyAttribute?))");
11770         } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11771              xmlSchemaPContentErr(ctxt,
11772                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11773                 NULL, node, child, NULL,
11774                 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11775                 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11776                 "length | minLength | maxLength | enumeration | whiteSpace | "
11777                 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11778         } else {
11779             /* Simple type */
11780             xmlSchemaPContentErr(ctxt,
11781                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11782                 NULL, node, child, NULL,
11783                 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11784                 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11785                 "length | minLength | maxLength | enumeration | whiteSpace | "
11786                 "pattern)*))");
11787         }
11788     }
11789     return (NULL);
11790 }
11791
11792 /**
11793  * xmlSchemaParseExtension:
11794  * @ctxt:  a schema validation context
11795  * @schema:  the schema being built
11796  * @node:  a subtree containing XML Schema informations
11797  *
11798  * Parses an <extension>, which is found inside a
11799  * <simpleContent> or <complexContent>.
11800  * *WARNING* this interface is highly subject to change.
11801  *
11802  * TODO: Returns the type definition or NULL in case of error
11803  */
11804 static xmlSchemaTypePtr
11805 xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11806                         xmlNodePtr node, xmlSchemaTypeType parentType)
11807 {
11808     xmlSchemaTypePtr type;
11809     xmlNodePtr child = NULL;
11810     xmlAttrPtr attr;
11811
11812     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11813         return (NULL);
11814     /* Not a component, don't create it. */
11815     type = ctxt->ctxtType;
11816     type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
11817
11818     /*
11819     * Check for illegal attributes.
11820     */
11821     attr = node->properties;
11822     while (attr != NULL) {
11823         if (attr->ns == NULL) {
11824             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11825                 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11826                 xmlSchemaPIllegalAttrErr(ctxt,
11827                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11828             }
11829         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11830             xmlSchemaPIllegalAttrErr(ctxt,
11831                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11832         }
11833         attr = attr->next;
11834     }
11835
11836     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11837
11838     /*
11839     * Attribute "base" - mandatory.
11840     */
11841     if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11842         "base", &(type->baseNs), &(type->base)) == 0) &&
11843         (type->base == NULL)) {
11844         xmlSchemaPMissingAttrErr(ctxt,
11845             XML_SCHEMAP_S4S_ATTR_MISSING,
11846             NULL, node, "base", NULL);
11847     }
11848     /*
11849     * And now for the children...
11850     */
11851     child = node->children;
11852     if (IS_SCHEMA(child, "annotation")) {
11853         /*
11854         * Add the annotation to the type ancestor.
11855         */
11856         xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11857             xmlSchemaParseAnnotation(ctxt, child, 1));
11858         child = child->next;
11859     }
11860     if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11861         /*
11862         * Corresponds to <complexType><complexContent><extension>... and:
11863         *
11864         * Model groups <all>, <choice>, <sequence> and <group>.
11865         */
11866         if (IS_SCHEMA(child, "all")) {
11867             type->subtypes = (xmlSchemaTypePtr)
11868                 xmlSchemaParseModelGroup(ctxt, schema,
11869                     child, XML_SCHEMA_TYPE_ALL, 1);
11870             child = child->next;
11871         } else if (IS_SCHEMA(child, "choice")) {
11872             type->subtypes = (xmlSchemaTypePtr)
11873                 xmlSchemaParseModelGroup(ctxt, schema,
11874                     child, XML_SCHEMA_TYPE_CHOICE, 1);
11875             child = child->next;
11876         } else if (IS_SCHEMA(child, "sequence")) {
11877             type->subtypes = (xmlSchemaTypePtr)
11878                 xmlSchemaParseModelGroup(ctxt, schema,
11879                 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11880             child = child->next;
11881         } else if (IS_SCHEMA(child, "group")) {
11882             type->subtypes = (xmlSchemaTypePtr)
11883                 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11884             /*
11885             * Note that the reference will be resolved in
11886             * xmlSchemaResolveTypeReferences();
11887             */
11888             child = child->next;
11889         }
11890     }
11891     if (child != NULL) {
11892         /*
11893         * Attribute uses/declarations.
11894         */
11895         if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11896             (xmlSchemaItemListPtr *) &(type->attrUses),
11897             XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11898             return(NULL);
11899         /*
11900         * Attribute wildcard.
11901         */
11902         if (IS_SCHEMA(child, "anyAttribute")) {
11903             ctxt->ctxtType->attributeWildcard =
11904                 xmlSchemaParseAnyAttribute(ctxt, schema, child);
11905             child = child->next;
11906         }
11907     }
11908     if (child != NULL) {
11909         if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11910             /* Complex content extension. */
11911             xmlSchemaPContentErr(ctxt,
11912                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11913                 NULL, node, child, NULL,
11914                 "(annotation?, ((group | all | choice | sequence)?, "
11915                 "((attribute | attributeGroup)*, anyAttribute?)))");
11916         } else {
11917             /* Simple content extension. */
11918             xmlSchemaPContentErr(ctxt,
11919                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11920                 NULL, node, child, NULL,
11921                 "(annotation?, ((attribute | attributeGroup)*, "
11922                 "anyAttribute?))");
11923         }
11924     }
11925     return (NULL);
11926 }
11927
11928 /**
11929  * xmlSchemaParseSimpleContent:
11930  * @ctxt:  a schema validation context
11931  * @schema:  the schema being built
11932  * @node:  a subtree containing XML Schema informations
11933  *
11934  * parse a XML schema SimpleContent definition
11935  * *WARNING* this interface is highly subject to change
11936  *
11937  * Returns the type definition or NULL in case of error
11938  */
11939 static int
11940 xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
11941                             xmlSchemaPtr schema, xmlNodePtr node,
11942                             int *hasRestrictionOrExtension)
11943 {
11944     xmlSchemaTypePtr type;
11945     xmlNodePtr child = NULL;
11946     xmlAttrPtr attr;
11947
11948     if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11949         (hasRestrictionOrExtension == NULL))
11950         return (-1);
11951     *hasRestrictionOrExtension = 0;
11952     /* Not a component, don't create it. */
11953     type = ctxt->ctxtType;
11954     type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11955     /*
11956     * Check for illegal attributes.
11957     */
11958     attr = node->properties;
11959     while (attr != NULL) {
11960         if (attr->ns == NULL) {
11961             if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
11962                 xmlSchemaPIllegalAttrErr(ctxt,
11963                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11964             }
11965         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11966             xmlSchemaPIllegalAttrErr(ctxt,
11967                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11968         }
11969         attr = attr->next;
11970     }
11971
11972     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11973
11974     /*
11975     * And now for the children...
11976     */
11977     child = node->children;
11978     if (IS_SCHEMA(child, "annotation")) {
11979         /*
11980         * Add the annotation to the complex type ancestor.
11981         */
11982         xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11983             xmlSchemaParseAnnotation(ctxt, child, 1));
11984         child = child->next;
11985     }
11986     if (child == NULL) {
11987         xmlSchemaPContentErr(ctxt,
11988             XML_SCHEMAP_S4S_ELEM_MISSING,
11989             NULL, node, NULL, NULL,
11990             "(annotation?, (restriction | extension))");
11991     }
11992     if (child == NULL) {
11993         xmlSchemaPContentErr(ctxt,
11994             XML_SCHEMAP_S4S_ELEM_MISSING,
11995             NULL, node, NULL, NULL,
11996             "(annotation?, (restriction | extension))");
11997     }
11998     if (IS_SCHEMA(child, "restriction")) {
11999         xmlSchemaParseRestriction(ctxt, schema, child,
12000             XML_SCHEMA_TYPE_SIMPLE_CONTENT);
12001         (*hasRestrictionOrExtension) = 1;
12002         child = child->next;
12003     } else if (IS_SCHEMA(child, "extension")) {
12004         xmlSchemaParseExtension(ctxt, schema, child,
12005             XML_SCHEMA_TYPE_SIMPLE_CONTENT);
12006         (*hasRestrictionOrExtension) = 1;
12007         child = child->next;
12008     }
12009     if (child != NULL) {
12010         xmlSchemaPContentErr(ctxt,
12011             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12012             NULL, node, child, NULL,
12013             "(annotation?, (restriction | extension))");
12014     }
12015     return (0);
12016 }
12017
12018 /**
12019  * xmlSchemaParseComplexContent:
12020  * @ctxt:  a schema validation context
12021  * @schema:  the schema being built
12022  * @node:  a subtree containing XML Schema informations
12023  *
12024  * parse a XML schema ComplexContent definition
12025  * *WARNING* this interface is highly subject to change
12026  *
12027  * Returns the type definition or NULL in case of error
12028  */
12029 static int
12030 xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
12031                              xmlSchemaPtr schema, xmlNodePtr node,
12032                              int *hasRestrictionOrExtension)
12033 {
12034     xmlSchemaTypePtr type;
12035     xmlNodePtr child = NULL;
12036     xmlAttrPtr attr;
12037
12038     if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
12039         (hasRestrictionOrExtension == NULL))
12040         return (-1);
12041     *hasRestrictionOrExtension = 0;
12042     /* Not a component, don't create it. */
12043     type = ctxt->ctxtType;
12044     /*
12045     * Check for illegal attributes.
12046     */
12047     attr = node->properties;
12048     while (attr != NULL) {
12049         if (attr->ns == NULL) {
12050             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
12051                 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
12052             {
12053                 xmlSchemaPIllegalAttrErr(ctxt,
12054                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12055             }
12056         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12057             xmlSchemaPIllegalAttrErr(ctxt,
12058                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12059         }
12060         attr = attr->next;
12061     }
12062
12063     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12064
12065     /*
12066     * Set the 'mixed' on the complex type ancestor.
12067     */
12068     if (xmlGetBooleanProp(ctxt, node, "mixed", 0))  {
12069         if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
12070             type->flags |= XML_SCHEMAS_TYPE_MIXED;
12071     }
12072     child = node->children;
12073     if (IS_SCHEMA(child, "annotation")) {
12074         /*
12075         * Add the annotation to the complex type ancestor.
12076         */
12077         xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12078             xmlSchemaParseAnnotation(ctxt, child, 1));
12079         child = child->next;
12080     }
12081     if (child == NULL) {
12082         xmlSchemaPContentErr(ctxt,
12083             XML_SCHEMAP_S4S_ELEM_MISSING,
12084             NULL, node, NULL,
12085             NULL, "(annotation?, (restriction | extension))");
12086     }
12087     if (child == NULL) {
12088         xmlSchemaPContentErr(ctxt,
12089             XML_SCHEMAP_S4S_ELEM_MISSING,
12090             NULL, node, NULL,
12091             NULL, "(annotation?, (restriction | extension))");
12092     }
12093     if (IS_SCHEMA(child, "restriction")) {
12094         xmlSchemaParseRestriction(ctxt, schema, child,
12095             XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12096         (*hasRestrictionOrExtension) = 1;
12097         child = child->next;
12098     } else if (IS_SCHEMA(child, "extension")) {
12099         xmlSchemaParseExtension(ctxt, schema, child,
12100             XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12101         (*hasRestrictionOrExtension) = 1;
12102         child = child->next;
12103     }
12104     if (child != NULL) {
12105         xmlSchemaPContentErr(ctxt,
12106             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12107             NULL, node, child,
12108             NULL, "(annotation?, (restriction | extension))");
12109     }
12110     return (0);
12111 }
12112
12113 /**
12114  * xmlSchemaParseComplexType:
12115  * @ctxt:  a schema validation context
12116  * @schema:  the schema being built
12117  * @node:  a subtree containing XML Schema informations
12118  *
12119  * parse a XML schema Complex Type definition
12120  * *WARNING* this interface is highly subject to change
12121  *
12122  * Returns the type definition or NULL in case of error
12123  */
12124 static xmlSchemaTypePtr
12125 xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
12126                           xmlNodePtr node, int topLevel)
12127 {
12128     xmlSchemaTypePtr type, ctxtType;
12129     xmlNodePtr child = NULL;
12130     const xmlChar *name = NULL;
12131     xmlAttrPtr attr;
12132     const xmlChar *attrValue;
12133 #ifdef ENABLE_NAMED_LOCALS
12134     char buf[40];
12135 #endif
12136     int final = 0, block = 0, hasRestrictionOrExtension = 0;
12137
12138
12139     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12140         return (NULL);
12141
12142     ctxtType = ctxt->ctxtType;
12143
12144     if (topLevel) {
12145         attr = xmlSchemaGetPropNode(node, "name");
12146         if (attr == NULL) {
12147             xmlSchemaPMissingAttrErr(ctxt,
12148                 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
12149             return (NULL);
12150         } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
12151             xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12152             return (NULL);
12153         }
12154     }
12155
12156     if (topLevel == 0) {
12157         /*
12158         * Parse as local complex type definition.
12159         */
12160 #ifdef ENABLE_NAMED_LOCALS
12161         snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
12162         type = xmlSchemaAddType(ctxt, schema,
12163             XML_SCHEMA_TYPE_COMPLEX,
12164             xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
12165             ctxt->targetNamespace, node, 0);
12166 #else
12167         type = xmlSchemaAddType(ctxt, schema,
12168             XML_SCHEMA_TYPE_COMPLEX,
12169             NULL, ctxt->targetNamespace, node, 0);
12170 #endif
12171         if (type == NULL)
12172             return (NULL);
12173         name = type->name;
12174         type->node = node;
12175         type->type = XML_SCHEMA_TYPE_COMPLEX;
12176         /*
12177         * TODO: We need the target namespace.
12178         */
12179     } else {
12180         /*
12181         * Parse as global complex type definition.
12182         */
12183         type = xmlSchemaAddType(ctxt, schema,
12184             XML_SCHEMA_TYPE_COMPLEX,
12185             name, ctxt->targetNamespace, node, 1);
12186         if (type == NULL)
12187             return (NULL);
12188         type->node = node;
12189         type->type = XML_SCHEMA_TYPE_COMPLEX;
12190         type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
12191     }
12192     type->targetNamespace = ctxt->targetNamespace;
12193     /*
12194     * Handle attributes.
12195     */
12196     attr = node->properties;
12197     while (attr != NULL) {
12198         if (attr->ns == NULL) {
12199             if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12200                 /*
12201                 * Attribute "id".
12202                 */
12203                 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12204             } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12205                 /*
12206                 * Attribute "mixed".
12207                 */
12208                 if (xmlSchemaPGetBoolNodeValue(ctxt,
12209                         NULL, (xmlNodePtr) attr))
12210                     type->flags |= XML_SCHEMAS_TYPE_MIXED;
12211             } else if (topLevel) {
12212                 /*
12213                 * Attributes of global complex type definitions.
12214                 */
12215                 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12216                     /* Pass. */
12217                 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12218                     /*
12219                     * Attribute "abstract".
12220                     */
12221                     if (xmlSchemaPGetBoolNodeValue(ctxt,
12222                             NULL, (xmlNodePtr) attr))
12223                         type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12224                 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12225                     /*
12226                     * Attribute "final".
12227                     */
12228                     attrValue = xmlSchemaGetNodeContent(ctxt,
12229                         (xmlNodePtr) attr);
12230                     if (xmlSchemaPValAttrBlockFinal(attrValue,
12231                         &(type->flags),
12232                         -1,
12233                         XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12234                         XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12235                         -1, -1, -1) != 0)
12236                     {
12237                         xmlSchemaPSimpleTypeErr(ctxt,
12238                             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12239                             NULL, (xmlNodePtr) attr, NULL,
12240                             "(#all | List of (extension | restriction))",
12241                             attrValue, NULL, NULL, NULL);
12242                     } else
12243                         final = 1;
12244                 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12245                     /*
12246                     * Attribute "block".
12247                     */
12248                     attrValue = xmlSchemaGetNodeContent(ctxt,
12249                         (xmlNodePtr) attr);
12250                     if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
12251                         -1,
12252                         XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
12253                         XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
12254                         -1, -1, -1) != 0) {
12255                         xmlSchemaPSimpleTypeErr(ctxt,
12256                             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12257                             NULL, (xmlNodePtr) attr, NULL,
12258                             "(#all | List of (extension | restriction)) ",
12259                             attrValue, NULL, NULL, NULL);
12260                     } else
12261                         block = 1;
12262                 } else {
12263                         xmlSchemaPIllegalAttrErr(ctxt,
12264                             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12265                 }
12266             } else {
12267                 xmlSchemaPIllegalAttrErr(ctxt,
12268                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12269             }
12270         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12271             xmlSchemaPIllegalAttrErr(ctxt,
12272                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12273         }
12274         attr = attr->next;
12275     }
12276     if (! block) {
12277         /*
12278         * Apply default "block" values.
12279         */
12280         if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12281             type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12282         if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12283             type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12284     }
12285     if (! final) {
12286         /*
12287         * Apply default "block" values.
12288         */
12289         if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12290             type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12291         if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12292             type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12293     }
12294     /*
12295     * And now for the children...
12296     */
12297     child = node->children;
12298     if (IS_SCHEMA(child, "annotation")) {
12299         type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
12300         child = child->next;
12301     }
12302     ctxt->ctxtType = type;
12303     if (IS_SCHEMA(child, "simpleContent")) {
12304         /*
12305         * <complexType><simpleContent>...
12306         * 3.4.3 : 2.2
12307         * Specifying mixed='true' when the <simpleContent>
12308         * alternative is chosen has no effect
12309         */
12310         if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12311             type->flags ^= XML_SCHEMAS_TYPE_MIXED;
12312         xmlSchemaParseSimpleContent(ctxt, schema, child,
12313             &hasRestrictionOrExtension);
12314         child = child->next;
12315     } else if (IS_SCHEMA(child, "complexContent")) {
12316         /*
12317         * <complexType><complexContent>...
12318         */
12319         type->contentType = XML_SCHEMA_CONTENT_EMPTY;
12320         xmlSchemaParseComplexContent(ctxt, schema, child,
12321             &hasRestrictionOrExtension);
12322         child = child->next;
12323     } else {
12324         /*
12325         * E.g <complexType><sequence>... or <complexType><attribute>... etc.
12326         *
12327         * SPEC
12328         * "...the third alternative (neither <simpleContent> nor
12329         * <complexContent>) is chosen. This case is understood as shorthand
12330         * for complex content restricting the `ur-type definition`, and the
12331         * details of the mappings should be modified as necessary.
12332         */
12333         type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12334         type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
12335         /*
12336         * Parse model groups.
12337         */
12338         if (IS_SCHEMA(child, "all")) {
12339             type->subtypes = (xmlSchemaTypePtr)
12340                 xmlSchemaParseModelGroup(ctxt, schema, child,
12341                     XML_SCHEMA_TYPE_ALL, 1);
12342             child = child->next;
12343         } else if (IS_SCHEMA(child, "choice")) {
12344             type->subtypes = (xmlSchemaTypePtr)
12345                 xmlSchemaParseModelGroup(ctxt, schema, child,
12346                     XML_SCHEMA_TYPE_CHOICE, 1);
12347             child = child->next;
12348         } else if (IS_SCHEMA(child, "sequence")) {
12349             type->subtypes = (xmlSchemaTypePtr)
12350                 xmlSchemaParseModelGroup(ctxt, schema, child,
12351                     XML_SCHEMA_TYPE_SEQUENCE, 1);
12352             child = child->next;
12353         } else if (IS_SCHEMA(child, "group")) {
12354             type->subtypes = (xmlSchemaTypePtr)
12355                 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
12356             /*
12357             * Note that the reference will be resolved in
12358             * xmlSchemaResolveTypeReferences();
12359             */
12360             child = child->next;
12361         }
12362         /*
12363         * Parse attribute decls/refs.
12364         */
12365         if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12366             (xmlSchemaItemListPtr *) &(type->attrUses),
12367             XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12368             return(NULL);
12369         /*
12370         * Parse attribute wildcard.
12371         */
12372         if (IS_SCHEMA(child, "anyAttribute")) {
12373             type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12374             child = child->next;
12375         }
12376     }
12377     if (child != NULL) {
12378         xmlSchemaPContentErr(ctxt,
12379             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12380             NULL, node, child,
12381             NULL, "(annotation?, (simpleContent | complexContent | "
12382             "((group | all | choice | sequence)?, ((attribute | "
12383             "attributeGroup)*, anyAttribute?))))");
12384     }
12385     /*
12386     * REDEFINE: SPEC src-redefine (5)
12387     */
12388     if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12389         xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
12390             NULL, node, "This is a redefinition, thus the "
12391             "<complexType> must have a <restriction> or <extension> "
12392             "grand-child", NULL);
12393     }
12394     ctxt->ctxtType = ctxtType;
12395     return (type);
12396 }
12397
12398 /************************************************************************
12399  *                                                                      *
12400  *                      Validating using Schemas                        *
12401  *                                                                      *
12402  ************************************************************************/
12403
12404 /************************************************************************
12405  *                                                                      *
12406  *                      Reading/Writing Schemas                         *
12407  *                                                                      *
12408  ************************************************************************/
12409
12410 #if 0 /* Will be enabled if it is clear what options are needed. */
12411 /**
12412  * xmlSchemaParserCtxtSetOptions:
12413  * @ctxt:       a schema parser context
12414  * @options: a combination of xmlSchemaParserOption
12415  *
12416  * Sets the options to be used during the parse.
12417  *
12418  * Returns 0 in case of success, -1 in case of an
12419  * API error.
12420  */
12421 static int
12422 xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12423                               int options)
12424
12425 {
12426     int i;
12427
12428     if (ctxt == NULL)
12429         return (-1);
12430     /*
12431     * WARNING: Change the start value if adding to the
12432     * xmlSchemaParseOption.
12433     */
12434     for (i = 1; i < (int) sizeof(int) * 8; i++) {
12435         if (options & 1<<i) {
12436             return (-1);
12437         }
12438     }
12439     ctxt->options = options;
12440     return (0);
12441 }
12442
12443 /**
12444  * xmlSchemaValidCtxtGetOptions:
12445  * @ctxt: a schema parser context
12446  *
12447  * Returns the option combination of the parser context.
12448  */
12449 static int
12450 xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
12451
12452 {
12453     if (ctxt == NULL)
12454         return (-1);
12455     else
12456         return (ctxt->options);
12457 }
12458 #endif
12459
12460 /**
12461  * xmlSchemaNewParserCtxt:
12462  * @URL:  the location of the schema
12463  *
12464  * Create an XML Schemas parse context for that file/resource expected
12465  * to contain an XML Schemas file.
12466  *
12467  * Returns the parser context or NULL in case of error
12468  */
12469 xmlSchemaParserCtxtPtr
12470 xmlSchemaNewParserCtxt(const char *URL)
12471 {
12472     xmlSchemaParserCtxtPtr ret;
12473
12474     if (URL == NULL)
12475         return (NULL);
12476
12477     ret = xmlSchemaParserCtxtCreate();
12478     if (ret == NULL)
12479         return(NULL);
12480     ret->dict = xmlDictCreate();
12481     ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
12482     return (ret);
12483 }
12484
12485 /**
12486  * xmlSchemaNewMemParserCtxt:
12487  * @buffer:  a pointer to a char array containing the schemas
12488  * @size:  the size of the array
12489  *
12490  * Create an XML Schemas parse context for that memory buffer expected
12491  * to contain an XML Schemas file.
12492  *
12493  * Returns the parser context or NULL in case of error
12494  */
12495 xmlSchemaParserCtxtPtr
12496 xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12497 {
12498     xmlSchemaParserCtxtPtr ret;
12499
12500     if ((buffer == NULL) || (size <= 0))
12501         return (NULL);
12502     ret = xmlSchemaParserCtxtCreate();
12503     if (ret == NULL)
12504         return(NULL);
12505     ret->buffer = buffer;
12506     ret->size = size;
12507     ret->dict = xmlDictCreate();
12508     return (ret);
12509 }
12510
12511 /**
12512  * xmlSchemaNewDocParserCtxt:
12513  * @doc:  a preparsed document tree
12514  *
12515  * Create an XML Schemas parse context for that document.
12516  * NB. The document may be modified during the parsing process.
12517  *
12518  * Returns the parser context or NULL in case of error
12519  */
12520 xmlSchemaParserCtxtPtr
12521 xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12522 {
12523     xmlSchemaParserCtxtPtr ret;
12524
12525     if (doc == NULL)
12526       return (NULL);
12527     ret = xmlSchemaParserCtxtCreate();
12528     if (ret == NULL)
12529         return(NULL);
12530     ret->doc = doc;
12531     ret->dict = xmlDictCreate();
12532     /* The application has responsibility for the document */
12533     ret->preserve = 1;
12534
12535     return (ret);
12536 }
12537
12538 /**
12539  * xmlSchemaFreeParserCtxt:
12540  * @ctxt:  the schema parser context
12541  *
12542  * Free the resources associated to the schema parser context
12543  */
12544 void
12545 xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12546 {
12547     if (ctxt == NULL)
12548         return;
12549     if (ctxt->doc != NULL && !ctxt->preserve)
12550         xmlFreeDoc(ctxt->doc);
12551     if (ctxt->vctxt != NULL) {
12552         xmlSchemaFreeValidCtxt(ctxt->vctxt);
12553     }
12554     if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12555         xmlSchemaConstructionCtxtFree(ctxt->constructor);
12556         ctxt->constructor = NULL;
12557         ctxt->ownsConstructor = 0;
12558     }
12559     if (ctxt->attrProhibs != NULL)
12560         xmlSchemaItemListFree(ctxt->attrProhibs);
12561     xmlDictFree(ctxt->dict);
12562     xmlFree(ctxt);
12563 }
12564
12565 /************************************************************************
12566  *                                                                      *
12567  *                      Building the content models                     *
12568  *                                                                      *
12569  ************************************************************************/
12570
12571 /**
12572  * xmlSchemaBuildContentModelForSubstGroup:
12573  *
12574  * Returns 1 if nillable, 0 otherwise
12575  */
12576 static int
12577 xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
12578         xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
12579 {
12580     xmlAutomataStatePtr start, tmp;
12581     xmlSchemaElementPtr elemDecl, member;
12582     xmlSchemaSubstGroupPtr substGroup;
12583     int i;
12584     int ret = 0;
12585
12586     elemDecl = (xmlSchemaElementPtr) particle->children;
12587     /*
12588     * Wrap the substitution group with a CHOICE.
12589     */
12590     start = pctxt->state;
12591     if (end == NULL)
12592         end = xmlAutomataNewState(pctxt->am);
12593     substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
12594     if (substGroup == NULL) {
12595         xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
12596             XML_SCHEMAP_INTERNAL,
12597             "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12598             "declaration is marked having a subst. group but none "
12599             "available.\n", elemDecl->name, NULL);
12600         return(0);
12601     }
12602     if (counter >= 0) {
12603         /*
12604         * NOTE that we put the declaration in, even if it's abstract.
12605         * However, an error will be raised during *validation* if an element
12606         * information item shall be validated against an abstract element
12607         * declaration.
12608         */
12609         tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12610         xmlAutomataNewTransition2(pctxt->am, tmp, end,
12611                     elemDecl->name, elemDecl->targetNamespace, elemDecl);
12612         /*
12613         * Add subst. group members.
12614         */
12615         for (i = 0; i < substGroup->members->nbItems; i++) {
12616             member = (xmlSchemaElementPtr) substGroup->members->items[i];
12617             xmlAutomataNewTransition2(pctxt->am, tmp, end,
12618                                member->name, member->targetNamespace, member);
12619         }
12620     } else if (particle->maxOccurs == 1) {
12621         /*
12622         * NOTE that we put the declaration in, even if it's abstract,
12623         */
12624         xmlAutomataNewEpsilon(pctxt->am,
12625             xmlAutomataNewTransition2(pctxt->am,
12626             start, NULL,
12627             elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12628         /*
12629         * Add subst. group members.
12630         */
12631         for (i = 0; i < substGroup->members->nbItems; i++) {
12632             member = (xmlSchemaElementPtr) substGroup->members->items[i];
12633             /*
12634             * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2()
12635             *  was incorrectly used instead of xmlAutomataNewTransition2()
12636             *  (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL
12637             *  section in xmlSchemaBuildAContentModel() ).
12638             * TODO: Check if xmlAutomataNewOnceTrans2() was instead
12639             *  intended for the above "counter" section originally. I.e.,
12640             *  check xs:all with subst-groups.
12641             *
12642             * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12643             *                  member->name, member->targetNamespace,
12644             *                  1, 1, member);
12645             */
12646             tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL,
12647                 member->name, member->targetNamespace, member);
12648             xmlAutomataNewEpsilon(pctxt->am, tmp, end);
12649         }
12650     } else {
12651         xmlAutomataStatePtr hop;
12652         int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12653             UNBOUNDED : particle->maxOccurs - 1;
12654         int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12655
12656         counter =
12657             xmlAutomataNewCounter(pctxt->am, minOccurs,
12658             maxOccurs);
12659         hop = xmlAutomataNewState(pctxt->am);
12660
12661         xmlAutomataNewEpsilon(pctxt->am,
12662             xmlAutomataNewTransition2(pctxt->am,
12663             start, NULL,
12664             elemDecl->name, elemDecl->targetNamespace, elemDecl),
12665             hop);
12666         /*
12667          * Add subst. group members.
12668          */
12669         for (i = 0; i < substGroup->members->nbItems; i++) {
12670             member = (xmlSchemaElementPtr) substGroup->members->items[i];
12671             xmlAutomataNewEpsilon(pctxt->am,
12672                 xmlAutomataNewTransition2(pctxt->am,
12673                 start, NULL,
12674                 member->name, member->targetNamespace, member),
12675                 hop);
12676         }
12677         xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12678         xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12679     }
12680     if (particle->minOccurs == 0) {
12681         xmlAutomataNewEpsilon(pctxt->am, start, end);
12682         ret = 1;
12683     }
12684     pctxt->state = end;
12685     return(ret);
12686 }
12687
12688 /**
12689  * xmlSchemaBuildContentModelForElement:
12690  *
12691  * Returns 1 if nillable, 0 otherwise
12692  */
12693 static int
12694 xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12695                                      xmlSchemaParticlePtr particle)
12696 {
12697     int ret = 0;
12698
12699     if (((xmlSchemaElementPtr) particle->children)->flags &
12700         XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12701         /*
12702         * Substitution groups.
12703         */
12704         ret = xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
12705     } else {
12706         xmlSchemaElementPtr elemDecl;
12707         xmlAutomataStatePtr start;
12708
12709         elemDecl = (xmlSchemaElementPtr) particle->children;
12710
12711         if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
12712             return(0);
12713         if (particle->maxOccurs == 1) {
12714             start = ctxt->state;
12715             ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12716                     elemDecl->name, elemDecl->targetNamespace, elemDecl);
12717         } else if ((particle->maxOccurs >= UNBOUNDED) &&
12718                    (particle->minOccurs < 2)) {
12719             /* Special case. */
12720             start = ctxt->state;
12721             ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12722                 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12723             ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
12724                 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12725         } else {
12726             int counter;
12727             int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12728                             UNBOUNDED : particle->maxOccurs - 1;
12729             int minOccurs = particle->minOccurs < 1 ?
12730                             0 : particle->minOccurs - 1;
12731
12732             start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
12733             counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12734             ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12735                 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12736             xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12737             ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12738                 NULL, counter);
12739         }
12740         if (particle->minOccurs == 0) {
12741             xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12742             ret = 1;
12743         }
12744     }
12745     return(ret);
12746 }
12747
12748 /**
12749  * xmlSchemaBuildAContentModel:
12750  * @ctxt:  the schema parser context
12751  * @particle:  the particle component
12752  * @name:  the complex type's name whose content is being built
12753  *
12754  * Create the automaton for the {content type} of a complex type.
12755  *
12756  * Returns 1 if the content is nillable, 0 otherwise
12757  */
12758 static int
12759 xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
12760                             xmlSchemaParticlePtr particle)
12761 {
12762     int ret = 0, tmp2;
12763
12764     if (particle == NULL) {
12765         PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
12766         return(1);
12767     }
12768     if (particle->children == NULL) {
12769         /*
12770         * Just return in this case. A missing "term" of the particle
12771         * might arise due to an invalid "term" component.
12772         */
12773         return(1);
12774     }
12775
12776     switch (particle->children->type) {
12777         case XML_SCHEMA_TYPE_ANY: {
12778             xmlAutomataStatePtr start, end;
12779             xmlSchemaWildcardPtr wild;
12780             xmlSchemaWildcardNsPtr ns;
12781
12782             wild = (xmlSchemaWildcardPtr) particle->children;
12783
12784             start = pctxt->state;
12785             end = xmlAutomataNewState(pctxt->am);
12786
12787             if (particle->maxOccurs == 1) {
12788                 if (wild->any == 1) {
12789                     /*
12790                     * We need to add both transitions:
12791                     *
12792                     * 1. the {"*", "*"} for elements in a namespace.
12793                     */
12794                     pctxt->state =
12795                         xmlAutomataNewTransition2(pctxt->am,
12796                         start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12797                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12798                     /*
12799                     * 2. the {"*"} for elements in no namespace.
12800                     */
12801                     pctxt->state =
12802                         xmlAutomataNewTransition2(pctxt->am,
12803                         start, NULL, BAD_CAST "*", NULL, wild);
12804                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12805
12806                 } else if (wild->nsSet != NULL) {
12807                     ns = wild->nsSet;
12808                     do {
12809                         pctxt->state = start;
12810                         pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12811                             pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12812                         xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12813                         ns = ns->next;
12814                     } while (ns != NULL);
12815
12816                 } else if (wild->negNsSet != NULL) {
12817                     pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12818                         start, end, BAD_CAST "*", wild->negNsSet->value,
12819                         wild);
12820                 }
12821             } else {
12822                 int counter;
12823                 xmlAutomataStatePtr hop;
12824                 int maxOccurs =
12825                     particle->maxOccurs == UNBOUNDED ? UNBOUNDED :
12826                                            particle->maxOccurs - 1;
12827                 int minOccurs =
12828                     particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12829
12830                 counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12831                 hop = xmlAutomataNewState(pctxt->am);
12832                 if (wild->any == 1) {
12833                     pctxt->state =
12834                         xmlAutomataNewTransition2(pctxt->am,
12835                         start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12836                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12837                     pctxt->state =
12838                         xmlAutomataNewTransition2(pctxt->am,
12839                         start, NULL, BAD_CAST "*", NULL, wild);
12840                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12841                 } else if (wild->nsSet != NULL) {
12842                     ns = wild->nsSet;
12843                     do {
12844                         pctxt->state =
12845                             xmlAutomataNewTransition2(pctxt->am,
12846                                 start, NULL, BAD_CAST "*", ns->value, wild);
12847                         xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12848                         ns = ns->next;
12849                     } while (ns != NULL);
12850
12851                 } else if (wild->negNsSet != NULL) {
12852                     pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12853                         start, hop, BAD_CAST "*", wild->negNsSet->value,
12854                         wild);
12855                 }
12856                 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12857                 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12858             }
12859             if (particle->minOccurs == 0) {
12860                 xmlAutomataNewEpsilon(pctxt->am, start, end);
12861                 ret = 1;
12862             }
12863             pctxt->state = end;
12864             break;
12865         }
12866         case XML_SCHEMA_TYPE_ELEMENT:
12867             ret = xmlSchemaBuildContentModelForElement(pctxt, particle);
12868             break;
12869         case XML_SCHEMA_TYPE_SEQUENCE:{
12870             xmlSchemaTreeItemPtr sub;
12871
12872             ret = 1;
12873             /*
12874              * If max and min occurances are default (1) then
12875              * simply iterate over the particles of the <sequence>.
12876              */
12877             if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12878                 sub = particle->children->children;
12879
12880                 while (sub != NULL) {
12881                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
12882                                         (xmlSchemaParticlePtr) sub);
12883                     if (tmp2 != 1) ret = 0;
12884                     sub = sub->next;
12885                 }
12886             } else {
12887                 xmlAutomataStatePtr oldstate = pctxt->state;
12888
12889                 if (particle->maxOccurs >= UNBOUNDED) {
12890                     if (particle->minOccurs > 1) {
12891                         xmlAutomataStatePtr tmp;
12892                         int counter;
12893
12894                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12895                             oldstate, NULL);
12896                         oldstate = pctxt->state;
12897
12898                         counter = xmlAutomataNewCounter(pctxt->am,
12899                             particle->minOccurs - 1, UNBOUNDED);
12900
12901                         sub = particle->children->children;
12902                         while (sub != NULL) {
12903                             tmp2 = xmlSchemaBuildAContentModel(pctxt,
12904                                             (xmlSchemaParticlePtr) sub);
12905                             if (tmp2 != 1) ret = 0;
12906                             sub = sub->next;
12907                         }
12908                         tmp = pctxt->state;
12909                         xmlAutomataNewCountedTrans(pctxt->am, tmp,
12910                                                    oldstate, counter);
12911                         pctxt->state =
12912                             xmlAutomataNewCounterTrans(pctxt->am, tmp,
12913                                                        NULL, counter);
12914                         if (ret == 1)
12915                             xmlAutomataNewEpsilon(pctxt->am,
12916                                                 oldstate, pctxt->state);
12917
12918                     } else {
12919                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12920                             oldstate, NULL);
12921                         oldstate = pctxt->state;
12922
12923                         sub = particle->children->children;
12924                         while (sub != NULL) {
12925                             tmp2 = xmlSchemaBuildAContentModel(pctxt,
12926                                         (xmlSchemaParticlePtr) sub);
12927                             if (tmp2 != 1) ret = 0;
12928                             sub = sub->next;
12929                         }
12930                         xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
12931                                               oldstate);
12932                         /*
12933                          * epsilon needed to block previous trans from
12934                          * being allowed to enter back from another
12935                          * construct
12936                          */
12937                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12938                                             pctxt->state, NULL);
12939                         if (particle->minOccurs == 0) {
12940                             xmlAutomataNewEpsilon(pctxt->am,
12941                                 oldstate, pctxt->state);
12942                             ret = 1;
12943                         }
12944                     }
12945                 } else if ((particle->maxOccurs > 1)
12946                            || (particle->minOccurs > 1)) {
12947                     xmlAutomataStatePtr tmp;
12948                     int counter;
12949
12950                     pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12951                         oldstate, NULL);
12952                     oldstate = pctxt->state;
12953
12954                     counter = xmlAutomataNewCounter(pctxt->am,
12955                         particle->minOccurs - 1,
12956                         particle->maxOccurs - 1);
12957
12958                     sub = particle->children->children;
12959                     while (sub != NULL) {
12960                         tmp2 = xmlSchemaBuildAContentModel(pctxt,
12961                                         (xmlSchemaParticlePtr) sub);
12962                         if (tmp2 != 1) ret = 0;
12963                         sub = sub->next;
12964                     }
12965                     tmp = pctxt->state;
12966                     xmlAutomataNewCountedTrans(pctxt->am,
12967                         tmp, oldstate, counter);
12968                     pctxt->state =
12969                         xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
12970                                                    counter);
12971                     if ((particle->minOccurs == 0) || (ret == 1)) {
12972                         xmlAutomataNewEpsilon(pctxt->am,
12973                                             oldstate, pctxt->state);
12974                         ret = 1;
12975                     }
12976                 } else {
12977                     sub = particle->children->children;
12978                     while (sub != NULL) {
12979                         tmp2 = xmlSchemaBuildAContentModel(pctxt,
12980                                         (xmlSchemaParticlePtr) sub);
12981                         if (tmp2 != 1) ret = 0;
12982                         sub = sub->next;
12983                     }
12984
12985                     /*
12986                      * epsilon needed to block previous trans from
12987                      * being allowed to enter back from another
12988                      * construct
12989                      */
12990                     pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12991                                         pctxt->state, NULL);
12992
12993                     if (particle->minOccurs == 0) {
12994                         xmlAutomataNewEpsilon(pctxt->am, oldstate,
12995                                               pctxt->state);
12996                         ret = 1;
12997                     }
12998                 }
12999             }
13000             break;
13001         }
13002         case XML_SCHEMA_TYPE_CHOICE:{
13003             xmlSchemaTreeItemPtr sub;
13004             xmlAutomataStatePtr start, end;
13005
13006             ret = 0;
13007             start = pctxt->state;
13008             end = xmlAutomataNewState(pctxt->am);
13009
13010             /*
13011              * iterate over the subtypes and remerge the end with an
13012              * epsilon transition
13013              */
13014             if (particle->maxOccurs == 1) {
13015                 sub = particle->children->children;
13016                 while (sub != NULL) {
13017                     pctxt->state = start;
13018                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
13019                                         (xmlSchemaParticlePtr) sub);
13020                     if (tmp2 == 1) ret = 1;
13021                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
13022                     sub = sub->next;
13023                 }
13024             } else {
13025                 int counter;
13026                 xmlAutomataStatePtr hop, base;
13027                 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
13028                     UNBOUNDED : particle->maxOccurs - 1;
13029                 int minOccurs =
13030                     particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
13031
13032                 /*
13033                  * use a counter to keep track of the number of transtions
13034                  * which went through the choice.
13035                  */
13036                 counter =
13037                     xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
13038                 hop = xmlAutomataNewState(pctxt->am);
13039                 base = xmlAutomataNewState(pctxt->am);
13040
13041                 sub = particle->children->children;
13042                 while (sub != NULL) {
13043                     pctxt->state = base;
13044                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
13045                                         (xmlSchemaParticlePtr) sub);
13046                     if (tmp2 == 1) ret = 1;
13047                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
13048                     sub = sub->next;
13049                 }
13050                 xmlAutomataNewEpsilon(pctxt->am, start, base);
13051                 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
13052                 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
13053                 if (ret == 1)
13054                     xmlAutomataNewEpsilon(pctxt->am, base, end);
13055             }
13056             if (particle->minOccurs == 0) {
13057                 xmlAutomataNewEpsilon(pctxt->am, start, end);
13058                 ret = 1;
13059             }
13060             pctxt->state = end;
13061             break;
13062         }
13063         case XML_SCHEMA_TYPE_ALL:{
13064             xmlAutomataStatePtr start, tmp;
13065             xmlSchemaParticlePtr sub;
13066             xmlSchemaElementPtr elemDecl;
13067
13068             ret = 1;
13069
13070             sub = (xmlSchemaParticlePtr) particle->children->children;
13071             if (sub == NULL)
13072                 break;
13073
13074             ret = 0;
13075
13076             start = pctxt->state;
13077             tmp = xmlAutomataNewState(pctxt->am);
13078             xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp);
13079             pctxt->state = tmp;
13080             while (sub != NULL) {
13081                 pctxt->state = tmp;
13082
13083                 elemDecl = (xmlSchemaElementPtr) sub->children;
13084                 if (elemDecl == NULL) {
13085                     PERROR_INT("xmlSchemaBuildAContentModel",
13086                         "<element> particle has no term");
13087                     return(ret);
13088                 };
13089                 /*
13090                 * NOTE: The {max occurs} of all the particles in the
13091                 * {particles} of the group must be 0 or 1; this is
13092                 * already ensured during the parse of the content of
13093                 * <all>.
13094                 */
13095                 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
13096                     int counter;
13097
13098                     /*
13099                      * This is an abstract group, we need to share
13100                      * the same counter for all the element transitions
13101                      * derived from the group
13102                      */
13103                     counter = xmlAutomataNewCounter(pctxt->am,
13104                                        sub->minOccurs, sub->maxOccurs);
13105                     xmlSchemaBuildContentModelForSubstGroup(pctxt,
13106                                        sub, counter, pctxt->state);
13107                 } else {
13108                     if ((sub->minOccurs == 1) &&
13109                         (sub->maxOccurs == 1)) {
13110                         xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
13111                                                 pctxt->state,
13112                                                 elemDecl->name,
13113                                                 elemDecl->targetNamespace,
13114                                                 1, 1, elemDecl);
13115                     } else if ((sub->minOccurs == 0) &&
13116                         (sub->maxOccurs == 1)) {
13117
13118                         xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
13119                                                  pctxt->state,
13120                                                  elemDecl->name,
13121                                                  elemDecl->targetNamespace,
13122                                                  0,
13123                                                  1,
13124                                                  elemDecl);
13125                     }
13126                 }
13127                 sub = (xmlSchemaParticlePtr) sub->next;
13128             }
13129             pctxt->state =
13130                 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0);
13131             if (particle->minOccurs == 0) {
13132                 xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state);
13133                 ret = 1;
13134             }
13135             break;
13136         }
13137         case XML_SCHEMA_TYPE_GROUP:
13138             /*
13139             * If we hit a model group definition, then this means that
13140             * it was empty, thus was not substituted for the containing
13141             * model group. Just do nothing in this case.
13142             * TODO: But the group should be substituted and not occur at
13143             * all in the content model at this point. Fix this.
13144             */
13145             ret = 1;
13146             break;
13147         default:
13148             xmlSchemaInternalErr2(ACTXT_CAST pctxt,
13149                 "xmlSchemaBuildAContentModel",
13150                 "found unexpected term of type '%s' in content model",
13151                 WXS_ITEM_TYPE_NAME(particle->children), NULL);
13152             return(ret);
13153     }
13154     return(ret);
13155 }
13156
13157 /**
13158  * xmlSchemaBuildContentModel:
13159  * @ctxt:  the schema parser context
13160  * @type:  the complex type definition
13161  * @name:  the element name
13162  *
13163  * Builds the content model of the complex type.
13164  */
13165 static void
13166 xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
13167                            xmlSchemaParserCtxtPtr ctxt)
13168 {
13169     if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13170         (type->contModel != NULL) ||
13171         ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13172         (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
13173         return;
13174
13175 #ifdef DEBUG_CONTENT
13176     xmlGenericError(xmlGenericErrorContext,
13177                     "Building content model for %s\n", name);
13178 #endif
13179     ctxt->am = NULL;
13180     ctxt->am = xmlNewAutomata();
13181     if (ctxt->am == NULL) {
13182         xmlGenericError(xmlGenericErrorContext,
13183             "Cannot create automata for complex type %s\n", type->name);
13184         return;
13185     }
13186     ctxt->state = xmlAutomataGetInitState(ctxt->am);
13187     /*
13188     * Build the automaton.
13189     */
13190     xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
13191     xmlAutomataSetFinalState(ctxt->am, ctxt->state);
13192     type->contModel = xmlAutomataCompile(ctxt->am);
13193     if (type->contModel == NULL) {
13194         xmlSchemaPCustomErr(ctxt,
13195             XML_SCHEMAP_INTERNAL,
13196             WXS_BASIC_CAST type, type->node,
13197             "Failed to compile the content model", NULL);
13198     } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
13199         xmlSchemaPCustomErr(ctxt,
13200             XML_SCHEMAP_NOT_DETERMINISTIC,
13201             /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
13202             WXS_BASIC_CAST type, type->node,
13203             "The content model is not determinist", NULL);
13204     } else {
13205 #ifdef DEBUG_CONTENT_REGEXP
13206         xmlGenericError(xmlGenericErrorContext,
13207                         "Content model of %s:\n", type->name);
13208         xmlRegexpPrint(stderr, type->contModel);
13209 #endif
13210     }
13211     ctxt->state = NULL;
13212     xmlFreeAutomata(ctxt->am);
13213     ctxt->am = NULL;
13214 }
13215
13216 /**
13217  * xmlSchemaResolveElementReferences:
13218  * @elem:  the schema element context
13219  * @ctxt:  the schema parser context
13220  *
13221  * Resolves the references of an element declaration
13222  * or particle, which has an element declaration as it's
13223  * term.
13224  */
13225 static void
13226 xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13227                                   xmlSchemaParserCtxtPtr ctxt)
13228 {
13229     if ((ctxt == NULL) || (elemDecl == NULL) ||
13230         ((elemDecl != NULL) &&
13231         (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
13232         return;
13233     elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
13234
13235     if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
13236         xmlSchemaTypePtr type;
13237
13238         /* (type definition) ... otherwise the type definition `resolved`
13239         * to by the `actual value` of the type [attribute] ...
13240         */
13241         type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
13242             elemDecl->namedTypeNs);
13243         if (type == NULL) {
13244             xmlSchemaPResCompAttrErr(ctxt,
13245                 XML_SCHEMAP_SRC_RESOLVE,
13246                 WXS_BASIC_CAST elemDecl, elemDecl->node,
13247                 "type", elemDecl->namedType, elemDecl->namedTypeNs,
13248                 XML_SCHEMA_TYPE_BASIC, "type definition");
13249         } else
13250             elemDecl->subtypes = type;
13251     }
13252     if (elemDecl->substGroup != NULL) {
13253         xmlSchemaElementPtr substHead;
13254
13255         /*
13256         * FIXME TODO: Do we need a new field in _xmlSchemaElement for
13257         * substitutionGroup?
13258         */
13259         substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13260             elemDecl->substGroupNs);
13261         if (substHead == NULL) {
13262             xmlSchemaPResCompAttrErr(ctxt,
13263                 XML_SCHEMAP_SRC_RESOLVE,
13264                 WXS_BASIC_CAST elemDecl, NULL,
13265                 "substitutionGroup", elemDecl->substGroup,
13266                 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
13267         } else {
13268             xmlSchemaResolveElementReferences(substHead, ctxt);
13269             /*
13270             * Set the "substitution group affiliation".
13271             * NOTE that now we use the "refDecl" field for this.
13272             */
13273             WXS_SUBST_HEAD(elemDecl) = substHead;
13274             /*
13275             * The type definitions is set to:
13276             * SPEC "...the {type definition} of the element
13277             * declaration `resolved` to by the `actual value`
13278             * of the substitutionGroup [attribute], if present"
13279             */
13280             if (elemDecl->subtypes == NULL)
13281                 elemDecl->subtypes = substHead->subtypes;
13282         }
13283     }
13284     /*
13285     * SPEC "The definition of anyType serves as the default type definition
13286     * for element declarations whose XML representation does not specify one."
13287     */
13288     if ((elemDecl->subtypes == NULL) &&
13289         (elemDecl->namedType == NULL) &&
13290         (elemDecl->substGroup == NULL))
13291         elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13292 }
13293
13294 /**
13295  * xmlSchemaResolveUnionMemberTypes:
13296  * @ctxt:  the schema parser context
13297  * @type:  the schema simple type definition
13298  *
13299  * Checks and builds the "member type definitions" property of the union
13300  * simple type. This handles part (1), part (2) is done in
13301  * xmlSchemaFinishMemberTypeDefinitionsProperty()
13302  *
13303  * Returns -1 in case of an internal error, 0 otherwise.
13304  */
13305 static int
13306 xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13307                                  xmlSchemaTypePtr type)
13308 {
13309
13310     xmlSchemaTypeLinkPtr link, lastLink, newLink;
13311     xmlSchemaTypePtr memberType;
13312
13313     /*
13314     * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13315     * define the explicit members as the type definitions `resolved`
13316     * to by the items in the `actual value` of the memberTypes [attribute],
13317     * if any, followed by the type definitions corresponding to the
13318     * <simpleType>s among the [children] of <union>, if any."
13319     */
13320     /*
13321     * Resolve references.
13322     */
13323     link = type->memberTypes;
13324     lastLink = NULL;
13325     while (link != NULL) {
13326         const xmlChar *name, *nsName;
13327
13328         name = ((xmlSchemaQNameRefPtr) link->type)->name;
13329         nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13330
13331         memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
13332         if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
13333             xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
13334                 WXS_BASIC_CAST type, type->node, "memberTypes",
13335                 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13336             /*
13337             * Remove the member type link.
13338             */
13339             if (lastLink == NULL)
13340                 type->memberTypes = link->next;
13341             else
13342                 lastLink->next = link->next;
13343             newLink = link;
13344             link = link->next;
13345             xmlFree(newLink);
13346         } else {
13347             link->type = memberType;
13348             lastLink = link;
13349             link = link->next;
13350         }
13351     }
13352     /*
13353     * Add local simple types,
13354     */
13355     memberType = type->subtypes;
13356     while (memberType != NULL) {
13357         link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13358         if (link == NULL) {
13359             xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13360             return (-1);
13361         }
13362         link->type = memberType;
13363         link->next = NULL;
13364         if (lastLink == NULL)
13365             type->memberTypes = link;
13366         else
13367             lastLink->next = link;
13368         lastLink = link;
13369         memberType = memberType->next;
13370     }
13371     return (0);
13372 }
13373
13374 /**
13375  * xmlSchemaIsDerivedFromBuiltInType:
13376  * @ctxt:  the schema parser context
13377  * @type:  the type definition
13378  * @valType: the value type
13379  *
13380  *
13381  * Returns 1 if the type has the given value type, or
13382  * is derived from such a type.
13383  */
13384 static int
13385 xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13386 {
13387     if (type == NULL)
13388         return (0);
13389     if (WXS_IS_COMPLEX(type))
13390         return (0);
13391     if (type->type == XML_SCHEMA_TYPE_BASIC) {
13392         if (type->builtInType == valType)
13393             return(1);
13394         if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13395             (type->builtInType == XML_SCHEMAS_ANYTYPE))
13396             return (0);
13397         return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13398     }
13399     return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13400 }
13401
13402 #if 0
13403 /**
13404  * xmlSchemaIsDerivedFromBuiltInType:
13405  * @ctxt:  the schema parser context
13406  * @type:  the type definition
13407  * @valType: the value type
13408  *
13409  *
13410  * Returns 1 if the type has the given value type, or
13411  * is derived from such a type.
13412  */
13413 static int
13414 xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13415 {
13416     if (type == NULL)
13417         return (0);
13418     if (WXS_IS_COMPLEX(type))
13419         return (0);
13420     if (type->type == XML_SCHEMA_TYPE_BASIC) {
13421         if (type->builtInType == valType)
13422             return(1);
13423         return (0);
13424     } else
13425         return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13426
13427     return (0);
13428 }
13429
13430 static xmlSchemaTypePtr
13431 xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13432 {
13433     if (type == NULL)
13434         return (NULL);
13435     if (WXS_IS_COMPLEX(type))
13436         return (NULL);
13437     if (type->type == XML_SCHEMA_TYPE_BASIC)
13438         return(type);
13439     return(xmlSchemaQueryBuiltInType(type->subtypes));
13440 }
13441 #endif
13442
13443 /**
13444  * xmlSchemaGetPrimitiveType:
13445  * @type:  the simpleType definition
13446  *
13447  * Returns the primitive type of the given type or
13448  * NULL in case of error.
13449  */
13450 static xmlSchemaTypePtr
13451 xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13452 {
13453
13454     while (type != NULL) {
13455         /*
13456         * Note that anySimpleType is actually not a primitive type
13457         * but we need that here.
13458         */
13459         if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13460            (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
13461             return (type);
13462         type = type->baseType;
13463     }
13464
13465     return (NULL);
13466 }
13467
13468 #if 0
13469 /**
13470  * xmlSchemaGetBuiltInTypeAncestor:
13471  * @type:  the simpleType definition
13472  *
13473  * Returns the primitive type of the given type or
13474  * NULL in case of error.
13475  */
13476 static xmlSchemaTypePtr
13477 xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13478 {
13479     if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
13480         return (0);
13481     while (type != NULL) {
13482         if (type->type == XML_SCHEMA_TYPE_BASIC)
13483             return (type);
13484         type = type->baseType;
13485     }
13486
13487     return (NULL);
13488 }
13489 #endif
13490
13491 /**
13492  * xmlSchemaCloneWildcardNsConstraints:
13493  * @ctxt:  the schema parser context
13494  * @dest:  the destination wildcard
13495  * @source: the source wildcard
13496  *
13497  * Clones the namespace constraints of source
13498  * and assignes them to dest.
13499  * Returns -1 on internal error, 0 otherwise.
13500  */
13501 static int
13502 xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
13503                                     xmlSchemaWildcardPtr dest,
13504                                     xmlSchemaWildcardPtr source)
13505 {
13506     xmlSchemaWildcardNsPtr cur, tmp, last;
13507
13508     if ((source == NULL) || (dest == NULL))
13509         return(-1);
13510     dest->any = source->any;
13511     cur = source->nsSet;
13512     last = NULL;
13513     while (cur != NULL) {
13514         tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13515         if (tmp == NULL)
13516             return(-1);
13517         tmp->value = cur->value;
13518         if (last == NULL)
13519             dest->nsSet = tmp;
13520         else
13521             last->next = tmp;
13522         last = tmp;
13523         cur = cur->next;
13524     }
13525     if (dest->negNsSet != NULL)
13526         xmlSchemaFreeWildcardNsSet(dest->negNsSet);
13527     if (source->negNsSet != NULL) {
13528         dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13529         if (dest->negNsSet == NULL)
13530             return(-1);
13531         dest->negNsSet->value = source->negNsSet->value;
13532     } else
13533         dest->negNsSet = NULL;
13534     return(0);
13535 }
13536
13537 /**
13538  * xmlSchemaUnionWildcards:
13539  * @ctxt:  the schema parser context
13540  * @completeWild:  the first wildcard
13541  * @curWild: the second wildcard
13542  *
13543  * Unions the namespace constraints of the given wildcards.
13544  * @completeWild will hold the resulting union.
13545  * Returns a positive error code on failure, -1 in case of an
13546  * internal error, 0 otherwise.
13547  */
13548 static int
13549 xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
13550                             xmlSchemaWildcardPtr completeWild,
13551                             xmlSchemaWildcardPtr curWild)
13552 {
13553     xmlSchemaWildcardNsPtr cur, curB, tmp;
13554
13555     /*
13556     * 1 If O1 and O2 are the same value, then that value must be the
13557     * value.
13558     */
13559     if ((completeWild->any == curWild->any) &&
13560         ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13561         ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13562
13563         if ((completeWild->negNsSet == NULL) ||
13564             (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13565
13566             if (completeWild->nsSet != NULL) {
13567                 int found = 0;
13568
13569                 /*
13570                 * Check equality of sets.
13571                 */
13572                 cur = completeWild->nsSet;
13573                 while (cur != NULL) {
13574                     found = 0;
13575                     curB = curWild->nsSet;
13576                     while (curB != NULL) {
13577                         if (cur->value == curB->value) {
13578                             found = 1;
13579                             break;
13580                         }
13581                         curB = curB->next;
13582                     }
13583                     if (!found)
13584                         break;
13585                     cur = cur->next;
13586                 }
13587                 if (found)
13588                     return(0);
13589             } else
13590                 return(0);
13591         }
13592     }
13593     /*
13594     * 2 If either O1 or O2 is any, then any must be the value
13595     */
13596     if (completeWild->any != curWild->any) {
13597         if (completeWild->any == 0) {
13598             completeWild->any = 1;
13599             if (completeWild->nsSet != NULL) {
13600                 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13601                 completeWild->nsSet = NULL;
13602             }
13603             if (completeWild->negNsSet != NULL) {
13604                 xmlFree(completeWild->negNsSet);
13605                 completeWild->negNsSet = NULL;
13606             }
13607         }
13608         return (0);
13609     }
13610     /*
13611     * 3 If both O1 and O2 are sets of (namespace names or `absent`),
13612     * then the union of those sets must be the value.
13613     */
13614     if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13615         int found;
13616         xmlSchemaWildcardNsPtr start;
13617
13618         cur = curWild->nsSet;
13619         start = completeWild->nsSet;
13620         while (cur != NULL) {
13621             found = 0;
13622             curB = start;
13623             while (curB != NULL) {
13624                 if (cur->value == curB->value) {
13625                     found = 1;
13626                     break;
13627                 }
13628                 curB = curB->next;
13629             }
13630             if (!found) {
13631                 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13632                 if (tmp == NULL)
13633                     return (-1);
13634                 tmp->value = cur->value;
13635                 tmp->next = completeWild->nsSet;
13636                 completeWild->nsSet = tmp;
13637             }
13638             cur = cur->next;
13639         }
13640
13641         return(0);
13642     }
13643     /*
13644     * 4 If the two are negations of different values (namespace names
13645     * or `absent`), then a pair of not and `absent` must be the value.
13646     */
13647     if ((completeWild->negNsSet != NULL) &&
13648         (curWild->negNsSet != NULL) &&
13649         (completeWild->negNsSet->value != curWild->negNsSet->value)) {
13650         completeWild->negNsSet->value = NULL;
13651
13652         return(0);
13653     }
13654     /*
13655      * 5.
13656      */
13657     if (((completeWild->negNsSet != NULL) &&
13658         (completeWild->negNsSet->value != NULL) &&
13659         (curWild->nsSet != NULL)) ||
13660         ((curWild->negNsSet != NULL) &&
13661         (curWild->negNsSet->value != NULL) &&
13662         (completeWild->nsSet != NULL))) {
13663
13664         int nsFound, absentFound = 0;
13665
13666         if (completeWild->nsSet != NULL) {
13667             cur = completeWild->nsSet;
13668             curB = curWild->negNsSet;
13669         } else {
13670             cur = curWild->nsSet;
13671             curB = completeWild->negNsSet;
13672         }
13673         nsFound = 0;
13674         while (cur != NULL) {
13675             if (cur->value == NULL)
13676                 absentFound = 1;
13677             else if (cur->value == curB->value)
13678                 nsFound = 1;
13679             if (nsFound && absentFound)
13680                 break;
13681             cur = cur->next;
13682         }
13683
13684         if (nsFound && absentFound) {
13685             /*
13686             * 5.1 If the set S includes both the negated namespace
13687             * name and `absent`, then any must be the value.
13688             */
13689             completeWild->any = 1;
13690             if (completeWild->nsSet != NULL) {
13691                 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13692                 completeWild->nsSet = NULL;
13693             }
13694             if (completeWild->negNsSet != NULL) {
13695                 xmlFree(completeWild->negNsSet);
13696                 completeWild->negNsSet = NULL;
13697             }
13698         } else if (nsFound && (!absentFound)) {
13699             /*
13700             * 5.2 If the set S includes the negated namespace name
13701             * but not `absent`, then a pair of not and `absent` must
13702             * be the value.
13703             */
13704             if (completeWild->nsSet != NULL) {
13705                 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13706                 completeWild->nsSet = NULL;
13707             }
13708             if (completeWild->negNsSet == NULL) {
13709                 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13710                 if (completeWild->negNsSet == NULL)
13711                     return (-1);
13712             }
13713             completeWild->negNsSet->value = NULL;
13714         } else if ((!nsFound) && absentFound) {
13715             /*
13716             * 5.3 If the set S includes `absent` but not the negated
13717             * namespace name, then the union is not expressible.
13718             */
13719             xmlSchemaPErr(ctxt, completeWild->node,
13720                 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
13721                 "The union of the wilcard is not expressible.\n",
13722                 NULL, NULL);
13723             return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
13724         } else if ((!nsFound) && (!absentFound)) {
13725             /*
13726             * 5.4 If the set S does not include either the negated namespace
13727             * name or `absent`, then whichever of O1 or O2 is a pair of not
13728             * and a namespace name must be the value.
13729             */
13730             if (completeWild->negNsSet == NULL) {
13731                 if (completeWild->nsSet != NULL) {
13732                     xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13733                     completeWild->nsSet = NULL;
13734                 }
13735                 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13736                 if (completeWild->negNsSet == NULL)
13737                     return (-1);
13738                 completeWild->negNsSet->value = curWild->negNsSet->value;
13739             }
13740         }
13741         return (0);
13742     }
13743     /*
13744      * 6.
13745      */
13746     if (((completeWild->negNsSet != NULL) &&
13747         (completeWild->negNsSet->value == NULL) &&
13748         (curWild->nsSet != NULL)) ||
13749         ((curWild->negNsSet != NULL) &&
13750         (curWild->negNsSet->value == NULL) &&
13751         (completeWild->nsSet != NULL))) {
13752
13753         if (completeWild->nsSet != NULL) {
13754             cur = completeWild->nsSet;
13755         } else {
13756             cur = curWild->nsSet;
13757         }
13758         while (cur != NULL) {
13759             if (cur->value == NULL) {
13760                 /*
13761                 * 6.1 If the set S includes `absent`, then any must be the
13762                 * value.
13763                 */
13764                 completeWild->any = 1;
13765                 if (completeWild->nsSet != NULL) {
13766                     xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13767                     completeWild->nsSet = NULL;
13768                 }
13769                 if (completeWild->negNsSet != NULL) {
13770                     xmlFree(completeWild->negNsSet);
13771                     completeWild->negNsSet = NULL;
13772                 }
13773                 return (0);
13774             }
13775             cur = cur->next;
13776         }
13777         if (completeWild->negNsSet == NULL) {
13778             /*
13779             * 6.2 If the set S does not include `absent`, then a pair of not
13780             * and `absent` must be the value.
13781             */
13782             if (completeWild->nsSet != NULL) {
13783                 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13784                 completeWild->nsSet = NULL;
13785             }
13786             completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13787             if (completeWild->negNsSet == NULL)
13788                 return (-1);
13789             completeWild->negNsSet->value = NULL;
13790         }
13791         return (0);
13792     }
13793     return (0);
13794
13795 }
13796
13797 /**
13798  * xmlSchemaIntersectWildcards:
13799  * @ctxt:  the schema parser context
13800  * @completeWild:  the first wildcard
13801  * @curWild: the second wildcard
13802  *
13803  * Intersects the namespace constraints of the given wildcards.
13804  * @completeWild will hold the resulting intersection.
13805  * Returns a positive error code on failure, -1 in case of an
13806  * internal error, 0 otherwise.
13807  */
13808 static int
13809 xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
13810                             xmlSchemaWildcardPtr completeWild,
13811                             xmlSchemaWildcardPtr curWild)
13812 {
13813     xmlSchemaWildcardNsPtr cur, curB, prev,  tmp;
13814
13815     /*
13816     * 1 If O1 and O2 are the same value, then that value must be the
13817     * value.
13818     */
13819     if ((completeWild->any == curWild->any) &&
13820         ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13821         ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13822
13823         if ((completeWild->negNsSet == NULL) ||
13824             (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13825
13826             if (completeWild->nsSet != NULL) {
13827                 int found = 0;
13828
13829                 /*
13830                 * Check equality of sets.
13831                 */
13832                 cur = completeWild->nsSet;
13833                 while (cur != NULL) {
13834                     found = 0;
13835                     curB = curWild->nsSet;
13836                     while (curB != NULL) {
13837                         if (cur->value == curB->value) {
13838                             found = 1;
13839                             break;
13840                         }
13841                         curB = curB->next;
13842                     }
13843                     if (!found)
13844                         break;
13845                     cur = cur->next;
13846                 }
13847                 if (found)
13848                     return(0);
13849             } else
13850                 return(0);
13851         }
13852     }
13853     /*
13854     * 2 If either O1 or O2 is any, then the other must be the value.
13855     */
13856     if ((completeWild->any != curWild->any) && (completeWild->any)) {
13857         if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13858             return(-1);
13859         return(0);
13860     }
13861     /*
13862     * 3 If either O1 or O2 is a pair of not and a value (a namespace
13863     * name or `absent`) and the other is a set of (namespace names or
13864     * `absent`), then that set, minus the negated value if it was in
13865     * the set, minus `absent` if it was in the set, must be the value.
13866     */
13867     if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13868         ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13869         const xmlChar *neg;
13870
13871         if (completeWild->nsSet == NULL) {
13872             neg = completeWild->negNsSet->value;
13873             if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13874                 return(-1);
13875         } else
13876             neg = curWild->negNsSet->value;
13877         /*
13878         * Remove absent and negated.
13879         */
13880         prev = NULL;
13881         cur = completeWild->nsSet;
13882         while (cur != NULL) {
13883             if (cur->value == NULL) {
13884                 if (prev == NULL)
13885                     completeWild->nsSet = cur->next;
13886                 else
13887                     prev->next = cur->next;
13888                 xmlFree(cur);
13889                 break;
13890             }
13891             prev = cur;
13892             cur = cur->next;
13893         }
13894         if (neg != NULL) {
13895             prev = NULL;
13896             cur = completeWild->nsSet;
13897             while (cur != NULL) {
13898                 if (cur->value == neg) {
13899                     if (prev == NULL)
13900                         completeWild->nsSet = cur->next;
13901                     else
13902                         prev->next = cur->next;
13903                     xmlFree(cur);
13904                     break;
13905                 }
13906                 prev = cur;
13907                 cur = cur->next;
13908             }
13909         }
13910
13911         return(0);
13912     }
13913     /*
13914     * 4 If both O1 and O2 are sets of (namespace names or `absent`),
13915     * then the intersection of those sets must be the value.
13916     */
13917     if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13918         int found;
13919
13920         cur = completeWild->nsSet;
13921         prev = NULL;
13922         while (cur != NULL) {
13923             found = 0;
13924             curB = curWild->nsSet;
13925             while (curB != NULL) {
13926                 if (cur->value == curB->value) {
13927                     found = 1;
13928                     break;
13929                 }
13930                 curB = curB->next;
13931             }
13932             if (!found) {
13933                 if (prev == NULL)
13934                     completeWild->nsSet = cur->next;
13935                 else
13936                     prev->next = cur->next;
13937                 tmp = cur->next;
13938                 xmlFree(cur);
13939                 cur = tmp;
13940                 continue;
13941             }
13942             prev = cur;
13943             cur = cur->next;
13944         }
13945
13946         return(0);
13947     }
13948     /* 5 If the two are negations of different namespace names,
13949     * then the intersection is not expressible
13950     */
13951     if ((completeWild->negNsSet != NULL) &&
13952         (curWild->negNsSet != NULL) &&
13953         (completeWild->negNsSet->value != curWild->negNsSet->value) &&
13954         (completeWild->negNsSet->value != NULL) &&
13955         (curWild->negNsSet->value != NULL)) {
13956
13957         xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
13958             "The intersection of the wilcard is not expressible.\n",
13959             NULL, NULL);
13960         return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
13961     }
13962     /*
13963     * 6 If the one is a negation of a namespace name and the other
13964     * is a negation of `absent`, then the one which is the negation
13965     * of a namespace name must be the value.
13966     */
13967     if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
13968         (completeWild->negNsSet->value != curWild->negNsSet->value) &&
13969         (completeWild->negNsSet->value == NULL)) {
13970         completeWild->negNsSet->value =  curWild->negNsSet->value;
13971     }
13972     return(0);
13973 }
13974
13975 /**
13976  * xmlSchemaIsWildcardNsConstraintSubset:
13977  * @ctxt:  the schema parser context
13978  * @sub:  the first wildcard
13979  * @super: the second wildcard
13980  *
13981  * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
13982  *
13983  * Returns 0 if the namespace constraint of @sub is an intensional
13984  * subset of @super, 1 otherwise.
13985  */
13986 static int
13987 xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
13988                           xmlSchemaWildcardPtr super)
13989 {
13990     /*
13991     * 1 super must be any.
13992     */
13993     if (super->any)
13994         return (0);
13995     /*
13996     * 2.1 sub must be a pair of not and a namespace name or `absent`.
13997     * 2.2 super must be a pair of not and the same value.
13998     */
13999     if ((sub->negNsSet != NULL) &&
14000         (super->negNsSet != NULL) &&
14001         (sub->negNsSet->value == super->negNsSet->value))
14002         return (0);
14003     /*
14004     * 3.1 sub must be a set whose members are either namespace names or `absent`.
14005     */
14006     if (sub->nsSet != NULL) {
14007         /*
14008         * 3.2.1 super must be the same set or a superset thereof.
14009         */
14010         if (super->nsSet != NULL) {
14011             xmlSchemaWildcardNsPtr cur, curB;
14012             int found = 0;
14013
14014             cur = sub->nsSet;
14015             while (cur != NULL) {
14016                 found = 0;
14017                 curB = super->nsSet;
14018                 while (curB != NULL) {
14019                     if (cur->value == curB->value) {
14020                         found = 1;
14021                         break;
14022                     }
14023                     curB = curB->next;
14024                 }
14025                 if (!found)
14026                     return (1);
14027                 cur = cur->next;
14028             }
14029             if (found)
14030                 return (0);
14031         } else if (super->negNsSet != NULL) {
14032             xmlSchemaWildcardNsPtr cur;
14033             /*
14034             * 3.2.2 super must be a pair of not and a namespace name or
14035             * `absent` and that value must not be in sub's set.
14036             */
14037             cur = sub->nsSet;
14038             while (cur != NULL) {
14039                 if (cur->value == super->negNsSet->value)
14040                     return (1);
14041                 cur = cur->next;
14042             }
14043             return (0);
14044         }
14045     }
14046     return (1);
14047 }
14048
14049 static int
14050 xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
14051                                      int *fixed,
14052                                      const xmlChar **value,
14053                                      xmlSchemaValPtr *val)
14054 {
14055     *fixed = 0;
14056     *value = NULL;
14057     if (val != 0)
14058         *val = NULL;
14059
14060     if (attruse->defValue != NULL) {
14061         *value = attruse->defValue;
14062         if (val != NULL)
14063             *val = attruse->defVal;
14064         if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
14065             *fixed = 1;
14066         return(1);
14067     } else if ((attruse->attrDecl != NULL) &&
14068         (attruse->attrDecl->defValue != NULL)) {
14069         *value = attruse->attrDecl->defValue;
14070         if (val != NULL)
14071             *val = attruse->attrDecl->defVal;
14072         if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
14073             *fixed = 1;
14074         return(1);
14075     }
14076     return(0);
14077 }
14078 /**
14079  * xmlSchemaCheckCVCWildcardNamespace:
14080  * @wild:  the wildcard
14081  * @ns:  the namespace
14082  *
14083  * Validation Rule: Wildcard allows Namespace Name
14084  * (cvc-wildcard-namespace)
14085  *
14086  * Returns 0 if the given namespace matches the wildcard,
14087  * 1 otherwise and -1 on API errors.
14088  */
14089 static int
14090 xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
14091                                    const xmlChar* ns)
14092 {
14093     if (wild == NULL)
14094         return(-1);
14095
14096     if (wild->any)
14097         return(0);
14098     else if (wild->nsSet != NULL) {
14099         xmlSchemaWildcardNsPtr cur;
14100
14101         cur = wild->nsSet;
14102         while (cur != NULL) {
14103             if (xmlStrEqual(cur->value, ns))
14104                 return(0);
14105             cur = cur->next;
14106         }
14107     } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
14108         (!xmlStrEqual(wild->negNsSet->value, ns)))
14109         return(0);
14110
14111     return(1);
14112 }
14113
14114 #define XML_SCHEMA_ACTION_DERIVE 0
14115 #define XML_SCHEMA_ACTION_REDEFINE 1
14116
14117 #define WXS_ACTION_STR(a) \
14118 ((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
14119
14120 /*
14121 * Schema Component Constraint:
14122 *   Derivation Valid (Restriction, Complex)
14123 *   derivation-ok-restriction (2) - (4)
14124 *
14125 * ATTENTION:
14126 * In XML Schema 1.1 this will be:
14127 * Validation Rule:
14128 *     Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
14129 *
14130 */
14131 static int
14132 xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
14133                                        int action,
14134                                        xmlSchemaBasicItemPtr item,
14135                                        xmlSchemaBasicItemPtr baseItem,
14136                                        xmlSchemaItemListPtr uses,
14137                                        xmlSchemaItemListPtr baseUses,
14138                                        xmlSchemaWildcardPtr wild,
14139                                        xmlSchemaWildcardPtr baseWild)
14140 {
14141     xmlSchemaAttributeUsePtr cur = NULL, bcur;
14142     int i, j, found; /* err = 0; */
14143     const xmlChar *bEffValue;
14144     int effFixed;
14145
14146     if (uses != NULL) {
14147         for (i = 0; i < uses->nbItems; i++) {
14148             cur = uses->items[i];
14149             found = 0;
14150             if (baseUses == NULL)
14151                 goto not_found;
14152             for (j = 0; j < baseUses->nbItems; j++) {
14153                 bcur = baseUses->items[j];
14154                 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14155                         WXS_ATTRUSE_DECL_NAME(bcur)) &&
14156                     (WXS_ATTRUSE_DECL_TNS(cur) ==
14157                         WXS_ATTRUSE_DECL_TNS(bcur)))
14158                 {
14159                     /*
14160                     * (2.1) "If there is an attribute use in the {attribute
14161                     * uses} of the {base type definition} (call this B) whose
14162                     * {attribute declaration} has the same {name} and {target
14163                     * namespace}, then  all of the following must be true:"
14164                     */
14165                     found = 1;
14166
14167                     if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14168                         (bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14169                     {
14170                         xmlChar *str = NULL;
14171                         /*
14172                         * (2.1.1) "one of the following must be true:"
14173                         * (2.1.1.1) "B's {required} is false."
14174                         * (2.1.1.2) "R's {required} is true."
14175                         */
14176                         xmlSchemaPAttrUseErr4(pctxt,
14177                             XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14178                             WXS_ITEM_NODE(item), item, cur,
14179                             "The 'optional' attribute use is inconsistent "
14180                             "with the corresponding 'required' attribute use of "
14181                             "the %s %s",
14182                             WXS_ACTION_STR(action),
14183                             xmlSchemaGetComponentDesignation(&str, baseItem),
14184                             NULL, NULL);
14185                         FREE_AND_NULL(str);
14186                         /* err = pctxt->err; */
14187                     } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
14188                         WXS_ATTRUSE_TYPEDEF(cur),
14189                         WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14190                     {
14191                         xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14192
14193                         /*
14194                         * SPEC (2.1.2) "R's {attribute declaration}'s
14195                         * {type definition} must be validly derived from
14196                         * B's {type definition} given the empty set as
14197                         * defined in Type Derivation OK (Simple) ($3.14.6)."
14198                         */
14199                         xmlSchemaPAttrUseErr4(pctxt,
14200                             XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14201                             WXS_ITEM_NODE(item), item, cur,
14202                             "The attribute declaration's %s "
14203                             "is not validly derived from "
14204                             "the corresponding %s of the "
14205                             "attribute declaration in the %s %s",
14206                             xmlSchemaGetComponentDesignation(&strA,
14207                                 WXS_ATTRUSE_TYPEDEF(cur)),
14208                             xmlSchemaGetComponentDesignation(&strB,
14209                                 WXS_ATTRUSE_TYPEDEF(bcur)),
14210                             WXS_ACTION_STR(action),
14211                             xmlSchemaGetComponentDesignation(&strC, baseItem));
14212                             /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14213                         FREE_AND_NULL(strA);
14214                         FREE_AND_NULL(strB);
14215                         FREE_AND_NULL(strC);
14216                         /* err = pctxt->err; */
14217                     } else {
14218                         /*
14219                         * 2.1.3 [Definition:]  Let the effective value
14220                         * constraint of an attribute use be its {value
14221                         * constraint}, if present, otherwise its {attribute
14222                         * declaration}'s {value constraint} .
14223                         */
14224                         xmlSchemaGetEffectiveValueConstraint(bcur,
14225                             &effFixed, &bEffValue, NULL);
14226                         /*
14227                         * 2.1.3 ... one of the following must be true
14228                         *
14229                         * 2.1.3.1 B's `effective value constraint` is
14230                         * `absent` or default.
14231                         */
14232                         if ((bEffValue != NULL) &&
14233                             (effFixed == 1)) {
14234                             const xmlChar *rEffValue = NULL;
14235
14236                             xmlSchemaGetEffectiveValueConstraint(bcur,
14237                                 &effFixed, &rEffValue, NULL);
14238                             /*
14239                             * 2.1.3.2 R's `effective value constraint` is
14240                             * fixed with the same string as B's.
14241                             * MAYBE TODO: Compare the computed values.
14242                             *       Hmm, it says "same string" so
14243                             *       string-equality might really be sufficient.
14244                             */
14245                             if ((effFixed == 0) ||
14246                                 (! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14247                             {
14248                                 xmlChar *str = NULL;
14249
14250                                 xmlSchemaPAttrUseErr4(pctxt,
14251                                     XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14252                                     WXS_ITEM_NODE(item), item, cur,
14253                                     "The effective value constraint of the "
14254                                     "attribute use is inconsistent with "
14255                                     "its correspondent in the %s %s",
14256                                     WXS_ACTION_STR(action),
14257                                     xmlSchemaGetComponentDesignation(&str,
14258                                         baseItem),
14259                                     NULL, NULL);
14260                                 FREE_AND_NULL(str);
14261                                 /* err = pctxt->err; */
14262                             }
14263                         }
14264                     }
14265                     break;
14266                 }
14267             }
14268 not_found:
14269             if (!found) {
14270                 /*
14271                 * (2.2) "otherwise the {base type definition} must have an
14272                 * {attribute wildcard} and the {target namespace} of the
14273                 * R's {attribute declaration} must be `valid` with respect
14274                 * to that wildcard, as defined in Wildcard allows Namespace
14275                 * Name ($3.10.4)."
14276                 */
14277                 if ((baseWild == NULL) ||
14278                     (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14279                     (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14280                 {
14281                     xmlChar *str = NULL;
14282
14283                     xmlSchemaPAttrUseErr4(pctxt,
14284                         XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14285                         WXS_ITEM_NODE(item), item, cur,
14286                         "Neither a matching attribute use, "
14287                         "nor a matching wildcard exists in the %s %s",
14288                         WXS_ACTION_STR(action),
14289                         xmlSchemaGetComponentDesignation(&str, baseItem),
14290                         NULL, NULL);
14291                     FREE_AND_NULL(str);
14292                     /* err = pctxt->err; */
14293                 }
14294             }
14295         }
14296     }
14297     /*
14298     * SPEC derivation-ok-restriction (3):
14299     * (3) "For each attribute use in the {attribute uses} of the {base type
14300     * definition} whose {required} is true, there must be an attribute
14301     * use with an {attribute declaration} with the same {name} and
14302     * {target namespace} as its {attribute declaration} in the {attribute
14303     * uses} of the complex type definition itself whose {required} is true.
14304     */
14305     if (baseUses != NULL) {
14306         for (j = 0; j < baseUses->nbItems; j++) {
14307             bcur = baseUses->items[j];
14308             if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14309                 continue;
14310             found = 0;
14311             if (uses != NULL) {
14312                 for (i = 0; i < uses->nbItems; i++) {
14313                     cur = uses->items[i];
14314                     if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14315                         WXS_ATTRUSE_DECL_NAME(bcur)) &&
14316                         (WXS_ATTRUSE_DECL_TNS(cur) ==
14317                         WXS_ATTRUSE_DECL_TNS(bcur))) {
14318                         found = 1;
14319                         break;
14320                     }
14321                 }
14322             }
14323             if (!found) {
14324                 xmlChar *strA = NULL, *strB = NULL;
14325
14326                 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14327                     XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14328                     NULL, item,
14329                     "A matching attribute use for the "
14330                     "'required' %s of the %s %s is missing",
14331                     xmlSchemaGetComponentDesignation(&strA, bcur),
14332                     WXS_ACTION_STR(action),
14333                     xmlSchemaGetComponentDesignation(&strB, baseItem),
14334                     NULL);
14335                 FREE_AND_NULL(strA);
14336                 FREE_AND_NULL(strB);
14337             }
14338         }
14339     }
14340     /*
14341     * derivation-ok-restriction (4)
14342     */
14343     if (wild != NULL) {
14344         /*
14345         * (4) "If there is an {attribute wildcard}, all of the
14346         * following must be true:"
14347         */
14348         if (baseWild == NULL) {
14349             xmlChar *str = NULL;
14350
14351             /*
14352             * (4.1) "The {base type definition} must also have one."
14353             */
14354             xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14355                 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14356                 NULL, item,
14357                 "The %s has an attribute wildcard, "
14358                 "but the %s %s '%s' does not have one",
14359                 WXS_ITEM_TYPE_NAME(item),
14360                 WXS_ACTION_STR(action),
14361                 WXS_ITEM_TYPE_NAME(baseItem),
14362                 xmlSchemaGetComponentQName(&str, baseItem));
14363             FREE_AND_NULL(str);
14364             return(pctxt->err);
14365         } else if ((baseWild->any == 0) &&
14366                 xmlSchemaCheckCOSNSSubset(wild, baseWild))
14367         {
14368             xmlChar *str = NULL;
14369             /*
14370             * (4.2) "The complex type definition's {attribute wildcard}'s
14371             * {namespace constraint} must be a subset of the {base type
14372             * definition}'s {attribute wildcard}'s {namespace constraint},
14373             * as defined by Wildcard Subset ($3.10.6)."
14374             */
14375             xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14376                 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14377                 NULL, item,
14378                 "The attribute wildcard is not a valid "
14379                 "subset of the wildcard in the %s %s '%s'",
14380                 WXS_ACTION_STR(action),
14381                 WXS_ITEM_TYPE_NAME(baseItem),
14382                 xmlSchemaGetComponentQName(&str, baseItem),
14383                 NULL);
14384             FREE_AND_NULL(str);
14385             return(pctxt->err);
14386         }
14387         /* 4.3 Unless the {base type definition} is the `ur-type
14388         * definition`, the complex type definition's {attribute
14389         * wildcard}'s {process contents} must be identical to or
14390         * stronger than the {base type definition}'s {attribute
14391         * wildcard}'s {process contents}, where strict is stronger
14392         * than lax is stronger than skip.
14393         */
14394         if ((! WXS_IS_ANYTYPE(baseItem)) &&
14395             (wild->processContents < baseWild->processContents)) {
14396             xmlChar *str = NULL;
14397             xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14398                 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14399                 NULL, baseItem,
14400                 "The {process contents} of the attribute wildcard is "
14401                 "weaker than the one in the %s %s '%s'",
14402                 WXS_ACTION_STR(action),
14403                 WXS_ITEM_TYPE_NAME(baseItem),
14404                 xmlSchemaGetComponentQName(&str, baseItem),
14405                 NULL);
14406             FREE_AND_NULL(str)
14407                 return(pctxt->err);
14408         }
14409     }
14410     return(0);
14411 }
14412
14413
14414 static int
14415 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14416                                   xmlSchemaBasicItemPtr item,
14417                                   xmlSchemaWildcardPtr *completeWild,
14418                                   xmlSchemaItemListPtr list,
14419                                   xmlSchemaItemListPtr prohibs);
14420 /**
14421  * xmlSchemaFixupTypeAttributeUses:
14422  * @ctxt:  the schema parser context
14423  * @type:  the complex type definition
14424  *
14425  *
14426  * Builds the wildcard and the attribute uses on the given complex type.
14427  * Returns -1 if an internal error occurs, 0 otherwise.
14428  *
14429  * ATTENTION TODO: Experimantally this uses pointer comparisons for
14430  * strings, so recheck this if we start to hardcode some schemata, since
14431  * they might not be in the same dict.
14432  * NOTE: It is allowed to "extend" the xs:anyType type.
14433  */
14434 static int
14435 xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
14436                                   xmlSchemaTypePtr type)
14437 {
14438     xmlSchemaTypePtr baseType = NULL;
14439     xmlSchemaAttributeUsePtr use;
14440     xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
14441
14442     if (type->baseType == NULL) {
14443         PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14444             "no base type");
14445         return (-1);
14446     }
14447     baseType = type->baseType;
14448     if (WXS_IS_TYPE_NOT_FIXED(baseType))
14449         if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
14450             return(-1);
14451
14452     uses = type->attrUses;
14453     baseUses = baseType->attrUses;
14454     /*
14455     * Expand attribute group references. And build the 'complete'
14456     * wildcard, i.e. intersect multiple wildcards.
14457     * Move attribute prohibitions into a separate list.
14458     */
14459     if (uses != NULL) {
14460         if (WXS_IS_RESTRICTION(type)) {
14461             /*
14462             * This one will transfer all attr. prohibitions
14463             * into pctxt->attrProhibs.
14464             */
14465             if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14466                 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14467                 pctxt->attrProhibs) == -1)
14468             {
14469                 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14470                 "failed to expand attributes");
14471             }
14472             if (pctxt->attrProhibs->nbItems != 0)
14473                 prohibs = pctxt->attrProhibs;
14474         } else {
14475             if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14476                 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14477                 NULL) == -1)
14478             {
14479                 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14480                 "failed to expand attributes");
14481             }
14482         }
14483     }
14484     /*
14485     * Inherit the attribute uses of the base type.
14486     */
14487     if (baseUses != NULL) {
14488         int i, j;
14489         xmlSchemaAttributeUseProhibPtr pro;
14490
14491         if (WXS_IS_RESTRICTION(type)) {
14492             int usesCount;
14493             xmlSchemaAttributeUsePtr tmp;
14494
14495             if (uses != NULL)
14496                 usesCount = uses->nbItems;
14497             else
14498                 usesCount = 0;
14499
14500             /* Restriction. */
14501             for (i = 0; i < baseUses->nbItems; i++) {
14502                 use = baseUses->items[i];
14503                 if (prohibs) {
14504                     /*
14505                     * Filter out prohibited uses.
14506                     */
14507                     for (j = 0; j < prohibs->nbItems; j++) {
14508                         pro = prohibs->items[j];
14509                         if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14510                             (WXS_ATTRUSE_DECL_TNS(use) ==
14511                                 pro->targetNamespace))
14512                         {
14513                             goto inherit_next;
14514                         }
14515                     }
14516                 }
14517                 if (usesCount) {
14518                     /*
14519                     * Filter out existing uses.
14520                     */
14521                     for (j = 0; j < usesCount; j++) {
14522                         tmp = uses->items[j];
14523                         if ((WXS_ATTRUSE_DECL_NAME(use) ==
14524                                 WXS_ATTRUSE_DECL_NAME(tmp)) &&
14525                             (WXS_ATTRUSE_DECL_TNS(use) ==
14526                                 WXS_ATTRUSE_DECL_TNS(tmp)))
14527                         {
14528                             goto inherit_next;
14529                         }
14530                     }
14531                 }
14532                 if (uses == NULL) {
14533                     type->attrUses = xmlSchemaItemListCreate();
14534                     if (type->attrUses == NULL)
14535                         goto exit_failure;
14536                     uses = type->attrUses;
14537                 }
14538                 xmlSchemaItemListAddSize(uses, 2, use);
14539 inherit_next: {}
14540             }
14541         } else {
14542             /* Extension. */
14543             for (i = 0; i < baseUses->nbItems; i++) {
14544                 use = baseUses->items[i];
14545                 if (uses == NULL) {
14546                     type->attrUses = xmlSchemaItemListCreate();
14547                     if (type->attrUses == NULL)
14548                         goto exit_failure;
14549                     uses = type->attrUses;
14550                 }
14551                 xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14552             }
14553         }
14554     }
14555     /*
14556     * Shrink attr. uses.
14557     */
14558     if (uses) {
14559         if (uses->nbItems == 0) {
14560             xmlSchemaItemListFree(uses);
14561             type->attrUses = NULL;
14562         }
14563         /*
14564         * TODO: We could shrink the size of the array
14565         * to fit the actual number of items.
14566         */
14567     }
14568     /*
14569     * Compute the complete wildcard.
14570     */
14571     if (WXS_IS_EXTENSION(type)) {
14572         if (baseType->attributeWildcard != NULL) {
14573             /*
14574             * (3.2.2.1) "If the `base wildcard` is non-`absent`, then
14575             * the appropriate case among the following:"
14576             */
14577             if (type->attributeWildcard != NULL) {
14578                 /*
14579                 * Union the complete wildcard with the base wildcard.
14580                 * SPEC {attribute wildcard}
14581                 * (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14582                 * and {annotation} are those of the `complete wildcard`,
14583                 * and whose {namespace constraint} is the intensional union
14584                 * of the {namespace constraint} of the `complete wildcard`
14585                 * and of the `base wildcard`, as defined in Attribute
14586                 * Wildcard Union ($3.10.6)."
14587                 */
14588                 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14589                     baseType->attributeWildcard) == -1)
14590                     goto exit_failure;
14591             } else {
14592                 /*
14593                 * (3.2.2.1.1) "If the `complete wildcard` is `absent`,
14594                 * then the `base wildcard`."
14595                 */
14596                 type->attributeWildcard = baseType->attributeWildcard;
14597             }
14598         } else {
14599             /*
14600             * (3.2.2.2) "otherwise (the `base wildcard` is `absent`) the
14601             * `complete wildcard`"
14602             * NOOP
14603             */
14604         }
14605     } else {
14606         /*
14607         * SPEC {attribute wildcard}
14608         * (3.1) "If the <restriction> alternative is chosen, then the
14609         * `complete wildcard`;"
14610         * NOOP
14611         */
14612     }
14613
14614     return (0);
14615
14616 exit_failure:
14617     return(-1);
14618 }
14619
14620 /**
14621  * xmlSchemaTypeFinalContains:
14622  * @schema:  the schema
14623  * @type:  the type definition
14624  * @final: the final
14625  *
14626  * Evaluates if a type definition contains the given "final".
14627  * This does take "finalDefault" into account as well.
14628  *
14629  * Returns 1 if the type does containt the given "final",
14630  * 0 otherwise.
14631  */
14632 static int
14633 xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
14634 {
14635     if (type == NULL)
14636         return (0);
14637     if (type->flags & final)
14638         return (1);
14639     else
14640         return (0);
14641 }
14642
14643 /**
14644  * xmlSchemaGetUnionSimpleTypeMemberTypes:
14645  * @type:  the Union Simple Type
14646  *
14647  * Returns a list of member types of @type if existing,
14648  * returns NULL otherwise.
14649  */
14650 static xmlSchemaTypeLinkPtr
14651 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14652 {
14653     while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
14654         if (type->memberTypes != NULL)
14655             return (type->memberTypes);
14656         else
14657             type = type->baseType;
14658     }
14659     return (NULL);
14660 }
14661
14662 /**
14663  * xmlSchemaGetParticleTotalRangeMin:
14664  * @particle: the particle
14665  *
14666  * Schema Component Constraint: Effective Total Range
14667  * (all and sequence) + (choice)
14668  *
14669  * Returns the minimun Effective Total Range.
14670  */
14671 static int
14672 xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
14673 {
14674     if ((particle->children == NULL) ||
14675         (particle->minOccurs == 0))
14676         return (0);
14677     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14678         int min = -1, cur;
14679         xmlSchemaParticlePtr part =
14680             (xmlSchemaParticlePtr) particle->children->children;
14681
14682         if (part == NULL)
14683             return (0);
14684         while (part != NULL) {
14685             if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14686                 (part->children->type == XML_SCHEMA_TYPE_ANY))
14687                 cur = part->minOccurs;
14688             else
14689                 cur = xmlSchemaGetParticleTotalRangeMin(part);
14690             if (cur == 0)
14691                 return (0);
14692             if ((min > cur) || (min == -1))
14693                 min = cur;
14694             part = (xmlSchemaParticlePtr) part->next;
14695         }
14696         return (particle->minOccurs * min);
14697     } else {
14698         /* <all> and <sequence> */
14699         int sum = 0;
14700         xmlSchemaParticlePtr part =
14701             (xmlSchemaParticlePtr) particle->children->children;
14702
14703         if (part == NULL)
14704             return (0);
14705         do {
14706             if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14707                 (part->children->type == XML_SCHEMA_TYPE_ANY))
14708                 sum += part->minOccurs;
14709             else
14710                 sum += xmlSchemaGetParticleTotalRangeMin(part);
14711             part = (xmlSchemaParticlePtr) part->next;
14712         } while (part != NULL);
14713         return (particle->minOccurs * sum);
14714     }
14715 }
14716
14717 #if 0
14718 /**
14719  * xmlSchemaGetParticleTotalRangeMax:
14720  * @particle: the particle
14721  *
14722  * Schema Component Constraint: Effective Total Range
14723  * (all and sequence) + (choice)
14724  *
14725  * Returns the maximum Effective Total Range.
14726  */
14727 static int
14728 xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14729 {
14730     if ((particle->children == NULL) ||
14731         (particle->children->children == NULL))
14732         return (0);
14733     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14734         int max = -1, cur;
14735         xmlSchemaParticlePtr part =
14736             (xmlSchemaParticlePtr) particle->children->children;
14737
14738         for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14739             if (part->children == NULL)
14740                 continue;
14741             if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14742                 (part->children->type == XML_SCHEMA_TYPE_ANY))
14743                 cur = part->maxOccurs;
14744             else
14745                 cur = xmlSchemaGetParticleTotalRangeMax(part);
14746             if (cur == UNBOUNDED)
14747                 return (UNBOUNDED);
14748             if ((max < cur) || (max == -1))
14749                 max = cur;
14750         }
14751         /* TODO: Handle overflows? */
14752         return (particle->maxOccurs * max);
14753     } else {
14754         /* <all> and <sequence> */
14755         int sum = 0, cur;
14756         xmlSchemaParticlePtr part =
14757             (xmlSchemaParticlePtr) particle->children->children;
14758
14759         for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14760             if (part->children == NULL)
14761                 continue;
14762             if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14763                 (part->children->type == XML_SCHEMA_TYPE_ANY))
14764                 cur = part->maxOccurs;
14765             else
14766                 cur = xmlSchemaGetParticleTotalRangeMax(part);
14767             if (cur == UNBOUNDED)
14768                 return (UNBOUNDED);
14769             if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14770                 return (UNBOUNDED);
14771             sum += cur;
14772         }
14773         /* TODO: Handle overflows? */
14774         return (particle->maxOccurs * sum);
14775     }
14776 }
14777 #endif
14778
14779 /**
14780  * xmlSchemaIsParticleEmptiable:
14781  * @particle: the particle
14782  *
14783  * Schema Component Constraint: Particle Emptiable
14784  * Checks whether the given particle is emptiable.
14785  *
14786  * Returns 1 if emptiable, 0 otherwise.
14787  */
14788 static int
14789 xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14790 {
14791     /*
14792     * SPEC (1) "Its {min occurs} is 0."
14793     */
14794     if ((particle == NULL) || (particle->minOccurs == 0) ||
14795         (particle->children == NULL))
14796         return (1);
14797     /*
14798     * SPEC (2) "Its {term} is a group and the minimum part of the
14799     * effective total range of that group, [...] is 0."
14800     */
14801     if (WXS_IS_MODEL_GROUP(particle->children)) {
14802         if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
14803             return (1);
14804     }
14805     return (0);
14806 }
14807
14808 /**
14809  * xmlSchemaCheckCOSSTDerivedOK:
14810  * @actxt: a context
14811  * @type:  the derived simple type definition
14812  * @baseType:  the base type definition
14813  * @subset: the subset of ('restriction', ect.)
14814  *
14815  * Schema Component Constraint:
14816  * Type Derivation OK (Simple) (cos-st-derived-OK)
14817  *
14818  * Checks wheter @type can be validly
14819  * derived from @baseType.
14820  *
14821  * Returns 0 on success, an positive error code otherwise.
14822  */
14823 static int
14824 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
14825                              xmlSchemaTypePtr type,
14826                              xmlSchemaTypePtr baseType,
14827                              int subset)
14828 {
14829     /*
14830     * 1 They are the same type definition.
14831     * TODO: The identy check might have to be more complex than this.
14832     */
14833     if (type == baseType)
14834         return (0);
14835     /*
14836     * 2.1 restriction is not in the subset, or in the {final}
14837     * of its own {base type definition};
14838     *
14839     * NOTE that this will be used also via "xsi:type".
14840     *
14841     * TODO: Revise this, it looks strange. How can the "type"
14842     * not be fixed or *in* fixing?
14843     */
14844     if (WXS_IS_TYPE_NOT_FIXED(type))
14845         if (xmlSchemaTypeFixup(type, actxt) == -1)
14846             return(-1);
14847     if (WXS_IS_TYPE_NOT_FIXED(baseType))
14848         if (xmlSchemaTypeFixup(baseType, actxt) == -1)
14849             return(-1);
14850     if ((subset & SUBSET_RESTRICTION) ||
14851         (xmlSchemaTypeFinalContains(type->baseType,
14852             XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14853         return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
14854     }
14855     /* 2.2 */
14856     if (type->baseType == baseType) {
14857         /*
14858         * 2.2.1 D's `base type definition` is B.
14859         */
14860         return (0);
14861     }
14862     /*
14863     * 2.2.2 D's `base type definition` is not the `ur-type definition`
14864     * and is validly derived from B given the subset, as defined by this
14865     * constraint.
14866     */
14867     if ((! WXS_IS_ANYTYPE(type->baseType)) &&
14868         (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
14869             baseType, subset) == 0)) {
14870         return (0);
14871     }
14872     /*
14873     * 2.2.3 D's {variety} is list or union and B is the `simple ur-type
14874     * definition`.
14875     */
14876     if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14877         (WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
14878         return (0);
14879     }
14880     /*
14881     * 2.2.4 B's {variety} is union and D is validly derived from a type
14882     * definition in B's {member type definitions} given the subset, as
14883     * defined by this constraint.
14884     *
14885     * NOTE: This seems not to involve built-in types, since there is no
14886     * built-in Union Simple Type.
14887     */
14888     if (WXS_IS_UNION(baseType)) {
14889         xmlSchemaTypeLinkPtr cur;
14890
14891         cur = baseType->memberTypes;
14892         while (cur != NULL) {
14893             if (WXS_IS_TYPE_NOT_FIXED(cur->type))
14894                 if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
14895                     return(-1);
14896             if (xmlSchemaCheckCOSSTDerivedOK(actxt,
14897                     type, cur->type, subset) == 0)
14898             {
14899                 /*
14900                 * It just has to be validly derived from at least one
14901                 * member-type.
14902                 */
14903                 return (0);
14904             }
14905             cur = cur->next;
14906         }
14907     }
14908     return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14909 }
14910
14911 /**
14912  * xmlSchemaCheckTypeDefCircularInternal:
14913  * @pctxt:  the schema parser context
14914  * @ctxtType:  the type definition
14915  * @ancestor: an ancestor of @ctxtType
14916  *
14917  * Checks st-props-correct (2) + ct-props-correct (3).
14918  * Circular type definitions are not allowed.
14919  *
14920  * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
14921  * circular, 0 otherwise.
14922  */
14923 static int
14924 xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14925                            xmlSchemaTypePtr ctxtType,
14926                            xmlSchemaTypePtr ancestor)
14927 {
14928     int ret;
14929
14930     if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14931         return (0);
14932
14933     if (ctxtType == ancestor) {
14934         xmlSchemaPCustomErr(pctxt,
14935             XML_SCHEMAP_ST_PROPS_CORRECT_2,
14936             WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
14937             "The definition is circular", NULL);
14938         return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14939     }
14940     if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14941         /*
14942         * Avoid inifinite recursion on circular types not yet checked.
14943         */
14944         return (0);
14945     }
14946     ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14947     ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14948         ancestor->baseType);
14949     ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14950     return (ret);
14951 }
14952
14953 /**
14954  * xmlSchemaCheckTypeDefCircular:
14955  * @item:  the complex/simple type definition
14956  * @ctxt:  the parser context
14957  * @name:  the name
14958  *
14959  * Checks for circular type definitions.
14960  */
14961 static void
14962 xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
14963                               xmlSchemaParserCtxtPtr ctxt)
14964 {
14965     if ((item == NULL) ||
14966         (item->type == XML_SCHEMA_TYPE_BASIC) ||
14967         (item->baseType == NULL))
14968         return;
14969     xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
14970         item->baseType);
14971 }
14972
14973 /*
14974 * Simple Type Definition Representation OK (src-simple-type) 4
14975 *
14976 * "4 Circular union type definition is disallowed. That is, if the
14977 * <union> alternative is chosen, there must not be any entries in the
14978 * memberTypes [attribute] at any depth which resolve to the component
14979 * corresponding to the <simpleType>."
14980 *
14981 * Note that this should work on the *representation* of a component,
14982 * thus assumes any union types in the member types not being yet
14983 * substituted. At this stage we need the variety of the types
14984 * to be already computed.
14985 */
14986 static int
14987 xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
14988                                         xmlSchemaTypePtr ctxType,
14989                                         xmlSchemaTypeLinkPtr members)
14990 {
14991     xmlSchemaTypeLinkPtr member;
14992     xmlSchemaTypePtr memberType;
14993
14994     member = members;
14995     while (member != NULL) {
14996         memberType = member->type;
14997         while ((memberType != NULL) &&
14998             (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
14999             if (memberType == ctxType) {
15000                 xmlSchemaPCustomErr(pctxt,
15001                     XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
15002                     WXS_BASIC_CAST ctxType, NULL,
15003                     "The union type definition is circular", NULL);
15004                 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
15005             }
15006             if ((WXS_IS_UNION(memberType)) &&
15007                 ((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
15008             {
15009                 int res;
15010                 memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
15011                 res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
15012                     ctxType,
15013                     xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
15014                 memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
15015                 if (res != 0)
15016                     return(res);
15017             }
15018             memberType = memberType->baseType;
15019         }
15020         member = member->next;
15021     }
15022     return(0);
15023 }
15024
15025 static int
15026 xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
15027                                    xmlSchemaTypePtr type)
15028 {
15029     if (! WXS_IS_UNION(type))
15030         return(0);
15031     return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
15032         type->memberTypes));
15033 }
15034
15035 /**
15036  * xmlSchemaResolveTypeReferences:
15037  * @item:  the complex/simple type definition
15038  * @ctxt:  the parser context
15039  * @name:  the name
15040  *
15041  * Resolvese type definition references
15042  */
15043 static void
15044 xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
15045                          xmlSchemaParserCtxtPtr ctxt)
15046 {
15047     if (typeDef == NULL)
15048         return;
15049
15050     /*
15051     * Resolve the base type.
15052     */
15053     if (typeDef->baseType == NULL) {
15054         typeDef->baseType = xmlSchemaGetType(ctxt->schema,
15055             typeDef->base, typeDef->baseNs);
15056         if (typeDef->baseType == NULL) {
15057             xmlSchemaPResCompAttrErr(ctxt,
15058                 XML_SCHEMAP_SRC_RESOLVE,
15059                 WXS_BASIC_CAST typeDef, typeDef->node,
15060                 "base", typeDef->base, typeDef->baseNs,
15061                 XML_SCHEMA_TYPE_SIMPLE, NULL);
15062             return;
15063         }
15064     }
15065     if (WXS_IS_SIMPLE(typeDef)) {
15066         if (WXS_IS_UNION(typeDef)) {
15067             /*
15068             * Resolve the memberTypes.
15069             */
15070             xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
15071             return;
15072         } else if (WXS_IS_LIST(typeDef)) {
15073             /*
15074             * Resolve the itemType.
15075             */
15076             if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
15077
15078                 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
15079                     typeDef->base, typeDef->baseNs);
15080
15081                 if ((typeDef->subtypes == NULL) ||
15082                     (! WXS_IS_SIMPLE(typeDef->subtypes)))
15083                 {
15084                     typeDef->subtypes = NULL;
15085                     xmlSchemaPResCompAttrErr(ctxt,
15086                         XML_SCHEMAP_SRC_RESOLVE,
15087                         WXS_BASIC_CAST typeDef, typeDef->node,
15088                         "itemType", typeDef->base, typeDef->baseNs,
15089                         XML_SCHEMA_TYPE_SIMPLE, NULL);
15090                 }
15091             }
15092             return;
15093         }
15094     }
15095     /*
15096     * The ball of letters below means, that if we have a particle
15097     * which has a QName-helper component as its {term}, we want
15098     * to resolve it...
15099     */
15100     else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
15101         ((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
15102             XML_SCHEMA_TYPE_PARTICLE) &&
15103         (WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
15104         ((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
15105             XML_SCHEMA_EXTRA_QNAMEREF))
15106     {
15107         xmlSchemaQNameRefPtr ref =
15108             WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
15109         xmlSchemaModelGroupDefPtr groupDef;
15110
15111         /*
15112         * URGENT TODO: Test this.
15113         */
15114         WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
15115         /*
15116         * Resolve the MG definition reference.
15117         */
15118         groupDef =
15119             WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
15120                 ref->itemType, ref->name, ref->targetNamespace);
15121         if (groupDef == NULL) {
15122             xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
15123                 NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
15124                 "ref", ref->name, ref->targetNamespace, ref->itemType,
15125                 NULL);
15126             /* Remove the particle. */
15127             WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15128         } else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
15129             /* Remove the particle. */
15130             WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15131         else {
15132             /*
15133             * Assign the MG definition's {model group} to the
15134             * particle's {term}.
15135             */
15136             WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
15137
15138             if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
15139                 /*
15140                 * SPEC cos-all-limited (1.2)
15141                 * "1.2 the {term} property of a particle with
15142                 * {max occurs}=1 which is part of a pair which constitutes
15143                 * the {content type} of a complex type definition."
15144                 */
15145                 if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
15146                     xmlSchemaCustomErr(ACTXT_CAST ctxt,
15147                         /* TODO: error code */
15148                         XML_SCHEMAP_COS_ALL_LIMITED,
15149                         WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
15150                         "The particle's {max occurs} must be 1, since the "
15151                         "reference resolves to an 'all' model group",
15152                         NULL, NULL);
15153                 }
15154             }
15155         }
15156     }
15157 }
15158
15159
15160
15161 /**
15162  * xmlSchemaCheckSTPropsCorrect:
15163  * @ctxt:  the schema parser context
15164  * @type:  the simple type definition
15165  *
15166  * Checks st-props-correct.
15167  *
15168  * Returns 0 if the properties are correct,
15169  * if not, a positive error code and -1 on internal
15170  * errors.
15171  */
15172 static int
15173 xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
15174                              xmlSchemaTypePtr type)
15175 {
15176     xmlSchemaTypePtr baseType = type->baseType;
15177     xmlChar *str = NULL;
15178
15179     /* STATE: error funcs converted. */
15180     /*
15181     * Schema Component Constraint: Simple Type Definition Properties Correct
15182     *
15183     * NOTE: This is somehow redundant, since we actually built a simple type
15184     * to have all the needed information; this acts as an self test.
15185     */
15186     /* Base type: If the datatype has been `derived` by `restriction`
15187     * then the Simple Type Definition component from which it is `derived`,
15188     * otherwise the Simple Type Definition for anySimpleType ($4.1.6).
15189     */
15190     if (baseType == NULL) {
15191         /*
15192         * TODO: Think about: "modulo the impact of Missing
15193         * Sub-components ($5.3)."
15194         */
15195         xmlSchemaPCustomErr(ctxt,
15196             XML_SCHEMAP_ST_PROPS_CORRECT_1,
15197             WXS_BASIC_CAST type, NULL,
15198             "No base type existent", NULL);
15199         return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15200
15201     }
15202     if (! WXS_IS_SIMPLE(baseType)) {
15203         xmlSchemaPCustomErr(ctxt,
15204             XML_SCHEMAP_ST_PROPS_CORRECT_1,
15205             WXS_BASIC_CAST type, NULL,
15206             "The base type '%s' is not a simple type",
15207             xmlSchemaGetComponentQName(&str, baseType));
15208         FREE_AND_NULL(str)
15209         return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15210     }
15211     if ((WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
15212         (WXS_IS_RESTRICTION(type) == 0) &&
15213         ((! WXS_IS_ANY_SIMPLE_TYPE(baseType)) &&
15214          (baseType->type != XML_SCHEMA_TYPE_SIMPLE))) {
15215         xmlSchemaPCustomErr(ctxt,
15216             XML_SCHEMAP_ST_PROPS_CORRECT_1,
15217             WXS_BASIC_CAST type, NULL,
15218             "A type, derived by list or union, must have "
15219             "the simple ur-type definition as base type, not '%s'",
15220             xmlSchemaGetComponentQName(&str, baseType));
15221         FREE_AND_NULL(str)
15222         return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15223     }
15224     /*
15225     * Variety: One of {atomic, list, union}.
15226     */
15227     if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15228         (! WXS_IS_LIST(type))) {
15229         xmlSchemaPCustomErr(ctxt,
15230             XML_SCHEMAP_ST_PROPS_CORRECT_1,
15231             WXS_BASIC_CAST type, NULL,
15232             "The variety is absent", NULL);
15233         return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15234     }
15235     /* TODO: Finish this. Hmm, is this finished? */
15236
15237     /*
15238     * 3 The {final} of the {base type definition} must not contain restriction.
15239     */
15240     if (xmlSchemaTypeFinalContains(baseType,
15241         XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15242         xmlSchemaPCustomErr(ctxt,
15243             XML_SCHEMAP_ST_PROPS_CORRECT_3,
15244             WXS_BASIC_CAST type, NULL,
15245             "The 'final' of its base type '%s' must not contain "
15246             "'restriction'",
15247             xmlSchemaGetComponentQName(&str, baseType));
15248         FREE_AND_NULL(str)
15249         return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
15250     }
15251
15252     /*
15253     * 2 All simple type definitions must be derived ultimately from the `simple
15254     * ur-type definition` (so circular definitions are disallowed). That is, it
15255     * must be possible to reach a built-in primitive datatype or the `simple
15256     * ur-type definition` by repeatedly following the {base type definition}.
15257     *
15258     * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
15259     */
15260     return (0);
15261 }
15262
15263 /**
15264  * xmlSchemaCheckCOSSTRestricts:
15265  * @ctxt:  the schema parser context
15266  * @type:  the simple type definition
15267  *
15268  * Schema Component Constraint:
15269  * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15270
15271  * Checks if the given @type (simpleType) is derived validly by restriction.
15272  * STATUS:
15273  *
15274  * Returns -1 on internal errors, 0 if the type is validly derived,
15275  * a positive error code otherwise.
15276  */
15277 static int
15278 xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
15279                              xmlSchemaTypePtr type)
15280 {
15281     xmlChar *str = NULL;
15282
15283     if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
15284         PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15285             "given type is not a user-derived simpleType");
15286         return (-1);
15287     }
15288
15289     if (WXS_IS_ATOMIC(type)) {
15290         xmlSchemaTypePtr primitive;
15291         /*
15292         * 1.1 The {base type definition} must be an atomic simple
15293         * type definition or a built-in primitive datatype.
15294         */
15295         if (! WXS_IS_ATOMIC(type->baseType)) {
15296             xmlSchemaPCustomErr(pctxt,
15297                 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
15298                 WXS_BASIC_CAST type, NULL,
15299                 "The base type '%s' is not an atomic simple type",
15300                 xmlSchemaGetComponentQName(&str, type->baseType));
15301             FREE_AND_NULL(str)
15302             return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15303         }
15304         /* 1.2 The {final} of the {base type definition} must not contain
15305         * restriction.
15306         */
15307         /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
15308         if (xmlSchemaTypeFinalContains(type->baseType,
15309             XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15310             xmlSchemaPCustomErr(pctxt,
15311                 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
15312                 WXS_BASIC_CAST type, NULL,
15313                 "The final of its base type '%s' must not contain 'restriction'",
15314                 xmlSchemaGetComponentQName(&str, type->baseType));
15315             FREE_AND_NULL(str)
15316             return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15317         }
15318
15319         /*
15320         * 1.3.1 DF must be an allowed constraining facet for the {primitive
15321         * type definition}, as specified in the appropriate subsection of 3.2
15322         * Primitive datatypes.
15323         */
15324         if (type->facets != NULL) {
15325             xmlSchemaFacetPtr facet;
15326             int ok = 1;
15327
15328             primitive = xmlSchemaGetPrimitiveType(type);
15329             if (primitive == NULL) {
15330                 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15331                     "failed to get primitive type");
15332                 return (-1);
15333             }
15334             facet = type->facets;
15335             do {
15336                 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
15337                     ok = 0;
15338                     xmlSchemaPIllegalFacetAtomicErr(pctxt,
15339                         XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
15340                         type, primitive, facet);
15341                 }
15342                 facet = facet->next;
15343             } while (facet != NULL);
15344             if (ok == 0)
15345                 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
15346         }
15347         /*
15348         * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15349         * of the {base type definition} (call this BF),then the DF's {value}
15350         * must be a valid restriction of BF's {value} as defined in
15351         * [XML Schemas: Datatypes]."
15352         *
15353         * NOTE (1.3.2) Facet derivation constraints are currently handled in
15354         * xmlSchemaDeriveAndValidateFacets()
15355         */
15356     } else if (WXS_IS_LIST(type)) {
15357         xmlSchemaTypePtr itemType = NULL;
15358
15359         itemType = type->subtypes;
15360         if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
15361             PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15362                 "failed to evaluate the item type");
15363             return (-1);
15364         }
15365         if (WXS_IS_TYPE_NOT_FIXED(itemType))
15366             xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
15367         /*
15368         * 2.1 The {item type definition} must have a {variety} of atomic or
15369         * union (in which case all the {member type definitions}
15370         * must be atomic).
15371         */
15372         if ((! WXS_IS_ATOMIC(itemType)) &&
15373             (! WXS_IS_UNION(itemType))) {
15374             xmlSchemaPCustomErr(pctxt,
15375                 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15376                 WXS_BASIC_CAST type, NULL,
15377                 "The item type '%s' does not have a variety of atomic or union",
15378                 xmlSchemaGetComponentQName(&str, itemType));
15379             FREE_AND_NULL(str)
15380             return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15381         } else if (WXS_IS_UNION(itemType)) {
15382             xmlSchemaTypeLinkPtr member;
15383
15384             member = itemType->memberTypes;
15385             while (member != NULL) {
15386                 if (! WXS_IS_ATOMIC(member->type)) {
15387                     xmlSchemaPCustomErr(pctxt,
15388                         XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15389                         WXS_BASIC_CAST type, NULL,
15390                         "The item type is a union type, but the "
15391                         "member type '%s' of this item type is not atomic",
15392                         xmlSchemaGetComponentQName(&str, member->type));
15393                     FREE_AND_NULL(str)
15394                     return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15395                 }
15396                 member = member->next;
15397             }
15398         }
15399
15400         if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
15401             xmlSchemaFacetPtr facet;
15402             /*
15403             * This is the case if we have: <simpleType><list ..
15404             */
15405             /*
15406             * 2.3.1
15407             * 2.3.1.1 The {final} of the {item type definition} must not
15408             * contain list.
15409             */
15410             if (xmlSchemaTypeFinalContains(itemType,
15411                 XML_SCHEMAS_TYPE_FINAL_LIST)) {
15412                 xmlSchemaPCustomErr(pctxt,
15413                     XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
15414                     WXS_BASIC_CAST type, NULL,
15415                     "The final of its item type '%s' must not contain 'list'",
15416                     xmlSchemaGetComponentQName(&str, itemType));
15417                 FREE_AND_NULL(str)
15418                 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15419             }
15420             /*
15421             * 2.3.1.2 The {facets} must only contain the whiteSpace
15422             * facet component.
15423             * OPTIMIZE TODO: the S4S already disallows any facet
15424             * to be specified.
15425             */
15426             if (type->facets != NULL) {
15427                 facet = type->facets;
15428                 do {
15429                     if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15430                         xmlSchemaPIllegalFacetListUnionErr(pctxt,
15431                             XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
15432                             type, facet);
15433                         return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15434                     }
15435                     facet = facet->next;
15436                 } while (facet != NULL);
15437             }
15438             /*
15439             * MAYBE TODO: (Hmm, not really) Datatypes states:
15440             * A `list` datatype can be `derived` from an `atomic` datatype
15441             * whose `lexical space` allows space (such as string or anyURI)or
15442             * a `union` datatype any of whose {member type definitions}'s
15443             * `lexical space` allows space.
15444             */
15445         } else {
15446             /*
15447             * This is the case if we have: <simpleType><restriction ...
15448             * I.e. the variety of "list" is inherited.
15449             */
15450             /*
15451             * 2.3.2
15452             * 2.3.2.1 The {base type definition} must have a {variety} of list.
15453             */
15454             if (! WXS_IS_LIST(type->baseType)) {
15455                 xmlSchemaPCustomErr(pctxt,
15456                     XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
15457                     WXS_BASIC_CAST type, NULL,
15458                     "The base type '%s' must be a list type",
15459                     xmlSchemaGetComponentQName(&str, type->baseType));
15460                 FREE_AND_NULL(str)
15461                 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15462             }
15463             /*
15464             * 2.3.2.2 The {final} of the {base type definition} must not
15465             * contain restriction.
15466             */
15467             if (xmlSchemaTypeFinalContains(type->baseType,
15468                 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15469                 xmlSchemaPCustomErr(pctxt,
15470                     XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
15471                     WXS_BASIC_CAST type, NULL,
15472                     "The 'final' of the base type '%s' must not contain 'restriction'",
15473                     xmlSchemaGetComponentQName(&str, type->baseType));
15474                 FREE_AND_NULL(str)
15475                 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15476             }
15477             /*
15478             * 2.3.2.3 The {item type definition} must be validly derived
15479             * from the {base type definition}'s {item type definition} given
15480             * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6).
15481             */
15482             {
15483                 xmlSchemaTypePtr baseItemType;
15484
15485                 baseItemType = type->baseType->subtypes;
15486                 if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
15487                     PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15488                         "failed to eval the item type of a base type");
15489                     return (-1);
15490                 }
15491                 if ((itemType != baseItemType) &&
15492                     (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
15493                         baseItemType, 0) != 0)) {
15494                     xmlChar *strBIT = NULL, *strBT = NULL;
15495                     xmlSchemaPCustomErrExt(pctxt,
15496                         XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
15497                         WXS_BASIC_CAST type, NULL,
15498                         "The item type '%s' is not validly derived from "
15499                         "the item type '%s' of the base type '%s'",
15500                         xmlSchemaGetComponentQName(&str, itemType),
15501                         xmlSchemaGetComponentQName(&strBIT, baseItemType),
15502                         xmlSchemaGetComponentQName(&strBT, type->baseType));
15503
15504                     FREE_AND_NULL(str)
15505                     FREE_AND_NULL(strBIT)
15506                     FREE_AND_NULL(strBT)
15507                     return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15508                 }
15509             }
15510
15511             if (type->facets != NULL) {
15512                 xmlSchemaFacetPtr facet;
15513                 int ok = 1;
15514                 /*
15515                 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
15516                 * and enumeration facet components are allowed among the {facets}.
15517                 */
15518                 facet = type->facets;
15519                 do {
15520                     switch (facet->type) {
15521                         case XML_SCHEMA_FACET_LENGTH:
15522                         case XML_SCHEMA_FACET_MINLENGTH:
15523                         case XML_SCHEMA_FACET_MAXLENGTH:
15524                         case XML_SCHEMA_FACET_WHITESPACE:
15525                             /*
15526                             * TODO: 2.5.1.2 List datatypes
15527                             * The value of `whiteSpace` is fixed to the value collapse.
15528                             */
15529                         case XML_SCHEMA_FACET_PATTERN:
15530                         case XML_SCHEMA_FACET_ENUMERATION:
15531                             break;
15532                         default: {
15533                             xmlSchemaPIllegalFacetListUnionErr(pctxt,
15534                                 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
15535                                 type, facet);
15536                             /*
15537                             * We could return, but it's nicer to report all
15538                             * invalid facets.
15539                             */
15540                             ok = 0;
15541                         }
15542                     }
15543                     facet = facet->next;
15544                 } while (facet != NULL);
15545                 if (ok == 0)
15546                     return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15547                 /*
15548                 * SPEC (2.3.2.5) (same as 1.3.2)
15549                 *
15550                 * NOTE (2.3.2.5) This is currently done in
15551                 * xmlSchemaDeriveAndValidateFacets()
15552                 */
15553             }
15554         }
15555     } else if (WXS_IS_UNION(type)) {
15556         /*
15557         * 3.1 The {member type definitions} must all have {variety} of
15558         * atomic or list.
15559         */
15560         xmlSchemaTypeLinkPtr member;
15561
15562         member = type->memberTypes;
15563         while (member != NULL) {
15564             if (WXS_IS_TYPE_NOT_FIXED(member->type))
15565                 xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
15566
15567             if ((! WXS_IS_ATOMIC(member->type)) &&
15568                 (! WXS_IS_LIST(member->type))) {
15569                 xmlSchemaPCustomErr(pctxt,
15570                     XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
15571                     WXS_BASIC_CAST type, NULL,
15572                     "The member type '%s' is neither an atomic, nor a list type",
15573                     xmlSchemaGetComponentQName(&str, member->type));
15574                 FREE_AND_NULL(str)
15575                 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15576             }
15577             member = member->next;
15578         }
15579         /*
15580         * 3.3.1 If the {base type definition} is the `simple ur-type
15581         * definition`
15582         */
15583         if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
15584             /*
15585             * 3.3.1.1 All of the {member type definitions} must have a
15586             * {final} which does not contain union.
15587             */
15588             member = type->memberTypes;
15589             while (member != NULL) {
15590                 if (xmlSchemaTypeFinalContains(member->type,
15591                     XML_SCHEMAS_TYPE_FINAL_UNION)) {
15592                     xmlSchemaPCustomErr(pctxt,
15593                         XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
15594                         WXS_BASIC_CAST type, NULL,
15595                         "The 'final' of member type '%s' contains 'union'",
15596                         xmlSchemaGetComponentQName(&str, member->type));
15597                     FREE_AND_NULL(str)
15598                     return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15599                 }
15600                 member = member->next;
15601             }
15602             /*
15603             * 3.3.1.2 The {facets} must be empty.
15604             */
15605             if (type->facetSet != NULL) {
15606                 xmlSchemaPCustomErr(pctxt,
15607                     XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
15608                     WXS_BASIC_CAST type, NULL,
15609                     "No facets allowed", NULL);
15610                 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15611             }
15612         } else {
15613             /*
15614             * 3.3.2.1 The {base type definition} must have a {variety} of union.
15615             * I.e. the variety of "list" is inherited.
15616             */
15617             if (! WXS_IS_UNION(type->baseType)) {
15618                 xmlSchemaPCustomErr(pctxt,
15619                     XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
15620                     WXS_BASIC_CAST type, NULL,
15621                     "The base type '%s' is not a union type",
15622                     xmlSchemaGetComponentQName(&str, type->baseType));
15623                 FREE_AND_NULL(str)
15624                 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15625             }
15626             /*
15627             * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15628             */
15629             if (xmlSchemaTypeFinalContains(type->baseType,
15630                 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15631                 xmlSchemaPCustomErr(pctxt,
15632                     XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
15633                     WXS_BASIC_CAST type, NULL,
15634                     "The 'final' of its base type '%s' must not contain 'restriction'",
15635                     xmlSchemaGetComponentQName(&str, type->baseType));
15636                 FREE_AND_NULL(str)
15637                 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15638             }
15639             /*
15640             * 3.3.2.3 The {member type definitions}, in order, must be validly
15641             * derived from the corresponding type definitions in the {base
15642             * type definition}'s {member type definitions} given the empty set,
15643             * as defined in Type Derivation OK (Simple) ($3.14.6).
15644             */
15645             {
15646                 xmlSchemaTypeLinkPtr baseMember;
15647
15648                 /*
15649                 * OPTIMIZE: if the type is restricting, it has no local defined
15650                 * member types and inherits the member types of the base type;
15651                 * thus a check for equality can be skipped.
15652                 */
15653                 /*
15654                 * Even worse: I cannot see a scenario where a restricting
15655                 * union simple type can have other member types as the member
15656                 * types of it's base type. This check seems not necessary with
15657                 * respect to the derivation process in libxml2.
15658                 * But necessary if constructing types with an API.
15659                 */
15660                 if (type->memberTypes != NULL) {
15661                     member = type->memberTypes;
15662                     baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
15663                     if ((member == NULL) && (baseMember != NULL)) {
15664                         PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15665                             "different number of member types in base");
15666                     }
15667                     while (member != NULL) {
15668                         if (baseMember == NULL) {
15669                             PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15670                             "different number of member types in base");
15671                         } else if ((member->type != baseMember->type) &&
15672                             (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
15673                                 member->type, baseMember->type, 0) != 0)) {
15674                             xmlChar *strBMT = NULL, *strBT = NULL;
15675
15676                             xmlSchemaPCustomErrExt(pctxt,
15677                                 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
15678                                 WXS_BASIC_CAST type, NULL,
15679                                 "The member type %s is not validly "
15680                                 "derived from its corresponding member "
15681                                 "type %s of the base type %s",
15682                                 xmlSchemaGetComponentQName(&str, member->type),
15683                                 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15684                                 xmlSchemaGetComponentQName(&strBT, type->baseType));
15685                             FREE_AND_NULL(str)
15686                             FREE_AND_NULL(strBMT)
15687                             FREE_AND_NULL(strBT)
15688                             return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
15689                         }
15690                         member = member->next;
15691                         if (baseMember != NULL)
15692                             baseMember = baseMember->next;
15693                     }
15694                 }
15695             }
15696             /*
15697             * 3.3.2.4 Only pattern and enumeration facet components are
15698             * allowed among the {facets}.
15699             */
15700             if (type->facets != NULL) {
15701                 xmlSchemaFacetPtr facet;
15702                 int ok = 1;
15703
15704                 facet = type->facets;
15705                 do {
15706                     if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15707                         (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
15708                         xmlSchemaPIllegalFacetListUnionErr(pctxt,
15709                                 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
15710                                 type, facet);
15711                         ok = 0;
15712                     }
15713                     facet = facet->next;
15714                 } while (facet != NULL);
15715                 if (ok == 0)
15716                     return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
15717
15718             }
15719             /*
15720             * SPEC (3.3.2.5) (same as 1.3.2)
15721             *
15722             * NOTE (3.3.2.5) This is currently done in
15723             * xmlSchemaDeriveAndValidateFacets()
15724             */
15725         }
15726     }
15727
15728     return (0);
15729 }
15730
15731 /**
15732  * xmlSchemaCheckSRCSimpleType:
15733  * @ctxt:  the schema parser context
15734  * @type:  the simple type definition
15735  *
15736  * Checks crc-simple-type constraints.
15737  *
15738  * Returns 0 if the constraints are satisfied,
15739  * if not a positive error code and -1 on internal
15740  * errors.
15741  */
15742 #if 0
15743 static int
15744 xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15745                             xmlSchemaTypePtr type)
15746 {
15747     /*
15748     * src-simple-type.1 The corresponding simple type definition, if any,
15749     * must satisfy the conditions set out in Constraints on Simple Type
15750     * Definition Schema Components ($3.14.6).
15751     */
15752     if (WXS_IS_RESTRICTION(type)) {
15753         /*
15754         * src-simple-type.2 "If the <restriction> alternative is chosen,
15755         * either it must have a base [attribute] or a <simpleType> among its
15756         * [children], but not both."
15757         * NOTE: This is checked in the parse function of <restriction>.
15758         */
15759         /*
15760         *
15761         */
15762     } else if (WXS_IS_LIST(type)) {
15763         /* src-simple-type.3 "If the <list> alternative is chosen, either it must have
15764         * an itemType [attribute] or a <simpleType> among its [children],
15765         * but not both."
15766         *
15767         * NOTE: This is checked in the parse function of <list>.
15768         */
15769     } else if (WXS_IS_UNION(type)) {
15770         /*
15771         * src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
15772         */
15773     }
15774     return (0);
15775 }
15776 #endif
15777
15778 static int
15779 xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15780 {
15781    if (ctxt->vctxt == NULL) {
15782         ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15783         if (ctxt->vctxt == NULL) {
15784             xmlSchemaPErr(ctxt, NULL,
15785                 XML_SCHEMAP_INTERNAL,
15786                 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
15787                 "failed to create a temp. validation context.\n",
15788                 NULL, NULL);
15789             return (-1);
15790         }
15791         /* TODO: Pass user data. */
15792         xmlSchemaSetValidErrors(ctxt->vctxt,
15793             ctxt->error, ctxt->warning, ctxt->errCtxt);
15794         xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15795             ctxt->serror, ctxt->errCtxt);
15796     }
15797     return (0);
15798 }
15799
15800 static int
15801 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15802                              xmlNodePtr node,
15803                              xmlSchemaTypePtr type,
15804                              const xmlChar *value,
15805                              xmlSchemaValPtr *retVal,
15806                              int fireErrors,
15807                              int normalize,
15808                              int isNormalized);
15809
15810 /**
15811  * xmlSchemaParseCheckCOSValidDefault:
15812  * @pctxt:  the schema parser context
15813  * @type:  the simple type definition
15814  * @value: the default value
15815  * @node: an optional node (the holder of the value)
15816  *
15817  * Schema Component Constraint: Element Default Valid (Immediate)
15818  * (cos-valid-default)
15819  * This will be used by the parser only. For the validator there's
15820  * an other version.
15821  *
15822  * Returns 0 if the constraints are satisfied,
15823  * if not, a positive error code and -1 on internal
15824  * errors.
15825  */
15826 static int
15827 xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15828                                    xmlNodePtr node,
15829                                    xmlSchemaTypePtr type,
15830                                    const xmlChar *value,
15831                                    xmlSchemaValPtr *val)
15832 {
15833     int ret = 0;
15834
15835     /*
15836     * cos-valid-default:
15837     * Schema Component Constraint: Element Default Valid (Immediate)
15838     * For a string to be a valid default with respect to a type
15839     * definition the appropriate case among the following must be true:
15840     */
15841     if WXS_IS_COMPLEX(type) {
15842         /*
15843         * Complex type.
15844         *
15845         * SPEC (2.1) "its {content type} must be a simple type definition
15846         * or mixed."
15847         * SPEC (2.2.2) "If the {content type} is mixed, then the {content
15848         * type}'s particle must be `emptiable` as defined by
15849         * Particle Emptiable ($3.9.6)."
15850         */
15851         if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15852             ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
15853             /* NOTE that this covers (2.2.2) as well. */
15854             xmlSchemaPCustomErr(pctxt,
15855                 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
15856                 WXS_BASIC_CAST type, type->node,
15857                 "For a string to be a valid default, the type definition "
15858                 "must be a simple type or a complex type with mixed content "
15859                 "and a particle emptiable", NULL);
15860             return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15861         }
15862     }
15863     /*
15864     * 1 If the type definition is a simple type definition, then the string
15865     * must be `valid` with respect to that definition as defined by String
15866     * Valid ($3.14.4).
15867     *
15868     * AND
15869     *
15870     * 2.2.1 If the {content type} is a simple type definition, then the
15871     * string must be `valid` with respect to that simple type definition
15872     * as defined by String Valid ($3.14.4).
15873     */
15874     if (WXS_IS_SIMPLE(type))
15875         ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15876             type, value, val, 1, 1, 0);
15877     else if (WXS_HAS_SIMPLE_CONTENT(type))
15878         ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15879             type->contentTypeDef, value, val, 1, 1, 0);
15880     else
15881         return (ret);
15882
15883     if (ret < 0) {
15884         PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15885             "calling xmlSchemaVCheckCVCSimpleType()");
15886     }
15887
15888     return (ret);
15889 }
15890
15891 /**
15892  * xmlSchemaCheckCTPropsCorrect:
15893  * @ctxt:  the schema parser context
15894  * @type:  the complex type definition
15895  *
15896  *.(4.6) Constraints on Complex Type Definition Schema Components
15897  * Schema Component Constraint:
15898  * Complex Type Definition Properties Correct (ct-props-correct)
15899  * STATUS: (seems) complete
15900  *
15901  * Returns 0 if the constraints are satisfied, a positive
15902  * error code if not and -1 if an internal error occurred.
15903  */
15904 static int
15905 xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15906                              xmlSchemaTypePtr type)
15907 {
15908     /*
15909     * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15910     *
15911     * SPEC (1) "The values of the properties of a complex type definition must
15912     * be as described in the property tableau in The Complex Type Definition
15913     * Schema Component ($3.4.1), modulo the impact of Missing
15914     * Sub-components ($5.3)."
15915     */
15916     if ((type->baseType != NULL) &&
15917         (WXS_IS_SIMPLE(type->baseType)) &&
15918         (WXS_IS_EXTENSION(type) == 0)) {
15919         /*
15920         * SPEC (2) "If the {base type definition} is a simple type definition,
15921         * the {derivation method} must be extension."
15922         */
15923         xmlSchemaCustomErr(ACTXT_CAST pctxt,
15924             XML_SCHEMAP_SRC_CT_1,
15925             NULL, WXS_BASIC_CAST type,
15926             "If the base type is a simple type, the derivation method must be "
15927             "'extension'", NULL, NULL);
15928         return (XML_SCHEMAP_SRC_CT_1);
15929     }
15930     /*
15931     * SPEC (3) "Circular definitions are disallowed, except for the `ur-type
15932     * definition`. That is, it must be possible to reach the `ur-type
15933     * definition` by repeatedly following the {base type definition}."
15934     *
15935     * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
15936     */
15937     /*
15938     * NOTE that (4) and (5) need the following:
15939     *   - attribute uses need to be already inherited (apply attr. prohibitions)
15940     *   - attribute group references need to be expanded already
15941     *   - simple types need to be typefixed already
15942     */
15943     if (type->attrUses &&
15944         (((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15945     {
15946         xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15947         xmlSchemaAttributeUsePtr use, tmp;
15948         int i, j, hasId = 0;
15949
15950         for (i = uses->nbItems -1; i >= 0; i--) {
15951             use = uses->items[i];
15952
15953             /*
15954             * SPEC ct-props-correct
15955             * (4) "Two distinct attribute declarations in the
15956             * {attribute uses} must not have identical {name}s and
15957             * {target namespace}s."
15958             */
15959             if (i > 0) {
15960                 for (j = i -1; j >= 0; j--) {
15961                     tmp = uses->items[j];
15962                     if ((WXS_ATTRUSE_DECL_NAME(use) ==
15963                         WXS_ATTRUSE_DECL_NAME(tmp)) &&
15964                         (WXS_ATTRUSE_DECL_TNS(use) ==
15965                         WXS_ATTRUSE_DECL_TNS(tmp)))
15966                     {
15967                         xmlChar *str = NULL;
15968
15969                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
15970                             XML_SCHEMAP_AG_PROPS_CORRECT,
15971                             NULL, WXS_BASIC_CAST type,
15972                             "Duplicate %s",
15973                             xmlSchemaGetComponentDesignation(&str, use),
15974                             NULL);
15975                         FREE_AND_NULL(str);
15976                         /*
15977                         * Remove the duplicate.
15978                         */
15979                         if (xmlSchemaItemListRemove(uses, i) == -1)
15980                             goto exit_failure;
15981                         goto next_use;
15982                     }
15983                 }
15984             }
15985             /*
15986             * SPEC ct-props-correct
15987             * (5) "Two distinct attribute declarations in the
15988             * {attribute uses} must not have {type definition}s which
15989             * are or are derived from ID."
15990             */
15991             if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15992                 if (xmlSchemaIsDerivedFromBuiltInType(
15993                     WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
15994                 {
15995                     if (hasId) {
15996                         xmlChar *str = NULL;
15997
15998                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
15999                             XML_SCHEMAP_AG_PROPS_CORRECT,
16000                             NULL, WXS_BASIC_CAST type,
16001                             "There must not exist more than one attribute "
16002                             "declaration of type 'xs:ID' "
16003                             "(or derived from 'xs:ID'). The %s violates this "
16004                             "constraint",
16005                             xmlSchemaGetComponentDesignation(&str, use),
16006                             NULL);
16007                         FREE_AND_NULL(str);
16008                         if (xmlSchemaItemListRemove(uses, i) == -1)
16009                             goto exit_failure;
16010                     }
16011
16012                     hasId = 1;
16013                 }
16014             }
16015 next_use: {}
16016         }
16017     }
16018     return (0);
16019 exit_failure:
16020     return(-1);
16021 }
16022
16023 static int
16024 xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
16025                        xmlSchemaTypePtr typeB)
16026 {
16027     /*
16028     * TODO: This should implement component-identity
16029     * in the future.
16030     */
16031     if ((typeA == NULL) || (typeB == NULL))
16032         return (0);
16033     return (typeA == typeB);
16034 }
16035
16036 /**
16037  * xmlSchemaCheckCOSCTDerivedOK:
16038  * @ctxt:  the schema parser context
16039  * @type:  the to-be derived complex type definition
16040  * @baseType:  the base complex type definition
16041  * @set: the given set
16042  *
16043  * Schema Component Constraint:
16044  * Type Derivation OK (Complex) (cos-ct-derived-ok)
16045  *
16046  * STATUS: completed
16047  *
16048  * Returns 0 if the constraints are satisfied, or 1
16049  * if not.
16050  */
16051 static int
16052 xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16053                              xmlSchemaTypePtr type,
16054                              xmlSchemaTypePtr baseType,
16055                              int set)
16056 {
16057     int equal = xmlSchemaAreEqualTypes(type, baseType);
16058     /* TODO: Error codes. */
16059     /*
16060     * SPEC "For a complex type definition (call it D, for derived)
16061     * to be validly derived from a type definition (call this
16062     * B, for base) given a subset of {extension, restriction}
16063     * all of the following must be true:"
16064     */
16065     if (! equal) {
16066         /*
16067         * SPEC (1) "If B and D are not the same type definition, then the
16068         * {derivation method} of D must not be in the subset."
16069         */
16070         if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
16071             ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
16072             return (1);
16073     } else {
16074         /*
16075         * SPEC (2.1) "B and D must be the same type definition."
16076         */
16077         return (0);
16078     }
16079     /*
16080     * SPEC (2.2) "B must be D's {base type definition}."
16081     */
16082     if (type->baseType == baseType)
16083         return (0);
16084     /*
16085     * SPEC (2.3.1) "D's {base type definition} must not be the `ur-type
16086     * definition`."
16087     */
16088     if (WXS_IS_ANYTYPE(type->baseType))
16089         return (1);
16090
16091     if (WXS_IS_COMPLEX(type->baseType)) {
16092         /*
16093         * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
16094         * must be validly derived from B given the subset as defined by this
16095         * constraint."
16096         */
16097         return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
16098             baseType, set));
16099     } else {
16100         /*
16101         * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
16102         * must be validly derived from B given the subset as defined in Type
16103         * Derivation OK (Simple) ($3.14.6).
16104         */
16105         return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
16106             baseType, set));
16107     }
16108 }
16109
16110 /**
16111  * xmlSchemaCheckCOSDerivedOK:
16112  * @type:  the derived simple type definition
16113  * @baseType:  the base type definition
16114  *
16115  * Calls:
16116  * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
16117  *
16118  * Checks wheter @type can be validly derived from @baseType.
16119  *
16120  * Returns 0 on success, an positive error code otherwise.
16121  */
16122 static int
16123 xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16124                            xmlSchemaTypePtr type,
16125                            xmlSchemaTypePtr baseType,
16126                            int set)
16127 {
16128     if (WXS_IS_SIMPLE(type))
16129         return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
16130     else
16131         return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
16132 }
16133
16134 /**
16135  * xmlSchemaCheckCOSCTExtends:
16136  * @ctxt:  the schema parser context
16137  * @type:  the complex type definition
16138  *
16139  * (3.4.6) Constraints on Complex Type Definition Schema Components
16140  * Schema Component Constraint:
16141  * Derivation Valid (Extension) (cos-ct-extends)
16142  *
16143  * STATUS:
16144  *   missing:
16145  *     (1.5)
16146  *     (1.4.3.2.2.2) "Particle Valid (Extension)"
16147  *
16148  * Returns 0 if the constraints are satisfied, a positive
16149  * error code if not and -1 if an internal error occurred.
16150  */
16151 static int
16152 xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16153                            xmlSchemaTypePtr type)
16154 {
16155     xmlSchemaTypePtr base = type->baseType;
16156     /*
16157     * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16158     * temporarily only.
16159     */
16160     /*
16161     * SPEC (1) "If the {base type definition} is a complex type definition,
16162     * then all of the following must be true:"
16163     */
16164     if (WXS_IS_COMPLEX(base)) {
16165         /*
16166         * SPEC (1.1) "The {final} of the {base type definition} must not
16167         * contain extension."
16168         */
16169         if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16170             xmlSchemaPCustomErr(ctxt,
16171                 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16172                 WXS_BASIC_CAST type, NULL,
16173                 "The 'final' of the base type definition "
16174                 "contains 'extension'", NULL);
16175             return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16176         }
16177
16178         /*
16179         * ATTENTION: The constrains (1.2) and (1.3) are not applied,
16180         * since they are automatically satisfied through the
16181         * inheriting mechanism.
16182         * Note that even if redefining components, the inheriting mechanism
16183         * is used.
16184         */
16185 #if 0
16186         /*
16187         * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
16188         * uses}
16189         * of the complex type definition itself, that is, for every attribute
16190         * use in the {attribute uses} of the {base type definition}, there
16191         * must be an attribute use in the {attribute uses} of the complex
16192         * type definition itself whose {attribute declaration} has the same
16193         * {name}, {target namespace} and {type definition} as its attribute
16194         * declaration"
16195         */
16196         if (base->attrUses != NULL) {
16197             int i, j, found;
16198             xmlSchemaAttributeUsePtr use, buse;
16199
16200             for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16201                 buse = (WXS_LIST_CAST base->attrUses)->items[i];
16202                 found = 0;
16203                 if (type->attrUses != NULL) {
16204                     use = (WXS_LIST_CAST type->attrUses)->items[j];
16205                     for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16206                     {
16207                         if ((WXS_ATTRUSE_DECL_NAME(use) ==
16208                                 WXS_ATTRUSE_DECL_NAME(buse)) &&
16209                             (WXS_ATTRUSE_DECL_TNS(use) ==
16210                                 WXS_ATTRUSE_DECL_TNS(buse)) &&
16211                             (WXS_ATTRUSE_TYPEDEF(use) ==
16212                                 WXS_ATTRUSE_TYPEDEF(buse))
16213                         {
16214                             found = 1;
16215                             break;
16216                         }
16217                     }
16218                 }
16219                 if (! found) {
16220                     xmlChar *str = NULL;
16221
16222                     xmlSchemaCustomErr(ACTXT_CAST ctxt,
16223                         XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16224                         NULL, WXS_BASIC_CAST type,
16225                         /*
16226                         * TODO: The report does not indicate that also the
16227                         * type needs to be the same.
16228                         */
16229                         "This type is missing a matching correspondent "
16230                         "for its {base type}'s %s in its {attribute uses}",
16231                         xmlSchemaGetComponentDesignation(&str,
16232                             buse->children),
16233                         NULL);
16234                     FREE_AND_NULL(str)
16235                 }
16236             }
16237         }
16238         /*
16239         * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16240         * definition must also have one, and the base type definition's
16241         * {attribute  wildcard}'s {namespace constraint} must be a subset
16242         * of the complex  type definition's {attribute wildcard}'s {namespace
16243         * constraint}, as defined by Wildcard Subset ($3.10.6)."
16244         */
16245
16246         /*
16247         * MAYBE TODO: Enable if ever needed. But this will be needed only
16248         * if created the type via a schema construction API.
16249         */
16250         if (base->attributeWildcard != NULL) {
16251             if (type->attributeWilcard == NULL) {
16252                 xmlChar *str = NULL;
16253
16254                 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16255                     XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16256                     NULL, type,
16257                     "The base %s has an attribute wildcard, "
16258                     "but this type is missing an attribute wildcard",
16259                     xmlSchemaGetComponentDesignation(&str, base));
16260                 FREE_AND_NULL(str)
16261
16262             } else if (xmlSchemaCheckCOSNSSubset(
16263                 base->attributeWildcard, type->attributeWildcard))
16264             {
16265                 xmlChar *str = NULL;
16266
16267                 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16268                     XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16269                     NULL, type,
16270                     "The attribute wildcard is not a valid "
16271                     "superset of the one in the base %s",
16272                     xmlSchemaGetComponentDesignation(&str, base));
16273                 FREE_AND_NULL(str)
16274             }
16275         }
16276 #endif
16277         /*
16278         * SPEC (1.4) "One of the following must be true:"
16279         */
16280         if ((type->contentTypeDef != NULL) &&
16281             (type->contentTypeDef == base->contentTypeDef)) {
16282             /*
16283             * SPEC (1.4.1) "The {content type} of the {base type definition}
16284             * and the {content type} of the complex type definition itself
16285             * must be the same simple type definition"
16286             * PASS
16287             */
16288         } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16289             (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16290             /*
16291             * SPEC (1.4.2) "The {content type} of both the {base type
16292             * definition} and the complex type definition itself must
16293             * be empty."
16294             * PASS
16295             */
16296         } else {
16297             /*
16298             * SPEC (1.4.3) "All of the following must be true:"
16299             */
16300             if (type->subtypes == NULL) {
16301                 /*
16302                 * SPEC 1.4.3.1 The {content type} of the complex type
16303                 * definition itself must specify a particle.
16304                 */
16305                 xmlSchemaPCustomErr(ctxt,
16306                     XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16307                     WXS_BASIC_CAST type, NULL,
16308                     "The content type must specify a particle", NULL);
16309                 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16310             }
16311             /*
16312             * SPEC (1.4.3.2) "One of the following must be true:"
16313             */
16314             if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16315                 /*
16316                 * SPEC (1.4.3.2.1) "The {content type} of the {base type
16317                 * definition} must be empty.
16318                 * PASS
16319                 */
16320             } else {
16321                 /*
16322                 * SPEC (1.4.3.2.2) "All of the following must be true:"
16323                 */
16324                 if ((type->contentType != base->contentType) ||
16325                     ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16326                     (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16327                     /*
16328                     * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16329                     * or both must be element-only."
16330                     */
16331                     xmlSchemaPCustomErr(ctxt,
16332                         XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16333                         WXS_BASIC_CAST type, NULL,
16334                         "The content type of both, the type and its base "
16335                         "type, must either 'mixed' or 'element-only'", NULL);
16336                     return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16337                 }
16338                 /*
16339                 * URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
16340                 * complex type definition must be a `valid extension`
16341                 * of the {base type definition}'s particle, as defined
16342                 * in Particle Valid (Extension) ($3.9.6)."
16343                 *
16344                 * NOTE that we won't check "Particle Valid (Extension)",
16345                 * since it is ensured by the derivation process in
16346                 * xmlSchemaTypeFixup(). We need to implement this when heading
16347                 * for a construction API
16348                 * TODO: !! This is needed to be checked if redefining a type !!
16349                 */
16350             }
16351             /*
16352             * URGENT TODO (1.5)
16353             */
16354         }
16355     } else {
16356         /*
16357         * SPEC (2) "If the {base type definition} is a simple type definition,
16358         * then all of the following must be true:"
16359         */
16360         if (type->contentTypeDef != base) {
16361             /*
16362             * SPEC (2.1) "The {content type} must be the same simple type
16363             * definition."
16364             */
16365             xmlSchemaPCustomErr(ctxt,
16366                 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16367                 WXS_BASIC_CAST type, NULL,
16368                 "The content type must be the simple base type", NULL);
16369             return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16370         }
16371         if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16372             /*
16373             * SPEC (2.2) "The {final} of the {base type definition} must not
16374             * contain extension"
16375             * NOTE that this is the same as (1.1).
16376             */
16377             xmlSchemaPCustomErr(ctxt,
16378                 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16379                 WXS_BASIC_CAST type, NULL,
16380                 "The 'final' of the base type definition "
16381                 "contains 'extension'", NULL);
16382             return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16383         }
16384     }
16385     return (0);
16386 }
16387
16388 /**
16389  * xmlSchemaCheckDerivationOKRestriction:
16390  * @ctxt:  the schema parser context
16391  * @type:  the complex type definition
16392  *
16393  * (3.4.6) Constraints on Complex Type Definition Schema Components
16394  * Schema Component Constraint:
16395  * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16396  *
16397  * STATUS:
16398  *   missing:
16399  *     (5.4.2) ???
16400  *
16401  * ATTENTION:
16402  * In XML Schema 1.1 this will be:
16403  * Validation Rule: Checking complex type subsumption
16404  *
16405  * Returns 0 if the constraints are satisfied, a positive
16406  * error code if not and -1 if an internal error occurred.
16407  */
16408 static int
16409 xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16410                                       xmlSchemaTypePtr type)
16411 {
16412     xmlSchemaTypePtr base;
16413
16414     /*
16415     * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
16416     * temporarily only.
16417     */
16418     base = type->baseType;
16419     if (! WXS_IS_COMPLEX(base)) {
16420         xmlSchemaCustomErr(ACTXT_CAST ctxt,
16421             XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16422             type->node, WXS_BASIC_CAST type,
16423             "The base type must be a complex type", NULL, NULL);
16424         return(ctxt->err);
16425     }
16426     if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16427         /*
16428         * SPEC (1) "The {base type definition} must be a complex type
16429         * definition whose {final} does not contain restriction."
16430         */
16431         xmlSchemaCustomErr(ACTXT_CAST ctxt,
16432             XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16433             type->node, WXS_BASIC_CAST type,
16434             "The 'final' of the base type definition "
16435             "contains 'restriction'", NULL, NULL);
16436         return (ctxt->err);
16437     }
16438     /*
16439     * SPEC (2), (3) and (4)
16440     * Those are handled in a separate function, since the
16441     * same constraints are needed for redefinition of
16442     * attribute groups as well.
16443     */
16444     if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16445         XML_SCHEMA_ACTION_DERIVE,
16446         WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16447         type->attrUses, base->attrUses,
16448         type->attributeWildcard,
16449         base->attributeWildcard) == -1)
16450     {
16451         return(-1);
16452     }
16453     /*
16454     * SPEC (5) "One of the following must be true:"
16455     */
16456     if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16457         /*
16458         * SPEC (5.1) "The {base type definition} must be the
16459         * `ur-type definition`."
16460         * PASS
16461         */
16462     } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16463             (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16464         /*
16465         * SPEC (5.2.1) "The {content type} of the complex type definition
16466         * must be a simple type definition"
16467         *
16468         * SPEC (5.2.2) "One of the following must be true:"
16469         */
16470         if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16471             (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16472         {
16473             int err;
16474             /*
16475             * SPEC (5.2.2.1) "The {content type} of the {base type
16476             * definition} must be a simple type definition from which
16477             * the {content type} is validly derived given the empty
16478             * set as defined in Type Derivation OK (Simple) ($3.14.6)."
16479             *
16480             * ATTENTION TODO: This seems not needed if the type implicitely
16481             * derived from the base type.
16482             *
16483             */
16484             err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16485                 type->contentTypeDef, base->contentTypeDef, 0);
16486             if (err != 0) {
16487                 xmlChar *strA = NULL, *strB = NULL;
16488
16489                 if (err == -1)
16490                     return(-1);
16491                 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16492                     XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16493                     NULL, WXS_BASIC_CAST type,
16494                     "The {content type} %s is not validly derived from the "
16495                     "base type's {content type} %s",
16496                     xmlSchemaGetComponentDesignation(&strA,
16497                         type->contentTypeDef),
16498                     xmlSchemaGetComponentDesignation(&strB,
16499                         base->contentTypeDef));
16500                 FREE_AND_NULL(strA);
16501                 FREE_AND_NULL(strB);
16502                 return(ctxt->err);
16503             }
16504         } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16505             (xmlSchemaIsParticleEmptiable(
16506                 (xmlSchemaParticlePtr) base->subtypes))) {
16507             /*
16508             * SPEC (5.2.2.2) "The {base type definition} must be mixed
16509             * and have a particle which is `emptiable` as defined in
16510             * Particle Emptiable ($3.9.6)."
16511             * PASS
16512             */
16513         } else {
16514             xmlSchemaPCustomErr(ctxt,
16515                 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16516                 WXS_BASIC_CAST type, NULL,
16517                 "The content type of the base type must be either "
16518                 "a simple type or 'mixed' and an emptiable particle", NULL);
16519             return (ctxt->err);
16520         }
16521     } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16522         /*
16523         * SPEC (5.3.1) "The {content type} of the complex type itself must
16524         * be empty"
16525         */
16526         if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16527             /*
16528             * SPEC (5.3.2.1) "The {content type} of the {base type
16529             * definition} must also be empty."
16530             * PASS
16531             */
16532         } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16533             (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16534             xmlSchemaIsParticleEmptiable(
16535                 (xmlSchemaParticlePtr) base->subtypes)) {
16536             /*
16537             * SPEC (5.3.2.2) "The {content type} of the {base type
16538             * definition} must be elementOnly or mixed and have a particle
16539             * which is `emptiable` as defined in Particle Emptiable ($3.9.6)."
16540             * PASS
16541             */
16542         } else {
16543             xmlSchemaPCustomErr(ctxt,
16544                 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16545                 WXS_BASIC_CAST type, NULL,
16546                 "The content type of the base type must be either "
16547                 "empty or 'mixed' (or 'elements-only') and an emptiable "
16548                 "particle", NULL);
16549             return (ctxt->err);
16550         }
16551     } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16552         WXS_HAS_MIXED_CONTENT(type)) {
16553         /*
16554         * SPEC (5.4.1.1) "The {content type} of the complex type definition
16555         * itself must be element-only"
16556         */
16557         if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
16558             /*
16559             * SPEC (5.4.1.2) "The {content type} of the complex type
16560             * definition itself and of the {base type definition} must be
16561             * mixed"
16562             */
16563             xmlSchemaPCustomErr(ctxt,
16564                 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16565                 WXS_BASIC_CAST type, NULL,
16566                 "If the content type is 'mixed', then the content type of the "
16567                 "base type must also be 'mixed'", NULL);
16568             return (ctxt->err);
16569         }
16570         /*
16571         * SPEC (5.4.2) "The particle of the complex type definition itself
16572         * must be a `valid restriction` of the particle of the {content
16573         * type} of the {base type definition} as defined in Particle Valid
16574         * (Restriction) ($3.9.6).
16575         *
16576         * URGENT TODO: (5.4.2)
16577         */
16578     } else {
16579         xmlSchemaPCustomErr(ctxt,
16580             XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16581             WXS_BASIC_CAST type, NULL,
16582             "The type is not a valid restriction of its base type", NULL);
16583         return (ctxt->err);
16584     }
16585     return (0);
16586 }
16587
16588 /**
16589  * xmlSchemaCheckCTComponent:
16590  * @ctxt:  the schema parser context
16591  * @type:  the complex type definition
16592  *
16593  * (3.4.6) Constraints on Complex Type Definition Schema Components
16594  *
16595  * Returns 0 if the constraints are satisfied, a positive
16596  * error code if not and -1 if an internal error occurred.
16597  */
16598 static int
16599 xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16600                           xmlSchemaTypePtr type)
16601 {
16602     int ret;
16603     /*
16604     * Complex Type Definition Properties Correct
16605     */
16606     ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16607     if (ret != 0)
16608         return (ret);
16609     if (WXS_IS_EXTENSION(type))
16610         ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16611     else
16612         ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16613     return (ret);
16614 }
16615
16616 /**
16617  * xmlSchemaCheckSRCCT:
16618  * @ctxt:  the schema parser context
16619  * @type:  the complex type definition
16620  *
16621  * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
16622  * Schema Representation Constraint:
16623  * Complex Type Definition Representation OK (src-ct)
16624  *
16625  * Returns 0 if the constraints are satisfied, a positive
16626  * error code if not and -1 if an internal error occurred.
16627  */
16628 static int
16629 xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
16630                     xmlSchemaTypePtr type)
16631 {
16632     xmlSchemaTypePtr base;
16633     int ret = 0;
16634
16635     /*
16636     * TODO: Adjust the error codes here, as I used
16637     * XML_SCHEMAP_SRC_CT_1 only yet.
16638     */
16639     base = type->baseType;
16640     if (! WXS_HAS_SIMPLE_CONTENT(type)) {
16641         /*
16642         * 1 If the <complexContent> alternative is chosen, the type definition
16643         * `resolved` to by the `actual value` of the base [attribute]
16644         * must be a complex type definition;
16645         */
16646         if (! WXS_IS_COMPLEX(base)) {
16647             xmlChar *str = NULL;
16648             xmlSchemaPCustomErr(ctxt,
16649                 XML_SCHEMAP_SRC_CT_1,
16650                 WXS_BASIC_CAST type, type->node,
16651                 "If using <complexContent>, the base type is expected to be "
16652                 "a complex type. The base type '%s' is a simple type",
16653                 xmlSchemaFormatQName(&str, base->targetNamespace,
16654                 base->name));
16655             FREE_AND_NULL(str)
16656             return (XML_SCHEMAP_SRC_CT_1);
16657         }
16658     } else {
16659         /*
16660         * SPEC
16661         * 2 If the <simpleContent> alternative is chosen, all of the
16662         * following must be true:
16663         * 2.1 The type definition `resolved` to by the `actual value` of the
16664         * base [attribute] must be one of the following:
16665         */
16666         if (WXS_IS_SIMPLE(base)) {
16667             if (WXS_IS_EXTENSION(type) == 0) {
16668                 xmlChar *str = NULL;
16669                 /*
16670                 * 2.1.3 only if the <extension> alternative is also
16671                 * chosen, a simple type definition.
16672                 */
16673                 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
16674                 xmlSchemaPCustomErr(ctxt,
16675                     XML_SCHEMAP_SRC_CT_1,
16676                     WXS_BASIC_CAST type, NULL,
16677                     "If using <simpleContent> and <restriction>, the base "
16678                     "type must be a complex type. The base type '%s' is "
16679                     "a simple type",
16680                     xmlSchemaFormatQName(&str, base->targetNamespace,
16681                         base->name));
16682                 FREE_AND_NULL(str)
16683                 return (XML_SCHEMAP_SRC_CT_1);
16684             }
16685         } else {
16686             /* Base type is a complex type. */
16687             if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16688                 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16689                 /*
16690                 * 2.1.1 a complex type definition whose {content type} is a
16691                 * simple type definition;
16692                 * PASS
16693                 */
16694                 if (base->contentTypeDef == NULL) {
16695                     xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16696                         WXS_BASIC_CAST type, NULL,
16697                         "Internal error: xmlSchemaCheckSRCCT, "
16698                         "'%s', base type has no content type",
16699                         type->name);
16700                     return (-1);
16701                 }
16702             } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16703                 (WXS_IS_RESTRICTION(type))) {
16704
16705                 /*
16706                 * 2.1.2 only if the <restriction> alternative is also
16707                 * chosen, a complex type definition whose {content type}
16708                 * is mixed and a particle emptiable.
16709                 */
16710                 if (! xmlSchemaIsParticleEmptiable(
16711                     (xmlSchemaParticlePtr) base->subtypes)) {
16712                     ret = XML_SCHEMAP_SRC_CT_1;
16713                 } else
16714                     /*
16715                     * Attention: at this point the <simpleType> child is in
16716                     * ->contentTypeDef (put there during parsing).
16717                     */
16718                     if (type->contentTypeDef == NULL) {
16719                     xmlChar *str = NULL;
16720                     /*
16721                     * 2.2 If clause 2.1.2 above is satisfied, then there
16722                     * must be a <simpleType> among the [children] of
16723                     * <restriction>.
16724                     */
16725                     /* TODO: Change error code to ..._SRC_CT_2_2. */
16726                     xmlSchemaPCustomErr(ctxt,
16727                         XML_SCHEMAP_SRC_CT_1,
16728                         WXS_BASIC_CAST type, NULL,
16729                         "A <simpleType> is expected among the children "
16730                         "of <restriction>, if <simpleContent> is used and "
16731                         "the base type '%s' is a complex type",
16732                         xmlSchemaFormatQName(&str, base->targetNamespace,
16733                         base->name));
16734                     FREE_AND_NULL(str)
16735                     return (XML_SCHEMAP_SRC_CT_1);
16736                 }
16737             } else {
16738                 ret = XML_SCHEMAP_SRC_CT_1;
16739             }
16740         }
16741         if (ret > 0) {
16742             xmlChar *str = NULL;
16743             if (WXS_IS_RESTRICTION(type)) {
16744                 xmlSchemaPCustomErr(ctxt,
16745                     XML_SCHEMAP_SRC_CT_1,
16746                     WXS_BASIC_CAST type, NULL,
16747                     "If <simpleContent> and <restriction> is used, the "
16748                     "base type must be a simple type or a complex type with "
16749                     "mixed content and particle emptiable. The base type "
16750                     "'%s' is none of those",
16751                     xmlSchemaFormatQName(&str, base->targetNamespace,
16752                     base->name));
16753             } else {
16754                 xmlSchemaPCustomErr(ctxt,
16755                     XML_SCHEMAP_SRC_CT_1,
16756                     WXS_BASIC_CAST type, NULL,
16757                     "If <simpleContent> and <extension> is used, the "
16758                     "base type must be a simple type. The base type '%s' "
16759                     "is a complex type",
16760                     xmlSchemaFormatQName(&str, base->targetNamespace,
16761                     base->name));
16762             }
16763             FREE_AND_NULL(str)
16764         }
16765     }
16766     /*
16767     * SPEC (3) "The corresponding complex type definition component must
16768     * satisfy the conditions set out in Constraints on Complex Type
16769     * Definition Schema Components ($3.4.6);"
16770     * NOTE (3) will be done in xmlSchemaTypeFixup().
16771     */
16772     /*
16773     * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
16774     * above for {attribute wildcard} is satisfied, the intensional
16775     * intersection must be expressible, as defined in Attribute Wildcard
16776     * Intersection ($3.10.6).
16777     * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
16778     */
16779     return (ret);
16780 }
16781
16782 #ifdef ENABLE_PARTICLE_RESTRICTION
16783 /**
16784  * xmlSchemaCheckParticleRangeOK:
16785  * @ctxt:  the schema parser context
16786  * @type:  the complex type definition
16787  *
16788  * (3.9.6) Constraints on Particle Schema Components
16789  * Schema Component Constraint:
16790  * Occurrence Range OK (range-ok)
16791  *
16792  * STATUS: complete
16793  *
16794  * Returns 0 if the constraints are satisfied, a positive
16795  * error code if not and -1 if an internal error occurred.
16796  */
16797 static int
16798 xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16799                               int bmin, int bmax)
16800 {
16801     if (rmin < bmin)
16802         return (1);
16803     if ((bmax != UNBOUNDED) &&
16804         (rmax > bmax))
16805         return (1);
16806     return (0);
16807 }
16808
16809 /**
16810  * xmlSchemaCheckRCaseNameAndTypeOK:
16811  * @ctxt:  the schema parser context
16812  * @r: the restricting element declaration particle
16813  * @b: the base element declaration particle
16814  *
16815  * (3.9.6) Constraints on Particle Schema Components
16816  * Schema Component Constraint:
16817  * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16818  * (rcase-NameAndTypeOK)
16819  *
16820  * STATUS:
16821  *   MISSING (3.2.3)
16822  *   CLARIFY: (3.2.2)
16823  *
16824  * Returns 0 if the constraints are satisfied, a positive
16825  * error code if not and -1 if an internal error occurred.
16826  */
16827 static int
16828 xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16829                                  xmlSchemaParticlePtr r,
16830                                  xmlSchemaParticlePtr b)
16831 {
16832     xmlSchemaElementPtr elemR, elemB;
16833
16834     /* TODO: Error codes (rcase-NameAndTypeOK). */
16835     elemR = (xmlSchemaElementPtr) r->children;
16836     elemB = (xmlSchemaElementPtr) b->children;
16837     /*
16838     * SPEC (1) "The declarations' {name}s and {target namespace}s are
16839     * the same."
16840     */
16841     if ((elemR != elemB) &&
16842         ((! xmlStrEqual(elemR->name, elemB->name)) ||
16843         (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16844         return (1);
16845     /*
16846     * SPEC (2) "R's occurrence range is a valid restriction of B's
16847     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
16848     */
16849     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16850             b->minOccurs, b->maxOccurs) != 0)
16851         return (1);
16852     /*
16853     * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16854     * {scope} are global."
16855     */
16856     if (elemR == elemB)
16857         return (0);
16858     /*
16859     * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16860     */
16861     if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16862         (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16863          return (1);
16864     /*
16865     * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16866     * or is not fixed, or R's declaration's {value constraint} is fixed
16867     * with the same value."
16868     */
16869     if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16870         ((elemR->value == NULL) ||
16871          ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16872          /* TODO: Equality of the initial value or normalized or canonical? */
16873          (! xmlStrEqual(elemR->value, elemB->value))))
16874          return (1);
16875     /*
16876     * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16877     * definitions} is a subset of B's declaration's {identity-constraint
16878     * definitions}, if any."
16879     */
16880     if (elemB->idcs != NULL) {
16881         /* TODO */
16882     }
16883     /*
16884     * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16885     * superset of B's declaration's {disallowed substitutions}."
16886     */
16887     if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16888          ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16889         ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16890          ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16891         ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16892          ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16893          return (1);
16894     /*
16895     * SPEC (3.2.5) "R's {type definition} is validly derived given
16896     * {extension, list, union} from B's {type definition}"
16897     *
16898     * BADSPEC TODO: What's the point of adding "list" and "union" to the
16899     * set, if the corresponding constraints handle "restriction" and
16900     * "extension" only?
16901     *
16902     */
16903     {
16904         int set = 0;
16905
16906         set |= SUBSET_EXTENSION;
16907         set |= SUBSET_LIST;
16908         set |= SUBSET_UNION;
16909         if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
16910             elemB->subtypes, set) != 0)
16911             return (1);
16912     }
16913     return (0);
16914 }
16915
16916 /**
16917  * xmlSchemaCheckRCaseNSCompat:
16918  * @ctxt:  the schema parser context
16919  * @r: the restricting element declaration particle
16920  * @b: the base wildcard particle
16921  *
16922  * (3.9.6) Constraints on Particle Schema Components
16923  * Schema Component Constraint:
16924  * Particle Derivation OK (Elt:Any -- NSCompat)
16925  * (rcase-NSCompat)
16926  *
16927  * STATUS: complete
16928  *
16929  * Returns 0 if the constraints are satisfied, a positive
16930  * error code if not and -1 if an internal error occurred.
16931  */
16932 static int
16933 xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16934                             xmlSchemaParticlePtr r,
16935                             xmlSchemaParticlePtr b)
16936 {
16937     /* TODO:Error codes (rcase-NSCompat). */
16938     /*
16939     * SPEC "For an element declaration particle to be a `valid restriction`
16940     * of a wildcard particle all of the following must be true:"
16941     *
16942     * SPEC (1) "The element declaration's {target namespace} is `valid`
16943     * with respect to the wildcard's {namespace constraint} as defined by
16944     * Wildcard allows Namespace Name ($3.10.4)."
16945     */
16946     if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
16947         ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16948         return (1);
16949     /*
16950     * SPEC (2) "R's occurrence range is a valid restriction of B's
16951     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
16952     */
16953     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16954             b->minOccurs, b->maxOccurs) != 0)
16955         return (1);
16956
16957     return (0);
16958 }
16959
16960 /**
16961  * xmlSchemaCheckRCaseRecurseAsIfGroup:
16962  * @ctxt:  the schema parser context
16963  * @r: the restricting element declaration particle
16964  * @b: the base model group particle
16965  *
16966  * (3.9.6) Constraints on Particle Schema Components
16967  * Schema Component Constraint:
16968  * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
16969  * (rcase-RecurseAsIfGroup)
16970  *
16971  * STATUS: TODO
16972  *
16973  * Returns 0 if the constraints are satisfied, a positive
16974  * error code if not and -1 if an internal error occurred.
16975  */
16976 static int
16977 xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16978                                     xmlSchemaParticlePtr r,
16979                                     xmlSchemaParticlePtr b)
16980 {
16981     /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16982     TODO
16983     return (0);
16984 }
16985
16986 /**
16987  * xmlSchemaCheckRCaseNSSubset:
16988  * @ctxt:  the schema parser context
16989  * @r: the restricting wildcard particle
16990  * @b: the base wildcard particle
16991  *
16992  * (3.9.6) Constraints on Particle Schema Components
16993  * Schema Component Constraint:
16994  * Particle Derivation OK (Any:Any -- NSSubset)
16995  * (rcase-NSSubset)
16996  *
16997  * STATUS: complete
16998  *
16999  * Returns 0 if the constraints are satisfied, a positive
17000  * error code if not and -1 if an internal error occurred.
17001  */
17002 static int
17003 xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
17004                                     xmlSchemaParticlePtr r,
17005                                     xmlSchemaParticlePtr b,
17006                                     int isAnyTypeBase)
17007 {
17008     /* TODO: Error codes (rcase-NSSubset). */
17009     /*
17010     * SPEC (1) "R's occurrence range is a valid restriction of B's
17011     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17012     */
17013     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17014             b->minOccurs, b->maxOccurs))
17015         return (1);
17016     /*
17017     * SPEC (2) "R's {namespace constraint} must be an intensional subset
17018     * of B's {namespace constraint} as defined by Wildcard Subset ($3.10.6)."
17019     */
17020     if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
17021         (xmlSchemaWildcardPtr) b->children))
17022         return (1);
17023     /*
17024     * SPEC (3) "Unless B is the content model wildcard of the `ur-type
17025     * definition`, R's {process contents} must be identical to or stronger
17026     * than B's {process contents}, where strict is stronger than lax is
17027     * stronger than skip."
17028     */
17029     if (! isAnyTypeBase) {
17030         if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
17031             ((xmlSchemaWildcardPtr) b->children)->processContents)
17032             return (1);
17033     }
17034
17035     return (0);
17036 }
17037
17038 /**
17039  * xmlSchemaCheckCOSParticleRestrict:
17040  * @ctxt:  the schema parser context
17041  * @type:  the complex type definition
17042  *
17043  * (3.9.6) Constraints on Particle Schema Components
17044  * Schema Component Constraint:
17045  * Particle Valid (Restriction) (cos-particle-restrict)
17046  *
17047  * STATUS: TODO
17048  *
17049  * Returns 0 if the constraints are satisfied, a positive
17050  * error code if not and -1 if an internal error occurred.
17051  */
17052 static int
17053 xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
17054                                   xmlSchemaParticlePtr r,
17055                                   xmlSchemaParticlePtr b)
17056 {
17057     int ret = 0;
17058
17059     /*part = WXS_TYPE_PARTICLE(type);
17060     basePart = WXS_TYPE_PARTICLE(base);
17061     */
17062
17063     TODO
17064
17065     /*
17066     * SPEC (1) "They are the same particle."
17067     */
17068     if (r == b)
17069         return (0);
17070
17071
17072     return (0);
17073 }
17074
17075 #if 0
17076 /**
17077  * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
17078  * @ctxt:  the schema parser context
17079  * @r: the model group particle
17080  * @b: the base wildcard particle
17081  *
17082  * (3.9.6) Constraints on Particle Schema Components
17083  * Schema Component Constraint:
17084  * Particle Derivation OK (All/Choice/Sequence:Any --
17085  *                         NSRecurseCheckCardinality)
17086  * (rcase-NSRecurseCheckCardinality)
17087  *
17088  * STATUS: TODO: subst-groups
17089  *
17090  * Returns 0 if the constraints are satisfied, a positive
17091  * error code if not and -1 if an internal error occurred.
17092  */
17093 static int
17094 xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
17095                                              xmlSchemaParticlePtr r,
17096                                              xmlSchemaParticlePtr b)
17097 {
17098     xmlSchemaParticlePtr part;
17099     /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
17100     if ((r->children == NULL) || (r->children->children == NULL))
17101         return (-1);
17102     /*
17103     * SPEC "For a group particle to be a `valid restriction` of a
17104     * wildcard particle..."
17105     *
17106     * SPEC (1) "Every member of the {particles} of the group is a `valid
17107     * restriction` of the wildcard as defined by
17108     * Particle Valid (Restriction) ($3.9.6)."
17109     */
17110     part = (xmlSchemaParticlePtr) r->children->children;
17111     do {
17112         if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
17113             return (1);
17114         part = (xmlSchemaParticlePtr) part->next;
17115     } while (part != NULL);
17116     /*
17117     * SPEC (2) "The effective total range of the group [...] is a
17118     * valid restriction of B's occurrence range as defined by
17119     * Occurrence Range OK ($3.9.6)."
17120     */
17121     if (xmlSchemaCheckParticleRangeOK(
17122             xmlSchemaGetParticleTotalRangeMin(r),
17123             xmlSchemaGetParticleTotalRangeMax(r),
17124             b->minOccurs, b->maxOccurs) != 0)
17125         return (1);
17126     return (0);
17127 }
17128 #endif
17129
17130 /**
17131  * xmlSchemaCheckRCaseRecurse:
17132  * @ctxt:  the schema parser context
17133  * @r: the <all> or <sequence> model group particle
17134  * @b: the base <all> or <sequence> model group particle
17135  *
17136  * (3.9.6) Constraints on Particle Schema Components
17137  * Schema Component Constraint:
17138  * Particle Derivation OK (All:All,Sequence:Sequence --
17139                            Recurse)
17140  * (rcase-Recurse)
17141  *
17142  * STATUS:  ?
17143  * TODO: subst-groups
17144  *
17145  * Returns 0 if the constraints are satisfied, a positive
17146  * error code if not and -1 if an internal error occurred.
17147  */
17148 static int
17149 xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17150                            xmlSchemaParticlePtr r,
17151                            xmlSchemaParticlePtr b)
17152 {
17153     /* xmlSchemaParticlePtr part; */
17154     /* TODO: Error codes (rcase-Recurse). */
17155     if ((r->children == NULL) || (b->children == NULL) ||
17156         (r->children->type != b->children->type))
17157         return (-1);
17158     /*
17159     * SPEC "For an all or sequence group particle to be a `valid
17160     * restriction` of another group particle with the same {compositor}..."
17161     *
17162     * SPEC (1) "R's occurrence range is a valid restriction of B's
17163     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17164     */
17165     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17166             b->minOccurs, b->maxOccurs))
17167         return (1);
17168
17169
17170     return (0);
17171 }
17172
17173 #endif
17174
17175 #define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17176     xmlSchemaPCustomErrExt(pctxt,      \
17177         XML_SCHEMAP_INVALID_FACET_VALUE, \
17178         WXS_BASIC_CAST fac1, fac1->node, \
17179         "It is an error for both '%s' and '%s' to be specified on the "\
17180         "same type definition", \
17181         BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17182         BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17183
17184 #define FACET_RESTR_ERR(fac1, msg) \
17185     xmlSchemaPCustomErr(pctxt,      \
17186         XML_SCHEMAP_INVALID_FACET_VALUE, \
17187         WXS_BASIC_CAST fac1, fac1->node, \
17188         msg, NULL);
17189
17190 #define FACET_RESTR_FIXED_ERR(fac) \
17191     xmlSchemaPCustomErr(pctxt, \
17192         XML_SCHEMAP_INVALID_FACET_VALUE, \
17193         WXS_BASIC_CAST fac, fac->node, \
17194         "The base type's facet is 'fixed', thus the value must not " \
17195         "differ", NULL);
17196
17197 static void
17198 xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17199                         xmlSchemaFacetPtr facet1,
17200                         xmlSchemaFacetPtr facet2,
17201                         int lessGreater,
17202                         int orEqual,
17203                         int ofBase)
17204 {
17205     xmlChar *msg = NULL;
17206
17207     msg = xmlStrdup(BAD_CAST "'");
17208     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17209     msg = xmlStrcat(msg, BAD_CAST "' has to be");
17210     if (lessGreater == 0)
17211         msg = xmlStrcat(msg, BAD_CAST " equal to");
17212     if (lessGreater == 1)
17213         msg = xmlStrcat(msg, BAD_CAST " greater than");
17214     else
17215         msg = xmlStrcat(msg, BAD_CAST " less than");
17216
17217     if (orEqual)
17218         msg = xmlStrcat(msg, BAD_CAST " or equal to");
17219     msg = xmlStrcat(msg, BAD_CAST " '");
17220     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17221     if (ofBase)
17222         msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17223     else
17224         msg = xmlStrcat(msg, BAD_CAST "'");
17225
17226     xmlSchemaPCustomErr(pctxt,
17227         XML_SCHEMAP_INVALID_FACET_VALUE,
17228         WXS_BASIC_CAST facet1, NULL,
17229         (const char *) msg, NULL);
17230
17231     if (msg != NULL)
17232         xmlFree(msg);
17233 }
17234
17235 /*
17236 * xmlSchemaDeriveAndValidateFacets:
17237 *
17238 * Schema Component Constraint: Simple Type Restriction (Facets)
17239 * (st-restrict-facets)
17240 */
17241 static int
17242 xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17243                                  xmlSchemaTypePtr type)
17244 {
17245     xmlSchemaTypePtr base = type->baseType;
17246     xmlSchemaFacetLinkPtr link, cur, last = NULL;
17247     xmlSchemaFacetPtr facet, bfacet,
17248         flength = NULL, ftotdig = NULL, ffracdig = NULL,
17249         fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17250         fmininc = NULL, fmaxinc = NULL,
17251         fminexc = NULL, fmaxexc = NULL,
17252         bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17253         bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17254         bfmininc = NULL, bfmaxinc = NULL,
17255         bfminexc = NULL, bfmaxexc = NULL;
17256     int res; /* err = 0, fixedErr; */
17257
17258     /*
17259     * SPEC st-restrict-facets 1:
17260     * "The {variety} of R is the same as that of B."
17261     */
17262     /*
17263     * SPEC st-restrict-facets 2:
17264     * "If {variety} is atomic, the {primitive type definition}
17265     * of R is the same as that of B."
17266     *
17267     * NOTE: we leave 1 & 2 out for now, since this will be
17268     * satisfied by the derivation process.
17269     * CONSTRUCTION TODO: Maybe needed if using a construction API.
17270     */
17271     /*
17272     * SPEC st-restrict-facets 3:
17273     * "The {facets} of R are the union of S and the {facets}
17274     * of B, eliminating duplicates. To eliminate duplicates,
17275     * when a facet of the same kind occurs in both S and the
17276     * {facets} of B, the one in the {facets} of B is not
17277     * included, with the exception of enumeration and pattern
17278     * facets, for which multiple occurrences with distinct values
17279     * are allowed."
17280     */
17281
17282     if ((type->facetSet == NULL) && (base->facetSet == NULL))
17283         return (0);
17284
17285     last = type->facetSet;
17286     if (last != NULL)
17287         while (last->next != NULL)
17288             last = last->next;
17289
17290     for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17291         facet = cur->facet;
17292         switch (facet->type) {
17293             case XML_SCHEMA_FACET_LENGTH:
17294                 flength = facet; break;
17295             case XML_SCHEMA_FACET_MINLENGTH:
17296                 fminlen = facet; break;
17297             case XML_SCHEMA_FACET_MININCLUSIVE:
17298                 fmininc = facet; break;
17299             case XML_SCHEMA_FACET_MINEXCLUSIVE:
17300                 fminexc = facet; break;
17301             case XML_SCHEMA_FACET_MAXLENGTH:
17302                 fmaxlen = facet; break;
17303             case XML_SCHEMA_FACET_MAXINCLUSIVE:
17304                 fmaxinc = facet; break;
17305             case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17306                 fmaxexc = facet; break;
17307             case XML_SCHEMA_FACET_TOTALDIGITS:
17308                 ftotdig = facet; break;
17309             case XML_SCHEMA_FACET_FRACTIONDIGITS:
17310                 ffracdig = facet; break;
17311             default:
17312                 break;
17313         }
17314     }
17315     for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17316         facet = cur->facet;
17317         switch (facet->type) {
17318             case XML_SCHEMA_FACET_LENGTH:
17319                 bflength = facet; break;
17320             case XML_SCHEMA_FACET_MINLENGTH:
17321                 bfminlen = facet; break;
17322             case XML_SCHEMA_FACET_MININCLUSIVE:
17323                 bfmininc = facet; break;
17324             case XML_SCHEMA_FACET_MINEXCLUSIVE:
17325                 bfminexc = facet; break;
17326             case XML_SCHEMA_FACET_MAXLENGTH:
17327                 bfmaxlen = facet; break;
17328             case XML_SCHEMA_FACET_MAXINCLUSIVE:
17329                 bfmaxinc = facet; break;
17330             case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17331                 bfmaxexc = facet; break;
17332             case XML_SCHEMA_FACET_TOTALDIGITS:
17333                 bftotdig = facet; break;
17334             case XML_SCHEMA_FACET_FRACTIONDIGITS:
17335                 bffracdig = facet; break;
17336             default:
17337                 break;
17338         }
17339     }
17340     /*
17341     * length and minLength or maxLength (2.2) + (3.2)
17342     */
17343     if (flength && (fminlen || fmaxlen)) {
17344         FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17345             "either of 'minLength' or 'maxLength' to be specified on "
17346             "the same type definition")
17347     }
17348     /*
17349     * Mutual exclusions in the same derivation step.
17350     */
17351     if ((fmaxinc) && (fmaxexc)) {
17352         /*
17353         * SCC "maxInclusive and maxExclusive"
17354         */
17355         FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17356     }
17357     if ((fmininc) && (fminexc)) {
17358         /*
17359         * SCC "minInclusive and minExclusive"
17360         */
17361         FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
17362     }
17363
17364     if (flength && bflength) {
17365         /*
17366         * SCC "length valid restriction"
17367         * The values have to be equal.
17368         */
17369         res = xmlSchemaCompareValues(flength->val, bflength->val);
17370         if (res == -2)
17371             goto internal_error;
17372         if (res != 0)
17373             xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17374         if ((res != 0) && (bflength->fixed)) {
17375             FACET_RESTR_FIXED_ERR(flength)
17376         }
17377
17378     }
17379     if (fminlen && bfminlen) {
17380         /*
17381         * SCC "minLength valid restriction"
17382         * minLength >= BASE minLength
17383         */
17384         res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17385         if (res == -2)
17386             goto internal_error;
17387         if (res == -1)
17388             xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17389         if ((res != 0) && (bfminlen->fixed)) {
17390             FACET_RESTR_FIXED_ERR(fminlen)
17391         }
17392     }
17393     if (fmaxlen && bfmaxlen) {
17394         /*
17395         * SCC "maxLength valid restriction"
17396         * maxLength <= BASE minLength
17397         */
17398         res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17399         if (res == -2)
17400             goto internal_error;
17401         if (res == 1)
17402             xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17403         if ((res != 0) && (bfmaxlen->fixed)) {
17404             FACET_RESTR_FIXED_ERR(fmaxlen)
17405         }
17406     }
17407     /*
17408     * SCC "length and minLength or maxLength"
17409     */
17410     if (! flength)
17411         flength = bflength;
17412     if (flength) {
17413         if (! fminlen)
17414             fminlen = bfminlen;
17415         if (fminlen) {
17416             /* (1.1) length >= minLength */
17417             res = xmlSchemaCompareValues(flength->val, fminlen->val);
17418             if (res == -2)
17419                 goto internal_error;
17420             if (res == -1)
17421                 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17422         }
17423         if (! fmaxlen)
17424             fmaxlen = bfmaxlen;
17425         if (fmaxlen) {
17426             /* (2.1) length <= maxLength */
17427             res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17428             if (res == -2)
17429                 goto internal_error;
17430             if (res == 1)
17431                 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17432         }
17433     }
17434     if (fmaxinc) {
17435         /*
17436         * "maxInclusive"
17437         */
17438         if (fmininc) {
17439             /* SCC "maxInclusive >= minInclusive" */
17440             res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17441             if (res == -2)
17442                 goto internal_error;
17443             if (res == -1) {
17444                 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17445             }
17446         }
17447         /*
17448         * SCC "maxInclusive valid restriction"
17449         */
17450         if (bfmaxinc) {
17451             /* maxInclusive <= BASE maxInclusive */
17452             res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17453             if (res == -2)
17454                 goto internal_error;
17455             if (res == 1)
17456                 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17457             if ((res != 0) && (bfmaxinc->fixed)) {
17458                 FACET_RESTR_FIXED_ERR(fmaxinc)
17459             }
17460         }
17461         if (bfmaxexc) {
17462             /* maxInclusive < BASE maxExclusive */
17463             res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17464             if (res == -2)
17465                 goto internal_error;
17466             if (res != -1) {
17467                 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17468             }
17469         }
17470         if (bfmininc) {
17471             /* maxInclusive >= BASE minInclusive */
17472             res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17473             if (res == -2)
17474                 goto internal_error;
17475             if (res == -1) {
17476                 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17477             }
17478         }
17479         if (bfminexc) {
17480             /* maxInclusive > BASE minExclusive */
17481             res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17482             if (res == -2)
17483                 goto internal_error;
17484             if (res != 1) {
17485                 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17486             }
17487         }
17488     }
17489     if (fmaxexc) {
17490         /*
17491         * "maxExclusive >= minExclusive"
17492         */
17493         if (fminexc) {
17494             res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17495             if (res == -2)
17496                 goto internal_error;
17497             if (res == -1) {
17498                 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17499             }
17500         }
17501         /*
17502         * "maxExclusive valid restriction"
17503         */
17504         if (bfmaxexc) {
17505             /* maxExclusive <= BASE maxExclusive */
17506             res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17507             if (res == -2)
17508                 goto internal_error;
17509             if (res == 1) {
17510                 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17511             }
17512             if ((res != 0) && (bfmaxexc->fixed)) {
17513                 FACET_RESTR_FIXED_ERR(fmaxexc)
17514             }
17515         }
17516         if (bfmaxinc) {
17517             /* maxExclusive <= BASE maxInclusive */
17518             res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17519             if (res == -2)
17520                 goto internal_error;
17521             if (res == 1) {
17522                 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17523             }
17524         }
17525         if (bfmininc) {
17526             /* maxExclusive > BASE minInclusive */
17527             res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17528             if (res == -2)
17529                 goto internal_error;
17530             if (res != 1) {
17531                 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17532             }
17533         }
17534         if (bfminexc) {
17535             /* maxExclusive > BASE minExclusive */
17536             res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17537             if (res == -2)
17538                 goto internal_error;
17539             if (res != 1) {
17540                 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17541             }
17542         }
17543     }
17544     if (fminexc) {
17545         /*
17546         * "minExclusive < maxInclusive"
17547         */
17548         if (fmaxinc) {
17549             res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17550             if (res == -2)
17551                 goto internal_error;
17552             if (res != -1) {
17553                 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17554             }
17555         }
17556         /*
17557         * "minExclusive valid restriction"
17558         */
17559         if (bfminexc) {
17560             /* minExclusive >= BASE minExclusive */
17561             res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17562             if (res == -2)
17563                 goto internal_error;
17564             if (res == -1) {
17565                 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17566             }
17567             if ((res != 0) && (bfminexc->fixed)) {
17568                 FACET_RESTR_FIXED_ERR(fminexc)
17569             }
17570         }
17571         if (bfmaxinc) {
17572             /* minExclusive <= BASE maxInclusive */
17573             res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17574             if (res == -2)
17575                 goto internal_error;
17576             if (res == 1) {
17577                 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17578             }
17579         }
17580         if (bfmininc) {
17581             /* minExclusive >= BASE minInclusive */
17582             res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17583             if (res == -2)
17584                 goto internal_error;
17585             if (res == -1) {
17586                 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17587             }
17588         }
17589         if (bfmaxexc) {
17590             /* minExclusive < BASE maxExclusive */
17591             res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17592             if (res == -2)
17593                 goto internal_error;
17594             if (res != -1) {
17595                 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17596             }
17597         }
17598     }
17599     if (fmininc) {
17600         /*
17601         * "minInclusive < maxExclusive"
17602         */
17603         if (fmaxexc) {
17604             res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17605             if (res == -2)
17606                 goto internal_error;
17607             if (res != -1) {
17608                 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17609             }
17610         }
17611         /*
17612         * "minExclusive valid restriction"
17613         */
17614         if (bfmininc) {
17615             /* minInclusive >= BASE minInclusive */
17616             res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17617             if (res == -2)
17618                 goto internal_error;
17619             if (res == -1) {
17620                 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17621             }
17622             if ((res != 0) && (bfmininc->fixed)) {
17623                 FACET_RESTR_FIXED_ERR(fmininc)
17624             }
17625         }
17626         if (bfmaxinc) {
17627             /* minInclusive <= BASE maxInclusive */
17628             res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17629             if (res == -2)
17630                 goto internal_error;
17631             if (res == 1) {
17632                 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17633             }
17634         }
17635         if (bfminexc) {
17636             /* minInclusive > BASE minExclusive */
17637             res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17638             if (res == -2)
17639                 goto internal_error;
17640             if (res != 1)
17641                 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17642         }
17643         if (bfmaxexc) {
17644             /* minInclusive < BASE maxExclusive */
17645             res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17646             if (res == -2)
17647                 goto internal_error;
17648             if (res != -1)
17649                 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17650         }
17651     }
17652     if (ftotdig && bftotdig) {
17653         /*
17654         * SCC " totalDigits valid restriction"
17655         * totalDigits <= BASE totalDigits
17656         */
17657         res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17658         if (res == -2)
17659             goto internal_error;
17660         if (res == 1)
17661             xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17662             -1, 1, 1);
17663         if ((res != 0) && (bftotdig->fixed)) {
17664             FACET_RESTR_FIXED_ERR(ftotdig)
17665         }
17666     }
17667     if (ffracdig && bffracdig) {
17668         /*
17669         * SCC  "fractionDigits valid restriction"
17670         * fractionDigits <= BASE fractionDigits
17671         */
17672         res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17673         if (res == -2)
17674             goto internal_error;
17675         if (res == 1)
17676             xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17677             -1, 1, 1);
17678         if ((res != 0) && (bffracdig->fixed)) {
17679             FACET_RESTR_FIXED_ERR(ffracdig)
17680         }
17681     }
17682     /*
17683     * SCC "fractionDigits less than or equal to totalDigits"
17684     */
17685     if (! ftotdig)
17686         ftotdig = bftotdig;
17687     if (! ffracdig)
17688         ffracdig = bffracdig;
17689     if (ftotdig && ffracdig) {
17690         res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17691         if (res == -2)
17692             goto internal_error;
17693         if (res == 1)
17694             xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17695                 -1, 1, 0);
17696     }
17697     /*
17698     * *Enumerations* won' be added here, since only the first set
17699     * of enumerations in the ancestor-or-self axis is used
17700     * for validation, plus we need to use the base type of those
17701     * enumerations for whitespace.
17702     *
17703     * *Patterns*: won't be add here, since they are ORed at
17704     * type level and ANDed at ancestor level. This will
17705     * happed during validation by walking the base axis
17706     * of the type.
17707     */
17708     for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17709         bfacet = cur->facet;
17710         /*
17711         * Special handling of enumerations and patterns.
17712         * TODO: hmm, they should not appear in the set, so remove this.
17713         */
17714         if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
17715             (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
17716             continue;
17717         /*
17718         * Search for a duplicate facet in the current type.
17719         */
17720         link = type->facetSet;
17721         /* err = 0; */
17722         /* fixedErr = 0; */
17723         while (link != NULL) {
17724             facet = link->facet;
17725             if (facet->type == bfacet->type) {
17726                 switch (facet->type) {
17727                     case XML_SCHEMA_FACET_WHITESPACE:
17728                         /*
17729                         * The whitespace must be stronger.
17730                         */
17731                         if (facet->whitespace < bfacet->whitespace) {
17732                             FACET_RESTR_ERR(facet,
17733                                 "The 'whitespace' value has to be equal to "
17734                                 "or stronger than the 'whitespace' value of "
17735                                 "the base type")
17736                         }
17737                         if ((bfacet->fixed) &&
17738                             (facet->whitespace != bfacet->whitespace)) {
17739                             FACET_RESTR_FIXED_ERR(facet)
17740                         }
17741                         break;
17742                     default:
17743                         break;
17744                 }
17745                 /* Duplicate found. */
17746                 break;
17747             }
17748             link = link->next;
17749         }
17750         /*
17751         * If no duplicate was found: add the base types's facet
17752         * to the set.
17753         */
17754         if (link == NULL) {
17755             link = (xmlSchemaFacetLinkPtr)
17756                 xmlMalloc(sizeof(xmlSchemaFacetLink));
17757             if (link == NULL) {
17758                 xmlSchemaPErrMemory(pctxt,
17759                     "deriving facets, creating a facet link", NULL);
17760                 return (-1);
17761             }
17762             link->facet = cur->facet;
17763             link->next = NULL;
17764             if (last == NULL)
17765                 type->facetSet = link;
17766             else
17767                 last->next = link;
17768             last = link;
17769         }
17770
17771     }
17772
17773     return (0);
17774 internal_error:
17775     PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17776         "an error occurred");
17777     return (-1);
17778 }
17779
17780 static int
17781 xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17782                                              xmlSchemaTypePtr type)
17783 {
17784     xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17785     /*
17786     * The actual value is then formed by replacing any union type
17787     * definition in the `explicit members` with the members of their
17788     * {member type definitions}, in order.
17789     *
17790     * TODO: There's a bug entry at
17791     * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17792     * which indicates that we'll keep the union types the future.
17793     */
17794     link = type->memberTypes;
17795     while (link != NULL) {
17796
17797         if (WXS_IS_TYPE_NOT_FIXED(link->type))
17798             xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
17799
17800         if (WXS_IS_UNION(link->type)) {
17801             subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
17802             if (subLink != NULL) {
17803                 link->type = subLink->type;
17804                 if (subLink->next != NULL) {
17805                     lastLink = link->next;
17806                     subLink = subLink->next;
17807                     prevLink = link;
17808                     while (subLink != NULL) {
17809                         newLink = (xmlSchemaTypeLinkPtr)
17810                             xmlMalloc(sizeof(xmlSchemaTypeLink));
17811                         if (newLink == NULL) {
17812                             xmlSchemaPErrMemory(pctxt, "allocating a type link",
17813                                 NULL);
17814                             return (-1);
17815                         }
17816                         newLink->type = subLink->type;
17817                         prevLink->next = newLink;
17818                         prevLink = newLink;
17819                         newLink->next = lastLink;
17820
17821                         subLink = subLink->next;
17822                     }
17823                 }
17824             }
17825         }
17826         link = link->next;
17827     }
17828     return (0);
17829 }
17830
17831 static void
17832 xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17833 {
17834     int has = 0, needVal = 0, normVal = 0;
17835
17836     has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17837     if (has) {
17838         needVal = (type->baseType->flags &
17839             XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17840         normVal = (type->baseType->flags &
17841             XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17842     }
17843     if (type->facets != NULL) {
17844         xmlSchemaFacetPtr fac;
17845
17846         for (fac = type->facets; fac != NULL; fac = fac->next) {
17847             switch (fac->type) {
17848                 case XML_SCHEMA_FACET_WHITESPACE:
17849                     break;
17850                 case XML_SCHEMA_FACET_PATTERN:
17851                     normVal = 1;
17852                     has = 1;
17853                     break;
17854                 case XML_SCHEMA_FACET_ENUMERATION:
17855                     needVal = 1;
17856                     normVal = 1;
17857                     has = 1;
17858                     break;
17859                 default:
17860                     has = 1;
17861                     break;
17862             }
17863         }
17864     }
17865     if (normVal)
17866         type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17867     if (needVal)
17868         type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17869     if (has)
17870         type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17871
17872     if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
17873         xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17874         /*
17875         * OPTIMIZE VAL TODO: Some facets need a computed value.
17876         */
17877         if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17878             (prim->builtInType != XML_SCHEMAS_STRING)) {
17879             type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17880         }
17881     }
17882 }
17883
17884 static int
17885 xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17886 {
17887
17888
17889     /*
17890     * Evaluate the whitespace-facet value.
17891     */
17892     if (WXS_IS_LIST(type)) {
17893         type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17894         return (0);
17895     } else if (WXS_IS_UNION(type))
17896         return (0);
17897
17898     if (type->facetSet != NULL) {
17899         xmlSchemaFacetLinkPtr lin;
17900
17901         for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17902             if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17903                 switch (lin->facet->whitespace) {
17904                 case XML_SCHEMAS_FACET_PRESERVE:
17905                     type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17906                     break;
17907                 case XML_SCHEMAS_FACET_REPLACE:
17908                     type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17909                     break;
17910                 case XML_SCHEMAS_FACET_COLLAPSE:
17911                     type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17912                     break;
17913                 default:
17914                     return (-1);
17915                 }
17916                 return (0);
17917             }
17918         }
17919     }
17920     /*
17921     * For all `atomic` datatypes other than string (and types `derived`
17922     * by `restriction` from it) the value of whiteSpace is fixed to
17923     * collapse
17924     */
17925     {
17926         xmlSchemaTypePtr anc;
17927
17928         for (anc = type->baseType; anc != NULL &&
17929                 anc->builtInType != XML_SCHEMAS_ANYTYPE;
17930                 anc = anc->baseType) {
17931
17932             if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17933                 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17934                     type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17935
17936                 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17937                     (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17938                     type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17939
17940                 } else
17941                     type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17942                 break;
17943             }
17944         }
17945     }
17946     return (0);
17947 }
17948
17949 static int
17950 xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17951                           xmlSchemaTypePtr type)
17952 {
17953     if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17954         return(0);
17955     if (! WXS_IS_TYPE_NOT_FIXED_1(type))
17956         return(0);
17957     type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
17958
17959     if (WXS_IS_LIST(type)) {
17960         /*
17961         * Corresponds to <simpleType><list>...
17962         */
17963         if (type->subtypes == NULL) {
17964             /*
17965             * This one is really needed, so get out.
17966             */
17967             PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17968                 "list type has no item-type assigned");
17969             return(-1);
17970         }
17971     } else if (WXS_IS_UNION(type)) {
17972         /*
17973         * Corresponds to <simpleType><union>...
17974         */
17975         if (type->memberTypes == NULL) {
17976             /*
17977             * This one is really needed, so get out.
17978             */
17979             PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17980                 "union type has no member-types assigned");
17981             return(-1);
17982         }
17983     } else {
17984         /*
17985         * Corresponds to <simpleType><restriction>...
17986         */
17987         if (type->baseType == NULL) {
17988             PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17989                 "type has no base-type assigned");
17990             return(-1);
17991         }
17992         if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
17993             if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17994                 return(-1);
17995         /*
17996         * Variety
17997         * If the <restriction> alternative is chosen, then the
17998         * {variety} of the {base type definition}.
17999         */
18000         if (WXS_IS_ATOMIC(type->baseType))
18001             type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
18002         else if (WXS_IS_LIST(type->baseType)) {
18003             type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
18004             /*
18005             * Inherit the itemType.
18006             */
18007             type->subtypes = type->baseType->subtypes;
18008         } else if (WXS_IS_UNION(type->baseType)) {
18009             type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
18010             /*
18011             * NOTE that we won't assign the memberTypes of the base,
18012             * since this will make trouble when freeing them; we will
18013             * use a lookup function to access them instead.
18014             */
18015         }
18016     }
18017     return(0);
18018 }
18019
18020 #ifdef DEBUG_TYPE
18021 static void
18022 xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
18023                        xmlSchemaTypePtr type)
18024 {
18025     if (type->node != NULL) {
18026         xmlGenericError(xmlGenericErrorContext,
18027                         "Type of %s : %s:%d :", name,
18028                         type->node->doc->URL,
18029                         xmlGetLineNo(type->node));
18030     } else {
18031         xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
18032     }
18033     if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
18034         switch (type->contentType) {
18035             case XML_SCHEMA_CONTENT_SIMPLE:
18036                 xmlGenericError(xmlGenericErrorContext, "simple\n");
18037                 break;
18038             case XML_SCHEMA_CONTENT_ELEMENTS:
18039                 xmlGenericError(xmlGenericErrorContext, "elements\n");
18040                 break;
18041             case XML_SCHEMA_CONTENT_UNKNOWN:
18042                 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
18043                 break;
18044             case XML_SCHEMA_CONTENT_EMPTY:
18045                 xmlGenericError(xmlGenericErrorContext, "empty\n");
18046                 break;
18047             case XML_SCHEMA_CONTENT_MIXED:
18048                 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
18049                     type->subtypes))
18050                     xmlGenericError(xmlGenericErrorContext,
18051                         "mixed as emptiable particle\n");
18052                 else
18053                     xmlGenericError(xmlGenericErrorContext, "mixed\n");
18054                 break;
18055                 /* Removed, since not used. */
18056                 /*
18057                 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
18058                 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
18059                 break;
18060                 */
18061             case XML_SCHEMA_CONTENT_BASIC:
18062                 xmlGenericError(xmlGenericErrorContext, "basic\n");
18063                 break;
18064             default:
18065                 xmlGenericError(xmlGenericErrorContext,
18066                     "not registered !!!\n");
18067                 break;
18068         }
18069     }
18070 }
18071 #endif
18072
18073 /*
18074 * 3.14.6 Constraints on Simple Type Definition Schema Components
18075 */
18076 static int
18077 xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
18078                                  xmlSchemaTypePtr type)
18079 {
18080     int res, olderrs = pctxt->nberrors;
18081
18082     if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18083         return(-1);
18084
18085     if (! WXS_IS_TYPE_NOT_FIXED(type))
18086         return(0);
18087
18088     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18089     type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
18090
18091     if (type->baseType == NULL) {
18092         PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
18093             "missing baseType");
18094         goto exit_failure;
18095     }
18096     if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
18097         xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
18098     /*
18099     * If a member type of a union is a union itself, we need to substitute
18100     * that member type for its member types.
18101     * NOTE that this might change in WXS 1.1; i.e. we will keep the union
18102     * types in WXS 1.1.
18103     */
18104     if ((type->memberTypes != NULL) &&
18105         (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
18106         return(-1);
18107     /*
18108     * SPEC src-simple-type 1
18109     * "The corresponding simple type definition, if any, must satisfy
18110     * the conditions set out in Constraints on Simple Type Definition
18111     * Schema Components ($3.14.6)."
18112     */
18113     /*
18114     * Schema Component Constraint: Simple Type Definition Properties Correct
18115     * (st-props-correct)
18116     */
18117     res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
18118     HFAILURE HERROR
18119     /*
18120     * Schema Component Constraint: Derivation Valid (Restriction, Simple)
18121     * (cos-st-restricts)
18122     */
18123     res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
18124     HFAILURE HERROR
18125     /*
18126     * TODO: Removed the error report, since it got annoying to get an
18127     * extra error report, if anything failed until now.
18128     * Enable this if needed.
18129     *
18130     * xmlSchemaPErr(ctxt, type->node,
18131     *    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
18132     *    "Simple type '%s' does not satisfy the constraints "
18133     *    "on simple type definitions.\n",
18134     *    type->name, NULL);
18135     */
18136     /*
18137     * Schema Component Constraint: Simple Type Restriction (Facets)
18138     * (st-restrict-facets)
18139     */
18140     res = xmlSchemaCheckFacetValues(type, pctxt);
18141     HFAILURE HERROR
18142     if ((type->facetSet != NULL) ||
18143         (type->baseType->facetSet != NULL)) {
18144         res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18145         HFAILURE HERROR
18146     }
18147     /*
18148     * Whitespace value.
18149     */
18150     res = xmlSchemaTypeFixupWhitespace(type);
18151     HFAILURE HERROR
18152     xmlSchemaTypeFixupOptimFacets(type);
18153
18154 exit_error:
18155 #ifdef DEBUG_TYPE
18156     xmlSchemaDebugFixedType(pctxt, type);
18157 #endif
18158     if (olderrs != pctxt->nberrors)
18159         return(pctxt->err);
18160     return(0);
18161
18162 exit_failure:
18163 #ifdef DEBUG_TYPE
18164     xmlSchemaDebugFixedType(pctxt, type);
18165 #endif
18166     return(-1);
18167 }
18168
18169 static int
18170 xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18171                           xmlSchemaTypePtr type)
18172 {
18173     int res = 0, olderrs = pctxt->nberrors;
18174     xmlSchemaTypePtr baseType = type->baseType;
18175
18176     if (! WXS_IS_TYPE_NOT_FIXED(type))
18177         return(0);
18178     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18179     if (baseType == NULL) {
18180         PERROR_INT("xmlSchemaFixupComplexType",
18181             "missing baseType");
18182         goto exit_failure;
18183     }
18184     /*
18185     * Fixup the base type.
18186     */
18187     if (WXS_IS_TYPE_NOT_FIXED(baseType))
18188         xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
18189     if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18190         /*
18191         * Skip fixup if the base type is invalid.
18192         * TODO: Generate a warning!
18193         */
18194         return(0);
18195     }
18196     /*
18197     * This basically checks if the base type can be derived.
18198     */
18199     res = xmlSchemaCheckSRCCT(pctxt, type);
18200     HFAILURE HERROR
18201     /*
18202     * Fixup the content type.
18203     */
18204     if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18205         /*
18206         * Corresponds to <complexType><simpleContent>...
18207         */
18208         if ((WXS_IS_COMPLEX(baseType)) &&
18209             (baseType->contentTypeDef != NULL) &&
18210             (WXS_IS_RESTRICTION(type))) {
18211             xmlSchemaTypePtr contentBase, content;
18212 #ifdef ENABLE_NAMED_LOCALS
18213             char buf[30];
18214             const xmlChar *tmpname;
18215 #endif
18216             /*
18217             * SPEC (1) If <restriction> + base type is <complexType>,
18218             * "whose own {content type} is a simple type..."
18219             */
18220             if (type->contentTypeDef != NULL) {
18221                 /*
18222                 * SPEC (1.1) "the simple type definition corresponding to the
18223                 * <simpleType> among the [children] of <restriction> if there
18224                 * is one;"
18225                 * Note that this "<simpleType> among the [children]" was put
18226                 * into ->contentTypeDef during parsing.
18227                 */
18228                 contentBase = type->contentTypeDef;
18229                 type->contentTypeDef = NULL;
18230             } else {
18231                 /*
18232                 * (1.2) "...otherwise (<restriction> has no <simpleType>
18233                 * among its [children]), the simple type definition which
18234                 * is the {content type} of the ... base type."
18235                 */
18236                 contentBase = baseType->contentTypeDef;
18237             }
18238             /*
18239             * SPEC
18240             * "... a simple type definition which restricts the simple
18241             * type definition identified in clause 1.1 or clause 1.2
18242             * with a set of facet components"
18243             *
18244             * Create the anonymous simple type, which will be the content
18245             * type of the complex type.
18246             */
18247 #ifdef ENABLE_NAMED_LOCALS
18248             snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18249             tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
18250             content = xmlSchemaAddType(pctxt, pctxt->schema,
18251                 XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
18252                 type->node, 0);
18253 #else
18254             content = xmlSchemaAddType(pctxt, pctxt->schema,
18255                 XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
18256                 type->node, 0);
18257 #endif
18258             if (content == NULL)
18259                 goto exit_failure;
18260             /*
18261             * We will use the same node as for the <complexType>
18262             * to have it somehow anchored in the schema doc.
18263             */
18264             content->type = XML_SCHEMA_TYPE_SIMPLE;
18265             content->baseType = contentBase;
18266             /*
18267             * Move the facets, previously anchored on the
18268             * complexType during parsing.
18269             */
18270             content->facets = type->facets;
18271             type->facets = NULL;
18272             content->facetSet = type->facetSet;
18273             type->facetSet = NULL;
18274
18275             type->contentTypeDef = content;
18276             if (WXS_IS_TYPE_NOT_FIXED(contentBase))
18277                 xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
18278             /*
18279             * Fixup the newly created type. We don't need to check
18280             * for circularity here.
18281             */
18282             res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18283             HFAILURE HERROR
18284             res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18285             HFAILURE HERROR
18286
18287         } else if ((WXS_IS_COMPLEX(baseType)) &&
18288             (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18289             (WXS_IS_RESTRICTION(type))) {
18290             /*
18291             * SPEC (2) If <restriction> + base is a mixed <complexType> with
18292             * an emptiable particle, then a simple type definition which
18293             * restricts the <restriction>'s <simpleType> child.
18294             */
18295             if ((type->contentTypeDef == NULL) ||
18296                 (type->contentTypeDef->baseType == NULL)) {
18297                 /*
18298                 * TODO: Check if this ever happens.
18299                 */
18300                 xmlSchemaPCustomErr(pctxt,
18301                     XML_SCHEMAP_INTERNAL,
18302                     WXS_BASIC_CAST type, NULL,
18303                     "Internal error: xmlSchemaTypeFixup, "
18304                     "complex type '%s': the <simpleContent><restriction> "
18305                     "is missing a <simpleType> child, but was not catched "
18306                     "by xmlSchemaCheckSRCCT()", type->name);
18307                 goto exit_failure;
18308             }
18309         } else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
18310             /*
18311             * SPEC (3) If <extension> + base is <complexType> with
18312             * <simpleType> content, "...then the {content type} of that
18313             * complex type definition"
18314             */
18315             if (baseType->contentTypeDef == NULL) {
18316                 /*
18317                 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18318                 * should have catched this already.
18319                 */
18320                 xmlSchemaPCustomErr(pctxt,
18321                     XML_SCHEMAP_INTERNAL,
18322                     WXS_BASIC_CAST type, NULL,
18323                     "Internal error: xmlSchemaTypeFixup, "
18324                     "complex type '%s': the <extension>ed base type is "
18325                     "a complex type with no simple content type",
18326                     type->name);
18327                 goto exit_failure;
18328             }
18329             type->contentTypeDef = baseType->contentTypeDef;
18330         } else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
18331             /*
18332             * SPEC (4) <extension> + base is <simpleType>
18333             * "... then that simple type definition"
18334             */
18335             type->contentTypeDef = baseType;
18336         } else {
18337             /*
18338             * TODO: Check if this ever happens.
18339             */
18340             xmlSchemaPCustomErr(pctxt,
18341                 XML_SCHEMAP_INTERNAL,
18342                 WXS_BASIC_CAST type, NULL,
18343                 "Internal error: xmlSchemaTypeFixup, "
18344                 "complex type '%s' with <simpleContent>: unhandled "
18345                 "derivation case", type->name);
18346             goto exit_failure;
18347         }
18348     } else {
18349         int dummySequence = 0;
18350         xmlSchemaParticlePtr particle =
18351             (xmlSchemaParticlePtr) type->subtypes;
18352         /*
18353         * Corresponds to <complexType><complexContent>...
18354         *
18355         * NOTE that the effective mixed was already set during parsing of
18356         * <complexType> and <complexContent>; its flag value is
18357         * XML_SCHEMAS_TYPE_MIXED.
18358         *
18359         * Compute the "effective content":
18360         * (2.1.1) + (2.1.2) + (2.1.3)
18361         */
18362         if ((particle == NULL) ||
18363             ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18364             ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18365             (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18366             ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18367             (particle->minOccurs == 0))) &&
18368             ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18369             if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18370                 /*
18371                 * SPEC (2.1.4) "If the `effective mixed` is true, then
18372                 * a particle whose properties are as follows:..."
18373                 *
18374                 * Empty sequence model group with
18375                 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18376                 * NOTE that we sill assign it the <complexType> node to
18377                 * somehow anchor it in the doc.
18378                 */
18379                 if ((particle == NULL) ||
18380                     (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18381                     /*
18382                     * Create the particle.
18383                     */
18384                     particle = xmlSchemaAddParticle(pctxt,
18385                         type->node, 1, 1);
18386                     if (particle == NULL)
18387                         goto exit_failure;
18388                     /*
18389                     * Create the model group.
18390                     */ /* URGENT TODO: avoid adding to pending items. */
18391                     particle->children = (xmlSchemaTreeItemPtr)
18392                         xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18393                         XML_SCHEMA_TYPE_SEQUENCE, type->node);
18394                     if (particle->children == NULL)
18395                         goto exit_failure;
18396
18397                     type->subtypes = (xmlSchemaTypePtr) particle;
18398                 }
18399                 dummySequence = 1;
18400                 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18401             } else {
18402                 /*
18403                 * SPEC (2.1.5) "otherwise empty"
18404                 */
18405                 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18406             }
18407         } else {
18408             /*
18409             * SPEC (2.2) "otherwise the particle corresponding to the
18410             * <all>, <choice>, <group> or <sequence> among the
18411             * [children]."
18412             */
18413             type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18414         }
18415         /*
18416         * Compute the "content type".
18417         */
18418         if (WXS_IS_RESTRICTION(type)) {
18419             /*
18420             * SPEC (3.1) "If <restriction>..."
18421             * (3.1.1) + (3.1.2) */
18422             if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18423                 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18424                     type->contentType = XML_SCHEMA_CONTENT_MIXED;
18425             }
18426         } else {
18427             /*
18428             * SPEC (3.2) "If <extension>..."
18429             */
18430             if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18431                 /*
18432                 * SPEC (3.2.1)
18433                 * "If the `effective content` is empty, then the
18434                 *  {content type} of the [...] base ..."
18435                 */
18436                 type->contentType = baseType->contentType;
18437                 type->subtypes = baseType->subtypes;
18438                 /*
18439                 * Fixes bug #347316:
18440                 * This is the case when the base type has a simple
18441                 * type definition as content.
18442                 */
18443                 type->contentTypeDef = baseType->contentTypeDef;
18444                 /*
18445                 * NOTE that the effective mixed is ignored here.
18446                 */
18447             } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18448                 /*
18449                 * SPEC (3.2.2)
18450                 */
18451                 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18452                     type->contentType = XML_SCHEMA_CONTENT_MIXED;
18453             } else {
18454                 /*
18455                 * SPEC (3.2.3)
18456                 */
18457                 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18458                     type->contentType = XML_SCHEMA_CONTENT_MIXED;
18459                     /*
18460                     * "A model group whose {compositor} is sequence and whose
18461                     * {particles} are..."
18462                     */
18463                 if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18464                     (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18465                     ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18466                         XML_SCHEMA_TYPE_ALL))
18467                 {
18468                     /*
18469                     * SPEC cos-all-limited (1)
18470                     */
18471                     xmlSchemaCustomErr(ACTXT_CAST pctxt,
18472                         /* TODO: error code */
18473                         XML_SCHEMAP_COS_ALL_LIMITED,
18474                         WXS_ITEM_NODE(type), NULL,
18475                         "The type has an 'all' model group in its "
18476                         "{content type} and thus cannot be derived from "
18477                         "a non-empty type, since this would produce a "
18478                         "'sequence' model group containing the 'all' "
18479                         "model group; 'all' model groups are not "
18480                         "allowed to appear inside other model groups",
18481                         NULL, NULL);
18482
18483                 } else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18484                     (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18485                     ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18486                         XML_SCHEMA_TYPE_ALL))
18487                 {
18488                     /*
18489                     * SPEC cos-all-limited (1)
18490                     */
18491                     xmlSchemaCustomErr(ACTXT_CAST pctxt,
18492                         /* TODO: error code */
18493                         XML_SCHEMAP_COS_ALL_LIMITED,
18494                         WXS_ITEM_NODE(type), NULL,
18495                         "A type cannot be derived by extension from a type "
18496                         "which has an 'all' model group in its "
18497                         "{content type}, since this would produce a "
18498                         "'sequence' model group containing the 'all' "
18499                         "model group; 'all' model groups are not "
18500                         "allowed to appear inside other model groups",
18501                         NULL, NULL);
18502
18503                 } else if (! dummySequence) {
18504                     xmlSchemaTreeItemPtr effectiveContent =
18505                         (xmlSchemaTreeItemPtr) type->subtypes;
18506                     /*
18507                     * Create the particle.
18508                     */
18509                     particle = xmlSchemaAddParticle(pctxt,
18510                         type->node, 1, 1);
18511                     if (particle == NULL)
18512                         goto exit_failure;
18513                     /*
18514                     * Create the "sequence" model group.
18515                     */
18516                     particle->children = (xmlSchemaTreeItemPtr)
18517                         xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18518                         XML_SCHEMA_TYPE_SEQUENCE, type->node);
18519                     if (particle->children == NULL)
18520                         goto exit_failure;
18521                     WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
18522                     /*
18523                     * SPEC "the particle of the {content type} of
18524                     * the ... base ..."
18525                     * Create a duplicate of the base type's particle
18526                     * and assign its "term" to it.
18527                     */
18528                     particle->children->children =
18529                         (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18530                         type->node,
18531                         ((xmlSchemaParticlePtr) baseType->subtypes)->minOccurs,
18532                         ((xmlSchemaParticlePtr) baseType->subtypes)->maxOccurs);
18533                     if (particle->children->children == NULL)
18534                         goto exit_failure;
18535                     particle = (xmlSchemaParticlePtr)
18536                         particle->children->children;
18537                     particle->children =
18538                         ((xmlSchemaParticlePtr) baseType->subtypes)->children;
18539                     /*
18540                     * SPEC "followed by the `effective content`."
18541                     */
18542                     particle->next = effectiveContent;
18543                     /*
18544                     * This all will result in:
18545                     * new-particle
18546                     *   --> new-sequence(
18547                     *         new-particle
18548                     *           --> base-model,
18549                     *         this-particle
18550                     *           --> this-model
18551                     *       )
18552                     */
18553                 } else {
18554                     /*
18555                     * This is the case when there is already an empty
18556                     * <sequence> with minOccurs==maxOccurs==1.
18557                     * Just add the base types's content type.
18558                     * NOTE that, although we miss to add an intermediate
18559                     * <sequence>, this should produce no difference to
18560                     * neither the regex compilation of the content model,
18561                     * nor to the complex type contraints.
18562                     */
18563                     particle->children->children =
18564                         (xmlSchemaTreeItemPtr) baseType->subtypes;
18565                 }
18566             }
18567         }
18568     }
18569     /*
18570     * Now fixup attribute uses:
18571     *   - expand attr. group references
18572     *     - intersect attribute wildcards
18573     *   - inherit attribute uses of the base type
18574     *   - inherit or union attr. wildcards if extending
18575     *   - apply attr. use prohibitions if restricting
18576     */
18577     res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
18578     HFAILURE HERROR
18579     /*
18580     * Apply the complex type component constraints; this will not
18581     * check attributes, since this is done in
18582     * xmlSchemaFixupTypeAttributeUses().
18583     */
18584     res = xmlSchemaCheckCTComponent(pctxt, type);
18585     HFAILURE HERROR
18586
18587 #ifdef DEBUG_TYPE
18588     xmlSchemaDebugFixedType(pctxt, type);
18589 #endif
18590     if (olderrs != pctxt->nberrors)
18591         return(pctxt->err);
18592     else
18593         return(0);
18594
18595 exit_error:
18596     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18597 #ifdef DEBUG_TYPE
18598     xmlSchemaDebugFixedType(pctxt, type);
18599 #endif
18600     return(pctxt->err);
18601
18602 exit_failure:
18603     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18604 #ifdef DEBUG_TYPE
18605     xmlSchemaDebugFixedType(pctxt, type);
18606 #endif
18607     return(-1);
18608 }
18609
18610
18611 /**
18612  * xmlSchemaTypeFixup:
18613  * @typeDecl:  the schema type definition
18614  * @ctxt:  the schema parser context
18615  *
18616  * Fixes the content model of the type.
18617  * URGENT TODO: We need an int result!
18618  */
18619 static int
18620 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
18621                    xmlSchemaAbstractCtxtPtr actxt)
18622 {
18623     if (type == NULL)
18624         return(0);
18625     if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18626         AERROR_INT("xmlSchemaTypeFixup",
18627             "this function needs a parser context");
18628         return(-1);
18629     }
18630     if (! WXS_IS_TYPE_NOT_FIXED(type))
18631         return(0);
18632     if (type->type == XML_SCHEMA_TYPE_COMPLEX)
18633         return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
18634     else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
18635         return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
18636     return(0);
18637 }
18638
18639 /**
18640  * xmlSchemaCheckFacet:
18641  * @facet:  the facet
18642  * @typeDecl:  the schema type definition
18643  * @pctxt:  the schema parser context or NULL
18644  * @name: the optional name of the type
18645  *
18646  * Checks and computes the values of facets.
18647  *
18648  * Returns 0 if valid, a positive error code if not valid and
18649  *         -1 in case of an internal or API error.
18650  */
18651 int
18652 xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
18653                     xmlSchemaTypePtr typeDecl,
18654                     xmlSchemaParserCtxtPtr pctxt,
18655                     const xmlChar * name ATTRIBUTE_UNUSED)
18656 {
18657     int ret = 0, ctxtGiven;
18658
18659     if ((facet == NULL) || (typeDecl == NULL))
18660         return(-1);
18661     /*
18662     * TODO: will the parser context be given if used from
18663     * the relaxNG module?
18664     */
18665     if (pctxt == NULL)
18666         ctxtGiven = 0;
18667     else
18668         ctxtGiven = 1;
18669
18670     switch (facet->type) {
18671         case XML_SCHEMA_FACET_MININCLUSIVE:
18672         case XML_SCHEMA_FACET_MINEXCLUSIVE:
18673         case XML_SCHEMA_FACET_MAXINCLUSIVE:
18674         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18675         case XML_SCHEMA_FACET_ENUMERATION: {
18676                 /*
18677                  * Okay we need to validate the value
18678                  * at that point.
18679                  */
18680                 xmlSchemaTypePtr base;
18681
18682                 /* 4.3.5.5 Constraints on enumeration Schema Components
18683                 * Schema Component Constraint: enumeration valid restriction
18684                 * It is an `error` if any member of {value} is not in the
18685                 * `value space` of {base type definition}.
18686                 *
18687                 * minInclusive, maxInclusive, minExclusive, maxExclusive:
18688                 * The value `must` be in the
18689                 * `value space` of the `base type`.
18690                 */
18691                 /*
18692                 * This function is intended to deliver a compiled value
18693                 * on the facet. In this implementation of XML Schemata the
18694                 * type holding a facet, won't be a built-in type.
18695                 * Thus to ensure that other API
18696                 * calls (relaxng) do work, if the given type is a built-in
18697                 * type, we will assume that the given built-in type *is
18698                 * already* the base type.
18699                 */
18700                 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18701                     base = typeDecl->baseType;
18702                     if (base == NULL) {
18703                         PERROR_INT("xmlSchemaCheckFacet",
18704                             "a type user derived type has no base type");
18705                         return (-1);
18706                     }
18707                 } else
18708                     base = typeDecl;
18709
18710                 if (! ctxtGiven) {
18711                     /*
18712                     * A context is needed if called from RelaxNG.
18713                     */
18714                     pctxt = xmlSchemaNewParserCtxt("*");
18715                     if (pctxt == NULL)
18716                         return (-1);
18717                 }
18718                 /*
18719                 * NOTE: This call does not check the content nodes,
18720                 * since they are not available:
18721                 * facet->node is just the node holding the facet
18722                 * definition, *not* the attribute holding the *value*
18723                 * of the facet.
18724                 */
18725                 ret = xmlSchemaVCheckCVCSimpleType(
18726                     ACTXT_CAST pctxt, facet->node, base,
18727                     facet->value, &(facet->val), 1, 1, 0);
18728                 if (ret != 0) {
18729                     if (ret < 0) {
18730                         /* No error message for RelaxNG. */
18731                         if (ctxtGiven) {
18732                             xmlSchemaCustomErr(ACTXT_CAST pctxt,
18733                                 XML_SCHEMAP_INTERNAL, facet->node, NULL,
18734                                 "Internal error: xmlSchemaCheckFacet, "
18735                                 "failed to validate the value '%s' of the "
18736                                 "facet '%s' against the base type",
18737                                 facet->value, xmlSchemaFacetTypeToString(facet->type));
18738                         }
18739                         goto internal_error;
18740                     }
18741                     ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18742                     /* No error message for RelaxNG. */
18743                     if (ctxtGiven) {
18744                         xmlChar *str = NULL;
18745
18746                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
18747                             ret, facet->node, WXS_BASIC_CAST facet,
18748                             "The value '%s' of the facet does not validate "
18749                             "against the base type '%s'",
18750                             facet->value,
18751                             xmlSchemaFormatQName(&str,
18752                                 base->targetNamespace, base->name));
18753                         FREE_AND_NULL(str);
18754                     }
18755                     goto exit;
18756                 } else if (facet->val == NULL) {
18757                     if (ctxtGiven) {
18758                         PERROR_INT("xmlSchemaCheckFacet",
18759                             "value was not computed");
18760                     }
18761                     TODO
18762                 }
18763                 break;
18764             }
18765         case XML_SCHEMA_FACET_PATTERN:
18766             facet->regexp = xmlRegexpCompile(facet->value);
18767             if (facet->regexp == NULL) {
18768                 ret = XML_SCHEMAP_REGEXP_INVALID;
18769                 /* No error message for RelaxNG. */
18770                 if (ctxtGiven) {
18771                     xmlSchemaCustomErr(ACTXT_CAST pctxt,
18772                         ret, facet->node, WXS_BASIC_CAST typeDecl,
18773                         "The value '%s' of the facet 'pattern' is not a "
18774                         "valid regular expression",
18775                         facet->value, NULL);
18776                 }
18777             }
18778             break;
18779         case XML_SCHEMA_FACET_TOTALDIGITS:
18780         case XML_SCHEMA_FACET_FRACTIONDIGITS:
18781         case XML_SCHEMA_FACET_LENGTH:
18782         case XML_SCHEMA_FACET_MAXLENGTH:
18783         case XML_SCHEMA_FACET_MINLENGTH:
18784
18785             if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18786                 ret = xmlSchemaValidatePredefinedType(
18787                     xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18788                     facet->value, &(facet->val));
18789             } else {
18790                 ret = xmlSchemaValidatePredefinedType(
18791                     xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18792                     facet->value, &(facet->val));
18793             }
18794             if (ret != 0) {
18795                 if (ret < 0) {
18796                     /* No error message for RelaxNG. */
18797                     if (ctxtGiven) {
18798                         PERROR_INT("xmlSchemaCheckFacet",
18799                             "validating facet value");
18800                     }
18801                     goto internal_error;
18802                 }
18803                 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18804                 /* No error message for RelaxNG. */
18805                 if (ctxtGiven) {
18806                     /* error code */
18807                     xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18808                         ret, facet->node, WXS_BASIC_CAST typeDecl,
18809                         "The value '%s' of the facet '%s' is not a valid '%s'",
18810                         facet->value,
18811                         xmlSchemaFacetTypeToString(facet->type),
18812                         (facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18813                             BAD_CAST "nonNegativeInteger" :
18814                             BAD_CAST "positiveInteger",
18815                         NULL);
18816                 }
18817             }
18818             break;
18819
18820         case XML_SCHEMA_FACET_WHITESPACE:{
18821                 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18822                     facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18823                 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18824                     facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18825                 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18826                     facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18827                 } else {
18828                     ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18829                     /* No error message for RelaxNG. */
18830                     if (ctxtGiven) {
18831                         /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
18832                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
18833                             ret, facet->node, WXS_BASIC_CAST typeDecl,
18834                             "The value '%s' of the facet 'whitespace' is not "
18835                             "valid", facet->value, NULL);
18836                     }
18837                 }
18838             }
18839         default:
18840             break;
18841     }
18842 exit:
18843     if ((! ctxtGiven) && (pctxt != NULL))
18844         xmlSchemaFreeParserCtxt(pctxt);
18845     return (ret);
18846 internal_error:
18847     if ((! ctxtGiven) && (pctxt != NULL))
18848         xmlSchemaFreeParserCtxt(pctxt);
18849     return (-1);
18850 }
18851
18852 /**
18853  * xmlSchemaCheckFacetValues:
18854  * @typeDecl:  the schema type definition
18855  * @ctxt:  the schema parser context
18856  *
18857  * Checks the default values types, especially for facets
18858  */
18859 static int
18860 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
18861                           xmlSchemaParserCtxtPtr pctxt)
18862 {
18863     int res, olderrs = pctxt->nberrors;
18864     const xmlChar *name = typeDecl->name;
18865     /*
18866     * NOTE: It is intended to use the facets list, instead
18867     * of facetSet.
18868     */
18869     if (typeDecl->facets != NULL) {
18870         xmlSchemaFacetPtr facet = typeDecl->facets;
18871
18872         /*
18873         * Temporarily assign the "schema" to the validation context
18874         * of the parser context. This is needed for NOTATION validation.
18875         */
18876         if (pctxt->vctxt == NULL) {
18877             if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18878                 return(-1);
18879         }
18880         pctxt->vctxt->schema = pctxt->schema;
18881         while (facet != NULL) {
18882             res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18883             HFAILURE
18884             facet = facet->next;
18885         }
18886         pctxt->vctxt->schema = NULL;
18887     }
18888     if (olderrs != pctxt->nberrors)
18889         return(pctxt->err);
18890     return(0);
18891 exit_failure:
18892     return(-1);
18893 }
18894
18895 /**
18896  * xmlSchemaGetCircModelGrDefRef:
18897  * @ctxtMGroup: the searched model group
18898  * @selfMGroup: the second searched model group
18899  * @particle: the first particle
18900  *
18901  * This one is intended to be used by
18902  * xmlSchemaCheckGroupDefCircular only.
18903  *
18904  * Returns the particle with the circular model group definition reference,
18905  * otherwise NULL.
18906  */
18907 static xmlSchemaTreeItemPtr
18908 xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
18909                               xmlSchemaTreeItemPtr particle)
18910 {
18911     xmlSchemaTreeItemPtr circ = NULL;
18912     xmlSchemaTreeItemPtr term;
18913     xmlSchemaModelGroupDefPtr gdef;
18914
18915     for (; particle != NULL; particle = particle->next) {
18916         term = particle->children;
18917         if (term == NULL)
18918             continue;
18919         switch (term->type) {
18920             case XML_SCHEMA_TYPE_GROUP:
18921                 gdef = (xmlSchemaModelGroupDefPtr) term;
18922                 if (gdef == groupDef)
18923                     return (particle);
18924                 /*
18925                 * Mark this model group definition to avoid infinite
18926                 * recursion on circular references not yet examined.
18927                 */
18928                 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18929                     continue;
18930                 if (gdef->children != NULL) {
18931                     gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18932                     circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18933                         gdef->children->children);
18934                     gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18935                     if (circ != NULL)
18936                         return (circ);
18937                 }
18938                 break;
18939             case XML_SCHEMA_TYPE_SEQUENCE:
18940             case XML_SCHEMA_TYPE_CHOICE:
18941             case XML_SCHEMA_TYPE_ALL:
18942                 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18943                 if (circ != NULL)
18944                     return (circ);
18945                 break;
18946             default:
18947                 break;
18948         }
18949     }
18950     return (NULL);
18951 }
18952
18953 /**
18954  * xmlSchemaCheckGroupDefCircular:
18955  * @item:  the model group definition
18956  * @ctxt:  the parser context
18957  * @name:  the name
18958  *
18959  * Checks for circular references to model group definitions.
18960  */
18961 static void
18962 xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
18963                                xmlSchemaParserCtxtPtr ctxt)
18964 {
18965     /*
18966     * Schema Component Constraint: Model Group Correct
18967     * 2 Circular groups are disallowed. That is, within the {particles}
18968     * of a group there must not be at any depth a particle whose {term}
18969     * is the group itself.
18970     */
18971     if ((item == NULL) ||
18972         (item->type != XML_SCHEMA_TYPE_GROUP) ||
18973         (item->children == NULL))
18974         return;
18975     {
18976         xmlSchemaTreeItemPtr circ;
18977
18978         circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
18979         if (circ != NULL) {
18980             xmlChar *str = NULL;
18981             /*
18982             * TODO: The error report is not adequate: this constraint
18983             * is defined for model groups but not definitions, but since
18984             * there cannot be any circular model groups without a model group
18985             * definition (if not using a construction API), we check those
18986             * defintions only.
18987             */
18988             xmlSchemaPCustomErr(ctxt,
18989                 XML_SCHEMAP_MG_PROPS_CORRECT_2,
18990                 NULL, WXS_ITEM_NODE(circ),
18991                 "Circular reference to the model group definition '%s' "
18992                 "defined", xmlSchemaFormatQName(&str,
18993                     item->targetNamespace, item->name));
18994             FREE_AND_NULL(str)
18995             /*
18996             * NOTE: We will cut the reference to avoid further
18997             * confusion of the processor. This is a fatal error.
18998             */
18999             circ->children = NULL;
19000         }
19001     }
19002 }
19003
19004 /**
19005  * xmlSchemaModelGroupToModelGroupDefFixup:
19006  * @ctxt:  the parser context
19007  * @mg:  the model group
19008  *
19009  * Assigns the model group of model group definitions to the "term"
19010  * of the referencing particle.
19011  * In xmlSchemaResolveModelGroupParticleReferences the model group
19012  * definitions were assigned to the "term", since needed for the
19013  * circularity check.
19014  *
19015  * Schema Component Constraint:
19016  *     All Group Limited (cos-all-limited) (1.2)
19017  */
19018 static void
19019 xmlSchemaModelGroupToModelGroupDefFixup(
19020     xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
19021     xmlSchemaModelGroupPtr mg)
19022 {
19023     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19024
19025     while (particle != NULL) {
19026         if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19027             ((WXS_PARTICLE_TERM(particle))->type !=
19028                 XML_SCHEMA_TYPE_GROUP))
19029         {
19030             particle = WXS_PTC_CAST particle->next;
19031             continue;
19032         }
19033         if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
19034             /*
19035             * TODO: Remove the particle.
19036             */
19037             WXS_PARTICLE_TERM(particle) = NULL;
19038             particle = WXS_PTC_CAST particle->next;
19039             continue;
19040         }
19041         /*
19042         * Assign the model group to the {term} of the particle.
19043         */
19044         WXS_PARTICLE_TERM(particle) =
19045             WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
19046
19047         particle = WXS_PTC_CAST particle->next;
19048     }
19049 }
19050
19051 /**
19052  * xmlSchemaCheckAttrGroupCircularRecur:
19053  * @ctxtGr: the searched attribute group
19054  * @attr: the current attribute list to be processed
19055  *
19056  * This one is intended to be used by
19057  * xmlSchemaCheckAttrGroupCircular only.
19058  *
19059  * Returns the circular attribute grou reference, otherwise NULL.
19060  */
19061 static xmlSchemaQNameRefPtr
19062 xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
19063                                      xmlSchemaItemListPtr list)
19064 {
19065     xmlSchemaAttributeGroupPtr gr;
19066     xmlSchemaQNameRefPtr ref, circ;
19067     int i;
19068     /*
19069     * We will search for an attribute group reference which
19070     * references the context attribute group.
19071     */
19072     for (i = 0; i < list->nbItems; i++) {
19073         ref = list->items[i];
19074         if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19075             (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
19076             (ref->item != NULL))
19077         {
19078             gr = WXS_ATTR_GROUP_CAST ref->item;
19079             if (gr == ctxtGr)
19080                 return(ref);
19081             if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
19082                 continue;
19083             /*
19084             * Mark as visited to avoid infinite recursion on
19085             * circular references not yet examined.
19086             */
19087             if ((gr->attrUses) &&
19088                 (gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
19089             {
19090                 gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
19091                 circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
19092                     (xmlSchemaItemListPtr) gr->attrUses);
19093                 gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
19094                 if (circ != NULL)
19095                     return (circ);
19096             }
19097
19098         }
19099     }
19100     return (NULL);
19101 }
19102
19103 /**
19104  * xmlSchemaCheckAttrGroupCircular:
19105  * attrGr:  the attribute group definition
19106  * @ctxt:  the parser context
19107  * @name:  the name
19108  *
19109  * Checks for circular references of attribute groups.
19110  */
19111 static int
19112 xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
19113                                 xmlSchemaParserCtxtPtr ctxt)
19114 {
19115     /*
19116     * Schema Representation Constraint:
19117     * Attribute Group Definition Representation OK
19118     * 3 Circular group reference is disallowed outside <redefine>.
19119     * That is, unless this element information item's parent is
19120     * <redefine>, then among the [children], if any, there must
19121     * not be an <attributeGroup> with ref [attribute] which resolves
19122     * to the component corresponding to this <attributeGroup>. Indirect
19123     * circularity is also ruled out. That is, when QName resolution
19124     * (Schema Document) ($3.15.3) is applied to a `QName` arising from
19125     * any <attributeGroup>s with a ref [attribute] among the [children],
19126     * it must not be the case that a `QName` is encountered at any depth
19127     * which resolves to the component corresponding to this <attributeGroup>.
19128     */
19129     if (attrGr->attrUses == NULL)
19130         return(0);
19131     else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
19132         return(0);
19133     else {
19134         xmlSchemaQNameRefPtr circ;
19135
19136         circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
19137             (xmlSchemaItemListPtr) attrGr->attrUses);
19138         if (circ != NULL) {
19139             xmlChar *str = NULL;
19140             /*
19141             * TODO: Report the referenced attr group as QName.
19142             */
19143             xmlSchemaPCustomErr(ctxt,
19144                 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
19145                 NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
19146                 "Circular reference to the attribute group '%s' "
19147                 "defined", xmlSchemaGetComponentQName(&str, attrGr));
19148             FREE_AND_NULL(str);
19149             /*
19150             * NOTE: We will cut the reference to avoid further
19151             * confusion of the processor.
19152             * BADSPEC TODO: The spec should define how to process in this case.
19153             */
19154             circ->item = NULL;
19155             return(ctxt->err);
19156         }
19157     }
19158     return(0);
19159 }
19160
19161 static int
19162 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19163                                   xmlSchemaAttributeGroupPtr attrGr);
19164
19165 /**
19166  * xmlSchemaExpandAttributeGroupRefs:
19167  * @pctxt: the parser context
19168  * @node: the node of the component holding the attribute uses
19169  * @completeWild: the intersected wildcard to be returned
19170  * @list: the attribute uses
19171  *
19172  * Substitutes contained attribute group references
19173  * for their attribute uses. Wilcards are intersected.
19174  * Attribute use prohibitions are removed from the list
19175  * and returned via the @prohibs list.
19176  * Pointlessness of attr. prohibs, if a matching attr. decl
19177  * is existent a well, are checked.
19178  */
19179 static int
19180 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19181                                   xmlSchemaBasicItemPtr item,
19182                                   xmlSchemaWildcardPtr *completeWild,
19183                                   xmlSchemaItemListPtr list,
19184                                   xmlSchemaItemListPtr prohibs)
19185 {
19186     xmlSchemaAttributeGroupPtr gr;
19187     xmlSchemaAttributeUsePtr use;
19188     xmlSchemaItemListPtr sublist;
19189     int i, j;
19190     int created = (*completeWild == NULL) ? 0 : 1;
19191
19192     if (prohibs)
19193         prohibs->nbItems = 0;
19194
19195     for (i = 0; i < list->nbItems; i++) {
19196         use = list->items[i];
19197
19198         if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19199             if (prohibs == NULL) {
19200                 PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19201                     "unexpected attr prohibition found");
19202                 return(-1);
19203             }
19204             /*
19205             * Remove from attribute uses.
19206             */
19207             if (xmlSchemaItemListRemove(list, i) == -1)
19208                 return(-1);
19209             i--;
19210             /*
19211             * Note that duplicate prohibitions were already
19212             * handled at parsing time.
19213             */
19214             /*
19215             * Add to list of prohibitions.
19216             */
19217             xmlSchemaItemListAddSize(prohibs, 2, use);
19218             continue;
19219         }
19220         if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19221             ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19222         {
19223             if ((WXS_QNAME_CAST use)->item == NULL)
19224                 return(-1);
19225             gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19226             /*
19227             * Expand the referenced attr. group.
19228             * TODO: remove this, this is done in a previous step, so
19229             * already done here.
19230             */
19231             if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19232                 if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19233                     return(-1);
19234             }
19235             /*
19236             * Build the 'complete' wildcard; i.e. intersect multiple
19237             * wildcards.
19238             */
19239             if (gr->attributeWildcard != NULL) {
19240                 if (*completeWild == NULL) {
19241                     *completeWild = gr->attributeWildcard;
19242                 } else {
19243                     if (! created) {
19244                         xmlSchemaWildcardPtr tmpWild;
19245
19246                          /*
19247                         * Copy the first encountered wildcard as context,
19248                         * except for the annotation.
19249                         *
19250                         * Although the complete wildcard might not correspond
19251                         * to any node in the schema, we will anchor it on
19252                         * the node of the owner component.
19253                         */
19254                         tmpWild =  xmlSchemaAddWildcard(pctxt, pctxt->schema,
19255                             XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19256                             WXS_ITEM_NODE(item));
19257                         if (tmpWild == NULL)
19258                             return(-1);
19259                         if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19260                             tmpWild, *completeWild) == -1)
19261                             return (-1);
19262                         tmpWild->processContents = (*completeWild)->processContents;
19263                         *completeWild = tmpWild;
19264                         created = 1;
19265                     }
19266
19267                     if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19268                         gr->attributeWildcard) == -1)
19269                         return(-1);
19270                 }
19271             }
19272             /*
19273             * Just remove the reference if the referenced group does not
19274             * contain any attribute uses.
19275             */
19276             sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19277             if ((sublist == NULL) || sublist->nbItems == 0) {
19278                 if (xmlSchemaItemListRemove(list, i) == -1)
19279                     return(-1);
19280                 i--;
19281                 continue;
19282             }
19283             /*
19284             * Add the attribute uses.
19285             */
19286             list->items[i] = sublist->items[0];
19287             if (sublist->nbItems != 1) {
19288                 for (j = 1; j < sublist->nbItems; j++) {
19289                     i++;
19290                     if (xmlSchemaItemListInsert(list,
19291                             sublist->items[j], i) == -1)
19292                         return(-1);
19293                 }
19294             }
19295         }
19296
19297     }
19298     /*
19299     * Handle pointless prohibitions of declared attributes.
19300     */
19301     if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19302         xmlSchemaAttributeUseProhibPtr prohib;
19303
19304         for (i = prohibs->nbItems -1; i >= 0; i--) {
19305             prohib = prohibs->items[i];
19306             for (j = 0; j < list->nbItems; j++) {
19307                 use = list->items[j];
19308
19309                 if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19310                     (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19311                 {
19312                     xmlChar *str = NULL;
19313
19314                     xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19315                         XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19316                         prohib->node, NULL,
19317                         "Skipping pointless attribute use prohibition "
19318                         "'%s', since a corresponding attribute use "
19319                         "exists already in the type definition",
19320                         xmlSchemaFormatQName(&str,
19321                             prohib->targetNamespace, prohib->name),
19322                         NULL, NULL);
19323                     FREE_AND_NULL(str);
19324                     /*
19325                     * Remove the prohibition.
19326                     */
19327                     if (xmlSchemaItemListRemove(prohibs, i) == -1)
19328                         return(-1);
19329                     break;
19330                 }
19331             }
19332         }
19333     }
19334     return(0);
19335 }
19336
19337 /**
19338  * xmlSchemaAttributeGroupExpandRefs:
19339  * @pctxt:  the parser context
19340  * @attrGr:  the attribute group definition
19341  *
19342  * Computation of:
19343  * {attribute uses} property
19344  * {attribute wildcard} property
19345  *
19346  * Substitutes contained attribute group references
19347  * for their attribute uses. Wilcards are intersected.
19348  */
19349 static int
19350 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19351                                   xmlSchemaAttributeGroupPtr attrGr)
19352 {
19353     if ((attrGr->attrUses == NULL) ||
19354         (attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19355         return(0);
19356
19357     attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19358     if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19359         &(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19360         return(-1);
19361     return(0);
19362 }
19363
19364 /**
19365  * xmlSchemaAttributeGroupExpandRefs:
19366  * @pctxt:  the parser context
19367  * @attrGr:  the attribute group definition
19368  *
19369  * Substitutes contained attribute group references
19370  * for their attribute uses. Wilcards are intersected.
19371  *
19372  * Schema Component Constraint:
19373  *    Attribute Group Definition Properties Correct (ag-props-correct)
19374  */
19375 static int
19376 xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19377                                   xmlSchemaAttributeGroupPtr attrGr)
19378 {
19379     /*
19380     * SPEC ag-props-correct
19381     * (1) "The values of the properties of an attribute group definition
19382     * must be as described in the property tableau in The Attribute
19383     * Group Definition Schema Component ($3.6.1), modulo the impact of
19384     * Missing Sub-components ($5.3);"
19385     */
19386
19387     if ((attrGr->attrUses != NULL) &&
19388         (WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19389     {
19390         xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19391         xmlSchemaAttributeUsePtr use, tmp;
19392         int i, j, hasId = 0;
19393
19394         for (i = uses->nbItems -1; i >= 0; i--) {
19395             use = uses->items[i];
19396             /*
19397             * SPEC ag-props-correct
19398             * (2) "Two distinct members of the {attribute uses} must not have
19399             * {attribute declaration}s both of whose {name}s match and whose
19400             * {target namespace}s are identical."
19401             */
19402             if (i > 0) {
19403                 for (j = i -1; j >= 0; j--) {
19404                     tmp = uses->items[j];
19405                     if ((WXS_ATTRUSE_DECL_NAME(use) ==
19406                         WXS_ATTRUSE_DECL_NAME(tmp)) &&
19407                         (WXS_ATTRUSE_DECL_TNS(use) ==
19408                         WXS_ATTRUSE_DECL_TNS(tmp)))
19409                     {
19410                         xmlChar *str = NULL;
19411
19412                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
19413                             XML_SCHEMAP_AG_PROPS_CORRECT,
19414                             attrGr->node, WXS_BASIC_CAST attrGr,
19415                             "Duplicate %s",
19416                             xmlSchemaGetComponentDesignation(&str, use),
19417                             NULL);
19418                         FREE_AND_NULL(str);
19419                         /*
19420                         * Remove the duplicate.
19421                         */
19422                         if (xmlSchemaItemListRemove(uses, i) == -1)
19423                             return(-1);
19424                         goto next_use;
19425                     }
19426                 }
19427             }
19428             /*
19429             * SPEC ag-props-correct
19430             * (3) "Two distinct members of the {attribute uses} must not have
19431             * {attribute declaration}s both of whose {type definition}s are or
19432             * are derived from ID."
19433             * TODO: Does 'derived' include member-types of unions?
19434             */
19435             if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19436                 if (xmlSchemaIsDerivedFromBuiltInType(
19437                     WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19438                 {
19439                     if (hasId) {
19440                         xmlChar *str = NULL;
19441
19442                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
19443                             XML_SCHEMAP_AG_PROPS_CORRECT,
19444                             attrGr->node, WXS_BASIC_CAST attrGr,
19445                             "There must not exist more than one attribute "
19446                             "declaration of type 'xs:ID' "
19447                             "(or derived from 'xs:ID'). The %s violates this "
19448                             "constraint",
19449                             xmlSchemaGetComponentDesignation(&str, use),
19450                             NULL);
19451                         FREE_AND_NULL(str);
19452                         if (xmlSchemaItemListRemove(uses, i) == -1)
19453                             return(-1);
19454                     }
19455                     hasId = 1;
19456                 }
19457             }
19458 next_use: {}
19459         }
19460     }
19461     return(0);
19462 }
19463
19464 /**
19465  * xmlSchemaResolveAttrGroupReferences:
19466  * @attrgrpDecl:  the schema attribute definition
19467  * @ctxt:  the schema parser context
19468  * @name:  the attribute name
19469  *
19470  * Resolves references to attribute group definitions.
19471  */
19472 static int
19473 xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19474                                     xmlSchemaParserCtxtPtr ctxt)
19475 {
19476     xmlSchemaAttributeGroupPtr group;
19477
19478     if (ref->item != NULL)
19479         return(0);
19480     group = xmlSchemaGetAttributeGroup(ctxt->schema,
19481         ref->name,
19482         ref->targetNamespace);
19483     if (group == NULL) {
19484         xmlSchemaPResCompAttrErr(ctxt,
19485             XML_SCHEMAP_SRC_RESOLVE,
19486             NULL, ref->node,
19487             "ref", ref->name, ref->targetNamespace,
19488             ref->itemType, NULL);
19489         return(ctxt->err);
19490     }
19491     ref->item = WXS_BASIC_CAST group;
19492     return(0);
19493 }
19494
19495 /**
19496  * xmlSchemaCheckAttrPropsCorrect:
19497  * @item:  an schema attribute declaration/use
19498  * @ctxt:  a schema parser context
19499  * @name:  the name of the attribute
19500  *
19501  *
19502  * Schema Component Constraint:
19503  *    Attribute Declaration Properties Correct (a-props-correct)
19504  *
19505  * Validates the value constraints of an attribute declaration/use.
19506  * NOTE that this needs the simle type definitions to be already
19507  *   builded and checked.
19508  */
19509 static int
19510 xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19511                                xmlSchemaAttributePtr attr)
19512 {
19513
19514     /*
19515     * SPEC a-props-correct (1)
19516     * "The values of the properties of an attribute declaration must
19517     * be as described in the property tableau in The Attribute
19518     * Declaration Schema Component ($3.2.1), modulo the impact of
19519     * Missing Sub-components ($5.3)."
19520     */
19521
19522     if (WXS_ATTR_TYPEDEF(attr) == NULL)
19523         return(0);
19524
19525     if (attr->defValue != NULL) {
19526         int ret;
19527
19528         /*
19529         * SPEC a-props-correct (3)
19530         * "If the {type definition} is or is derived from ID then there
19531         * must not be a {value constraint}."
19532         */
19533         if (xmlSchemaIsDerivedFromBuiltInType(
19534             WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19535         {
19536             xmlSchemaCustomErr(ACTXT_CAST pctxt,
19537                 XML_SCHEMAP_A_PROPS_CORRECT_3,
19538                 NULL, WXS_BASIC_CAST attr,
19539                 "Value constraints are not allowed if the type definition "
19540                 "is or is derived from xs:ID",
19541                 NULL, NULL);
19542             return(pctxt->err);
19543         }
19544         /*
19545         * SPEC a-props-correct (2)
19546         * "if there is a {value constraint}, the canonical lexical
19547         * representation of its value must be `valid` with respect
19548         * to the {type definition} as defined in String Valid ($3.14.4)."
19549         * TODO: Don't care about the *canonical* stuff here, this requirement
19550         * will be removed in WXS 1.1 anyway.
19551         */
19552         ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
19553             attr->node, WXS_ATTR_TYPEDEF(attr),
19554             attr->defValue, &(attr->defVal),
19555             1, 1, 0);
19556         if (ret != 0) {
19557             if (ret < 0) {
19558                 PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
19559                     "calling xmlSchemaVCheckCVCSimpleType()");
19560                 return(-1);
19561             }
19562             xmlSchemaCustomErr(ACTXT_CAST pctxt,
19563                 XML_SCHEMAP_A_PROPS_CORRECT_2,
19564                 NULL, WXS_BASIC_CAST attr,
19565                 "The value of the value constraint is not valid",
19566                 NULL, NULL);
19567             return(pctxt->err);
19568         }
19569     }
19570
19571     return(0);
19572 }
19573
19574 static xmlSchemaElementPtr
19575 xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19576                                  xmlSchemaElementPtr ancestor)
19577 {
19578     xmlSchemaElementPtr ret;
19579
19580     if (WXS_SUBST_HEAD(ancestor) == NULL)
19581         return (NULL);
19582     if (WXS_SUBST_HEAD(ancestor) == elemDecl)
19583         return (ancestor);
19584
19585     if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
19586         return (NULL);
19587     WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
19588     ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
19589         WXS_SUBST_HEAD(ancestor));
19590     WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
19591
19592     return (ret);
19593 }
19594
19595 /**
19596  * xmlSchemaCheckElemPropsCorrect:
19597  * @ctxt:  a schema parser context
19598  * @decl: the element declaration
19599  * @name:  the name of the attribute
19600  *
19601  * Schema Component Constraint:
19602  * Element Declaration Properties Correct (e-props-correct)
19603  *
19604  * STATUS:
19605  *   missing: (6)
19606  */
19607 static int
19608 xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19609                                xmlSchemaElementPtr elemDecl)
19610 {
19611     int ret = 0;
19612     xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
19613     /*
19614     * SPEC (1) "The values of the properties of an element declaration
19615     * must be as described in the property tableau in The Element
19616     * Declaration Schema Component ($3.3.1), modulo the impact of Missing
19617     * Sub-components ($5.3)."
19618     */
19619     if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19620         xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
19621
19622         xmlSchemaCheckElementDeclComponent(head, pctxt);
19623         /*
19624         * SPEC (3) "If there is a non-`absent` {substitution group
19625         * affiliation}, then {scope} must be global."
19626         */
19627         if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19628             xmlSchemaPCustomErr(pctxt,
19629                 XML_SCHEMAP_E_PROPS_CORRECT_3,
19630                 WXS_BASIC_CAST elemDecl, NULL,
19631                 "Only global element declarations can have a "
19632                 "substitution group affiliation", NULL);
19633             ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
19634         }
19635         /*
19636         * TODO: SPEC (6) "Circular substitution groups are disallowed.
19637         * That is, it must not be possible to return to an element declaration
19638         * by repeatedly following the {substitution group affiliation}
19639         * property."
19640         */
19641         if (head == elemDecl)
19642             circ = head;
19643         else if (WXS_SUBST_HEAD(head) != NULL)
19644             circ = xmlSchemaCheckSubstGroupCircular(head, head);
19645         else
19646             circ = NULL;
19647         if (circ != NULL) {
19648             xmlChar *strA = NULL, *strB = NULL;
19649
19650             xmlSchemaPCustomErrExt(pctxt,
19651                 XML_SCHEMAP_E_PROPS_CORRECT_6,
19652                 WXS_BASIC_CAST circ, NULL,
19653                 "The element declaration '%s' defines a circular "
19654                 "substitution group to element declaration '%s'",
19655                 xmlSchemaGetComponentQName(&strA, circ),
19656                 xmlSchemaGetComponentQName(&strB, head),
19657                 NULL);
19658             FREE_AND_NULL(strA)
19659             FREE_AND_NULL(strB)
19660             ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19661         }
19662         /*
19663         * SPEC (4) "If there is a {substitution group affiliation},
19664         * the {type definition}
19665         * of the element declaration must be validly derived from the {type
19666         * definition} of the {substitution group affiliation}, given the value
19667         * of the {substitution group exclusions} of the {substitution group
19668         * affiliation}, as defined in Type Derivation OK (Complex) ($3.4.6)
19669         * (if the {type definition} is complex) or as defined in
19670         * Type Derivation OK (Simple) ($3.14.6) (if the {type definition} is
19671         * simple)."
19672         *
19673         * NOTE: {substitution group exclusions} means the values of the
19674         * attribute "final".
19675         */
19676
19677         if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
19678             int set = 0;
19679
19680             if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19681                 set |= SUBSET_EXTENSION;
19682             if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19683                 set |= SUBSET_RESTRICTION;
19684
19685             if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
19686                 WXS_ELEM_TYPEDEF(head), set) != 0) {
19687                 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19688
19689                 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
19690                 xmlSchemaPCustomErrExt(pctxt,
19691                     XML_SCHEMAP_E_PROPS_CORRECT_4,
19692                     WXS_BASIC_CAST elemDecl, NULL,
19693                     "The type definition '%s' was "
19694                     "either rejected by the substitution group "
19695                     "affiliation '%s', or not validly derived from its type "
19696                     "definition '%s'",
19697                     xmlSchemaGetComponentQName(&strA, typeDef),
19698                     xmlSchemaGetComponentQName(&strB, head),
19699                     xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
19700                 FREE_AND_NULL(strA)
19701                 FREE_AND_NULL(strB)
19702                 FREE_AND_NULL(strC)
19703             }
19704         }
19705     }
19706     /*
19707     * SPEC (5) "If the {type definition} or {type definition}'s
19708     * {content type}
19709     * is or is derived from ID then there must not be a {value constraint}.
19710     * Note: The use of ID as a type definition for elements goes beyond
19711     * XML 1.0, and should be avoided if backwards compatibility is desired"
19712     */
19713     if ((elemDecl->value != NULL) &&
19714         ((WXS_IS_SIMPLE(typeDef) &&
19715           xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
19716          (WXS_IS_COMPLEX(typeDef) &&
19717           WXS_HAS_SIMPLE_CONTENT(typeDef) &&
19718           xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19719             XML_SCHEMAS_ID)))) {
19720
19721         ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19722         xmlSchemaPCustomErr(pctxt,
19723             XML_SCHEMAP_E_PROPS_CORRECT_5,
19724             WXS_BASIC_CAST elemDecl, NULL,
19725             "The type definition (or type definition's content type) is or "
19726             "is derived from ID; value constraints are not allowed in "
19727             "conjunction with such a type definition", NULL);
19728     } else if (elemDecl->value != NULL) {
19729         int vcret;
19730         xmlNodePtr node = NULL;
19731
19732         /*
19733         * SPEC (2) "If there is a {value constraint}, the canonical lexical
19734         * representation of its value must be `valid` with respect to the
19735         * {type definition} as defined in Element Default Valid (Immediate)
19736         * ($3.3.6)."
19737         */
19738         if (typeDef == NULL) {
19739             xmlSchemaPErr(pctxt, elemDecl->node,
19740                 XML_SCHEMAP_INTERNAL,
19741                 "Internal error: xmlSchemaCheckElemPropsCorrect, "
19742                 "type is missing... skipping validation of "
19743                 "the value constraint", NULL, NULL);
19744             return (-1);
19745         }
19746         if (elemDecl->node != NULL) {
19747             if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19748                 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19749                     BAD_CAST "fixed");
19750             else
19751                 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19752                     BAD_CAST "default");
19753         }
19754         vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19755             typeDef, elemDecl->value, &(elemDecl->defVal));
19756         if (vcret != 0) {
19757             if (vcret < 0) {
19758                 PERROR_INT("xmlSchemaElemCheckValConstr",
19759                     "failed to validate the value constraint of an "
19760                     "element declaration");
19761                 return (-1);
19762             }
19763             return (vcret);
19764         }
19765     }
19766
19767     return (ret);
19768 }
19769
19770 /**
19771  * xmlSchemaCheckElemSubstGroup:
19772  * @ctxt:  a schema parser context
19773  * @decl: the element declaration
19774  * @name:  the name of the attribute
19775  *
19776  * Schema Component Constraint:
19777  * Substitution Group (cos-equiv-class)
19778  *
19779  * In Libxml2 the subst. groups will be precomputed, in terms of that
19780  * a list will be built for each subst. group head, holding all direct
19781  * referents to this head.
19782  * NOTE that this function needs:
19783  *   1. circular subst. groups to be checked beforehand
19784  *   2. the declaration's type to be derived from the head's type
19785  *
19786  * STATUS:
19787  *
19788  */
19789 static void
19790 xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19791                              xmlSchemaElementPtr elemDecl)
19792 {
19793     if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
19794         /* SPEC (1) "Its {abstract} is false." */
19795         (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19796         return;
19797     {
19798         xmlSchemaElementPtr head;
19799         xmlSchemaTypePtr headType, type;
19800         int set, methSet;
19801         /*
19802         * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19803         * {disallowed substitutions} as the blocking constraint, as defined in
19804         * Substitution Group OK (Transitive) ($3.3.6)."
19805         */
19806         for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19807             head = WXS_SUBST_HEAD(head)) {
19808             set = 0;
19809             methSet = 0;
19810             /*
19811             * The blocking constraints.
19812             */
19813             if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19814                 continue;
19815             headType = head->subtypes;
19816             type = elemDecl->subtypes;
19817             if (headType == type)
19818                 goto add_member;
19819             if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19820                 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19821             if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19822                 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19823             /*
19824             * SPEC: Substitution Group OK (Transitive) (2.3)
19825             * "The set of all {derivation method}s involved in the
19826             * derivation of D's {type definition} from C's {type definition}
19827             * does not intersect with the union of the blocking constraint,
19828             * C's {prohibited substitutions} (if C is complex, otherwise the
19829             * empty set) and the {prohibited substitutions} (respectively the
19830             * empty set) of any intermediate {type definition}s in the
19831             * derivation of D's {type definition} from C's {type definition}."
19832             */
19833             /*
19834             * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19835             * subst.head axis, the methSet does not need to be computed for
19836             * the full depth over and over.
19837             */
19838             /*
19839             * The set of all {derivation method}s involved in the derivation
19840             */
19841             while ((type != NULL) && (type != headType)) {
19842                 if ((WXS_IS_EXTENSION(type)) &&
19843                     ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19844                     methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19845
19846                 if (WXS_IS_RESTRICTION(type) &&
19847                     ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19848                     methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19849
19850                 type = type->baseType;
19851             }
19852             /*
19853             * The {prohibited substitutions} of all intermediate types +
19854             * the head's type.
19855             */
19856             type = elemDecl->subtypes->baseType;
19857             while (type != NULL) {
19858                 if (WXS_IS_COMPLEX(type)) {
19859                     if ((type->flags &
19860                             XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19861                         ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19862                     set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19863                     if ((type->flags &
19864                             XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19865                         ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19866                     set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19867                 } else
19868                     break;
19869                 if (type == headType)
19870                     break;
19871                 type = type->baseType;
19872             }
19873             if ((set != 0) &&
19874                 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19875                 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19876                 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19877                 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19878                 continue;
19879             }
19880 add_member:
19881             xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19882             if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19883                 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19884         }
19885     }
19886 }
19887
19888 #ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */
19889 /**
19890  * xmlSchemaCheckElementDeclComponent
19891  * @pctxt: the schema parser context
19892  * @ctxtComponent: the context component (an element declaration)
19893  * @ctxtParticle: the first particle of the context component
19894  * @searchParticle: the element declaration particle to be analysed
19895  *
19896  * Schema Component Constraint: Element Declarations Consistent
19897  */
19898 static int
19899 xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,
19900                                     xmlSchemaBasicItemPtr ctxtComponent,
19901                                     xmlSchemaParticlePtr ctxtParticle,
19902                                     xmlSchemaParticlePtr searchParticle,
19903                                     xmlSchemaParticlePtr curParticle,
19904                                     int search)
19905 {
19906     return(0);
19907
19908     int ret = 0;
19909     xmlSchemaParticlePtr cur = curParticle;
19910     if (curParticle == NULL) {
19911         return(0);
19912     }
19913     if (WXS_PARTICLE_TERM(curParticle) == NULL) {
19914         /*
19915         * Just return in this case. A missing "term" of the particle
19916         * might arise due to an invalid "term" component.
19917         */
19918         return(0);
19919     }
19920     while (cur != NULL) {
19921         switch (WXS_PARTICLE_TERM(cur)->type) {
19922             case XML_SCHEMA_TYPE_ANY:
19923                 break;
19924             case XML_SCHEMA_TYPE_ELEMENT:
19925                 if (search == 0) {
19926                     ret = xmlSchemaCheckElementDeclConsistent(pctxt,
19927                         ctxtComponent, ctxtParticle, cur, ctxtParticle, 1);
19928                     if (ret != 0)
19929                         return(ret);
19930                 } else {
19931                     xmlSchemaElementPtr elem =
19932                         WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur));
19933                     /*
19934                     * SPEC Element Declarations Consistent:
19935                     * "If the {particles} contains, either directly,
19936                     * indirectly (that is, within the {particles} of a
19937                     * contained model group, recursively) or `implicitly`
19938                     * two or more element declaration particles with
19939                     * the same {name} and {target namespace}, then
19940                     * all their type definitions must be the same
19941                     * top-level definition [...]"
19942                     */
19943                     if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name,
19944                             WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) &&
19945                         xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19946                             WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace))
19947                     {
19948                         xmlChar *strA = NULL, *strB = NULL;
19949
19950                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
19951                             /* TODO: error code */
19952                             XML_SCHEMAP_COS_NONAMBIG,
19953                             WXS_ITEM_NODE(cur), NULL,
19954                             "In the content model of %s, there are multiple "
19955                             "element declarations for '%s' with different "
19956                             "type definitions",
19957                             xmlSchemaGetComponentDesignation(&strA,
19958                                 ctxtComponent),
19959                             xmlSchemaFormatQName(&strB,
19960                                 WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19961                                 WXS_PARTICLE_TERM_AS_ELEM(cur)->name));
19962                         FREE_AND_NULL(strA);
19963                         FREE_AND_NULL(strB);
19964                         return(XML_SCHEMAP_COS_NONAMBIG);
19965                     }
19966                 }
19967                 break;
19968             case XML_SCHEMA_TYPE_SEQUENCE: {
19969                 break;
19970                 }
19971             case XML_SCHEMA_TYPE_CHOICE:{
19972                 /*
19973                 xmlSchemaTreeItemPtr sub;
19974
19975                 sub = WXS_PARTICLE_TERM(particle)->children;  (xmlSchemaParticlePtr)
19976                 while (sub != NULL) {
19977                     ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent,
19978                         ctxtParticle, ctxtElem);
19979                     if (ret != 0)
19980                         return(ret);
19981                     sub = sub->next;
19982                 }
19983                 */
19984                 break;
19985                 }
19986             case XML_SCHEMA_TYPE_ALL:
19987                 break;
19988             case XML_SCHEMA_TYPE_GROUP:
19989                 break;
19990             default:
19991                 xmlSchemaInternalErr2(ACTXT_CAST pctxt,
19992                     "xmlSchemaCheckElementDeclConsistent",
19993                     "found unexpected term of type '%s' in content model",
19994                     WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL);
19995                 return(-1);
19996         }
19997         cur = (xmlSchemaParticlePtr) cur->next;
19998     }
19999
20000 exit:
20001     return(ret);
20002 }
20003 #endif
20004
20005 /**
20006  * xmlSchemaCheckElementDeclComponent
20007  * @item:  an schema element declaration/particle
20008  * @ctxt:  a schema parser context
20009  * @name:  the name of the attribute
20010  *
20011  * Validates the value constraints of an element declaration.
20012  * Adds substitution group members.
20013  */
20014 static void
20015 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
20016                                    xmlSchemaParserCtxtPtr ctxt)
20017 {
20018     if (elemDecl == NULL)
20019         return;
20020     if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
20021         return;
20022     elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
20023     if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) {
20024         /*
20025         * Adds substitution group members.
20026         */
20027         xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
20028     }
20029 }
20030
20031 /**
20032  * xmlSchemaResolveModelGroupParticleReferences:
20033  * @particle:  a particle component
20034  * @ctxt:  a parser context
20035  *
20036  * Resolves references of a model group's {particles} to
20037  * model group definitions and to element declarations.
20038  */
20039 static void
20040 xmlSchemaResolveModelGroupParticleReferences(
20041     xmlSchemaParserCtxtPtr ctxt,
20042     xmlSchemaModelGroupPtr mg)
20043 {
20044     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
20045     xmlSchemaQNameRefPtr ref;
20046     xmlSchemaBasicItemPtr refItem;
20047
20048     /*
20049     * URGENT TODO: Test this.
20050     */
20051     while (particle != NULL) {
20052         if ((WXS_PARTICLE_TERM(particle) == NULL) ||
20053             ((WXS_PARTICLE_TERM(particle))->type !=
20054                 XML_SCHEMA_EXTRA_QNAMEREF))
20055         {
20056             goto next_particle;
20057         }
20058         ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
20059         /*
20060         * Resolve the reference.
20061         * NULL the {term} by default.
20062         */
20063         particle->children = NULL;
20064
20065         refItem = xmlSchemaGetNamedComponent(ctxt->schema,
20066             ref->itemType, ref->name, ref->targetNamespace);
20067         if (refItem == NULL) {
20068             xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
20069                 NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
20070                 ref->targetNamespace, ref->itemType, NULL);
20071             /* TODO: remove the particle. */
20072             goto next_particle;
20073         }
20074         if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
20075             if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
20076                 /* TODO: remove the particle. */
20077                 goto next_particle;
20078             /*
20079             * NOTE that we will assign the model group definition
20080             * itself to the "term" of the particle. This will ease
20081             * the check for circular model group definitions. After
20082             * that the "term" will be assigned the model group of the
20083             * model group definition.
20084             */
20085             if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
20086                     XML_SCHEMA_TYPE_ALL) {
20087                 /*
20088                 * SPEC cos-all-limited (1)
20089                 * SPEC cos-all-limited (1.2)
20090                 * "It appears only as the value of one or both of the
20091                 * following properties:"
20092                 * (1.1) "the {model group} property of a model group
20093                 *        definition."
20094                 * (1.2) "the {term} property of a particle [... of] the "
20095                 * {content type} of a complex type definition."
20096                 */
20097                 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20098                     /* TODO: error code */
20099                     XML_SCHEMAP_COS_ALL_LIMITED,
20100                     WXS_ITEM_NODE(particle), NULL,
20101                     "A model group definition is referenced, but "
20102                     "it contains an 'all' model group, which "
20103                     "cannot be contained by model groups",
20104                     NULL, NULL);
20105                 /* TODO: remove the particle. */
20106                 goto next_particle;
20107             }
20108             particle->children = (xmlSchemaTreeItemPtr) refItem;
20109         } else {
20110             /*
20111             * TODO: Are referenced element declarations the only
20112             * other components we expect here?
20113             */
20114             particle->children = (xmlSchemaTreeItemPtr) refItem;
20115         }
20116 next_particle:
20117         particle = WXS_PTC_CAST particle->next;
20118     }
20119 }
20120
20121 static int
20122 xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
20123                        xmlSchemaValPtr y)
20124 {
20125     xmlSchemaTypePtr tx, ty, ptx, pty;
20126     int ret;
20127
20128     while (x != NULL) {
20129         /* Same types. */
20130         tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
20131         ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
20132         ptx = xmlSchemaGetPrimitiveType(tx);
20133         pty = xmlSchemaGetPrimitiveType(ty);
20134         /*
20135         * (1) if a datatype T' is `derived` by `restriction` from an
20136         * atomic datatype T then the `value space` of T' is a subset of
20137         * the `value space` of T. */
20138         /*
20139         * (2) if datatypes T' and T'' are `derived` by `restriction`
20140         * from a common atomic ancestor T then the `value space`s of T'
20141         * and T'' may overlap.
20142         */
20143         if (ptx != pty)
20144             return(0);
20145         /*
20146         * We assume computed values to be normalized, so do a fast
20147         * string comparison for string based types.
20148         */
20149         if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
20150             WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
20151             if (! xmlStrEqual(
20152                 xmlSchemaValueGetAsString(x),
20153                 xmlSchemaValueGetAsString(y)))
20154                 return (0);
20155         } else {
20156             ret = xmlSchemaCompareValuesWhtsp(
20157                 x, XML_SCHEMA_WHITESPACE_PRESERVE,
20158                 y, XML_SCHEMA_WHITESPACE_PRESERVE);
20159             if (ret == -2)
20160                 return(-1);
20161             if (ret != 0)
20162                 return(0);
20163         }
20164         /*
20165         * Lists.
20166         */
20167         x = xmlSchemaValueGetNext(x);
20168         if (x != NULL) {
20169             y = xmlSchemaValueGetNext(y);
20170             if (y == NULL)
20171                 return (0);
20172         } else if (xmlSchemaValueGetNext(y) != NULL)
20173             return (0);
20174         else
20175             return (1);
20176     }
20177     return (0);
20178 }
20179
20180 /**
20181  * xmlSchemaResolveAttrUseReferences:
20182  * @item:  an attribute use
20183  * @ctxt:  a parser context
20184  *
20185  * Resolves the referenced attribute declaration.
20186  */
20187 static int
20188 xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
20189                                   xmlSchemaParserCtxtPtr ctxt)
20190 {
20191     if ((ctxt == NULL) || (ause == NULL))
20192         return(-1);
20193     if ((ause->attrDecl == NULL) ||
20194         (ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
20195         return(0);
20196
20197     {
20198         xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
20199
20200         /*
20201         * TODO: Evaluate, what errors could occur if the declaration is not
20202         * found.
20203         */
20204         ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
20205             ref->name, ref->targetNamespace);
20206         if (ause->attrDecl == NULL) {
20207             xmlSchemaPResCompAttrErr(ctxt,
20208                 XML_SCHEMAP_SRC_RESOLVE,
20209                 WXS_BASIC_CAST ause, ause->node,
20210                 "ref", ref->name, ref->targetNamespace,
20211                 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20212             return(ctxt->err);;
20213         }
20214     }
20215     return(0);
20216 }
20217
20218 /**
20219  * xmlSchemaCheckAttrUsePropsCorrect:
20220  * @ctxt:  a parser context
20221  * @use:  an attribute use
20222  *
20223  * Schema Component Constraint:
20224  * Attribute Use Correct (au-props-correct)
20225  *
20226  */
20227 static int
20228 xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
20229                              xmlSchemaAttributeUsePtr use)
20230 {
20231     if ((ctxt == NULL) || (use == NULL))
20232         return(-1);
20233     if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
20234         ((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
20235         return(0);
20236
20237     /*
20238     * SPEC au-props-correct (1)
20239     * "The values of the properties of an attribute use must be as
20240     * described in the property tableau in The Attribute Use Schema
20241     * Component ($3.5.1), modulo the impact of Missing
20242     * Sub-components ($5.3)."
20243     */
20244
20245     if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
20246         ((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
20247         ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20248     {
20249         xmlSchemaPCustomErr(ctxt,
20250             XML_SCHEMAP_AU_PROPS_CORRECT_2,
20251             WXS_BASIC_CAST use, NULL,
20252             "The attribute declaration has a 'fixed' value constraint "
20253             ", thus the attribute use must also have a 'fixed' value "
20254             "constraint",
20255             NULL);
20256         return(ctxt->err);
20257     }
20258     /*
20259     * Compute and check the value constraint's value.
20260     */
20261     if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
20262         int ret;
20263         /*
20264         * TODO: The spec seems to be missing a check of the
20265         * value constraint of the attribute use. We will do it here.
20266         */
20267         /*
20268         * SPEC a-props-correct (3)
20269         */
20270         if (xmlSchemaIsDerivedFromBuiltInType(
20271             WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20272         {
20273             xmlSchemaCustomErr(ACTXT_CAST ctxt,
20274                 XML_SCHEMAP_AU_PROPS_CORRECT,
20275                 NULL, WXS_BASIC_CAST use,
20276                 "Value constraints are not allowed if the type definition "
20277                 "is or is derived from xs:ID",
20278                 NULL, NULL);
20279             return(ctxt->err);
20280         }
20281
20282         ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20283             use->node, WXS_ATTRUSE_TYPEDEF(use),
20284             use->defValue, &(use->defVal),
20285             1, 1, 0);
20286         if (ret != 0) {
20287             if (ret < 0) {
20288                 PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20289                     "calling xmlSchemaVCheckCVCSimpleType()");
20290                 return(-1);
20291             }
20292             xmlSchemaCustomErr(ACTXT_CAST ctxt,
20293                 XML_SCHEMAP_AU_PROPS_CORRECT,
20294                 NULL, WXS_BASIC_CAST use,
20295                 "The value of the value constraint is not valid",
20296                 NULL, NULL);
20297             return(ctxt->err);
20298         }
20299     }
20300     /*
20301     * SPEC au-props-correct (2)
20302     * "If the {attribute declaration} has a fixed
20303     * {value constraint}, then if the attribute use itself has a
20304     * {value constraint}, it must also be fixed and its value must match
20305     * that of the {attribute declaration}'s {value constraint}."
20306     */
20307     if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20308         (((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20309     {
20310         if (! xmlSchemaAreValuesEqual(use->defVal,
20311                 (WXS_ATTRUSE_DECL(use))->defVal))
20312         {
20313             xmlSchemaPCustomErr(ctxt,
20314                 XML_SCHEMAP_AU_PROPS_CORRECT_2,
20315                 WXS_BASIC_CAST use, NULL,
20316                 "The 'fixed' value constraint of the attribute use "
20317                 "must match the attribute declaration's value "
20318                 "constraint '%s'",
20319                 (WXS_ATTRUSE_DECL(use))->defValue);
20320         }
20321         return(ctxt->err);
20322     }
20323     return(0);
20324 }
20325
20326
20327
20328
20329 /**
20330  * xmlSchemaResolveAttrTypeReferences:
20331  * @item:  an attribute declaration
20332  * @ctxt:  a parser context
20333  *
20334  * Resolves the referenced type definition component.
20335  */
20336 static int
20337 xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20338                                    xmlSchemaParserCtxtPtr ctxt)
20339 {
20340     /*
20341     * The simple type definition corresponding to the <simpleType> element
20342     * information item in the [children], if present, otherwise the simple
20343     * type definition `resolved` to by the `actual value` of the type
20344     * [attribute], if present, otherwise the `simple ur-type definition`.
20345     */
20346     if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
20347         return(0);
20348     item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20349     if (item->subtypes != NULL)
20350         return(0);
20351     if (item->typeName != NULL) {
20352         xmlSchemaTypePtr type;
20353
20354         type = xmlSchemaGetType(ctxt->schema, item->typeName,
20355             item->typeNs);
20356         if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
20357             xmlSchemaPResCompAttrErr(ctxt,
20358                 XML_SCHEMAP_SRC_RESOLVE,
20359                 WXS_BASIC_CAST item, item->node,
20360                 "type", item->typeName, item->typeNs,
20361                 XML_SCHEMA_TYPE_SIMPLE, NULL);
20362             return(ctxt->err);
20363         } else
20364             item->subtypes = type;
20365
20366     } else {
20367         /*
20368         * The type defaults to the xs:anySimpleType.
20369         */
20370         item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20371     }
20372     return(0);
20373 }
20374
20375 /**
20376  * xmlSchemaResolveIDCKeyReferences:
20377  * @idc:  the identity-constraint definition
20378  * @ctxt:  the schema parser context
20379  * @name:  the attribute name
20380  *
20381  * Resolve keyRef references to key/unique IDCs.
20382  * Schema Component Constraint:
20383  *   Identity-constraint Definition Properties Correct (c-props-correct)
20384  */
20385 static int
20386 xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
20387                           xmlSchemaParserCtxtPtr pctxt)
20388 {
20389     if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
20390         return(0);
20391     if (idc->ref->name != NULL) {
20392         idc->ref->item = (xmlSchemaBasicItemPtr)
20393             xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20394                 idc->ref->targetNamespace);
20395         if (idc->ref->item == NULL) {
20396             /*
20397             * TODO: It is actually not an error to fail to resolve
20398             * at this stage. BUT we need to be that strict!
20399             */
20400             xmlSchemaPResCompAttrErr(pctxt,
20401                 XML_SCHEMAP_SRC_RESOLVE,
20402                 WXS_BASIC_CAST idc, idc->node,
20403                 "refer", idc->ref->name,
20404                 idc->ref->targetNamespace,
20405                 XML_SCHEMA_TYPE_IDC_KEY, NULL);
20406             return(pctxt->err);
20407         } else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20408             /*
20409             * SPEC c-props-correct (1)
20410             */
20411             xmlSchemaCustomErr(ACTXT_CAST pctxt,
20412                 XML_SCHEMAP_C_PROPS_CORRECT,
20413                 NULL, WXS_BASIC_CAST idc,
20414                 "The keyref references a keyref",
20415                 NULL, NULL);
20416             idc->ref->item = NULL;
20417             return(pctxt->err);
20418         } else {
20419             if (idc->nbFields !=
20420                 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20421                 xmlChar *str = NULL;
20422                 xmlSchemaIDCPtr refer;
20423
20424                 refer = (xmlSchemaIDCPtr) idc->ref->item;
20425                 /*
20426                 * SPEC c-props-correct(2)
20427                 * "If the {identity-constraint category} is keyref,
20428                 * the cardinality of the {fields} must equal that of
20429                 * the {fields} of the {referenced key}.
20430                 */
20431                 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20432                     XML_SCHEMAP_C_PROPS_CORRECT,
20433                     NULL, WXS_BASIC_CAST idc,
20434                     "The cardinality of the keyref differs from the "
20435                     "cardinality of the referenced key/unique '%s'",
20436                     xmlSchemaFormatQName(&str, refer->targetNamespace,
20437                         refer->name),
20438                     NULL);
20439                 FREE_AND_NULL(str)
20440                 return(pctxt->err);
20441             }
20442         }
20443     }
20444     return(0);
20445 }
20446
20447 static int
20448 xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20449                                        xmlSchemaParserCtxtPtr pctxt)
20450 {
20451     if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20452         prohib->targetNamespace) == NULL) {
20453
20454         xmlSchemaPResCompAttrErr(pctxt,
20455             XML_SCHEMAP_SRC_RESOLVE,
20456             NULL, prohib->node,
20457             "ref", prohib->name, prohib->targetNamespace,
20458             XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20459         return(XML_SCHEMAP_SRC_RESOLVE);
20460     }
20461     return(0);
20462 }
20463
20464 #define WXS_REDEFINED_TYPE(c) \
20465 (((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20466
20467 #define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20468 (((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20469
20470 #define WXS_REDEFINED_ATTR_GROUP(c) \
20471 (((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20472
20473 static int
20474 xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20475 {
20476     int err = 0;
20477     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20478     xmlSchemaBasicItemPtr prev, item;
20479     int wasRedefined;
20480
20481     if (redef == NULL)
20482         return(0);
20483
20484     do {
20485         item = redef->item;
20486         /*
20487         * First try to locate the redefined component in the
20488         * schema graph starting with the redefined schema.
20489         * NOTE: According to this schema bug entry:
20490         *   http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20491         *   it's not clear if the referenced component needs to originate
20492         *   from the <redefine>d schema _document_ or the schema; the latter
20493         *   would include all imported and included sub-schemas of the
20494         *   <redefine>d schema. Currenlty we latter approach is used.
20495         *   SUPPLEMENT: It seems that the WG moves towards the latter
20496         *   approach, so we are doing it right.
20497         *
20498         */
20499         prev = xmlSchemaFindRedefCompInGraph(
20500             redef->targetBucket, item->type,
20501             redef->refName, redef->refTargetNs);
20502         if (prev == NULL) {
20503             xmlChar *str = NULL;
20504             xmlNodePtr node;
20505
20506             /*
20507             * SPEC src-redefine:
20508             * (6.2.1) "The `actual value` of its own name attribute plus
20509             * target namespace must successfully `resolve` to a model
20510             * group definition in I."
20511             * (7.2.1) "The `actual value` of its own name attribute plus
20512             * target namespace must successfully `resolve` to an attribute
20513             * group definition in I."
20514
20515             *
20516             * Note that, if we are redefining with the use of references
20517             * to components, the spec assumes the src-resolve to be used;
20518             * but this won't assure that we search only *inside* the
20519             * redefined schema.
20520             */
20521             if (redef->reference)
20522                 node = WXS_ITEM_NODE(redef->reference);
20523             else
20524                 node = WXS_ITEM_NODE(item);
20525             xmlSchemaCustomErr(ACTXT_CAST pctxt,
20526                 /*
20527                 * TODO: error code.
20528                 * Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20529                 * reference kind.
20530                 */
20531                 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
20532                 "The %s '%s' to be redefined could not be found in "
20533                 "the redefined schema",
20534                 WXS_ITEM_TYPE_NAME(item),
20535                 xmlSchemaFormatQName(&str, redef->refTargetNs,
20536                     redef->refName));
20537             FREE_AND_NULL(str);
20538             err = pctxt->err;
20539             redef = redef->next;
20540             continue;
20541         }
20542         /*
20543         * TODO: Obtaining and setting the redefinition state is really
20544         * clumsy.
20545         */
20546         wasRedefined = 0;
20547         switch (item->type) {
20548             case XML_SCHEMA_TYPE_COMPLEX:
20549             case XML_SCHEMA_TYPE_SIMPLE:
20550                 if ((WXS_TYPE_CAST prev)->flags &
20551                     XML_SCHEMAS_TYPE_REDEFINED)
20552                 {
20553                     wasRedefined = 1;
20554                     break;
20555                 }
20556                 /* Mark it as redefined. */
20557                 (WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20558                 /*
20559                 * Assign the redefined type to the
20560                 * base type of the redefining type.
20561                 * TODO: How
20562                 */
20563                 ((xmlSchemaTypePtr) item)->baseType =
20564                     (xmlSchemaTypePtr) prev;
20565                 break;
20566             case XML_SCHEMA_TYPE_GROUP:
20567                 if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20568                     XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20569                 {
20570                     wasRedefined = 1;
20571                     break;
20572                 }
20573                 /* Mark it as redefined. */
20574                 (WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20575                     XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20576                 if (redef->reference != NULL) {
20577                     /*
20578                     * Overwrite the QName-reference with the
20579                     * referenced model group def.
20580                     */
20581                     (WXS_PTC_CAST redef->reference)->children =
20582                         WXS_TREE_CAST prev;
20583                 }
20584                 redef->target = prev;
20585                 break;
20586             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20587                 if ((WXS_ATTR_GROUP_CAST prev)->flags &
20588                     XML_SCHEMAS_ATTRGROUP_REDEFINED)
20589                 {
20590                     wasRedefined = 1;
20591                     break;
20592                 }
20593                 (WXS_ATTR_GROUP_CAST prev)->flags |=
20594                     XML_SCHEMAS_ATTRGROUP_REDEFINED;
20595                 if (redef->reference != NULL) {
20596                     /*
20597                     * Assign the redefined attribute group to the
20598                     * QName-reference component.
20599                     * This is the easy case, since we will just
20600                     * expand the redefined group.
20601                     */
20602                     (WXS_QNAME_CAST redef->reference)->item = prev;
20603                     redef->target = NULL;
20604                 } else {
20605                     /*
20606                     * This is the complicated case: we need
20607                     * to apply src-redefine (7.2.2) at a later
20608                     * stage, i.e. when attribute group references
20609                     * have beed expanded and simple types have
20610                     * beed fixed.
20611                     */
20612                     redef->target = prev;
20613                 }
20614                 break;
20615             default:
20616                 PERROR_INT("xmlSchemaResolveRedefReferences",
20617                     "Unexpected redefined component type");
20618                 return(-1);
20619         }
20620         if (wasRedefined) {
20621             xmlChar *str = NULL;
20622             xmlNodePtr node;
20623
20624             if (redef->reference)
20625                 node = WXS_ITEM_NODE(redef->reference);
20626             else
20627                 node = WXS_ITEM_NODE(redef->item);
20628
20629             xmlSchemaCustomErr(ACTXT_CAST pctxt,
20630                 /* TODO: error code. */
20631                 XML_SCHEMAP_SRC_REDEFINE,
20632                 node, NULL,
20633                 "The referenced %s was already redefined. Multiple "
20634                 "redefinition of the same component is not supported",
20635                 xmlSchemaGetComponentDesignation(&str, prev),
20636                 NULL);
20637             FREE_AND_NULL(str)
20638             err = pctxt->err;
20639             redef = redef->next;
20640             continue;
20641         }
20642         redef = redef->next;
20643     } while (redef != NULL);
20644
20645     return(err);
20646 }
20647
20648 static int
20649 xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20650 {
20651     int err = 0;
20652     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20653     xmlSchemaBasicItemPtr item;
20654
20655     if (redef == NULL)
20656         return(0);
20657
20658     do {
20659         if (redef->target == NULL) {
20660             redef = redef->next;
20661             continue;
20662         }
20663         item = redef->item;
20664
20665         switch (item->type) {
20666             case XML_SCHEMA_TYPE_SIMPLE:
20667             case XML_SCHEMA_TYPE_COMPLEX:
20668                 /*
20669                 * Since the spec wants the {name} of the redefined
20670                 * type to be 'absent', we'll NULL it.
20671                 */
20672                 (WXS_TYPE_CAST redef->target)->name = NULL;
20673
20674                 /*
20675                 * TODO: Seems like there's nothing more to do. The normal
20676                 * inheritance mechanism is used. But not 100% sure.
20677                 */
20678                 break;
20679             case XML_SCHEMA_TYPE_GROUP:
20680                 /*
20681                 * URGENT TODO:
20682                 * SPEC src-redefine:
20683                 * (6.2.2) "The {model group} of the model group definition
20684                 * which corresponds to it per XML Representation of Model
20685                 * Group Definition Schema Components ($3.7.2) must be a
20686                 * `valid restriction` of the {model group} of that model
20687                 * group definition in I, as defined in Particle Valid
20688                 * (Restriction) ($3.9.6)."
20689                 */
20690                 break;
20691             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20692                 /*
20693                 * SPEC src-redefine:
20694                 * (7.2.2) "The {attribute uses} and {attribute wildcard} of
20695                 * the attribute group definition which corresponds to it
20696                 * per XML Representation of Attribute Group Definition Schema
20697                 * Components ($3.6.2) must be `valid restrictions` of the
20698                 * {attribute uses} and {attribute wildcard} of that attribute
20699                 * group definition in I, as defined in clause 2, clause 3 and
20700                 * clause 4 of Derivation Valid (Restriction, Complex)
20701                 * ($3.4.6) (where references to the base type definition are
20702                 * understood as references to the attribute group definition
20703                 * in I)."
20704                 */
20705                 err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20706                     XML_SCHEMA_ACTION_REDEFINE,
20707                     item, redef->target,
20708                     (WXS_ATTR_GROUP_CAST item)->attrUses,
20709                     (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20710                     (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20711                     (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20712                 if (err == -1)
20713                     return(-1);
20714                 break;
20715             default:
20716                 break;
20717         }
20718         redef = redef->next;
20719     } while (redef != NULL);
20720     return(0);
20721 }
20722
20723
20724 static int
20725 xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20726                        xmlSchemaBucketPtr bucket)
20727 {
20728     xmlSchemaBasicItemPtr item;
20729     int err;
20730     xmlHashTablePtr *table;
20731     const xmlChar *name;
20732     int i;
20733
20734 #define WXS_GET_GLOBAL_HASH(c, slot) { \
20735     if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20736         table = &(WXS_IMPBUCKET((c))->schema->slot); \
20737     else \
20738         table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20739
20740     /*
20741     * Add global components to the schema's hash tables.
20742     * This is the place where duplicate components will be
20743     * detected.
20744     * TODO: I think normally we should support imports of the
20745     *   same namespace from multiple locations. We don't do currently,
20746     *   but if we do then according to:
20747     *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20748     *   we would need, if imported directly, to import redefined
20749     *   components as well to be able to catch clashing components.
20750     *   (I hope I'll still know what this means after some months :-()
20751     */
20752     if (bucket == NULL)
20753         return(-1);
20754     if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20755         return(0);
20756     bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20757
20758     for (i = 0; i < bucket->globals->nbItems; i++) {
20759         item = bucket->globals->items[i];
20760         table = NULL;
20761         switch (item->type) {
20762             case XML_SCHEMA_TYPE_COMPLEX:
20763             case XML_SCHEMA_TYPE_SIMPLE:
20764                 if (WXS_REDEFINED_TYPE(item))
20765                     continue;
20766                 name = (WXS_TYPE_CAST item)->name;
20767                 WXS_GET_GLOBAL_HASH(bucket, typeDecl)
20768                 break;
20769             case XML_SCHEMA_TYPE_ELEMENT:
20770                 name = (WXS_ELEM_CAST item)->name;
20771                 WXS_GET_GLOBAL_HASH(bucket, elemDecl)
20772                 break;
20773             case XML_SCHEMA_TYPE_ATTRIBUTE:
20774                 name = (WXS_ATTR_CAST item)->name;
20775                 WXS_GET_GLOBAL_HASH(bucket, attrDecl)
20776                 break;
20777             case XML_SCHEMA_TYPE_GROUP:
20778                 if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20779                     continue;
20780                 name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20781                 WXS_GET_GLOBAL_HASH(bucket, groupDecl)
20782                 break;
20783             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20784                 if (WXS_REDEFINED_ATTR_GROUP(item))
20785                     continue;
20786                 name = (WXS_ATTR_GROUP_CAST item)->name;
20787                 WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
20788                 break;
20789             case XML_SCHEMA_TYPE_IDC_KEY:
20790             case XML_SCHEMA_TYPE_IDC_UNIQUE:
20791             case XML_SCHEMA_TYPE_IDC_KEYREF:
20792                 name = (WXS_IDC_CAST item)->name;
20793                 WXS_GET_GLOBAL_HASH(bucket, idcDef)
20794                 break;
20795             case XML_SCHEMA_TYPE_NOTATION:
20796                 name = ((xmlSchemaNotationPtr) item)->name;
20797                 WXS_GET_GLOBAL_HASH(bucket, notaDecl)
20798                 break;
20799             default:
20800                 PERROR_INT("xmlSchemaAddComponents",
20801                     "Unexpected global component type");
20802                 continue;
20803         }
20804         if (*table == NULL) {
20805             *table = xmlHashCreateDict(10, pctxt->dict);
20806             if (*table == NULL) {
20807                 PERROR_INT("xmlSchemaAddComponents",
20808                     "failed to create a component hash table");
20809                 return(-1);
20810             }
20811         }
20812         err = xmlHashAddEntry(*table, name, item);
20813         if (err != 0) {
20814             xmlChar *str = NULL;
20815
20816             xmlSchemaCustomErr(ACTXT_CAST pctxt,
20817                 XML_SCHEMAP_REDEFINED_TYPE,
20818                 WXS_ITEM_NODE(item),
20819                 WXS_BASIC_CAST item,
20820                 "A global %s '%s' does already exist",
20821                 WXS_ITEM_TYPE_NAME(item),
20822                 xmlSchemaGetComponentQName(&str, item));
20823             FREE_AND_NULL(str);
20824         }
20825     }
20826     /*
20827     * Process imported/included schemas.
20828     */
20829     if (bucket->relations != NULL) {
20830         xmlSchemaSchemaRelationPtr rel = bucket->relations;
20831         do {
20832             if ((rel->bucket != NULL) &&
20833                 ((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20834                 if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20835                     return(-1);
20836             }
20837             rel = rel->next;
20838         } while (rel != NULL);
20839     }
20840     return(0);
20841 }
20842
20843 static int
20844 xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20845                          xmlSchemaBucketPtr rootBucket)
20846 {
20847     xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20848     xmlSchemaTreeItemPtr item, *items;
20849     int nbItems, i, ret = 0;
20850     xmlSchemaBucketPtr oldbucket = con->bucket;
20851     xmlSchemaElementPtr elemDecl;
20852
20853 #define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20854
20855     if ((con->pending == NULL) ||
20856         (con->pending->nbItems == 0))
20857         return(0);
20858
20859     /*
20860     * Since xmlSchemaFixupComplexType() will create new particles
20861     * (local components), and those particle components need a bucket
20862     * on the constructor, we'll assure here that the constructor has
20863     * a bucket.
20864     * TODO: Think about storing locals _only_ on the main bucket.
20865     */
20866     if (con->bucket == NULL)
20867         con->bucket = rootBucket;
20868
20869     /* TODO:
20870     * SPEC (src-redefine):
20871     * (6.2) "If it has no such self-reference, then all of the
20872     * following must be true:"
20873
20874     * (6.2.2) The {model group} of the model group definition which
20875     * corresponds to it per XML Representation of Model Group
20876     * Definition Schema Components ($3.7.2) must be a `valid
20877     * restriction` of the {model group} of that model group definition
20878     * in I, as defined in Particle Valid (Restriction) ($3.9.6)."
20879     */
20880     xmlSchemaCheckSRCRedefineFirst(pctxt);
20881
20882     /*
20883     * Add global components to the schemata's hash tables.
20884     */
20885     xmlSchemaAddComponents(pctxt, rootBucket);
20886
20887     pctxt->ctxtType = NULL;
20888     items = (xmlSchemaTreeItemPtr *) con->pending->items;
20889     nbItems = con->pending->nbItems;
20890     /*
20891     * Now that we have parsed *all* the schema document(s) and converted
20892     * them to schema components, we can resolve references, apply component
20893     * constraints, create the FSA from the content model, etc.
20894     */
20895     /*
20896     * Resolve references of..
20897     *
20898     * 1. element declarations:
20899     *   - the type definition
20900     *   - the substitution group affiliation
20901     * 2. simple/complex types:
20902     *   - the base type definition
20903     *   - the memberTypes of union types
20904     *   - the itemType of list types
20905     * 3. attributes declarations and attribute uses:
20906     *   - the type definition
20907     *   - if an attribute use, then the attribute declaration
20908     * 4. attribute group references:
20909     *   - the attribute group definition
20910     * 5. particles:
20911     *   - the term of the particle (e.g. a model group)
20912     * 6. IDC key-references:
20913     *   - the referenced IDC 'key' or 'unique' definition
20914     * 7. Attribute prohibitions which had a "ref" attribute.
20915     */
20916     for (i = 0; i < nbItems; i++) {
20917         item = items[i];
20918         switch (item->type) {
20919             case XML_SCHEMA_TYPE_ELEMENT:
20920                 xmlSchemaResolveElementReferences(
20921                     (xmlSchemaElementPtr) item, pctxt);
20922                 FIXHFAILURE;
20923                 break;
20924             case XML_SCHEMA_TYPE_COMPLEX:
20925             case XML_SCHEMA_TYPE_SIMPLE:
20926                 xmlSchemaResolveTypeReferences(
20927                     (xmlSchemaTypePtr) item, pctxt);
20928                 FIXHFAILURE;
20929                 break;
20930             case XML_SCHEMA_TYPE_ATTRIBUTE:
20931                 xmlSchemaResolveAttrTypeReferences(
20932                     (xmlSchemaAttributePtr) item, pctxt);
20933                 FIXHFAILURE;
20934                 break;
20935             case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20936                 xmlSchemaResolveAttrUseReferences(
20937                     (xmlSchemaAttributeUsePtr) item, pctxt);
20938                 FIXHFAILURE;
20939                 break;
20940             case XML_SCHEMA_EXTRA_QNAMEREF:
20941                 if ((WXS_QNAME_CAST item)->itemType ==
20942                     XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20943                 {
20944                     xmlSchemaResolveAttrGroupReferences(
20945                         WXS_QNAME_CAST item, pctxt);
20946                 }
20947                 FIXHFAILURE;
20948                 break;
20949             case XML_SCHEMA_TYPE_SEQUENCE:
20950             case XML_SCHEMA_TYPE_CHOICE:
20951             case XML_SCHEMA_TYPE_ALL:
20952                 xmlSchemaResolveModelGroupParticleReferences(pctxt,
20953                     WXS_MODEL_GROUP_CAST item);
20954                 FIXHFAILURE;
20955                 break;
20956             case XML_SCHEMA_TYPE_IDC_KEY:
20957             case XML_SCHEMA_TYPE_IDC_UNIQUE:
20958             case XML_SCHEMA_TYPE_IDC_KEYREF:
20959                 xmlSchemaResolveIDCKeyReferences(
20960                     (xmlSchemaIDCPtr) item, pctxt);
20961                 FIXHFAILURE;
20962                 break;
20963             case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20964                 /*
20965                 * Handle attribue prohibition which had a
20966                 * "ref" attribute.
20967                 */
20968                 xmlSchemaResolveAttrUseProhibReferences(
20969                     WXS_ATTR_PROHIB_CAST item, pctxt);
20970                 FIXHFAILURE;
20971                 break;
20972             default:
20973                 break;
20974         }
20975     }
20976     if (pctxt->nberrors != 0)
20977         goto exit_error;
20978
20979     /*
20980     * Now that all references are resolved we
20981     * can check for circularity of...
20982     * 1. the base axis of type definitions
20983     * 2. nested model group definitions
20984     * 3. nested attribute group definitions
20985     * TODO: check for circual substitution groups.
20986     */
20987     for (i = 0; i < nbItems; i++) {
20988         item = items[i];
20989         /*
20990         * Let's better stop on the first error here.
20991         */
20992         switch (item->type) {
20993             case XML_SCHEMA_TYPE_COMPLEX:
20994             case XML_SCHEMA_TYPE_SIMPLE:
20995                 xmlSchemaCheckTypeDefCircular(
20996                     (xmlSchemaTypePtr) item, pctxt);
20997                 FIXHFAILURE;
20998                 if (pctxt->nberrors != 0)
20999                     goto exit_error;
21000                 break;
21001             case XML_SCHEMA_TYPE_GROUP:
21002                 xmlSchemaCheckGroupDefCircular(
21003                     (xmlSchemaModelGroupDefPtr) item, pctxt);
21004                 FIXHFAILURE;
21005                 if (pctxt->nberrors != 0)
21006                     goto exit_error;
21007                 break;
21008             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21009                 xmlSchemaCheckAttrGroupCircular(
21010                     (xmlSchemaAttributeGroupPtr) item, pctxt);
21011                 FIXHFAILURE;
21012                 if (pctxt->nberrors != 0)
21013                     goto exit_error;
21014                 break;
21015             default:
21016                 break;
21017         }
21018     }
21019     if (pctxt->nberrors != 0)
21020         goto exit_error;
21021     /*
21022     * Model group definition references:
21023     * Such a reference is reflected by a particle at the component
21024     * level. Until now the 'term' of such particles pointed
21025     * to the model group definition; this was done, in order to
21026     * ease circularity checks. Now we need to set the 'term' of
21027     * such particles to the model group of the model group definition.
21028     */
21029     for (i = 0; i < nbItems; i++) {
21030         item = items[i];
21031         switch (item->type) {
21032             case XML_SCHEMA_TYPE_SEQUENCE:
21033             case XML_SCHEMA_TYPE_CHOICE:
21034                 xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
21035                     WXS_MODEL_GROUP_CAST item);
21036                 break;
21037             default:
21038                 break;
21039         }
21040     }
21041     if (pctxt->nberrors != 0)
21042         goto exit_error;
21043     /*
21044     * Expand attribute group references of attribute group definitions.
21045     */
21046     for (i = 0; i < nbItems; i++) {
21047         item = items[i];
21048         switch (item->type) {
21049             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21050                 if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
21051                     WXS_ATTR_GROUP_HAS_REFS(item))
21052                 {
21053                     xmlSchemaAttributeGroupExpandRefs(pctxt,
21054                         WXS_ATTR_GROUP_CAST item);
21055                     FIXHFAILURE;
21056                 }
21057                 break;
21058             default:
21059                 break;
21060         }
21061     }
21062     if (pctxt->nberrors != 0)
21063         goto exit_error;
21064     /*
21065     * First compute the variety of simple types. This is needed as
21066     * a seperate step, since otherwise we won't be able to detect
21067     * circular union types in all cases.
21068     */
21069     for (i = 0; i < nbItems; i++) {
21070         item = items[i];
21071         switch (item->type) {
21072             case XML_SCHEMA_TYPE_SIMPLE:
21073                 if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
21074                     xmlSchemaFixupSimpleTypeStageOne(pctxt,
21075                         (xmlSchemaTypePtr) item);
21076                     FIXHFAILURE;
21077                 }
21078                 break;
21079             default:
21080                 break;
21081         }
21082     }
21083     if (pctxt->nberrors != 0)
21084         goto exit_error;
21085     /*
21086     * Detect circular union types. Note that this needs the variety to
21087     * be already computed.
21088     */
21089     for (i = 0; i < nbItems; i++) {
21090         item = items[i];
21091         switch (item->type) {
21092             case XML_SCHEMA_TYPE_SIMPLE:
21093                 if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
21094                     xmlSchemaCheckUnionTypeDefCircular(pctxt,
21095                         (xmlSchemaTypePtr) item);
21096                     FIXHFAILURE;
21097                 }
21098                 break;
21099             default:
21100                 break;
21101         }
21102     }
21103     if (pctxt->nberrors != 0)
21104         goto exit_error;
21105
21106     /*
21107     * Do the complete type fixup for simple types.
21108     */
21109     for (i = 0; i < nbItems; i++) {
21110         item = items[i];
21111         switch (item->type) {
21112             case XML_SCHEMA_TYPE_SIMPLE:
21113                 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21114                     xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
21115                     FIXHFAILURE;
21116                 }
21117                 break;
21118             default:
21119                 break;
21120         }
21121     }
21122     if (pctxt->nberrors != 0)
21123         goto exit_error;
21124     /*
21125     * At this point we need build and check all simple types.
21126     */
21127     /*
21128     * Apply contraints for attribute declarations.
21129     */
21130     for (i = 0; i < nbItems; i++) {
21131         item = items[i];
21132         switch (item->type) {
21133             case XML_SCHEMA_TYPE_ATTRIBUTE:
21134                 xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
21135                 FIXHFAILURE;
21136                 break;
21137             default:
21138                 break;
21139         }
21140     }
21141     if (pctxt->nberrors != 0)
21142         goto exit_error;
21143     /*
21144     * Apply constraints for attribute uses.
21145     */
21146     for (i = 0; i < nbItems; i++) {
21147         item = items[i];
21148         switch (item->type) {
21149             case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21150                 if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
21151                     xmlSchemaCheckAttrUsePropsCorrect(pctxt,
21152                         WXS_ATTR_USE_CAST item);
21153                     FIXHFAILURE;
21154                 }
21155                 break;
21156             default:
21157                 break;
21158         }
21159     }
21160     if (pctxt->nberrors != 0)
21161         goto exit_error;
21162
21163     /*
21164     * Apply constraints for attribute group definitions.
21165     */
21166     for (i = 0; i < nbItems; i++) {
21167         item = items[i];
21168         switch (item->type) {
21169         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21170             if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
21171                 ( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
21172             {
21173                 xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
21174                 FIXHFAILURE;
21175             }
21176             break;
21177         default:
21178             break;
21179         }
21180     }
21181     if (pctxt->nberrors != 0)
21182         goto exit_error;
21183
21184     /*
21185     * Apply constraints for redefinitions.
21186     */
21187     if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
21188         xmlSchemaCheckSRCRedefineSecond(pctxt);
21189     if (pctxt->nberrors != 0)
21190         goto exit_error;
21191
21192     /*
21193     * Complex types are builded and checked.
21194     */
21195     for (i = 0; i < nbItems; i++) {
21196         item = con->pending->items[i];
21197         switch (item->type) {
21198             case XML_SCHEMA_TYPE_COMPLEX:
21199                 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21200                     xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
21201                     FIXHFAILURE;
21202                 }
21203                 break;
21204             default:
21205                 break;
21206         }
21207     }
21208     if (pctxt->nberrors != 0)
21209         goto exit_error;
21210
21211     /*
21212     * The list could have changed, since xmlSchemaFixupComplexType()
21213     * will create particles and model groups in some cases.
21214     */
21215     items = (xmlSchemaTreeItemPtr *) con->pending->items;
21216     nbItems = con->pending->nbItems;
21217
21218     /*
21219     * Apply some constraints for element declarations.
21220     */
21221     for (i = 0; i < nbItems; i++) {
21222         item = items[i];
21223         switch (item->type) {
21224             case XML_SCHEMA_TYPE_ELEMENT:
21225                 elemDecl = (xmlSchemaElementPtr) item;
21226
21227                 if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
21228                 {
21229                     xmlSchemaCheckElementDeclComponent(
21230                         (xmlSchemaElementPtr) elemDecl, pctxt);
21231                     FIXHFAILURE;
21232                 }
21233
21234 #ifdef WXS_ELEM_DECL_CONS_ENABLED
21235                 /*
21236                 * Schema Component Constraint: Element Declarations Consistent
21237                 * Apply this constraint to local types of element declarations.
21238                 */
21239                 if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
21240                     (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
21241                     (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
21242                 {
21243                     xmlSchemaCheckElementDeclConsistent(pctxt,
21244                         WXS_BASIC_CAST elemDecl,
21245                         WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
21246                         NULL, NULL, 0);
21247                 }
21248 #endif
21249                 break;
21250             default:
21251                 break;
21252         }
21253     }
21254     if (pctxt->nberrors != 0)
21255         goto exit_error;
21256
21257     /*
21258     * Finally we can build the automaton from the content model of
21259     * complex types.
21260     */
21261
21262     for (i = 0; i < nbItems; i++) {
21263         item = items[i];
21264         switch (item->type) {
21265             case XML_SCHEMA_TYPE_COMPLEX:
21266                 xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
21267                 /* FIXHFAILURE; */
21268                 break;
21269             default:
21270                 break;
21271         }
21272     }
21273     if (pctxt->nberrors != 0)
21274         goto exit_error;
21275     /*
21276     * URGENT TODO: cos-element-consistent
21277     */
21278     goto exit;
21279
21280 exit_error:
21281     ret = pctxt->err;
21282     goto exit;
21283
21284 exit_failure:
21285     ret = -1;
21286
21287 exit:
21288     /*
21289     * Reset the constructor. This is needed for XSI acquisition, since
21290     * those items will be processed over and over again for every XSI
21291     * if not cleared here.
21292     */
21293     con->bucket = oldbucket;
21294     con->pending->nbItems = 0;
21295     if (con->substGroups != NULL) {
21296         xmlHashFree(con->substGroups,
21297             (xmlHashDeallocator) xmlSchemaSubstGroupFree);
21298         con->substGroups = NULL;
21299     }
21300     if (con->redefs != NULL) {
21301         xmlSchemaRedefListFree(con->redefs);
21302         con->redefs = NULL;
21303     }
21304     return(ret);
21305 }
21306 /**
21307  * xmlSchemaParse:
21308  * @ctxt:  a schema validation context
21309  *
21310  * parse a schema definition resource and build an internal
21311  * XML Shema struture which can be used to validate instances.
21312  *
21313  * Returns the internal XML Schema structure built from the resource or
21314  *         NULL in case of error
21315  */
21316 xmlSchemaPtr
21317 xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21318 {
21319     xmlSchemaPtr mainSchema = NULL;
21320     xmlSchemaBucketPtr bucket = NULL;
21321     int res;
21322
21323     /*
21324     * This one is used if the schema to be parsed was specified via
21325     * the API; i.e. not automatically by the validated instance document.
21326     */
21327
21328     xmlSchemaInitTypes();
21329
21330     if (ctxt == NULL)
21331         return (NULL);
21332
21333     /* TODO: Init the context. Is this all we need?*/
21334     ctxt->nberrors = 0;
21335     ctxt->err = 0;
21336     ctxt->counter = 0;
21337
21338     /* Create the *main* schema. */
21339     mainSchema = xmlSchemaNewSchema(ctxt);
21340     if (mainSchema == NULL)
21341         goto exit_failure;
21342     /*
21343     * Create the schema constructor.
21344     */
21345     if (ctxt->constructor == NULL) {
21346         ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21347         if (ctxt->constructor == NULL)
21348             return(NULL);
21349         /* Take ownership of the constructor to be able to free it. */
21350         ctxt->ownsConstructor = 1;
21351     }
21352     ctxt->constructor->mainSchema = mainSchema;
21353     /*
21354     * Locate and add the schema document.
21355     */
21356     res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21357         ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21358         NULL, NULL, &bucket);
21359     if (res == -1)
21360         goto exit_failure;
21361     if (res != 0)
21362         goto exit;
21363
21364     if (bucket == NULL) {
21365         /* TODO: Error code, actually we failed to *locate* the schema. */
21366         if (ctxt->URL)
21367             xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21368                 NULL, NULL,
21369                 "Failed to locate the main schema resource at '%s'",
21370                 ctxt->URL, NULL);
21371         else
21372             xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21373                 NULL, NULL,
21374                 "Failed to locate the main schema resource",
21375                     NULL, NULL);
21376         goto exit;
21377     }
21378     /* Then do the parsing for good. */
21379     if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
21380         goto exit_failure;
21381     if (ctxt->nberrors != 0)
21382         goto exit;
21383
21384     mainSchema->doc = bucket->doc;
21385     mainSchema->preserve = ctxt->preserve;
21386
21387     ctxt->schema = mainSchema;
21388
21389     if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
21390         goto exit_failure;
21391
21392     /*
21393     * TODO: This is not nice, since we cannot distinguish from the
21394     * result if there was an internal error or not.
21395     */
21396 exit:
21397     if (ctxt->nberrors != 0) {
21398         if (mainSchema) {
21399             xmlSchemaFree(mainSchema);
21400             mainSchema = NULL;
21401         }
21402         if (ctxt->constructor) {
21403             xmlSchemaConstructionCtxtFree(ctxt->constructor);
21404             ctxt->constructor = NULL;
21405             ctxt->ownsConstructor = 0;
21406         }
21407     }
21408     ctxt->schema = NULL;
21409     return(mainSchema);
21410 exit_failure:
21411     /*
21412     * Quite verbose, but should catch internal errors, which were
21413     * not communitated.
21414     */
21415     if (mainSchema) {
21416         xmlSchemaFree(mainSchema);
21417         mainSchema = NULL;
21418     }
21419     if (ctxt->constructor) {
21420         xmlSchemaConstructionCtxtFree(ctxt->constructor);
21421         ctxt->constructor = NULL;
21422         ctxt->ownsConstructor = 0;
21423     }
21424     PERROR_INT2("xmlSchemaParse",
21425         "An internal error occurred");
21426     ctxt->schema = NULL;
21427     return(NULL);
21428 }
21429
21430 /**
21431  * xmlSchemaSetParserErrors:
21432  * @ctxt:  a schema validation context
21433  * @err:  the error callback
21434  * @warn:  the warning callback
21435  * @ctx:  contextual data for the callbacks
21436  *
21437  * Set the callback functions used to handle errors for a validation context
21438  */
21439 void
21440 xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21441                          xmlSchemaValidityErrorFunc err,
21442                          xmlSchemaValidityWarningFunc warn, void *ctx)
21443 {
21444     if (ctxt == NULL)
21445         return;
21446     ctxt->error = err;
21447     ctxt->warning = warn;
21448     ctxt->errCtxt = ctx;
21449     if (ctxt->vctxt != NULL)
21450         xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21451 }
21452
21453 /**
21454  * xmlSchemaSetParserStructuredErrors:
21455  * @ctxt:  a schema parser context
21456  * @serror:  the structured error function
21457  * @ctx: the functions context
21458  *
21459  * Set the structured error callback
21460  */
21461 void
21462 xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21463                                    xmlStructuredErrorFunc serror,
21464                                    void *ctx)
21465 {
21466     if (ctxt == NULL)
21467         return;
21468     ctxt->serror = serror;
21469     ctxt->errCtxt = ctx;
21470     if (ctxt->vctxt != NULL)
21471         xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
21472 }
21473
21474 /**
21475  * xmlSchemaGetParserErrors:
21476  * @ctxt:  a XMl-Schema parser context
21477  * @err: the error callback result
21478  * @warn: the warning callback result
21479  * @ctx: contextual data for the callbacks result
21480  *
21481  * Get the callback information used to handle errors for a parser context
21482  *
21483  * Returns -1 in case of failure, 0 otherwise
21484  */
21485 int
21486 xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21487                          xmlSchemaValidityErrorFunc * err,
21488                          xmlSchemaValidityWarningFunc * warn, void **ctx)
21489 {
21490         if (ctxt == NULL)
21491                 return(-1);
21492         if (err != NULL)
21493                 *err = ctxt->error;
21494         if (warn != NULL)
21495                 *warn = ctxt->warning;
21496         if (ctx != NULL)
21497                 *ctx = ctxt->errCtxt;
21498         return(0);
21499 }
21500
21501 /**
21502  * xmlSchemaFacetTypeToString:
21503  * @type:  the facet type
21504  *
21505  * Convert the xmlSchemaTypeType to a char string.
21506  *
21507  * Returns the char string representation of the facet type if the
21508  *     type is a facet and an "Internal Error" string otherwise.
21509  */
21510 static const xmlChar *
21511 xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21512 {
21513     switch (type) {
21514         case XML_SCHEMA_FACET_PATTERN:
21515             return (BAD_CAST "pattern");
21516         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
21517             return (BAD_CAST "maxExclusive");
21518         case XML_SCHEMA_FACET_MAXINCLUSIVE:
21519             return (BAD_CAST "maxInclusive");
21520         case XML_SCHEMA_FACET_MINEXCLUSIVE:
21521             return (BAD_CAST "minExclusive");
21522         case XML_SCHEMA_FACET_MININCLUSIVE:
21523             return (BAD_CAST "minInclusive");
21524         case XML_SCHEMA_FACET_WHITESPACE:
21525             return (BAD_CAST "whiteSpace");
21526         case XML_SCHEMA_FACET_ENUMERATION:
21527             return (BAD_CAST "enumeration");
21528         case XML_SCHEMA_FACET_LENGTH:
21529             return (BAD_CAST "length");
21530         case XML_SCHEMA_FACET_MAXLENGTH:
21531             return (BAD_CAST "maxLength");
21532         case XML_SCHEMA_FACET_MINLENGTH:
21533             return (BAD_CAST "minLength");
21534         case XML_SCHEMA_FACET_TOTALDIGITS:
21535             return (BAD_CAST "totalDigits");
21536         case XML_SCHEMA_FACET_FRACTIONDIGITS:
21537             return (BAD_CAST "fractionDigits");
21538         default:
21539             break;
21540     }
21541     return (BAD_CAST "Internal Error");
21542 }
21543
21544 static xmlSchemaWhitespaceValueType
21545 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21546 {
21547     /*
21548     * The normalization type can be changed only for types which are derived
21549     * from xsd:string.
21550     */
21551     if (type->type == XML_SCHEMA_TYPE_BASIC) {
21552         /*
21553         * Note that we assume a whitespace of preserve for anySimpleType.
21554         */
21555         if ((type->builtInType == XML_SCHEMAS_STRING) ||
21556             (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21557             return(XML_SCHEMA_WHITESPACE_PRESERVE);
21558         else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
21559             return(XML_SCHEMA_WHITESPACE_REPLACE);
21560         else {
21561             /*
21562             * For all `atomic` datatypes other than string (and types `derived`
21563             * by `restriction` from it) the value of whiteSpace is fixed to
21564             * collapse
21565             * Note that this includes built-in list datatypes.
21566             */
21567             return(XML_SCHEMA_WHITESPACE_COLLAPSE);
21568         }
21569     } else if (WXS_IS_LIST(type)) {
21570         /*
21571         * For list types the facet "whiteSpace" is fixed to "collapse".
21572         */
21573         return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21574     } else if (WXS_IS_UNION(type)) {
21575         return (XML_SCHEMA_WHITESPACE_UNKNOWN);
21576     } else if (WXS_IS_ATOMIC(type)) {
21577         if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21578             return (XML_SCHEMA_WHITESPACE_PRESERVE);
21579         else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21580             return (XML_SCHEMA_WHITESPACE_REPLACE);
21581         else
21582             return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21583     }
21584     return (-1);
21585 }
21586
21587 /************************************************************************
21588  *                                                                      *
21589  *                      Simple type validation                          *
21590  *                                                                      *
21591  ************************************************************************/
21592
21593
21594 /************************************************************************
21595  *                                                                      *
21596  *                      DOM Validation code                             *
21597  *                                                                      *
21598  ************************************************************************/
21599
21600 /**
21601  * xmlSchemaAssembleByLocation:
21602  * @pctxt:  a schema parser context
21603  * @vctxt:  a schema validation context
21604  * @schema: the existing schema
21605  * @node: the node that fired the assembling
21606  * @nsName: the namespace name of the new schema
21607  * @location: the location of the schema
21608  *
21609  * Expands an existing schema by an additional schema.
21610  *
21611  * Returns 0 if the new schema is correct, a positive error code
21612  * number otherwise and -1 in case of an internal or API error.
21613  */
21614 static int
21615 xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
21616                             xmlSchemaPtr schema,
21617                             xmlNodePtr node,
21618                             const xmlChar *nsName,
21619                             const xmlChar *location)
21620 {
21621     int ret = 0;
21622     xmlSchemaParserCtxtPtr pctxt;
21623     xmlSchemaBucketPtr bucket = NULL;
21624
21625     if ((vctxt == NULL) || (schema == NULL))
21626         return (-1);
21627
21628     if (vctxt->pctxt == NULL) {
21629         VERROR_INT("xmlSchemaAssembleByLocation",
21630             "no parser context available");
21631         return(-1);
21632     }
21633     pctxt = vctxt->pctxt;
21634     if (pctxt->constructor == NULL) {
21635         PERROR_INT("xmlSchemaAssembleByLocation",
21636             "no constructor");
21637         return(-1);
21638     }
21639     /*
21640     * Acquire the schema document.
21641     */
21642     location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21643         location, node);
21644     /*
21645     * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21646     * the process will automatically change this to
21647     * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21648     */
21649     ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21650         location, NULL, NULL, 0, node, NULL, nsName,
21651         &bucket);
21652     if (ret != 0)
21653         return(ret);
21654     if (bucket == NULL) {
21655         /*
21656         * Generate a warning that the document could not be located.
21657         */
21658         xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21659             node, NULL,
21660             "The document at location '%s' could not be acquired",
21661             location, NULL, NULL);
21662         return(ret);
21663     }
21664     /*
21665     * The first located schema will be handled as if all other
21666     * schemas imported by XSI were imported by this first schema.
21667     */
21668     if ((bucket != NULL) &&
21669         (WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21670         WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21671     /*
21672     * TODO: Is this handled like an import? I.e. is it not an error
21673     * if the schema cannot be located?
21674     */
21675     if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21676         return(0);
21677     /*
21678     * We will reuse the parser context for every schema imported
21679     * directly via XSI. So reset the context.
21680     */
21681     pctxt->nberrors = 0;
21682     pctxt->err = 0;
21683     pctxt->doc = bucket->doc;
21684
21685     ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21686     if (ret == -1) {
21687         pctxt->doc = NULL;
21688         goto exit_failure;
21689     }
21690     /* Paranoid error channelling. */
21691     if ((ret == 0) && (pctxt->nberrors != 0))
21692         ret = pctxt->err;
21693     if (pctxt->nberrors == 0) {
21694         /*
21695         * Only bother to fixup pending components, if there was
21696         * no error yet.
21697         * For every XSI acquired schema (and its sub-schemata) we will
21698         * fixup the components.
21699         */
21700         xmlSchemaFixupComponents(pctxt, bucket);
21701         ret = pctxt->err;
21702         /*
21703         * Not nice, but we need somehow to channel the schema parser
21704         * error to the validation context.
21705         */
21706         if ((ret != 0) && (vctxt->err == 0))
21707             vctxt->err = ret;
21708         vctxt->nberrors += pctxt->nberrors;
21709     } else {
21710         /* Add to validation error sum. */
21711         vctxt->nberrors += pctxt->nberrors;
21712     }
21713     pctxt->doc = NULL;
21714     return(ret);
21715 exit_failure:
21716     pctxt->doc = NULL;
21717     return (-1);
21718 }
21719
21720 static xmlSchemaAttrInfoPtr
21721 xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21722                          int metaType)
21723 {
21724     if (vctxt->nbAttrInfos == 0)
21725         return (NULL);
21726     {
21727         int i;
21728         xmlSchemaAttrInfoPtr iattr;
21729
21730         for (i = 0; i < vctxt->nbAttrInfos; i++) {
21731             iattr = vctxt->attrInfos[i];
21732             if (iattr->metaType == metaType)
21733                 return (iattr);
21734         }
21735
21736     }
21737     return (NULL);
21738 }
21739
21740 /**
21741  * xmlSchemaAssembleByXSI:
21742  * @vctxt:  a schema validation context
21743  *
21744  * Expands an existing schema by an additional schema using
21745  * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21746  * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21747  * must be set to 1.
21748  *
21749  * Returns 0 if the new schema is correct, a positive error code
21750  * number otherwise and -1 in case of an internal or API error.
21751  */
21752 static int
21753 xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
21754 {
21755     const xmlChar *cur, *end;
21756     const xmlChar *nsname = NULL, *location;
21757     int count = 0;
21758     int ret = 0;
21759     xmlSchemaAttrInfoPtr iattr;
21760
21761     /*
21762     * Parse the value; we will assume an even number of values
21763     * to be given (this is how Xerces and XSV work).
21764     *
21765     * URGENT TODO: !! This needs to work for both
21766     * @noNamespaceSchemaLocation AND @schemaLocation on the same
21767     * element !!
21768     */
21769     iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21770         XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21771     if (iattr == NULL)
21772         iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21773         XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21774     if (iattr == NULL)
21775         return (0);
21776     cur = iattr->value;
21777     do {
21778         /*
21779         * TODO: Move the string parsing mechanism away from here.
21780         */
21781         if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
21782             /*
21783             * Get the namespace name.
21784             */
21785             while (IS_BLANK_CH(*cur))
21786                 cur++;
21787             end = cur;
21788             while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21789                 end++;
21790             if (end == cur)
21791                 break;
21792             count++; /* TODO: Don't use the schema's dict. */
21793             nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21794             cur = end;
21795         }
21796         /*
21797         * Get the URI.
21798         */
21799         while (IS_BLANK_CH(*cur))
21800             cur++;
21801         end = cur;
21802         while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21803             end++;
21804         if (end == cur) {
21805             if (iattr->metaType ==
21806                 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21807             {
21808                 /*
21809                 * If using @schemaLocation then tuples are expected.
21810                 * I.e. the namespace name *and* the document's URI.
21811                 */
21812                 xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21813                     iattr->node, NULL,
21814                     "The value must consist of tuples: the target namespace "
21815                     "name and the document's URI", NULL, NULL, NULL);
21816             }
21817             break;
21818         }
21819         count++; /* TODO: Don't use the schema's dict. */
21820         location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21821         cur = end;
21822         ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21823             iattr->node, nsname, location);
21824         if (ret == -1) {
21825             VERROR_INT("xmlSchemaAssembleByXSI",
21826                 "assembling schemata");
21827             return (-1);
21828         }
21829     } while (*cur != 0);
21830     return (ret);
21831 }
21832
21833 static const xmlChar *
21834 xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21835                          const xmlChar *prefix)
21836 {
21837     if (vctxt->sax != NULL) {
21838         int i, j;
21839         xmlSchemaNodeInfoPtr inode;
21840
21841         for (i = vctxt->depth; i >= 0; i--) {
21842             if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21843                 inode = vctxt->elemInfos[i];
21844                 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21845                     if (((prefix == NULL) &&
21846                             (inode->nsBindings[j] == NULL)) ||
21847                         ((prefix != NULL) && xmlStrEqual(prefix,
21848                             inode->nsBindings[j]))) {
21849
21850                         /*
21851                         * Note that the namespace bindings are already
21852                         * in a string dict.
21853                         */
21854                         return (inode->nsBindings[j+1]);
21855                     }
21856                 }
21857             }
21858         }
21859         return (NULL);
21860 #ifdef LIBXML_READER_ENABLED
21861     } else if (vctxt->reader != NULL) {
21862         xmlChar *nsName;
21863
21864         nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21865         if (nsName != NULL) {
21866             const xmlChar *ret;
21867
21868             ret = xmlDictLookup(vctxt->dict, nsName, -1);
21869             xmlFree(nsName);
21870             return (ret);
21871         } else
21872             return (NULL);
21873 #endif
21874     } else {
21875         xmlNsPtr ns;
21876
21877         if ((vctxt->inode->node == NULL) ||
21878             (vctxt->inode->node->doc == NULL)) {
21879             VERROR_INT("xmlSchemaLookupNamespace",
21880                 "no node or node's doc avaliable");
21881             return (NULL);
21882         }
21883         ns = xmlSearchNs(vctxt->inode->node->doc,
21884             vctxt->inode->node, prefix);
21885         if (ns != NULL)
21886             return (ns->href);
21887         return (NULL);
21888     }
21889 }
21890
21891 /*
21892 * This one works on the schema of the validation context.
21893 */
21894 static int
21895 xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21896                           xmlSchemaPtr schema,
21897                           xmlNodePtr node,
21898                           const xmlChar *value,
21899                           xmlSchemaValPtr *val,
21900                           int valNeeded)
21901 {
21902     int ret;
21903
21904     if (vctxt && (vctxt->schema == NULL)) {
21905         VERROR_INT("xmlSchemaValidateNotation",
21906             "a schema is needed on the validation context");
21907         return (-1);
21908     }
21909     ret = xmlValidateQName(value, 1);
21910     if (ret != 0)
21911         return (ret);
21912     {
21913         xmlChar *localName = NULL;
21914         xmlChar *prefix = NULL;
21915
21916         localName = xmlSplitQName2(value, &prefix);
21917         if (prefix != NULL) {
21918             const xmlChar *nsName = NULL;
21919
21920             if (vctxt != NULL)
21921                 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21922             else if (node != NULL) {
21923                 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21924                 if (ns != NULL)
21925                     nsName = ns->href;
21926             } else {
21927                 xmlFree(prefix);
21928                 xmlFree(localName);
21929                 return (1);
21930             }
21931             if (nsName == NULL) {
21932                 xmlFree(prefix);
21933                 xmlFree(localName);
21934                 return (1);
21935             }
21936             if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
21937                 if ((valNeeded) && (val != NULL)) {
21938                     (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName),
21939                                                        xmlStrdup(nsName));
21940                     if (*val == NULL)
21941                         ret = -1;
21942                 }
21943             } else
21944                 ret = 1;
21945             xmlFree(prefix);
21946             xmlFree(localName);
21947         } else {
21948             if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
21949                 if (valNeeded && (val != NULL)) {
21950                     (*val) = xmlSchemaNewNOTATIONValue(
21951                         BAD_CAST xmlStrdup(value), NULL);
21952                     if (*val == NULL)
21953                         ret = -1;
21954                 }
21955             } else
21956                 return (1);
21957         }
21958     }
21959     return (ret);
21960 }
21961
21962 static int
21963 xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21964                        const xmlChar* lname,
21965                        const xmlChar* nsname)
21966 {
21967     int i;
21968
21969     lname = xmlDictLookup(vctxt->dict, lname, -1);
21970     if (lname == NULL)
21971         return(-1);
21972     if (nsname != NULL) {
21973         nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21974         if (nsname == NULL)
21975             return(-1);
21976     }
21977     for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21978         if ((vctxt->nodeQNames->items [i] == lname) &&
21979             (vctxt->nodeQNames->items[i +1] == nsname))
21980             /* Already there */
21981             return(i);
21982     }
21983     /* Add new entry. */
21984     i = vctxt->nodeQNames->nbItems;
21985     xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21986     xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21987     return(i);
21988 }
21989
21990 /************************************************************************
21991  *                                                                      *
21992  *  Validation of identity-constraints (IDC)                            *
21993  *                                                                      *
21994  ************************************************************************/
21995
21996 /**
21997  * xmlSchemaAugmentIDC:
21998  * @idcDef: the IDC definition
21999  *
22000  * Creates an augmented IDC definition item.
22001  *
22002  * Returns the item, or NULL on internal errors.
22003  */
22004 static void
22005 xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
22006                     xmlSchemaValidCtxtPtr vctxt)
22007 {
22008     xmlSchemaIDCAugPtr aidc;
22009
22010     aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
22011     if (aidc == NULL) {
22012         xmlSchemaVErrMemory(vctxt,
22013             "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
22014             NULL);
22015         return;
22016     }
22017     aidc->keyrefDepth = -1;
22018     aidc->def = idcDef;
22019     aidc->next = NULL;
22020     if (vctxt->aidcs == NULL)
22021         vctxt->aidcs = aidc;
22022     else {
22023         aidc->next = vctxt->aidcs;
22024         vctxt->aidcs = aidc;
22025     }
22026     /*
22027     * Save if we have keyrefs at all.
22028     */
22029     if ((vctxt->hasKeyrefs == 0) &&
22030         (idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
22031         vctxt->hasKeyrefs = 1;
22032 }
22033
22034 /**
22035  * xmlSchemaAugmentImportedIDC:
22036  * @imported: the imported schema
22037  *
22038  * Creates an augmented IDC definition for the imported schema.
22039  */
22040 static void
22041 xmlSchemaAugmentImportedIDC(xmlSchemaImportPtr imported, xmlSchemaValidCtxtPtr vctxt, xmlChar *name ATTRIBUTE_UNUSED) {
22042     if (imported->schema->idcDef != NULL) {
22043             xmlHashScan(imported->schema->idcDef ,
22044             (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
22045     }
22046 }
22047
22048 /**
22049  * xmlSchemaIDCNewBinding:
22050  * @idcDef: the IDC definition of this binding
22051  *
22052  * Creates a new IDC binding.
22053  *
22054  * Returns the new IDC binding, NULL on internal errors.
22055  */
22056 static xmlSchemaPSVIIDCBindingPtr
22057 xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
22058 {
22059     xmlSchemaPSVIIDCBindingPtr ret;
22060
22061     ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
22062             sizeof(xmlSchemaPSVIIDCBinding));
22063     if (ret == NULL) {
22064         xmlSchemaVErrMemory(NULL,
22065             "allocating a PSVI IDC binding item", NULL);
22066         return (NULL);
22067     }
22068     memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
22069     ret->definition = idcDef;
22070     return (ret);
22071 }
22072
22073 /**
22074  * xmlSchemaIDCStoreNodeTableItem:
22075  * @vctxt: the WXS validation context
22076  * @item: the IDC node table item
22077  *
22078  * The validation context is used to store IDC node table items.
22079  * They are stored to avoid copying them if IDC node-tables are merged
22080  * with corresponding parent IDC node-tables (bubbling).
22081  *
22082  * Returns 0 if succeeded, -1 on internal errors.
22083  */
22084 static int
22085 xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
22086                                xmlSchemaPSVIIDCNodePtr item)
22087 {
22088     /*
22089     * Add to gobal list.
22090     */
22091     if (vctxt->idcNodes == NULL) {
22092         vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22093             xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
22094         if (vctxt->idcNodes == NULL) {
22095             xmlSchemaVErrMemory(vctxt,
22096                 "allocating the IDC node table item list", NULL);
22097             return (-1);
22098         }
22099         vctxt->sizeIdcNodes = 20;
22100     } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
22101         vctxt->sizeIdcNodes *= 2;
22102         vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22103             xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
22104             sizeof(xmlSchemaPSVIIDCNodePtr));
22105         if (vctxt->idcNodes == NULL) {
22106             xmlSchemaVErrMemory(vctxt,
22107                 "re-allocating the IDC node table item list", NULL);
22108             return (-1);
22109         }
22110     }
22111     vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
22112
22113     return (0);
22114 }
22115
22116 /**
22117  * xmlSchemaIDCStoreKey:
22118  * @vctxt: the WXS validation context
22119  * @item: the IDC key
22120  *
22121  * The validation context is used to store an IDC key.
22122  *
22123  * Returns 0 if succeeded, -1 on internal errors.
22124  */
22125 static int
22126 xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
22127                      xmlSchemaPSVIIDCKeyPtr key)
22128 {
22129     /*
22130     * Add to gobal list.
22131     */
22132     if (vctxt->idcKeys == NULL) {
22133         vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22134             xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
22135         if (vctxt->idcKeys == NULL) {
22136             xmlSchemaVErrMemory(vctxt,
22137                 "allocating the IDC key storage list", NULL);
22138             return (-1);
22139         }
22140         vctxt->sizeIdcKeys = 40;
22141     } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
22142         vctxt->sizeIdcKeys *= 2;
22143         vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22144             xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
22145             sizeof(xmlSchemaPSVIIDCKeyPtr));
22146         if (vctxt->idcKeys == NULL) {
22147             xmlSchemaVErrMemory(vctxt,
22148                 "re-allocating the IDC key storage list", NULL);
22149             return (-1);
22150         }
22151     }
22152     vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
22153
22154     return (0);
22155 }
22156
22157 /**
22158  * xmlSchemaIDCAppendNodeTableItem:
22159  * @bind: the IDC binding
22160  * @ntItem: the node-table item
22161  *
22162  * Appends the IDC node-table item to the binding.
22163  *
22164  * Returns 0 on success and -1 on internal errors.
22165  */
22166 static int
22167 xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
22168                                 xmlSchemaPSVIIDCNodePtr ntItem)
22169 {
22170     if (bind->nodeTable == NULL) {
22171         bind->sizeNodes = 10;
22172         bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22173             xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
22174         if (bind->nodeTable == NULL) {
22175             xmlSchemaVErrMemory(NULL,
22176                 "allocating an array of IDC node-table items", NULL);
22177             return(-1);
22178         }
22179     } else if (bind->sizeNodes <= bind->nbNodes) {
22180         bind->sizeNodes *= 2;
22181         bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22182             xmlRealloc(bind->nodeTable, bind->sizeNodes *
22183                 sizeof(xmlSchemaPSVIIDCNodePtr));
22184         if (bind->nodeTable == NULL) {
22185             xmlSchemaVErrMemory(NULL,
22186                 "re-allocating an array of IDC node-table items", NULL);
22187             return(-1);
22188         }
22189     }
22190     bind->nodeTable[bind->nbNodes++] = ntItem;
22191     return(0);
22192 }
22193
22194 /**
22195  * xmlSchemaIDCAcquireBinding:
22196  * @vctxt: the WXS validation context
22197  * @matcher: the IDC matcher
22198  *
22199  * Looks up an PSVI IDC binding, for the IDC definition and
22200  * of the given matcher. If none found, a new one is created
22201  * and added to the IDC table.
22202  *
22203  * Returns an IDC binding or NULL on internal errors.
22204  */
22205 static xmlSchemaPSVIIDCBindingPtr
22206 xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
22207                           xmlSchemaIDCMatcherPtr matcher)
22208 {
22209     xmlSchemaNodeInfoPtr ielem;
22210
22211     ielem = vctxt->elemInfos[matcher->depth];
22212
22213     if (ielem->idcTable == NULL) {
22214         ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
22215         if (ielem->idcTable == NULL)
22216             return (NULL);
22217         return(ielem->idcTable);
22218     } else {
22219         xmlSchemaPSVIIDCBindingPtr bind = NULL;
22220
22221         bind = ielem->idcTable;
22222         do {
22223             if (bind->definition == matcher->aidc->def)
22224                 return(bind);
22225             if (bind->next == NULL) {
22226                 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
22227                 if (bind->next == NULL)
22228                     return (NULL);
22229                 return(bind->next);
22230             }
22231             bind = bind->next;
22232         } while (bind != NULL);
22233     }
22234     return (NULL);
22235 }
22236
22237 static xmlSchemaItemListPtr
22238 xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22239                              xmlSchemaIDCMatcherPtr matcher)
22240 {
22241     if (matcher->targets == NULL)
22242         matcher->targets = xmlSchemaItemListCreate();
22243     return(matcher->targets);
22244 }
22245
22246 /**
22247  * xmlSchemaIDCFreeKey:
22248  * @key: the IDC key
22249  *
22250  * Frees an IDC key together with its compiled value.
22251  */
22252 static void
22253 xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
22254 {
22255     if (key->val != NULL)
22256         xmlSchemaFreeValue(key->val);
22257     xmlFree(key);
22258 }
22259
22260 /**
22261  * xmlSchemaIDCFreeBinding:
22262  *
22263  * Frees an IDC binding. Note that the node table-items
22264  * are not freed.
22265  */
22266 static void
22267 xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
22268 {
22269     if (bind->nodeTable != NULL)
22270         xmlFree(bind->nodeTable);
22271     if (bind->dupls != NULL)
22272         xmlSchemaItemListFree(bind->dupls);
22273     xmlFree(bind);
22274 }
22275
22276 /**
22277  * xmlSchemaIDCFreeIDCTable:
22278  * @bind: the first IDC binding in the list
22279  *
22280  * Frees an IDC table, i.e. all the IDC bindings in the list.
22281  */
22282 static void
22283 xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
22284 {
22285     xmlSchemaPSVIIDCBindingPtr prev;
22286
22287     while (bind != NULL) {
22288         prev = bind;
22289         bind = bind->next;
22290         xmlSchemaIDCFreeBinding(prev);
22291     }
22292 }
22293
22294 /**
22295  * xmlSchemaIDCFreeMatcherList:
22296  * @matcher: the first IDC matcher in the list
22297  *
22298  * Frees a list of IDC matchers.
22299  */
22300 static void
22301 xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22302 {
22303     xmlSchemaIDCMatcherPtr next;
22304
22305     while (matcher != NULL) {
22306         next = matcher->next;
22307         if (matcher->keySeqs != NULL) {
22308             int i;
22309             for (i = 0; i < matcher->sizeKeySeqs; i++)
22310                 if (matcher->keySeqs[i] != NULL)
22311                     xmlFree(matcher->keySeqs[i]);
22312             xmlFree(matcher->keySeqs);
22313         }
22314         if (matcher->targets != NULL) {
22315             if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22316                 int i;
22317                 xmlSchemaPSVIIDCNodePtr idcNode;
22318                 /*
22319                 * Node-table items for keyrefs are not stored globally
22320                 * to the validation context, since they are not bubbled.
22321                 * We need to free them here.
22322                 */
22323                 for (i = 0; i < matcher->targets->nbItems; i++) {
22324                     idcNode =
22325                         (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22326                     xmlFree(idcNode->keys);
22327                     xmlFree(idcNode);
22328                 }
22329             }
22330             xmlSchemaItemListFree(matcher->targets);
22331         }
22332         xmlFree(matcher);
22333         matcher = next;
22334     }
22335 }
22336
22337 /**
22338  * xmlSchemaIDCReleaseMatcherList:
22339  * @vctxt: the WXS validation context
22340  * @matcher: the first IDC matcher in the list
22341  *
22342  * Caches a list of IDC matchers for reuse.
22343  */
22344 static void
22345 xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
22346                                xmlSchemaIDCMatcherPtr matcher)
22347 {
22348     xmlSchemaIDCMatcherPtr next;
22349
22350     while (matcher != NULL) {
22351         next = matcher->next;
22352         if (matcher->keySeqs != NULL) {
22353             int i;
22354             /*
22355             * Don't free the array, but only the content.
22356             */
22357             for (i = 0; i < matcher->sizeKeySeqs; i++)
22358                 if (matcher->keySeqs[i] != NULL) {
22359                     xmlFree(matcher->keySeqs[i]);
22360                     matcher->keySeqs[i] = NULL;
22361                 }
22362         }
22363         if (matcher->targets) {
22364             if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22365                 int i;
22366                 xmlSchemaPSVIIDCNodePtr idcNode;
22367                 /*
22368                 * Node-table items for keyrefs are not stored globally
22369                 * to the validation context, since they are not bubbled.
22370                 * We need to free them here.
22371                 */
22372                 for (i = 0; i < matcher->targets->nbItems; i++) {
22373                     idcNode =
22374                         (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22375                     xmlFree(idcNode->keys);
22376                     xmlFree(idcNode);
22377                 }
22378             }
22379             xmlSchemaItemListFree(matcher->targets);
22380             matcher->targets = NULL;
22381         }
22382         matcher->next = NULL;
22383         /*
22384         * Cache the matcher.
22385         */
22386         if (vctxt->idcMatcherCache != NULL)
22387             matcher->nextCached = vctxt->idcMatcherCache;
22388         vctxt->idcMatcherCache = matcher;
22389
22390         matcher = next;
22391     }
22392 }
22393
22394 /**
22395  * xmlSchemaIDCAddStateObject:
22396  * @vctxt: the WXS validation context
22397  * @matcher: the IDC matcher
22398  * @sel: the XPath information
22399  * @parent: the parent "selector" state object if any
22400  * @type: "selector" or "field"
22401  *
22402  * Creates/reuses and activates state objects for the given
22403  * XPath information; if the XPath expression consists of unions,
22404  * multiple state objects are created for every unioned expression.
22405  *
22406  * Returns 0 on success and -1 on internal errors.
22407  */
22408 static int
22409 xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22410                         xmlSchemaIDCMatcherPtr matcher,
22411                         xmlSchemaIDCSelectPtr sel,
22412                         int type)
22413 {
22414     xmlSchemaIDCStateObjPtr sto;
22415
22416     /*
22417     * Reuse the state objects from the pool.
22418     */
22419     if (vctxt->xpathStatePool != NULL) {
22420         sto = vctxt->xpathStatePool;
22421         vctxt->xpathStatePool = sto->next;
22422         sto->next = NULL;
22423     } else {
22424         /*
22425         * Create a new state object.
22426         */
22427         sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22428         if (sto == NULL) {
22429             xmlSchemaVErrMemory(NULL,
22430                 "allocating an IDC state object", NULL);
22431             return (-1);
22432         }
22433         memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22434     }
22435     /*
22436     * Add to global list.
22437     */
22438     if (vctxt->xpathStates != NULL)
22439         sto->next = vctxt->xpathStates;
22440     vctxt->xpathStates = sto;
22441
22442     /*
22443     * Free the old xpath validation context.
22444     */
22445     if (sto->xpathCtxt != NULL)
22446         xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22447
22448     /*
22449     * Create a new XPath (pattern) validation context.
22450     */
22451     sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22452         (xmlPatternPtr) sel->xpathComp);
22453     if (sto->xpathCtxt == NULL) {
22454         VERROR_INT("xmlSchemaIDCAddStateObject",
22455             "failed to create an XPath validation context");
22456         return (-1);
22457     }
22458     sto->type = type;
22459     sto->depth = vctxt->depth;
22460     sto->matcher = matcher;
22461     sto->sel = sel;
22462     sto->nbHistory = 0;
22463
22464 #ifdef DEBUG_IDC
22465     xmlGenericError(xmlGenericErrorContext, "IDC:   STO push '%s'\n",
22466         sto->sel->xpath);
22467 #endif
22468     return (0);
22469 }
22470
22471 /**
22472  * xmlSchemaXPathEvaluate:
22473  * @vctxt: the WXS validation context
22474  * @nodeType: the nodeType of the current node
22475  *
22476  * Evaluates all active XPath state objects.
22477  *
22478  * Returns the number of IC "field" state objects which resolved to
22479  * this node, 0 if none resolved and -1 on internal errors.
22480  */
22481 static int
22482 xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
22483                        xmlElementType nodeType)
22484 {
22485     xmlSchemaIDCStateObjPtr sto, head = NULL, first;
22486     int res, resolved = 0, depth = vctxt->depth;
22487
22488     if (vctxt->xpathStates == NULL)
22489         return (0);
22490
22491     if (nodeType == XML_ATTRIBUTE_NODE)
22492         depth++;
22493 #ifdef DEBUG_IDC
22494     {
22495         xmlChar *str = NULL;
22496         xmlGenericError(xmlGenericErrorContext,
22497             "IDC: EVAL on %s, depth %d, type %d\n",
22498             xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22499                 vctxt->inode->localName), depth, nodeType);
22500         FREE_AND_NULL(str)
22501     }
22502 #endif
22503     /*
22504     * Process all active XPath state objects.
22505     */
22506     first = vctxt->xpathStates;
22507     sto = first;
22508     while (sto != head) {
22509 #ifdef DEBUG_IDC
22510         if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
22511             xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] selector '%s'\n",
22512                 sto->matcher->aidc->def->name, sto->sel->xpath);
22513         else
22514             xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] field '%s'\n",
22515                 sto->matcher->aidc->def->name, sto->sel->xpath);
22516 #endif
22517         if (nodeType == XML_ELEMENT_NODE)
22518             res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
22519                 vctxt->inode->localName, vctxt->inode->nsName);
22520         else
22521             res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
22522                 vctxt->inode->localName, vctxt->inode->nsName);
22523
22524         if (res == -1) {
22525             VERROR_INT("xmlSchemaXPathEvaluate",
22526                 "calling xmlStreamPush()");
22527             return (-1);
22528         }
22529         if (res == 0)
22530             goto next_sto;
22531         /*
22532         * Full match.
22533         */
22534 #ifdef DEBUG_IDC
22535         xmlGenericError(xmlGenericErrorContext, "IDC:     "
22536             "MATCH\n");
22537 #endif
22538         /*
22539         * Register a match in the state object history.
22540         */
22541         if (sto->history == NULL) {
22542             sto->history = (int *) xmlMalloc(5 * sizeof(int));
22543             if (sto->history == NULL) {
22544                 xmlSchemaVErrMemory(NULL,
22545                     "allocating the state object history", NULL);
22546                 return(-1);
22547             }
22548             sto->sizeHistory = 5;
22549         } else if (sto->sizeHistory <= sto->nbHistory) {
22550             sto->sizeHistory *= 2;
22551             sto->history = (int *) xmlRealloc(sto->history,
22552                 sto->sizeHistory * sizeof(int));
22553             if (sto->history == NULL) {
22554                 xmlSchemaVErrMemory(NULL,
22555                     "re-allocating the state object history", NULL);
22556                 return(-1);
22557             }
22558         }
22559         sto->history[sto->nbHistory++] = depth;
22560
22561 #ifdef DEBUG_IDC
22562         xmlGenericError(xmlGenericErrorContext, "IDC:       push match '%d'\n",
22563             vctxt->depth);
22564 #endif
22565
22566         if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22567             xmlSchemaIDCSelectPtr sel;
22568             /*
22569             * Activate state objects for the IDC fields of
22570             * the IDC selector.
22571             */
22572 #ifdef DEBUG_IDC
22573             xmlGenericError(xmlGenericErrorContext, "IDC:     "
22574                 "activating field states\n");
22575 #endif
22576             sel = sto->matcher->aidc->def->fields;
22577             while (sel != NULL) {
22578                 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22579                     sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22580                     return (-1);
22581                 sel = sel->next;
22582             }
22583         } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22584             /*
22585             * An IDC key node was found by the IDC field.
22586             */
22587 #ifdef DEBUG_IDC
22588             xmlGenericError(xmlGenericErrorContext,
22589                 "IDC:     key found\n");
22590 #endif
22591             /*
22592             * Notify that the character value of this node is
22593             * needed.
22594             */
22595             if (resolved == 0) {
22596                 if ((vctxt->inode->flags &
22597                     XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22598                 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22599             }
22600             resolved++;
22601         }
22602 next_sto:
22603         if (sto->next == NULL) {
22604             /*
22605             * Evaluate field state objects created on this node as well.
22606             */
22607             head = first;
22608             sto = vctxt->xpathStates;
22609         } else
22610             sto = sto->next;
22611     }
22612     return (resolved);
22613 }
22614
22615 static const xmlChar *
22616 xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
22617                               xmlChar **buf,
22618                               xmlSchemaPSVIIDCKeyPtr *seq,
22619                               int count)
22620 {
22621     int i, res;
22622     xmlChar *value = NULL;
22623
22624     *buf = xmlStrdup(BAD_CAST "[");
22625     for (i = 0; i < count; i++) {
22626         *buf = xmlStrcat(*buf, BAD_CAST "'");
22627         res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22628             xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22629             &value);
22630         if (res == 0)
22631             *buf = xmlStrcat(*buf, BAD_CAST value);
22632         else {
22633             VERROR_INT("xmlSchemaFormatIDCKeySequence",
22634                 "failed to compute a canonical value");
22635             *buf = xmlStrcat(*buf, BAD_CAST "???");
22636         }
22637         if (i < count -1)
22638             *buf = xmlStrcat(*buf, BAD_CAST "', ");
22639         else
22640             *buf = xmlStrcat(*buf, BAD_CAST "'");
22641         if (value != NULL) {
22642             xmlFree(value);
22643             value = NULL;
22644         }
22645     }
22646     *buf = xmlStrcat(*buf, BAD_CAST "]");
22647
22648     return (BAD_CAST *buf);
22649 }
22650
22651 /**
22652  * xmlSchemaXPathPop:
22653  * @vctxt: the WXS validation context
22654  *
22655  * Pops all XPath states.
22656  *
22657  * Returns 0 on success and -1 on internal errors.
22658  */
22659 static int
22660 xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22661 {
22662     xmlSchemaIDCStateObjPtr sto;
22663     int res;
22664
22665     if (vctxt->xpathStates == NULL)
22666         return(0);
22667     sto = vctxt->xpathStates;
22668     do {
22669         res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22670         if (res == -1)
22671             return (-1);
22672         sto = sto->next;
22673     } while (sto != NULL);
22674     return(0);
22675 }
22676
22677 /**
22678  * xmlSchemaXPathProcessHistory:
22679  * @vctxt: the WXS validation context
22680  * @type: the simple/complex type of the current node if any at all
22681  * @val: the precompiled value
22682  *
22683  * Processes and pops the history items of the IDC state objects.
22684  * IDC key-sequences are validated/created on IDC bindings.
22685  *
22686  * Returns 0 on success and -1 on internal errors.
22687  */
22688 static int
22689 xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
22690                              int depth)
22691 {
22692     xmlSchemaIDCStateObjPtr sto, nextsto;
22693     int res, matchDepth;
22694     xmlSchemaPSVIIDCKeyPtr key = NULL;
22695     xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
22696
22697     if (vctxt->xpathStates == NULL)
22698         return (0);
22699     sto = vctxt->xpathStates;
22700
22701 #ifdef DEBUG_IDC
22702     {
22703         xmlChar *str = NULL;
22704         xmlGenericError(xmlGenericErrorContext,
22705             "IDC: BACK on %s, depth %d\n",
22706             xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22707                 vctxt->inode->localName), vctxt->depth);
22708         FREE_AND_NULL(str)
22709     }
22710 #endif
22711     /*
22712     * Evaluate the state objects.
22713     */
22714     while (sto != NULL) {
22715         res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22716         if (res == -1) {
22717             VERROR_INT("xmlSchemaXPathProcessHistory",
22718                 "calling xmlStreamPop()");
22719             return (-1);
22720         }
22721 #ifdef DEBUG_IDC
22722         xmlGenericError(xmlGenericErrorContext, "IDC:   stream pop '%s'\n",
22723             sto->sel->xpath);
22724 #endif
22725         if (sto->nbHistory == 0)
22726             goto deregister_check;
22727
22728         matchDepth = sto->history[sto->nbHistory -1];
22729
22730         /*
22731         * Only matches at the current depth are of interest.
22732         */
22733         if (matchDepth != depth) {
22734             sto = sto->next;
22735             continue;
22736         }
22737         if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22738             /*
22739             * NOTE: According to
22740             *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22741             *   ... the simple-content of complex types is also allowed.
22742             */
22743
22744             if (WXS_IS_COMPLEX(type)) {
22745                 if (WXS_HAS_SIMPLE_CONTENT(type)) {
22746                     /*
22747                     * Sanity check for complex types with simple content.
22748                     */
22749                     simpleType = type->contentTypeDef;
22750                     if (simpleType == NULL) {
22751                         VERROR_INT("xmlSchemaXPathProcessHistory",
22752                             "field resolves to a CT with simple content "
22753                             "but the CT is missing the ST definition");
22754                         return (-1);
22755                     }
22756                 } else
22757                     simpleType = NULL;
22758             } else
22759                 simpleType = type;
22760             if (simpleType == NULL) {
22761                 xmlChar *str = NULL;
22762
22763                 /*
22764                 * Not qualified if the field resolves to a node of non
22765                 * simple type.
22766                 */
22767                 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22768                     XML_SCHEMAV_CVC_IDC, NULL,
22769                     WXS_BASIC_CAST sto->matcher->aidc->def,
22770                     "The XPath '%s' of a field of %s does evaluate to a node of "
22771                     "non-simple type",
22772                     sto->sel->xpath,
22773                     xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22774                 FREE_AND_NULL(str);
22775                 sto->nbHistory--;
22776                 goto deregister_check;
22777             }
22778
22779             if ((key == NULL) && (vctxt->inode->val == NULL)) {
22780                 /*
22781                 * Failed to provide the normalized value; maybe
22782                 * the value was invalid.
22783                 */
22784                 VERROR(XML_SCHEMAV_CVC_IDC,
22785                     WXS_BASIC_CAST sto->matcher->aidc->def,
22786                     "Warning: No precomputed value available, the value "
22787                     "was either invalid or something strange happend");
22788                 sto->nbHistory--;
22789                 goto deregister_check;
22790             } else {
22791                 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22792                 xmlSchemaPSVIIDCKeyPtr *keySeq;
22793                 int pos, idx;
22794
22795                 /*
22796                 * The key will be anchored on the matcher's list of
22797                 * key-sequences. The position in this list is determined
22798                 * by the target node's depth relative to the matcher's
22799                 * depth of creation (i.e. the depth of the scope element).
22800                 *
22801                 * Element        Depth    Pos   List-entries
22802                 * <scope>          0              NULL
22803                 *   <bar>          1              NULL
22804                 *     <target/>    2       2      target
22805                 *   <bar>
22806                 * </scope>
22807                 *
22808                 * The size of the list is only dependant on the depth of
22809                 * the tree.
22810                 * An entry will be NULLed in selector_leave, i.e. when
22811                 * we hit the target's
22812                 */
22813                 pos = sto->depth - matcher->depth;
22814                 idx = sto->sel->index;
22815
22816                 /*
22817                 * Create/grow the array of key-sequences.
22818                 */
22819                 if (matcher->keySeqs == NULL) {
22820                     if (pos > 9)
22821                         matcher->sizeKeySeqs = pos * 2;
22822                     else
22823                         matcher->sizeKeySeqs = 10;
22824                     matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22825                         xmlMalloc(matcher->sizeKeySeqs *
22826                         sizeof(xmlSchemaPSVIIDCKeyPtr *));
22827                     if (matcher->keySeqs == NULL) {
22828                         xmlSchemaVErrMemory(NULL,
22829                             "allocating an array of key-sequences",
22830                             NULL);
22831                         return(-1);
22832                     }
22833                     memset(matcher->keySeqs, 0,
22834                         matcher->sizeKeySeqs *
22835                         sizeof(xmlSchemaPSVIIDCKeyPtr *));
22836                 } else if (pos >= matcher->sizeKeySeqs) {
22837                     int i = matcher->sizeKeySeqs;
22838
22839                     matcher->sizeKeySeqs *= 2;
22840                     matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22841                         xmlRealloc(matcher->keySeqs,
22842                         matcher->sizeKeySeqs *
22843                         sizeof(xmlSchemaPSVIIDCKeyPtr *));
22844                     if (matcher->keySeqs == NULL) {
22845                         xmlSchemaVErrMemory(NULL,
22846                             "reallocating an array of key-sequences",
22847                             NULL);
22848                         return (-1);
22849                     }
22850                     /*
22851                     * The array needs to be NULLed.
22852                     * TODO: Use memset?
22853                     */
22854                     for (; i < matcher->sizeKeySeqs; i++)
22855                         matcher->keySeqs[i] = NULL;
22856                 }
22857
22858                 /*
22859                 * Get/create the key-sequence.
22860                 */
22861                 keySeq = matcher->keySeqs[pos];
22862                 if (keySeq == NULL) {
22863                     goto create_sequence;
22864                 } else if (keySeq[idx] != NULL) {
22865                     xmlChar *str = NULL;
22866                     /*
22867                     * cvc-identity-constraint:
22868                     * 3 For each node in the `target node set` all
22869                     * of the {fields}, with that node as the context
22870                     * node, evaluate to either an empty node-set or
22871                     * a node-set with exactly one member, which must
22872                     * have a simple type.
22873                     *
22874                     * The key was already set; report an error.
22875                     */
22876                     xmlSchemaCustomErr(ACTXT_CAST vctxt,
22877                         XML_SCHEMAV_CVC_IDC, NULL,
22878                         WXS_BASIC_CAST matcher->aidc->def,
22879                         "The XPath '%s' of a field of %s evaluates to a "
22880                         "node-set with more than one member",
22881                         sto->sel->xpath,
22882                         xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22883                     FREE_AND_NULL(str);
22884                     sto->nbHistory--;
22885                     goto deregister_check;
22886                 } else
22887                     goto create_key;
22888
22889 create_sequence:
22890                 /*
22891                 * Create a key-sequence.
22892                 */
22893                 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22894                     matcher->aidc->def->nbFields *
22895                     sizeof(xmlSchemaPSVIIDCKeyPtr));
22896                 if (keySeq == NULL) {
22897                     xmlSchemaVErrMemory(NULL,
22898                         "allocating an IDC key-sequence", NULL);
22899                     return(-1);
22900                 }
22901                 memset(keySeq, 0, matcher->aidc->def->nbFields *
22902                     sizeof(xmlSchemaPSVIIDCKeyPtr));
22903                 matcher->keySeqs[pos] = keySeq;
22904 create_key:
22905                 /*
22906                 * Create a key once per node only.
22907                 */
22908                 if (key == NULL) {
22909                     key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22910                         sizeof(xmlSchemaPSVIIDCKey));
22911                     if (key == NULL) {
22912                         xmlSchemaVErrMemory(NULL,
22913                             "allocating a IDC key", NULL);
22914                         xmlFree(keySeq);
22915                         matcher->keySeqs[pos] = NULL;
22916                         return(-1);
22917                     }
22918                     /*
22919                     * Consume the compiled value.
22920                     */
22921                     key->type = simpleType;
22922                     key->val = vctxt->inode->val;
22923                     vctxt->inode->val = NULL;
22924                     /*
22925                     * Store the key in a global list.
22926                     */
22927                     if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22928                         xmlSchemaIDCFreeKey(key);
22929                         return (-1);
22930                     }
22931                 }
22932                 keySeq[idx] = key;
22933             }
22934         } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22935
22936             xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
22937             /* xmlSchemaPSVIIDCBindingPtr bind; */
22938             xmlSchemaPSVIIDCNodePtr ntItem;
22939             xmlSchemaIDCMatcherPtr matcher;
22940             xmlSchemaIDCPtr idc;
22941             xmlSchemaItemListPtr targets;
22942             int pos, i, j, nbKeys;
22943             /*
22944             * Here we have the following scenario:
22945             * An IDC 'selector' state object resolved to a target node,
22946             * during the time this target node was in the
22947             * ancestor-or-self axis, the 'field' state object(s) looked
22948             * out for matching nodes to create a key-sequence for this
22949             * target node. Now we are back to this target node and need
22950             * to put the key-sequence, together with the target node
22951             * itself, into the node-table of the corresponding IDC
22952             * binding.
22953             */
22954             matcher = sto->matcher;
22955             idc = matcher->aidc->def;
22956             nbKeys = idc->nbFields;
22957             pos = depth - matcher->depth;
22958             /*
22959             * Check if the matcher has any key-sequences at all, plus
22960             * if it has a key-sequence for the current target node.
22961             */
22962             if ((matcher->keySeqs == NULL) ||
22963                 (matcher->sizeKeySeqs <= pos)) {
22964                 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22965                     goto selector_key_error;
22966                 else
22967                     goto selector_leave;
22968             }
22969
22970             keySeq = &(matcher->keySeqs[pos]);
22971             if (*keySeq == NULL) {
22972                 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22973                     goto selector_key_error;
22974                 else
22975                     goto selector_leave;
22976             }
22977
22978             for (i = 0; i < nbKeys; i++) {
22979                 if ((*keySeq)[i] == NULL) {
22980                     /*
22981                     * Not qualified, if not all fields did resolve.
22982                     */
22983                     if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22984                         /*
22985                         * All fields of a "key" IDC must resolve.
22986                         */
22987                         goto selector_key_error;
22988                     }
22989                     goto selector_leave;
22990                 }
22991             }
22992             /*
22993             * All fields did resolve.
22994             */
22995
22996             /*
22997             * 4.1 If the {identity-constraint category} is unique(/key),
22998             * then no two members of the `qualified node set` have
22999             * `key-sequences` whose members are pairwise equal, as
23000             * defined by Equal in [XML Schemas: Datatypes].
23001             *
23002             * Get the IDC binding from the matcher and check for
23003             * duplicate key-sequences.
23004             */
23005 #if 0
23006             bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23007 #endif
23008             targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
23009             if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
23010                 (targets->nbItems != 0)) {
23011                 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
23012
23013                 i = 0;
23014                 res = 0;
23015                 /*
23016                 * Compare the key-sequences, key by key.
23017                 */
23018                 do {
23019                     bkeySeq =
23020                         ((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys;
23021                     for (j = 0; j < nbKeys; j++) {
23022                         ckey = (*keySeq)[j];
23023                         bkey = bkeySeq[j];
23024                         res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
23025                         if (res == -1) {
23026                             return (-1);
23027                         } else if (res == 0) {
23028                             /*
23029                             * One of the keys differs, so the key-sequence
23030                             * won't be equal; get out.
23031                             */
23032                             break;
23033                         }
23034                     }
23035                     if (res == 1) {
23036                         /*
23037                         * Duplicate key-sequence found.
23038                         */
23039                         break;
23040                     }
23041                     i++;
23042                 } while (i < targets->nbItems);
23043                 if (i != targets->nbItems) {
23044                     xmlChar *str = NULL, *strB = NULL;
23045                     /*
23046                     * TODO: Try to report the key-sequence.
23047                     */
23048                     xmlSchemaCustomErr(ACTXT_CAST vctxt,
23049                         XML_SCHEMAV_CVC_IDC, NULL,
23050                         WXS_BASIC_CAST idc,
23051                         "Duplicate key-sequence %s in %s",
23052                         xmlSchemaFormatIDCKeySequence(vctxt, &str,
23053                             (*keySeq), nbKeys),
23054                         xmlSchemaGetIDCDesignation(&strB, idc));
23055                     FREE_AND_NULL(str);
23056                     FREE_AND_NULL(strB);
23057                     goto selector_leave;
23058                 }
23059             }
23060             /*
23061             * Add a node-table item to the IDC binding.
23062             */
23063             ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
23064                 sizeof(xmlSchemaPSVIIDCNode));
23065             if (ntItem == NULL) {
23066                 xmlSchemaVErrMemory(NULL,
23067                     "allocating an IDC node-table item", NULL);
23068                 xmlFree(*keySeq);
23069                 *keySeq = NULL;
23070                 return(-1);
23071             }
23072             memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
23073
23074             /*
23075             * Store the node-table item in a global list.
23076             */
23077             if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23078                 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
23079                     xmlFree(ntItem);
23080                     xmlFree(*keySeq);
23081                     *keySeq = NULL;
23082                     return (-1);
23083                 }
23084                 ntItem->nodeQNameID = -1;
23085             } else {
23086                 /*
23087                 * Save a cached QName for this node on the IDC node, to be
23088                 * able to report it, even if the node is not saved.
23089                 */
23090                 ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
23091                     vctxt->inode->localName, vctxt->inode->nsName);
23092                 if (ntItem->nodeQNameID == -1) {
23093                     xmlFree(ntItem);
23094                     xmlFree(*keySeq);
23095                     *keySeq = NULL;
23096                     return (-1);
23097                 }
23098             }
23099             /*
23100             * Init the node-table item: Save the node, position and
23101             * consume the key-sequence.
23102             */
23103             ntItem->node = vctxt->node;
23104             ntItem->nodeLine = vctxt->inode->nodeLine;
23105             ntItem->keys = *keySeq;
23106             *keySeq = NULL;
23107 #if 0
23108             if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1)
23109 #endif
23110             if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
23111                 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23112                     /*
23113                     * Free the item, since keyref items won't be
23114                     * put on a global list.
23115                     */
23116                     xmlFree(ntItem->keys);
23117                     xmlFree(ntItem);
23118                 }
23119                 return (-1);
23120             }
23121
23122             goto selector_leave;
23123 selector_key_error:
23124             {
23125                 xmlChar *str = NULL;
23126                 /*
23127                 * 4.2.1 (KEY) The `target node set` and the
23128                 * `qualified node set` are equal, that is, every
23129                 * member of the `target node set` is also a member
23130                 * of the `qualified node set` and vice versa.
23131                 */
23132                 xmlSchemaCustomErr(ACTXT_CAST vctxt,
23133                     XML_SCHEMAV_CVC_IDC, NULL,
23134                     WXS_BASIC_CAST idc,
23135                     "Not all fields of %s evaluate to a node",
23136                     xmlSchemaGetIDCDesignation(&str, idc), NULL);
23137                 FREE_AND_NULL(str);
23138             }
23139 selector_leave:
23140             /*
23141             * Free the key-sequence if not added to the IDC table.
23142             */
23143             if ((keySeq != NULL) && (*keySeq != NULL)) {
23144                 xmlFree(*keySeq);
23145                 *keySeq = NULL;
23146             }
23147         } /* if selector */
23148
23149         sto->nbHistory--;
23150
23151 deregister_check:
23152         /*
23153         * Deregister state objects if they reach the depth of creation.
23154         */
23155         if ((sto->nbHistory == 0) && (sto->depth == depth)) {
23156 #ifdef DEBUG_IDC
23157             xmlGenericError(xmlGenericErrorContext, "IDC:   STO pop '%s'\n",
23158                 sto->sel->xpath);
23159 #endif
23160             if (vctxt->xpathStates != sto) {
23161                 VERROR_INT("xmlSchemaXPathProcessHistory",
23162                     "The state object to be removed is not the first "
23163                     "in the list");
23164             }
23165             nextsto = sto->next;
23166             /*
23167             * Unlink from the list of active XPath state objects.
23168             */
23169             vctxt->xpathStates = sto->next;
23170             sto->next = vctxt->xpathStatePool;
23171             /*
23172             * Link it to the pool of reusable state objects.
23173             */
23174             vctxt->xpathStatePool = sto;
23175             sto = nextsto;
23176         } else
23177             sto = sto->next;
23178     } /* while (sto != NULL) */
23179     return (0);
23180 }
23181
23182 /**
23183  * xmlSchemaIDCRegisterMatchers:
23184  * @vctxt: the WXS validation context
23185  * @elemDecl: the element declaration
23186  *
23187  * Creates helper objects to evaluate IDC selectors/fields
23188  * successively.
23189  *
23190  * Returns 0 if OK and -1 on internal errors.
23191  */
23192 static int
23193 xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
23194                              xmlSchemaElementPtr elemDecl)
23195 {
23196     xmlSchemaIDCMatcherPtr matcher, last = NULL;
23197     xmlSchemaIDCPtr idc, refIdc;
23198     xmlSchemaIDCAugPtr aidc;
23199
23200     idc = (xmlSchemaIDCPtr) elemDecl->idcs;
23201     if (idc == NULL)
23202         return (0);
23203
23204 #ifdef DEBUG_IDC
23205     {
23206         xmlChar *str = NULL;
23207         xmlGenericError(xmlGenericErrorContext,
23208             "IDC: REGISTER on %s, depth %d\n",
23209             (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
23210                 vctxt->inode->localName), vctxt->depth);
23211         FREE_AND_NULL(str)
23212     }
23213 #endif
23214     if (vctxt->inode->idcMatchers != NULL) {
23215         VERROR_INT("xmlSchemaIDCRegisterMatchers",
23216             "The chain of IDC matchers is expected to be empty");
23217         return (-1);
23218     }
23219     do {
23220         if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23221             /*
23222             * Since IDCs bubbles are expensive we need to know the
23223             * depth at which the bubbles should stop; this will be
23224             * the depth of the top-most keyref IDC. If no keyref
23225             * references a key/unique IDC, the keyrefDepth will
23226             * be -1, indicating that no bubbles are needed.
23227             */
23228             refIdc = (xmlSchemaIDCPtr) idc->ref->item;
23229             if (refIdc != NULL) {
23230                 /*
23231                 * Remember that we have keyrefs on this node.
23232                 */
23233                 vctxt->inode->hasKeyrefs = 1;
23234                 /*
23235                 * Lookup the referenced augmented IDC info.
23236                 */
23237                 aidc = vctxt->aidcs;
23238                 while (aidc != NULL) {
23239                     if (aidc->def == refIdc)
23240                         break;
23241                     aidc = aidc->next;
23242                 }
23243                 if (aidc == NULL) {
23244                     VERROR_INT("xmlSchemaIDCRegisterMatchers",
23245                         "Could not find an augmented IDC item for an IDC "
23246                         "definition");
23247                     return (-1);
23248                 }
23249                 if ((aidc->keyrefDepth == -1) ||
23250                     (vctxt->depth < aidc->keyrefDepth))
23251                     aidc->keyrefDepth = vctxt->depth;
23252             }
23253         }
23254         /*
23255         * Lookup the augmented IDC item for the IDC definition.
23256         */
23257         aidc = vctxt->aidcs;
23258         while (aidc != NULL) {
23259             if (aidc->def == idc)
23260                 break;
23261             aidc = aidc->next;
23262         }
23263         if (aidc == NULL) {
23264             VERROR_INT("xmlSchemaIDCRegisterMatchers",
23265                 "Could not find an augmented IDC item for an IDC definition");
23266             return (-1);
23267         }
23268         /*
23269         * Create an IDC matcher for every IDC definition.
23270         */
23271         if (vctxt->idcMatcherCache != NULL) {
23272             /*
23273             * Reuse a cached matcher.
23274             */
23275             matcher = vctxt->idcMatcherCache;
23276             vctxt->idcMatcherCache = matcher->nextCached;
23277             matcher->nextCached = NULL;
23278         } else {
23279             matcher = (xmlSchemaIDCMatcherPtr)
23280                 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
23281             if (matcher == NULL) {
23282                 xmlSchemaVErrMemory(vctxt,
23283                     "allocating an IDC matcher", NULL);
23284                 return (-1);
23285             }
23286             memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
23287         }
23288         if (last == NULL)
23289             vctxt->inode->idcMatchers = matcher;
23290         else
23291             last->next = matcher;
23292         last = matcher;
23293
23294         matcher->type = IDC_MATCHER;
23295         matcher->depth = vctxt->depth;
23296         matcher->aidc = aidc;
23297         matcher->idcType = aidc->def->type;
23298 #ifdef DEBUG_IDC
23299         xmlGenericError(xmlGenericErrorContext, "IDC:   register matcher\n");
23300 #endif
23301         /*
23302         * Init the automaton state object.
23303         */
23304         if (xmlSchemaIDCAddStateObject(vctxt, matcher,
23305             idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
23306             return (-1);
23307
23308         idc = idc->next;
23309     } while (idc != NULL);
23310     return (0);
23311 }
23312
23313 static int
23314 xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
23315                            xmlSchemaNodeInfoPtr ielem)
23316 {
23317     xmlSchemaPSVIIDCBindingPtr bind;
23318     int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
23319     xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
23320     xmlSchemaPSVIIDCNodePtr *targets, *dupls;
23321
23322     xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
23323     /* vctxt->createIDCNodeTables */
23324     while (matcher != NULL) {
23325         /*
23326         * Skip keyref IDCs and empty IDC target-lists.
23327         */
23328         if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
23329             WXS_ILIST_IS_EMPTY(matcher->targets))
23330         {
23331             matcher = matcher->next;
23332             continue;
23333         }
23334         /*
23335         * If we _want_ the IDC node-table to be created in any case
23336         * then do so. Otherwise create them only if keyrefs need them.
23337         */
23338         if ((! vctxt->createIDCNodeTables) &&
23339             ((matcher->aidc->keyrefDepth == -1) ||
23340              (matcher->aidc->keyrefDepth > vctxt->depth)))
23341         {
23342             matcher = matcher->next;
23343             continue;
23344         }
23345         /*
23346         * Get/create the IDC binding on this element for the IDC definition.
23347         */
23348         bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23349
23350         if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
23351             dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23352             nbDupls = bind->dupls->nbItems;
23353         } else {
23354             dupls = NULL;
23355             nbDupls = 0;
23356         }
23357         if (bind->nodeTable != NULL) {
23358             nbNodeTable = bind->nbNodes;
23359         } else {
23360             nbNodeTable = 0;
23361         }
23362
23363         if ((nbNodeTable == 0) && (nbDupls == 0)) {
23364             /*
23365             * Transfer all IDC target-nodes to the IDC node-table.
23366             */
23367             bind->nodeTable =
23368                 (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23369             bind->sizeNodes = matcher->targets->sizeItems;
23370             bind->nbNodes = matcher->targets->nbItems;
23371
23372             matcher->targets->items = NULL;
23373             matcher->targets->sizeItems = 0;
23374             matcher->targets->nbItems = 0;
23375         } else {
23376             /*
23377             * Compare the key-sequences and add to the IDC node-table.
23378             */
23379             nbTargets = matcher->targets->nbItems;
23380             targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23381             nbFields = matcher->aidc->def->nbFields;
23382             i = 0;
23383             do {
23384                 keys = targets[i]->keys;
23385                 if (nbDupls) {
23386                     /*
23387                     * Search in already found duplicates first.
23388                     */
23389                     j = 0;
23390                     do {
23391                         if (nbFields == 1) {
23392                             res = xmlSchemaAreValuesEqual(keys[0]->val,
23393                                 dupls[j]->keys[0]->val);
23394                             if (res == -1)
23395                                 goto internal_error;
23396                             if (res == 1) {
23397                                 /*
23398                                 * Equal key-sequence.
23399                                 */
23400                                 goto next_target;
23401                             }
23402                         } else {
23403                             res = 0;
23404                             ntkeys = dupls[j]->keys;
23405                             for (k = 0; k < nbFields; k++) {
23406                                 res = xmlSchemaAreValuesEqual(keys[k]->val,
23407                                     ntkeys[k]->val);
23408                                 if (res == -1)
23409                                     goto internal_error;
23410                                 if (res == 0) {
23411                                     /*
23412                                     * One of the keys differs.
23413                                     */
23414                                     break;
23415                                 }
23416                             }
23417                             if (res == 1) {
23418                                 /*
23419                                 * Equal key-sequence found.
23420                                 */
23421                                 goto next_target;
23422                             }
23423                         }
23424                         j++;
23425                     } while (j < nbDupls);
23426                 }
23427                 if (nbNodeTable) {
23428                     j = 0;
23429                     do {
23430                         if (nbFields == 1) {
23431                             res = xmlSchemaAreValuesEqual(keys[0]->val,
23432                                 bind->nodeTable[j]->keys[0]->val);
23433                             if (res == -1)
23434                                 goto internal_error;
23435                             if (res == 0) {
23436                                 /*
23437                                 * The key-sequence differs.
23438                                 */
23439                                 goto next_node_table_entry;
23440                             }
23441                         } else {
23442                             res = 0;
23443                             ntkeys = bind->nodeTable[j]->keys;
23444                             for (k = 0; k < nbFields; k++) {
23445                                 res = xmlSchemaAreValuesEqual(keys[k]->val,
23446                                     ntkeys[k]->val);
23447                                 if (res == -1)
23448                                     goto internal_error;
23449                                 if (res == 0) {
23450                                     /*
23451                                     * One of the keys differs.
23452                                     */
23453                                     goto next_node_table_entry;
23454                                 }
23455                             }
23456                         }
23457                         /*
23458                         * Add the duplicate to the list of duplicates.
23459                         */
23460                         if (bind->dupls == NULL) {
23461                             bind->dupls = xmlSchemaItemListCreate();
23462                             if (bind->dupls == NULL)
23463                                 goto internal_error;
23464                         }
23465                         if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23466                             goto internal_error;
23467                         /*
23468                         * Remove the duplicate entry from the IDC node-table.
23469                         */
23470                         bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23471                         bind->nbNodes--;
23472
23473                         goto next_target;
23474
23475 next_node_table_entry:
23476                         j++;
23477                     } while (j < nbNodeTable);
23478                 }
23479                 /*
23480                 * If everything is fine, then add the IDC target-node to
23481                 * the IDC node-table.
23482                 */
23483                 if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23484                     goto internal_error;
23485
23486 next_target:
23487                 i++;
23488             } while (i < nbTargets);
23489         }
23490         matcher = matcher->next;
23491     }
23492     return(0);
23493
23494 internal_error:
23495     return(-1);
23496 }
23497
23498 /**
23499  * xmlSchemaBubbleIDCNodeTables:
23500  * @depth: the current tree depth
23501  *
23502  * Merges IDC bindings of an element at @depth into the corresponding IDC
23503  * bindings of its parent element. If a duplicate note-table entry is found,
23504  * both, the parent node-table entry and child entry are discarded from the
23505  * node-table of the parent.
23506  *
23507  * Returns 0 if OK and -1 on internal errors.
23508  */
23509 static int
23510 xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23511 {
23512     xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
23513     xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23514     xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
23515     xmlSchemaIDCAugPtr aidc;
23516     int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
23517
23518     bind = vctxt->inode->idcTable;
23519     if (bind == NULL) {
23520         /* Fine, no table, no bubbles. */
23521         return (0);
23522     }
23523
23524     parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23525     /*
23526     * Walk all bindings; create new or add to existing bindings.
23527     * Remove duplicate key-sequences.
23528     */
23529     while (bind != NULL) {
23530
23531         if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23532             goto next_binding;
23533         /*
23534         * Check if the key/unique IDC table needs to be bubbled.
23535         */
23536         if (! vctxt->createIDCNodeTables) {
23537             aidc = vctxt->aidcs;
23538             do {
23539                 if (aidc->def == bind->definition) {
23540                     if ((aidc->keyrefDepth == -1) ||
23541                         (aidc->keyrefDepth >= vctxt->depth)) {
23542                         goto next_binding;
23543                     }
23544                     break;
23545                 }
23546                 aidc = aidc->next;
23547             } while (aidc != NULL);
23548         }
23549
23550         if (parTable != NULL)
23551             parBind = *parTable;
23552         /*
23553         * Search a matching parent binding for the
23554         * IDC definition.
23555         */
23556         while (parBind != NULL) {
23557             if (parBind->definition == bind->definition)
23558                 break;
23559             parBind = parBind->next;
23560         }
23561
23562         if (parBind != NULL) {
23563             /*
23564             * Compare every node-table entry of the child node,
23565             * i.e. the key-sequence within, ...
23566             */
23567             oldNum = parBind->nbNodes; /* Skip newly added items. */
23568
23569             if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23570                 oldDupls = parBind->dupls->nbItems;
23571                 dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23572             } else {
23573                 dupls = NULL;
23574                 oldDupls = 0;
23575             }
23576
23577             parNodes = parBind->nodeTable;
23578             nbFields = bind->definition->nbFields;
23579
23580             for (i = 0; i < bind->nbNodes; i++) {
23581                 node = bind->nodeTable[i];
23582                 if (node == NULL)
23583                     continue;
23584                 /*
23585                 * ...with every key-sequence of the parent node, already
23586                 * evaluated to be a duplicate key-sequence.
23587                 */
23588                 if (oldDupls) {
23589                     j = 0;
23590                     while (j < oldDupls) {
23591                         if (nbFields == 1) {
23592                             ret = xmlSchemaAreValuesEqual(
23593                                 node->keys[0]->val,
23594                                 dupls[j]->keys[0]->val);
23595                             if (ret == -1)
23596                                 goto internal_error;
23597                             if (ret == 0) {
23598                                 j++;
23599                                 continue;
23600                             }
23601                         } else {
23602                             parNode = dupls[j];
23603                             for (k = 0; k < nbFields; k++) {
23604                                 ret = xmlSchemaAreValuesEqual(
23605                                     node->keys[k]->val,
23606                                     parNode->keys[k]->val);
23607                                 if (ret == -1)
23608                                     goto internal_error;
23609                                 if (ret == 0)
23610                                     break;
23611                             }
23612                         }
23613                         if (ret == 1)
23614                             /* Duplicate found. */
23615                             break;
23616                         j++;
23617                     }
23618                     if (j != oldDupls) {
23619                         /* Duplicate found. Skip this entry. */
23620                         continue;
23621                     }
23622                 }
23623                 /*
23624                 * ... and with every key-sequence of the parent node.
23625                 */
23626                 if (oldNum) {
23627                     j = 0;
23628                     while (j < oldNum) {
23629                         parNode = parNodes[j];
23630                         if (nbFields == 1) {
23631                             ret = xmlSchemaAreValuesEqual(
23632                                 node->keys[0]->val,
23633                                 parNode->keys[0]->val);
23634                             if (ret == -1)
23635                                 goto internal_error;
23636                             if (ret == 0) {
23637                                 j++;
23638                                 continue;
23639                             }
23640                         } else {
23641                             for (k = 0; k < nbFields; k++) {
23642                                 ret = xmlSchemaAreValuesEqual(
23643                                     node->keys[k]->val,
23644                                     parNode->keys[k]->val);
23645                                 if (ret == -1)
23646                                     goto internal_error;
23647                                 if (ret == 0)
23648                                     break;
23649                             }
23650                         }
23651                         if (ret == 1)
23652                             /* Duplicate found. */
23653                             break;
23654                         j++;
23655                     }
23656                     if (j != oldNum) {
23657                         /*
23658                         * Handle duplicates. Move the duplicate in
23659                         * the parent's node-table to the list of
23660                         * duplicates.
23661                         */
23662                         oldNum--;
23663                         parBind->nbNodes--;
23664                         /*
23665                         * Move last old item to pos of duplicate.
23666                         */
23667                         parNodes[j] = parNodes[oldNum];
23668
23669                         if (parBind->nbNodes != oldNum) {
23670                             /*
23671                             * If new items exist, move last new item to
23672                             * last of old items.
23673                             */
23674                             parNodes[oldNum] =
23675                                 parNodes[parBind->nbNodes];
23676                         }
23677                         if (parBind->dupls == NULL) {
23678                             parBind->dupls = xmlSchemaItemListCreate();
23679                             if (parBind->dupls == NULL)
23680                                 goto internal_error;
23681                         }
23682                         xmlSchemaItemListAdd(parBind->dupls, parNode);
23683                     } else {
23684                         /*
23685                         * Add the node-table entry (node and key-sequence) of
23686                         * the child node to the node table of the parent node.
23687                         */
23688                         if (parBind->nodeTable == NULL) {
23689                             parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23690                                 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
23691                             if (parBind->nodeTable == NULL) {
23692                                 xmlSchemaVErrMemory(NULL,
23693                                     "allocating IDC list of node-table items", NULL);
23694                                 goto internal_error;
23695                             }
23696                             parBind->sizeNodes = 1;
23697                         } else if (parBind->nbNodes >= parBind->sizeNodes) {
23698                             parBind->sizeNodes *= 2;
23699                             parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23700                                 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23701                                 sizeof(xmlSchemaPSVIIDCNodePtr));
23702                             if (parBind->nodeTable == NULL) {
23703                                 xmlSchemaVErrMemory(NULL,
23704                                     "re-allocating IDC list of node-table items", NULL);
23705                                 goto internal_error;
23706                             }
23707                         }
23708                         parNodes = parBind->nodeTable;
23709                         /*
23710                         * Append the new node-table entry to the 'new node-table
23711                         * entries' section.
23712                         */
23713                         parNodes[parBind->nbNodes++] = node;
23714                     }
23715
23716                 }
23717
23718             }
23719         } else {
23720             /*
23721             * No binding for the IDC was found: create a new one and
23722             * copy all node-tables.
23723             */
23724             parBind = xmlSchemaIDCNewBinding(bind->definition);
23725             if (parBind == NULL)
23726                 goto internal_error;
23727
23728             /*
23729             * TODO: Hmm, how to optimize the initial number of
23730             * allocated entries?
23731             */
23732             if (bind->nbNodes != 0) {
23733                 /*
23734                 * Add all IDC node-table entries.
23735                 */
23736                 if (! vctxt->psviExposeIDCNodeTables) {
23737                     /*
23738                     * Just move the entries.
23739                     * NOTE: this is quite save here, since
23740                     * all the keyref lookups have already been
23741                     * performed.
23742                     */
23743                     parBind->nodeTable = bind->nodeTable;
23744                     bind->nodeTable = NULL;
23745                     parBind->sizeNodes = bind->sizeNodes;
23746                     bind->sizeNodes = 0;
23747                     parBind->nbNodes = bind->nbNodes;
23748                     bind->nbNodes = 0;
23749                 } else {
23750                     /*
23751                     * Copy the entries.
23752                     */
23753                     parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23754                         xmlMalloc(bind->nbNodes *
23755                         sizeof(xmlSchemaPSVIIDCNodePtr));
23756                     if (parBind->nodeTable == NULL) {
23757                         xmlSchemaVErrMemory(NULL,
23758                             "allocating an array of IDC node-table "
23759                             "items", NULL);
23760                         xmlSchemaIDCFreeBinding(parBind);
23761                         goto internal_error;
23762                     }
23763                     parBind->sizeNodes = bind->nbNodes;
23764                     parBind->nbNodes = bind->nbNodes;
23765                     memcpy(parBind->nodeTable, bind->nodeTable,
23766                         bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23767                 }
23768             }
23769             if (bind->dupls) {
23770                 /*
23771                 * Move the duplicates.
23772                 */
23773                 if (parBind->dupls != NULL)
23774                     xmlSchemaItemListFree(parBind->dupls);
23775                 parBind->dupls = bind->dupls;
23776                 bind->dupls = NULL;
23777             }
23778             if (parTable != NULL) {
23779                 if (*parTable == NULL)
23780                     *parTable = parBind;
23781                 else {
23782                     parBind->next = *parTable;
23783                     *parTable = parBind;
23784                 }
23785             }
23786         }
23787
23788 next_binding:
23789         bind = bind->next;
23790     }
23791     return (0);
23792
23793 internal_error:
23794     return(-1);
23795 }
23796
23797 /**
23798  * xmlSchemaCheckCVCIDCKeyRef:
23799  * @vctxt: the WXS validation context
23800  * @elemDecl: the element declaration
23801  *
23802  * Check the cvc-idc-keyref constraints.
23803  */
23804 static int
23805 xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23806 {
23807     xmlSchemaIDCMatcherPtr matcher;
23808     xmlSchemaPSVIIDCBindingPtr bind;
23809
23810     matcher = vctxt->inode->idcMatchers;
23811     /*
23812     * Find a keyref.
23813     */
23814     while (matcher != NULL) {
23815         if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23816             matcher->targets &&
23817             matcher->targets->nbItems)
23818         {
23819             int i, j, k, res, nbFields, hasDupls;
23820             xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
23821             xmlSchemaPSVIIDCNodePtr refNode = NULL;
23822
23823             nbFields = matcher->aidc->def->nbFields;
23824
23825             /*
23826             * Find the IDC node-table for the referenced IDC key/unique.
23827             */
23828             bind = vctxt->inode->idcTable;
23829             while (bind != NULL) {
23830                 if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
23831                     bind->definition)
23832                     break;
23833                 bind = bind->next;
23834             }
23835             hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
23836             /*
23837             * Search for a matching key-sequences.
23838             */
23839             for (i = 0; i < matcher->targets->nbItems; i++) {
23840                 res = 0;
23841                 refNode = matcher->targets->items[i];
23842                 if (bind != NULL) {
23843                     refKeys = refNode->keys;
23844                     for (j = 0; j < bind->nbNodes; j++) {
23845                         keys = bind->nodeTable[j]->keys;
23846                         for (k = 0; k < nbFields; k++) {
23847                             res = xmlSchemaAreValuesEqual(keys[k]->val,
23848                                 refKeys[k]->val);
23849                             if (res == 0)
23850                                 break;
23851                             else if (res == -1) {
23852                                 return (-1);
23853                             }
23854                         }
23855                         if (res == 1) {
23856                             /*
23857                             * Match found.
23858                             */
23859                             break;
23860                         }
23861                     }
23862                     if ((res == 0) && hasDupls) {
23863                         /*
23864                         * Search in duplicates
23865                         */
23866                         for (j = 0; j < bind->dupls->nbItems; j++) {
23867                             keys = ((xmlSchemaPSVIIDCNodePtr)
23868                                 bind->dupls->items[j])->keys;
23869                             for (k = 0; k < nbFields; k++) {
23870                                 res = xmlSchemaAreValuesEqual(keys[k]->val,
23871                                     refKeys[k]->val);
23872                                 if (res == 0)
23873                                     break;
23874                                 else if (res == -1) {
23875                                     return (-1);
23876                                 }
23877                             }
23878                             if (res == 1) {
23879                                 /*
23880                                 * Match in duplicates found.
23881                                 */
23882                                 xmlChar *str = NULL, *strB = NULL;
23883                                 xmlSchemaKeyrefErr(vctxt,
23884                                     XML_SCHEMAV_CVC_IDC, refNode,
23885                                     (xmlSchemaTypePtr) matcher->aidc->def,
23886                                     "More than one match found for "
23887                                     "key-sequence %s of keyref '%s'",
23888                                     xmlSchemaFormatIDCKeySequence(vctxt, &str,
23889                                         refNode->keys, nbFields),
23890                                     xmlSchemaGetComponentQName(&strB,
23891                                         matcher->aidc->def));
23892                                 FREE_AND_NULL(str);
23893                                 FREE_AND_NULL(strB);
23894                                 break;
23895                             }
23896                         }
23897                     }
23898                 }
23899
23900                 if (res == 0) {
23901                     xmlChar *str = NULL, *strB = NULL;
23902                     xmlSchemaKeyrefErr(vctxt,
23903                         XML_SCHEMAV_CVC_IDC, refNode,
23904                         (xmlSchemaTypePtr) matcher->aidc->def,
23905                         "No match found for key-sequence %s of keyref '%s'",
23906                         xmlSchemaFormatIDCKeySequence(vctxt, &str,
23907                             refNode->keys, nbFields),
23908                         xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
23909                     FREE_AND_NULL(str);
23910                     FREE_AND_NULL(strB);
23911                 }
23912             }
23913         }
23914         matcher = matcher->next;
23915     }
23916     /* TODO: Return an error if any error encountered. */
23917     return (0);
23918 }
23919
23920 /************************************************************************
23921  *                                                                      *
23922  *                      XML Reader validation code                      *
23923  *                                                                      *
23924  ************************************************************************/
23925
23926 static xmlSchemaAttrInfoPtr
23927 xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
23928 {
23929     xmlSchemaAttrInfoPtr iattr;
23930     /*
23931     * Grow/create list of attribute infos.
23932     */
23933     if (vctxt->attrInfos == NULL) {
23934         vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23935             xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23936         vctxt->sizeAttrInfos = 1;
23937         if (vctxt->attrInfos == NULL) {
23938             xmlSchemaVErrMemory(vctxt,
23939                 "allocating attribute info list", NULL);
23940             return (NULL);
23941         }
23942     } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23943         vctxt->sizeAttrInfos++;
23944         vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23945             xmlRealloc(vctxt->attrInfos,
23946                 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23947         if (vctxt->attrInfos == NULL) {
23948             xmlSchemaVErrMemory(vctxt,
23949                 "re-allocating attribute info list", NULL);
23950             return (NULL);
23951         }
23952     } else {
23953         iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23954         if (iattr->localName != NULL) {
23955             VERROR_INT("xmlSchemaGetFreshAttrInfo",
23956                 "attr info not cleared");
23957             return (NULL);
23958         }
23959         iattr->nodeType = XML_ATTRIBUTE_NODE;
23960         return (iattr);
23961     }
23962     /*
23963     * Create an attribute info.
23964     */
23965     iattr = (xmlSchemaAttrInfoPtr)
23966         xmlMalloc(sizeof(xmlSchemaAttrInfo));
23967     if (iattr == NULL) {
23968         xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
23969         return (NULL);
23970     }
23971     memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23972     iattr->nodeType = XML_ATTRIBUTE_NODE;
23973     vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23974
23975     return (iattr);
23976 }
23977
23978 static int
23979 xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23980                         xmlNodePtr attrNode,
23981                         int nodeLine,
23982                         const xmlChar *localName,
23983                         const xmlChar *nsName,
23984                         int ownedNames,
23985                         xmlChar *value,
23986                         int ownedValue)
23987 {
23988     xmlSchemaAttrInfoPtr attr;
23989
23990     attr = xmlSchemaGetFreshAttrInfo(vctxt);
23991     if (attr == NULL) {
23992         VERROR_INT("xmlSchemaPushAttribute",
23993             "calling xmlSchemaGetFreshAttrInfo()");
23994         return (-1);
23995     }
23996     attr->node = attrNode;
23997     attr->nodeLine = nodeLine;
23998     attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23999     attr->localName = localName;
24000     attr->nsName = nsName;
24001     if (ownedNames)
24002         attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
24003     /*
24004     * Evaluate if it's an XSI attribute.
24005     */
24006     if (nsName != NULL) {
24007         if (xmlStrEqual(localName, BAD_CAST "nil")) {
24008             if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24009                 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
24010             }
24011         } else if (xmlStrEqual(localName, BAD_CAST "type")) {
24012             if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24013                 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
24014             }
24015         } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
24016             if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24017                 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
24018             }
24019         } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
24020             if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24021                 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
24022             }
24023         } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
24024             attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
24025         }
24026     }
24027     attr->value = value;
24028     if (ownedValue)
24029         attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
24030     if (attr->metaType != 0)
24031         attr->state = XML_SCHEMAS_ATTR_META;
24032     return (0);
24033 }
24034
24035 /**
24036  * xmlSchemaClearElemInfo:
24037  * @vctxt: the WXS validation context
24038  * @ielem: the element information item
24039  */
24040 static void
24041 xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,
24042                        xmlSchemaNodeInfoPtr ielem)
24043 {
24044     ielem->hasKeyrefs = 0;
24045     ielem->appliedXPath = 0;
24046     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
24047         FREE_AND_NULL(ielem->localName);
24048         FREE_AND_NULL(ielem->nsName);
24049     } else {
24050         ielem->localName = NULL;
24051         ielem->nsName = NULL;
24052     }
24053     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24054         FREE_AND_NULL(ielem->value);
24055     } else {
24056         ielem->value = NULL;
24057     }
24058     if (ielem->val != NULL) {
24059         /*
24060         * PSVI TODO: Be careful not to free it when the value is
24061         * exposed via PSVI.
24062         */
24063         xmlSchemaFreeValue(ielem->val);
24064         ielem->val = NULL;
24065     }
24066     if (ielem->idcMatchers != NULL) {
24067         /*
24068         * REVISIT OPTIMIZE TODO: Use a pool of IDC matchers.
24069         *   Does it work?
24070         */
24071         xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers);
24072 #if 0
24073         xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
24074 #endif
24075         ielem->idcMatchers = NULL;
24076     }
24077     if (ielem->idcTable != NULL) {
24078         /*
24079         * OPTIMIZE TODO: Use a pool of IDC tables??.
24080         */
24081         xmlSchemaIDCFreeIDCTable(ielem->idcTable);
24082         ielem->idcTable = NULL;
24083     }
24084     if (ielem->regexCtxt != NULL) {
24085         xmlRegFreeExecCtxt(ielem->regexCtxt);
24086         ielem->regexCtxt = NULL;
24087     }
24088     if (ielem->nsBindings != NULL) {
24089         xmlFree((xmlChar **)ielem->nsBindings);
24090         ielem->nsBindings = NULL;
24091         ielem->nbNsBindings = 0;
24092         ielem->sizeNsBindings = 0;
24093     }
24094 }
24095
24096 /**
24097  * xmlSchemaGetFreshElemInfo:
24098  * @vctxt: the schema validation context
24099  *
24100  * Creates/reuses and initializes the element info item for
24101  * the currect tree depth.
24102  *
24103  * Returns the element info item or NULL on API or internal errors.
24104  */
24105 static xmlSchemaNodeInfoPtr
24106 xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
24107 {
24108     xmlSchemaNodeInfoPtr info = NULL;
24109
24110     if (vctxt->depth > vctxt->sizeElemInfos) {
24111         VERROR_INT("xmlSchemaGetFreshElemInfo",
24112             "inconsistent depth encountered");
24113         return (NULL);
24114     }
24115     if (vctxt->elemInfos == NULL) {
24116         vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24117             xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
24118         if (vctxt->elemInfos == NULL) {
24119             xmlSchemaVErrMemory(vctxt,
24120                 "allocating the element info array", NULL);
24121             return (NULL);
24122         }
24123         memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
24124         vctxt->sizeElemInfos = 10;
24125     } else if (vctxt->sizeElemInfos <= vctxt->depth) {
24126         int i = vctxt->sizeElemInfos;
24127
24128         vctxt->sizeElemInfos *= 2;
24129         vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24130             xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
24131             sizeof(xmlSchemaNodeInfoPtr));
24132         if (vctxt->elemInfos == NULL) {
24133             xmlSchemaVErrMemory(vctxt,
24134                 "re-allocating the element info array", NULL);
24135             return (NULL);
24136         }
24137         /*
24138         * We need the new memory to be NULLed.
24139         * TODO: Use memset instead?
24140         */
24141         for (; i < vctxt->sizeElemInfos; i++)
24142             vctxt->elemInfos[i] = NULL;
24143     } else
24144         info = vctxt->elemInfos[vctxt->depth];
24145
24146     if (info == NULL) {
24147         info = (xmlSchemaNodeInfoPtr)
24148             xmlMalloc(sizeof(xmlSchemaNodeInfo));
24149         if (info == NULL) {
24150             xmlSchemaVErrMemory(vctxt,
24151                 "allocating an element info", NULL);
24152             return (NULL);
24153         }
24154         vctxt->elemInfos[vctxt->depth] = info;
24155     } else {
24156         if (info->localName != NULL) {
24157             VERROR_INT("xmlSchemaGetFreshElemInfo",
24158                 "elem info has not been cleared");
24159             return (NULL);
24160         }
24161     }
24162     memset(info, 0, sizeof(xmlSchemaNodeInfo));
24163     info->nodeType = XML_ELEMENT_NODE;
24164     info->depth = vctxt->depth;
24165
24166     return (info);
24167 }
24168
24169 #define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
24170 #define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
24171 #define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
24172
24173 static int
24174 xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
24175                         xmlNodePtr node,
24176                         xmlSchemaTypePtr type,
24177                         xmlSchemaValType valType,
24178                         const xmlChar * value,
24179                         xmlSchemaValPtr val,
24180                         unsigned long length,
24181                         int fireErrors)
24182 {
24183     int ret, error = 0;
24184
24185     xmlSchemaTypePtr tmpType;
24186     xmlSchemaFacetLinkPtr facetLink;
24187     xmlSchemaFacetPtr facet;
24188     unsigned long len = 0;
24189     xmlSchemaWhitespaceValueType ws;
24190
24191     /*
24192     * In Libxml2, derived built-in types have currently no explicit facets.
24193     */
24194     if (type->type == XML_SCHEMA_TYPE_BASIC)
24195         return (0);
24196
24197     /*
24198     * NOTE: Do not jump away, if the facetSet of the given type is
24199     * empty: until now, "pattern" and "enumeration" facets of the
24200     * *base types* need to be checked as well.
24201     */
24202     if (type->facetSet == NULL)
24203         goto pattern_and_enum;
24204
24205     if (! WXS_IS_ATOMIC(type)) {
24206         if (WXS_IS_LIST(type))
24207             goto WXS_IS_LIST;
24208         else
24209             goto pattern_and_enum;
24210     }
24211
24212     /*
24213     * Whitespace handling is only of importance for string-based
24214     * types.
24215     */
24216     tmpType = xmlSchemaGetPrimitiveType(type);
24217     if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
24218         WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
24219         ws = xmlSchemaGetWhiteSpaceFacetValue(type);
24220     } else
24221         ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
24222
24223     /*
24224     * If the value was not computed (for string or
24225     * anySimpleType based types), then use the provided
24226     * type.
24227     */
24228     if (val != NULL)
24229         valType = xmlSchemaGetValType(val);
24230
24231     ret = 0;
24232     for (facetLink = type->facetSet; facetLink != NULL;
24233         facetLink = facetLink->next) {
24234         /*
24235         * Skip the pattern "whiteSpace": it is used to
24236         * format the character content beforehand.
24237         */
24238         switch (facetLink->facet->type) {
24239             case XML_SCHEMA_FACET_WHITESPACE:
24240             case XML_SCHEMA_FACET_PATTERN:
24241             case XML_SCHEMA_FACET_ENUMERATION:
24242                 continue;
24243             case XML_SCHEMA_FACET_LENGTH:
24244             case XML_SCHEMA_FACET_MINLENGTH:
24245             case XML_SCHEMA_FACET_MAXLENGTH:
24246                 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
24247                     valType, value, val, &len, ws);
24248                 break;
24249             default:
24250                 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
24251                     valType, value, val, ws);
24252                 break;
24253         }
24254         if (ret < 0) {
24255             AERROR_INT("xmlSchemaValidateFacets",
24256                 "validating against a atomic type facet");
24257             return (-1);
24258         } else if (ret > 0) {
24259             if (fireErrors)
24260                 xmlSchemaFacetErr(actxt, ret, node,
24261                 value, len, type, facetLink->facet, NULL, NULL, NULL);
24262             else
24263                 return (ret);
24264             if (error == 0)
24265                 error = ret;
24266         }
24267         ret = 0;
24268     }
24269
24270 WXS_IS_LIST:
24271     if (! WXS_IS_LIST(type))
24272         goto pattern_and_enum;
24273     /*
24274     * "length", "minLength" and "maxLength" of list types.
24275     */
24276     ret = 0;
24277     for (facetLink = type->facetSet; facetLink != NULL;
24278         facetLink = facetLink->next) {
24279
24280         switch (facetLink->facet->type) {
24281             case XML_SCHEMA_FACET_LENGTH:
24282             case XML_SCHEMA_FACET_MINLENGTH:
24283             case XML_SCHEMA_FACET_MAXLENGTH:
24284                 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
24285                     value, length, NULL);
24286                 break;
24287             default:
24288                 continue;
24289         }
24290         if (ret < 0) {
24291             AERROR_INT("xmlSchemaValidateFacets",
24292                 "validating against a list type facet");
24293             return (-1);
24294         } else if (ret > 0) {
24295             if (fireErrors)
24296                 xmlSchemaFacetErr(actxt, ret, node,
24297                 value, length, type, facetLink->facet, NULL, NULL, NULL);
24298             else
24299                 return (ret);
24300             if (error == 0)
24301                 error = ret;
24302         }
24303         ret = 0;
24304     }
24305
24306 pattern_and_enum:
24307     if (error >= 0) {
24308         int found = 0;
24309         /*
24310         * Process enumerations. Facet values are in the value space
24311         * of the defining type's base type. This seems to be a bug in the
24312         * XML Schema 1.0 spec. Use the whitespace type of the base type.
24313         * Only the first set of enumerations in the ancestor-or-self axis
24314         * is used for validation.
24315         */
24316         ret = 0;
24317         tmpType = type;
24318         do {
24319             for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
24320                 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
24321                     continue;
24322                 found = 1;
24323                 ret = xmlSchemaAreValuesEqual(facet->val, val);
24324                 if (ret == 1)
24325                     break;
24326                 else if (ret < 0) {
24327                     AERROR_INT("xmlSchemaValidateFacets",
24328                         "validating against an enumeration facet");
24329                     return (-1);
24330                 }
24331             }
24332             if (ret != 0)
24333                 break;
24334             /*
24335             * Break on the first set of enumerations. Any additional
24336             *  enumerations which might be existent on the ancestors
24337             *  of the current type are restricted by this set; thus
24338             *  *must* *not* be taken into account.
24339             */
24340             if (found)
24341                 break;
24342             tmpType = tmpType->baseType;
24343         } while ((tmpType != NULL) &&
24344             (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24345         if (found && (ret == 0)) {
24346             ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
24347             if (fireErrors) {
24348                 xmlSchemaFacetErr(actxt, ret, node,
24349                     value, 0, type, NULL, NULL, NULL, NULL);
24350             } else
24351                 return (ret);
24352             if (error == 0)
24353                 error = ret;
24354         }
24355     }
24356
24357     if (error >= 0) {
24358         int found;
24359         /*
24360         * Process patters. Pattern facets are ORed at type level
24361         * and ANDed if derived. Walk the base type axis.
24362         */
24363         tmpType = type;
24364         facet = NULL;
24365         do {
24366             found = 0;
24367             for (facetLink = tmpType->facetSet; facetLink != NULL;
24368                 facetLink = facetLink->next) {
24369                 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
24370                     continue;
24371                 found = 1;
24372                 /*
24373                 * NOTE that for patterns, @value needs to be the
24374                 * normalized vaule.
24375                 */
24376                 ret = xmlRegexpExec(facetLink->facet->regexp, value);
24377                 if (ret == 1)
24378                     break;
24379                 else if (ret < 0) {
24380                     AERROR_INT("xmlSchemaValidateFacets",
24381                         "validating against a pattern facet");
24382                     return (-1);
24383                 } else {
24384                     /*
24385                     * Save the last non-validating facet.
24386                     */
24387                     facet = facetLink->facet;
24388                 }
24389             }
24390             if (found && (ret != 1)) {
24391                 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
24392                 if (fireErrors) {
24393                     xmlSchemaFacetErr(actxt, ret, node,
24394                         value, 0, type, facet, NULL, NULL, NULL);
24395                 } else
24396                     return (ret);
24397                 if (error == 0)
24398                     error = ret;
24399                 break;
24400             }
24401             tmpType = tmpType->baseType;
24402         } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24403     }
24404
24405     return (error);
24406 }
24407
24408 static xmlChar *
24409 xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24410                         const xmlChar *value)
24411 {
24412     switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
24413         case XML_SCHEMA_WHITESPACE_COLLAPSE:
24414             return (xmlSchemaCollapseString(value));
24415         case XML_SCHEMA_WHITESPACE_REPLACE:
24416             return (xmlSchemaWhiteSpaceReplace(value));
24417         default:
24418             return (NULL);
24419     }
24420 }
24421
24422 static int
24423 xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24424                        const xmlChar *value,
24425                        xmlSchemaValPtr *val,
24426                        int valNeeded)
24427 {
24428     int ret;
24429     const xmlChar *nsName;
24430     xmlChar *local, *prefix = NULL;
24431
24432     ret = xmlValidateQName(value, 1);
24433     if (ret != 0) {
24434         if (ret == -1) {
24435             VERROR_INT("xmlSchemaValidateQName",
24436                 "calling xmlValidateQName()");
24437             return (-1);
24438         }
24439         return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24440     }
24441     /*
24442     * NOTE: xmlSplitQName2 will always return a duplicated
24443     * strings.
24444     */
24445     local = xmlSplitQName2(value, &prefix);
24446     if (local == NULL)
24447         local = xmlStrdup(value);
24448     /*
24449     * OPTIMIZE TODO: Use flags for:
24450     *  - is there any namespace binding?
24451     *  - is there a default namespace?
24452     */
24453     nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24454
24455     if (prefix != NULL) {
24456         xmlFree(prefix);
24457         /*
24458         * A namespace must be found if the prefix is
24459         * NOT NULL.
24460         */
24461         if (nsName == NULL) {
24462             ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24463             xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
24464                 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24465                 "The QName value '%s' has no "
24466                 "corresponding namespace declaration in "
24467                 "scope", value, NULL);
24468             if (local != NULL)
24469                 xmlFree(local);
24470             return (ret);
24471         }
24472     }
24473     if (valNeeded && val) {
24474         if (nsName != NULL)
24475             *val = xmlSchemaNewQNameValue(
24476                 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24477         else
24478             *val = xmlSchemaNewQNameValue(NULL,
24479                 BAD_CAST local);
24480     } else
24481         xmlFree(local);
24482     return (0);
24483 }
24484
24485 /*
24486 * cvc-simple-type
24487 */
24488 static int
24489 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24490                              xmlNodePtr node,
24491                              xmlSchemaTypePtr type,
24492                              const xmlChar *value,
24493                              xmlSchemaValPtr *retVal,
24494                              int fireErrors,
24495                              int normalize,
24496                              int isNormalized)
24497 {
24498     int ret = 0, valNeeded = (retVal) ? 1 : 0;
24499     xmlSchemaValPtr val = NULL;
24500     /* xmlSchemaWhitespaceValueType ws; */
24501     xmlChar *normValue = NULL;
24502
24503 #define NORMALIZE(atype) \
24504     if ((! isNormalized) && \
24505     (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24506         normValue = xmlSchemaNormalizeValue(atype, value); \
24507         if (normValue != NULL) \
24508             value = normValue; \
24509         isNormalized = 1; \
24510     }
24511
24512     if ((retVal != NULL) && (*retVal != NULL)) {
24513         xmlSchemaFreeValue(*retVal);
24514         *retVal = NULL;
24515     }
24516     /*
24517     * 3.14.4 Simple Type Definition Validation Rules
24518     * Validation Rule: String Valid
24519     */
24520     /*
24521     * 1 It is schema-valid with respect to that definition as defined
24522     * by Datatype Valid in [XML Schemas: Datatypes].
24523     */
24524     /*
24525     * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24526     * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6), then
24527     * the string must be a `declared entity name`.
24528     */
24529     /*
24530     * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24531     * given the empty set, as defined in Type Derivation OK (Simple) ($3.14.6),
24532     * then every whitespace-delimited substring of the string must be a `declared
24533     * entity name`.
24534     */
24535     /*
24536     * 2.3 otherwise no further condition applies.
24537     */
24538     if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24539         valNeeded = 1;
24540     if (value == NULL)
24541         value = BAD_CAST "";
24542     if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
24543         xmlSchemaTypePtr biType; /* The built-in type. */
24544         /*
24545         * SPEC (1.2.1) "if {variety} is `atomic` then the string must `match`
24546         * a literal in the `lexical space` of {base type definition}"
24547         */
24548         /*
24549         * Whitespace-normalize.
24550         */
24551         NORMALIZE(type);
24552         if (type->type != XML_SCHEMA_TYPE_BASIC) {
24553             /*
24554             * Get the built-in type.
24555             */
24556             biType = type->baseType;
24557             while ((biType != NULL) &&
24558                 (biType->type != XML_SCHEMA_TYPE_BASIC))
24559                 biType = biType->baseType;
24560
24561             if (biType == NULL) {
24562                 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24563                     "could not get the built-in type");
24564                 goto internal_error;
24565             }
24566         } else
24567             biType = type;
24568         /*
24569         * NOTATIONs need to be processed here, since they need
24570         * to lookup in the hashtable of NOTATION declarations of the schema.
24571         */
24572         if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24573             switch (biType->builtInType) {
24574                 case XML_SCHEMAS_NOTATION:
24575                     ret = xmlSchemaValidateNotation(
24576                         (xmlSchemaValidCtxtPtr) actxt,
24577                         ((xmlSchemaValidCtxtPtr) actxt)->schema,
24578                         NULL, value, &val, valNeeded);
24579                     break;
24580                 case XML_SCHEMAS_QNAME:
24581                     ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24582                         value, &val, valNeeded);
24583                     break;
24584                 default:
24585                     /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24586                     if (valNeeded)
24587                         ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24588                             value, &val, node);
24589                     else
24590                         ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24591                             value, NULL, node);
24592                     break;
24593             }
24594         } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24595             switch (biType->builtInType) {
24596                 case XML_SCHEMAS_NOTATION:
24597                     ret = xmlSchemaValidateNotation(NULL,
24598                         ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24599                         value, &val, valNeeded);
24600                     break;
24601                 default:
24602                     /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24603                     if (valNeeded)
24604                         ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24605                             value, &val, node);
24606                     else
24607                         ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24608                             value, NULL, node);
24609                     break;
24610             }
24611         } else {
24612             /*
24613             * Validation via a public API is not implemented yet.
24614             */
24615             TODO
24616             goto internal_error;
24617         }
24618         if (ret != 0) {
24619             if (ret < 0) {
24620                 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24621                     "validating against a built-in type");
24622                 goto internal_error;
24623             }
24624             if (WXS_IS_LIST(type))
24625                 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24626             else
24627                 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24628         }
24629         if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24630             /*
24631             * Check facets.
24632             */
24633             ret = xmlSchemaValidateFacets(actxt, node, type,
24634                 (xmlSchemaValType) biType->builtInType, value, val,
24635                 0, fireErrors);
24636             if (ret != 0) {
24637                 if (ret < 0) {
24638                     AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24639                         "validating facets of atomic simple type");
24640                     goto internal_error;
24641                 }
24642                 if (WXS_IS_LIST(type))
24643                     ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24644                 else
24645                     ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24646             }
24647         }
24648         if (fireErrors && (ret > 0))
24649             xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24650     } else if (WXS_IS_LIST(type)) {
24651
24652         xmlSchemaTypePtr itemType;
24653         const xmlChar *cur, *end;
24654         xmlChar *tmpValue = NULL;
24655         unsigned long len = 0;
24656         xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24657         /* 1.2.2 if {variety} is `list` then the string must be a sequence
24658         * of white space separated tokens, each of which `match`es a literal
24659         * in the `lexical space` of {item type definition}
24660         */
24661         /*
24662         * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24663         * the list type has an enum or pattern facet.
24664         */
24665         NORMALIZE(type);
24666         /*
24667         * VAL TODO: Optimize validation of empty values.
24668         * VAL TODO: We do not have computed values for lists.
24669         */
24670         itemType = WXS_LIST_ITEMTYPE(type);
24671         cur = value;
24672         do {
24673             while (IS_BLANK_CH(*cur))
24674                 cur++;
24675             end = cur;
24676             while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24677                 end++;
24678             if (end == cur)
24679                 break;
24680             tmpValue = xmlStrndup(cur, end - cur);
24681             len++;
24682
24683             if (valNeeded)
24684                 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24685                     tmpValue, &curVal, fireErrors, 0, 1);
24686             else
24687                 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24688                     tmpValue, NULL, fireErrors, 0, 1);
24689             FREE_AND_NULL(tmpValue);
24690             if (curVal != NULL) {
24691                 /*
24692                 * Add to list of computed values.
24693                 */
24694                 if (val == NULL)
24695                     val = curVal;
24696                 else
24697                     xmlSchemaValueAppend(prevVal, curVal);
24698                 prevVal = curVal;
24699                 curVal = NULL;
24700             }
24701             if (ret != 0) {
24702                 if (ret < 0) {
24703                     AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24704                         "validating an item of list simple type");
24705                     goto internal_error;
24706                 }
24707                 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24708                 break;
24709             }
24710             cur = end;
24711         } while (*cur != 0);
24712         FREE_AND_NULL(tmpValue);
24713         if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24714             /*
24715             * Apply facets (pattern, enumeration).
24716             */
24717             ret = xmlSchemaValidateFacets(actxt, node, type,
24718                 XML_SCHEMAS_UNKNOWN, value, val,
24719                 len, fireErrors);
24720             if (ret != 0) {
24721                 if (ret < 0) {
24722                     AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24723                         "validating facets of list simple type");
24724                     goto internal_error;
24725                 }
24726                 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24727             }
24728         }
24729         if (fireErrors && (ret > 0)) {
24730             /*
24731             * Report the normalized value.
24732             */
24733             normalize = 1;
24734             NORMALIZE(type);
24735             xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24736         }
24737     } else if (WXS_IS_UNION(type)) {
24738         xmlSchemaTypeLinkPtr memberLink;
24739         /*
24740         * TODO: For all datatypes `derived` by `union`  whiteSpace does
24741         * not apply directly; however, the normalization behavior of `union`
24742         * types is controlled by the value of whiteSpace on that one of the
24743         * `memberTypes` against which the `union` is successfully validated.
24744         *
24745         * This means that the value is normalized by the first validating
24746         * member type, then the facets of the union type are applied. This
24747         * needs changing of the value!
24748         */
24749
24750         /*
24751         * 1.2.3 if {variety} is `union` then the string must `match` a
24752         * literal in the `lexical space` of at least one member of
24753         * {member type definitions}
24754         */
24755         memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24756         if (memberLink == NULL) {
24757             AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24758                 "union simple type has no member types");
24759             goto internal_error;
24760         }
24761         /*
24762         * Always normalize union type values, since we currently
24763         * cannot store the whitespace information with the value
24764         * itself; otherwise a later value-comparison would be
24765         * not possible.
24766         */
24767         while (memberLink != NULL) {
24768             if (valNeeded)
24769                 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24770                     memberLink->type, value, &val, 0, 1, 0);
24771             else
24772                 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24773                     memberLink->type, value, NULL, 0, 1, 0);
24774             if (ret <= 0)
24775                 break;
24776             memberLink = memberLink->next;
24777         }
24778         if (ret != 0) {
24779             if (ret < 0) {
24780                 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24781                     "validating members of union simple type");
24782                 goto internal_error;
24783             }
24784             ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24785         }
24786         /*
24787         * Apply facets (pattern, enumeration).
24788         */
24789         if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24790             /*
24791             * The normalization behavior of `union` types is controlled by
24792             * the value of whiteSpace on that one of the `memberTypes`
24793             * against which the `union` is successfully validated.
24794             */
24795             NORMALIZE(memberLink->type);
24796             ret = xmlSchemaValidateFacets(actxt, node, type,
24797                 XML_SCHEMAS_UNKNOWN, value, val,
24798                 0, fireErrors);
24799             if (ret != 0) {
24800                 if (ret < 0) {
24801                     AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24802                         "validating facets of union simple type");
24803                     goto internal_error;
24804                 }
24805                 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24806             }
24807         }
24808         if (fireErrors && (ret > 0))
24809             xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24810     }
24811
24812     if (normValue != NULL)
24813         xmlFree(normValue);
24814     if (ret == 0) {
24815         if (retVal != NULL)
24816             *retVal = val;
24817         else if (val != NULL)
24818             xmlSchemaFreeValue(val);
24819     } else if (val != NULL)
24820         xmlSchemaFreeValue(val);
24821     return (ret);
24822 internal_error:
24823     if (normValue != NULL)
24824         xmlFree(normValue);
24825     if (val != NULL)
24826         xmlSchemaFreeValue(val);
24827     return (-1);
24828 }
24829
24830 static int
24831 xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24832                            const xmlChar *value,
24833                            const xmlChar **nsName,
24834                            const xmlChar **localName)
24835 {
24836     int ret = 0;
24837
24838     if ((nsName == NULL) || (localName == NULL))
24839         return (-1);
24840     *nsName = NULL;
24841     *localName = NULL;
24842
24843     ret = xmlValidateQName(value, 1);
24844     if (ret == -1)
24845         return (-1);
24846     if (ret > 0) {
24847         xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
24848             XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24849             value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24850         return (1);
24851     }
24852     {
24853         xmlChar *local = NULL;
24854         xmlChar *prefix;
24855
24856         /*
24857         * NOTE: xmlSplitQName2 will return a duplicated
24858         * string.
24859         */
24860         local = xmlSplitQName2(value, &prefix);
24861         if (local == NULL)
24862             *localName = xmlDictLookup(vctxt->dict, value, -1);
24863         else {
24864             *localName = xmlDictLookup(vctxt->dict, local, -1);
24865             xmlFree(local);
24866         }
24867
24868         *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24869
24870         if (prefix != NULL) {
24871             xmlFree(prefix);
24872             /*
24873             * A namespace must be found if the prefix is NOT NULL.
24874             */
24875             if (*nsName == NULL) {
24876                 xmlSchemaCustomErr(ACTXT_CAST vctxt,
24877                     XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24878                     WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24879                     "The QName value '%s' has no "
24880                     "corresponding namespace declaration in scope",
24881                     value, NULL);
24882                 return (2);
24883             }
24884         }
24885     }
24886     return (0);
24887 }
24888
24889 static int
24890 xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24891                         xmlSchemaAttrInfoPtr iattr,
24892                         xmlSchemaTypePtr *localType,
24893                         xmlSchemaElementPtr elemDecl)
24894 {
24895     int ret = 0;
24896     /*
24897     * cvc-elt (3.3.4) : (4)
24898     * AND
24899     * Schema-Validity Assessment (Element) (cvc-assess-elt)
24900     *   (1.2.1.2.1) - (1.2.1.2.4)
24901     * Handle 'xsi:type'.
24902     */
24903     if (localType == NULL)
24904         return (-1);
24905     *localType = NULL;
24906     if (iattr == NULL)
24907         return (0);
24908     else {
24909         const xmlChar *nsName = NULL, *local = NULL;
24910         /*
24911         * TODO: We should report a *warning* that the type was overriden
24912         * by the instance.
24913         */
24914         ACTIVATE_ATTRIBUTE(iattr);
24915         /*
24916         * (cvc-elt) (3.3.4) : (4.1)
24917         * (cvc-assess-elt) (1.2.1.2.2)
24918         */
24919         ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24920             &nsName, &local);
24921         if (ret != 0) {
24922             if (ret < 0) {
24923                 VERROR_INT("xmlSchemaValidateElementByDeclaration",
24924                     "calling xmlSchemaQNameExpand() to validate the "
24925                     "attribute 'xsi:type'");
24926                 goto internal_error;
24927             }
24928             goto exit;
24929         }
24930         /*
24931         * (cvc-elt) (3.3.4) : (4.2)
24932         * (cvc-assess-elt) (1.2.1.2.3)
24933         */
24934         *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24935         if (*localType == NULL) {
24936             xmlChar *str = NULL;
24937
24938             xmlSchemaCustomErr(ACTXT_CAST vctxt,
24939                 XML_SCHEMAV_CVC_ELT_4_2, NULL,
24940                 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24941                 "The QName value '%s' of the xsi:type attribute does not "
24942                 "resolve to a type definition",
24943                 xmlSchemaFormatQName(&str, nsName, local), NULL);
24944             FREE_AND_NULL(str);
24945             ret = vctxt->err;
24946             goto exit;
24947         }
24948         if (elemDecl != NULL) {
24949             int set = 0;
24950
24951             /*
24952             * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
24953             * "The `local type definition` must be validly
24954             * derived from the {type definition} given the union of
24955             * the {disallowed substitutions} and the {type definition}'s
24956             * {prohibited substitutions}, as defined in
24957             * Type Derivation OK (Complex) ($3.4.6)
24958             * (if it is a complex type definition),
24959             * or given {disallowed substitutions} as defined in Type
24960             * Derivation OK (Simple) ($3.14.6) (if it is a simple type
24961             * definition)."
24962             *
24963             * {disallowed substitutions}: the "block" on the element decl.
24964             * {prohibited substitutions}: the "block" on the type def.
24965             */
24966             /*
24967             * OPTIMIZE TODO: We could map types already evaluated
24968             * to be validly derived from other types to avoid checking
24969             * this over and over for the same types.
24970             */
24971             if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24972                 (elemDecl->subtypes->flags &
24973                     XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24974                 set |= SUBSET_EXTENSION;
24975
24976             if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24977                 (elemDecl->subtypes->flags &
24978                     XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24979                 set |= SUBSET_RESTRICTION;
24980
24981             /*
24982             * REMOVED and CHANGED since this produced a parser context
24983             * which adds to the string dict of the schema. So this would
24984             * change the schema and we don't want this. We don't need
24985             * the parser context anymore.
24986             *
24987             * if ((vctxt->pctxt == NULL) &&
24988             *   (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24989             *       return (-1);
24990             */
24991
24992             if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
24993                 elemDecl->subtypes, set) != 0) {
24994                 xmlChar *str = NULL;
24995
24996                 xmlSchemaCustomErr(ACTXT_CAST vctxt,
24997                     XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24998                     "The type definition '%s', specified by xsi:type, is "
24999                     "blocked or not validly derived from the type definition "
25000                     "of the element declaration",
25001                     xmlSchemaFormatQName(&str,
25002                         (*localType)->targetNamespace,
25003                         (*localType)->name),
25004                     NULL);
25005                 FREE_AND_NULL(str);
25006                 ret = vctxt->err;
25007                 *localType = NULL;
25008             }
25009         }
25010     }
25011 exit:
25012     ACTIVATE_ELEM;
25013     return (ret);
25014 internal_error:
25015     ACTIVATE_ELEM;
25016     return (-1);
25017 }
25018
25019 static int
25020 xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
25021 {
25022     xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
25023     xmlSchemaTypePtr actualType;
25024
25025     /*
25026     * cvc-elt (3.3.4) : 1
25027     */
25028     if (elemDecl == NULL) {
25029         VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
25030             "No matching declaration available");
25031         return (vctxt->err);
25032     }
25033     actualType = WXS_ELEM_TYPEDEF(elemDecl);
25034     /*
25035     * cvc-elt (3.3.4) : 2
25036     */
25037     if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
25038         VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
25039             "The element declaration is abstract");
25040         return (vctxt->err);
25041     }
25042     if (actualType == NULL) {
25043         VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25044             "The type definition is absent");
25045         return (XML_SCHEMAV_CVC_TYPE_1);
25046     }
25047     if (vctxt->nbAttrInfos != 0) {
25048         int ret;
25049         xmlSchemaAttrInfoPtr iattr;
25050         /*
25051         * cvc-elt (3.3.4) : 3
25052         * Handle 'xsi:nil'.
25053         */
25054         iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25055             XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
25056         if (iattr) {
25057             ACTIVATE_ATTRIBUTE(iattr);
25058             /*
25059             * Validate the value.
25060             */
25061             ret = xmlSchemaVCheckCVCSimpleType(
25062                 ACTXT_CAST vctxt, NULL,
25063                 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
25064                 iattr->value, &(iattr->val), 1, 0, 0);
25065             ACTIVATE_ELEM;
25066             if (ret < 0) {
25067                 VERROR_INT("xmlSchemaValidateElemDecl",
25068                     "calling xmlSchemaVCheckCVCSimpleType() to "
25069                     "validate the attribute 'xsi:nil'");
25070                 return (-1);
25071             }
25072             if (ret == 0) {
25073                 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
25074                     /*
25075                     * cvc-elt (3.3.4) : 3.1
25076                     */
25077                     VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
25078                         "The element is not 'nillable'");
25079                     /* Does not return an error on purpose. */
25080                 } else {
25081                     if (xmlSchemaValueGetAsBoolean(iattr->val)) {
25082                         /*
25083                         * cvc-elt (3.3.4) : 3.2.2
25084                         */
25085                         if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
25086                             (elemDecl->value != NULL)) {
25087                             VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
25088                                 "The element cannot be 'nilled' because "
25089                                 "there is a fixed value constraint defined "
25090                                 "for it");
25091                              /* Does not return an error on purpose. */
25092                         } else
25093                             vctxt->inode->flags |=
25094                                 XML_SCHEMA_ELEM_INFO_NILLED;
25095                     }
25096                 }
25097             }
25098         }
25099         /*
25100         * cvc-elt (3.3.4) : 4
25101         * Handle 'xsi:type'.
25102         */
25103         iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25104             XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25105         if (iattr) {
25106             xmlSchemaTypePtr localType = NULL;
25107
25108             ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
25109                 elemDecl);
25110             if (ret != 0) {
25111                 if (ret == -1) {
25112                     VERROR_INT("xmlSchemaValidateElemDecl",
25113                         "calling xmlSchemaProcessXSIType() to "
25114                         "process the attribute 'xsi:type'");
25115                     return (-1);
25116                 }
25117                 /* Does not return an error on purpose. */
25118             }
25119             if (localType != NULL) {
25120                 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
25121                 actualType = localType;
25122             }
25123         }
25124     }
25125     /*
25126     * IDC: Register identity-constraint XPath matchers.
25127     */
25128     if ((elemDecl->idcs != NULL) &&
25129         (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
25130             return (-1);
25131     /*
25132     * No actual type definition.
25133     */
25134     if (actualType == NULL) {
25135         VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25136             "The type definition is absent");
25137         return (XML_SCHEMAV_CVC_TYPE_1);
25138     }
25139     /*
25140     * Remember the actual type definition.
25141     */
25142     vctxt->inode->typeDef = actualType;
25143
25144     return (0);
25145 }
25146
25147 static int
25148 xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
25149 {
25150     xmlSchemaAttrInfoPtr iattr;
25151     int ret = 0, i;
25152
25153     /*
25154     * SPEC cvc-type (3.1.1)
25155     * "The attributes of must be empty, excepting those whose namespace
25156     * name is identical to http://www.w3.org/2001/XMLSchema-instance and
25157     * whose local name is one of type, nil, schemaLocation or
25158     * noNamespaceSchemaLocation."
25159     */
25160     if (vctxt->nbAttrInfos == 0)
25161         return (0);
25162     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25163         iattr = vctxt->attrInfos[i];
25164         if (! iattr->metaType) {
25165             ACTIVATE_ATTRIBUTE(iattr)
25166             xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25167                 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
25168             ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
25169         }
25170     }
25171     ACTIVATE_ELEM
25172     return (ret);
25173 }
25174
25175 /*
25176 * Cleanup currently used attribute infos.
25177 */
25178 static void
25179 xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
25180 {
25181     int i;
25182     xmlSchemaAttrInfoPtr attr;
25183
25184     if (vctxt->nbAttrInfos == 0)
25185         return;
25186     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25187         attr = vctxt->attrInfos[i];
25188         if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
25189             if (attr->localName != NULL)
25190                 xmlFree((xmlChar *) attr->localName);
25191             if (attr->nsName != NULL)
25192                 xmlFree((xmlChar *) attr->nsName);
25193         }
25194         if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
25195             if (attr->value != NULL)
25196                 xmlFree((xmlChar *) attr->value);
25197         }
25198         if (attr->val != NULL) {
25199             xmlSchemaFreeValue(attr->val);
25200             attr->val = NULL;
25201         }
25202         memset(attr, 0, sizeof(xmlSchemaAttrInfo));
25203     }
25204     vctxt->nbAttrInfos = 0;
25205 }
25206
25207 /*
25208 * 3.4.4 Complex Type Definition Validation Rules
25209 *   Element Locally Valid (Complex Type) (cvc-complex-type)
25210 * 3.2.4 Attribute Declaration Validation Rules
25211 *   Validation Rule: Attribute Locally Valid (cvc-attribute)
25212 *   Attribute Locally Valid (Use) (cvc-au)
25213 *
25214 * Only "assessed" attribute information items will be visible to
25215 * IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
25216 */
25217 static int
25218 xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
25219 {
25220     xmlSchemaTypePtr type = vctxt->inode->typeDef;
25221     xmlSchemaItemListPtr attrUseList;
25222     xmlSchemaAttributeUsePtr attrUse = NULL;
25223     xmlSchemaAttributePtr attrDecl = NULL;
25224     xmlSchemaAttrInfoPtr iattr, tmpiattr;
25225     int i, j, found, nbAttrs, nbUses;
25226     int xpathRes = 0, res, wildIDs = 0, fixed;
25227     xmlNodePtr defAttrOwnerElem = NULL;
25228
25229     /*
25230     * SPEC (cvc-attribute)
25231     * (1) "The declaration must not be `absent` (see Missing
25232     * Sub-components ($5.3) for how this can fail to be
25233     * the case)."
25234     * (2) "Its {type definition} must not be absent."
25235     *
25236     * NOTE (1) + (2): This is not handled here, since we currently do not
25237     * allow validation against schemas which have missing sub-components.
25238     *
25239     * SPEC (cvc-complex-type)
25240     * (3) "For each attribute information item in the element information
25241     * item's [attributes] excepting those whose [namespace name] is
25242     * identical to http://www.w3.org/2001/XMLSchema-instance and whose
25243     * [local name] is one of type, nil, schemaLocation or
25244     * noNamespaceSchemaLocation, the appropriate case among the following
25245     * must be true:
25246     *
25247     */
25248     attrUseList = (xmlSchemaItemListPtr) type->attrUses;
25249     /*
25250     * @nbAttrs is the number of attributes present in the instance.
25251     */
25252     nbAttrs = vctxt->nbAttrInfos;
25253     if (attrUseList != NULL)
25254         nbUses = attrUseList->nbItems;
25255     else
25256         nbUses = 0;
25257     for (i = 0; i < nbUses; i++) {
25258         found = 0;
25259         attrUse = attrUseList->items[i];
25260         attrDecl = WXS_ATTRUSE_DECL(attrUse);
25261         for (j = 0; j < nbAttrs; j++) {
25262             iattr = vctxt->attrInfos[j];
25263             /*
25264             * SPEC (cvc-complex-type) (3)
25265             * Skip meta attributes.
25266             */
25267             if (iattr->metaType)
25268                 continue;
25269             if (iattr->localName[0] != attrDecl->name[0])
25270                 continue;
25271             if (!xmlStrEqual(iattr->localName, attrDecl->name))
25272                 continue;
25273             if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
25274                 continue;
25275             found = 1;
25276             /*
25277             * SPEC (cvc-complex-type)
25278             * (3.1) "If there is among the {attribute uses} an attribute
25279             * use with an {attribute declaration} whose {name} matches
25280             * the attribute information item's [local name] and whose
25281             * {target namespace} is identical to the attribute information
25282             * item's [namespace name] (where an `absent` {target namespace}
25283             * is taken to be identical to a [namespace name] with no value),
25284             * then the attribute information must be `valid` with respect
25285             * to that attribute use as per Attribute Locally Valid (Use)
25286             * ($3.5.4). In this case the {attribute declaration} of that
25287             * attribute use is the `context-determined declaration` for the
25288             * attribute information item with respect to Schema-Validity
25289             * Assessment (Attribute) ($3.2.4) and
25290             * Assessment Outcome (Attribute) ($3.2.5).
25291             */
25292             iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25293             iattr->use = attrUse;
25294             /*
25295             * Context-determined declaration.
25296             */
25297             iattr->decl = attrDecl;
25298             iattr->typeDef = attrDecl->subtypes;
25299             break;
25300         }
25301
25302         if (found)
25303             continue;
25304
25305         if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
25306             /*
25307             * Handle non-existent, required attributes.
25308             *
25309             * SPEC (cvc-complex-type)
25310             * (4) "The {attribute declaration} of each attribute use in
25311             * the {attribute uses} whose {required} is true matches one
25312             * of the attribute information items in the element information
25313             * item's [attributes] as per clause 3.1 above."
25314             */
25315             tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25316             if (tmpiattr == NULL) {
25317                 VERROR_INT(
25318                     "xmlSchemaVAttributesComplex",
25319                     "calling xmlSchemaGetFreshAttrInfo()");
25320                 return (-1);
25321             }
25322             tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
25323             tmpiattr->use = attrUse;
25324             tmpiattr->decl = attrDecl;
25325         } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
25326             ((attrUse->defValue != NULL) ||
25327              (attrDecl->defValue != NULL))) {
25328             /*
25329             * Handle non-existent, optional, default/fixed attributes.
25330             */
25331             tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25332             if (tmpiattr == NULL) {
25333                 VERROR_INT(
25334                     "xmlSchemaVAttributesComplex",
25335                     "calling xmlSchemaGetFreshAttrInfo()");
25336                 return (-1);
25337             }
25338             tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
25339             tmpiattr->use = attrUse;
25340             tmpiattr->decl = attrDecl;
25341             tmpiattr->typeDef = attrDecl->subtypes;
25342             tmpiattr->localName = attrDecl->name;
25343             tmpiattr->nsName = attrDecl->targetNamespace;
25344         }
25345     }
25346
25347     if (vctxt->nbAttrInfos == 0)
25348         return (0);
25349     /*
25350     * Validate against the wildcard.
25351     */
25352     if (type->attributeWildcard != NULL) {
25353         /*
25354         * SPEC (cvc-complex-type)
25355         * (3.2.1) "There must be an {attribute wildcard}."
25356         */
25357         for (i = 0; i < nbAttrs; i++) {
25358             iattr = vctxt->attrInfos[i];
25359             /*
25360             * SPEC (cvc-complex-type) (3)
25361             * Skip meta attributes.
25362             */
25363             if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
25364                 continue;
25365             /*
25366             * SPEC (cvc-complex-type)
25367             * (3.2.2) "The attribute information item must be `valid` with
25368             * respect to it as defined in Item Valid (Wildcard) ($3.10.4)."
25369             *
25370             * SPEC Item Valid (Wildcard) (cvc-wildcard)
25371             * "... its [namespace name] must be `valid` with respect to
25372             * the wildcard constraint, as defined in Wildcard allows
25373             * Namespace Name ($3.10.4)."
25374             */
25375             if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
25376                     iattr->nsName) == 0) {
25377                 /*
25378                 * Handle processContents.
25379                 *
25380                 * SPEC (cvc-wildcard):
25381                 * processContents | context-determined declaration:
25382                 * "strict"          "mustFind"
25383                 * "lax"             "none"
25384                 * "skip"            "skip"
25385                 */
25386                 if (type->attributeWildcard->processContents ==
25387                     XML_SCHEMAS_ANY_SKIP) {
25388                      /*
25389                     * context-determined declaration = "skip"
25390                     *
25391                     * SPEC PSVI Assessment Outcome (Attribute)
25392                     * [validity] = "notKnown"
25393                     * [validation attempted] = "none"
25394                     */
25395                     iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
25396                     continue;
25397                 }
25398                 /*
25399                 * Find an attribute declaration.
25400                 */
25401                 iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25402                     iattr->localName, iattr->nsName);
25403                 if (iattr->decl != NULL) {
25404                     iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25405                     /*
25406                     * SPEC (cvc-complex-type)
25407                     * (5) "Let [Definition:]  the wild IDs be the set of
25408                     * all attribute information item to which clause 3.2
25409                     * applied and whose `validation` resulted in a
25410                     * `context-determined declaration` of mustFind or no
25411                     * `context-determined declaration` at all, and whose
25412                     * [local name] and [namespace name] resolve (as
25413                     * defined by QName resolution (Instance) ($3.15.4)) to
25414                     * an attribute declaration whose {type definition} is
25415                     * or is derived from ID. Then all of the following
25416                     * must be true:"
25417                     */
25418                     iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
25419                     if (xmlSchemaIsDerivedFromBuiltInType(
25420                         iattr->typeDef, XML_SCHEMAS_ID)) {
25421                         /*
25422                         * SPEC (5.1) "There must be no more than one
25423                         * item in `wild IDs`."
25424                         */
25425                         if (wildIDs != 0) {
25426                             /* VAL TODO */
25427                             iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
25428                             TODO
25429                             continue;
25430                         }
25431                         wildIDs++;
25432                         /*
25433                         * SPEC (cvc-complex-type)
25434                         * (5.2) "If `wild IDs` is non-empty, there must not
25435                         * be any attribute uses among the {attribute uses}
25436                         * whose {attribute declaration}'s {type definition}
25437                         * is or is derived from ID."
25438                         */
25439                         if (attrUseList != NULL) {
25440                             for (j = 0; j < attrUseList->nbItems; j++) {
25441                                 if (xmlSchemaIsDerivedFromBuiltInType(
25442                                     WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25443                                     XML_SCHEMAS_ID)) {
25444                                     /* URGENT VAL TODO: implement */
25445                             iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25446                                     TODO
25447                                     break;
25448                                 }
25449                             }
25450                         }
25451                     }
25452                 } else if (type->attributeWildcard->processContents ==
25453                     XML_SCHEMAS_ANY_LAX) {
25454                     iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
25455                     /*
25456                     * SPEC PSVI Assessment Outcome (Attribute)
25457                     * [validity] = "notKnown"
25458                     * [validation attempted] = "none"
25459                     */
25460                 } else {
25461                     iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
25462                 }
25463             }
25464         }
25465     }
25466
25467     if (vctxt->nbAttrInfos == 0)
25468         return (0);
25469
25470     /*
25471     * Get the owner element; needed for creation of default attributes.
25472     * This fixes bug #341337, reported by David Grohmann.
25473     */
25474     if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25475         xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25476         if (ielem && ielem->node && ielem->node->doc)
25477             defAttrOwnerElem = ielem->node;
25478     }
25479     /*
25480     * Validate values, create default attributes, evaluate IDCs.
25481     */
25482     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25483         iattr = vctxt->attrInfos[i];
25484         /*
25485         * VAL TODO: Note that we won't try to resolve IDCs to
25486         * "lax" and "skip" validated attributes. Check what to
25487         * do in this case.
25488         */
25489         if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25490             (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
25491             continue;
25492         /*
25493         * VAL TODO: What to do if the type definition is missing?
25494         */
25495         if (iattr->typeDef == NULL) {
25496             iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
25497             continue;
25498         }
25499
25500         ACTIVATE_ATTRIBUTE(iattr);
25501         fixed = 0;
25502         xpathRes = 0;
25503
25504         if (vctxt->xpathStates != NULL) {
25505             /*
25506             * Evaluate IDCs.
25507             */
25508             xpathRes = xmlSchemaXPathEvaluate(vctxt,
25509                 XML_ATTRIBUTE_NODE);
25510             if (xpathRes == -1) {
25511                 VERROR_INT("xmlSchemaVAttributesComplex",
25512                     "calling xmlSchemaXPathEvaluate()");
25513                 goto internal_error;
25514             }
25515         }
25516
25517         if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
25518             /*
25519             * Default/fixed attributes.
25520             * We need the value only if we need to resolve IDCs or
25521             * will create default attributes.
25522             */
25523             if ((xpathRes) || (defAttrOwnerElem)) {
25524                 if (iattr->use->defValue != NULL) {
25525                     iattr->value = (xmlChar *) iattr->use->defValue;
25526                     iattr->val = iattr->use->defVal;
25527                 } else {
25528                     iattr->value = (xmlChar *) iattr->decl->defValue;
25529                     iattr->val = iattr->decl->defVal;
25530                 }
25531                 /*
25532                 * IDCs will consume the precomputed default value,
25533                 * so we need to clone it.
25534                 */
25535                 if (iattr->val == NULL) {
25536                     VERROR_INT("xmlSchemaVAttributesComplex",
25537                         "default/fixed value on an attribute use was "
25538                         "not precomputed");
25539                     goto internal_error;
25540                 }
25541                 iattr->val = xmlSchemaCopyValue(iattr->val);
25542                 if (iattr->val == NULL) {
25543                     VERROR_INT("xmlSchemaVAttributesComplex",
25544                         "calling xmlSchemaCopyValue()");
25545                     goto internal_error;
25546                 }
25547             }
25548             /*
25549             * PSVI: Add the default attribute to the current element.
25550             * VAL TODO: Should we use the *normalized* value? This currently
25551             *   uses the *initial* value.
25552             */
25553
25554             if (defAttrOwnerElem) {
25555                 xmlChar *normValue;
25556                 const xmlChar *value;
25557
25558                 value = iattr->value;
25559                 /*
25560                 * Normalize the value.
25561                 */
25562                 normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25563                     iattr->value);
25564                 if (normValue != NULL)
25565                     value = BAD_CAST normValue;
25566
25567                 if (iattr->nsName == NULL) {
25568                     if (xmlNewProp(defAttrOwnerElem,
25569                         iattr->localName, value) == NULL) {
25570                         VERROR_INT("xmlSchemaVAttributesComplex",
25571                             "calling xmlNewProp()");
25572                         if (normValue != NULL)
25573                             xmlFree(normValue);
25574                         goto internal_error;
25575                     }
25576                 } else {
25577                     xmlNsPtr ns;
25578
25579                     ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25580                         defAttrOwnerElem, iattr->nsName);
25581                     if (ns == NULL) {
25582                         xmlChar prefix[12];
25583                         int counter = 0;
25584
25585                         /*
25586                         * Create a namespace declaration on the validation
25587                         * root node if no namespace declaration is in scope.
25588                         */
25589                         do {
25590                             snprintf((char *) prefix, 12, "p%d", counter++);
25591                             ns = xmlSearchNs(defAttrOwnerElem->doc,
25592                                 defAttrOwnerElem, BAD_CAST prefix);
25593                             if (counter > 1000) {
25594                                 VERROR_INT(
25595                                     "xmlSchemaVAttributesComplex",
25596                                     "could not compute a ns prefix for a "
25597                                     "default/fixed attribute");
25598                                 if (normValue != NULL)
25599                                     xmlFree(normValue);
25600                                 goto internal_error;
25601                             }
25602                         } while (ns != NULL);
25603                         ns = xmlNewNs(vctxt->validationRoot,
25604                             iattr->nsName, BAD_CAST prefix);
25605                     }
25606                     /*
25607                     * TODO:
25608                     * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25609                     * If we have QNames: do we need to ensure there's a
25610                     * prefix defined for the QName?
25611                     */
25612                     xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
25613                 }
25614                 if (normValue != NULL)
25615                     xmlFree(normValue);
25616             }
25617             /*
25618             * Go directly to IDC evaluation.
25619             */
25620             goto eval_idcs;
25621         }
25622         /*
25623         * Validate the value.
25624         */
25625         if (vctxt->value != NULL) {
25626             /*
25627             * Free last computed value; just for safety reasons.
25628             */
25629             xmlSchemaFreeValue(vctxt->value);
25630             vctxt->value = NULL;
25631         }
25632         /*
25633         * Note that the attribute *use* can be unavailable, if
25634         * the attribute was a wild attribute.
25635         */
25636         if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25637             ((iattr->use != NULL) &&
25638              (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
25639             fixed = 1;
25640         else
25641             fixed = 0;
25642         /*
25643         * SPEC (cvc-attribute)
25644         * (3) "The item's `normalized value` must be locally `valid`
25645         * with respect to that {type definition} as per
25646         * String Valid ($3.14.4)."
25647         *
25648         * VAL TODO: Do we already have the
25649         * "normalized attribute value" here?
25650         */
25651         if (xpathRes || fixed) {
25652             iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
25653             /*
25654             * Request a computed value.
25655             */
25656             res = xmlSchemaVCheckCVCSimpleType(
25657                 ACTXT_CAST vctxt,
25658                 iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
25659                 1, 1, 0);
25660         } else {
25661             res = xmlSchemaVCheckCVCSimpleType(
25662                 ACTXT_CAST vctxt,
25663                 iattr->node, iattr->typeDef, iattr->value, NULL,
25664                 1, 0, 0);
25665         }
25666
25667         if (res != 0) {
25668             if (res == -1) {
25669                 VERROR_INT("xmlSchemaVAttributesComplex",
25670                     "calling xmlSchemaStreamValidateSimpleTypeValue()");
25671                 goto internal_error;
25672             }
25673             iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
25674             /*
25675             * SPEC PSVI Assessment Outcome (Attribute)
25676             * [validity] = "invalid"
25677             */
25678             goto eval_idcs;
25679         }
25680
25681         if (fixed) {
25682             /*
25683             * SPEC Attribute Locally Valid (Use) (cvc-au)
25684             * "For an attribute information item to be `valid`
25685             * with respect to an attribute use its *normalized*
25686             * value must match the *canonical* lexical
25687             * representation of the attribute use's {value
25688             * constraint}value, if it is present and fixed."
25689             *
25690             * VAL TODO: The requirement for the *canonical* value
25691             * will be removed in XML Schema 1.1.
25692             */
25693             /*
25694             * SPEC Attribute Locally Valid (cvc-attribute)
25695             * (4) "The item's *actual* value must match the *value* of
25696             * the {value constraint}, if it is present and fixed."
25697             */
25698             if (iattr->val == NULL) {
25699                 /* VAL TODO: A value was not precomputed. */
25700                 TODO
25701                 goto eval_idcs;
25702             }
25703             if ((iattr->use != NULL) &&
25704                 (iattr->use->defValue != NULL)) {
25705                 if (iattr->use->defVal == NULL) {
25706                     /* VAL TODO: A default value was not precomputed. */
25707                     TODO
25708                     goto eval_idcs;
25709                 }
25710                 iattr->vcValue = iattr->use->defValue;
25711                 /*
25712                 if (xmlSchemaCompareValuesWhtsp(attr->val,
25713                     (xmlSchemaWhitespaceValueType) ws,
25714                     attr->use->defVal,
25715                     (xmlSchemaWhitespaceValueType) ws) != 0) {
25716                 */
25717                 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25718                     iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25719             } else {
25720                 if (iattr->decl->defVal == NULL) {
25721                     /* VAL TODO: A default value was not precomputed. */
25722                     TODO
25723                     goto eval_idcs;
25724                 }
25725                 iattr->vcValue = iattr->decl->defValue;
25726                 /*
25727                 if (xmlSchemaCompareValuesWhtsp(attr->val,
25728                     (xmlSchemaWhitespaceValueType) ws,
25729                     attrDecl->defVal,
25730                     (xmlSchemaWhitespaceValueType) ws) != 0) {
25731                 */
25732                 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25733                     iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25734             }
25735             /*
25736             * [validity] = "valid"
25737             */
25738         }
25739 eval_idcs:
25740         /*
25741         * Evaluate IDCs.
25742         */
25743         if (xpathRes) {
25744             if (xmlSchemaXPathProcessHistory(vctxt,
25745                 vctxt->depth +1) == -1) {
25746                 VERROR_INT("xmlSchemaVAttributesComplex",
25747                     "calling xmlSchemaXPathEvaluate()");
25748                 goto internal_error;
25749             }
25750         } else if (vctxt->xpathStates != NULL)
25751             xmlSchemaXPathPop(vctxt);
25752     }
25753
25754     /*
25755     * Report errors.
25756     */
25757     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25758         iattr = vctxt->attrInfos[i];
25759         if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25760             (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25761             (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25762             (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
25763             continue;
25764         ACTIVATE_ATTRIBUTE(iattr);
25765         switch (iattr->state) {
25766             case XML_SCHEMAS_ATTR_ERR_MISSING: {
25767                     xmlChar *str = NULL;
25768                     ACTIVATE_ELEM;
25769                     xmlSchemaCustomErr(ACTXT_CAST vctxt,
25770                         XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25771                         "The attribute '%s' is required but missing",
25772                         xmlSchemaFormatQName(&str,
25773                             iattr->decl->targetNamespace,
25774                             iattr->decl->name),
25775                         NULL);
25776                     FREE_AND_NULL(str)
25777                     break;
25778                 }
25779             case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25780                 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25781                     "The type definition is absent");
25782                 break;
25783             case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
25784                 xmlSchemaCustomErr(ACTXT_CAST vctxt,
25785                     XML_SCHEMAV_CVC_AU, NULL, NULL,
25786                     "The value '%s' does not match the fixed "
25787                     "value constraint '%s'",
25788                     iattr->value, iattr->vcValue);
25789                 break;
25790             case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25791                 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25792                     "No matching global attribute declaration available, but "
25793                     "demanded by the strict wildcard");
25794                 break;
25795             case XML_SCHEMAS_ATTR_UNKNOWN:
25796                 if (iattr->metaType)
25797                     break;
25798                 /*
25799                 * MAYBE VAL TODO: One might report different error messages
25800                 * for the following errors.
25801                 */
25802                 if (type->attributeWildcard == NULL) {
25803                     xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25804                         XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
25805                 } else {
25806                     xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25807                         XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
25808                 }
25809                 break;
25810             default:
25811                 break;
25812         }
25813     }
25814
25815     ACTIVATE_ELEM;
25816     return (0);
25817 internal_error:
25818     ACTIVATE_ELEM;
25819     return (-1);
25820 }
25821
25822 static int
25823 xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25824                               int *skip)
25825 {
25826     xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25827     /*
25828     * The namespace of the element was already identified to be
25829     * matching the wildcard.
25830     */
25831     if ((skip == NULL) || (wild == NULL) ||
25832         (wild->type != XML_SCHEMA_TYPE_ANY)) {
25833         VERROR_INT("xmlSchemaValidateElemWildcard",
25834             "bad arguments");
25835         return (-1);
25836     }
25837     *skip = 0;
25838     if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25839         /*
25840         * URGENT VAL TODO: Either we need to position the stream to the
25841         * next sibling, or walk the whole subtree.
25842         */
25843         *skip = 1;
25844         return (0);
25845     }
25846     {
25847         xmlSchemaElementPtr decl = NULL;
25848
25849         decl = xmlSchemaGetElem(vctxt->schema,
25850             vctxt->inode->localName, vctxt->inode->nsName);
25851         if (decl != NULL) {
25852             vctxt->inode->decl = decl;
25853             return (0);
25854         }
25855     }
25856     if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25857         /* VAL TODO: Change to proper error code. */
25858         VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
25859             "No matching global element declaration available, but "
25860             "demanded by the strict wildcard");
25861         return (vctxt->err);
25862     }
25863     if (vctxt->nbAttrInfos != 0) {
25864         xmlSchemaAttrInfoPtr iattr;
25865         /*
25866         * SPEC Validation Rule: Schema-Validity Assessment (Element)
25867         * (1.2.1.2.1) - (1.2.1.2.3 )
25868         *
25869         * Use the xsi:type attribute for the type definition.
25870         */
25871         iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25872             XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25873         if (iattr != NULL) {
25874             if (xmlSchemaProcessXSIType(vctxt, iattr,
25875                 &(vctxt->inode->typeDef), NULL) == -1) {
25876                 VERROR_INT("xmlSchemaValidateElemWildcard",
25877                     "calling xmlSchemaProcessXSIType() to "
25878                     "process the attribute 'xsi:nil'");
25879                 return (-1);
25880             }
25881             /*
25882             * Don't return an error on purpose.
25883             */
25884             return (0);
25885         }
25886     }
25887     /*
25888     * SPEC Validation Rule: Schema-Validity Assessment (Element)
25889     *
25890     * Fallback to "anyType".
25891     */
25892     vctxt->inode->typeDef =
25893         xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25894     return (0);
25895 }
25896
25897 /*
25898 * xmlSchemaCheckCOSValidDefault:
25899 *
25900 * This will be called if: not nilled, no content and a default/fixed
25901 * value is provided.
25902 */
25903
25904 static int
25905 xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25906                               const xmlChar *value,
25907                               xmlSchemaValPtr *val)
25908 {
25909     int ret = 0;
25910     xmlSchemaNodeInfoPtr inode = vctxt->inode;
25911
25912     /*
25913     * cos-valid-default:
25914     * Schema Component Constraint: Element Default Valid (Immediate)
25915     * For a string to be a valid default with respect to a type
25916     * definition the appropriate case among the following must be true:
25917     */
25918     if WXS_IS_COMPLEX(inode->typeDef) {
25919         /*
25920         * Complex type.
25921         *
25922         * SPEC (2.1) "its {content type} must be a simple type definition
25923         * or mixed."
25924         * SPEC (2.2.2) "If the {content type} is mixed, then the {content
25925         * type}'s particle must be `emptiable` as defined by
25926         * Particle Emptiable ($3.9.6)."
25927         */
25928         if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25929             ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25930              (! WXS_EMPTIABLE(inode->typeDef)))) {
25931             ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25932             /* NOTE that this covers (2.2.2) as well. */
25933             VERROR(ret, NULL,
25934                 "For a string to be a valid default, the type definition "
25935                 "must be a simple type or a complex type with simple content "
25936                 "or mixed content and a particle emptiable");
25937             return(ret);
25938         }
25939     }
25940     /*
25941     * 1 If the type definition is a simple type definition, then the string
25942     * must be `valid` with respect to that definition as defined by String
25943     * Valid ($3.14.4).
25944     *
25945     * AND
25946     *
25947     * 2.2.1 If the {content type} is a simple type definition, then the
25948     * string must be `valid` with respect to that simple type definition
25949     * as defined by String Valid ($3.14.4).
25950     */
25951     if (WXS_IS_SIMPLE(inode->typeDef)) {
25952
25953         ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25954             NULL, inode->typeDef, value, val, 1, 1, 0);
25955
25956     } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
25957
25958         ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25959             NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25960     }
25961     if (ret < 0) {
25962         VERROR_INT("xmlSchemaCheckCOSValidDefault",
25963             "calling xmlSchemaVCheckCVCSimpleType()");
25964     }
25965     return (ret);
25966 }
25967
25968 static void
25969 xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
25970                                const xmlChar * name ATTRIBUTE_UNUSED,
25971                                xmlSchemaElementPtr item,
25972                                xmlSchemaNodeInfoPtr inode)
25973 {
25974     inode->decl = item;
25975 #ifdef DEBUG_CONTENT
25976     {
25977         xmlChar *str = NULL;
25978
25979         if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
25980             xmlGenericError(xmlGenericErrorContext,
25981                 "AUTOMATON callback for '%s' [declaration]\n",
25982                 xmlSchemaFormatQName(&str,
25983                 inode->localName, inode->nsName));
25984         } else {
25985             xmlGenericError(xmlGenericErrorContext,
25986                     "AUTOMATON callback for '%s' [wildcard]\n",
25987                     xmlSchemaFormatQName(&str,
25988                     inode->localName, inode->nsName));
25989
25990         }
25991         FREE_AND_NULL(str)
25992     }
25993 #endif
25994 }
25995
25996 static int
25997 xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
25998 {
25999     vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
26000     if (vctxt->inode == NULL) {
26001         VERROR_INT("xmlSchemaValidatorPushElem",
26002             "calling xmlSchemaGetFreshElemInfo()");
26003         return (-1);
26004     }
26005     vctxt->nbAttrInfos = 0;
26006     return (0);
26007 }
26008
26009 static int
26010 xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
26011                              xmlSchemaNodeInfoPtr inode,
26012                              xmlSchemaTypePtr type,
26013                              const xmlChar *value)
26014 {
26015     if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
26016         return (xmlSchemaVCheckCVCSimpleType(
26017             ACTXT_CAST vctxt, NULL,
26018             type, value, &(inode->val), 1, 1, 0));
26019     else
26020         return (xmlSchemaVCheckCVCSimpleType(
26021             ACTXT_CAST vctxt, NULL,
26022             type, value, NULL, 1, 0, 0));
26023 }
26024
26025
26026
26027 /*
26028 * Process END of element.
26029 */
26030 static int
26031 xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
26032 {
26033     int ret = 0;
26034     xmlSchemaNodeInfoPtr inode = vctxt->inode;
26035
26036     if (vctxt->nbAttrInfos != 0)
26037         xmlSchemaClearAttrInfos(vctxt);
26038     if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
26039         /*
26040         * This element was not expected;
26041         * we will not validate child elements of broken parents.
26042         * Skip validation of all content of the parent.
26043         */
26044         vctxt->skipDepth = vctxt->depth -1;
26045         goto end_elem;
26046     }
26047     if ((inode->typeDef == NULL) ||
26048         (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
26049         /*
26050         * 1. the type definition might be missing if the element was
26051         *    error prone
26052         * 2. it might be abstract.
26053         */
26054         goto end_elem;
26055     }
26056     /*
26057     * Check the content model.
26058     */
26059     if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
26060         (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
26061
26062         /*
26063         * Workaround for "anyType".
26064         */
26065         if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
26066             goto character_content;
26067
26068         if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
26069             xmlChar *values[10];
26070             int terminal, nbval = 10, nbneg;
26071
26072             if (inode->regexCtxt == NULL) {
26073                 /*
26074                 * Create the regex context.
26075                 */
26076                 inode->regexCtxt =
26077                     xmlRegNewExecCtxt(inode->typeDef->contModel,
26078                     (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26079                     vctxt);
26080                 if (inode->regexCtxt == NULL) {
26081                     VERROR_INT("xmlSchemaValidatorPopElem",
26082                         "failed to create a regex context");
26083                     goto internal_error;
26084                 }
26085 #ifdef DEBUG_AUTOMATA
26086                 xmlGenericError(xmlGenericErrorContext,
26087                     "AUTOMATON create on '%s'\n", inode->localName);
26088 #endif
26089             }
26090
26091             /*
26092              * Do not check further content if the node has been nilled
26093              */
26094             if (INODE_NILLED(inode)) {
26095                 ret = 0;
26096 #ifdef DEBUG_AUTOMATA
26097                 xmlGenericError(xmlGenericErrorContext,
26098                     "AUTOMATON succeeded on nilled '%s'\n",
26099                     inode->localName);
26100 #endif
26101                 goto skip_nilled;
26102             }
26103
26104             /*
26105             * Get hold of the still expected content, since a further
26106             * call to xmlRegExecPushString() will lose this information.
26107             */
26108             xmlRegExecNextValues(inode->regexCtxt,
26109                 &nbval, &nbneg, &values[0], &terminal);
26110             ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
26111             if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) {
26112                 /*
26113                 * Still missing something.
26114                 */
26115                 ret = 1;
26116                 inode->flags |=
26117                     XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26118                 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26119                     XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
26120                     "Missing child element(s)",
26121                     nbval, nbneg, values);
26122 #ifdef DEBUG_AUTOMATA
26123                 xmlGenericError(xmlGenericErrorContext,
26124                     "AUTOMATON missing ERROR on '%s'\n",
26125                     inode->localName);
26126 #endif
26127             } else {
26128                 /*
26129                 * Content model is satisfied.
26130                 */
26131                 ret = 0;
26132 #ifdef DEBUG_AUTOMATA
26133                 xmlGenericError(xmlGenericErrorContext,
26134                     "AUTOMATON succeeded on '%s'\n",
26135                     inode->localName);
26136 #endif
26137             }
26138
26139         }
26140     }
26141
26142 skip_nilled:
26143
26144     if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
26145         goto end_elem;
26146
26147 character_content:
26148
26149     if (vctxt->value != NULL) {
26150         xmlSchemaFreeValue(vctxt->value);
26151         vctxt->value = NULL;
26152     }
26153     /*
26154     * Check character content.
26155     */
26156     if (inode->decl == NULL) {
26157         /*
26158         * Speedup if no declaration exists.
26159         */
26160         if (WXS_IS_SIMPLE(inode->typeDef)) {
26161             ret = xmlSchemaVCheckINodeDataType(vctxt,
26162                 inode, inode->typeDef, inode->value);
26163         } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26164             ret = xmlSchemaVCheckINodeDataType(vctxt,
26165                 inode, inode->typeDef->contentTypeDef,
26166                 inode->value);
26167         }
26168         if (ret < 0) {
26169             VERROR_INT("xmlSchemaValidatorPopElem",
26170                 "calling xmlSchemaVCheckCVCSimpleType()");
26171             goto internal_error;
26172         }
26173         goto end_elem;
26174     }
26175     /*
26176     * cvc-elt (3.3.4) : 5
26177     * The appropriate case among the following must be true:
26178     */
26179     /*
26180     * cvc-elt (3.3.4) : 5.1
26181     * If the declaration has a {value constraint},
26182     * the item has neither element nor character [children] and
26183     * clause 3.2 has not applied, then all of the following must be true:
26184     */
26185     if ((inode->decl->value != NULL) &&
26186         (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
26187         (! INODE_NILLED(inode))) {
26188         /*
26189         * cvc-elt (3.3.4) : 5.1.1
26190         * If the `actual type definition` is a `local type definition`
26191         * then the canonical lexical representation of the {value constraint}
26192         * value must be a valid default for the `actual type definition` as
26193         * defined in Element Default Valid (Immediate) ($3.3.6).
26194         */
26195         /*
26196         * NOTE: 'local' above means types acquired by xsi:type.
26197         * NOTE: Although the *canonical* value is stated, it is not
26198         * relevant if canonical or not. Additionally XML Schema 1.1
26199         * will removed this requirement as well.
26200         */
26201         if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
26202
26203             ret = xmlSchemaCheckCOSValidDefault(vctxt,
26204                 inode->decl->value, &(inode->val));
26205             if (ret != 0) {
26206                 if (ret < 0) {
26207                     VERROR_INT("xmlSchemaValidatorPopElem",
26208                         "calling xmlSchemaCheckCOSValidDefault()");
26209                     goto internal_error;
26210                 }
26211                 goto end_elem;
26212             }
26213             /*
26214             * Stop here, to avoid redundant validation of the value
26215             * (see following).
26216             */
26217             goto default_psvi;
26218         }
26219         /*
26220         * cvc-elt (3.3.4) : 5.1.2
26221         * The element information item with the canonical lexical
26222         * representation of the {value constraint} value used as its
26223         * `normalized value` must be `valid` with respect to the
26224         * `actual type definition` as defined by Element Locally Valid (Type)
26225         * ($3.3.4).
26226         */
26227         if (WXS_IS_SIMPLE(inode->typeDef)) {
26228             ret = xmlSchemaVCheckINodeDataType(vctxt,
26229                 inode, inode->typeDef, inode->decl->value);
26230         } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26231             ret = xmlSchemaVCheckINodeDataType(vctxt,
26232                 inode, inode->typeDef->contentTypeDef,
26233                 inode->decl->value);
26234         }
26235         if (ret != 0) {
26236             if (ret < 0) {
26237                 VERROR_INT("xmlSchemaValidatorPopElem",
26238                     "calling xmlSchemaVCheckCVCSimpleType()");
26239                 goto internal_error;
26240             }
26241             goto end_elem;
26242         }
26243
26244 default_psvi:
26245         /*
26246         * PSVI: Create a text node on the instance element.
26247         */
26248         if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
26249             (inode->node != NULL)) {
26250             xmlNodePtr textChild;
26251             xmlChar *normValue;
26252             /*
26253             * VAL TODO: Normalize the value.
26254             */
26255             normValue = xmlSchemaNormalizeValue(inode->typeDef,
26256                 inode->decl->value);
26257             if (normValue != NULL) {
26258                 textChild = xmlNewText(BAD_CAST normValue);
26259                 xmlFree(normValue);
26260             } else
26261                 textChild = xmlNewText(inode->decl->value);
26262             if (textChild == NULL) {
26263                 VERROR_INT("xmlSchemaValidatorPopElem",
26264                     "calling xmlNewText()");
26265                 goto internal_error;
26266             } else
26267                 xmlAddChild(inode->node, textChild);
26268         }
26269
26270     } else if (! INODE_NILLED(inode)) {
26271         /*
26272         * 5.2.1 The element information item must be `valid` with respect
26273         * to the `actual type definition` as defined by Element Locally
26274         * Valid (Type) ($3.3.4).
26275         */
26276         if (WXS_IS_SIMPLE(inode->typeDef)) {
26277              /*
26278             * SPEC (cvc-type) (3.1)
26279             * "If the type definition is a simple type definition, ..."
26280             * (3.1.3) "If clause 3.2 of Element Locally Valid
26281             * (Element) ($3.3.4) did not apply, then the `normalized value`
26282             * must be `valid` with respect to the type definition as defined
26283             * by String Valid ($3.14.4).
26284             */
26285             ret = xmlSchemaVCheckINodeDataType(vctxt,
26286                     inode, inode->typeDef, inode->value);
26287         } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26288             /*
26289             * SPEC (cvc-type) (3.2) "If the type definition is a complex type
26290             * definition, then the element information item must be
26291             * `valid` with respect to the type definition as per
26292             * Element Locally Valid (Complex Type) ($3.4.4);"
26293             *
26294             * SPEC (cvc-complex-type) (2.2)
26295             * "If the {content type} is a simple type definition, ...
26296             * the `normalized value` of the element information item is
26297             * `valid` with respect to that simple type definition as
26298             * defined by String Valid ($3.14.4)."
26299             */
26300             ret = xmlSchemaVCheckINodeDataType(vctxt,
26301                 inode, inode->typeDef->contentTypeDef, inode->value);
26302         }
26303         if (ret != 0) {
26304             if (ret < 0) {
26305                 VERROR_INT("xmlSchemaValidatorPopElem",
26306                     "calling xmlSchemaVCheckCVCSimpleType()");
26307                 goto internal_error;
26308             }
26309             goto end_elem;
26310         }
26311         /*
26312         * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
26313         * not applied, all of the following must be true:
26314         */
26315         if ((inode->decl->value != NULL) &&
26316             (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
26317
26318             /*
26319             * TODO: We will need a computed value, when comparison is
26320             * done on computed values.
26321             */
26322             /*
26323             * 5.2.2.1 The element information item must have no element
26324             * information item [children].
26325             */
26326             if (inode->flags &
26327                     XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
26328                 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
26329                 VERROR(ret, NULL,
26330                     "The content must not containt element nodes since "
26331                     "there is a fixed value constraint");
26332                 goto end_elem;
26333             } else {
26334                 /*
26335                 * 5.2.2.2 The appropriate case among the following must
26336                 * be true:
26337                 */
26338                 if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
26339                     /*
26340                     * 5.2.2.2.1 If the {content type} of the `actual type
26341                     * definition` is mixed, then the *initial value* of the
26342                     * item must match the canonical lexical representation
26343                     * of the {value constraint} value.
26344                     *
26345                     * ... the *initial value* of an element information
26346                     * item is the string composed of, in order, the
26347                     * [character code] of each character information item in
26348                     * the [children] of that element information item.
26349                     */
26350                     if (! xmlStrEqual(inode->value, inode->decl->value)){
26351                         /*
26352                         * VAL TODO: Report invalid & expected values as well.
26353                         * VAL TODO: Implement the canonical stuff.
26354                         */
26355                         ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
26356                         xmlSchemaCustomErr(ACTXT_CAST vctxt,
26357                             ret, NULL, NULL,
26358                             "The initial value '%s' does not match the fixed "
26359                             "value constraint '%s'",
26360                             inode->value, inode->decl->value);
26361                         goto end_elem;
26362                     }
26363                 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26364                     /*
26365                     * 5.2.2.2.2 If the {content type} of the `actual type
26366                     * definition` is a simple type definition, then the
26367                     * *actual value* of the item must match the canonical
26368                     * lexical representation of the {value constraint} value.
26369                     */
26370                     /*
26371                     * VAL TODO: *actual value* is the normalized value, impl.
26372                     *           this.
26373                     * VAL TODO: Report invalid & expected values as well.
26374                     * VAL TODO: Implement a comparison with the computed values.
26375                     */
26376                     if (! xmlStrEqual(inode->value,
26377                             inode->decl->value)) {
26378                         ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
26379                         xmlSchemaCustomErr(ACTXT_CAST vctxt,
26380                             ret, NULL, NULL,
26381                             "The actual value '%s' does not match the fixed "
26382                             "value constraint '%s'",
26383                             inode->value,
26384                             inode->decl->value);
26385                         goto end_elem;
26386                     }
26387                 }
26388             }
26389         }
26390     }
26391
26392 end_elem:
26393     if (vctxt->depth < 0) {
26394         /* TODO: raise error? */
26395         return (0);
26396     }
26397     if (vctxt->depth == vctxt->skipDepth)
26398         vctxt->skipDepth = -1;
26399     /*
26400     * Evaluate the history of XPath state objects.
26401     */
26402     if (inode->appliedXPath &&
26403         (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
26404         goto internal_error;
26405     /*
26406     * MAYBE TODO:
26407     * SPEC (6) "The element information item must be `valid` with
26408     * respect to each of the {identity-constraint definitions} as per
26409     * Identity-constraint Satisfied ($3.11.4)."
26410     */
26411     /*
26412     * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26413     *   need to be built in any case.
26414     *   We will currently build IDC node-tables and bubble them only if
26415     *   keyrefs do exist.
26416     */
26417
26418     /*
26419     * Add the current IDC target-nodes to the IDC node-tables.
26420     */
26421     if ((inode->idcMatchers != NULL) &&
26422         (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26423     {
26424         if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26425             goto internal_error;
26426     }
26427     /*
26428     * Validate IDC keyrefs.
26429     */
26430     if (vctxt->inode->hasKeyrefs)
26431         if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26432             goto internal_error;
26433     /*
26434     * Merge/free the IDC table.
26435     */
26436     if (inode->idcTable != NULL) {
26437 #ifdef DEBUG_IDC_NODE_TABLE
26438         xmlSchemaDebugDumpIDCTable(stdout,
26439             inode->nsName,
26440             inode->localName,
26441             inode->idcTable);
26442 #endif
26443         if ((vctxt->depth > 0) &&
26444             (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26445         {
26446             /*
26447             * Merge the IDC node table with the table of the parent node.
26448             */
26449             if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26450                 goto internal_error;
26451         }
26452     }
26453     /*
26454     * Clear the current ielem.
26455     * VAL TODO: Don't free the PSVI IDC tables if they are
26456     * requested for the PSVI.
26457     */
26458     xmlSchemaClearElemInfo(vctxt, inode);
26459     /*
26460     * Skip further processing if we are on the validation root.
26461     */
26462     if (vctxt->depth == 0) {
26463         vctxt->depth--;
26464         vctxt->inode = NULL;
26465         return (0);
26466     }
26467     /*
26468     * Reset the keyrefDepth if needed.
26469     */
26470     if (vctxt->aidcs != NULL) {
26471         xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26472         do {
26473             if (aidc->keyrefDepth == vctxt->depth) {
26474                 /*
26475                 * A 'keyrefDepth' of a key/unique IDC matches the current
26476                 * depth, this means that we are leaving the scope of the
26477                 * top-most keyref IDC which refers to this IDC.
26478                 */
26479                 aidc->keyrefDepth = -1;
26480             }
26481             aidc = aidc->next;
26482         } while (aidc != NULL);
26483     }
26484     vctxt->depth--;
26485     vctxt->inode = vctxt->elemInfos[vctxt->depth];
26486     /*
26487     * VAL TODO: 7 If the element information item is the `validation root`, it must be
26488     * `valid` per Validation Root Valid (ID/IDREF) ($3.3.4).
26489     */
26490     return (ret);
26491
26492 internal_error:
26493     vctxt->err = -1;
26494     return (-1);
26495 }
26496
26497 /*
26498 * 3.4.4 Complex Type Definition Validation Rules
26499 * Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26500 */
26501 static int
26502 xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
26503 {
26504     xmlSchemaNodeInfoPtr pielem;
26505     xmlSchemaTypePtr ptype;
26506     int ret = 0;
26507
26508     if (vctxt->depth <= 0) {
26509         VERROR_INT("xmlSchemaValidateChildElem",
26510             "not intended for the validation root");
26511         return (-1);
26512     }
26513     pielem = vctxt->elemInfos[vctxt->depth -1];
26514     if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26515         pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26516     /*
26517     * Handle 'nilled' elements.
26518     */
26519     if (INODE_NILLED(pielem)) {
26520         /*
26521         * SPEC (cvc-elt) (3.3.4) : (3.2.1)
26522         */
26523         ACTIVATE_PARENT_ELEM;
26524         ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26525         VERROR(ret, NULL,
26526             "Neither character nor element content is allowed, "
26527             "because the element was 'nilled'");
26528         ACTIVATE_ELEM;
26529         goto unexpected_elem;
26530     }
26531
26532     ptype = pielem->typeDef;
26533
26534     if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26535         /*
26536         * Workaround for "anyType": we have currently no content model
26537         * assigned for "anyType", so handle it explicitely.
26538         * "anyType" has an unbounded, lax "any" wildcard.
26539         */
26540         vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26541             vctxt->inode->localName,
26542             vctxt->inode->nsName);
26543
26544         if (vctxt->inode->decl == NULL) {
26545             xmlSchemaAttrInfoPtr iattr;
26546             /*
26547             * Process "xsi:type".
26548             * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
26549             */
26550             iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26551                 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26552             if (iattr != NULL) {
26553                 ret = xmlSchemaProcessXSIType(vctxt, iattr,
26554                     &(vctxt->inode->typeDef), NULL);
26555                 if (ret != 0) {
26556                     if (ret == -1) {
26557                         VERROR_INT("xmlSchemaValidateChildElem",
26558                             "calling xmlSchemaProcessXSIType() to "
26559                             "process the attribute 'xsi:nil'");
26560                         return (-1);
26561                     }
26562                     return (ret);
26563                 }
26564             } else {
26565                  /*
26566                  * Fallback to "anyType".
26567                  *
26568                  * SPEC (cvc-assess-elt)
26569                  * "If the item cannot be `strictly assessed`, [...]
26570                  * an element information item's schema validity may be laxly
26571                  * assessed if its `context-determined declaration` is not
26572                  * skip by `validating` with respect to the `ur-type
26573                  * definition` as per Element Locally Valid (Type) ($3.3.4)."
26574                 */
26575                 vctxt->inode->typeDef =
26576                     xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26577             }
26578         }
26579         return (0);
26580     }
26581
26582     switch (ptype->contentType) {
26583         case XML_SCHEMA_CONTENT_EMPTY:
26584             /*
26585             * SPEC (2.1) "If the {content type} is empty, then the
26586             * element information item has no character or element
26587             * information item [children]."
26588             */
26589             ACTIVATE_PARENT_ELEM
26590             ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26591             VERROR(ret, NULL,
26592                 "Element content is not allowed, "
26593                 "because the content type is empty");
26594             ACTIVATE_ELEM
26595             goto unexpected_elem;
26596             break;
26597
26598         case XML_SCHEMA_CONTENT_MIXED:
26599         case XML_SCHEMA_CONTENT_ELEMENTS: {
26600             xmlRegExecCtxtPtr regexCtxt;
26601             xmlChar *values[10];
26602             int terminal, nbval = 10, nbneg;
26603
26604             /* VAL TODO: Optimized "anyType" validation.*/
26605
26606             if (ptype->contModel == NULL) {
26607                 VERROR_INT("xmlSchemaValidateChildElem",
26608                     "type has elem content but no content model");
26609                 return (-1);
26610             }
26611             /*
26612             * Safety belf for evaluation if the cont. model was already
26613             * examined to be invalid.
26614             */
26615             if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26616                 VERROR_INT("xmlSchemaValidateChildElem",
26617                     "validating elem, but elem content is already invalid");
26618                 return (-1);
26619             }
26620
26621             regexCtxt = pielem->regexCtxt;
26622             if (regexCtxt == NULL) {
26623                 /*
26624                 * Create the regex context.
26625                 */
26626                 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26627                     (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26628                     vctxt);
26629                 if (regexCtxt == NULL) {
26630                     VERROR_INT("xmlSchemaValidateChildElem",
26631                         "failed to create a regex context");
26632                     return (-1);
26633                 }
26634                 pielem->regexCtxt = regexCtxt;
26635 #ifdef DEBUG_AUTOMATA
26636                 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26637                     pielem->localName);
26638 #endif
26639             }
26640
26641             /*
26642             * SPEC (2.4) "If the {content type} is element-only or mixed,
26643             * then the sequence of the element information item's
26644             * element information item [children], if any, taken in
26645             * order, is `valid` with respect to the {content type}'s
26646             * particle, as defined in Element Sequence Locally Valid
26647             * (Particle) ($3.9.4)."
26648             */
26649             ret = xmlRegExecPushString2(regexCtxt,
26650                 vctxt->inode->localName,
26651                 vctxt->inode->nsName,
26652                 vctxt->inode);
26653 #ifdef DEBUG_AUTOMATA
26654             if (ret < 0)
26655                 xmlGenericError(xmlGenericErrorContext,
26656                 "AUTOMATON push ERROR for '%s' on '%s'\n",
26657                 vctxt->inode->localName, pielem->localName);
26658             else
26659                 xmlGenericError(xmlGenericErrorContext,
26660                 "AUTOMATON push OK for '%s' on '%s'\n",
26661                 vctxt->inode->localName, pielem->localName);
26662 #endif
26663             if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26664                 VERROR_INT("xmlSchemaValidateChildElem",
26665                     "calling xmlRegExecPushString2()");
26666                 return (-1);
26667             }
26668             if (ret < 0) {
26669                 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26670                     &values[0], &terminal);
26671                 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26672                     XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26673                     "This element is not expected",
26674                     nbval, nbneg, values);
26675                 ret = vctxt->err;
26676                 goto unexpected_elem;
26677             } else
26678                 ret = 0;
26679         }
26680             break;
26681         case XML_SCHEMA_CONTENT_SIMPLE:
26682         case XML_SCHEMA_CONTENT_BASIC:
26683             ACTIVATE_PARENT_ELEM
26684             if (WXS_IS_COMPLEX(ptype)) {
26685                 /*
26686                 * SPEC (cvc-complex-type) (2.2)
26687                 * "If the {content type} is a simple type definition, then
26688                 * the element information item has no element information
26689                 * item [children], ..."
26690                 */
26691                 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26692                 VERROR(ret, NULL, "Element content is not allowed, "
26693                     "because the content type is a simple type definition");
26694             } else {
26695                 /*
26696                 * SPEC (cvc-type) (3.1.2) "The element information item must
26697                 * have no element information item [children]."
26698                 */
26699                 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26700                 VERROR(ret, NULL, "Element content is not allowed, "
26701                     "because the type definition is simple");
26702             }
26703             ACTIVATE_ELEM
26704             ret = vctxt->err;
26705             goto unexpected_elem;
26706             break;
26707
26708         default:
26709             break;
26710     }
26711     return (ret);
26712 unexpected_elem:
26713     /*
26714     * Pop this element and set the skipDepth to skip
26715     * all further content of the parent element.
26716     */
26717     vctxt->skipDepth = vctxt->depth;
26718     vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26719     pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26720     return (ret);
26721 }
26722
26723 #define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26724 #define XML_SCHEMA_PUSH_TEXT_CREATED 2
26725 #define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26726
26727 static int
26728 xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26729                   int nodeType, const xmlChar *value, int len,
26730                   int mode, int *consumed)
26731 {
26732     /*
26733     * Unfortunately we have to duplicate the text sometimes.
26734     * OPTIMIZE: Maybe we could skip it, if:
26735     *   1. content type is simple
26736     *   2. whitespace is "collapse"
26737     *   3. it consists of whitespace only
26738     *
26739     * Process character content.
26740     */
26741     if (consumed != NULL)
26742         *consumed = 0;
26743     if (INODE_NILLED(vctxt->inode)) {
26744         /*
26745         * SPEC cvc-elt (3.3.4 - 3.2.1)
26746         * "The element information item must have no character or
26747         * element information item [children]."
26748         */
26749         VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26750             "Neither character nor element content is allowed "
26751             "because the element is 'nilled'");
26752         return (vctxt->err);
26753     }
26754     /*
26755     * SPEC (2.1) "If the {content type} is empty, then the
26756     * element information item has no character or element
26757     * information item [children]."
26758     */
26759     if (vctxt->inode->typeDef->contentType ==
26760             XML_SCHEMA_CONTENT_EMPTY) {
26761         VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26762             "Character content is not allowed, "
26763             "because the content type is empty");
26764         return (vctxt->err);
26765     }
26766
26767     if (vctxt->inode->typeDef->contentType ==
26768             XML_SCHEMA_CONTENT_ELEMENTS) {
26769         if ((nodeType != XML_TEXT_NODE) ||
26770             (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26771             /*
26772             * SPEC cvc-complex-type (2.3)
26773             * "If the {content type} is element-only, then the
26774             * element information item has no character information
26775             * item [children] other than those whose [character
26776             * code] is defined as a white space in [XML 1.0 (Second
26777             * Edition)]."
26778             */
26779             VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26780                 "Character content other than whitespace is not allowed "
26781                 "because the content type is 'element-only'");
26782             return (vctxt->err);
26783         }
26784         return (0);
26785     }
26786
26787     if ((value == NULL) || (value[0] == 0))
26788         return (0);
26789     /*
26790     * Save the value.
26791     * NOTE that even if the content type is *mixed*, we need the
26792     * *initial value* for default/fixed value constraints.
26793     */
26794     if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26795         ((vctxt->inode->decl == NULL) ||
26796         (vctxt->inode->decl->value == NULL)))
26797         return (0);
26798
26799     if (vctxt->inode->value == NULL) {
26800         /*
26801         * Set the value.
26802         */
26803         switch (mode) {
26804             case XML_SCHEMA_PUSH_TEXT_PERSIST:
26805                 /*
26806                 * When working on a tree.
26807                 */
26808                 vctxt->inode->value = value;
26809                 break;
26810             case XML_SCHEMA_PUSH_TEXT_CREATED:
26811                 /*
26812                 * When working with the reader.
26813                 * The value will be freed by the element info.
26814                 */
26815                 vctxt->inode->value = value;
26816                 if (consumed != NULL)
26817                     *consumed = 1;
26818                 vctxt->inode->flags |=
26819                     XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26820                 break;
26821             case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26822                 /*
26823                 * When working with SAX.
26824                 * The value will be freed by the element info.
26825                 */
26826                 if (len != -1)
26827                     vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26828                 else
26829                     vctxt->inode->value = BAD_CAST xmlStrdup(value);
26830                 vctxt->inode->flags |=
26831                     XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26832                 break;
26833             default:
26834                 break;
26835         }
26836     } else {
26837         if (len < 0)
26838             len = xmlStrlen(value);
26839         /*
26840         * Concat the value.
26841         */
26842         if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
26843             vctxt->inode->value = BAD_CAST xmlStrncat(
26844                 (xmlChar *) vctxt->inode->value, value, len);
26845         } else {
26846             vctxt->inode->value =
26847                 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
26848             vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26849         }
26850     }
26851
26852     return (0);
26853 }
26854
26855 static int
26856 xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
26857 {
26858     int ret = 0;
26859
26860     if ((vctxt->skipDepth != -1) &&
26861         (vctxt->depth >= vctxt->skipDepth)) {
26862         VERROR_INT("xmlSchemaValidateElem",
26863             "in skip-state");
26864         goto internal_error;
26865     }
26866     if (vctxt->xsiAssemble) {
26867         /*
26868         * We will stop validation if there was an error during
26869         * dynamic schema construction.
26870         * Note that we simply set @skipDepth to 0, this could
26871         * mean that a streaming document via SAX would be
26872         * still read to the end but it won't be validated any more.
26873         * TODO: If we are sure how to stop the validation at once
26874         *   for all input scenarios, then this should be changed to
26875         *   instantly stop the validation.
26876         */
26877         ret = xmlSchemaAssembleByXSI(vctxt);
26878         if (ret != 0) {
26879             if (ret == -1)
26880                 goto internal_error;
26881             vctxt->skipDepth = 0;
26882             return(ret);
26883         }
26884         /*
26885          * Augment the IDC definitions for the main schema and all imported ones
26886          * NOTE: main schema is the first in the imported list
26887          */
26888         xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt);
26889     }
26890     if (vctxt->depth > 0) {
26891         /*
26892         * Validate this element against the content model
26893         * of the parent.
26894         */
26895         ret = xmlSchemaValidateChildElem(vctxt);
26896         if (ret != 0) {
26897             if (ret < 0) {
26898                 VERROR_INT("xmlSchemaValidateElem",
26899                     "calling xmlSchemaStreamValidateChildElement()");
26900                 goto internal_error;
26901             }
26902             goto exit;
26903         }
26904         if (vctxt->depth == vctxt->skipDepth)
26905             goto exit;
26906         if ((vctxt->inode->decl == NULL) &&
26907             (vctxt->inode->typeDef == NULL)) {
26908             VERROR_INT("xmlSchemaValidateElem",
26909                 "the child element was valid but neither the "
26910                 "declaration nor the type was set");
26911             goto internal_error;
26912         }
26913     } else {
26914         /*
26915         * Get the declaration of the validation root.
26916         */
26917         vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26918             vctxt->inode->localName,
26919             vctxt->inode->nsName);
26920         if (vctxt->inode->decl == NULL) {
26921             ret = XML_SCHEMAV_CVC_ELT_1;
26922             VERROR(ret, NULL,
26923                 "No matching global declaration available "
26924                 "for the validation root");
26925             goto exit;
26926         }
26927     }
26928
26929     if (vctxt->inode->decl == NULL)
26930         goto type_validation;
26931
26932     if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26933         int skip;
26934         /*
26935         * Wildcards.
26936         */
26937         ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26938         if (ret != 0) {
26939             if (ret < 0) {
26940                 VERROR_INT("xmlSchemaValidateElem",
26941                     "calling xmlSchemaValidateElemWildcard()");
26942                 goto internal_error;
26943             }
26944             goto exit;
26945         }
26946         if (skip) {
26947             vctxt->skipDepth = vctxt->depth;
26948             goto exit;
26949         }
26950         /*
26951         * The declaration might be set by the wildcard validation,
26952         * when the processContents is "lax" or "strict".
26953         */
26954         if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26955             /*
26956             * Clear the "decl" field to not confuse further processing.
26957             */
26958             vctxt->inode->decl = NULL;
26959             goto type_validation;
26960         }
26961     }
26962     /*
26963     * Validate against the declaration.
26964     */
26965     ret = xmlSchemaValidateElemDecl(vctxt);
26966     if (ret != 0) {
26967         if (ret < 0) {
26968             VERROR_INT("xmlSchemaValidateElem",
26969                 "calling xmlSchemaValidateElemDecl()");
26970             goto internal_error;
26971         }
26972         goto exit;
26973     }
26974     /*
26975     * Validate against the type definition.
26976     */
26977 type_validation:
26978
26979     if (vctxt->inode->typeDef == NULL) {
26980         vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26981         ret = XML_SCHEMAV_CVC_TYPE_1;
26982         VERROR(ret, NULL,
26983             "The type definition is absent");
26984         goto exit;
26985     }
26986     if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26987         vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26988         ret = XML_SCHEMAV_CVC_TYPE_2;
26989             VERROR(ret, NULL,
26990             "The type definition is abstract");
26991         goto exit;
26992     }
26993     /*
26994     * Evaluate IDCs. Do it here, since new IDC matchers are registered
26995     * during validation against the declaration. This must be done
26996     * _before_ attribute validation.
26997     */
26998     if (vctxt->xpathStates != NULL) {
26999         ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
27000         vctxt->inode->appliedXPath = 1;
27001         if (ret == -1) {
27002             VERROR_INT("xmlSchemaValidateElem",
27003                 "calling xmlSchemaXPathEvaluate()");
27004             goto internal_error;
27005         }
27006     }
27007     /*
27008     * Validate attributes.
27009     */
27010     if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
27011         if ((vctxt->nbAttrInfos != 0) ||
27012             (vctxt->inode->typeDef->attrUses != NULL)) {
27013
27014             ret = xmlSchemaVAttributesComplex(vctxt);
27015         }
27016     } else if (vctxt->nbAttrInfos != 0) {
27017
27018         ret = xmlSchemaVAttributesSimple(vctxt);
27019     }
27020     /*
27021     * Clear registered attributes.
27022     */
27023     if (vctxt->nbAttrInfos != 0)
27024         xmlSchemaClearAttrInfos(vctxt);
27025     if (ret == -1) {
27026         VERROR_INT("xmlSchemaValidateElem",
27027             "calling attributes validation");
27028         goto internal_error;
27029     }
27030     /*
27031     * Don't return an error if attributes are invalid on purpose.
27032     */
27033     ret = 0;
27034
27035 exit:
27036     if (ret != 0)
27037         vctxt->skipDepth = vctxt->depth;
27038     return (ret);
27039 internal_error:
27040     return (-1);
27041 }
27042
27043 #ifdef XML_SCHEMA_READER_ENABLED
27044 static int
27045 xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
27046 {
27047     const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
27048     int depth, nodeType, ret = 0, consumed;
27049     xmlSchemaNodeInfoPtr ielem;
27050
27051     vctxt->depth = -1;
27052     ret = xmlTextReaderRead(vctxt->reader);
27053     /*
27054     * Move to the document element.
27055     */
27056     while (ret == 1) {
27057         nodeType = xmlTextReaderNodeType(vctxt->reader);
27058         if (nodeType == XML_ELEMENT_NODE)
27059             goto root_found;
27060         ret = xmlTextReaderRead(vctxt->reader);
27061     }
27062     goto exit;
27063
27064 root_found:
27065
27066     do {
27067         depth = xmlTextReaderDepth(vctxt->reader);
27068         nodeType = xmlTextReaderNodeType(vctxt->reader);
27069
27070         if (nodeType == XML_ELEMENT_NODE) {
27071
27072             vctxt->depth++;
27073             if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27074                 VERROR_INT("xmlSchemaVReaderWalk",
27075                     "calling xmlSchemaValidatorPushElem()");
27076                 goto internal_error;
27077             }
27078             ielem = vctxt->inode;
27079             ielem->localName = xmlTextReaderLocalName(vctxt->reader);
27080             ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
27081             ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
27082             /*
27083             * Is the element empty?
27084             */
27085             ret = xmlTextReaderIsEmptyElement(vctxt->reader);
27086             if (ret == -1) {
27087                 VERROR_INT("xmlSchemaVReaderWalk",
27088                     "calling xmlTextReaderIsEmptyElement()");
27089                 goto internal_error;
27090             }
27091             if (ret) {
27092                 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27093             }
27094             /*
27095             * Register attributes.
27096             */
27097             vctxt->nbAttrInfos = 0;
27098             ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
27099             if (ret == -1) {
27100                 VERROR_INT("xmlSchemaVReaderWalk",
27101                     "calling xmlTextReaderMoveToFirstAttribute()");
27102                 goto internal_error;
27103             }
27104             if (ret == 1) {
27105                 do {
27106                     /*
27107                     * VAL TODO: How do we know that the reader works on a
27108                     * node tree, to be able to pass a node here?
27109                     */
27110                     if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
27111                         (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
27112                         xmlTextReaderNamespaceUri(vctxt->reader), 1,
27113                         xmlTextReaderValue(vctxt->reader), 1) == -1) {
27114
27115                         VERROR_INT("xmlSchemaVReaderWalk",
27116                             "calling xmlSchemaValidatorPushAttribute()");
27117                         goto internal_error;
27118                     }
27119                     ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
27120                     if (ret == -1) {
27121                         VERROR_INT("xmlSchemaVReaderWalk",
27122                             "calling xmlTextReaderMoveToFirstAttribute()");
27123                         goto internal_error;
27124                     }
27125                 } while (ret == 1);
27126                 /*
27127                 * Back to element position.
27128                 */
27129                 ret = xmlTextReaderMoveToElement(vctxt->reader);
27130                 if (ret == -1) {
27131                     VERROR_INT("xmlSchemaVReaderWalk",
27132                         "calling xmlTextReaderMoveToElement()");
27133                     goto internal_error;
27134                 }
27135             }
27136             /*
27137             * Validate the element.
27138             */
27139             ret= xmlSchemaValidateElem(vctxt);
27140             if (ret != 0) {
27141                 if (ret == -1) {
27142                     VERROR_INT("xmlSchemaVReaderWalk",
27143                         "calling xmlSchemaValidateElem()");
27144                     goto internal_error;
27145                 }
27146                 goto exit;
27147             }
27148             if (vctxt->depth == vctxt->skipDepth) {
27149                 int curDepth;
27150                 /*
27151                 * Skip all content.
27152                 */
27153                 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
27154                     ret = xmlTextReaderRead(vctxt->reader);
27155                     curDepth = xmlTextReaderDepth(vctxt->reader);
27156                     while ((ret == 1) && (curDepth != depth)) {
27157                         ret = xmlTextReaderRead(vctxt->reader);
27158                         curDepth = xmlTextReaderDepth(vctxt->reader);
27159                     }
27160                     if (ret < 0) {
27161                         /*
27162                         * VAL TODO: A reader error occurred; what to do here?
27163                         */
27164                         ret = 1;
27165                         goto exit;
27166                     }
27167                 }
27168                 goto leave_elem;
27169             }
27170             /*
27171             * READER VAL TODO: Is an END_ELEM really never called
27172             * if the elem is empty?
27173             */
27174             if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27175                 goto leave_elem;
27176         } else if (nodeType == END_ELEM) {
27177             /*
27178             * Process END of element.
27179             */
27180 leave_elem:
27181             ret = xmlSchemaValidatorPopElem(vctxt);
27182             if (ret != 0) {
27183                 if (ret < 0) {
27184                     VERROR_INT("xmlSchemaVReaderWalk",
27185                         "calling xmlSchemaValidatorPopElem()");
27186                     goto internal_error;
27187                 }
27188                 goto exit;
27189             }
27190             if (vctxt->depth >= 0)
27191                 ielem = vctxt->inode;
27192             else
27193                 ielem = NULL;
27194         } else if ((nodeType == XML_TEXT_NODE) ||
27195             (nodeType == XML_CDATA_SECTION_NODE) ||
27196             (nodeType == WHTSP) ||
27197             (nodeType == SIGN_WHTSP)) {
27198             /*
27199             * Process character content.
27200             */
27201             xmlChar *value;
27202
27203             if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
27204                 nodeType = XML_TEXT_NODE;
27205
27206             value = xmlTextReaderValue(vctxt->reader);
27207             ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
27208                 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
27209             if (! consumed)
27210                 xmlFree(value);
27211             if (ret == -1) {
27212                 VERROR_INT("xmlSchemaVReaderWalk",
27213                     "calling xmlSchemaVPushText()");
27214                 goto internal_error;
27215             }
27216         } else if ((nodeType == XML_ENTITY_NODE) ||
27217             (nodeType == XML_ENTITY_REF_NODE)) {
27218             /*
27219             * VAL TODO: What to do with entities?
27220             */
27221             TODO
27222         }
27223         /*
27224         * Read next node.
27225         */
27226         ret = xmlTextReaderRead(vctxt->reader);
27227     } while (ret == 1);
27228
27229 exit:
27230     return (ret);
27231 internal_error:
27232     return (-1);
27233 }
27234 #endif
27235
27236 /************************************************************************
27237  *                                                                      *
27238  *                      SAX validation handlers                         *
27239  *                                                                      *
27240  ************************************************************************/
27241
27242 /*
27243 * Process text content.
27244 */
27245 static void
27246 xmlSchemaSAXHandleText(void *ctx,
27247                        const xmlChar * ch,
27248                        int len)
27249 {
27250     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27251
27252     if (vctxt->depth < 0)
27253         return;
27254     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27255         return;
27256     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27257         vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27258     if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
27259         XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27260         VERROR_INT("xmlSchemaSAXHandleCDataSection",
27261             "calling xmlSchemaVPushText()");
27262         vctxt->err = -1;
27263         xmlStopParser(vctxt->parserCtxt);
27264     }
27265 }
27266
27267 /*
27268 * Process CDATA content.
27269 */
27270 static void
27271 xmlSchemaSAXHandleCDataSection(void *ctx,
27272                              const xmlChar * ch,
27273                              int len)
27274 {
27275     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27276
27277     if (vctxt->depth < 0)
27278         return;
27279     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27280         return;
27281     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27282         vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27283     if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
27284         XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27285         VERROR_INT("xmlSchemaSAXHandleCDataSection",
27286             "calling xmlSchemaVPushText()");
27287         vctxt->err = -1;
27288         xmlStopParser(vctxt->parserCtxt);
27289     }
27290 }
27291
27292 static void
27293 xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
27294                             const xmlChar * name ATTRIBUTE_UNUSED)
27295 {
27296     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27297
27298     if (vctxt->depth < 0)
27299         return;
27300     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27301         return;
27302     /* SAX VAL TODO: What to do here? */
27303     TODO
27304 }
27305
27306 static void
27307 xmlSchemaSAXHandleStartElementNs(void *ctx,
27308                                  const xmlChar * localname,
27309                                  const xmlChar * prefix ATTRIBUTE_UNUSED,
27310                                  const xmlChar * URI,
27311                                  int nb_namespaces,
27312                                  const xmlChar ** namespaces,
27313                                  int nb_attributes,
27314                                  int nb_defaulted ATTRIBUTE_UNUSED,
27315                                  const xmlChar ** attributes)
27316 {
27317     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27318     int ret;
27319     xmlSchemaNodeInfoPtr ielem;
27320     int i, j;
27321
27322     /*
27323     * SAX VAL TODO: What to do with nb_defaulted?
27324     */
27325     /*
27326     * Skip elements if inside a "skip" wildcard or invalid.
27327     */
27328     vctxt->depth++;
27329     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27330         return;
27331     /*
27332     * Push the element.
27333     */
27334     if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27335         VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27336             "calling xmlSchemaValidatorPushElem()");
27337         goto internal_error;
27338     }
27339     ielem = vctxt->inode;
27340     /*
27341     * TODO: Is this OK?
27342     */
27343     ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
27344     ielem->localName = localname;
27345     ielem->nsName = URI;
27346     ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27347     /*
27348     * Register namespaces on the elem info.
27349     */
27350     if (nb_namespaces != 0) {
27351         /*
27352         * Although the parser builds its own namespace list,
27353         * we have no access to it, so we'll use an own one.
27354         */
27355         for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
27356             /*
27357             * Store prefix and namespace name.
27358             */
27359             if (ielem->nsBindings == NULL) {
27360                 ielem->nsBindings =
27361                     (const xmlChar **) xmlMalloc(10 *
27362                         sizeof(const xmlChar *));
27363                 if (ielem->nsBindings == NULL) {
27364                     xmlSchemaVErrMemory(vctxt,
27365                         "allocating namespace bindings for SAX validation",
27366                         NULL);
27367                     goto internal_error;
27368                 }
27369                 ielem->nbNsBindings = 0;
27370                 ielem->sizeNsBindings = 5;
27371             } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
27372                 ielem->sizeNsBindings *= 2;
27373                 ielem->nsBindings =
27374                     (const xmlChar **) xmlRealloc(
27375                         (void *) ielem->nsBindings,
27376                         ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
27377                 if (ielem->nsBindings == NULL) {
27378                     xmlSchemaVErrMemory(vctxt,
27379                         "re-allocating namespace bindings for SAX validation",
27380                         NULL);
27381                     goto internal_error;
27382                 }
27383             }
27384
27385             ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
27386             if (namespaces[j+1][0] == 0) {
27387                 /*
27388                 * Handle xmlns="".
27389                 */
27390                 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
27391             } else
27392                 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
27393                     namespaces[j+1];
27394             ielem->nbNsBindings++;
27395         }
27396     }
27397     /*
27398     * Register attributes.
27399     * SAX VAL TODO: We are not adding namespace declaration
27400     * attributes yet.
27401     */
27402     if (nb_attributes != 0) {
27403         int valueLen, k, l;
27404         xmlChar *value;
27405
27406         for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27407             /*
27408             * Duplicate the value, changing any &#38; to a literal ampersand.
27409             *
27410             * libxml2 differs from normal SAX here in that it escapes all ampersands
27411             * as &#38; instead of delivering the raw converted string. Changing the
27412             * behavior at this point would break applications that use this API, so
27413             * we are forced to work around it.
27414             */
27415             valueLen = attributes[j+4] - attributes[j+3];
27416             value = xmlMallocAtomic(valueLen + 1);
27417             if (value == NULL) {
27418                 xmlSchemaVErrMemory(vctxt,
27419                     "allocating string for decoded attribute",
27420                     NULL);
27421                 goto internal_error;
27422             }
27423             for (k = 0, l = 0; k < valueLen; l++) {
27424                 if (k < valueLen - 4 &&
27425                     attributes[j+3][k+0] == '&' &&
27426                     attributes[j+3][k+1] == '#' &&
27427                     attributes[j+3][k+2] == '3' &&
27428                     attributes[j+3][k+3] == '8' &&
27429                     attributes[j+3][k+4] == ';') {
27430                     value[l] = '&';
27431                     k += 5;
27432                 } else {
27433                     value[l] = attributes[j+3][k];
27434                     k++;
27435                 }
27436             }
27437             value[l] = '\0';
27438             /*
27439             * TODO: Set the node line.
27440             */
27441             ret = xmlSchemaValidatorPushAttribute(vctxt,
27442                 NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
27443                 value, 1);
27444             if (ret == -1) {
27445                 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27446                     "calling xmlSchemaValidatorPushAttribute()");
27447                 goto internal_error;
27448             }
27449         }
27450     }
27451     /*
27452     * Validate the element.
27453     */
27454     ret = xmlSchemaValidateElem(vctxt);
27455     if (ret != 0) {
27456         if (ret == -1) {
27457             VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27458                 "calling xmlSchemaValidateElem()");
27459             goto internal_error;
27460         }
27461         goto exit;
27462     }
27463
27464 exit:
27465     return;
27466 internal_error:
27467     vctxt->err = -1;
27468     xmlStopParser(vctxt->parserCtxt);
27469     return;
27470 }
27471
27472 static void
27473 xmlSchemaSAXHandleEndElementNs(void *ctx,
27474                                const xmlChar * localname ATTRIBUTE_UNUSED,
27475                                const xmlChar * prefix ATTRIBUTE_UNUSED,
27476                                const xmlChar * URI ATTRIBUTE_UNUSED)
27477 {
27478     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27479     int res;
27480
27481     /*
27482     * Skip elements if inside a "skip" wildcard or if invalid.
27483     */
27484     if (vctxt->skipDepth != -1) {
27485         if (vctxt->depth > vctxt->skipDepth) {
27486             vctxt->depth--;
27487             return;
27488         } else
27489             vctxt->skipDepth = -1;
27490     }
27491     /*
27492     * SAX VAL TODO: Just a temporary check.
27493     */
27494     if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27495         (!xmlStrEqual(vctxt->inode->nsName, URI))) {
27496         VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27497             "elem pop mismatch");
27498     }
27499     res = xmlSchemaValidatorPopElem(vctxt);
27500     if (res != 0) {
27501         if (res < 0) {
27502             VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27503                 "calling xmlSchemaValidatorPopElem()");
27504             goto internal_error;
27505         }
27506         goto exit;
27507     }
27508 exit:
27509     return;
27510 internal_error:
27511     vctxt->err = -1;
27512     xmlStopParser(vctxt->parserCtxt);
27513     return;
27514 }
27515
27516 /************************************************************************
27517  *                                                                      *
27518  *                      Validation interfaces                           *
27519  *                                                                      *
27520  ************************************************************************/
27521
27522 /**
27523  * xmlSchemaNewValidCtxt:
27524  * @schema:  a precompiled XML Schemas
27525  *
27526  * Create an XML Schemas validation context based on the given schema.
27527  *
27528  * Returns the validation context or NULL in case of error
27529  */
27530 xmlSchemaValidCtxtPtr
27531 xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27532 {
27533     xmlSchemaValidCtxtPtr ret;
27534
27535     ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27536     if (ret == NULL) {
27537         xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
27538         return (NULL);
27539     }
27540     memset(ret, 0, sizeof(xmlSchemaValidCtxt));
27541     ret->type = XML_SCHEMA_CTXT_VALIDATOR;
27542     ret->dict = xmlDictCreate();
27543     ret->nodeQNames = xmlSchemaItemListCreate();
27544     ret->schema = schema;
27545     return (ret);
27546 }
27547
27548 /**
27549  * xmlSchemaValidateSetFilename:
27550  * @vctxt: the schema validation context
27551  * @filename: the file name
27552  *
27553  * Workaround to provide file error reporting information when this is
27554  * not provided by current APIs
27555  */
27556 void
27557 xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt, const char *filename) {
27558     if (vctxt == NULL)
27559         return;
27560     if (vctxt->filename != NULL)
27561         xmlFree(vctxt->filename);
27562     if (filename != NULL)
27563         vctxt->filename = (char *) xmlStrdup((const xmlChar *) filename);
27564     else
27565         vctxt->filename = NULL;
27566 }
27567
27568 /**
27569  * xmlSchemaClearValidCtxt:
27570  * @vctxt: the schema validation context
27571  *
27572  * Free the resources associated to the schema validation context;
27573  * leaves some fields alive intended for reuse of the context.
27574  */
27575 static void
27576 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27577 {
27578     if (vctxt == NULL)
27579         return;
27580
27581     /*
27582     * TODO: Should we clear the flags?
27583     *   Might be problematic if one reuses the context
27584     *   and assumes that the options remain the same.
27585     */
27586     vctxt->flags = 0;
27587     vctxt->validationRoot = NULL;
27588     vctxt->doc = NULL;
27589 #ifdef LIBXML_READER_ENABLED
27590     vctxt->reader = NULL;
27591 #endif
27592     vctxt->hasKeyrefs = 0;
27593
27594     if (vctxt->value != NULL) {
27595         xmlSchemaFreeValue(vctxt->value);
27596         vctxt->value = NULL;
27597     }
27598     /*
27599     * Augmented IDC information.
27600     */
27601     if (vctxt->aidcs != NULL) {
27602         xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27603         do {
27604             next = cur->next;
27605             xmlFree(cur);
27606             cur = next;
27607         } while (cur != NULL);
27608         vctxt->aidcs = NULL;
27609     }
27610     if (vctxt->idcMatcherCache != NULL) {
27611         xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp;
27612
27613         while (matcher) {
27614             tmp = matcher;
27615             matcher = matcher->nextCached;
27616             xmlSchemaIDCFreeMatcherList(tmp);
27617         }
27618         vctxt->idcMatcherCache = NULL;
27619     }
27620
27621
27622     if (vctxt->idcNodes != NULL) {
27623         int i;
27624         xmlSchemaPSVIIDCNodePtr item;
27625
27626         for (i = 0; i < vctxt->nbIdcNodes; i++) {
27627             item = vctxt->idcNodes[i];
27628             xmlFree(item->keys);
27629             xmlFree(item);
27630         }
27631         xmlFree(vctxt->idcNodes);
27632         vctxt->idcNodes = NULL;
27633         vctxt->nbIdcNodes = 0;
27634         vctxt->sizeIdcNodes = 0;
27635     }
27636     /*
27637     * Note that we won't delete the XPath state pool here.
27638     */
27639     if (vctxt->xpathStates != NULL) {
27640         xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27641         vctxt->xpathStates = NULL;
27642     }
27643     /*
27644     * Attribute info.
27645     */
27646     if (vctxt->nbAttrInfos != 0) {
27647         xmlSchemaClearAttrInfos(vctxt);
27648     }
27649     /*
27650     * Element info.
27651     */
27652     if (vctxt->elemInfos != NULL) {
27653         int i;
27654         xmlSchemaNodeInfoPtr ei;
27655
27656         for (i = 0; i < vctxt->sizeElemInfos; i++) {
27657             ei = vctxt->elemInfos[i];
27658             if (ei == NULL)
27659                 break;
27660             xmlSchemaClearElemInfo(vctxt, ei);
27661         }
27662     }
27663     xmlSchemaItemListClear(vctxt->nodeQNames);
27664     /* Recreate the dict. */
27665     xmlDictFree(vctxt->dict);
27666     /*
27667     * TODO: Is is save to recreate it? Do we have a scenario
27668     * where the user provides the dict?
27669     */
27670     vctxt->dict = xmlDictCreate();
27671
27672     if (vctxt->filename != NULL) {
27673         xmlFree(vctxt->filename);
27674         vctxt->filename = NULL;
27675     }
27676 }
27677
27678 /**
27679  * xmlSchemaFreeValidCtxt:
27680  * @ctxt:  the schema validation context
27681  *
27682  * Free the resources associated to the schema validation context
27683  */
27684 void
27685 xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27686 {
27687     if (ctxt == NULL)
27688         return;
27689     if (ctxt->value != NULL)
27690         xmlSchemaFreeValue(ctxt->value);
27691     if (ctxt->pctxt != NULL)
27692         xmlSchemaFreeParserCtxt(ctxt->pctxt);
27693     if (ctxt->idcNodes != NULL) {
27694         int i;
27695         xmlSchemaPSVIIDCNodePtr item;
27696
27697         for (i = 0; i < ctxt->nbIdcNodes; i++) {
27698             item = ctxt->idcNodes[i];
27699             xmlFree(item->keys);
27700             xmlFree(item);
27701         }
27702         xmlFree(ctxt->idcNodes);
27703     }
27704     if (ctxt->idcKeys != NULL) {
27705         int i;
27706         for (i = 0; i < ctxt->nbIdcKeys; i++)
27707             xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27708         xmlFree(ctxt->idcKeys);
27709     }
27710
27711     if (ctxt->xpathStates != NULL) {
27712         xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27713         ctxt->xpathStates = NULL;
27714     }
27715     if (ctxt->xpathStatePool != NULL) {
27716         xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27717         ctxt->xpathStatePool = NULL;
27718     }
27719
27720     /*
27721     * Augmented IDC information.
27722     */
27723     if (ctxt->aidcs != NULL) {
27724         xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27725         do {
27726             next = cur->next;
27727             xmlFree(cur);
27728             cur = next;
27729         } while (cur != NULL);
27730     }
27731     if (ctxt->attrInfos != NULL) {
27732         int i;
27733         xmlSchemaAttrInfoPtr attr;
27734
27735         /* Just a paranoid call to the cleanup. */
27736         if (ctxt->nbAttrInfos != 0)
27737             xmlSchemaClearAttrInfos(ctxt);
27738         for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27739             attr = ctxt->attrInfos[i];
27740             xmlFree(attr);
27741         }
27742         xmlFree(ctxt->attrInfos);
27743     }
27744     if (ctxt->elemInfos != NULL) {
27745         int i;
27746         xmlSchemaNodeInfoPtr ei;
27747
27748         for (i = 0; i < ctxt->sizeElemInfos; i++) {
27749             ei = ctxt->elemInfos[i];
27750             if (ei == NULL)
27751                 break;
27752             xmlSchemaClearElemInfo(ctxt, ei);
27753             xmlFree(ei);
27754         }
27755         xmlFree(ctxt->elemInfos);
27756     }
27757     if (ctxt->nodeQNames != NULL)
27758         xmlSchemaItemListFree(ctxt->nodeQNames);
27759     if (ctxt->dict != NULL)
27760         xmlDictFree(ctxt->dict);
27761     if (ctxt->filename != NULL)
27762         xmlFree(ctxt->filename);
27763     xmlFree(ctxt);
27764 }
27765
27766 /**
27767  * xmlSchemaIsValid:
27768  * @ctxt: the schema validation context
27769  *
27770  * Check if any error was detected during validation.
27771  *
27772  * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27773  *         of internal error.
27774  */
27775 int
27776 xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27777 {
27778     if (ctxt == NULL)
27779         return(-1);
27780     return(ctxt->err == 0);
27781 }
27782
27783 /**
27784  * xmlSchemaSetValidErrors:
27785  * @ctxt:  a schema validation context
27786  * @err:  the error function
27787  * @warn: the warning function
27788  * @ctx: the functions context
27789  *
27790  * Set the error and warning callback informations
27791  */
27792 void
27793 xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27794                         xmlSchemaValidityErrorFunc err,
27795                         xmlSchemaValidityWarningFunc warn, void *ctx)
27796 {
27797     if (ctxt == NULL)
27798         return;
27799     ctxt->error = err;
27800     ctxt->warning = warn;
27801     ctxt->errCtxt = ctx;
27802     if (ctxt->pctxt != NULL)
27803         xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
27804 }
27805
27806 /**
27807  * xmlSchemaSetValidStructuredErrors:
27808  * @ctxt:  a schema validation context
27809  * @serror:  the structured error function
27810  * @ctx: the functions context
27811  *
27812  * Set the structured error callback
27813  */
27814 void
27815 xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
27816                                   xmlStructuredErrorFunc serror, void *ctx)
27817 {
27818     if (ctxt == NULL)
27819         return;
27820         ctxt->serror = serror;
27821     ctxt->error = NULL;
27822     ctxt->warning = NULL;
27823     ctxt->errCtxt = ctx;
27824     if (ctxt->pctxt != NULL)
27825         xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
27826 }
27827
27828 /**
27829  * xmlSchemaGetValidErrors:
27830  * @ctxt: a XML-Schema validation context
27831  * @err: the error function result
27832  * @warn: the warning function result
27833  * @ctx: the functions context result
27834  *
27835  * Get the error and warning callback informations
27836  *
27837  * Returns -1 in case of error and 0 otherwise
27838  */
27839 int
27840 xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27841                         xmlSchemaValidityErrorFunc * err,
27842                         xmlSchemaValidityWarningFunc * warn, void **ctx)
27843 {
27844         if (ctxt == NULL)
27845                 return (-1);
27846         if (err != NULL)
27847                 *err = ctxt->error;
27848         if (warn != NULL)
27849                 *warn = ctxt->warning;
27850         if (ctx != NULL)
27851                 *ctx = ctxt->errCtxt;
27852         return (0);
27853 }
27854
27855
27856 /**
27857  * xmlSchemaSetValidOptions:
27858  * @ctxt:       a schema validation context
27859  * @options: a combination of xmlSchemaValidOption
27860  *
27861  * Sets the options to be used during the validation.
27862  *
27863  * Returns 0 in case of success, -1 in case of an
27864  * API error.
27865  */
27866 int
27867 xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27868                          int options)
27869
27870 {
27871     int i;
27872
27873     if (ctxt == NULL)
27874         return (-1);
27875     /*
27876     * WARNING: Change the start value if adding to the
27877     * xmlSchemaValidOption.
27878     * TODO: Is there an other, more easy to maintain,
27879     * way?
27880     */
27881     for (i = 1; i < (int) sizeof(int) * 8; i++) {
27882         if (options & 1<<i)
27883             return (-1);
27884     }
27885     ctxt->options = options;
27886     return (0);
27887 }
27888
27889 /**
27890  * xmlSchemaValidCtxtGetOptions:
27891  * @ctxt: a schema validation context
27892  *
27893  * Get the validation context options.
27894  *
27895  * Returns the option combination or -1 on error.
27896  */
27897 int
27898 xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
27899
27900 {
27901     if (ctxt == NULL)
27902         return (-1);
27903     else
27904         return (ctxt->options);
27905 }
27906
27907 static int
27908 xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27909 {
27910     xmlAttrPtr attr;
27911     int ret = 0;
27912     xmlSchemaNodeInfoPtr ielem = NULL;
27913     xmlNodePtr node, valRoot;
27914     const xmlChar *nsName;
27915
27916     /* DOC VAL TODO: Move this to the start function. */
27917     if (vctxt->validationRoot != NULL)
27918         valRoot = vctxt->validationRoot;
27919     else
27920         valRoot = xmlDocGetRootElement(vctxt->doc);
27921     if (valRoot == NULL) {
27922         /* VAL TODO: Error code? */
27923         VERROR(1, NULL, "The document has no document element");
27924         return (1);
27925     }
27926     vctxt->depth = -1;
27927     vctxt->validationRoot = valRoot;
27928     node = valRoot;
27929     while (node != NULL) {
27930         if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27931             goto next_sibling;
27932         if (node->type == XML_ELEMENT_NODE) {
27933
27934             /*
27935             * Init the node-info.
27936             */
27937             vctxt->depth++;
27938             if (xmlSchemaValidatorPushElem(vctxt) == -1)
27939                 goto internal_error;
27940             ielem = vctxt->inode;
27941             ielem->node = node;
27942             ielem->nodeLine = node->line;
27943             ielem->localName = node->name;
27944             if (node->ns != NULL)
27945                 ielem->nsName = node->ns->href;
27946             ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27947             /*
27948             * Register attributes.
27949             * DOC VAL TODO: We do not register namespace declaration
27950             * attributes yet.
27951             */
27952             vctxt->nbAttrInfos = 0;
27953             if (node->properties != NULL) {
27954                 attr = node->properties;
27955                 do {
27956                     if (attr->ns != NULL)
27957                         nsName = attr->ns->href;
27958                     else
27959                         nsName = NULL;
27960                     ret = xmlSchemaValidatorPushAttribute(vctxt,
27961                         (xmlNodePtr) attr,
27962                         /*
27963                         * Note that we give it the line number of the
27964                         * parent element.
27965                         */
27966                         ielem->nodeLine,
27967                         attr->name, nsName, 0,
27968                         xmlNodeListGetString(attr->doc, attr->children, 1), 1);
27969                     if (ret == -1) {
27970                         VERROR_INT("xmlSchemaDocWalk",
27971                             "calling xmlSchemaValidatorPushAttribute()");
27972                         goto internal_error;
27973                     }
27974                     attr = attr->next;
27975                 } while (attr);
27976             }
27977             /*
27978             * Validate the element.
27979             */
27980             ret = xmlSchemaValidateElem(vctxt);
27981             if (ret != 0) {
27982                 if (ret == -1) {
27983                     VERROR_INT("xmlSchemaDocWalk",
27984                         "calling xmlSchemaValidateElem()");
27985                     goto internal_error;
27986                 }
27987                 /*
27988                 * Don't stop validation; just skip the content
27989                 * of this element.
27990                 */
27991                 goto leave_node;
27992             }
27993             if ((vctxt->skipDepth != -1) &&
27994                 (vctxt->depth >= vctxt->skipDepth))
27995                 goto leave_node;
27996         } else if ((node->type == XML_TEXT_NODE) ||
27997             (node->type == XML_CDATA_SECTION_NODE)) {
27998             /*
27999             * Process character content.
28000             */
28001             if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
28002                 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
28003             ret = xmlSchemaVPushText(vctxt, node->type, node->content,
28004                 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
28005             if (ret < 0) {
28006                 VERROR_INT("xmlSchemaVDocWalk",
28007                     "calling xmlSchemaVPushText()");
28008                 goto internal_error;
28009             }
28010             /*
28011             * DOC VAL TODO: Should we skip further validation of the
28012             * element content here?
28013             */
28014         } else if ((node->type == XML_ENTITY_NODE) ||
28015             (node->type == XML_ENTITY_REF_NODE)) {
28016             /*
28017             * DOC VAL TODO: What to do with entities?
28018             */
28019             VERROR_INT("xmlSchemaVDocWalk",
28020                 "there is at least one entity reference in the node-tree "
28021                 "currently being validated. Processing of entities with "
28022                 "this XML Schema processor is not supported (yet). Please "
28023                 "substitute entities before validation.");
28024             goto internal_error;
28025         } else {
28026             goto leave_node;
28027             /*
28028             * DOC VAL TODO: XInclude nodes, etc.
28029             */
28030         }
28031         /*
28032         * Walk the doc.
28033         */
28034         if (node->children != NULL) {
28035             node = node->children;
28036             continue;
28037         }
28038 leave_node:
28039         if (node->type == XML_ELEMENT_NODE) {
28040             /*
28041             * Leaving the scope of an element.
28042             */
28043             if (node != vctxt->inode->node) {
28044                 VERROR_INT("xmlSchemaVDocWalk",
28045                     "element position mismatch");
28046                 goto internal_error;
28047             }
28048             ret = xmlSchemaValidatorPopElem(vctxt);
28049             if (ret != 0) {
28050                 if (ret < 0) {
28051                     VERROR_INT("xmlSchemaVDocWalk",
28052                         "calling xmlSchemaValidatorPopElem()");
28053                     goto internal_error;
28054                 }
28055             }
28056             if (node == valRoot)
28057                 goto exit;
28058         }
28059 next_sibling:
28060         if (node->next != NULL)
28061             node = node->next;
28062         else {
28063             node = node->parent;
28064             goto leave_node;
28065         }
28066     }
28067
28068 exit:
28069     return (ret);
28070 internal_error:
28071     return (-1);
28072 }
28073
28074 static int
28075 xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
28076     /*
28077     * Some initialization.
28078     */
28079     vctxt->err = 0;
28080     vctxt->nberrors = 0;
28081     vctxt->depth = -1;
28082     vctxt->skipDepth = -1;
28083     vctxt->xsiAssemble = 0;
28084     vctxt->hasKeyrefs = 0;
28085 #ifdef ENABLE_IDC_NODE_TABLES_TEST
28086     vctxt->createIDCNodeTables = 1;
28087 #else
28088     vctxt->createIDCNodeTables = 0;
28089 #endif
28090     /*
28091     * Create a schema + parser if necessary.
28092     */
28093     if (vctxt->schema == NULL) {
28094         xmlSchemaParserCtxtPtr pctxt;
28095
28096         vctxt->xsiAssemble = 1;
28097         /*
28098         * If not schema was given then we will create a schema
28099         * dynamically using XSI schema locations.
28100         *
28101         * Create the schema parser context.
28102         */
28103         if ((vctxt->pctxt == NULL) &&
28104            (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
28105            return (-1);
28106         pctxt = vctxt->pctxt;
28107         pctxt->xsiAssemble = 1;
28108         /*
28109         * Create the schema.
28110         */
28111         vctxt->schema = xmlSchemaNewSchema(pctxt);
28112         if (vctxt->schema == NULL)
28113             return (-1);
28114         /*
28115         * Create the schema construction context.
28116         */
28117         pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
28118         if (pctxt->constructor == NULL)
28119             return(-1);
28120         pctxt->constructor->mainSchema = vctxt->schema;
28121         /*
28122         * Take ownership of the constructor to be able to free it.
28123         */
28124         pctxt->ownsConstructor = 1;
28125     }
28126     /*
28127     * Augment the IDC definitions for the main schema and all imported ones
28128     * NOTE: main schema if the first in the imported list
28129     */
28130     xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt);
28131
28132     return(0);
28133 }
28134
28135 static void
28136 xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
28137     if (vctxt->xsiAssemble) {
28138         if (vctxt->schema != NULL) {
28139             xmlSchemaFree(vctxt->schema);
28140             vctxt->schema = NULL;
28141         }
28142     }
28143     xmlSchemaClearValidCtxt(vctxt);
28144 }
28145
28146 static int
28147 xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
28148 {
28149     int ret = 0;
28150
28151     if (xmlSchemaPreRun(vctxt) < 0)
28152         return(-1);
28153
28154     if (vctxt->doc != NULL) {
28155         /*
28156          * Tree validation.
28157          */
28158         ret = xmlSchemaVDocWalk(vctxt);
28159 #ifdef LIBXML_READER_ENABLED
28160     } else if (vctxt->reader != NULL) {
28161         /*
28162          * XML Reader validation.
28163          */
28164 #ifdef XML_SCHEMA_READER_ENABLED
28165         ret = xmlSchemaVReaderWalk(vctxt);
28166 #endif
28167 #endif
28168     } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
28169         /*
28170          * SAX validation.
28171          */
28172         ret = xmlParseDocument(vctxt->parserCtxt);
28173     } else {
28174         VERROR_INT("xmlSchemaVStart",
28175             "no instance to validate");
28176         ret = -1;
28177     }
28178
28179     xmlSchemaPostRun(vctxt);
28180     if (ret == 0)
28181         ret = vctxt->err;
28182     return (ret);
28183 }
28184
28185 /**
28186  * xmlSchemaValidateOneElement:
28187  * @ctxt:  a schema validation context
28188  * @elem:  an element node
28189  *
28190  * Validate a branch of a tree, starting with the given @elem.
28191  *
28192  * Returns 0 if the element and its subtree is valid, a positive error
28193  * code number otherwise and -1 in case of an internal or API error.
28194  */
28195 int
28196 xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
28197 {
28198     if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
28199         return (-1);
28200
28201     if (ctxt->schema == NULL)
28202         return (-1);
28203
28204     ctxt->doc = elem->doc;
28205     ctxt->node = elem;
28206     ctxt->validationRoot = elem;
28207     return(xmlSchemaVStart(ctxt));
28208 }
28209
28210 /**
28211  * xmlSchemaValidateDoc:
28212  * @ctxt:  a schema validation context
28213  * @doc:  a parsed document tree
28214  *
28215  * Validate a document tree in memory.
28216  *
28217  * Returns 0 if the document is schemas valid, a positive error code
28218  *     number otherwise and -1 in case of internal or API error.
28219  */
28220 int
28221 xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
28222 {
28223     if ((ctxt == NULL) || (doc == NULL))
28224         return (-1);
28225
28226     ctxt->doc = doc;
28227     ctxt->node = xmlDocGetRootElement(doc);
28228     if (ctxt->node == NULL) {
28229         xmlSchemaCustomErr(ACTXT_CAST ctxt,
28230             XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
28231             (xmlNodePtr) doc, NULL,
28232             "The document has no document element", NULL, NULL);
28233         return (ctxt->err);
28234     }
28235     ctxt->validationRoot = ctxt->node;
28236     return (xmlSchemaVStart(ctxt));
28237 }
28238
28239
28240 /************************************************************************
28241  *                                                                      *
28242  *              Function and data for SAX streaming API                 *
28243  *                                                                      *
28244  ************************************************************************/
28245 typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
28246 typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
28247
28248 struct _xmlSchemaSplitSAXData {
28249     xmlSAXHandlerPtr      user_sax;
28250     void                 *user_data;
28251     xmlSchemaValidCtxtPtr ctxt;
28252     xmlSAXHandlerPtr      schemas_sax;
28253 };
28254
28255 #define XML_SAX_PLUG_MAGIC 0xdc43ba21
28256
28257 struct _xmlSchemaSAXPlug {
28258     unsigned int magic;
28259
28260     /* the original callbacks informations */
28261     xmlSAXHandlerPtr     *user_sax_ptr;
28262     xmlSAXHandlerPtr      user_sax;
28263     void                **user_data_ptr;
28264     void                 *user_data;
28265
28266     /* the block plugged back and validation informations */
28267     xmlSAXHandler         schemas_sax;
28268     xmlSchemaValidCtxtPtr ctxt;
28269 };
28270
28271 /* All those functions just bounces to the user provided SAX handlers */
28272 static void
28273 internalSubsetSplit(void *ctx, const xmlChar *name,
28274                const xmlChar *ExternalID, const xmlChar *SystemID)
28275 {
28276     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28277     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28278         (ctxt->user_sax->internalSubset != NULL))
28279         ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
28280                                        SystemID);
28281 }
28282
28283 static int
28284 isStandaloneSplit(void *ctx)
28285 {
28286     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28287     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28288         (ctxt->user_sax->isStandalone != NULL))
28289         return(ctxt->user_sax->isStandalone(ctxt->user_data));
28290     return(0);
28291 }
28292
28293 static int
28294 hasInternalSubsetSplit(void *ctx)
28295 {
28296     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28297     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28298         (ctxt->user_sax->hasInternalSubset != NULL))
28299         return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
28300     return(0);
28301 }
28302
28303 static int
28304 hasExternalSubsetSplit(void *ctx)
28305 {
28306     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28307     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28308         (ctxt->user_sax->hasExternalSubset != NULL))
28309         return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
28310     return(0);
28311 }
28312
28313 static void
28314 externalSubsetSplit(void *ctx, const xmlChar *name,
28315                const xmlChar *ExternalID, const xmlChar *SystemID)
28316 {
28317     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28318     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28319         (ctxt->user_sax->externalSubset != NULL))
28320         ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID,
28321                                        SystemID);
28322 }
28323
28324 static xmlParserInputPtr
28325 resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
28326 {
28327     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28328     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28329         (ctxt->user_sax->resolveEntity != NULL))
28330         return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
28331                                              systemId));
28332     return(NULL);
28333 }
28334
28335 static xmlEntityPtr
28336 getEntitySplit(void *ctx, const xmlChar *name)
28337 {
28338     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28339     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28340         (ctxt->user_sax->getEntity != NULL))
28341         return(ctxt->user_sax->getEntity(ctxt->user_data, name));
28342     return(NULL);
28343 }
28344
28345 static xmlEntityPtr
28346 getParameterEntitySplit(void *ctx, const xmlChar *name)
28347 {
28348     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28349     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28350         (ctxt->user_sax->getParameterEntity != NULL))
28351         return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
28352     return(NULL);
28353 }
28354
28355
28356 static void
28357 entityDeclSplit(void *ctx, const xmlChar *name, int type,
28358           const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
28359 {
28360     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28361     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28362         (ctxt->user_sax->entityDecl != NULL))
28363         ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
28364                                    systemId, content);
28365 }
28366
28367 static void
28368 attributeDeclSplit(void *ctx, const xmlChar * elem,
28369                    const xmlChar * name, int type, int def,
28370                    const xmlChar * defaultValue, xmlEnumerationPtr tree)
28371 {
28372     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28373     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28374         (ctxt->user_sax->attributeDecl != NULL)) {
28375         ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
28376                                       def, defaultValue, tree);
28377     } else {
28378         xmlFreeEnumeration(tree);
28379     }
28380 }
28381
28382 static void
28383 elementDeclSplit(void *ctx, const xmlChar *name, int type,
28384             xmlElementContentPtr content)
28385 {
28386     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28387     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28388         (ctxt->user_sax->elementDecl != NULL))
28389         ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
28390 }
28391
28392 static void
28393 notationDeclSplit(void *ctx, const xmlChar *name,
28394              const xmlChar *publicId, const xmlChar *systemId)
28395 {
28396     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28397     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28398         (ctxt->user_sax->notationDecl != NULL))
28399         ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
28400                                      systemId);
28401 }
28402
28403 static void
28404 unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
28405                    const xmlChar *publicId, const xmlChar *systemId,
28406                    const xmlChar *notationName)
28407 {
28408     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28409     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28410         (ctxt->user_sax->unparsedEntityDecl != NULL))
28411         ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
28412                                            systemId, notationName);
28413 }
28414
28415 static void
28416 setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
28417 {
28418     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28419     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28420         (ctxt->user_sax->setDocumentLocator != NULL))
28421         ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
28422 }
28423
28424 static void
28425 startDocumentSplit(void *ctx)
28426 {
28427     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28428     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28429         (ctxt->user_sax->startDocument != NULL))
28430         ctxt->user_sax->startDocument(ctxt->user_data);
28431 }
28432
28433 static void
28434 endDocumentSplit(void *ctx)
28435 {
28436     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28437     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28438         (ctxt->user_sax->endDocument != NULL))
28439         ctxt->user_sax->endDocument(ctxt->user_data);
28440 }
28441
28442 static void
28443 processingInstructionSplit(void *ctx, const xmlChar *target,
28444                       const xmlChar *data)
28445 {
28446     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28447     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28448         (ctxt->user_sax->processingInstruction != NULL))
28449         ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
28450 }
28451
28452 static void
28453 commentSplit(void *ctx, const xmlChar *value)
28454 {
28455     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28456     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28457         (ctxt->user_sax->comment != NULL))
28458         ctxt->user_sax->comment(ctxt->user_data, value);
28459 }
28460
28461 /*
28462  * Varargs error callbacks to the user application, harder ...
28463  */
28464
28465 static void XMLCDECL
28466 warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28467     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28468     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28469         (ctxt->user_sax->warning != NULL)) {
28470         TODO
28471     }
28472 }
28473 static void XMLCDECL
28474 errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28475     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28476     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28477         (ctxt->user_sax->error != NULL)) {
28478         TODO
28479     }
28480 }
28481 static void XMLCDECL
28482 fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28483     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28484     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28485         (ctxt->user_sax->fatalError != NULL)) {
28486         TODO
28487     }
28488 }
28489
28490 /*
28491  * Those are function where both the user handler and the schemas handler
28492  * need to be called.
28493  */
28494 static void
28495 charactersSplit(void *ctx, const xmlChar *ch, int len)
28496 {
28497     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28498     if (ctxt == NULL)
28499         return;
28500     if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
28501         ctxt->user_sax->characters(ctxt->user_data, ch, len);
28502     if (ctxt->ctxt != NULL)
28503         xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28504 }
28505
28506 static void
28507 ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
28508 {
28509     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28510     if (ctxt == NULL)
28511         return;
28512     if ((ctxt->user_sax != NULL) &&
28513         (ctxt->user_sax->ignorableWhitespace != NULL))
28514         ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
28515     if (ctxt->ctxt != NULL)
28516         xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28517 }
28518
28519 static void
28520 cdataBlockSplit(void *ctx, const xmlChar *value, int len)
28521 {
28522     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28523     if (ctxt == NULL)
28524         return;
28525     if ((ctxt->user_sax != NULL) &&
28526         (ctxt->user_sax->cdataBlock != NULL))
28527         ctxt->user_sax->cdataBlock(ctxt->user_data, value, len);
28528     if (ctxt->ctxt != NULL)
28529         xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28530 }
28531
28532 static void
28533 referenceSplit(void *ctx, const xmlChar *name)
28534 {
28535     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28536     if (ctxt == NULL)
28537         return;
28538     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28539         (ctxt->user_sax->reference != NULL))
28540         ctxt->user_sax->reference(ctxt->user_data, name);
28541     if (ctxt->ctxt != NULL)
28542         xmlSchemaSAXHandleReference(ctxt->user_data, name);
28543 }
28544
28545 static void
28546 startElementNsSplit(void *ctx, const xmlChar * localname,
28547                     const xmlChar * prefix, const xmlChar * URI,
28548                     int nb_namespaces, const xmlChar ** namespaces,
28549                     int nb_attributes, int nb_defaulted,
28550                     const xmlChar ** attributes) {
28551     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28552     if (ctxt == NULL)
28553         return;
28554     if ((ctxt->user_sax != NULL) &&
28555         (ctxt->user_sax->startElementNs != NULL))
28556         ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28557                                        URI, nb_namespaces, namespaces,
28558                                        nb_attributes, nb_defaulted,
28559                                        attributes);
28560     if (ctxt->ctxt != NULL)
28561         xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28562                                          URI, nb_namespaces, namespaces,
28563                                          nb_attributes, nb_defaulted,
28564                                          attributes);
28565 }
28566
28567 static void
28568 endElementNsSplit(void *ctx, const xmlChar * localname,
28569                     const xmlChar * prefix, const xmlChar * URI) {
28570     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28571     if (ctxt == NULL)
28572         return;
28573     if ((ctxt->user_sax != NULL) &&
28574         (ctxt->user_sax->endElementNs != NULL))
28575         ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28576     if (ctxt->ctxt != NULL)
28577         xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28578 }
28579
28580 /**
28581  * xmlSchemaSAXPlug:
28582  * @ctxt:  a schema validation context
28583  * @sax:  a pointer to the original xmlSAXHandlerPtr
28584  * @user_data:  a pointer to the original SAX user data pointer
28585  *
28586  * Plug a SAX based validation layer in a SAX parsing event flow.
28587  * The original @saxptr and @dataptr data are replaced by new pointers
28588  * but the calls to the original will be maintained.
28589  *
28590  * Returns a pointer to a data structure needed to unplug the validation layer
28591  *         or NULL in case of errors.
28592  */
28593 xmlSchemaSAXPlugPtr
28594 xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28595                  xmlSAXHandlerPtr *sax, void **user_data)
28596 {
28597     xmlSchemaSAXPlugPtr ret;
28598     xmlSAXHandlerPtr old_sax;
28599
28600     if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28601         return(NULL);
28602
28603     /*
28604      * We only allow to plug into SAX2 event streams
28605      */
28606     old_sax = *sax;
28607     if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28608         return(NULL);
28609     if ((old_sax != NULL) &&
28610         (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28611         ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28612         return(NULL);
28613
28614     /*
28615      * everything seems right allocate the local data needed for that layer
28616      */
28617     ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28618     if (ret == NULL) {
28619         return(NULL);
28620     }
28621     memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28622     ret->magic = XML_SAX_PLUG_MAGIC;
28623     ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28624     ret->ctxt = ctxt;
28625     ret->user_sax_ptr = sax;
28626     ret->user_sax = old_sax;
28627     if (old_sax == NULL) {
28628         /*
28629          * go direct, no need for the split block and functions.
28630          */
28631         ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28632         ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28633         /*
28634          * Note that we use the same text-function for both, to prevent
28635          * the parser from testing for ignorable whitespace.
28636          */
28637         ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28638         ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28639
28640         ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28641         ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28642
28643         ret->user_data = ctxt;
28644         *user_data = ctxt;
28645     } else {
28646        /*
28647         * for each callback unused by Schemas initialize it to the Split
28648         * routine only if non NULL in the user block, this can speed up
28649         * things at the SAX level.
28650         */
28651         if (old_sax->internalSubset != NULL)
28652             ret->schemas_sax.internalSubset = internalSubsetSplit;
28653         if (old_sax->isStandalone != NULL)
28654             ret->schemas_sax.isStandalone = isStandaloneSplit;
28655         if (old_sax->hasInternalSubset != NULL)
28656             ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28657         if (old_sax->hasExternalSubset != NULL)
28658             ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28659         if (old_sax->resolveEntity != NULL)
28660             ret->schemas_sax.resolveEntity = resolveEntitySplit;
28661         if (old_sax->getEntity != NULL)
28662             ret->schemas_sax.getEntity = getEntitySplit;
28663         if (old_sax->entityDecl != NULL)
28664             ret->schemas_sax.entityDecl = entityDeclSplit;
28665         if (old_sax->notationDecl != NULL)
28666             ret->schemas_sax.notationDecl = notationDeclSplit;
28667         if (old_sax->attributeDecl != NULL)
28668             ret->schemas_sax.attributeDecl = attributeDeclSplit;
28669         if (old_sax->elementDecl != NULL)
28670             ret->schemas_sax.elementDecl = elementDeclSplit;
28671         if (old_sax->unparsedEntityDecl != NULL)
28672             ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28673         if (old_sax->setDocumentLocator != NULL)
28674             ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28675         if (old_sax->startDocument != NULL)
28676             ret->schemas_sax.startDocument = startDocumentSplit;
28677         if (old_sax->endDocument != NULL)
28678             ret->schemas_sax.endDocument = endDocumentSplit;
28679         if (old_sax->processingInstruction != NULL)
28680             ret->schemas_sax.processingInstruction = processingInstructionSplit;
28681         if (old_sax->comment != NULL)
28682             ret->schemas_sax.comment = commentSplit;
28683         if (old_sax->warning != NULL)
28684             ret->schemas_sax.warning = warningSplit;
28685         if (old_sax->error != NULL)
28686             ret->schemas_sax.error = errorSplit;
28687         if (old_sax->fatalError != NULL)
28688             ret->schemas_sax.fatalError = fatalErrorSplit;
28689         if (old_sax->getParameterEntity != NULL)
28690             ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28691         if (old_sax->externalSubset != NULL)
28692             ret->schemas_sax.externalSubset = externalSubsetSplit;
28693
28694         /*
28695          * the 6 schemas callback have to go to the splitter functions
28696          * Note that we use the same text-function for ignorableWhitespace
28697          * if possible, to prevent the parser from testing for ignorable
28698          * whitespace.
28699          */
28700         ret->schemas_sax.characters = charactersSplit;
28701         if ((old_sax->ignorableWhitespace != NULL) &&
28702             (old_sax->ignorableWhitespace != old_sax->characters))
28703             ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28704         else
28705             ret->schemas_sax.ignorableWhitespace = charactersSplit;
28706         ret->schemas_sax.cdataBlock = cdataBlockSplit;
28707         ret->schemas_sax.reference = referenceSplit;
28708         ret->schemas_sax.startElementNs = startElementNsSplit;
28709         ret->schemas_sax.endElementNs = endElementNsSplit;
28710
28711         ret->user_data_ptr = user_data;
28712         ret->user_data = *user_data;
28713         *user_data = ret;
28714     }
28715
28716     /*
28717      * plug the pointers back.
28718      */
28719     *sax = &(ret->schemas_sax);
28720     ctxt->sax = *sax;
28721     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28722     xmlSchemaPreRun(ctxt);
28723     return(ret);
28724 }
28725
28726 /**
28727  * xmlSchemaSAXUnplug:
28728  * @plug:  a data structure returned by xmlSchemaSAXPlug
28729  *
28730  * Unplug a SAX based validation layer in a SAX parsing event flow.
28731  * The original pointers used in the call are restored.
28732  *
28733  * Returns 0 in case of success and -1 in case of failure.
28734  */
28735 int
28736 xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28737 {
28738     xmlSAXHandlerPtr *sax;
28739     void **user_data;
28740
28741     if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28742         return(-1);
28743     plug->magic = 0;
28744
28745     xmlSchemaPostRun(plug->ctxt);
28746     /* restore the data */
28747     sax = plug->user_sax_ptr;
28748     *sax = plug->user_sax;
28749     if (plug->user_sax != NULL) {
28750         user_data = plug->user_data_ptr;
28751         *user_data = plug->user_data;
28752     }
28753
28754     /* free and return */
28755     xmlFree(plug);
28756     return(0);
28757 }
28758
28759 /**
28760  * xmlSchemaValidateSetLocator:
28761  * @vctxt: a schema validation context
28762  * @f: the locator function pointer
28763  * @ctxt: the locator context
28764  *
28765  * Allows to set a locator function to the validation context,
28766  * which will be used to provide file and line information since
28767  * those are not provided as part of the SAX validation flow
28768  * Setting @f to NULL disable the locator.
28769  */
28770
28771 void
28772 xmlSchemaValidateSetLocator(xmlSchemaValidCtxtPtr vctxt,
28773                             xmlSchemaValidityLocatorFunc f,
28774                             void *ctxt)
28775 {
28776     if (vctxt == NULL) return;
28777     vctxt->locFunc = f;
28778     vctxt->locCtxt = ctxt;
28779 }
28780
28781 /**
28782  * xmlSchemaValidateStreamLocator:
28783  * @ctx: the xmlTextReaderPtr used
28784  * @file: returned file information
28785  * @line: returned line information
28786  *
28787  * Internal locator function for the readers
28788  *
28789  * Returns 0 in case the Schema validation could be (des)activated and
28790  *         -1 in case of error.
28791  */
28792 static int
28793 xmlSchemaValidateStreamLocator(void *ctx, const char **file,
28794                                unsigned long *line) {
28795     xmlParserCtxtPtr ctxt;
28796
28797     if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
28798         return(-1);
28799
28800     if (file != NULL)
28801         *file = NULL;
28802     if (line != NULL)
28803         *line = 0;
28804
28805     ctxt = (xmlParserCtxtPtr) ctx;
28806     if (ctxt->input != NULL) {
28807        if (file != NULL)
28808            *file = ctxt->input->filename;
28809        if (line != NULL)
28810            *line = ctxt->input->line;
28811        return(0);
28812     }
28813     return(-1);
28814 }
28815
28816 /**
28817  * xmlSchemaValidateStream:
28818  * @ctxt:  a schema validation context
28819  * @input:  the input to use for reading the data
28820  * @enc:  an optional encoding information
28821  * @sax:  a SAX handler for the resulting events
28822  * @user_data:  the context to provide to the SAX handler.
28823  *
28824  * Validate an input based on a flow of SAX event from the parser
28825  * and forward the events to the @sax handler with the provided @user_data
28826  * the user provided @sax handler must be a SAX2 one.
28827  *
28828  * Returns 0 if the document is schemas valid, a positive error code
28829  *     number otherwise and -1 in case of internal or API error.
28830  */
28831 int
28832 xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
28833                         xmlParserInputBufferPtr input, xmlCharEncoding enc,
28834                         xmlSAXHandlerPtr sax, void *user_data)
28835 {
28836     xmlSchemaSAXPlugPtr plug = NULL;
28837     xmlSAXHandlerPtr old_sax = NULL;
28838     xmlParserCtxtPtr pctxt = NULL;
28839     xmlParserInputPtr inputStream = NULL;
28840     int ret;
28841
28842     if ((ctxt == NULL) || (input == NULL))
28843         return (-1);
28844
28845     /*
28846      * prepare the parser
28847      */
28848     pctxt = xmlNewParserCtxt();
28849     if (pctxt == NULL)
28850         return (-1);
28851     old_sax = pctxt->sax;
28852     pctxt->sax = sax;
28853     pctxt->userData = user_data;
28854 #if 0
28855     if (options)
28856         xmlCtxtUseOptions(pctxt, options);
28857 #endif
28858     pctxt->linenumbers = 1;
28859     xmlSchemaValidateSetLocator(ctxt, xmlSchemaValidateStreamLocator, pctxt);
28860
28861     inputStream = xmlNewIOInputStream(pctxt, input, enc);;
28862     if (inputStream == NULL) {
28863         ret = -1;
28864         goto done;
28865     }
28866     inputPush(pctxt, inputStream);
28867     ctxt->parserCtxt = pctxt;
28868     ctxt->input = input;
28869
28870     /*
28871      * Plug the validation and launch the parsing
28872      */
28873     plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28874     if (plug == NULL) {
28875         ret = -1;
28876         goto done;
28877     }
28878     ctxt->input = input;
28879     ctxt->enc = enc;
28880     ctxt->sax = pctxt->sax;
28881     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28882     ret = xmlSchemaVStart(ctxt);
28883
28884     if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28885         ret = ctxt->parserCtxt->errNo;
28886         if (ret == 0)
28887             ret = 1;
28888     }
28889
28890 done:
28891     ctxt->parserCtxt = NULL;
28892     ctxt->sax = NULL;
28893     ctxt->input = NULL;
28894     if (plug != NULL) {
28895         xmlSchemaSAXUnplug(plug);
28896     }
28897     /* cleanup */
28898     if (pctxt != NULL) {
28899         pctxt->sax = old_sax;
28900         xmlFreeParserCtxt(pctxt);
28901     }
28902     return (ret);
28903 }
28904
28905 /**
28906  * xmlSchemaValidateFile:
28907  * @ctxt: a schema validation context
28908  * @filename: the URI of the instance
28909  * @options: a future set of options, currently unused
28910  *
28911  * Do a schemas validation of the given resource, it will use the
28912  * SAX streamable validation internally.
28913  *
28914  * Returns 0 if the document is valid, a positive error code
28915  *     number otherwise and -1 in case of an internal or API error.
28916  */
28917 int
28918 xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
28919                       const char * filename,
28920                       int options ATTRIBUTE_UNUSED)
28921 {
28922     int ret;
28923     xmlParserInputBufferPtr input;
28924
28925     if ((ctxt == NULL) || (filename == NULL))
28926         return (-1);
28927
28928     input = xmlParserInputBufferCreateFilename(filename,
28929         XML_CHAR_ENCODING_NONE);
28930     if (input == NULL)
28931         return (-1);
28932     ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
28933         NULL, NULL);
28934     return (ret);
28935 }
28936
28937 /**
28938  * xmlSchemaValidCtxtGetParserCtxt:
28939  * @ctxt: a schema validation context
28940  *
28941  * allow access to the parser context of the schema validation context
28942  *
28943  * Returns the parser context of the schema validation context or NULL
28944  *         in case of error.
28945  */
28946 xmlParserCtxtPtr
28947 xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)
28948 {
28949     if (ctxt == NULL)
28950         return(NULL);
28951     return (ctxt->parserCtxt);
28952 }
28953
28954 #define bottom_xmlschemas
28955 #include "elfgcchack.h"
28956 #endif /* LIBXML_SCHEMAS_ENABLED */