0657b66a1fde684e1ba69e308dc17372835f7417
[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 #define IN_LIBXML
48 #include "libxml.h"
49
50 #ifdef LIBXML_SCHEMAS_ENABLED
51
52 #include <string.h>
53 #include <libxml/xmlmemory.h>
54 #include <libxml/parser.h>
55 #include <libxml/parserInternals.h>
56 #include <libxml/hash.h>
57 #include <libxml/uri.h>
58 #include <libxml/xmlschemas.h>
59 #include <libxml/schemasInternals.h>
60 #include <libxml/xmlschemastypes.h>
61 #include <libxml/xmlautomata.h>
62 #include <libxml/xmlregexp.h>
63 #include <libxml/dict.h>
64 #include <libxml/encoding.h>
65 #include <libxml/xmlIO.h>
66 #ifdef LIBXML_PATTERN_ENABLED
67 #include <libxml/pattern.h>
68 #endif
69 #ifdef LIBXML_READER_ENABLED
70 #include <libxml/xmlreader.h>
71 #endif
72
73 /* #define DEBUG 1 */
74
75 /* #define DEBUG_CONTENT 1 */
76
77 /* #define DEBUG_TYPE 1 */
78
79 /* #define DEBUG_CONTENT_REGEXP 1 */
80
81 /* #define DEBUG_AUTOMATA 1 */
82
83 /* #define DEBUG_IDC */
84
85 /* #define DEBUG_IDC_NODE_TABLE */
86
87 /* #define WXS_ELEM_DECL_CONS_ENABLED */
88
89 #ifdef DEBUG_IDC
90  #ifndef DEBUG_IDC_NODE_TABLE
91   #define DEBUG_IDC_NODE_TABLE
92  #endif
93 #endif
94
95 /* #define ENABLE_PARTICLE_RESTRICTION 1 */
96
97 #define ENABLE_REDEFINE
98
99 /* #define ENABLE_NAMED_LOCALS */
100
101 /* #define ENABLE_IDC_NODE_TABLES_TEST */
102
103 #define DUMP_CONTENT_MODEL
104
105 #ifdef LIBXML_READER_ENABLED
106 /* #define XML_SCHEMA_READER_ENABLED */
107 #endif
108
109 #define UNBOUNDED (1 << 30)
110 #define TODO                                                            \
111     xmlGenericError(xmlGenericErrorContext,                             \
112             "Unimplemented block at %s:%d\n",                           \
113             __FILE__, __LINE__);
114
115 #define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
116
117 /*
118  * The XML Schemas namespaces
119  */
120 static const xmlChar *xmlSchemaNs = (const xmlChar *)
121     "http://www.w3.org/2001/XMLSchema";
122
123 static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
124     "http://www.w3.org/2001/XMLSchema-instance";
125
126 static const xmlChar *xmlNamespaceNs = (const xmlChar *)
127     "http://www.w3.org/2000/xmlns/";
128
129 /*
130 * Come casting macros.
131 */
132 #define ACTXT_CAST (xmlSchemaAbstractCtxtPtr)
133 #define PCTXT_CAST (xmlSchemaParserCtxtPtr)
134 #define VCTXT_CAST (xmlSchemaValidCtxtPtr)
135 #define WXS_BASIC_CAST (xmlSchemaBasicItemPtr)
136 #define WXS_TREE_CAST (xmlSchemaTreeItemPtr)
137 #define WXS_PTC_CAST (xmlSchemaParticlePtr)
138 #define WXS_TYPE_CAST (xmlSchemaTypePtr)
139 #define WXS_ELEM_CAST (xmlSchemaElementPtr)
140 #define WXS_ATTR_GROUP_CAST (xmlSchemaAttributeGroupPtr)
141 #define WXS_ATTR_CAST (xmlSchemaAttributePtr)
142 #define WXS_ATTR_USE_CAST (xmlSchemaAttributeUsePtr)
143 #define WXS_ATTR_PROHIB_CAST (xmlSchemaAttributeUseProhibPtr)
144 #define WXS_MODEL_GROUPDEF_CAST (xmlSchemaModelGroupDefPtr)
145 #define WXS_MODEL_GROUP_CAST (xmlSchemaModelGroupPtr)
146 #define WXS_IDC_CAST (xmlSchemaIDCPtr)
147 #define WXS_QNAME_CAST (xmlSchemaQNameRefPtr)
148 #define WXS_LIST_CAST (xmlSchemaItemListPtr)
149
150 /*
151 * Macros to query common properties of components.
152 */
153 #define WXS_ITEM_NODE(i) xmlSchemaGetComponentNode(WXS_BASIC_CAST (i))
154
155 #define WXS_ITEM_TYPE_NAME(i) xmlSchemaGetComponentTypeStr(WXS_BASIC_CAST (i))
156 /*
157 * Macros for element declarations.
158 */
159 #define WXS_ELEM_TYPEDEF(e) (e)->subtypes
160
161 #define WXS_SUBST_HEAD(item) (item)->refDecl
162 /*
163 * Macros for attribute declarations.
164 */
165 #define WXS_ATTR_TYPEDEF(a) (a)->subtypes
166 /*
167 * Macros for attribute uses.
168 */
169 #define WXS_ATTRUSE_DECL(au) WXS_ATTR_CAST (WXS_ATTR_USE_CAST (au))->attrDecl
170
171 #define WXS_ATTRUSE_TYPEDEF(au) WXS_ATTR_TYPEDEF(WXS_ATTRUSE_DECL( WXS_ATTR_USE_CAST au))
172
173 #define WXS_ATTRUSE_DECL_NAME(au) (WXS_ATTRUSE_DECL(au))->name
174
175 #define WXS_ATTRUSE_DECL_TNS(au) (WXS_ATTRUSE_DECL(au))->targetNamespace
176 /*
177 * Macros for attribute groups.
178 */
179 #define WXS_ATTR_GROUP_HAS_REFS(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS)
180 #define WXS_ATTR_GROUP_EXPANDED(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED)
181 /*
182 * Macros for particles.
183 */
184 #define WXS_PARTICLE(p) WXS_PTC_CAST (p)
185
186 #define WXS_PARTICLE_TERM(p) (WXS_PARTICLE(p))->children
187
188 #define WXS_PARTICLE_TERM_AS_ELEM(p) (WXS_ELEM_CAST WXS_PARTICLE_TERM(p))
189
190 #define WXS_PARTICLE_MODEL(p) WXS_MODEL_GROUP_CAST WXS_PARTICLE(p)->children
191 /*
192 * Macros for model groups definitions.
193 */
194 #define WXS_MODELGROUPDEF_MODEL(mgd) (WXS_MODEL_GROUP_CAST (mgd))->children
195 /*
196 * Macros for model groups.
197 */
198 #define WXS_IS_MODEL_GROUP(i) \
199     (((i)->type == XML_SCHEMA_TYPE_SEQUENCE) || \
200      ((i)->type == XML_SCHEMA_TYPE_CHOICE) || \
201      ((i)->type == XML_SCHEMA_TYPE_ALL))
202
203 #define WXS_MODELGROUP_PARTICLE(mg) WXS_PTC_CAST (mg)->children
204 /*
205 * Macros for schema buckets.
206 */
207 #define WXS_IS_BUCKET_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \
208     ((t) == XML_SCHEMA_SCHEMA_REDEFINE))
209
210 #define WXS_IS_BUCKET_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \
211     ((t) == XML_SCHEMA_SCHEMA_IMPORT))
212
213 #define WXS_IMPBUCKET(b) ((xmlSchemaImportPtr) (b))
214
215 #define WXS_INCBUCKET(b) ((xmlSchemaIncludePtr) (b))
216 /*
217 * Macros for complex/simple types.
218 */
219 #define WXS_IS_ANYTYPE(i) \
220      (( (i)->type == XML_SCHEMA_TYPE_BASIC) && \
221       ( (WXS_TYPE_CAST (i))->builtInType == XML_SCHEMAS_ANYTYPE))
222
223 #define WXS_IS_COMPLEX(i) \
224     (((i)->type == XML_SCHEMA_TYPE_COMPLEX) || \
225      ((i)->builtInType == XML_SCHEMAS_ANYTYPE))
226
227 #define WXS_IS_SIMPLE(item) \
228     ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
229      ((item->type == XML_SCHEMA_TYPE_BASIC) && \
230       (item->builtInType != XML_SCHEMAS_ANYTYPE)))
231
232 #define WXS_IS_ANY_SIMPLE_TYPE(i) \
233     (((i)->type == XML_SCHEMA_TYPE_BASIC) && \
234       ((i)->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
235
236 #define WXS_IS_RESTRICTION(t) \
237     ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)
238
239 #define WXS_IS_EXTENSION(t) \
240     ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
241
242 #define WXS_IS_TYPE_NOT_FIXED(i) \
243     (((i)->type != XML_SCHEMA_TYPE_BASIC) && \
244      (((i)->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
245
246 #define WXS_IS_TYPE_NOT_FIXED_1(item) \
247     (((item)->type != XML_SCHEMA_TYPE_BASIC) && \
248      (((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0))
249
250 #define WXS_TYPE_IS_GLOBAL(t) ((t)->flags & XML_SCHEMAS_TYPE_GLOBAL)
251
252 #define WXS_TYPE_IS_LOCAL(t) (((t)->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0)
253 /*
254 * Macros for exclusively for complex types.
255 */
256 #define WXS_HAS_COMPLEX_CONTENT(item) \
257     ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
258      (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
259      (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
260
261 #define WXS_HAS_SIMPLE_CONTENT(item) \
262     ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
263      (item->contentType == XML_SCHEMA_CONTENT_BASIC))
264
265 #define WXS_HAS_MIXED_CONTENT(item) \
266     (item->contentType == XML_SCHEMA_CONTENT_MIXED)
267
268 #define WXS_EMPTIABLE(t) \
269     (xmlSchemaIsParticleEmptiable(WXS_PTC_CAST (t)->subtypes))
270
271 #define WXS_TYPE_CONTENTTYPE(t) (t)->subtypes
272
273 #define WXS_TYPE_PARTICLE(t) WXS_PTC_CAST (t)->subtypes
274
275 #define WXS_TYPE_PARTICLE_TERM(t) WXS_PARTICLE_TERM(WXS_TYPE_PARTICLE(t))
276 /*
277 * Macros for exclusively for simple types.
278 */
279 #define WXS_LIST_ITEMTYPE(t) (t)->subtypes
280
281 #define WXS_IS_ATOMIC(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
282
283 #define WXS_IS_LIST(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
284
285 #define WXS_IS_UNION(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
286 /*
287 * Misc parser context macros.
288 */
289 #define WXS_CONSTRUCTOR(ctx) (ctx)->constructor
290
291 #define WXS_HAS_BUCKETS(ctx) \
292 ( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \
293 (WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) )
294
295 #define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups
296
297 #define WXS_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket
298
299 #define WXS_SCHEMA(ctx) (ctx)->schema
300
301 #define WXS_ADD_LOCAL(ctx, item) \
302     xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, item)
303
304 #define WXS_ADD_GLOBAL(ctx, item) \
305     xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, item)
306
307 #define WXS_ADD_PENDING(ctx, item) \
308     xmlSchemaAddItemSize(&((ctx)->constructor->pending), 10, item)
309 /*
310 * xmlSchemaItemList macros.
311 */
312 #define WXS_ILIST_IS_EMPTY(l) ((l == NULL) || ((l)->nbItems == 0))
313 /*
314 * Misc macros.
315 */
316 #define IS_SCHEMA(node, type) \
317    ((node != NULL) && (node->ns != NULL) && \
318     (xmlStrEqual(node->name, (const xmlChar *) type)) && \
319     (xmlStrEqual(node->ns->href, xmlSchemaNs)))
320
321 #define FREE_AND_NULL(str) if ((str) != NULL) { xmlFree((xmlChar *) (str)); str = NULL; }
322
323 /*
324 * Since we put the default/fixed values into the dict, we can
325 * use pointer comparison for those values.
326 * REMOVED: (xmlStrEqual((v1), (v2)))
327 */
328 #define WXS_ARE_DEFAULT_STR_EQUAL(v1, v2) ((v1) == (v2))
329
330 #define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
331
332 #define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0))
333
334 #define HFAILURE if (res == -1) goto exit_failure;
335
336 #define HERROR if (res != 0) goto exit_error;
337
338 #define HSTOP(ctx) if ((ctx)->stop) goto exit;
339 /*
340 * Some flags used for various schema constraints.
341 */
342 #define SUBSET_RESTRICTION  1<<0
343 #define SUBSET_EXTENSION    1<<1
344 #define SUBSET_SUBSTITUTION 1<<2
345 #define SUBSET_LIST         1<<3
346 #define SUBSET_UNION        1<<4
347
348 typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
349 typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
350
351 typedef struct _xmlSchemaItemList xmlSchemaItemList;
352 typedef xmlSchemaItemList *xmlSchemaItemListPtr;
353 struct _xmlSchemaItemList {
354     void **items;  /* used for dynamic addition of schemata */
355     int nbItems; /* used for dynamic addition of schemata */
356     int sizeItems; /* used for dynamic addition of schemata */
357 };
358
359 #define XML_SCHEMA_CTXT_PARSER 1
360 #define XML_SCHEMA_CTXT_VALIDATOR 2
361
362 typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
363 typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
364 struct _xmlSchemaAbstractCtxt {
365     int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */
366 };
367
368 typedef struct _xmlSchemaBucket xmlSchemaBucket;
369 typedef xmlSchemaBucket *xmlSchemaBucketPtr;
370
371 #define XML_SCHEMA_SCHEMA_MAIN 0
372 #define XML_SCHEMA_SCHEMA_IMPORT 1
373 #define XML_SCHEMA_SCHEMA_INCLUDE 2
374 #define XML_SCHEMA_SCHEMA_REDEFINE 3
375
376 /**
377  * xmlSchemaSchemaRelation:
378  *
379  * Used to create a graph of schema relationships.
380  */
381 typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation;
382 typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr;
383 struct _xmlSchemaSchemaRelation {
384     xmlSchemaSchemaRelationPtr next;
385     int type; /* E.g. XML_SCHEMA_SCHEMA_IMPORT */
386     const xmlChar *importNamespace;
387     xmlSchemaBucketPtr bucket;
388 };
389
390 #define XML_SCHEMA_BUCKET_MARKED 1<<0
391 #define XML_SCHEMA_BUCKET_COMPS_ADDED 1<<1
392
393 struct _xmlSchemaBucket {
394     int type;
395     int flags;
396     const xmlChar *schemaLocation;
397     const xmlChar *origTargetNamespace;
398     const xmlChar *targetNamespace;
399     xmlDocPtr doc;
400     xmlSchemaSchemaRelationPtr relations;
401     int located;
402     int parsed;
403     int imported;
404     int preserveDoc;
405     xmlSchemaItemListPtr globals; /* Global components. */
406     xmlSchemaItemListPtr locals; /* Local components. */
407 };
408
409 /**
410  * xmlSchemaImport:
411  * (extends xmlSchemaBucket)
412  *
413  * Reflects a schema. Holds some information
414  * about the schema and its toplevel components. Duplicate
415  * toplevel components are not checked at this level.
416  */
417 typedef struct _xmlSchemaImport xmlSchemaImport;
418 typedef xmlSchemaImport *xmlSchemaImportPtr;
419 struct _xmlSchemaImport {
420     int type; /* Main OR import OR include. */
421     int flags;
422     const xmlChar *schemaLocation; /* The URI of the schema document. */
423     /* For chameleon includes, @origTargetNamespace will be NULL */
424     const xmlChar *origTargetNamespace;
425     /*
426     * For chameleon includes, @targetNamespace will be the
427     * targetNamespace of the including schema.
428     */
429     const xmlChar *targetNamespace;
430     xmlDocPtr doc; /* The schema node-tree. */
431     /* @relations will hold any included/imported/redefined schemas. */
432     xmlSchemaSchemaRelationPtr relations;
433     int located;
434     int parsed;
435     int imported;
436     int preserveDoc;
437     xmlSchemaItemListPtr globals;
438     xmlSchemaItemListPtr locals;
439     /* The imported schema. */
440     xmlSchemaPtr schema;
441 };
442
443 /*
444 * (extends xmlSchemaBucket)
445 */
446 typedef struct _xmlSchemaInclude xmlSchemaInclude;
447 typedef xmlSchemaInclude *xmlSchemaIncludePtr;
448 struct _xmlSchemaInclude {
449     int type;
450     int flags;
451     const xmlChar *schemaLocation;
452     const xmlChar *origTargetNamespace;
453     const xmlChar *targetNamespace;
454     xmlDocPtr doc;
455     xmlSchemaSchemaRelationPtr relations;
456     int located;
457     int parsed;
458     int imported;
459     int preserveDoc;
460     xmlSchemaItemListPtr globals; /* Global components. */
461     xmlSchemaItemListPtr locals; /* Local components. */
462
463     /* The owning main or import schema bucket. */
464     xmlSchemaImportPtr ownerImport;
465 };
466
467 /**
468  * xmlSchemaBasicItem:
469  *
470  * The abstract base type for schema components.
471  */
472 typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
473 typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
474 struct _xmlSchemaBasicItem {
475     xmlSchemaTypeType type;
476 };
477
478 /**
479  * xmlSchemaAnnotItem:
480  *
481  * The abstract base type for annotated schema components.
482  * (Extends xmlSchemaBasicItem)
483  */
484 typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
485 typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
486 struct _xmlSchemaAnnotItem {
487     xmlSchemaTypeType type;
488     xmlSchemaAnnotPtr annot;
489 };
490
491 /**
492  * xmlSchemaTreeItem:
493  *
494  * The abstract base type for tree-like structured schema components.
495  * (Extends xmlSchemaAnnotItem)
496  */
497 typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
498 typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
499 struct _xmlSchemaTreeItem {
500     xmlSchemaTypeType type;
501     xmlSchemaAnnotPtr annot;
502     xmlSchemaTreeItemPtr next;
503     xmlSchemaTreeItemPtr children;
504 };
505
506
507 #define XML_SCHEMA_ATTR_USE_FIXED 1<<0
508 /**
509  * xmlSchemaAttributeUsePtr:
510  *
511  * The abstract base type for tree-like structured schema components.
512  * (Extends xmlSchemaTreeItem)
513  */
514 typedef struct _xmlSchemaAttributeUse xmlSchemaAttributeUse;
515 typedef xmlSchemaAttributeUse *xmlSchemaAttributeUsePtr;
516 struct _xmlSchemaAttributeUse {
517     xmlSchemaTypeType type;
518     xmlSchemaAnnotPtr annot;
519     xmlSchemaAttributeUsePtr next; /* The next attr. use. */
520     /*
521     * The attr. decl. OR a QName-ref. to an attr. decl. OR
522     * a QName-ref. to an attribute group definition.
523     */
524     xmlSchemaAttributePtr attrDecl;
525
526     int flags;
527     xmlNodePtr node;
528     int occurs; /* required, optional */
529     const xmlChar * defValue;
530     xmlSchemaValPtr defVal;
531 };
532
533 /**
534  * xmlSchemaAttributeUseProhibPtr:
535  *
536  * A helper component to reflect attribute prohibitions.
537  * (Extends xmlSchemaBasicItem)
538  */
539 typedef struct _xmlSchemaAttributeUseProhib xmlSchemaAttributeUseProhib;
540 typedef xmlSchemaAttributeUseProhib *xmlSchemaAttributeUseProhibPtr;
541 struct _xmlSchemaAttributeUseProhib {
542     xmlSchemaTypeType type; /* == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB */
543     xmlNodePtr node;
544     const xmlChar *name;
545     const xmlChar *targetNamespace;
546     int isRef;
547 };
548
549 /**
550  * xmlSchemaRedef:
551  */
552 typedef struct _xmlSchemaRedef xmlSchemaRedef;
553 typedef xmlSchemaRedef *xmlSchemaRedefPtr;
554 struct _xmlSchemaRedef {
555     xmlSchemaRedefPtr next;
556     xmlSchemaBasicItemPtr item; /* The redefining component. */
557     xmlSchemaBasicItemPtr reference; /* The referencing component. */
558     xmlSchemaBasicItemPtr target; /* The to-be-redefined component. */
559     const xmlChar *refName; /* The name of the to-be-redefined component. */
560     const xmlChar *refTargetNs; /* The target namespace of the
561                                    to-be-redefined comp. */
562     xmlSchemaBucketPtr targetBucket; /* The redefined schema. */
563 };
564
565 /**
566  * xmlSchemaConstructionCtxt:
567  */
568 typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt;
569 typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr;
570 struct _xmlSchemaConstructionCtxt {
571     xmlSchemaPtr mainSchema; /* The main schema. */
572     xmlSchemaBucketPtr mainBucket; /* The main schema bucket */
573     xmlDictPtr dict;
574     xmlSchemaItemListPtr buckets; /* List of schema buckets. */
575     /* xmlSchemaItemListPtr relations; */ /* List of schema relations. */
576     xmlSchemaBucketPtr bucket; /* The current schema bucket */
577     xmlSchemaItemListPtr pending; /* All Components of all schemas that
578                                      need to be fixed. */
579     xmlHashTablePtr substGroups;
580     xmlSchemaRedefPtr redefs;
581     xmlSchemaRedefPtr lastRedef;
582 };
583
584 #define XML_SCHEMAS_PARSE_ERROR         1
585 #define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
586
587 struct _xmlSchemaParserCtxt {
588     int type;
589     void *errCtxt;             /* user specific error context */
590     xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */
591     xmlSchemaValidityWarningFunc warning;       /* the callback in case of warning */
592     int err;
593     int nberrors;
594     xmlStructuredErrorFunc serror;
595
596     xmlSchemaConstructionCtxtPtr constructor;
597     int ownsConstructor; /* TODO: Move this to parser *flags*. */
598
599     /* xmlSchemaPtr topschema;  */
600     /* xmlHashTablePtr namespaces;  */
601
602     xmlSchemaPtr schema;        /* The main schema in use */
603     int counter;
604
605     const xmlChar *URL;
606     xmlDocPtr doc;
607     int preserve;               /* Whether the doc should be freed  */
608
609     const char *buffer;
610     int size;
611
612     /*
613      * Used to build complex element content models
614      */
615     xmlAutomataPtr am;
616     xmlAutomataStatePtr start;
617     xmlAutomataStatePtr end;
618     xmlAutomataStatePtr state;
619
620     xmlDictPtr dict;            /* dictionnary for interned string names */
621     xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
622     int options;
623     xmlSchemaValidCtxtPtr vctxt;
624     int isS4S;
625     int isRedefine;
626     int xsiAssemble;
627     int stop; /* If the parser should stop; i.e. a critical error. */
628     const xmlChar *targetNamespace;
629     xmlSchemaBucketPtr redefined; /* The schema to be redefined. */
630
631     xmlSchemaRedefPtr redef; /* Used for redefinitions. */
632     int redefCounter; /* Used for redefinitions. */
633     xmlSchemaItemListPtr attrProhibs;
634 };
635
636 /**
637  * xmlSchemaQNameRef:
638  *
639  * A component reference item (not a schema component)
640  * (Extends xmlSchemaBasicItem)
641  */
642 typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
643 typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
644 struct _xmlSchemaQNameRef {
645     xmlSchemaTypeType type;
646     xmlSchemaBasicItemPtr item; /* The resolved referenced item. */
647     xmlSchemaTypeType itemType;
648     const xmlChar *name;
649     const xmlChar *targetNamespace;
650     xmlNodePtr node;
651 };
652
653 /**
654  * xmlSchemaParticle:
655  *
656  * A particle component.
657  * (Extends xmlSchemaTreeItem)
658  */
659 typedef struct _xmlSchemaParticle xmlSchemaParticle;
660 typedef xmlSchemaParticle *xmlSchemaParticlePtr;
661 struct _xmlSchemaParticle {
662     xmlSchemaTypeType type;
663     xmlSchemaAnnotPtr annot;
664     xmlSchemaTreeItemPtr next; /* next particle */
665     xmlSchemaTreeItemPtr children; /* the "term" (e.g. a model group,
666         a group definition, a XML_SCHEMA_EXTRA_QNAMEREF (if a reference),
667         etc.) */
668     int minOccurs;
669     int maxOccurs;
670     xmlNodePtr node;
671 };
672
673 /**
674  * xmlSchemaModelGroup:
675  *
676  * A model group component.
677  * (Extends xmlSchemaTreeItem)
678  */
679 typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
680 typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
681 struct _xmlSchemaModelGroup {
682     xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
683     xmlSchemaAnnotPtr annot;
684     xmlSchemaTreeItemPtr next; /* not used */
685     xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
686     xmlNodePtr node;
687 };
688
689 #define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
690 #define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1
691 /**
692  * xmlSchemaModelGroupDef:
693  *
694  * A model group definition component.
695  * (Extends xmlSchemaTreeItem)
696  */
697 typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
698 typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
699 struct _xmlSchemaModelGroupDef {
700     xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
701     xmlSchemaAnnotPtr annot;
702     xmlSchemaTreeItemPtr next; /* not used */
703     xmlSchemaTreeItemPtr children; /* the "model group" */
704     const xmlChar *name;
705     const xmlChar *targetNamespace;
706     xmlNodePtr node;
707     int flags;
708 };
709
710 typedef struct _xmlSchemaIDC xmlSchemaIDC;
711 typedef xmlSchemaIDC *xmlSchemaIDCPtr;
712
713 /**
714  * xmlSchemaIDCSelect:
715  *
716  * The identity-constraint "field" and "selector" item, holding the
717  * XPath expression.
718  */
719 typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
720 typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
721 struct _xmlSchemaIDCSelect {
722     xmlSchemaIDCSelectPtr next;
723     xmlSchemaIDCPtr idc;
724     int index; /* an index position if significant for IDC key-sequences */
725     const xmlChar *xpath; /* the XPath expression */
726     void *xpathComp; /* the compiled XPath expression */
727 };
728
729 /**
730  * xmlSchemaIDC:
731  *
732  * The identity-constraint definition component.
733  * (Extends xmlSchemaAnnotItem)
734  */
735
736 struct _xmlSchemaIDC {
737     xmlSchemaTypeType type;
738     xmlSchemaAnnotPtr annot;
739     xmlSchemaIDCPtr next;
740     xmlNodePtr node;
741     const xmlChar *name;
742     const xmlChar *targetNamespace;
743     xmlSchemaIDCSelectPtr selector;
744     xmlSchemaIDCSelectPtr fields;
745     int nbFields;
746     xmlSchemaQNameRefPtr ref;
747 };
748
749 /**
750  * xmlSchemaIDCAug:
751  *
752  * The augmented IDC information used for validation.
753  */
754 typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
755 typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
756 struct _xmlSchemaIDCAug {
757     xmlSchemaIDCAugPtr next; /* next in a list */
758     xmlSchemaIDCPtr def; /* the IDC definition */
759     int keyrefDepth; /* the lowest tree level to which IDC
760                         tables need to be bubbled upwards */
761 };
762
763 /**
764  * xmlSchemaPSVIIDCKeySequence:
765  *
766  * The key sequence of a node table item.
767  */
768 typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
769 typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
770 struct _xmlSchemaPSVIIDCKey {
771     xmlSchemaTypePtr type;
772     xmlSchemaValPtr val;
773 };
774
775 /**
776  * xmlSchemaPSVIIDCNode:
777  *
778  * The node table item of a node table.
779  */
780 typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
781 typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
782 struct _xmlSchemaPSVIIDCNode {
783     xmlNodePtr node;
784     xmlSchemaPSVIIDCKeyPtr *keys;
785     int nodeLine;
786     int nodeQNameID;
787
788 };
789
790 /**
791  * xmlSchemaPSVIIDCBinding:
792  *
793  * The identity-constraint binding item of the [identity-constraint table].
794  */
795 typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
796 typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
797 struct _xmlSchemaPSVIIDCBinding {
798     xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
799     xmlSchemaIDCPtr definition; /* the IDC definition */
800     xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
801     int nbNodes; /* number of entries in the node table */
802     int sizeNodes; /* size of the node table */
803     xmlSchemaItemListPtr dupls;
804 };
805
806
807 #define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
808 #define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
809
810 #define XPATH_STATE_OBJ_MATCHES -2
811 #define XPATH_STATE_OBJ_BLOCKED -3
812
813 typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
814 typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
815
816 /**
817  * xmlSchemaIDCStateObj:
818  *
819  * The state object used to evaluate XPath expressions.
820  */
821 typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
822 typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
823 struct _xmlSchemaIDCStateObj {
824     int type;
825     xmlSchemaIDCStateObjPtr next; /* next if in a list */
826     int depth; /* depth of creation */
827     int *history; /* list of (depth, state-id) tuples */
828     int nbHistory;
829     int sizeHistory;
830     xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
831                                        matcher */
832     xmlSchemaIDCSelectPtr sel;
833     void *xpathCtxt;
834 };
835
836 #define IDC_MATCHER 0
837
838 /**
839  * xmlSchemaIDCMatcher:
840  *
841  * Used to evaluate IDC selectors (and fields).
842  */
843 struct _xmlSchemaIDCMatcher {
844     int type;
845     int depth; /* the tree depth at creation time */
846     xmlSchemaIDCMatcherPtr next; /* next in the list */
847     xmlSchemaIDCMatcherPtr nextCached; /* next in the cache list */
848     xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
849     int idcType;
850     xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
851                                          elements */
852     int sizeKeySeqs;
853     xmlSchemaItemListPtr targets; /* list of target-node
854                                      (xmlSchemaPSVIIDCNodePtr) entries */
855 };
856
857 /*
858 * Element info flags.
859 */
860 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES  1<<0
861 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
862 #define XML_SCHEMA_ELEM_INFO_NILLED            1<<2
863 #define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE        1<<3
864
865 #define XML_SCHEMA_NODE_INFO_VALUE_NEEDED      1<<4
866 #define XML_SCHEMA_ELEM_INFO_EMPTY             1<<5
867 #define XML_SCHEMA_ELEM_INFO_HAS_CONTENT       1<<6
868
869 #define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT  1<<7
870 #define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT  1<<8
871 #define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED  1<<9
872 #define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE  1<<10
873
874 /**
875  * xmlSchemaNodeInfo:
876  *
877  * Holds information of an element node.
878  */
879 struct _xmlSchemaNodeInfo {
880     int nodeType;
881     xmlNodePtr node;
882     int nodeLine;
883     const xmlChar *localName;
884     const xmlChar *nsName;
885     const xmlChar *value;
886     xmlSchemaValPtr val; /* the pre-computed value if any */
887     xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
888
889     int flags; /* combination of node info flags */
890
891     int valNeeded;
892     int normVal;
893
894     xmlSchemaElementPtr decl; /* the element/attribute declaration */
895     int depth;
896     xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
897                                             for the scope element*/
898     xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
899                                            element */
900     xmlRegExecCtxtPtr regexCtxt;
901
902     const xmlChar **nsBindings; /* Namespace bindings on this element */
903     int nbNsBindings;
904     int sizeNsBindings;
905
906     int hasKeyrefs;
907     int appliedXPath; /* Indicates that an XPath has been applied. */
908 };
909
910 #define XML_SCHEMAS_ATTR_UNKNOWN 1
911 #define XML_SCHEMAS_ATTR_ASSESSED 2
912 #define XML_SCHEMAS_ATTR_PROHIBITED 3
913 #define XML_SCHEMAS_ATTR_ERR_MISSING 4
914 #define XML_SCHEMAS_ATTR_INVALID_VALUE 5
915 #define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
916 #define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
917 #define XML_SCHEMAS_ATTR_DEFAULT 8
918 #define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
919 #define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
920 #define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
921 #define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
922 #define XML_SCHEMAS_ATTR_WILD_SKIP 13
923 #define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
924 #define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
925 #define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
926 #define XML_SCHEMAS_ATTR_META 17
927 /*
928 * @metaType values of xmlSchemaAttrInfo.
929 */
930 #define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
931 #define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
932 #define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
933 #define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
934 #define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
935
936 typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
937 typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
938 struct _xmlSchemaAttrInfo {
939     int nodeType;
940     xmlNodePtr node;
941     int nodeLine;
942     const xmlChar *localName;
943     const xmlChar *nsName;
944     const xmlChar *value;
945     xmlSchemaValPtr val; /* the pre-computed value if any */
946     xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
947     int flags; /* combination of node info flags */
948
949     xmlSchemaAttributePtr decl; /* the attribute declaration */
950     xmlSchemaAttributeUsePtr use;  /* the attribute use */
951     int state;
952     int metaType;
953     const xmlChar *vcValue; /* the value constraint value */
954     xmlSchemaNodeInfoPtr parent;
955 };
956
957
958 #define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
959 /**
960  * xmlSchemaValidCtxt:
961  *
962  * A Schemas validation context
963  */
964 struct _xmlSchemaValidCtxt {
965     int type;
966     void *errCtxt;             /* user specific data block */
967     xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */
968     xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
969     xmlStructuredErrorFunc serror;
970
971     xmlSchemaPtr schema;        /* The schema in use */
972     xmlDocPtr doc;
973     xmlParserInputBufferPtr input;
974     xmlCharEncoding enc;
975     xmlSAXHandlerPtr sax;
976     xmlParserCtxtPtr parserCtxt;
977     void *user_data; /* TODO: What is this for? */
978     char *filename;
979
980     int err;
981     int nberrors;
982
983     xmlNodePtr node;
984     xmlNodePtr cur;
985     /* xmlSchemaTypePtr type; */
986
987     xmlRegExecCtxtPtr regexp;
988     xmlSchemaValPtr value;
989
990     int valueWS;
991     int options;
992     xmlNodePtr validationRoot;
993     xmlSchemaParserCtxtPtr pctxt;
994     int xsiAssemble;
995
996     int depth;
997     xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
998     int sizeElemInfos;
999     xmlSchemaNodeInfoPtr inode; /* the current element information */
1000
1001     xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
1002
1003     xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
1004     xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
1005     xmlSchemaIDCMatcherPtr idcMatcherCache; /* Cache for IDC matcher objects. */
1006
1007     xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
1008     int nbIdcNodes;
1009     int sizeIdcNodes;
1010
1011     xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
1012     int nbIdcKeys;
1013     int sizeIdcKeys;
1014
1015     int flags;
1016
1017     xmlDictPtr dict;
1018
1019 #ifdef LIBXML_READER_ENABLED
1020     xmlTextReaderPtr reader;
1021 #endif
1022
1023     xmlSchemaAttrInfoPtr *attrInfos;
1024     int nbAttrInfos;
1025     int sizeAttrInfos;
1026
1027     int skipDepth;
1028     xmlSchemaItemListPtr nodeQNames;
1029     int hasKeyrefs;
1030     int createIDCNodeTables;
1031     int psviExposeIDCNodeTables;
1032
1033     /* Locator for error reporting in streaming mode */
1034     xmlSchemaValidityLocatorFunc locFunc;
1035     void *locCtxt;
1036 };
1037
1038 /**
1039  * xmlSchemaSubstGroup:
1040  *
1041  *
1042  */
1043 typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
1044 typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
1045 struct _xmlSchemaSubstGroup {
1046     xmlSchemaElementPtr head;
1047     xmlSchemaItemListPtr members;
1048 };
1049
1050 /************************************************************************
1051  *                                                                      *
1052  *                      Some predeclarations                            *
1053  *                                                                      *
1054  ************************************************************************/
1055
1056 static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
1057                                  xmlSchemaPtr schema,
1058                                  xmlNodePtr node);
1059 static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
1060                                  xmlSchemaPtr schema,
1061                                  xmlNodePtr node);
1062 static int
1063 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
1064                    xmlSchemaAbstractCtxtPtr ctxt);
1065 static const xmlChar *
1066 xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
1067 static int
1068 xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1069                      xmlNodePtr node);
1070 static int
1071 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
1072                        xmlSchemaParserCtxtPtr ctxt);
1073 static void
1074 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
1075 static xmlSchemaWhitespaceValueType
1076 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
1077 static xmlSchemaTreeItemPtr
1078 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1079                          xmlNodePtr node, xmlSchemaTypeType type,
1080                          int withParticle);
1081 static const xmlChar *
1082 xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item);
1083 static xmlSchemaTypeLinkPtr
1084 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
1085 static void
1086 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1087                      const char *funcName,
1088                      const char *message);
1089 static int
1090 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt,
1091                              xmlSchemaTypePtr type,
1092                              xmlSchemaTypePtr baseType,
1093                              int subset);
1094 static void
1095 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
1096                                    xmlSchemaParserCtxtPtr ctxt);
1097 static void
1098 xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
1099 static xmlSchemaQNameRefPtr
1100 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
1101                                 xmlSchemaPtr schema,
1102                                 xmlNodePtr node);
1103
1104 /************************************************************************
1105  *                                                                      *
1106  *                      Helper functions                                *
1107  *                                                                      *
1108  ************************************************************************/
1109
1110 /**
1111  * xmlSchemaItemTypeToStr:
1112  * @type: the type of the schema item
1113  *
1114  * Returns the component name of a schema item.
1115  */
1116 static const xmlChar *
1117 xmlSchemaItemTypeToStr(xmlSchemaTypeType type)
1118 {
1119     switch (type) {
1120         case XML_SCHEMA_TYPE_BASIC:
1121             return(BAD_CAST "simple type definition");
1122         case XML_SCHEMA_TYPE_SIMPLE:
1123             return(BAD_CAST "simple type definition");
1124         case XML_SCHEMA_TYPE_COMPLEX:
1125             return(BAD_CAST "complex type definition");
1126         case XML_SCHEMA_TYPE_ELEMENT:
1127             return(BAD_CAST "element declaration");
1128         case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1129             return(BAD_CAST "attribute use");
1130         case XML_SCHEMA_TYPE_ATTRIBUTE:
1131             return(BAD_CAST "attribute declaration");
1132         case XML_SCHEMA_TYPE_GROUP:
1133             return(BAD_CAST "model group definition");
1134         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1135             return(BAD_CAST "attribute group definition");
1136         case XML_SCHEMA_TYPE_NOTATION:
1137             return(BAD_CAST "notation declaration");
1138         case XML_SCHEMA_TYPE_SEQUENCE:
1139             return(BAD_CAST "model group (sequence)");
1140         case XML_SCHEMA_TYPE_CHOICE:
1141             return(BAD_CAST "model group (choice)");
1142         case XML_SCHEMA_TYPE_ALL:
1143             return(BAD_CAST "model group (all)");
1144         case XML_SCHEMA_TYPE_PARTICLE:
1145             return(BAD_CAST "particle");
1146         case XML_SCHEMA_TYPE_IDC_UNIQUE:
1147             return(BAD_CAST "unique identity-constraint");
1148             /* return(BAD_CAST "IDC (unique)"); */
1149         case XML_SCHEMA_TYPE_IDC_KEY:
1150             return(BAD_CAST "key identity-constraint");
1151             /* return(BAD_CAST "IDC (key)"); */
1152         case XML_SCHEMA_TYPE_IDC_KEYREF:
1153             return(BAD_CAST "keyref identity-constraint");
1154             /* return(BAD_CAST "IDC (keyref)"); */
1155         case XML_SCHEMA_TYPE_ANY:
1156             return(BAD_CAST "wildcard (any)");
1157         case XML_SCHEMA_EXTRA_QNAMEREF:
1158             return(BAD_CAST "[helper component] QName reference");
1159         case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
1160             return(BAD_CAST "[helper component] attribute use prohibition");
1161         default:
1162             return(BAD_CAST "Not a schema component");
1163     }
1164 }
1165
1166 /**
1167  * xmlSchemaGetComponentTypeStr:
1168  * @type: the type of the schema item
1169  *
1170  * Returns the component name of a schema item.
1171  */
1172 static const xmlChar *
1173 xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)
1174 {
1175     switch (item->type) {
1176         case XML_SCHEMA_TYPE_BASIC:
1177             if (WXS_IS_COMPLEX(WXS_TYPE_CAST item))
1178                 return(BAD_CAST "complex type definition");
1179             else
1180                 return(BAD_CAST "simple type definition");
1181         default:
1182             return(xmlSchemaItemTypeToStr(item->type));
1183     }
1184 }
1185
1186 /**
1187  * xmlSchemaGetComponentNode:
1188  * @item: a schema component
1189  *
1190  * Returns node associated with the schema component.
1191  * NOTE that such a node need not be available; plus, a component's
1192  * node need not to reflect the component directly, since there is no
1193  * one-to-one relationship between the XML Schema representation and
1194  * the component representation.
1195  */
1196 static xmlNodePtr
1197 xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
1198 {
1199     switch (item->type) {
1200         case XML_SCHEMA_TYPE_ELEMENT:
1201             return (((xmlSchemaElementPtr) item)->node);
1202         case XML_SCHEMA_TYPE_ATTRIBUTE:
1203             return (((xmlSchemaAttributePtr) item)->node);
1204         case XML_SCHEMA_TYPE_COMPLEX:
1205         case XML_SCHEMA_TYPE_SIMPLE:
1206             return (((xmlSchemaTypePtr) item)->node);
1207         case XML_SCHEMA_TYPE_ANY:
1208         case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1209             return (((xmlSchemaWildcardPtr) item)->node);
1210         case XML_SCHEMA_TYPE_PARTICLE:
1211             return (((xmlSchemaParticlePtr) item)->node);
1212         case XML_SCHEMA_TYPE_SEQUENCE:
1213         case XML_SCHEMA_TYPE_CHOICE:
1214         case XML_SCHEMA_TYPE_ALL:
1215             return (((xmlSchemaModelGroupPtr) item)->node);
1216         case XML_SCHEMA_TYPE_GROUP:
1217             return (((xmlSchemaModelGroupDefPtr) item)->node);
1218         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1219             return (((xmlSchemaAttributeGroupPtr) item)->node);
1220         case XML_SCHEMA_TYPE_IDC_UNIQUE:
1221         case XML_SCHEMA_TYPE_IDC_KEY:
1222         case XML_SCHEMA_TYPE_IDC_KEYREF:
1223             return (((xmlSchemaIDCPtr) item)->node);
1224         case XML_SCHEMA_EXTRA_QNAMEREF:
1225             return(((xmlSchemaQNameRefPtr) item)->node);
1226         /* TODO: What to do with NOTATIONs?
1227         case XML_SCHEMA_TYPE_NOTATION:
1228             return (((xmlSchemaNotationPtr) item)->node);
1229         */
1230         case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1231             return (((xmlSchemaAttributeUsePtr) item)->node);
1232         default:
1233             return (NULL);
1234     }
1235 }
1236
1237 #if 0
1238 /**
1239  * xmlSchemaGetNextComponent:
1240  * @item: a schema component
1241  *
1242  * Returns the next sibling of the schema component.
1243  */
1244 static xmlSchemaBasicItemPtr
1245 xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1246 {
1247     switch (item->type) {
1248         case XML_SCHEMA_TYPE_ELEMENT:
1249             return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1250         case XML_SCHEMA_TYPE_ATTRIBUTE:
1251             return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1252         case XML_SCHEMA_TYPE_COMPLEX:
1253         case XML_SCHEMA_TYPE_SIMPLE:
1254             return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1255         case XML_SCHEMA_TYPE_ANY:
1256         case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1257             return (NULL);
1258         case XML_SCHEMA_TYPE_PARTICLE:
1259             return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1260         case XML_SCHEMA_TYPE_SEQUENCE:
1261         case XML_SCHEMA_TYPE_CHOICE:
1262         case XML_SCHEMA_TYPE_ALL:
1263             return (NULL);
1264         case XML_SCHEMA_TYPE_GROUP:
1265             return (NULL);
1266         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1267             return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1268         case XML_SCHEMA_TYPE_IDC_UNIQUE:
1269         case XML_SCHEMA_TYPE_IDC_KEY:
1270         case XML_SCHEMA_TYPE_IDC_KEYREF:
1271             return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1272         default:
1273             return (NULL);
1274     }
1275 }
1276 #endif
1277
1278
1279 /**
1280  * xmlSchemaFormatQName:
1281  * @buf: the string buffer
1282  * @namespaceName:  the namespace name
1283  * @localName: the local name
1284  *
1285  * Returns the given QName in the format "{namespaceName}localName" or
1286  * just "localName" if @namespaceName is NULL.
1287  *
1288  * Returns the localName if @namespaceName is NULL, a formatted
1289  * string otherwise.
1290  */
1291 static const xmlChar*
1292 xmlSchemaFormatQName(xmlChar **buf,
1293                      const xmlChar *namespaceName,
1294                      const xmlChar *localName)
1295 {
1296     FREE_AND_NULL(*buf)
1297     if (namespaceName != NULL) {
1298         *buf = xmlStrdup(BAD_CAST "{");
1299         *buf = xmlStrcat(*buf, namespaceName);
1300         *buf = xmlStrcat(*buf, BAD_CAST "}");
1301     }
1302     if (localName != NULL) {
1303         if (namespaceName == NULL)
1304             return(localName);
1305         *buf = xmlStrcat(*buf, localName);
1306     } else {
1307         *buf = xmlStrcat(*buf, BAD_CAST "(NULL)");
1308     }
1309     return ((const xmlChar *) *buf);
1310 }
1311
1312 static const xmlChar*
1313 xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
1314 {
1315     if (ns != NULL)
1316         return (xmlSchemaFormatQName(buf, ns->href, localName));
1317     else
1318         return (xmlSchemaFormatQName(buf, NULL, localName));
1319 }
1320
1321 static const xmlChar *
1322 xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1323 {
1324     switch (item->type) {
1325         case XML_SCHEMA_TYPE_ELEMENT:
1326             return (((xmlSchemaElementPtr) item)->name);
1327         case XML_SCHEMA_TYPE_ATTRIBUTE:
1328             return (((xmlSchemaAttributePtr) item)->name);
1329         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1330             return (((xmlSchemaAttributeGroupPtr) item)->name);
1331         case XML_SCHEMA_TYPE_BASIC:
1332         case XML_SCHEMA_TYPE_SIMPLE:
1333         case XML_SCHEMA_TYPE_COMPLEX:
1334             return (((xmlSchemaTypePtr) item)->name);
1335         case XML_SCHEMA_TYPE_GROUP:
1336             return (((xmlSchemaModelGroupDefPtr) item)->name);
1337         case XML_SCHEMA_TYPE_IDC_KEY:
1338         case XML_SCHEMA_TYPE_IDC_UNIQUE:
1339         case XML_SCHEMA_TYPE_IDC_KEYREF:
1340             return (((xmlSchemaIDCPtr) item)->name);
1341         case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1342             if (WXS_ATTRUSE_DECL(item) != NULL) {
1343                 return(xmlSchemaGetComponentName(
1344                     WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1345             } else
1346                 return(NULL);
1347         case XML_SCHEMA_EXTRA_QNAMEREF:
1348             return (((xmlSchemaQNameRefPtr) item)->name);
1349         case XML_SCHEMA_TYPE_NOTATION:
1350             return (((xmlSchemaNotationPtr) item)->name);
1351         default:
1352             /*
1353             * Other components cannot have names.
1354             */
1355             break;
1356     }
1357     return (NULL);
1358 }
1359
1360 #define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
1361 #define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
1362 /*
1363 static const xmlChar *
1364 xmlSchemaGetQNameRefName(void *ref)
1365 {
1366     return(((xmlSchemaQNameRefPtr) ref)->name);
1367 }
1368
1369 static const xmlChar *
1370 xmlSchemaGetQNameRefTargetNs(void *ref)
1371 {
1372     return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
1373 }
1374 */
1375
1376 static const xmlChar *
1377 xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1378 {
1379     switch (item->type) {
1380         case XML_SCHEMA_TYPE_ELEMENT:
1381             return (((xmlSchemaElementPtr) item)->targetNamespace);
1382         case XML_SCHEMA_TYPE_ATTRIBUTE:
1383             return (((xmlSchemaAttributePtr) item)->targetNamespace);
1384         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1385             return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1386         case XML_SCHEMA_TYPE_BASIC:
1387             return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1388         case XML_SCHEMA_TYPE_SIMPLE:
1389         case XML_SCHEMA_TYPE_COMPLEX:
1390             return (((xmlSchemaTypePtr) item)->targetNamespace);
1391         case XML_SCHEMA_TYPE_GROUP:
1392             return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1393         case XML_SCHEMA_TYPE_IDC_KEY:
1394         case XML_SCHEMA_TYPE_IDC_UNIQUE:
1395         case XML_SCHEMA_TYPE_IDC_KEYREF:
1396             return (((xmlSchemaIDCPtr) item)->targetNamespace);
1397         case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1398             if (WXS_ATTRUSE_DECL(item) != NULL) {
1399                 return(xmlSchemaGetComponentTargetNs(
1400                     WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1401             }
1402             /* TODO: Will returning NULL break something? */
1403             break;
1404         case XML_SCHEMA_EXTRA_QNAMEREF:
1405             return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
1406         case XML_SCHEMA_TYPE_NOTATION:
1407             return (((xmlSchemaNotationPtr) item)->targetNamespace);
1408         default:
1409             /*
1410             * Other components cannot have names.
1411             */
1412             break;
1413     }
1414     return (NULL);
1415 }
1416
1417 static const xmlChar*
1418 xmlSchemaGetComponentQName(xmlChar **buf,
1419                            void *item)
1420 {
1421     return (xmlSchemaFormatQName(buf,
1422         xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1423         xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1424 }
1425
1426 static const xmlChar*
1427 xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
1428 {
1429     xmlChar *str = NULL;
1430
1431     *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
1432     *buf = xmlStrcat(*buf, BAD_CAST " '");
1433     *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
1434         (xmlSchemaBasicItemPtr) item));
1435     *buf = xmlStrcat(*buf, BAD_CAST "'");
1436     FREE_AND_NULL(str);
1437     return(*buf);
1438 }
1439
1440 static const xmlChar*
1441 xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
1442 {
1443     return(xmlSchemaGetComponentDesignation(buf, idc));
1444 }
1445
1446 /**
1447  * xmlSchemaWildcardPCToString:
1448  * @pc: the type of processContents
1449  *
1450  * Returns a string representation of the type of
1451  * processContents.
1452  */
1453 static const xmlChar *
1454 xmlSchemaWildcardPCToString(int pc)
1455 {
1456     switch (pc) {
1457         case XML_SCHEMAS_ANY_SKIP:
1458             return (BAD_CAST "skip");
1459         case XML_SCHEMAS_ANY_LAX:
1460             return (BAD_CAST "lax");
1461         case XML_SCHEMAS_ANY_STRICT:
1462             return (BAD_CAST "strict");
1463         default:
1464             return (BAD_CAST "invalid process contents");
1465     }
1466 }
1467
1468 /**
1469  * xmlSchemaGetCanonValueWhtspExt:
1470  * @val: the precomputed value
1471  * @retValue: the returned value
1472  * @ws: the whitespace type of the value
1473  *
1474  * Get a the canonical representation of the value.
1475  * The caller has to free the returned retValue.
1476  *
1477  * Returns 0 if the value could be built and -1 in case of
1478  *         API errors or if the value type is not supported yet.
1479  */
1480 static int
1481 xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1482                                xmlSchemaWhitespaceValueType ws,
1483                                xmlChar **retValue)
1484 {
1485     int list;
1486     xmlSchemaValType valType;
1487     const xmlChar *value, *value2 = NULL;
1488
1489
1490     if ((retValue == NULL) || (val == NULL))
1491         return (-1);
1492     list = xmlSchemaValueGetNext(val) ? 1 : 0;
1493     *retValue = NULL;
1494     do {
1495         value = NULL;
1496         valType = xmlSchemaGetValType(val);
1497         switch (valType) {
1498             case XML_SCHEMAS_STRING:
1499             case XML_SCHEMAS_NORMSTRING:
1500             case XML_SCHEMAS_ANYSIMPLETYPE:
1501                 value = xmlSchemaValueGetAsString(val);
1502                 if (value != NULL) {
1503                     if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1504                         value2 = xmlSchemaCollapseString(value);
1505                     else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1506                         value2 = xmlSchemaWhiteSpaceReplace(value);
1507                     if (value2 != NULL)
1508                         value = value2;
1509                 }
1510                 break;
1511             default:
1512                 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1513                     if (value2 != NULL)
1514                         xmlFree((xmlChar *) value2);
1515                     goto internal_error;
1516                 }
1517                 value = value2;
1518         }
1519         if (*retValue == NULL)
1520             if (value == NULL) {
1521                 if (! list)
1522                     *retValue = xmlStrdup(BAD_CAST "");
1523             } else
1524                 *retValue = xmlStrdup(value);
1525         else if (value != NULL) {
1526             /* List. */
1527             *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1528             *retValue = xmlStrcat((xmlChar *) *retValue, value);
1529         }
1530         FREE_AND_NULL(value2)
1531         val = xmlSchemaValueGetNext(val);
1532     } while (val != NULL);
1533
1534     return (0);
1535 internal_error:
1536     if (*retValue != NULL)
1537         xmlFree((xmlChar *) (*retValue));
1538     if (value2 != NULL)
1539         xmlFree((xmlChar *) value2);
1540     return (-1);
1541 }
1542
1543 /**
1544  * xmlSchemaFormatItemForReport:
1545  * @buf: the string buffer
1546  * @itemDes: the designation of the item
1547  * @itemName: the name of the item
1548  * @item: the item as an object
1549  * @itemNode: the node of the item
1550  * @local: the local name
1551  * @parsing: if the function is used during the parse
1552  *
1553  * Returns a representation of the given item used
1554  * for error reports.
1555  *
1556  * The following order is used to build the resulting
1557  * designation if the arguments are not NULL:
1558  * 1a. If itemDes not NULL -> itemDes
1559  * 1b. If (itemDes not NULL) and (itemName not NULL)
1560  *     -> itemDes + itemName
1561  * 2. If the preceding was NULL and (item not NULL) -> item
1562  * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1563  *
1564  * If the itemNode is an attribute node, the name of the attribute
1565  * will be appended to the result.
1566  *
1567  * Returns the formatted string and sets @buf to the resulting value.
1568  */
1569 static xmlChar*
1570 xmlSchemaFormatItemForReport(xmlChar **buf,
1571                      const xmlChar *itemDes,
1572                      xmlSchemaBasicItemPtr item,
1573                      xmlNodePtr itemNode)
1574 {
1575     xmlChar *str = NULL;
1576     int named = 1;
1577
1578     if (*buf != NULL) {
1579         xmlFree(*buf);
1580         *buf = NULL;
1581     }
1582
1583     if (itemDes != NULL) {
1584         *buf = xmlStrdup(itemDes);
1585     } else if (item != NULL) {
1586         switch (item->type) {
1587         case XML_SCHEMA_TYPE_BASIC: {
1588             xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1589
1590             if (WXS_IS_ATOMIC(type))
1591                 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1592             else if (WXS_IS_LIST(type))
1593                 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
1594             else if (WXS_IS_UNION(type))
1595                 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1596             else
1597                 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1598             *buf = xmlStrcat(*buf, type->name);
1599             *buf = xmlStrcat(*buf, BAD_CAST "'");
1600             }
1601             break;
1602         case XML_SCHEMA_TYPE_SIMPLE: {
1603             xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1604
1605             if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1606                 *buf = xmlStrdup(BAD_CAST"");
1607             } else {
1608                 *buf = xmlStrdup(BAD_CAST "local ");
1609             }
1610             if (WXS_IS_ATOMIC(type))
1611                 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1612             else if (WXS_IS_LIST(type))
1613                 *buf = xmlStrcat(*buf, BAD_CAST "list type");
1614             else if (WXS_IS_UNION(type))
1615                 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1616             else
1617                 *buf = xmlStrcat(*buf, BAD_CAST "simple type");
1618             if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1619                 *buf = xmlStrcat(*buf, BAD_CAST " '");
1620                 *buf = xmlStrcat(*buf, type->name);
1621                 *buf = xmlStrcat(*buf, BAD_CAST "'");
1622             }
1623             }
1624             break;
1625         case XML_SCHEMA_TYPE_COMPLEX: {
1626             xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1627
1628             if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
1629                 *buf = xmlStrdup(BAD_CAST "");
1630             else
1631                 *buf = xmlStrdup(BAD_CAST "local ");
1632             *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1633             if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1634                 *buf = xmlStrcat(*buf, BAD_CAST " '");
1635                 *buf = xmlStrcat(*buf, type->name);
1636                 *buf = xmlStrcat(*buf, BAD_CAST "'");
1637             }
1638             }
1639             break;
1640         case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
1641                 xmlSchemaAttributeUsePtr ause;
1642
1643                 ause = WXS_ATTR_USE_CAST item;
1644                 *buf = xmlStrdup(BAD_CAST "attribute use ");
1645                 if (WXS_ATTRUSE_DECL(ause) != NULL) {
1646                     *buf = xmlStrcat(*buf, BAD_CAST "'");
1647                     *buf = xmlStrcat(*buf,
1648                         xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
1649                     FREE_AND_NULL(str)
1650                         *buf = xmlStrcat(*buf, BAD_CAST "'");
1651                 } else {
1652                     *buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
1653                 }
1654             }
1655             break;
1656         case XML_SCHEMA_TYPE_ATTRIBUTE: {
1657                 xmlSchemaAttributePtr attr;
1658
1659                 attr = (xmlSchemaAttributePtr) item;
1660                 *buf = xmlStrdup(BAD_CAST "attribute decl.");
1661                 *buf = xmlStrcat(*buf, BAD_CAST " '");
1662                 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1663                     attr->targetNamespace, attr->name));
1664                 FREE_AND_NULL(str)
1665                     *buf = xmlStrcat(*buf, BAD_CAST "'");
1666             }
1667             break;
1668         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1669             xmlSchemaGetComponentDesignation(buf, item);
1670             break;
1671         case XML_SCHEMA_TYPE_ELEMENT: {
1672                 xmlSchemaElementPtr elem;
1673
1674                 elem = (xmlSchemaElementPtr) item;
1675                 *buf = xmlStrdup(BAD_CAST "element decl.");
1676                 *buf = xmlStrcat(*buf, BAD_CAST " '");
1677                 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1678                     elem->targetNamespace, elem->name));
1679                 *buf = xmlStrcat(*buf, BAD_CAST "'");
1680             }
1681             break;
1682         case XML_SCHEMA_TYPE_IDC_UNIQUE:
1683         case XML_SCHEMA_TYPE_IDC_KEY:
1684         case XML_SCHEMA_TYPE_IDC_KEYREF:
1685             if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1686                 *buf = xmlStrdup(BAD_CAST "unique '");
1687             else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1688                 *buf = xmlStrdup(BAD_CAST "key '");
1689             else
1690                 *buf = xmlStrdup(BAD_CAST "keyRef '");
1691             *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1692             *buf = xmlStrcat(*buf, BAD_CAST "'");
1693             break;
1694         case XML_SCHEMA_TYPE_ANY:
1695         case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1696             *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1697                     ((xmlSchemaWildcardPtr) item)->processContents));
1698             *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1699             break;
1700         case XML_SCHEMA_FACET_MININCLUSIVE:
1701         case XML_SCHEMA_FACET_MINEXCLUSIVE:
1702         case XML_SCHEMA_FACET_MAXINCLUSIVE:
1703         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1704         case XML_SCHEMA_FACET_TOTALDIGITS:
1705         case XML_SCHEMA_FACET_FRACTIONDIGITS:
1706         case XML_SCHEMA_FACET_PATTERN:
1707         case XML_SCHEMA_FACET_ENUMERATION:
1708         case XML_SCHEMA_FACET_WHITESPACE:
1709         case XML_SCHEMA_FACET_LENGTH:
1710         case XML_SCHEMA_FACET_MAXLENGTH:
1711         case XML_SCHEMA_FACET_MINLENGTH:
1712             *buf = xmlStrdup(BAD_CAST "facet '");
1713             *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1714             *buf = xmlStrcat(*buf, BAD_CAST "'");
1715             break;
1716         case XML_SCHEMA_TYPE_GROUP: {
1717                 *buf = xmlStrdup(BAD_CAST "model group def.");
1718                 *buf = xmlStrcat(*buf, BAD_CAST " '");
1719                 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1720                 *buf = xmlStrcat(*buf, BAD_CAST "'");
1721                 FREE_AND_NULL(str)
1722             }
1723             break;
1724         case XML_SCHEMA_TYPE_SEQUENCE:
1725         case XML_SCHEMA_TYPE_CHOICE:
1726         case XML_SCHEMA_TYPE_ALL:
1727         case XML_SCHEMA_TYPE_PARTICLE:
1728             *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1729             break;
1730         case XML_SCHEMA_TYPE_NOTATION: {
1731                 *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1732                 *buf = xmlStrcat(*buf, BAD_CAST " '");
1733                 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1734                 *buf = xmlStrcat(*buf, BAD_CAST "'");
1735                 FREE_AND_NULL(str);
1736             }
1737         default:
1738             named = 0;
1739         }
1740     } else
1741         named = 0;
1742
1743     if ((named == 0) && (itemNode != NULL)) {
1744         xmlNodePtr elem;
1745
1746         if (itemNode->type == XML_ATTRIBUTE_NODE)
1747             elem = itemNode->parent;
1748         else
1749             elem = itemNode;
1750         *buf = xmlStrdup(BAD_CAST "Element '");
1751         if (elem->ns != NULL) {
1752             *buf = xmlStrcat(*buf,
1753                 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1754             FREE_AND_NULL(str)
1755         } else
1756             *buf = xmlStrcat(*buf, elem->name);
1757         *buf = xmlStrcat(*buf, BAD_CAST "'");
1758
1759     }
1760     if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1761         *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1762         if (itemNode->ns != NULL) {
1763             *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1764                 itemNode->ns->href, itemNode->name));
1765             FREE_AND_NULL(str)
1766         } else
1767             *buf = xmlStrcat(*buf, itemNode->name);
1768         *buf = xmlStrcat(*buf, BAD_CAST "'");
1769     }
1770     FREE_AND_NULL(str)
1771
1772     return (*buf);
1773 }
1774
1775 /**
1776  * xmlSchemaFormatFacetEnumSet:
1777  * @buf: the string buffer
1778  * @type: the type holding the enumeration facets
1779  *
1780  * Builds a string consisting of all enumeration elements.
1781  *
1782  * Returns a string of all enumeration elements.
1783  */
1784 static const xmlChar *
1785 xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1786                             xmlChar **buf, xmlSchemaTypePtr type)
1787 {
1788     xmlSchemaFacetPtr facet;
1789     xmlSchemaWhitespaceValueType ws;
1790     xmlChar *value = NULL;
1791     int res, found = 0;
1792
1793     if (*buf != NULL)
1794         xmlFree(*buf);
1795     *buf = NULL;
1796
1797     do {
1798         /*
1799         * Use the whitespace type of the base type.
1800         */
1801         ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1802         for (facet = type->facets; facet != NULL; facet = facet->next) {
1803             if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1804                 continue;
1805             found = 1;
1806             res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1807                 ws, &value);
1808             if (res == -1) {
1809                 xmlSchemaInternalErr(actxt,
1810                     "xmlSchemaFormatFacetEnumSet",
1811                     "compute the canonical lexical representation");
1812                 if (*buf != NULL)
1813                     xmlFree(*buf);
1814                 *buf = NULL;
1815                 return (NULL);
1816             }
1817             if (*buf == NULL)
1818                 *buf = xmlStrdup(BAD_CAST "'");
1819             else
1820                 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1821             *buf = xmlStrcat(*buf, BAD_CAST value);
1822             *buf = xmlStrcat(*buf, BAD_CAST "'");
1823             if (value != NULL) {
1824                 xmlFree((xmlChar *)value);
1825                 value = NULL;
1826             }
1827         }
1828         /*
1829         * The enumeration facet of a type restricts the enumeration
1830         * facet of the ancestor type; i.e., such restricted enumerations
1831         * do not belong to the set of the given type. Thus we break
1832         * on the first found enumeration.
1833         */
1834         if (found)
1835             break;
1836         type = type->baseType;
1837     } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1838
1839     return ((const xmlChar *) *buf);
1840 }
1841
1842 /************************************************************************
1843  *                                                                      *
1844  *                      Error functions                                 *
1845  *                                                                      *
1846  ************************************************************************/
1847
1848 #if 0
1849 static void
1850 xmlSchemaErrMemory(const char *msg)
1851 {
1852     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1853                      msg);
1854 }
1855 #endif
1856
1857 static void
1858 xmlSchemaPSimpleErr(const char *msg)
1859 {
1860     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1861                      msg);
1862 }
1863
1864 /**
1865  * xmlSchemaPErrMemory:
1866  * @node: a context node
1867  * @extra:  extra informations
1868  *
1869  * Handle an out of memory condition
1870  */
1871 static void
1872 xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1873                     const char *extra, xmlNodePtr node)
1874 {
1875     if (ctxt != NULL)
1876         ctxt->nberrors++;
1877     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1878                      extra);
1879 }
1880
1881 /**
1882  * xmlSchemaPErr:
1883  * @ctxt: the parsing context
1884  * @node: the context node
1885  * @error: the error code
1886  * @msg: the error message
1887  * @str1: extra data
1888  * @str2: extra data
1889  *
1890  * Handle a parser error
1891  */
1892 static void
1893 xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1894               const char *msg, const xmlChar * str1, const xmlChar * str2)
1895 {
1896     xmlGenericErrorFunc channel = NULL;
1897     xmlStructuredErrorFunc schannel = NULL;
1898     void *data = NULL;
1899
1900     if (ctxt != NULL) {
1901         ctxt->nberrors++;
1902         ctxt->err = error;
1903         channel = ctxt->error;
1904         data = ctxt->errCtxt;
1905         schannel = ctxt->serror;
1906     }
1907     __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1908                     error, XML_ERR_ERROR, NULL, 0,
1909                     (const char *) str1, (const char *) str2, NULL, 0, 0,
1910                     msg, str1, str2);
1911 }
1912
1913 /**
1914  * xmlSchemaPErr2:
1915  * @ctxt: the parsing context
1916  * @node: the context node
1917  * @node: the current child
1918  * @error: the error code
1919  * @msg: the error message
1920  * @str1: extra data
1921  * @str2: extra data
1922  *
1923  * Handle a parser error
1924  */
1925 static void
1926 xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1927                xmlNodePtr child, int error,
1928                const char *msg, const xmlChar * str1, const xmlChar * str2)
1929 {
1930     if (child != NULL)
1931         xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1932     else
1933         xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1934 }
1935
1936
1937 /**
1938  * xmlSchemaPErrExt:
1939  * @ctxt: the parsing context
1940  * @node: the context node
1941  * @error: the error code
1942  * @strData1: extra data
1943  * @strData2: extra data
1944  * @strData3: extra data
1945  * @msg: the message
1946  * @str1:  extra parameter for the message display
1947  * @str2:  extra parameter for the message display
1948  * @str3:  extra parameter for the message display
1949  * @str4:  extra parameter for the message display
1950  * @str5:  extra parameter for the message display
1951  *
1952  * Handle a parser error
1953  */
1954 static void
1955 xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1956                 const xmlChar * strData1, const xmlChar * strData2,
1957                 const xmlChar * strData3, const char *msg, const xmlChar * str1,
1958                 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1959                 const xmlChar * str5)
1960 {
1961
1962     xmlGenericErrorFunc channel = NULL;
1963     xmlStructuredErrorFunc schannel = NULL;
1964     void *data = NULL;
1965
1966     if (ctxt != NULL) {
1967         ctxt->nberrors++;
1968         ctxt->err = error;
1969         channel = ctxt->error;
1970         data = ctxt->errCtxt;
1971         schannel = ctxt->serror;
1972     }
1973     __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1974                     error, XML_ERR_ERROR, NULL, 0,
1975                     (const char *) strData1, (const char *) strData2,
1976                     (const char *) strData3, 0, 0, msg, str1, str2,
1977                     str3, str4, str5);
1978 }
1979
1980 /************************************************************************
1981  *                                                                      *
1982  *                      Allround error functions                        *
1983  *                                                                      *
1984  ************************************************************************/
1985
1986 /**
1987  * xmlSchemaVTypeErrMemory:
1988  * @node: a context node
1989  * @extra:  extra informations
1990  *
1991  * Handle an out of memory condition
1992  */
1993 static void
1994 xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
1995                     const char *extra, xmlNodePtr node)
1996 {
1997     if (ctxt != NULL) {
1998         ctxt->nberrors++;
1999         ctxt->err = XML_SCHEMAV_INTERNAL;
2000     }
2001     __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
2002                      extra);
2003 }
2004
2005 static void
2006 xmlSchemaPSimpleInternalErr(xmlNodePtr node,
2007                             const char *msg, const xmlChar *str)
2008 {
2009      __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node,
2010          msg, (const char *) str);
2011 }
2012
2013 #define WXS_ERROR_TYPE_ERROR 1
2014 #define WXS_ERROR_TYPE_WARNING 2
2015 /**
2016  * xmlSchemaErr3:
2017  * @ctxt: the validation context
2018  * @node: the context node
2019  * @error: the error code
2020  * @msg: the error message
2021  * @str1: extra data
2022  * @str2: extra data
2023  * @str3: extra data
2024  *
2025  * Handle a validation error
2026  */
2027 static void
2028 xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
2029                   xmlErrorLevel errorLevel,
2030                   int error, xmlNodePtr node, int line, const char *msg,
2031                   const xmlChar *str1, const xmlChar *str2,
2032                   const xmlChar *str3, const xmlChar *str4)
2033 {
2034     xmlStructuredErrorFunc schannel = NULL;
2035     xmlGenericErrorFunc channel = NULL;
2036     void *data = NULL;
2037
2038     if (ctxt != NULL) {
2039         if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2040             xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
2041             const char *file = NULL;
2042             int col = 0;
2043             if (errorLevel != XML_ERR_WARNING) {
2044                 vctxt->nberrors++;
2045                 vctxt->err = error;
2046                 channel = vctxt->error;
2047             } else {
2048                 channel = vctxt->warning;
2049             }
2050             schannel = vctxt->serror;
2051             data = vctxt->errCtxt;
2052
2053             /*
2054             * Error node. If we specify a line number, then
2055             * do not channel any node to the error function.
2056             */
2057             if (line == 0) {
2058                 if ((node == NULL) &&
2059                     (vctxt->depth >= 0) &&
2060                     (vctxt->inode != NULL)) {
2061                     node = vctxt->inode->node;
2062                 }
2063                 /*
2064                 * Get filename and line if no node-tree.
2065                 */
2066                 if ((node == NULL) &&
2067                     (vctxt->parserCtxt != NULL) &&
2068                     (vctxt->parserCtxt->input != NULL)) {
2069                     file = vctxt->parserCtxt->input->filename;
2070                     line = vctxt->parserCtxt->input->line;
2071                     col = vctxt->parserCtxt->input->col;
2072                 }
2073             } else {
2074                 /*
2075                 * Override the given node's (if any) position
2076                 * and channel only the given line number.
2077                 */
2078                 node = NULL;
2079                 /*
2080                 * Get filename.
2081                 */
2082                 if (vctxt->doc != NULL)
2083                     file = (const char *) vctxt->doc->URL;
2084                 else if ((vctxt->parserCtxt != NULL) &&
2085                     (vctxt->parserCtxt->input != NULL))
2086                     file = vctxt->parserCtxt->input->filename;
2087             }
2088             if (vctxt->locFunc != NULL) {
2089                 if ((file == NULL) || (line == 0)) {
2090                     unsigned long l;
2091                     const char *f;
2092                     vctxt->locFunc(vctxt->locCtxt, &f, &l);
2093                     if (file == NULL)
2094                         file = f;
2095                     if (line == 0)
2096                         line = (int) l;
2097                 }
2098             }
2099             if ((file == NULL) && (vctxt->filename != NULL))
2100                 file = vctxt->filename;
2101
2102             __xmlRaiseError(schannel, channel, data, ctxt,
2103                 node, XML_FROM_SCHEMASV,
2104                 error, errorLevel, file, line,
2105                 (const char *) str1, (const char *) str2,
2106                 (const char *) str3, 0, col, msg, str1, str2, str3, str4);
2107
2108         } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2109             xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
2110             if (errorLevel != XML_ERR_WARNING) {
2111                 pctxt->nberrors++;
2112                 pctxt->err = error;
2113                 channel = pctxt->error;
2114             } else {
2115                 channel = pctxt->warning;
2116             }
2117             schannel = pctxt->serror;
2118             data = pctxt->errCtxt;
2119             __xmlRaiseError(schannel, channel, data, ctxt,
2120                 node, XML_FROM_SCHEMASP, error,
2121                 errorLevel, NULL, 0,
2122                 (const char *) str1, (const char *) str2,
2123                 (const char *) str3, 0, 0, msg, str1, str2, str3, str4);
2124         } else {
2125             TODO
2126         }
2127     }
2128 }
2129
2130 /**
2131  * xmlSchemaErr3:
2132  * @ctxt: the validation context
2133  * @node: the context node
2134  * @error: the error code
2135  * @msg: the error message
2136  * @str1: extra data
2137  * @str2: extra data
2138  * @str3: extra data
2139  *
2140  * Handle a validation error
2141  */
2142 static void
2143 xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
2144               int error, xmlNodePtr node, const char *msg,
2145               const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
2146 {
2147     xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2148         msg, str1, str2, str3, NULL);
2149 }
2150
2151 static void
2152 xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
2153               int error, xmlNodePtr node, const char *msg,
2154               const xmlChar *str1, const xmlChar *str2,
2155               const xmlChar *str3, const xmlChar *str4)
2156 {
2157     xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2158         msg, str1, str2, str3, str4);
2159 }
2160
2161 static void
2162 xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2163              int error, xmlNodePtr node, const char *msg,
2164              const xmlChar *str1, const xmlChar *str2)
2165 {
2166     xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
2167 }
2168
2169 static xmlChar *
2170 xmlSchemaFormatNodeForError(xmlChar ** msg,
2171                             xmlSchemaAbstractCtxtPtr actxt,
2172                             xmlNodePtr node)
2173 {
2174     xmlChar *str = NULL;
2175
2176     *msg = NULL;
2177     if ((node != NULL) &&
2178         (node->type != XML_ELEMENT_NODE) &&
2179         (node->type != XML_ATTRIBUTE_NODE))
2180     {
2181         /*
2182         * Don't try to format other nodes than element and
2183         * attribute nodes.
2184         * Play save and return an empty string.
2185         */
2186         *msg = xmlStrdup(BAD_CAST "");
2187         return(*msg);
2188     }
2189     if (node != NULL) {
2190         /*
2191         * Work on tree nodes.
2192         */
2193         if (node->type == XML_ATTRIBUTE_NODE) {
2194             xmlNodePtr elem = node->parent;
2195
2196             *msg = xmlStrdup(BAD_CAST "Element '");
2197             if (elem->ns != NULL)
2198                 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2199                     elem->ns->href, elem->name));
2200             else
2201                 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2202                     NULL, elem->name));
2203             FREE_AND_NULL(str);
2204             *msg = xmlStrcat(*msg, BAD_CAST "', ");
2205             *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2206         } else {
2207             *msg = xmlStrdup(BAD_CAST "Element '");
2208         }
2209         if (node->ns != NULL)
2210             *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2211             node->ns->href, node->name));
2212         else
2213             *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2214             NULL, node->name));
2215         FREE_AND_NULL(str);
2216         *msg = xmlStrcat(*msg, BAD_CAST "': ");
2217     } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2218         xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2219         /*
2220         * Work on node infos.
2221         */
2222         if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2223             xmlSchemaNodeInfoPtr ielem =
2224                 vctxt->elemInfos[vctxt->depth];
2225
2226             *msg = xmlStrdup(BAD_CAST "Element '");
2227             *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2228                 ielem->nsName, ielem->localName));
2229             FREE_AND_NULL(str);
2230             *msg = xmlStrcat(*msg, BAD_CAST "', ");
2231             *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2232         } else {
2233             *msg = xmlStrdup(BAD_CAST "Element '");
2234         }
2235         *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2236             vctxt->inode->nsName, vctxt->inode->localName));
2237         FREE_AND_NULL(str);
2238         *msg = xmlStrcat(*msg, BAD_CAST "': ");
2239     } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
2240         /*
2241         * Hmm, no node while parsing?
2242         * Return an empty string, in case NULL will break something.
2243         */
2244         *msg = xmlStrdup(BAD_CAST "");
2245     } else {
2246         TODO
2247         return (NULL);
2248     }
2249     /*
2250     * VAL TODO: The output of the given schema component is currently
2251     * disabled.
2252     */
2253 #if 0
2254     if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2255         *msg = xmlStrcat(*msg, BAD_CAST " [");
2256         *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2257             NULL, type, NULL, 0));
2258         FREE_AND_NULL(str)
2259         *msg = xmlStrcat(*msg, BAD_CAST "]");
2260     }
2261 #endif
2262     return (*msg);
2263 }
2264
2265 static void
2266 xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
2267                      const char *funcName,
2268                      const char *message,
2269                      const xmlChar *str1,
2270                      const xmlChar *str2)
2271 {
2272     xmlChar *msg = NULL;
2273
2274     if (actxt == NULL)
2275         return;
2276     msg = xmlStrdup(BAD_CAST "Internal error: ");
2277     msg = xmlStrcat(msg, BAD_CAST funcName);
2278     msg = xmlStrcat(msg, BAD_CAST ", ");
2279     msg = xmlStrcat(msg, BAD_CAST message);
2280     msg = xmlStrcat(msg, BAD_CAST ".\n");
2281
2282     if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2283         xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
2284             (const char *) msg, str1, str2);
2285
2286     else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
2287         xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
2288             (const char *) msg, str1, str2);
2289
2290     FREE_AND_NULL(msg)
2291 }
2292
2293 static void
2294 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2295                      const char *funcName,
2296                      const char *message)
2297 {
2298     xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2299 }
2300
2301 #if 0
2302 static void
2303 xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2304                      const char *funcName,
2305                      const char *message,
2306                      const xmlChar *str1,
2307                      const xmlChar *str2)
2308 {
2309     xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
2310         str1, str2);
2311 }
2312 #endif
2313
2314 static void
2315 xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2316                    xmlParserErrors error,
2317                    xmlNodePtr node,
2318                    xmlSchemaBasicItemPtr item,
2319                    const char *message,
2320                    const xmlChar *str1, const xmlChar *str2,
2321                    const xmlChar *str3, const xmlChar *str4)
2322 {
2323     xmlChar *msg = NULL;
2324
2325     if ((node == NULL) && (item != NULL) &&
2326         (actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2327         node = WXS_ITEM_NODE(item);
2328         xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2329         msg = xmlStrcat(msg, BAD_CAST ": ");
2330     } else
2331         xmlSchemaFormatNodeForError(&msg, actxt, node);
2332     msg = xmlStrcat(msg, (const xmlChar *) message);
2333     msg = xmlStrcat(msg, BAD_CAST ".\n");
2334     xmlSchemaErr4(actxt, error, node,
2335         (const char *) msg, str1, str2, str3, str4);
2336     FREE_AND_NULL(msg)
2337 }
2338
2339 static void
2340 xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2341                    xmlParserErrors error,
2342                    xmlNodePtr node,
2343                    xmlSchemaBasicItemPtr item,
2344                    const char *message,
2345                    const xmlChar *str1,
2346                    const xmlChar *str2)
2347 {
2348     xmlSchemaCustomErr4(actxt, error, node, item,
2349         message, str1, str2, NULL, NULL);
2350 }
2351
2352
2353
2354 static void
2355 xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2356                    xmlParserErrors error,
2357                    xmlNodePtr node,
2358                    xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2359                    const char *message,
2360                    const xmlChar *str1,
2361                    const xmlChar *str2,
2362                    const xmlChar *str3)
2363 {
2364     xmlChar *msg = NULL;
2365
2366     xmlSchemaFormatNodeForError(&msg, actxt, node);
2367     msg = xmlStrcat(msg, (const xmlChar *) message);
2368     msg = xmlStrcat(msg, BAD_CAST ".\n");
2369
2370     /* URGENT TODO: Set the error code to something sane. */
2371     xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2372         (const char *) msg, str1, str2, str3, NULL);
2373
2374     FREE_AND_NULL(msg)
2375 }
2376
2377
2378
2379 static void
2380 xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2381                    xmlParserErrors error,
2382                    xmlSchemaPSVIIDCNodePtr idcNode,
2383                    xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2384                    const char *message,
2385                    const xmlChar *str1,
2386                    const xmlChar *str2)
2387 {
2388     xmlChar *msg = NULL, *qname = NULL;
2389
2390     msg = xmlStrdup(BAD_CAST "Element '%s': ");
2391     msg = xmlStrcat(msg, (const xmlChar *) message);
2392     msg = xmlStrcat(msg, BAD_CAST ".\n");
2393     xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
2394         error, NULL, idcNode->nodeLine, (const char *) msg,
2395         xmlSchemaFormatQName(&qname,
2396             vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2397             vctxt->nodeQNames->items[idcNode->nodeQNameID]),
2398         str1, str2, NULL);
2399     FREE_AND_NULL(qname);
2400     FREE_AND_NULL(msg);
2401 }
2402
2403 static int
2404 xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2405                            xmlNodePtr node)
2406 {
2407     if (node != NULL)
2408         return (node->type);
2409     if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2410         (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2411         return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2412     return (-1);
2413 }
2414
2415 static int
2416 xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2417 {
2418     switch (item->type) {
2419         case XML_SCHEMA_TYPE_COMPLEX:
2420         case XML_SCHEMA_TYPE_SIMPLE:
2421             if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2422                 return(1);
2423             break;
2424         case XML_SCHEMA_TYPE_GROUP:
2425             return (1);
2426         case XML_SCHEMA_TYPE_ELEMENT:
2427             if ( ((xmlSchemaElementPtr) item)->flags &
2428                 XML_SCHEMAS_ELEM_GLOBAL)
2429                 return(1);
2430             break;
2431         case XML_SCHEMA_TYPE_ATTRIBUTE:
2432             if ( ((xmlSchemaAttributePtr) item)->flags &
2433                 XML_SCHEMAS_ATTR_GLOBAL)
2434                 return(1);
2435             break;
2436         /* Note that attribute groups are always global. */
2437         default:
2438             return(1);
2439     }
2440     return (0);
2441 }
2442
2443 static void
2444 xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2445                        xmlParserErrors error,
2446                        xmlNodePtr node,
2447                        const xmlChar *value,
2448                        xmlSchemaTypePtr type,
2449                        int displayValue)
2450 {
2451     xmlChar *msg = NULL;
2452
2453     xmlSchemaFormatNodeForError(&msg, actxt, node);
2454
2455     if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2456             XML_ATTRIBUTE_NODE))
2457         msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2458     else
2459         msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2460             "value of ");
2461
2462     if (! xmlSchemaIsGlobalItem(type))
2463         msg = xmlStrcat(msg, BAD_CAST "the local ");
2464     else
2465         msg = xmlStrcat(msg, BAD_CAST "the ");
2466
2467     if (WXS_IS_ATOMIC(type))
2468         msg = xmlStrcat(msg, BAD_CAST "atomic type");
2469     else if (WXS_IS_LIST(type))
2470         msg = xmlStrcat(msg, BAD_CAST "list type");
2471     else if (WXS_IS_UNION(type))
2472         msg = xmlStrcat(msg, BAD_CAST "union type");
2473
2474     if (xmlSchemaIsGlobalItem(type)) {
2475         xmlChar *str = NULL;
2476         msg = xmlStrcat(msg, BAD_CAST " '");
2477         if (type->builtInType != 0) {
2478             msg = xmlStrcat(msg, BAD_CAST "xs:");
2479             msg = xmlStrcat(msg, type->name);
2480         } else
2481             msg = xmlStrcat(msg,
2482                 xmlSchemaFormatQName(&str,
2483                     type->targetNamespace, type->name));
2484         msg = xmlStrcat(msg, BAD_CAST "'");
2485         FREE_AND_NULL(str);
2486     }
2487     msg = xmlStrcat(msg, BAD_CAST ".\n");
2488     if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2489             XML_ATTRIBUTE_NODE))
2490         xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2491     else
2492         xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2493     FREE_AND_NULL(msg)
2494 }
2495
2496 static const xmlChar *
2497 xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2498                               xmlSchemaNodeInfoPtr ni,
2499                               xmlNodePtr node)
2500 {
2501     if (node != NULL) {
2502         if (node->ns != NULL)
2503             return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2504         else
2505             return (xmlSchemaFormatQName(str, NULL, node->name));
2506     } else if (ni != NULL)
2507         return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2508     return (NULL);
2509 }
2510
2511 static void
2512 xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2513                         xmlParserErrors error,
2514                         xmlSchemaAttrInfoPtr ni,
2515                         xmlNodePtr node)
2516 {
2517     xmlChar *msg = NULL, *str = NULL;
2518
2519     xmlSchemaFormatNodeForError(&msg, actxt, node);
2520     msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2521     xmlSchemaErr(actxt, error, node, (const char *) msg,
2522         xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2523         NULL);
2524     FREE_AND_NULL(str)
2525     FREE_AND_NULL(msg)
2526 }
2527
2528 static void
2529 xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2530                         xmlParserErrors error,
2531                         xmlNodePtr node,
2532                         xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2533                         const char *message,
2534                         int nbval,
2535                         int nbneg,
2536                         xmlChar **values)
2537 {
2538     xmlChar *str = NULL, *msg = NULL;
2539     xmlChar *localName, *nsName;
2540     const xmlChar *cur, *end;
2541     int i;
2542
2543     xmlSchemaFormatNodeForError(&msg, actxt, node);
2544     msg = xmlStrcat(msg, (const xmlChar *) message);
2545     msg = xmlStrcat(msg, BAD_CAST ".");
2546     /*
2547     * Note that is does not make sense to report that we have a
2548     * wildcard here, since the wildcard might be unfolded into
2549     * multiple transitions.
2550     */
2551     if (nbval + nbneg > 0) {
2552         if (nbval + nbneg > 1) {
2553             str = xmlStrdup(BAD_CAST " Expected is one of ( ");
2554         } else
2555             str = xmlStrdup(BAD_CAST " Expected is ( ");
2556         nsName = NULL;
2557
2558         for (i = 0; i < nbval + nbneg; i++) {
2559             cur = values[i];
2560             if (cur == NULL)
2561                 continue;
2562             if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2563                 (cur[3] == ' ')) {
2564                 cur += 4;
2565                 str = xmlStrcat(str, BAD_CAST "##other");
2566             }
2567             /*
2568             * Get the local name.
2569             */
2570             localName = NULL;
2571
2572             end = cur;
2573             if (*end == '*') {
2574                 localName = xmlStrdup(BAD_CAST "*");
2575                 end++;
2576             } else {
2577                 while ((*end != 0) && (*end != '|'))
2578                     end++;
2579                 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
2580             }
2581             if (*end != 0) {
2582                 end++;
2583                 /*
2584                 * Skip "*|*" if they come with negated expressions, since
2585                 * they represent the same negated wildcard.
2586                 */
2587                 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2588                     /*
2589                     * Get the namespace name.
2590                     */
2591                     cur = end;
2592                     if (*end == '*') {
2593                         nsName = xmlStrdup(BAD_CAST "{*}");
2594                     } else {
2595                         while (*end != 0)
2596                             end++;
2597
2598                         if (i >= nbval)
2599                             nsName = xmlStrdup(BAD_CAST "{##other:");
2600                         else
2601                             nsName = xmlStrdup(BAD_CAST "{");
2602
2603                         nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2604                         nsName = xmlStrcat(nsName, BAD_CAST "}");
2605                     }
2606                     str = xmlStrcat(str, BAD_CAST nsName);
2607                     FREE_AND_NULL(nsName)
2608                 } else {
2609                     FREE_AND_NULL(localName);
2610                     continue;
2611                 }
2612             }
2613             str = xmlStrcat(str, BAD_CAST localName);
2614             FREE_AND_NULL(localName);
2615
2616             if (i < nbval + nbneg -1)
2617                 str = xmlStrcat(str, BAD_CAST ", ");
2618         }
2619         str = xmlStrcat(str, BAD_CAST " ).\n");
2620         msg = xmlStrcat(msg, BAD_CAST str);
2621         FREE_AND_NULL(str)
2622     } else
2623       msg = xmlStrcat(msg, BAD_CAST "\n");
2624     xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2625     xmlFree(msg);
2626 }
2627
2628 static void
2629 xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2630                   xmlParserErrors error,
2631                   xmlNodePtr node,
2632                   const xmlChar *value,
2633                   unsigned long length,
2634                   xmlSchemaTypePtr type,
2635                   xmlSchemaFacetPtr facet,
2636                   const char *message,
2637                   const xmlChar *str1,
2638                   const xmlChar *str2)
2639 {
2640     xmlChar *str = NULL, *msg = NULL;
2641     xmlSchemaTypeType facetType;
2642     int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2643
2644     xmlSchemaFormatNodeForError(&msg, actxt, node);
2645     if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2646         facetType = XML_SCHEMA_FACET_ENUMERATION;
2647         /*
2648         * If enumerations are validated, one must not expect the
2649         * facet to be given.
2650         */
2651     } else
2652         facetType = facet->type;
2653     msg = xmlStrcat(msg, BAD_CAST "[");
2654     msg = xmlStrcat(msg, BAD_CAST "facet '");
2655     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2656     msg = xmlStrcat(msg, BAD_CAST "'] ");
2657     if (message == NULL) {
2658         /*
2659         * Use a default message.
2660         */
2661         if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2662             (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2663             (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2664
2665             char len[25], actLen[25];
2666
2667             /* FIXME, TODO: What is the max expected string length of the
2668             * this value?
2669             */
2670             if (nodeType == XML_ATTRIBUTE_NODE)
2671                 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2672             else
2673                 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2674
2675             snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2676             snprintf(actLen, 24, "%lu", length);
2677
2678             if (facetType == XML_SCHEMA_FACET_LENGTH)
2679                 msg = xmlStrcat(msg,
2680                 BAD_CAST "this differs from the allowed length of '%s'.\n");
2681             else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2682                 msg = xmlStrcat(msg,
2683                 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2684             else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2685                 msg = xmlStrcat(msg,
2686                 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2687
2688             if (nodeType == XML_ATTRIBUTE_NODE)
2689                 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2690                     value, (const xmlChar *) actLen, (const xmlChar *) len);
2691             else
2692                 xmlSchemaErr(actxt, error, node, (const char *) msg,
2693                     (const xmlChar *) actLen, (const xmlChar *) len);
2694
2695         } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2696             msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2697                 "of the set {%s}.\n");
2698             xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2699                 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2700         } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2701             msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2702                 "by the pattern '%s'.\n");
2703             xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2704                 facet->value);
2705         } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2706             msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2707                 "minimum value allowed ('%s').\n");
2708             xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2709                 facet->value);
2710         } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2711             msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2712                 "maximum value allowed ('%s').\n");
2713             xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2714                 facet->value);
2715         } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2716             msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
2717                 "'%s'.\n");
2718             xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2719                 facet->value);
2720         } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2721             msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2722                 "'%s'.\n");
2723             xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2724                 facet->value);
2725         } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2726             msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2727                 "digits than are allowed ('%s').\n");
2728             xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2729                 facet->value);
2730         } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2731             msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2732                 "digits than are allowed ('%s').\n");
2733             xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2734                 facet->value);
2735         } else if (nodeType == XML_ATTRIBUTE_NODE) {
2736             msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2737             xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2738         } else {
2739             msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2740             xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2741         }
2742     } else {
2743         msg = xmlStrcat(msg, (const xmlChar *) message);
2744         msg = xmlStrcat(msg, BAD_CAST ".\n");
2745         xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2746     }
2747     FREE_AND_NULL(str)
2748     xmlFree(msg);
2749 }
2750
2751 #define VERROR(err, type, msg) \
2752     xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
2753
2754 #define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
2755
2756 #define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2757 #define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
2758
2759 #define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2760
2761
2762 /**
2763  * xmlSchemaPMissingAttrErr:
2764  * @ctxt: the schema validation context
2765  * @ownerDes: the designation of  the owner
2766  * @ownerName: the name of the owner
2767  * @ownerItem: the owner as a schema object
2768  * @ownerElem: the owner as an element node
2769  * @node: the parent element node of the missing attribute node
2770  * @type: the corresponding type of the attribute node
2771  *
2772  * Reports an illegal attribute.
2773  */
2774 static void
2775 xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
2776                          xmlParserErrors error,
2777                          xmlSchemaBasicItemPtr ownerItem,
2778                          xmlNodePtr ownerElem,
2779                          const char *name,
2780                          const char *message)
2781 {
2782     xmlChar *des = NULL;
2783
2784     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2785
2786     if (message != NULL)
2787         xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
2788     else
2789         xmlSchemaPErr(ctxt, ownerElem, error,
2790             "%s: The attribute '%s' is required but missing.\n",
2791             BAD_CAST des, BAD_CAST name);
2792     FREE_AND_NULL(des);
2793 }
2794
2795
2796 /**
2797  * xmlSchemaPResCompAttrErr:
2798  * @ctxt: the schema validation context
2799  * @error: the error code
2800  * @ownerDes: the designation of  the owner
2801  * @ownerItem: the owner as a schema object
2802  * @ownerElem: the owner as an element node
2803  * @name: the name of the attribute holding the QName
2804  * @refName: the referenced local name
2805  * @refURI: the referenced namespace URI
2806  * @message: optional message
2807  *
2808  * Used to report QName attribute values that failed to resolve
2809  * to schema components.
2810  */
2811 static void
2812 xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
2813                          xmlParserErrors error,
2814                          xmlSchemaBasicItemPtr ownerItem,
2815                          xmlNodePtr ownerElem,
2816                          const char *name,
2817                          const xmlChar *refName,
2818                          const xmlChar *refURI,
2819                          xmlSchemaTypeType refType,
2820                          const char *refTypeStr)
2821 {
2822     xmlChar *des = NULL, *strA = NULL;
2823
2824     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2825     if (refTypeStr == NULL)
2826         refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
2827         xmlSchemaPErrExt(ctxt, ownerElem, error,
2828             NULL, NULL, NULL,
2829             "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2830             "%s.\n", BAD_CAST des, BAD_CAST name,
2831             xmlSchemaFormatQName(&strA, refURI, refName),
2832             BAD_CAST refTypeStr, NULL);
2833     FREE_AND_NULL(des)
2834     FREE_AND_NULL(strA)
2835 }
2836
2837 /**
2838  * xmlSchemaPCustomAttrErr:
2839  * @ctxt: the schema parser context
2840  * @error: the error code
2841  * @ownerDes: the designation of the owner
2842  * @ownerItem: the owner as a schema object
2843  * @attr: the illegal attribute node
2844  *
2845  * Reports an illegal attribute during the parse.
2846  */
2847 static void
2848 xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
2849                         xmlParserErrors error,
2850                         xmlChar **ownerDes,
2851                         xmlSchemaBasicItemPtr ownerItem,
2852                         xmlAttrPtr attr,
2853                         const char *msg)
2854 {
2855     xmlChar *des = NULL;
2856
2857     if (ownerDes == NULL)
2858         xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
2859     else if (*ownerDes == NULL) {
2860         xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
2861         des = *ownerDes;
2862     } else
2863         des = *ownerDes;
2864     if (attr == NULL) {
2865         xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL,
2866             "%s, attribute '%s': %s.\n",
2867             BAD_CAST des, (const xmlChar *) "Unknown",
2868             (const xmlChar *) msg, NULL, NULL);
2869     } else {
2870         xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2871             "%s, attribute '%s': %s.\n",
2872             BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2873     }
2874     if (ownerDes == NULL)
2875         FREE_AND_NULL(des);
2876 }
2877
2878 /**
2879  * xmlSchemaPIllegalAttrErr:
2880  * @ctxt: the schema parser context
2881  * @error: the error code
2882  * @ownerDes: the designation of the attribute's owner
2883  * @ownerItem: the attribute's owner item
2884  * @attr: the illegal attribute node
2885  *
2886  * Reports an illegal attribute during the parse.
2887  */
2888 static void
2889 xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
2890                          xmlParserErrors error,
2891                          xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
2892                          xmlAttrPtr attr)
2893 {
2894     xmlChar *strA = NULL, *strB = NULL;
2895
2896     xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2897     xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2898         "%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2899         xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2900         NULL, NULL);
2901     FREE_AND_NULL(strA);
2902     FREE_AND_NULL(strB);
2903 }
2904
2905 /**
2906  * xmlSchemaPCustomErr:
2907  * @ctxt: the schema parser context
2908  * @error: the error code
2909  * @itemDes: the designation of the schema item
2910  * @item: the schema item
2911  * @itemElem: the node of the schema item
2912  * @message: the error message
2913  * @str1: an optional param for the error message
2914  * @str2: an optional param for the error message
2915  * @str3: an optional param for the error message
2916  *
2917  * Reports an error during parsing.
2918  */
2919 static void
2920 xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
2921                     xmlParserErrors error,
2922                     xmlSchemaBasicItemPtr item,
2923                     xmlNodePtr itemElem,
2924                     const char *message,
2925                     const xmlChar *str1,
2926                     const xmlChar *str2,
2927                     const xmlChar *str3)
2928 {
2929     xmlChar *des = NULL, *msg = NULL;
2930
2931     xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
2932     msg = xmlStrdup(BAD_CAST "%s: ");
2933     msg = xmlStrcat(msg, (const xmlChar *) message);
2934     msg = xmlStrcat(msg, BAD_CAST ".\n");
2935     if ((itemElem == NULL) && (item != NULL))
2936         itemElem = WXS_ITEM_NODE(item);
2937     xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
2938         (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2939     FREE_AND_NULL(des);
2940     FREE_AND_NULL(msg);
2941 }
2942
2943 /**
2944  * xmlSchemaPCustomErr:
2945  * @ctxt: the schema parser context
2946  * @error: the error code
2947  * @itemDes: the designation of the schema item
2948  * @item: the schema item
2949  * @itemElem: the node of the schema item
2950  * @message: the error message
2951  * @str1: the optional param for the error message
2952  *
2953  * Reports an error during parsing.
2954  */
2955 static void
2956 xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
2957                     xmlParserErrors error,
2958                     xmlSchemaBasicItemPtr item,
2959                     xmlNodePtr itemElem,
2960                     const char *message,
2961                     const xmlChar *str1)
2962 {
2963     xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
2964         str1, NULL, NULL);
2965 }
2966
2967 /**
2968  * xmlSchemaPAttrUseErr:
2969  * @ctxt: the schema parser context
2970  * @error: the error code
2971  * @itemDes: the designation of the schema type
2972  * @item: the schema type
2973  * @itemElem: the node of the schema type
2974  * @attr: the invalid schema attribute
2975  * @message: the error message
2976  * @str1: the optional param for the error message
2977  *
2978  * Reports an attribute use error during parsing.
2979  */
2980 static void
2981 xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
2982                     xmlParserErrors error,
2983                     xmlNodePtr node,
2984                     xmlSchemaBasicItemPtr ownerItem,
2985                     const xmlSchemaAttributeUsePtr attruse,
2986                     const char *message,
2987                     const xmlChar *str1, const xmlChar *str2,
2988                     const xmlChar *str3,const xmlChar *str4)
2989 {
2990     xmlChar *str = NULL, *msg = NULL;
2991
2992     xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
2993     msg = xmlStrcat(msg, BAD_CAST ", ");
2994     msg = xmlStrcat(msg,
2995         BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
2996         WXS_BASIC_CAST attruse, NULL));
2997     FREE_AND_NULL(str);
2998     msg = xmlStrcat(msg, BAD_CAST ": ");
2999     msg = xmlStrcat(msg, (const xmlChar *) message);
3000     msg = xmlStrcat(msg, BAD_CAST ".\n");
3001     xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
3002         (const char *) msg, str1, str2, str3, str4);
3003     xmlFree(msg);
3004 }
3005
3006 /**
3007  * xmlSchemaPIllegalFacetAtomicErr:
3008  * @ctxt: the schema parser context
3009  * @error: the error code
3010  * @type: the schema type
3011  * @baseType: the base type of type
3012  * @facet: the illegal facet
3013  *
3014  * Reports an illegal facet for atomic simple types.
3015  */
3016 static void
3017 xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
3018                           xmlParserErrors error,
3019                           xmlSchemaTypePtr type,
3020                           xmlSchemaTypePtr baseType,
3021                           xmlSchemaFacetPtr facet)
3022 {
3023     xmlChar *des = NULL, *strT = NULL;
3024
3025     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
3026     xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
3027         "%s: The facet '%s' is not allowed on types derived from the "
3028         "type %s.\n",
3029         BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
3030         xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
3031         NULL, NULL);
3032     FREE_AND_NULL(des);
3033     FREE_AND_NULL(strT);
3034 }
3035
3036 /**
3037  * xmlSchemaPIllegalFacetListUnionErr:
3038  * @ctxt: the schema parser context
3039  * @error: the error code
3040  * @itemDes: the designation of the schema item involved
3041  * @item: the schema item involved
3042  * @facet: the illegal facet
3043  *
3044  * Reports an illegal facet for <list> and <union>.
3045  */
3046 static void
3047 xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
3048                           xmlParserErrors error,
3049                           xmlSchemaTypePtr type,
3050                           xmlSchemaFacetPtr facet)
3051 {
3052     xmlChar *des = NULL;
3053
3054     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3055         type->node);
3056     xmlSchemaPErr(ctxt, type->node, error,
3057         "%s: The facet '%s' is not allowed.\n",
3058         BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
3059     FREE_AND_NULL(des);
3060 }
3061
3062 /**
3063  * xmlSchemaPMutualExclAttrErr:
3064  * @ctxt: the schema validation context
3065  * @error: the error code
3066  * @elemDes: the designation of the parent element node
3067  * @attr: the bad attribute node
3068  * @type: the corresponding type of the attribute node
3069  *
3070  * Reports an illegal attribute.
3071  */
3072 static void
3073 xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3074                          xmlParserErrors error,
3075                          xmlSchemaBasicItemPtr ownerItem,
3076                          xmlAttrPtr attr,
3077                          const char *name1,
3078                          const char *name2)
3079 {
3080     xmlChar *des = NULL;
3081
3082     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
3083     xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
3084         "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
3085         BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
3086     FREE_AND_NULL(des);
3087 }
3088
3089 /**
3090  * xmlSchemaPSimpleTypeErr:
3091  * @ctxt:  the schema validation context
3092  * @error: the error code
3093  * @type: the type specifier
3094  * @ownerDes: the designation of the owner
3095  * @ownerItem: the schema object if existent
3096  * @node: the validated node
3097  * @value: the validated value
3098  *
3099  * Reports a simple type validation error.
3100  * TODO: Should this report the value of an element as well?
3101  */
3102 static void
3103 xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3104                         xmlParserErrors error,
3105                         xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
3106                         xmlNodePtr node,
3107                         xmlSchemaTypePtr type,
3108                         const char *expected,
3109                         const xmlChar *value,
3110                         const char *message,
3111                         const xmlChar *str1,
3112                         const xmlChar *str2)
3113 {
3114     xmlChar *msg = NULL;
3115
3116     xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
3117     if (message == NULL) {
3118         /*
3119         * Use default messages.
3120         */
3121         if (type != NULL) {
3122             if (node->type == XML_ATTRIBUTE_NODE)
3123                 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3124             else
3125                 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3126                 "valid value of ");
3127             if (! xmlSchemaIsGlobalItem(type))
3128                 msg = xmlStrcat(msg, BAD_CAST "the local ");
3129             else
3130                 msg = xmlStrcat(msg, BAD_CAST "the ");
3131
3132             if (WXS_IS_ATOMIC(type))
3133                 msg = xmlStrcat(msg, BAD_CAST "atomic type");
3134             else if (WXS_IS_LIST(type))
3135                 msg = xmlStrcat(msg, BAD_CAST "list type");
3136             else if (WXS_IS_UNION(type))
3137                 msg = xmlStrcat(msg, BAD_CAST "union type");
3138
3139             if (xmlSchemaIsGlobalItem(type)) {
3140                 xmlChar *str = NULL;
3141                 msg = xmlStrcat(msg, BAD_CAST " '");
3142                 if (type->builtInType != 0) {
3143                     msg = xmlStrcat(msg, BAD_CAST "xs:");
3144                     msg = xmlStrcat(msg, type->name);
3145                 } else
3146                     msg = xmlStrcat(msg,
3147                         xmlSchemaFormatQName(&str,
3148                             type->targetNamespace, type->name));
3149                 msg = xmlStrcat(msg, BAD_CAST "'.");
3150                 FREE_AND_NULL(str);
3151             }
3152         } else {
3153             if (node->type == XML_ATTRIBUTE_NODE)
3154                 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3155             else
3156                 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3157                 "valid.");
3158         }
3159         if (expected) {
3160             msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3161             msg = xmlStrcat(msg, BAD_CAST expected);
3162             msg = xmlStrcat(msg, BAD_CAST "'.\n");
3163         } else
3164             msg = xmlStrcat(msg, BAD_CAST "\n");
3165         if (node->type == XML_ATTRIBUTE_NODE)
3166             xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3167         else
3168             xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3169     } else {
3170         msg = xmlStrcat(msg, BAD_CAST message);
3171         msg = xmlStrcat(msg, BAD_CAST ".\n");
3172         xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
3173              (const char*) msg, str1, str2, NULL, NULL, NULL);
3174     }
3175     /* Cleanup. */
3176     FREE_AND_NULL(msg)
3177 }
3178
3179 /**
3180  * xmlSchemaPContentErr:
3181  * @ctxt: the schema parser context
3182  * @error: the error code
3183  * @onwerDes: the designation of the holder of the content
3184  * @ownerItem: the owner item of the holder of the content
3185  * @ownerElem: the node of the holder of the content
3186  * @child: the invalid child node
3187  * @message: the optional error message
3188  * @content: the optional string describing the correct content
3189  *
3190  * Reports an error concerning the content of a schema element.
3191  */
3192 static void
3193 xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
3194                      xmlParserErrors error,
3195                      xmlSchemaBasicItemPtr ownerItem,
3196                      xmlNodePtr ownerElem,
3197                      xmlNodePtr child,
3198                      const char *message,
3199                      const char *content)
3200 {
3201     xmlChar *des = NULL;
3202
3203     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
3204     if (message != NULL)
3205         xmlSchemaPErr2(ctxt, ownerElem, child, error,
3206             "%s: %s.\n",
3207             BAD_CAST des, BAD_CAST message);
3208     else {
3209         if (content != NULL) {
3210             xmlSchemaPErr2(ctxt, ownerElem, child, error,
3211                 "%s: The content is not valid. Expected is %s.\n",
3212                 BAD_CAST des, BAD_CAST content);
3213         } else {
3214             xmlSchemaPErr2(ctxt, ownerElem, child, error,
3215                 "%s: The content is not valid.\n",
3216                 BAD_CAST des, NULL);
3217         }
3218     }
3219     FREE_AND_NULL(des)
3220 }
3221
3222 /************************************************************************
3223  *                                                                      *
3224  *                      Streamable error functions                      *
3225  *                                                                      *
3226  ************************************************************************/
3227
3228
3229
3230
3231 /************************************************************************
3232  *                                                                      *
3233  *                      Validation helper functions                     *
3234  *                                                                      *
3235  ************************************************************************/
3236
3237
3238 /************************************************************************
3239  *                                                                      *
3240  *                      Allocation functions                            *
3241  *                                                                      *
3242  ************************************************************************/
3243
3244 /**
3245  * xmlSchemaNewSchemaForParserCtxt:
3246  * @ctxt:  a schema validation context
3247  *
3248  * Allocate a new Schema structure.
3249  *
3250  * Returns the newly allocated structure or NULL in case or error
3251  */
3252 static xmlSchemaPtr
3253 xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3254 {
3255     xmlSchemaPtr ret;
3256
3257     ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3258     if (ret == NULL) {
3259         xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
3260         return (NULL);
3261     }
3262     memset(ret, 0, sizeof(xmlSchema));
3263     ret->dict = ctxt->dict;
3264     xmlDictReference(ret->dict);
3265
3266     return (ret);
3267 }
3268
3269 /**
3270  * xmlSchemaNewFacet:
3271  *
3272  * Allocate a new Facet structure.
3273  *
3274  * Returns the newly allocated structure or NULL in case or error
3275  */
3276 xmlSchemaFacetPtr
3277 xmlSchemaNewFacet(void)
3278 {
3279     xmlSchemaFacetPtr ret;
3280
3281     ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3282     if (ret == NULL) {
3283         return (NULL);
3284     }
3285     memset(ret, 0, sizeof(xmlSchemaFacet));
3286
3287     return (ret);
3288 }
3289
3290 /**
3291  * xmlSchemaNewAnnot:
3292  * @ctxt:  a schema validation context
3293  * @node:  a node
3294  *
3295  * Allocate a new annotation structure.
3296  *
3297  * Returns the newly allocated structure or NULL in case or error
3298  */
3299 static xmlSchemaAnnotPtr
3300 xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3301 {
3302     xmlSchemaAnnotPtr ret;
3303
3304     ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3305     if (ret == NULL) {
3306         xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
3307         return (NULL);
3308     }
3309     memset(ret, 0, sizeof(xmlSchemaAnnot));
3310     ret->content = node;
3311     return (ret);
3312 }
3313
3314 static xmlSchemaItemListPtr
3315 xmlSchemaItemListCreate(void)
3316 {
3317     xmlSchemaItemListPtr ret;
3318
3319     ret = xmlMalloc(sizeof(xmlSchemaItemList));
3320     if (ret == NULL) {
3321         xmlSchemaPErrMemory(NULL,
3322             "allocating an item list structure", NULL);
3323         return (NULL);
3324     }
3325     memset(ret, 0, sizeof(xmlSchemaItemList));
3326     return (ret);
3327 }
3328
3329 static void
3330 xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3331 {
3332     if (list->items != NULL) {
3333         xmlFree(list->items);
3334         list->items = NULL;
3335     }
3336     list->nbItems = 0;
3337     list->sizeItems = 0;
3338 }
3339
3340 static int
3341 xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3342 {
3343     if (list->items == NULL) {
3344         list->items = (void **) xmlMalloc(
3345             20 * sizeof(void *));
3346         if (list->items == NULL) {
3347             xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3348             return(-1);
3349         }
3350         list->sizeItems = 20;
3351     } else if (list->sizeItems <= list->nbItems) {
3352         list->sizeItems *= 2;
3353         list->items = (void **) xmlRealloc(list->items,
3354             list->sizeItems * sizeof(void *));
3355         if (list->items == NULL) {
3356             xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3357             list->sizeItems = 0;
3358             return(-1);
3359         }
3360     }
3361     list->items[list->nbItems++] = item;
3362     return(0);
3363 }
3364
3365 static int
3366 xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3367                          int initialSize,
3368                          void *item)
3369 {
3370     if (list->items == NULL) {
3371         if (initialSize <= 0)
3372             initialSize = 1;
3373         list->items = (void **) xmlMalloc(
3374             initialSize * sizeof(void *));
3375         if (list->items == NULL) {
3376             xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3377             return(-1);
3378         }
3379         list->sizeItems = initialSize;
3380     } else if (list->sizeItems <= list->nbItems) {
3381         list->sizeItems *= 2;
3382         list->items = (void **) xmlRealloc(list->items,
3383             list->sizeItems * sizeof(void *));
3384         if (list->items == NULL) {
3385             xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3386             list->sizeItems = 0;
3387             return(-1);
3388         }
3389     }
3390     list->items[list->nbItems++] = item;
3391     return(0);
3392 }
3393
3394 static int
3395 xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3396 {
3397     if (list->items == NULL) {
3398         list->items = (void **) xmlMalloc(
3399             20 * sizeof(void *));
3400         if (list->items == NULL) {
3401             xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3402             return(-1);
3403         }
3404         list->sizeItems = 20;
3405     } else if (list->sizeItems <= list->nbItems) {
3406         list->sizeItems *= 2;
3407         list->items = (void **) xmlRealloc(list->items,
3408             list->sizeItems * sizeof(void *));
3409         if (list->items == NULL) {
3410             xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3411             list->sizeItems = 0;
3412             return(-1);
3413         }
3414     }
3415     /*
3416     * Just append if the index is greater/equal than the item count.
3417     */
3418     if (idx >= list->nbItems) {
3419         list->items[list->nbItems++] = item;
3420     } else {
3421         int i;
3422         for (i = list->nbItems; i > idx; i--)
3423             list->items[i] = list->items[i-1];
3424         list->items[idx] = item;
3425         list->nbItems++;
3426     }
3427     return(0);
3428 }
3429
3430 #if 0 /* enable if ever needed */
3431 static int
3432 xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3433                             int initialSize,
3434                             void *item,
3435                             int idx)
3436 {
3437     if (list->items == NULL) {
3438         if (initialSize <= 0)
3439             initialSize = 1;
3440         list->items = (void **) xmlMalloc(
3441             initialSize * sizeof(void *));
3442         if (list->items == NULL) {
3443             xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3444             return(-1);
3445         }
3446         list->sizeItems = initialSize;
3447     } else if (list->sizeItems <= list->nbItems) {
3448         list->sizeItems *= 2;
3449         list->items = (void **) xmlRealloc(list->items,
3450             list->sizeItems * sizeof(void *));
3451         if (list->items == NULL) {
3452             xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3453             list->sizeItems = 0;
3454             return(-1);
3455         }
3456     }
3457     /*
3458     * Just append if the index is greater/equal than the item count.
3459     */
3460     if (idx >= list->nbItems) {
3461         list->items[list->nbItems++] = item;
3462     } else {
3463         int i;
3464         for (i = list->nbItems; i > idx; i--)
3465             list->items[i] = list->items[i-1];
3466         list->items[idx] = item;
3467         list->nbItems++;
3468     }
3469     return(0);
3470 }
3471 #endif
3472
3473 static int
3474 xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3475 {
3476     int i;
3477     if ((list->items == NULL) || (idx >= list->nbItems)) {
3478         xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3479             "index error.\n");
3480         return(-1);
3481     }
3482
3483     if (list->nbItems == 1) {
3484         /* TODO: Really free the list? */
3485         xmlFree(list->items);
3486         list->items = NULL;
3487         list->nbItems = 0;
3488         list->sizeItems = 0;
3489     } else if (list->nbItems -1 == idx) {
3490         list->nbItems--;
3491     } else {
3492         for (i = idx; i < list->nbItems -1; i++)
3493             list->items[i] = list->items[i+1];
3494         list->nbItems--;
3495     }
3496     return(0);
3497 }
3498
3499 /**
3500  * xmlSchemaItemListFree:
3501  * @annot:  a schema type structure
3502  *
3503  * Deallocate a annotation structure
3504  */
3505 static void
3506 xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3507 {
3508     if (list == NULL)
3509         return;
3510     if (list->items != NULL)
3511         xmlFree(list->items);
3512     xmlFree(list);
3513 }
3514
3515 static void
3516 xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
3517 {
3518     if (bucket == NULL)
3519         return;
3520     if (bucket->globals != NULL) {
3521         xmlSchemaComponentListFree(bucket->globals);
3522         xmlSchemaItemListFree(bucket->globals);
3523     }
3524     if (bucket->locals != NULL) {
3525         xmlSchemaComponentListFree(bucket->locals);
3526         xmlSchemaItemListFree(bucket->locals);
3527     }
3528     if (bucket->relations != NULL) {
3529         xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3530         do {
3531             prev = cur;
3532             cur = cur->next;
3533             xmlFree(prev);
3534         } while (cur != NULL);
3535     }
3536     if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3537         xmlFreeDoc(bucket->doc);
3538     }
3539     if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
3540         if (WXS_IMPBUCKET(bucket)->schema != NULL)
3541             xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
3542     }
3543     xmlFree(bucket);
3544 }
3545
3546 static xmlSchemaBucketPtr
3547 xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
3548                          int type, const xmlChar *targetNamespace)
3549 {
3550     xmlSchemaBucketPtr ret;
3551     int size;
3552     xmlSchemaPtr mainSchema;
3553
3554     if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
3555         PERROR_INT("xmlSchemaBucketCreate",
3556             "no main schema on constructor");
3557         return(NULL);
3558     }
3559     mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
3560     /* Create the schema bucket. */
3561     if (WXS_IS_BUCKET_INCREDEF(type))
3562         size = sizeof(xmlSchemaInclude);
3563     else
3564         size = sizeof(xmlSchemaImport);
3565     ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3566     if (ret == NULL) {
3567         xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3568         return(NULL);
3569     }
3570     memset(ret, 0, size);
3571     ret->targetNamespace = targetNamespace;
3572     ret->type = type;
3573     ret->globals = xmlSchemaItemListCreate();
3574     if (ret->globals == NULL) {
3575         xmlFree(ret);
3576         return(NULL);
3577     }
3578     ret->locals = xmlSchemaItemListCreate();
3579     if (ret->locals == NULL) {
3580         xmlFree(ret);
3581         return(NULL);
3582     }
3583     /*
3584     * The following will assure that only the first bucket is marked as
3585     * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3586     * For each following import buckets an xmlSchema will be created.
3587     * An xmlSchema will be created for every distinct targetNamespace.
3588     * We assign the targetNamespace to the schemata here.
3589     */
3590     if (! WXS_HAS_BUCKETS(pctxt)) {
3591         if (WXS_IS_BUCKET_INCREDEF(type)) {
3592             PERROR_INT("xmlSchemaBucketCreate",
3593                 "first bucket but it's an include or redefine");
3594             xmlSchemaBucketFree(ret);
3595             return(NULL);
3596         }
3597         /* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3598         ret->type = XML_SCHEMA_SCHEMA_MAIN;
3599         /* Point to the *main* schema. */
3600         WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3601         WXS_IMPBUCKET(ret)->schema = mainSchema;
3602         /*
3603         * Ensure that the main schema gets a targetNamespace.
3604         */
3605         mainSchema->targetNamespace = targetNamespace;
3606     } else {
3607         if (type == XML_SCHEMA_SCHEMA_MAIN) {
3608             PERROR_INT("xmlSchemaBucketCreate",
3609                 "main bucket but it's not the first one");
3610             xmlSchemaBucketFree(ret);
3611             return(NULL);
3612         } else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3613             /*
3614             * Create a schema for imports and assign the
3615             * targetNamespace.
3616             */
3617             WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3618             if (WXS_IMPBUCKET(ret)->schema == NULL) {
3619                 xmlSchemaBucketFree(ret);
3620                 return(NULL);
3621             }
3622             WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
3623         }
3624     }
3625     if (WXS_IS_BUCKET_IMPMAIN(type)) {
3626         int res;
3627         /*
3628         * Imports go into the "schemasImports" slot of the main *schema*.
3629         * Note that we create an import entry for the main schema as well; i.e.,
3630         * even if there's only one schema, we'll get an import.
3631         */
3632         if (mainSchema->schemasImports == NULL) {
3633             mainSchema->schemasImports = xmlHashCreateDict(5,
3634                 WXS_CONSTRUCTOR(pctxt)->dict);
3635             if (mainSchema->schemasImports == NULL) {
3636                 xmlSchemaBucketFree(ret);
3637                 return(NULL);
3638             }
3639         }
3640         if (targetNamespace == NULL)
3641             res = xmlHashAddEntry(mainSchema->schemasImports,
3642                 XML_SCHEMAS_NO_NAMESPACE, ret);
3643         else
3644             res = xmlHashAddEntry(mainSchema->schemasImports,
3645                 targetNamespace, ret);
3646         if (res != 0) {
3647             PERROR_INT("xmlSchemaBucketCreate",
3648                 "failed to add the schema bucket to the hash");
3649             xmlSchemaBucketFree(ret);
3650             return(NULL);
3651         }
3652     } else {
3653         /* Set the @ownerImport of an include bucket. */
3654         if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3655             WXS_INCBUCKET(ret)->ownerImport =
3656                 WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
3657         else
3658             WXS_INCBUCKET(ret)->ownerImport =
3659                 WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
3660
3661         /* Includes got into the "includes" slot of the *main* schema. */
3662         if (mainSchema->includes == NULL) {
3663             mainSchema->includes = xmlSchemaItemListCreate();
3664             if (mainSchema->includes == NULL) {
3665                 xmlSchemaBucketFree(ret);
3666                 return(NULL);
3667             }
3668         }
3669         xmlSchemaItemListAdd(mainSchema->includes, ret);
3670     }
3671     /*
3672     * Add to list of all buckets; this is used for lookup
3673     * during schema construction time only.
3674     */
3675     if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
3676         return(NULL);
3677     return(ret);
3678 }
3679
3680 static int
3681 xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
3682 {
3683     if (*list == NULL) {
3684         *list = xmlSchemaItemListCreate();
3685         if (*list == NULL)
3686             return(-1);
3687     }
3688     xmlSchemaItemListAddSize(*list, initialSize, item);
3689     return(0);
3690 }
3691
3692 /**
3693  * xmlSchemaFreeAnnot:
3694  * @annot:  a schema type structure
3695  *
3696  * Deallocate a annotation structure
3697  */
3698 static void
3699 xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3700 {
3701     if (annot == NULL)
3702         return;
3703     if (annot->next == NULL) {
3704         xmlFree(annot);
3705     } else {
3706         xmlSchemaAnnotPtr prev;
3707
3708         do {
3709             prev = annot;
3710             annot = annot->next;
3711             xmlFree(prev);
3712         } while (annot != NULL);
3713     }
3714 }
3715
3716 /**
3717  * xmlSchemaFreeNotation:
3718  * @schema:  a schema notation structure
3719  *
3720  * Deallocate a Schema Notation structure.
3721  */
3722 static void
3723 xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3724 {
3725     if (nota == NULL)
3726         return;
3727     xmlFree(nota);
3728 }
3729
3730 /**
3731  * xmlSchemaFreeAttribute:
3732  * @attr:  an attribute declaration
3733  *
3734  * Deallocates an attribute declaration structure.
3735  */
3736 static void
3737 xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3738 {
3739     if (attr == NULL)
3740         return;
3741     if (attr->annot != NULL)
3742         xmlSchemaFreeAnnot(attr->annot);
3743     if (attr->defVal != NULL)
3744         xmlSchemaFreeValue(attr->defVal);
3745     xmlFree(attr);
3746 }
3747
3748 /**
3749  * xmlSchemaFreeAttributeUse:
3750  * @use:  an attribute use
3751  *
3752  * Deallocates an attribute use structure.
3753  */
3754 static void
3755 xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3756 {
3757     if (use == NULL)
3758         return;
3759     if (use->annot != NULL)
3760         xmlSchemaFreeAnnot(use->annot);
3761     if (use->defVal != NULL)
3762         xmlSchemaFreeValue(use->defVal);
3763     xmlFree(use);
3764 }
3765
3766 /**
3767  * xmlSchemaFreeAttributeUseProhib:
3768  * @prohib:  an attribute use prohibition
3769  *
3770  * Deallocates an attribute use structure.
3771  */
3772 static void
3773 xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3774 {
3775     if (prohib == NULL)
3776         return;
3777     xmlFree(prohib);
3778 }
3779
3780 /**
3781  * xmlSchemaFreeWildcardNsSet:
3782  * set:  a schema wildcard namespace
3783  *
3784  * Deallocates a list of wildcard constraint structures.
3785  */
3786 static void
3787 xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3788 {
3789     xmlSchemaWildcardNsPtr next;
3790
3791     while (set != NULL) {
3792         next = set->next;
3793         xmlFree(set);
3794         set = next;
3795     }
3796 }
3797
3798 /**
3799  * xmlSchemaFreeWildcard:
3800  * @wildcard:  a wildcard structure
3801  *
3802  * Deallocates a wildcard structure.
3803  */
3804 void
3805 xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3806 {
3807     if (wildcard == NULL)
3808         return;
3809     if (wildcard->annot != NULL)
3810         xmlSchemaFreeAnnot(wildcard->annot);
3811     if (wildcard->nsSet != NULL)
3812         xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3813     if (wildcard->negNsSet != NULL)
3814         xmlFree(wildcard->negNsSet);
3815     xmlFree(wildcard);
3816 }
3817
3818 /**
3819  * xmlSchemaFreeAttributeGroup:
3820  * @schema:  a schema attribute group structure
3821  *
3822  * Deallocate a Schema Attribute Group structure.
3823  */
3824 static void
3825 xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
3826 {
3827     if (attrGr == NULL)
3828         return;
3829     if (attrGr->annot != NULL)
3830         xmlSchemaFreeAnnot(attrGr->annot);
3831     if (attrGr->attrUses != NULL)
3832         xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3833     xmlFree(attrGr);
3834 }
3835
3836 /**
3837  * xmlSchemaFreeQNameRef:
3838  * @item: a QName reference structure
3839  *
3840  * Deallocatea a QName reference structure.
3841  */
3842 static void
3843 xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3844 {
3845     xmlFree(item);
3846 }
3847
3848 /**
3849  * xmlSchemaFreeTypeLinkList:
3850  * @alink: a type link
3851  *
3852  * Deallocate a list of types.
3853  */
3854 static void
3855 xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3856 {
3857     xmlSchemaTypeLinkPtr next;
3858
3859     while (link != NULL) {
3860         next = link->next;
3861         xmlFree(link);
3862         link = next;
3863     }
3864 }
3865
3866 static void
3867 xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3868 {
3869     xmlSchemaIDCStateObjPtr next;
3870     while (sto != NULL) {
3871         next = sto->next;
3872         if (sto->history != NULL)
3873             xmlFree(sto->history);
3874         if (sto->xpathCtxt != NULL)
3875             xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3876         xmlFree(sto);
3877         sto = next;
3878     }
3879 }
3880
3881 /**
3882  * xmlSchemaFreeIDC:
3883  * @idc: a identity-constraint definition
3884  *
3885  * Deallocates an identity-constraint definition.
3886  */
3887 static void
3888 xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3889 {
3890     xmlSchemaIDCSelectPtr cur, prev;
3891
3892     if (idcDef == NULL)
3893         return;
3894     if (idcDef->annot != NULL)
3895         xmlSchemaFreeAnnot(idcDef->annot);
3896     /* Selector */
3897     if (idcDef->selector != NULL) {
3898         if (idcDef->selector->xpathComp != NULL)
3899             xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3900         xmlFree(idcDef->selector);
3901     }
3902     /* Fields */
3903     if (idcDef->fields != NULL) {
3904         cur = idcDef->fields;
3905         do {
3906             prev = cur;
3907             cur = cur->next;
3908             if (prev->xpathComp != NULL)
3909                 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
3910             xmlFree(prev);
3911         } while (cur != NULL);
3912     }
3913     xmlFree(idcDef);
3914 }
3915
3916 /**
3917  * xmlSchemaFreeElement:
3918  * @schema:  a schema element structure
3919  *
3920  * Deallocate a Schema Element structure.
3921  */
3922 static void
3923 xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3924 {
3925     if (elem == NULL)
3926         return;
3927     if (elem->annot != NULL)
3928         xmlSchemaFreeAnnot(elem->annot);
3929     if (elem->contModel != NULL)
3930         xmlRegFreeRegexp(elem->contModel);
3931     if (elem->defVal != NULL)
3932         xmlSchemaFreeValue(elem->defVal);
3933     xmlFree(elem);
3934 }
3935
3936 /**
3937  * xmlSchemaFreeFacet:
3938  * @facet:  a schema facet structure
3939  *
3940  * Deallocate a Schema Facet structure.
3941  */
3942 void
3943 xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3944 {
3945     if (facet == NULL)
3946         return;
3947     if (facet->val != NULL)
3948         xmlSchemaFreeValue(facet->val);
3949     if (facet->regexp != NULL)
3950         xmlRegFreeRegexp(facet->regexp);
3951     if (facet->annot != NULL)
3952         xmlSchemaFreeAnnot(facet->annot);
3953     xmlFree(facet);
3954 }
3955
3956 /**
3957  * xmlSchemaFreeType:
3958  * @type:  a schema type structure
3959  *
3960  * Deallocate a Schema Type structure.
3961  */
3962 void
3963 xmlSchemaFreeType(xmlSchemaTypePtr type)
3964 {
3965     if (type == NULL)
3966         return;
3967     if (type->annot != NULL)
3968         xmlSchemaFreeAnnot(type->annot);
3969     if (type->facets != NULL) {
3970         xmlSchemaFacetPtr facet, next;
3971
3972         facet = type->facets;
3973         while (facet != NULL) {
3974             next = facet->next;
3975             xmlSchemaFreeFacet(facet);
3976             facet = next;
3977         }
3978     }
3979     if (type->attrUses != NULL)
3980         xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
3981     if (type->memberTypes != NULL)
3982         xmlSchemaFreeTypeLinkList(type->memberTypes);
3983     if (type->facetSet != NULL) {
3984         xmlSchemaFacetLinkPtr next, link;
3985
3986         link = type->facetSet;
3987         do {
3988             next = link->next;
3989             xmlFree(link);
3990             link = next;
3991         } while (link != NULL);
3992     }
3993     if (type->contModel != NULL)
3994         xmlRegFreeRegexp(type->contModel);
3995     xmlFree(type);
3996 }
3997
3998 /**
3999  * xmlSchemaFreeModelGroupDef:
4000  * @item:  a schema model group definition
4001  *
4002  * Deallocates a schema model group definition.
4003  */
4004 static void
4005 xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
4006 {
4007     if (item->annot != NULL)
4008         xmlSchemaFreeAnnot(item->annot);
4009     xmlFree(item);
4010 }
4011
4012 /**
4013  * xmlSchemaFreeModelGroup:
4014  * @item:  a schema model group
4015  *
4016  * Deallocates a schema model group structure.
4017  */
4018 static void
4019 xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
4020 {
4021     if (item->annot != NULL)
4022         xmlSchemaFreeAnnot(item->annot);
4023     xmlFree(item);
4024 }
4025
4026 static void
4027 xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
4028 {
4029     if ((list == NULL) || (list->nbItems == 0))
4030         return;
4031     {
4032         xmlSchemaTreeItemPtr item;
4033         xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
4034         int i;
4035
4036         for (i = 0; i < list->nbItems; i++) {
4037             item = items[i];
4038             if (item == NULL)
4039                 continue;
4040             switch (item->type) {
4041                 case XML_SCHEMA_TYPE_SIMPLE:
4042                 case XML_SCHEMA_TYPE_COMPLEX:
4043                     xmlSchemaFreeType((xmlSchemaTypePtr) item);
4044                     break;
4045                 case XML_SCHEMA_TYPE_ATTRIBUTE:
4046                     xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
4047                     break;
4048                 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
4049                     xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
4050                     break;
4051                 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
4052                     xmlSchemaFreeAttributeUseProhib(
4053                         (xmlSchemaAttributeUseProhibPtr) item);
4054                     break;
4055                 case XML_SCHEMA_TYPE_ELEMENT:
4056                     xmlSchemaFreeElement((xmlSchemaElementPtr) item);
4057                     break;
4058                 case XML_SCHEMA_TYPE_PARTICLE:
4059                     if (item->annot != NULL)
4060                         xmlSchemaFreeAnnot(item->annot);
4061                     xmlFree(item);
4062                     break;
4063                 case XML_SCHEMA_TYPE_SEQUENCE:
4064                 case XML_SCHEMA_TYPE_CHOICE:
4065                 case XML_SCHEMA_TYPE_ALL:
4066                     xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4067                     break;
4068                 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4069                     xmlSchemaFreeAttributeGroup(
4070                         (xmlSchemaAttributeGroupPtr) item);
4071                     break;
4072                 case XML_SCHEMA_TYPE_GROUP:
4073                     xmlSchemaFreeModelGroupDef(
4074                         (xmlSchemaModelGroupDefPtr) item);
4075                     break;
4076                 case XML_SCHEMA_TYPE_ANY:
4077                 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4078                     xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4079                     break;
4080                 case XML_SCHEMA_TYPE_IDC_KEY:
4081                 case XML_SCHEMA_TYPE_IDC_UNIQUE:
4082                 case XML_SCHEMA_TYPE_IDC_KEYREF:
4083                     xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4084                     break;
4085                 case XML_SCHEMA_TYPE_NOTATION:
4086                     xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4087                     break;
4088                 case XML_SCHEMA_EXTRA_QNAMEREF:
4089                     xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4090                     break;
4091                 default: {
4092                     /* TODO: This should never be hit. */
4093                     xmlSchemaPSimpleInternalErr(NULL,
4094                         "Internal error: xmlSchemaComponentListFree, "
4095                         "unexpected component type '%s'\n",
4096                         (const xmlChar *) WXS_ITEM_TYPE_NAME(item));
4097                          }
4098                     break;
4099             }
4100         }
4101         list->nbItems = 0;
4102     }
4103 }
4104
4105 /**
4106  * xmlSchemaFree:
4107  * @schema:  a schema structure
4108  *
4109  * Deallocate a Schema structure.
4110  */
4111 void
4112 xmlSchemaFree(xmlSchemaPtr schema)
4113 {
4114     if (schema == NULL)
4115         return;
4116     /* @volatiles is not used anymore :-/ */
4117     if (schema->volatiles != NULL)
4118         TODO
4119     /*
4120     * Note that those slots are not responsible for freeing
4121     * schema components anymore; this will now be done by
4122     * the schema buckets.
4123     */
4124     if (schema->notaDecl != NULL)
4125         xmlHashFree(schema->notaDecl, NULL);
4126     if (schema->attrDecl != NULL)
4127         xmlHashFree(schema->attrDecl, NULL);
4128     if (schema->attrgrpDecl != NULL)
4129         xmlHashFree(schema->attrgrpDecl, NULL);
4130     if (schema->elemDecl != NULL)
4131         xmlHashFree(schema->elemDecl, NULL);
4132     if (schema->typeDecl != NULL)
4133         xmlHashFree(schema->typeDecl, NULL);
4134     if (schema->groupDecl != NULL)
4135         xmlHashFree(schema->groupDecl, NULL);
4136     if (schema->idcDef != NULL)
4137         xmlHashFree(schema->idcDef, NULL);
4138
4139     if (schema->schemasImports != NULL)
4140         xmlHashFree(schema->schemasImports,
4141                     (xmlHashDeallocator) xmlSchemaBucketFree);
4142     if (schema->includes != NULL) {
4143         xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4144         int i;
4145         for (i = 0; i < list->nbItems; i++) {
4146             xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4147         }
4148         xmlSchemaItemListFree(list);
4149     }
4150     if (schema->annot != NULL)
4151         xmlSchemaFreeAnnot(schema->annot);
4152     /* Never free the doc here, since this will be done by the buckets. */
4153
4154     xmlDictFree(schema->dict);
4155     xmlFree(schema);
4156 }
4157
4158 /************************************************************************
4159  *                                                                      *
4160  *                      Debug functions                                 *
4161  *                                                                      *
4162  ************************************************************************/
4163
4164 #ifdef LIBXML_OUTPUT_ENABLED
4165
4166 static void
4167 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4168
4169 /**
4170  * xmlSchemaElementDump:
4171  * @elem:  an element
4172  * @output:  the file output
4173  *
4174  * Dump the element
4175  */
4176 static void
4177 xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
4178                      const xmlChar * name ATTRIBUTE_UNUSED,
4179                      const xmlChar * namespace ATTRIBUTE_UNUSED,
4180                      const xmlChar * context ATTRIBUTE_UNUSED)
4181 {
4182     if (elem == NULL)
4183         return;
4184
4185
4186     fprintf(output, "Element");
4187     if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4188         fprintf(output, " (global)");
4189     fprintf(output, ": '%s' ", elem->name);
4190     if (namespace != NULL)
4191         fprintf(output, "ns '%s'", namespace);
4192     fprintf(output, "\n");
4193 #if 0
4194     if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
4195         fprintf(output, "  min %d ", elem->minOccurs);
4196         if (elem->maxOccurs >= UNBOUNDED)
4197             fprintf(output, "max: unbounded\n");
4198         else if (elem->maxOccurs != 1)
4199             fprintf(output, "max: %d\n", elem->maxOccurs);
4200         else
4201             fprintf(output, "\n");
4202     }
4203 #endif
4204     /*
4205     * Misc other properties.
4206     */
4207     if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4208         (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4209         (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
4210         (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
4211         fprintf(output, "  props: ");
4212         if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4213             fprintf(output, "[fixed] ");
4214         if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4215             fprintf(output, "[default] ");
4216         if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4217             fprintf(output, "[abstract] ");
4218         if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4219             fprintf(output, "[nillable] ");
4220         fprintf(output, "\n");
4221     }
4222     /*
4223     * Default/fixed value.
4224     */
4225     if (elem->value != NULL)
4226         fprintf(output, "  value: '%s'\n", elem->value);
4227     /*
4228     * Type.
4229     */
4230     if (elem->namedType != NULL) {
4231         fprintf(output, "  type: '%s' ", elem->namedType);
4232         if (elem->namedTypeNs != NULL)
4233             fprintf(output, "ns '%s'\n", elem->namedTypeNs);
4234         else
4235             fprintf(output, "\n");
4236     } else if (elem->subtypes != NULL) {
4237         /*
4238         * Dump local types.
4239         */
4240         xmlSchemaTypeDump(elem->subtypes, output);
4241     }
4242     /*
4243     * Substitution group.
4244     */
4245     if (elem->substGroup != NULL) {
4246         fprintf(output, "  substitutionGroup: '%s' ", elem->substGroup);
4247         if (elem->substGroupNs != NULL)
4248             fprintf(output, "ns '%s'\n", elem->substGroupNs);
4249         else
4250             fprintf(output, "\n");
4251     }
4252 }
4253
4254 /**
4255  * xmlSchemaAnnotDump:
4256  * @output:  the file output
4257  * @annot:  a annotation
4258  *
4259  * Dump the annotation
4260  */
4261 static void
4262 xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4263 {
4264     xmlChar *content;
4265
4266     if (annot == NULL)
4267         return;
4268
4269     content = xmlNodeGetContent(annot->content);
4270     if (content != NULL) {
4271         fprintf(output, "  Annot: %s\n", content);
4272         xmlFree(content);
4273     } else
4274         fprintf(output, "  Annot: empty\n");
4275 }
4276
4277 /**
4278  * xmlSchemaContentModelDump:
4279  * @particle: the schema particle
4280  * @output: the file output
4281  * @depth: the depth used for intentation
4282  *
4283  * Dump a SchemaType structure
4284  */
4285 static void
4286 xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4287 {
4288     xmlChar *str = NULL;
4289     xmlSchemaTreeItemPtr term;
4290     char shift[100];
4291     int i;
4292
4293     if (particle == NULL)
4294         return;
4295     for (i = 0;((i < depth) && (i < 25));i++)
4296         shift[2 * i] = shift[2 * i + 1] = ' ';
4297     shift[2 * i] = shift[2 * i + 1] = 0;
4298     fprintf(output, "%s", shift);
4299     if (particle->children == NULL) {
4300         fprintf(output, "MISSING particle term\n");
4301         return;
4302     }
4303     term = particle->children;
4304     if (term == NULL) {
4305         fprintf(output, "(NULL)");
4306     } else {
4307         switch (term->type) {
4308             case XML_SCHEMA_TYPE_ELEMENT:
4309                 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4310                     ((xmlSchemaElementPtr)term)->targetNamespace,
4311                     ((xmlSchemaElementPtr)term)->name));
4312                 FREE_AND_NULL(str);
4313                 break;
4314             case XML_SCHEMA_TYPE_SEQUENCE:
4315                 fprintf(output, "SEQUENCE");
4316                 break;
4317             case XML_SCHEMA_TYPE_CHOICE:
4318                 fprintf(output, "CHOICE");
4319                 break;
4320             case XML_SCHEMA_TYPE_ALL:
4321                 fprintf(output, "ALL");
4322                 break;
4323             case XML_SCHEMA_TYPE_ANY:
4324                 fprintf(output, "ANY");
4325                 break;
4326             default:
4327                 fprintf(output, "UNKNOWN\n");
4328                 return;
4329         }
4330     }
4331     if (particle->minOccurs != 1)
4332         fprintf(output, " min: %d", particle->minOccurs);
4333     if (particle->maxOccurs >= UNBOUNDED)
4334         fprintf(output, " max: unbounded");
4335     else if (particle->maxOccurs != 1)
4336         fprintf(output, " max: %d", particle->maxOccurs);
4337     fprintf(output, "\n");
4338     if (term &&
4339         ((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4340          (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4341          (term->type == XML_SCHEMA_TYPE_ALL)) &&
4342          (term->children != NULL)) {
4343         xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4344             output, depth +1);
4345     }
4346     if (particle->next != NULL)
4347         xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4348                 output, depth);
4349 }
4350
4351 /**
4352  * xmlSchemaAttrUsesDump:
4353  * @uses:  attribute uses list
4354  * @output:  the file output
4355  *
4356  * Dumps a list of attribute use components.
4357  */
4358 static void
4359 xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4360 {
4361     xmlSchemaAttributeUsePtr use;
4362     xmlSchemaAttributeUseProhibPtr prohib;
4363     xmlSchemaQNameRefPtr ref;
4364     const xmlChar *name, *tns;
4365     xmlChar *str = NULL;
4366     int i;
4367
4368     if ((uses == NULL) || (uses->nbItems == 0))
4369         return;
4370
4371     fprintf(output, "  attributes:\n");
4372     for (i = 0; i < uses->nbItems; i++) {
4373         use = uses->items[i];
4374         if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4375             fprintf(output, "  [prohibition] ");
4376             prohib = (xmlSchemaAttributeUseProhibPtr) use;
4377             name = prohib->name;
4378             tns = prohib->targetNamespace;
4379         } else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4380             fprintf(output, "  [reference] ");
4381             ref = (xmlSchemaQNameRefPtr) use;
4382             name = ref->name;
4383             tns = ref->targetNamespace;
4384         } else {
4385             fprintf(output, "  [use] ");
4386             name = WXS_ATTRUSE_DECL_NAME(use);
4387             tns = WXS_ATTRUSE_DECL_TNS(use);
4388         }
4389         fprintf(output, "'%s'\n",
4390             (const char *) xmlSchemaFormatQName(&str, tns, name));
4391         FREE_AND_NULL(str);
4392     }
4393 }
4394
4395 /**
4396  * xmlSchemaTypeDump:
4397  * @output:  the file output
4398  * @type:  a type structure
4399  *
4400  * Dump a SchemaType structure
4401  */
4402 static void
4403 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4404 {
4405     if (type == NULL) {
4406         fprintf(output, "Type: NULL\n");
4407         return;
4408     }
4409     fprintf(output, "Type: ");
4410     if (type->name != NULL)
4411         fprintf(output, "'%s' ", type->name);
4412     else
4413         fprintf(output, "(no name) ");
4414     if (type->targetNamespace != NULL)
4415         fprintf(output, "ns '%s' ", type->targetNamespace);
4416     switch (type->type) {
4417         case XML_SCHEMA_TYPE_BASIC:
4418             fprintf(output, "[basic] ");
4419             break;
4420         case XML_SCHEMA_TYPE_SIMPLE:
4421             fprintf(output, "[simple] ");
4422             break;
4423         case XML_SCHEMA_TYPE_COMPLEX:
4424             fprintf(output, "[complex] ");
4425             break;
4426         case XML_SCHEMA_TYPE_SEQUENCE:
4427             fprintf(output, "[sequence] ");
4428             break;
4429         case XML_SCHEMA_TYPE_CHOICE:
4430             fprintf(output, "[choice] ");
4431             break;
4432         case XML_SCHEMA_TYPE_ALL:
4433             fprintf(output, "[all] ");
4434             break;
4435         case XML_SCHEMA_TYPE_UR:
4436             fprintf(output, "[ur] ");
4437             break;
4438         case XML_SCHEMA_TYPE_RESTRICTION:
4439             fprintf(output, "[restriction] ");
4440             break;
4441         case XML_SCHEMA_TYPE_EXTENSION:
4442             fprintf(output, "[extension] ");
4443             break;
4444         default:
4445             fprintf(output, "[unknown type %d] ", type->type);
4446             break;
4447     }
4448     fprintf(output, "content: ");
4449     switch (type->contentType) {
4450         case XML_SCHEMA_CONTENT_UNKNOWN:
4451             fprintf(output, "[unknown] ");
4452             break;
4453         case XML_SCHEMA_CONTENT_EMPTY:
4454             fprintf(output, "[empty] ");
4455             break;
4456         case XML_SCHEMA_CONTENT_ELEMENTS:
4457             fprintf(output, "[element] ");
4458             break;
4459         case XML_SCHEMA_CONTENT_MIXED:
4460             fprintf(output, "[mixed] ");
4461             break;
4462         case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
4463         /* not used. */
4464             break;
4465         case XML_SCHEMA_CONTENT_BASIC:
4466             fprintf(output, "[basic] ");
4467             break;
4468         case XML_SCHEMA_CONTENT_SIMPLE:
4469             fprintf(output, "[simple] ");
4470             break;
4471         case XML_SCHEMA_CONTENT_ANY:
4472             fprintf(output, "[any] ");
4473             break;
4474     }
4475     fprintf(output, "\n");
4476     if (type->base != NULL) {
4477         fprintf(output, "  base type: '%s'", type->base);
4478         if (type->baseNs != NULL)
4479             fprintf(output, " ns '%s'\n", type->baseNs);
4480         else
4481             fprintf(output, "\n");
4482     }
4483     if (type->attrUses != NULL)
4484         xmlSchemaAttrUsesDump(type->attrUses, output);
4485     if (type->annot != NULL)
4486         xmlSchemaAnnotDump(output, type->annot);
4487 #ifdef DUMP_CONTENT_MODEL
4488     if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4489         (type->subtypes != NULL)) {
4490         xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4491             output, 1);
4492     }
4493 #endif
4494 }
4495
4496 /**
4497  * xmlSchemaDump:
4498  * @output:  the file output
4499  * @schema:  a schema structure
4500  *
4501  * Dump a Schema structure.
4502  */
4503 void
4504 xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4505 {
4506     if (output == NULL)
4507         return;
4508     if (schema == NULL) {
4509         fprintf(output, "Schemas: NULL\n");
4510         return;
4511     }
4512     fprintf(output, "Schemas: ");
4513     if (schema->name != NULL)
4514         fprintf(output, "%s, ", schema->name);
4515     else
4516         fprintf(output, "no name, ");
4517     if (schema->targetNamespace != NULL)
4518         fprintf(output, "%s", (const char *) schema->targetNamespace);
4519     else
4520         fprintf(output, "no target namespace");
4521     fprintf(output, "\n");
4522     if (schema->annot != NULL)
4523         xmlSchemaAnnotDump(output, schema->annot);
4524     xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
4525                 output);
4526     xmlHashScanFull(schema->elemDecl,
4527                     (xmlHashScannerFull) xmlSchemaElementDump, output);
4528 }
4529
4530 #ifdef DEBUG_IDC_NODE_TABLE
4531 /**
4532  * xmlSchemaDebugDumpIDCTable:
4533  * @vctxt: the WXS validation context
4534  *
4535  * Displays the current IDC table for debug purposes.
4536  */
4537 static void
4538 xmlSchemaDebugDumpIDCTable(FILE * output,
4539                            const xmlChar *namespaceName,
4540                            const xmlChar *localName,
4541                            xmlSchemaPSVIIDCBindingPtr bind)
4542 {
4543     xmlChar *str = NULL;
4544     const xmlChar *value;
4545     xmlSchemaPSVIIDCNodePtr tab;
4546     xmlSchemaPSVIIDCKeyPtr key;
4547     int i, j, res;
4548
4549     fprintf(output, "IDC: TABLES on '%s'\n",
4550         xmlSchemaFormatQName(&str, namespaceName, localName));
4551     FREE_AND_NULL(str)
4552
4553     if (bind == NULL)
4554         return;
4555     do {
4556         fprintf(output, "IDC:   BINDING '%s' (%d)\n",
4557             xmlSchemaGetComponentQName(&str,
4558                 bind->definition), bind->nbNodes);
4559         FREE_AND_NULL(str)
4560         for (i = 0; i < bind->nbNodes; i++) {
4561             tab = bind->nodeTable[i];
4562             fprintf(output, "         ( ");
4563             for (j = 0; j < bind->definition->nbFields; j++) {
4564                 key = tab->keys[j];
4565                 if ((key != NULL) && (key->val != NULL)) {
4566                     res = xmlSchemaGetCanonValue(key->val, &value);
4567                     if (res >= 0)
4568                         fprintf(output, "'%s' ", value);
4569                     else
4570                         fprintf(output, "CANON-VALUE-FAILED ");
4571                     if (res == 0)
4572                         FREE_AND_NULL(value)
4573                 } else if (key != NULL)
4574                     fprintf(output, "(no val), ");
4575                 else
4576                     fprintf(output, "(key missing), ");
4577             }
4578             fprintf(output, ")\n");
4579         }
4580         if (bind->dupls && bind->dupls->nbItems) {
4581             fprintf(output, "IDC:     dupls (%d):\n", bind->dupls->nbItems);
4582             for (i = 0; i < bind->dupls->nbItems; i++) {
4583                 tab = bind->dupls->items[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         }
4603         bind = bind->next;
4604     } while (bind != NULL);
4605 }
4606 #endif /* DEBUG_IDC */
4607 #endif /* LIBXML_OUTPUT_ENABLED */
4608
4609 /************************************************************************
4610  *                                                                      *
4611  *                      Utilities                                       *
4612  *                                                                      *
4613  ************************************************************************/
4614
4615 /**
4616  * xmlSchemaGetPropNode:
4617  * @node: the element node
4618  * @name: the name of the attribute
4619  *
4620  * Seeks an attribute with a name of @name in
4621  * no namespace.
4622  *
4623  * Returns the attribute or NULL if not present.
4624  */
4625 static xmlAttrPtr
4626 xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
4627 {
4628     xmlAttrPtr prop;
4629
4630     if ((node == NULL) || (name == NULL))
4631         return(NULL);
4632     prop = node->properties;
4633     while (prop != NULL) {
4634         if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
4635             return(prop);
4636         prop = prop->next;
4637     }
4638     return (NULL);
4639 }
4640
4641 /**
4642  * xmlSchemaGetPropNodeNs:
4643  * @node: the element node
4644  * @uri: the uri
4645  * @name: the name of the attribute
4646  *
4647  * Seeks an attribute with a local name of @name and
4648  * a namespace URI of @uri.
4649  *
4650  * Returns the attribute or NULL if not present.
4651  */
4652 static xmlAttrPtr
4653 xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
4654 {
4655     xmlAttrPtr prop;
4656
4657     if ((node == NULL) || (name == NULL))
4658         return(NULL);
4659     prop = node->properties;
4660     while (prop != NULL) {
4661         if ((prop->ns != NULL) &&
4662             xmlStrEqual(prop->name, BAD_CAST name) &&
4663             xmlStrEqual(prop->ns->href, BAD_CAST uri))
4664             return(prop);
4665         prop = prop->next;
4666     }
4667     return (NULL);
4668 }
4669
4670 static const xmlChar *
4671 xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4672 {
4673     xmlChar *val;
4674     const xmlChar *ret;
4675
4676     val = xmlNodeGetContent(node);
4677     if (val == NULL)
4678         val = xmlStrdup((xmlChar *)"");
4679     ret = xmlDictLookup(ctxt->dict, val, -1);
4680     xmlFree(val);
4681     return(ret);
4682 }
4683
4684 static const xmlChar *
4685 xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4686 {
4687     return((const xmlChar*) xmlNodeGetContent(node));
4688 }
4689
4690 /**
4691  * xmlSchemaGetProp:
4692  * @ctxt: the parser context
4693  * @node: the node
4694  * @name: the property name
4695  *
4696  * Read a attribute value and internalize the string
4697  *
4698  * Returns the string or NULL if not present.
4699  */
4700 static const xmlChar *
4701 xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4702                  const char *name)
4703 {
4704     xmlChar *val;
4705     const xmlChar *ret;
4706
4707     val = xmlGetNoNsProp(node, BAD_CAST name);
4708     if (val == NULL)
4709         return(NULL);
4710     ret = xmlDictLookup(ctxt->dict, val, -1);
4711     xmlFree(val);
4712     return(ret);
4713 }
4714
4715 /************************************************************************
4716  *                                                                      *
4717  *                      Parsing functions                               *
4718  *                                                                      *
4719  ************************************************************************/
4720
4721 #define WXS_FIND_GLOBAL_ITEM(slot)                      \
4722     if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4723         ret = xmlHashLookup(schema->slot, name); \
4724         if (ret != NULL) goto exit; \
4725     } \
4726     if (xmlHashSize(schema->schemasImports) > 1) { \
4727         xmlSchemaImportPtr import; \
4728         if (nsName == NULL) \
4729             import = xmlHashLookup(schema->schemasImports, \
4730                 XML_SCHEMAS_NO_NAMESPACE); \
4731         else \
4732             import = xmlHashLookup(schema->schemasImports, nsName); \
4733         if (import == NULL) \
4734             goto exit; \
4735         ret = xmlHashLookup(import->schema->slot, name); \
4736     }
4737
4738 /**
4739  * xmlSchemaGetElem:
4740  * @schema:  the schema context
4741  * @name:  the element name
4742  * @ns:  the element namespace
4743  *
4744  * Lookup a global element declaration in the schema.
4745  *
4746  * Returns the element declaration or NULL if not found.
4747  */
4748 static xmlSchemaElementPtr
4749 xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
4750                  const xmlChar * nsName)
4751 {
4752     xmlSchemaElementPtr ret = NULL;
4753
4754     if ((name == NULL) || (schema == NULL))
4755         return(NULL);
4756     if (schema != NULL) {
4757         WXS_FIND_GLOBAL_ITEM(elemDecl)
4758     }
4759 exit:
4760 #ifdef DEBUG
4761     if (ret == NULL) {
4762         if (nsName == NULL)
4763             fprintf(stderr, "Unable to lookup element decl. %s", name);
4764         else
4765             fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
4766                     nsName);
4767     }
4768 #endif
4769     return (ret);
4770 }
4771
4772 /**
4773  * xmlSchemaGetType:
4774  * @schema:  the main schema
4775  * @name:  the type's name
4776  * nsName:  the type's namespace
4777  *
4778  * Lookup a type in the schemas or the predefined types
4779  *
4780  * Returns the group definition or NULL if not found.
4781  */
4782 static xmlSchemaTypePtr
4783 xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
4784                  const xmlChar * nsName)
4785 {
4786     xmlSchemaTypePtr ret = NULL;
4787
4788     if (name == NULL)
4789         return (NULL);
4790     /* First try the built-in types. */
4791     if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4792         ret = xmlSchemaGetPredefinedType(name, nsName);
4793         if (ret != NULL)
4794             goto exit;
4795         /*
4796         * Note that we try the parsed schemas as well here
4797         * since one might have parsed the S4S, which contain more
4798         * than the built-in types.
4799         * TODO: Can we optimize this?
4800         */
4801     }
4802     if (schema != NULL) {
4803         WXS_FIND_GLOBAL_ITEM(typeDecl)
4804     }
4805 exit:
4806
4807 #ifdef DEBUG
4808     if (ret == NULL) {
4809         if (nsName == NULL)
4810             fprintf(stderr, "Unable to lookup type %s", name);
4811         else
4812             fprintf(stderr, "Unable to lookup type %s:%s", name,
4813                     nsName);
4814     }
4815 #endif
4816     return (ret);
4817 }
4818
4819 /**
4820  * xmlSchemaGetAttributeDecl:
4821  * @schema:  the context of the schema
4822  * @name:  the name of the attribute
4823  * @ns:  the target namespace of the attribute
4824  *
4825  * Lookup a an attribute in the schema or imported schemas
4826  *
4827  * Returns the attribute declaration or NULL if not found.
4828  */
4829 static xmlSchemaAttributePtr
4830 xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
4831                  const xmlChar * nsName)
4832 {
4833     xmlSchemaAttributePtr ret = NULL;
4834
4835     if ((name == NULL) || (schema == NULL))
4836         return (NULL);
4837     if (schema != NULL) {
4838         WXS_FIND_GLOBAL_ITEM(attrDecl)
4839     }
4840 exit:
4841 #ifdef DEBUG
4842     if (ret == NULL) {
4843         if (nsName == NULL)
4844             fprintf(stderr, "Unable to lookup attribute %s", name);
4845         else
4846             fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4847                     nsName);
4848     }
4849 #endif
4850     return (ret);
4851 }
4852
4853 /**
4854  * xmlSchemaGetAttributeGroup:
4855  * @schema:  the context of the schema
4856  * @name:  the name of the attribute group
4857  * @ns:  the target namespace of the attribute group
4858  *
4859  * Lookup a an attribute group in the schema or imported schemas
4860  *
4861  * Returns the attribute group definition or NULL if not found.
4862  */
4863 static xmlSchemaAttributeGroupPtr
4864 xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4865                  const xmlChar * nsName)
4866 {
4867     xmlSchemaAttributeGroupPtr ret = NULL;
4868
4869     if ((name == NULL) || (schema == NULL))
4870         return (NULL);
4871     if (schema != NULL) {
4872         WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4873     }
4874 exit:
4875     /* TODO:
4876     if ((ret != NULL) && (ret->redef != NULL)) {
4877         * Return the last redefinition. *
4878         ret = ret->redef;
4879     }
4880     */
4881 #ifdef DEBUG
4882     if (ret == NULL) {
4883         if (nsName == NULL)
4884             fprintf(stderr, "Unable to lookup attribute group %s", name);
4885         else
4886             fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4887                     nsName);
4888     }
4889 #endif
4890     return (ret);
4891 }
4892
4893 /**
4894  * xmlSchemaGetGroup:
4895  * @schema:  the context of the schema
4896  * @name:  the name of the group
4897  * @ns:  the target namespace of the group
4898  *
4899  * Lookup a group in the schema or imported schemas
4900  *
4901  * Returns the group definition or NULL if not found.
4902  */
4903 static xmlSchemaModelGroupDefPtr
4904 xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4905                  const xmlChar * nsName)
4906 {
4907     xmlSchemaModelGroupDefPtr ret = NULL;
4908
4909     if ((name == NULL) || (schema == NULL))
4910         return (NULL);
4911     if (schema != NULL) {
4912         WXS_FIND_GLOBAL_ITEM(groupDecl)
4913     }
4914 exit:
4915
4916 #ifdef DEBUG
4917     if (ret == NULL) {
4918         if (nsName == NULL)
4919             fprintf(stderr, "Unable to lookup group %s", name);
4920         else
4921             fprintf(stderr, "Unable to lookup group %s:%s", name,
4922                     nsName);
4923     }
4924 #endif
4925     return (ret);
4926 }
4927
4928 static xmlSchemaNotationPtr
4929 xmlSchemaGetNotation(xmlSchemaPtr schema,
4930                      const xmlChar *name,
4931                      const xmlChar *nsName)
4932 {
4933     xmlSchemaNotationPtr ret = NULL;
4934
4935     if ((name == NULL) || (schema == NULL))
4936         return (NULL);
4937     if (schema != NULL) {
4938         WXS_FIND_GLOBAL_ITEM(notaDecl)
4939     }
4940 exit:
4941     return (ret);
4942 }
4943
4944 static xmlSchemaIDCPtr
4945 xmlSchemaGetIDC(xmlSchemaPtr schema,
4946                 const xmlChar *name,
4947                 const xmlChar *nsName)
4948 {
4949     xmlSchemaIDCPtr ret = NULL;
4950
4951     if ((name == NULL) || (schema == NULL))
4952         return (NULL);
4953     if (schema != NULL) {
4954         WXS_FIND_GLOBAL_ITEM(idcDef)
4955     }
4956 exit:
4957     return (ret);
4958 }
4959
4960 /**
4961  * xmlSchemaGetNamedComponent:
4962  * @schema:  the schema
4963  * @name:  the name of the group
4964  * @ns:  the target namespace of the group
4965  *
4966  * Lookup a group in the schema or imported schemas
4967  *
4968  * Returns the group definition or NULL if not found.
4969  */
4970 static xmlSchemaBasicItemPtr
4971 xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4972                            xmlSchemaTypeType itemType,
4973                            const xmlChar *name,
4974                            const xmlChar *targetNs)
4975 {
4976     switch (itemType) {
4977         case XML_SCHEMA_TYPE_GROUP:
4978             return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
4979                 name, targetNs));
4980         case XML_SCHEMA_TYPE_ELEMENT:
4981             return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
4982                 name, targetNs));
4983         default:
4984             TODO
4985             return (NULL);
4986     }
4987 }
4988
4989 /************************************************************************
4990  *                                                                      *
4991  *                      Parsing functions                               *
4992  *                                                                      *
4993  ************************************************************************/
4994
4995 #define IS_BLANK_NODE(n)                                                \
4996     (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
4997
4998 /**
4999  * xmlSchemaIsBlank:
5000  * @str:  a string
5001  * @len: the length of the string or -1
5002  *
5003  * Check if a string is ignorable
5004  *
5005  * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
5006  */
5007 static int
5008 xmlSchemaIsBlank(xmlChar * str, int len)
5009 {
5010     if (str == NULL)
5011         return (1);
5012     if (len < 0) {
5013         while (*str != 0) {
5014             if (!(IS_BLANK_CH(*str)))
5015                 return (0);
5016             str++;
5017         }
5018     } else while ((*str != 0) && (len != 0)) {
5019         if (!(IS_BLANK_CH(*str)))
5020             return (0);
5021         str++;
5022         len--;
5023     }
5024
5025     return (1);
5026 }
5027
5028 #define WXS_COMP_NAME(c, t) ((t) (c))->name
5029 #define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
5030 /*
5031 * xmlSchemaFindRedefCompInGraph:
5032 * ATTENTION TODO: This uses pointer comp. for strings.
5033 */
5034 static xmlSchemaBasicItemPtr
5035 xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
5036                               xmlSchemaTypeType type,
5037                               const xmlChar *name,
5038                               const xmlChar *nsName)
5039 {
5040     xmlSchemaBasicItemPtr ret;
5041     int i;
5042
5043     if ((bucket == NULL) || (name == NULL))
5044         return(NULL);
5045     if ((bucket->globals == NULL) ||
5046         (bucket->globals->nbItems == 0))
5047         goto subschemas;
5048     /*
5049     * Search in global components.
5050     */
5051     for (i = 0; i < bucket->globals->nbItems; i++) {
5052         ret = bucket->globals->items[i];
5053         if (ret->type == type) {
5054             switch (type) {
5055                 case XML_SCHEMA_TYPE_COMPLEX:
5056                 case XML_SCHEMA_TYPE_SIMPLE:
5057                     if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
5058                         (WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5059                         nsName))
5060                     {
5061                         return(ret);
5062                     }
5063                     break;
5064                 case XML_SCHEMA_TYPE_GROUP:
5065                     if ((WXS_COMP_NAME(ret,
5066                             xmlSchemaModelGroupDefPtr) == name) &&
5067                         (WXS_COMP_TNS(ret,
5068                             xmlSchemaModelGroupDefPtr) == nsName))
5069                     {
5070                         return(ret);
5071                     }
5072                     break;
5073                 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5074                     if ((WXS_COMP_NAME(ret,
5075                             xmlSchemaAttributeGroupPtr) == name) &&
5076                         (WXS_COMP_TNS(ret,
5077                             xmlSchemaAttributeGroupPtr) == nsName))
5078                     {
5079                         return(ret);
5080                     }
5081                     break;
5082                 default:
5083                     /* Should not be hit. */
5084                     return(NULL);
5085             }
5086         }
5087     }
5088 subschemas:
5089     /*
5090     * Process imported/included schemas.
5091     */
5092     if (bucket->relations != NULL) {
5093         xmlSchemaSchemaRelationPtr rel = bucket->relations;
5094
5095         /*
5096         * TODO: Marking the bucket will not avoid multiple searches
5097         * in the same schema, but avoids at least circularity.
5098         */
5099         bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5100         do {
5101             if ((rel->bucket != NULL) &&
5102                 ((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5103                 ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5104                     type, name, nsName);
5105                 if (ret != NULL)
5106                     return(ret);
5107             }
5108             rel = rel->next;
5109         } while (rel != NULL);
5110          bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5111     }
5112     return(NULL);
5113 }
5114
5115 /**
5116  * xmlSchemaAddNotation:
5117  * @ctxt:  a schema parser context
5118  * @schema:  the schema being built
5119  * @name:  the item name
5120  *
5121  * Add an XML schema annotation declaration
5122  * *WARNING* this interface is highly subject to change
5123  *
5124  * Returns the new struture or NULL in case of error
5125  */
5126 static xmlSchemaNotationPtr
5127 xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5128                      const xmlChar *name, const xmlChar *nsName,
5129                      xmlNodePtr node ATTRIBUTE_UNUSED)
5130 {
5131     xmlSchemaNotationPtr ret = NULL;
5132
5133     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5134         return (NULL);
5135
5136     ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5137     if (ret == NULL) {
5138         xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
5139         return (NULL);
5140     }
5141     memset(ret, 0, sizeof(xmlSchemaNotation));
5142     ret->type = XML_SCHEMA_TYPE_NOTATION;
5143     ret->name = name;
5144     ret->targetNamespace = nsName;
5145     /* TODO: do we need the node to be set?
5146     * ret->node = node;*/
5147     WXS_ADD_GLOBAL(ctxt, ret);
5148     return (ret);
5149 }
5150
5151 /**
5152  * xmlSchemaAddAttribute:
5153  * @ctxt:  a schema parser context
5154  * @schema:  the schema being built
5155  * @name:  the item name
5156  * @namespace:  the namespace
5157  *
5158  * Add an XML schema Attrribute declaration
5159  * *WARNING* this interface is highly subject to change
5160  *
5161  * Returns the new struture or NULL in case of error
5162  */
5163 static xmlSchemaAttributePtr
5164 xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5165                       const xmlChar * name, const xmlChar * nsName,
5166                       xmlNodePtr node, int topLevel)
5167 {
5168     xmlSchemaAttributePtr ret = NULL;
5169
5170     if ((ctxt == NULL) || (schema == NULL))
5171         return (NULL);
5172
5173     ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5174     if (ret == NULL) {
5175         xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
5176         return (NULL);
5177     }
5178     memset(ret, 0, sizeof(xmlSchemaAttribute));
5179     ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5180     ret->node = node;
5181     ret->name = name;
5182     ret->targetNamespace = nsName;
5183
5184     if (topLevel)
5185         WXS_ADD_GLOBAL(ctxt, ret);
5186     else
5187         WXS_ADD_LOCAL(ctxt, ret);
5188     WXS_ADD_PENDING(ctxt, ret);
5189     return (ret);
5190 }
5191
5192 /**
5193  * xmlSchemaAddAttributeUse:
5194  * @ctxt:  a schema parser context
5195  * @schema:  the schema being built
5196  * @name:  the item name
5197  * @namespace:  the namespace
5198  *
5199  * Add an XML schema Attrribute declaration
5200  * *WARNING* this interface is highly subject to change
5201  *
5202  * Returns the new struture or NULL in case of error
5203  */
5204 static xmlSchemaAttributeUsePtr
5205 xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5206                          xmlNodePtr node)
5207 {
5208     xmlSchemaAttributeUsePtr ret = NULL;
5209
5210     if (pctxt == NULL)
5211         return (NULL);
5212
5213     ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5214     if (ret == NULL) {
5215         xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5216         return (NULL);
5217     }
5218     memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5219     ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5220     ret->node = node;
5221
5222     WXS_ADD_LOCAL(pctxt, ret);
5223     return (ret);
5224 }
5225
5226 /*
5227 * xmlSchemaAddRedef:
5228 *
5229 * Adds a redefinition information. This is used at a later stage to:
5230 * resolve references to the redefined components and to check constraints.
5231 */
5232 static xmlSchemaRedefPtr
5233 xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5234                   xmlSchemaBucketPtr targetBucket,
5235                   void *item,
5236                   const xmlChar *refName,
5237                   const xmlChar *refTargetNs)
5238 {
5239     xmlSchemaRedefPtr ret;
5240
5241     ret = (xmlSchemaRedefPtr)
5242         xmlMalloc(sizeof(xmlSchemaRedef));
5243     if (ret == NULL) {
5244         xmlSchemaPErrMemory(pctxt,
5245             "allocating redefinition info", NULL);
5246         return (NULL);
5247     }
5248     memset(ret, 0, sizeof(xmlSchemaRedef));
5249     ret->item = item;
5250     ret->targetBucket = targetBucket;
5251     ret->refName = refName;
5252     ret->refTargetNs = refTargetNs;
5253     if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5254         WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5255     else
5256         WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5257     WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5258
5259     return (ret);
5260 }
5261
5262 /**
5263  * xmlSchemaAddAttributeGroupDefinition:
5264  * @ctxt:  a schema parser context
5265  * @schema:  the schema being built
5266  * @name:  the item name
5267  * @nsName:  the target namespace
5268  * @node: the corresponding node
5269  *
5270  * Add an XML schema Attrribute Group definition.
5271  *
5272  * Returns the new struture or NULL in case of error
5273  */
5274 static xmlSchemaAttributeGroupPtr
5275 xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5276                            xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5277                            const xmlChar *name,
5278                            const xmlChar *nsName,
5279                            xmlNodePtr node)
5280 {
5281     xmlSchemaAttributeGroupPtr ret = NULL;
5282
5283     if ((pctxt == NULL) || (name == NULL))
5284         return (NULL);
5285
5286     ret = (xmlSchemaAttributeGroupPtr)
5287         xmlMalloc(sizeof(xmlSchemaAttributeGroup));
5288     if (ret == NULL) {
5289         xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
5290         return (NULL);
5291     }
5292     memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
5293     ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5294     ret->name = name;
5295     ret->targetNamespace = nsName;
5296     ret->node = node;
5297
5298     /* TODO: Remove the flag. */
5299     ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5300     if (pctxt->isRedefine) {
5301         pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5302             ret, name, nsName);
5303         if (pctxt->redef == NULL) {
5304             xmlFree(ret);
5305             return(NULL);
5306         }
5307         pctxt->redefCounter = 0;
5308     }
5309     WXS_ADD_GLOBAL(pctxt, ret);
5310     WXS_ADD_PENDING(pctxt, ret);
5311     return (ret);
5312 }
5313
5314 /**
5315  * xmlSchemaAddElement:
5316  * @ctxt:  a schema parser context
5317  * @schema:  the schema being built
5318  * @name:  the type name
5319  * @namespace:  the type namespace
5320  *
5321  * Add an XML schema Element declaration
5322  * *WARNING* this interface is highly subject to change
5323  *
5324  * Returns the new struture or NULL in case of error
5325  */
5326 static xmlSchemaElementPtr
5327 xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
5328                     const xmlChar * name, const xmlChar * nsName,
5329                     xmlNodePtr node, int topLevel)
5330 {
5331     xmlSchemaElementPtr ret = NULL;
5332
5333     if ((ctxt == NULL) || (name == NULL))
5334         return (NULL);
5335
5336     ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5337     if (ret == NULL) {
5338         xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
5339         return (NULL);
5340     }
5341     memset(ret, 0, sizeof(xmlSchemaElement));
5342     ret->type = XML_SCHEMA_TYPE_ELEMENT;
5343     ret->name = name;
5344     ret->targetNamespace = nsName;
5345     ret->node = node;
5346
5347     if (topLevel)
5348         WXS_ADD_GLOBAL(ctxt, ret);
5349     else
5350         WXS_ADD_LOCAL(ctxt, ret);
5351     WXS_ADD_PENDING(ctxt, ret);
5352     return (ret);
5353 }
5354
5355 /**
5356  * xmlSchemaAddType:
5357  * @ctxt:  a schema parser context
5358  * @schema:  the schema being built
5359  * @name:  the item name
5360  * @namespace:  the namespace
5361  *
5362  * Add an XML schema item
5363  * *WARNING* this interface is highly subject to change
5364  *
5365  * Returns the new struture or NULL in case of error
5366  */
5367 static xmlSchemaTypePtr
5368 xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5369                  xmlSchemaTypeType type,
5370                  const xmlChar * name, const xmlChar * nsName,
5371                  xmlNodePtr node, int topLevel)
5372 {
5373     xmlSchemaTypePtr ret = NULL;
5374
5375     if ((ctxt == NULL) || (schema == NULL))
5376         return (NULL);
5377
5378     ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5379     if (ret == NULL) {
5380         xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
5381         return (NULL);
5382     }
5383     memset(ret, 0, sizeof(xmlSchemaType));
5384     ret->type = type;
5385     ret->name = name;
5386     ret->targetNamespace = nsName;
5387     ret->node = node;
5388     if (topLevel) {
5389         if (ctxt->isRedefine) {
5390             ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5391                 ret, name, nsName);
5392             if (ctxt->redef == NULL) {
5393                 xmlFree(ret);
5394                 return(NULL);
5395             }
5396             ctxt->redefCounter = 0;
5397         }
5398         WXS_ADD_GLOBAL(ctxt, ret);
5399     } else
5400         WXS_ADD_LOCAL(ctxt, ret);
5401     WXS_ADD_PENDING(ctxt, ret);
5402     return (ret);
5403 }
5404
5405 static xmlSchemaQNameRefPtr
5406 xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
5407                      xmlSchemaTypeType refType,
5408                      const xmlChar *refName,
5409                      const xmlChar *refNs)
5410 {
5411     xmlSchemaQNameRefPtr ret;
5412
5413     ret = (xmlSchemaQNameRefPtr)
5414         xmlMalloc(sizeof(xmlSchemaQNameRef));
5415     if (ret == NULL) {
5416         xmlSchemaPErrMemory(pctxt,
5417             "allocating QName reference item", NULL);
5418         return (NULL);
5419     }
5420     ret->node = NULL;
5421     ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5422     ret->name = refName;
5423     ret->targetNamespace = refNs;
5424     ret->item = NULL;
5425     ret->itemType = refType;
5426     /*
5427     * Store the reference item in the schema.
5428     */
5429     WXS_ADD_LOCAL(pctxt, ret);
5430     return (ret);
5431 }
5432
5433 static xmlSchemaAttributeUseProhibPtr
5434 xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5435 {
5436     xmlSchemaAttributeUseProhibPtr ret;
5437
5438     ret = (xmlSchemaAttributeUseProhibPtr)
5439         xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5440     if (ret == NULL) {
5441         xmlSchemaPErrMemory(pctxt,
5442             "allocating attribute use prohibition", NULL);
5443         return (NULL);
5444     }
5445     memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5446     ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5447     WXS_ADD_LOCAL(pctxt, ret);
5448     return (ret);
5449 }
5450
5451
5452 /**
5453  * xmlSchemaAddModelGroup:
5454  * @ctxt:  a schema parser context
5455  * @schema:  the schema being built
5456  * @type: the "compositor" type of the model group
5457  * @node: the node in the schema doc
5458  *
5459  * Adds a schema model group
5460  * *WARNING* this interface is highly subject to change
5461  *
5462  * Returns the new struture or NULL in case of error
5463  */
5464 static xmlSchemaModelGroupPtr
5465 xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5466                        xmlSchemaPtr schema,
5467                        xmlSchemaTypeType type,
5468                        xmlNodePtr node)
5469 {
5470     xmlSchemaModelGroupPtr ret = NULL;
5471
5472     if ((ctxt == NULL) || (schema == NULL))
5473         return (NULL);
5474
5475     ret = (xmlSchemaModelGroupPtr)
5476         xmlMalloc(sizeof(xmlSchemaModelGroup));
5477     if (ret == NULL) {
5478         xmlSchemaPErrMemory(ctxt, "allocating model group component",
5479             NULL);
5480         return (NULL);
5481     }
5482     memset(ret, 0, sizeof(xmlSchemaModelGroup));
5483     ret->type = type;
5484     ret->node = node;
5485     WXS_ADD_LOCAL(ctxt, ret);
5486     if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5487         (type == XML_SCHEMA_TYPE_CHOICE))
5488         WXS_ADD_PENDING(ctxt, ret);
5489     return (ret);
5490 }
5491
5492
5493 /**
5494  * xmlSchemaAddParticle:
5495  * @ctxt:  a schema parser context
5496  * @schema:  the schema being built
5497  * @node: the corresponding node in the schema doc
5498  * @min: the minOccurs
5499  * @max: the maxOccurs
5500  *
5501  * Adds an XML schema particle component.
5502  * *WARNING* this interface is highly subject to change
5503  *
5504  * Returns the new struture or NULL in case of error
5505  */
5506 static xmlSchemaParticlePtr
5507 xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
5508                      xmlNodePtr node, int min, int max)
5509 {
5510     xmlSchemaParticlePtr ret = NULL;
5511     if (ctxt == NULL)
5512         return (NULL);
5513
5514 #ifdef DEBUG
5515     fprintf(stderr, "Adding particle component\n");
5516 #endif
5517     ret = (xmlSchemaParticlePtr)
5518         xmlMalloc(sizeof(xmlSchemaParticle));
5519     if (ret == NULL) {
5520         xmlSchemaPErrMemory(ctxt, "allocating particle component",
5521             NULL);
5522         return (NULL);
5523     }
5524     ret->type = XML_SCHEMA_TYPE_PARTICLE;
5525     ret->annot = NULL;
5526     ret->node = node;
5527     ret->minOccurs = min;
5528     ret->maxOccurs = max;
5529     ret->next = NULL;
5530     ret->children = NULL;
5531
5532     WXS_ADD_LOCAL(ctxt, ret);
5533     /*
5534     * Note that addition to pending components will be done locally
5535     * to the specific parsing function, since the most particles
5536     * need not to be fixed up (i.e. the reference to be resolved).
5537     * REMOVED: WXS_ADD_PENDING(ctxt, ret);
5538     */
5539     return (ret);
5540 }
5541
5542 /**
5543  * xmlSchemaAddModelGroupDefinition:
5544  * @ctxt:  a schema validation context
5545  * @schema:  the schema being built
5546  * @name:  the group name
5547  *
5548  * Add an XML schema Group definition
5549  *
5550  * Returns the new struture or NULL in case of error
5551  */
5552 static xmlSchemaModelGroupDefPtr
5553 xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5554                                  xmlSchemaPtr schema,
5555                                  const xmlChar *name,
5556                                  const xmlChar *nsName,
5557                                  xmlNodePtr node)
5558 {
5559     xmlSchemaModelGroupDefPtr ret = NULL;
5560
5561     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5562         return (NULL);
5563
5564     ret = (xmlSchemaModelGroupDefPtr)
5565         xmlMalloc(sizeof(xmlSchemaModelGroupDef));
5566     if (ret == NULL) {
5567         xmlSchemaPErrMemory(ctxt, "adding group", NULL);
5568         return (NULL);
5569     }
5570     memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
5571     ret->name = name;
5572     ret->type = XML_SCHEMA_TYPE_GROUP;
5573     ret->node = node;
5574     ret->targetNamespace = nsName;
5575
5576     if (ctxt->isRedefine) {
5577         ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5578             ret, name, nsName);
5579         if (ctxt->redef == NULL) {
5580             xmlFree(ret);
5581             return(NULL);
5582         }
5583         ctxt->redefCounter = 0;
5584     }
5585     WXS_ADD_GLOBAL(ctxt, ret);
5586     WXS_ADD_PENDING(ctxt, ret);
5587     return (ret);
5588 }
5589
5590 /**
5591  * xmlSchemaNewWildcardNs:
5592  * @ctxt:  a schema validation context
5593  *
5594  * Creates a new wildcard namespace constraint.
5595  *
5596  * Returns the new struture or NULL in case of error
5597  */
5598 static xmlSchemaWildcardNsPtr
5599 xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5600 {
5601     xmlSchemaWildcardNsPtr ret;
5602
5603     ret = (xmlSchemaWildcardNsPtr)
5604         xmlMalloc(sizeof(xmlSchemaWildcardNs));
5605     if (ret == NULL) {
5606         xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
5607         return (NULL);
5608     }
5609     ret->value = NULL;
5610     ret->next = NULL;
5611     return (ret);
5612 }
5613
5614 static xmlSchemaIDCPtr
5615 xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5616                   const xmlChar *name, const xmlChar *nsName,
5617                   int category, xmlNodePtr node)
5618 {
5619     xmlSchemaIDCPtr ret = NULL;
5620
5621     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5622         return (NULL);
5623
5624     ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5625     if (ret == NULL) {
5626         xmlSchemaPErrMemory(ctxt,
5627             "allocating an identity-constraint definition", NULL);
5628         return (NULL);
5629     }
5630     memset(ret, 0, sizeof(xmlSchemaIDC));
5631     /* The target namespace of the parent element declaration. */
5632     ret->targetNamespace = nsName;
5633     ret->name = name;
5634     ret->type = category;
5635     ret->node = node;
5636
5637     WXS_ADD_GLOBAL(ctxt, ret);
5638     /*
5639     * Only keyrefs need to be fixup up.
5640     */
5641     if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
5642         WXS_ADD_PENDING(ctxt, ret);
5643     return (ret);
5644 }
5645
5646 /**
5647  * xmlSchemaAddWildcard:
5648  * @ctxt:  a schema validation context
5649  * @schema: a schema
5650  *
5651  * Adds a wildcard.
5652  * It corresponds to a xsd:anyAttribute and xsd:any.
5653  *
5654  * Returns the new struture or NULL in case of error
5655  */
5656 static xmlSchemaWildcardPtr
5657 xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5658                      xmlSchemaTypeType type, xmlNodePtr node)
5659 {
5660     xmlSchemaWildcardPtr ret = NULL;
5661
5662     if ((ctxt == NULL) || (schema == NULL))
5663         return (NULL);
5664
5665     ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5666     if (ret == NULL) {
5667         xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5668         return (NULL);
5669     }
5670     memset(ret, 0, sizeof(xmlSchemaWildcard));
5671     ret->type = type;
5672     ret->node = node;
5673     WXS_ADD_LOCAL(ctxt, ret);
5674     return (ret);
5675 }
5676
5677 static void
5678 xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5679 {
5680     if (group == NULL)
5681         return;
5682     if (group->members != NULL)
5683         xmlSchemaItemListFree(group->members);
5684     xmlFree(group);
5685 }
5686
5687 static xmlSchemaSubstGroupPtr
5688 xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5689                        xmlSchemaElementPtr head)
5690 {
5691     xmlSchemaSubstGroupPtr ret;
5692
5693     /* Init subst group hash. */
5694     if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5695         WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5696         if (WXS_SUBST_GROUPS(pctxt) == NULL)
5697             return(NULL);
5698     }
5699     /* Create a new substitution group. */
5700     ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5701     if (ret == NULL) {
5702         xmlSchemaPErrMemory(NULL,
5703             "allocating a substitution group container", NULL);
5704         return(NULL);
5705     }
5706     memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5707     ret->head = head;
5708     /* Create list of members. */
5709     ret->members = xmlSchemaItemListCreate();
5710     if (ret->members == NULL) {
5711         xmlSchemaSubstGroupFree(ret);
5712         return(NULL);
5713     }
5714     /* Add subst group to hash. */
5715     if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5716         head->name, head->targetNamespace, ret) != 0) {
5717         PERROR_INT("xmlSchemaSubstGroupAdd",
5718             "failed to add a new substitution container");
5719         xmlSchemaSubstGroupFree(ret);
5720         return(NULL);
5721     }
5722     return(ret);
5723 }
5724
5725 static xmlSchemaSubstGroupPtr
5726 xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5727                        xmlSchemaElementPtr head)
5728 {
5729     if (WXS_SUBST_GROUPS(pctxt) == NULL)
5730         return(NULL);
5731     return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5732         head->name, head->targetNamespace));
5733
5734 }
5735
5736 /**
5737  * xmlSchemaAddElementSubstitutionMember:
5738  * @pctxt:  a schema parser context
5739  * @head:  the head of the substitution group
5740  * @member: the new member of the substitution group
5741  *
5742  * Allocate a new annotation structure.
5743  *
5744  * Returns the newly allocated structure or NULL in case or error
5745  */
5746 static int
5747 xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5748                                       xmlSchemaElementPtr head,
5749                                       xmlSchemaElementPtr member)
5750 {
5751     xmlSchemaSubstGroupPtr substGroup = NULL;
5752
5753     if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5754         return (-1);
5755
5756     substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5757     if (substGroup == NULL)
5758         substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5759     if (substGroup == NULL)
5760         return(-1);
5761     if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5762         return(-1);
5763     return(0);
5764 }
5765
5766 /************************************************************************
5767  *                                                                      *
5768  *              Utilities for parsing                                   *
5769  *                                                                      *
5770  ************************************************************************/
5771
5772 /**
5773  * xmlSchemaPValAttrNodeQNameValue:
5774  * @ctxt:  a schema parser context
5775  * @schema: the schema context
5776  * @ownerDes: the designation of the parent element
5777  * @ownerItem: the parent as a schema object
5778  * @value:  the QName value
5779  * @local: the resulting local part if found, the attribute value otherwise
5780  * @uri:  the resulting namespace URI if found
5781  *
5782  * Extracts the local name and the URI of a QName value and validates it.
5783  * This one is intended to be used on attribute values that
5784  * should resolve to schema components.
5785  *
5786  * Returns 0, in case the QName is valid, a positive error code
5787  * if not valid and -1 if an internal error occurs.
5788  */
5789 static int
5790 xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
5791                                        xmlSchemaPtr schema,
5792                                        xmlSchemaBasicItemPtr ownerItem,
5793                                        xmlAttrPtr attr,
5794                                        const xmlChar *value,
5795                                        const xmlChar **uri,
5796                                        const xmlChar **local)
5797 {
5798     const xmlChar *pref;
5799     xmlNsPtr ns;
5800     int len, ret;
5801
5802     *uri = NULL;
5803     *local = NULL;
5804     ret = xmlValidateQName(value, 1);
5805     if (ret > 0) {
5806         xmlSchemaPSimpleTypeErr(ctxt,
5807             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5808             ownerItem, (xmlNodePtr) attr,
5809             xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5810             NULL, value, NULL, NULL, NULL);
5811         *local = value;
5812         return (ctxt->err);
5813     } else if (ret < 0)
5814         return (-1);
5815
5816     if (!strchr((char *) value, ':')) {
5817         ns = xmlSearchNs(attr->doc, attr->parent, NULL);
5818         if (ns)
5819             *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5820         else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5821             /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5822             * parser context. */
5823             /*
5824             * This one takes care of included schemas with no
5825             * target namespace.
5826             */
5827             *uri = ctxt->targetNamespace;
5828         }
5829         *local = xmlDictLookup(ctxt->dict, value, -1);
5830         return (0);
5831     }
5832     /*
5833     * At this point xmlSplitQName3 has to return a local name.
5834     */
5835     *local = xmlSplitQName3(value, &len);
5836     *local = xmlDictLookup(ctxt->dict, *local, -1);
5837     pref = xmlDictLookup(ctxt->dict, value, len);
5838     ns = xmlSearchNs(attr->doc, attr->parent, pref);
5839     if (ns == NULL) {
5840         xmlSchemaPSimpleTypeErr(ctxt,
5841             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5842             ownerItem, (xmlNodePtr) attr,
5843             xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5844             "The value '%s' of simple type 'xs:QName' has no "
5845             "corresponding namespace declaration in scope", value, NULL);
5846         return (ctxt->err);
5847     } else {
5848         *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5849     }
5850     return (0);
5851 }
5852
5853 /**
5854  * xmlSchemaPValAttrNodeQName:
5855  * @ctxt:  a schema parser context
5856  * @schema: the schema context
5857  * @ownerDes: the designation of the owner element
5858  * @ownerItem: the owner as a schema object
5859  * @attr:  the attribute node
5860  * @local: the resulting local part if found, the attribute value otherwise
5861  * @uri:  the resulting namespace URI if found
5862  *
5863  * Extracts and validates the QName of an attribute value.
5864  * This one is intended to be used on attribute values that
5865  * should resolve to schema components.
5866  *
5867  * Returns 0, in case the QName is valid, a positive error code
5868  * if not valid and -1 if an internal error occurs.
5869  */
5870 static int
5871 xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
5872                                        xmlSchemaPtr schema,
5873                                        xmlSchemaBasicItemPtr ownerItem,
5874                                        xmlAttrPtr attr,
5875                                        const xmlChar **uri,
5876                                        const xmlChar **local)
5877 {
5878     const xmlChar *value;
5879
5880     value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5881     return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5882         ownerItem, attr, value, uri, local));
5883 }
5884
5885 /**
5886  * xmlSchemaPValAttrQName:
5887  * @ctxt:  a schema parser context
5888  * @schema: the schema context
5889  * @ownerDes: the designation of the parent element
5890  * @ownerItem: the owner as a schema object
5891  * @ownerElem:  the parent node of the attribute
5892  * @name:  the name of the attribute
5893  * @local: the resulting local part if found, the attribute value otherwise
5894  * @uri:  the resulting namespace URI if found
5895  *
5896  * Extracts and validates the QName of an attribute value.
5897  *
5898  * Returns 0, in case the QName is valid, a positive error code
5899  * if not valid and -1 if an internal error occurs.
5900  */
5901 static int
5902 xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5903                                    xmlSchemaPtr schema,
5904                                    xmlSchemaBasicItemPtr ownerItem,
5905                                    xmlNodePtr ownerElem,
5906                                    const char *name,
5907                                    const xmlChar **uri,
5908                                    const xmlChar **local)
5909 {
5910     xmlAttrPtr attr;
5911
5912     attr = xmlSchemaGetPropNode(ownerElem, name);
5913     if (attr == NULL) {
5914         *local = NULL;
5915         *uri = NULL;
5916         return (0);
5917     }
5918     return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5919         ownerItem, attr, uri, local));
5920 }
5921
5922 /**
5923  * xmlSchemaPValAttrID:
5924  * @ctxt:  a schema parser context
5925  * @schema: the schema context
5926  * @ownerDes: the designation of the parent element
5927  * @ownerItem: the owner as a schema object
5928  * @ownerElem:  the parent node of the attribute
5929  * @name:  the name of the attribute
5930  *
5931  * Extracts and validates the ID of an attribute value.
5932  *
5933  * Returns 0, in case the ID is valid, a positive error code
5934  * if not valid and -1 if an internal error occurs.
5935  */
5936 static int
5937 xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
5938 {
5939     int ret;
5940     const xmlChar *value;
5941
5942     if (attr == NULL)
5943         return(0);
5944     value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
5945     ret = xmlValidateNCName(value, 1);
5946     if (ret == 0) {
5947         /*
5948         * NOTE: the IDness might have already be declared in the DTD
5949         */
5950         if (attr->atype != XML_ATTRIBUTE_ID) {
5951             xmlIDPtr res;
5952             xmlChar *strip;
5953
5954             /*
5955             * TODO: Use xmlSchemaStrip here; it's not exported at this
5956             * moment.
5957             */
5958             strip = xmlSchemaCollapseString(value);
5959             if (strip != NULL) {
5960                 xmlFree((xmlChar *) value);
5961                 value = strip;
5962             }
5963             res = xmlAddID(NULL, attr->doc, value, attr);
5964             if (res == NULL) {
5965                 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5966                 xmlSchemaPSimpleTypeErr(ctxt,
5967                     XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5968                     NULL, (xmlNodePtr) attr,
5969                     xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5970                     NULL, NULL, "Duplicate value '%s' of simple "
5971                     "type 'xs:ID'", value, NULL);
5972             } else
5973                 attr->atype = XML_ATTRIBUTE_ID;
5974         }
5975     } else if (ret > 0) {
5976         ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5977         xmlSchemaPSimpleTypeErr(ctxt,
5978             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5979             NULL, (xmlNodePtr) attr,
5980             xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5981             NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5982             "not a valid 'xs:NCName'",
5983             value, NULL);
5984     }
5985     if (value != NULL)
5986         xmlFree((xmlChar *)value);
5987
5988     return (ret);
5989 }
5990
5991 static int
5992 xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
5993                     xmlNodePtr ownerElem,
5994                     const xmlChar *name)
5995 {
5996     xmlAttrPtr attr;
5997
5998     attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5999     if (attr == NULL)
6000         return(0);
6001     return(xmlSchemaPValAttrNodeID(ctxt, attr));
6002
6003 }
6004
6005 /**
6006  * xmlGetMaxOccurs:
6007  * @ctxt:  a schema validation context
6008  * @node:  a subtree containing XML Schema informations
6009  *
6010  * Get the maxOccurs property
6011  *
6012  * Returns the default if not found, or the value
6013  */
6014 static int
6015 xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6016                 int min, int max, int def, const char *expected)
6017 {
6018     const xmlChar *val, *cur;
6019     int ret = 0;
6020     xmlAttrPtr attr;
6021
6022     attr = xmlSchemaGetPropNode(node, "maxOccurs");
6023     if (attr == NULL)
6024         return (def);
6025     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6026
6027     if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
6028         if (max != UNBOUNDED) {
6029             xmlSchemaPSimpleTypeErr(ctxt,
6030                 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6031                 /* XML_SCHEMAP_INVALID_MINOCCURS, */
6032                 NULL, (xmlNodePtr) attr, NULL, expected,
6033                 val, NULL, NULL, NULL);
6034             return (def);
6035         } else
6036             return (UNBOUNDED);  /* encoding it with -1 might be another option */
6037     }
6038
6039     cur = val;
6040     while (IS_BLANK_CH(*cur))
6041         cur++;
6042     if (*cur == 0) {
6043         xmlSchemaPSimpleTypeErr(ctxt,
6044             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6045             /* XML_SCHEMAP_INVALID_MINOCCURS, */
6046             NULL, (xmlNodePtr) attr, NULL, expected,
6047             val, NULL, NULL, NULL);
6048         return (def);
6049     }
6050     while ((*cur >= '0') && (*cur <= '9')) {
6051         ret = ret * 10 + (*cur - '0');
6052         cur++;
6053     }
6054     while (IS_BLANK_CH(*cur))
6055         cur++;
6056     /*
6057     * TODO: Restrict the maximal value to Integer.
6058     */
6059     if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6060         xmlSchemaPSimpleTypeErr(ctxt,
6061             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6062             /* XML_SCHEMAP_INVALID_MINOCCURS, */
6063             NULL, (xmlNodePtr) attr, NULL, expected,
6064             val, NULL, NULL, NULL);
6065         return (def);
6066     }
6067     return (ret);
6068 }
6069
6070 /**
6071  * xmlGetMinOccurs:
6072  * @ctxt:  a schema validation context
6073  * @node:  a subtree containing XML Schema informations
6074  *
6075  * Get the minOccurs property
6076  *
6077  * Returns the default if not found, or the value
6078  */
6079 static int
6080 xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6081                 int min, int max, int def, const char *expected)
6082 {
6083     const xmlChar *val, *cur;
6084     int ret = 0;
6085     xmlAttrPtr attr;
6086
6087     attr = xmlSchemaGetPropNode(node, "minOccurs");
6088     if (attr == NULL)
6089         return (def);
6090     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6091     cur = val;
6092     while (IS_BLANK_CH(*cur))
6093         cur++;
6094     if (*cur == 0) {
6095         xmlSchemaPSimpleTypeErr(ctxt,
6096             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6097             /* XML_SCHEMAP_INVALID_MINOCCURS, */
6098             NULL, (xmlNodePtr) attr, NULL, expected,
6099             val, NULL, NULL, NULL);
6100         return (def);
6101     }
6102     while ((*cur >= '0') && (*cur <= '9')) {
6103         ret = ret * 10 + (*cur - '0');
6104         cur++;
6105     }
6106     while (IS_BLANK_CH(*cur))
6107         cur++;
6108     /*
6109     * TODO: Restrict the maximal value to Integer.
6110     */
6111     if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6112         xmlSchemaPSimpleTypeErr(ctxt,
6113             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6114             /* XML_SCHEMAP_INVALID_MINOCCURS, */
6115             NULL, (xmlNodePtr) attr, NULL, expected,
6116             val, NULL, NULL, NULL);
6117         return (def);
6118     }
6119     return (ret);
6120 }
6121
6122 /**
6123  * xmlSchemaPGetBoolNodeValue:
6124  * @ctxt:  a schema validation context
6125  * @ownerDes:  owner designation
6126  * @ownerItem:  the owner as a schema item
6127  * @node: the node holding the value
6128  *
6129  * Converts a boolean string value into 1 or 0.
6130  *
6131  * Returns 0 or 1.
6132  */
6133 static int
6134 xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
6135                            xmlSchemaBasicItemPtr ownerItem,
6136                            xmlNodePtr node)
6137 {
6138     xmlChar *value = NULL;
6139     int res = 0;
6140
6141     value = xmlNodeGetContent(node);
6142     /*
6143     * 3.2.2.1 Lexical representation
6144     * An instance of a datatype that is defined as `boolean`
6145     * can have the following legal literals {true, false, 1, 0}.
6146     */
6147     if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6148         res = 1;
6149     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6150         res = 0;
6151     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6152         res = 1;
6153     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
6154         res = 0;
6155     else {
6156         xmlSchemaPSimpleTypeErr(ctxt,
6157             XML_SCHEMAP_INVALID_BOOLEAN,
6158             ownerItem, node,
6159             xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6160             NULL, BAD_CAST value,
6161             NULL, NULL, NULL);
6162     }
6163     if (value != NULL)
6164         xmlFree(value);
6165     return (res);
6166 }
6167
6168 /**
6169  * xmlGetBooleanProp:
6170  * @ctxt:  a schema validation context
6171  * @node:  a subtree containing XML Schema informations
6172  * @name:  the attribute name
6173  * @def:  the default value
6174  *
6175  * Evaluate if a boolean property is set
6176  *
6177  * Returns the default if not found, 0 if found to be false,
6178  * 1 if found to be true
6179  */
6180 static int
6181 xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
6182                   xmlNodePtr node,
6183                   const char *name, int def)
6184 {
6185     const xmlChar *val;
6186
6187     val = xmlSchemaGetProp(ctxt, node, name);
6188     if (val == NULL)
6189         return (def);
6190     /*
6191     * 3.2.2.1 Lexical representation
6192     * An instance of a datatype that is defined as `boolean`
6193     * can have the following legal literals {true, false, 1, 0}.
6194     */
6195     if (xmlStrEqual(val, BAD_CAST "true"))
6196         def = 1;
6197     else if (xmlStrEqual(val, BAD_CAST "false"))
6198         def = 0;
6199     else if (xmlStrEqual(val, BAD_CAST "1"))
6200         def = 1;
6201     else if (xmlStrEqual(val, BAD_CAST "0"))
6202         def = 0;
6203     else {
6204         xmlSchemaPSimpleTypeErr(ctxt,
6205             XML_SCHEMAP_INVALID_BOOLEAN,
6206             NULL,
6207             (xmlNodePtr) xmlSchemaGetPropNode(node, name),
6208             xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6209             NULL, val, NULL, NULL, NULL);
6210     }
6211     return (def);
6212 }
6213
6214 /************************************************************************
6215  *                                                                      *
6216  *              Shema extraction from an Infoset                        *
6217  *                                                                      *
6218  ************************************************************************/
6219 static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6220                                                  ctxt, xmlSchemaPtr schema,
6221                                                  xmlNodePtr node,
6222                                                  int topLevel);
6223 static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6224                                                   ctxt,
6225                                                   xmlSchemaPtr schema,
6226                                                   xmlNodePtr node,
6227                                                   int topLevel);
6228 static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6229                                                   ctxt,
6230                                                   xmlSchemaPtr schema,
6231                                                   xmlNodePtr node,
6232                                                   xmlSchemaTypeType parentType);
6233 static xmlSchemaBasicItemPtr
6234 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6235                              xmlSchemaPtr schema,
6236                              xmlNodePtr node,
6237                              xmlSchemaItemListPtr uses,
6238                              int parentType);
6239 static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6240                                            xmlSchemaPtr schema,
6241                                            xmlNodePtr node);
6242 static xmlSchemaWildcardPtr
6243 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6244                            xmlSchemaPtr schema, xmlNodePtr node);
6245
6246 /**
6247  * xmlSchemaPValAttrNodeValue:
6248  *
6249  * @ctxt:  a schema parser context
6250  * @ownerDes: the designation of the parent element
6251  * @ownerItem: the schema object owner if existent
6252  * @attr:  the schema attribute node being validated
6253  * @value: the value
6254  * @type: the built-in type to be validated against
6255  *
6256  * Validates a value against the given built-in type.
6257  * This one is intended to be used internally for validation
6258  * of schema attribute values during parsing of the schema.
6259  *
6260  * Returns 0 if the value is valid, a positive error code
6261  * number otherwise and -1 in case of an internal or API error.
6262  */
6263 static int
6264 xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
6265                            xmlSchemaBasicItemPtr ownerItem,
6266                            xmlAttrPtr attr,
6267                            const xmlChar *value,
6268                            xmlSchemaTypePtr type)
6269 {
6270
6271     int ret = 0;
6272
6273     /*
6274     * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6275     * one is really meant to be used internally, so better not.
6276     */
6277     if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
6278         return (-1);
6279     if (type->type != XML_SCHEMA_TYPE_BASIC) {
6280         PERROR_INT("xmlSchemaPValAttrNodeValue",
6281             "the given type is not a built-in type");
6282         return (-1);
6283     }
6284     switch (type->builtInType) {
6285         case XML_SCHEMAS_NCNAME:
6286         case XML_SCHEMAS_QNAME:
6287         case XML_SCHEMAS_ANYURI:
6288         case XML_SCHEMAS_TOKEN:
6289         case XML_SCHEMAS_LANGUAGE:
6290             ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6291                 (xmlNodePtr) attr);
6292             break;
6293         default: {
6294             PERROR_INT("xmlSchemaPValAttrNodeValue",
6295                 "validation using the given type is not supported while "
6296                 "parsing a schema");
6297             return (-1);
6298         }
6299     }
6300     /*
6301     * TODO: Should we use the S4S error codes instead?
6302     */
6303     if (ret < 0) {
6304         PERROR_INT("xmlSchemaPValAttrNodeValue",
6305             "failed to validate a schema attribute value");
6306         return (-1);
6307     } else if (ret > 0) {
6308         if (WXS_IS_LIST(type))
6309             ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6310         else
6311             ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6312         xmlSchemaPSimpleTypeErr(pctxt,
6313             ret, ownerItem, (xmlNodePtr) attr,
6314             type, NULL, value, NULL, NULL, NULL);
6315     }
6316     return (ret);
6317 }
6318
6319 /**
6320  * xmlSchemaPValAttrNode:
6321  *
6322  * @ctxt:  a schema parser context
6323  * @ownerDes: the designation of the parent element
6324  * @ownerItem: the schema object owner if existent
6325  * @attr:  the schema attribute node being validated
6326  * @type: the built-in type to be validated against
6327  * @value: the resulting value if any
6328  *
6329  * Extracts and validates a value against the given built-in type.
6330  * This one is intended to be used internally for validation
6331  * of schema attribute values during parsing of the schema.
6332  *
6333  * Returns 0 if the value is valid, a positive error code
6334  * number otherwise and -1 in case of an internal or API error.
6335  */
6336 static int
6337 xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
6338                            xmlSchemaBasicItemPtr ownerItem,
6339                            xmlAttrPtr attr,
6340                            xmlSchemaTypePtr type,
6341                            const xmlChar **value)
6342 {
6343     const xmlChar *val;
6344
6345     if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
6346         return (-1);
6347
6348     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6349     if (value != NULL)
6350         *value = val;
6351
6352     return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
6353         val, type));
6354 }
6355
6356 /**
6357  * xmlSchemaPValAttr:
6358  *
6359  * @ctxt:  a schema parser context
6360  * @node: the element node of the attribute
6361  * @ownerDes: the designation of the parent element
6362  * @ownerItem: the schema object owner if existent
6363  * @ownerElem: the owner element node
6364  * @name:  the name of the schema attribute node
6365  * @type: the built-in type to be validated against
6366  * @value: the resulting value if any
6367  *
6368  * Extracts and validates a value against the given built-in type.
6369  * This one is intended to be used internally for validation
6370  * of schema attribute values during parsing of the schema.
6371  *
6372  * Returns 0 if the value is valid, a positive error code
6373  * number otherwise and -1 in case of an internal or API error.
6374  */
6375 static int
6376 xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6377                        xmlSchemaBasicItemPtr ownerItem,
6378                        xmlNodePtr ownerElem,
6379                        const char *name,
6380                        xmlSchemaTypePtr type,
6381                        const xmlChar **value)
6382 {
6383     xmlAttrPtr attr;
6384
6385     if ((ctxt == NULL) || (type == NULL)) {
6386         if (value != NULL)
6387             *value = NULL;
6388         return (-1);
6389     }
6390     if (type->type != XML_SCHEMA_TYPE_BASIC) {
6391         if (value != NULL)
6392             *value = NULL;
6393         xmlSchemaPErr(ctxt, ownerElem,
6394             XML_SCHEMAP_INTERNAL,
6395             "Internal error: xmlSchemaPValAttr, the given "
6396             "type '%s' is not a built-in type.\n",
6397             type->name, NULL);
6398         return (-1);
6399     }
6400     attr = xmlSchemaGetPropNode(ownerElem, name);
6401     if (attr == NULL) {
6402         if (value != NULL)
6403             *value = NULL;
6404         return (0);
6405     }
6406     return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
6407         type, value));
6408 }
6409
6410 static int
6411 xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
6412                   xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6413                   xmlNodePtr node,
6414                   xmlAttrPtr attr,
6415                   const xmlChar *namespaceName)
6416 {
6417     /* TODO: Pointer comparison instead? */
6418     if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
6419         return (0);
6420     if (xmlStrEqual(xmlSchemaNs, namespaceName))
6421         return (0);
6422     /*
6423     * Check if the referenced namespace was <import>ed.
6424     */
6425     if (WXS_BUCKET(pctxt)->relations != NULL) {
6426         xmlSchemaSchemaRelationPtr rel;
6427
6428         rel = WXS_BUCKET(pctxt)->relations;
6429         do {
6430             if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
6431                 xmlStrEqual(namespaceName, rel->importNamespace))
6432                 return (0);
6433             rel = rel->next;
6434         } while (rel != NULL);
6435     }
6436     /*
6437     * No matching <import>ed namespace found.
6438     */
6439     {
6440         xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6441
6442         if (namespaceName == NULL)
6443             xmlSchemaCustomErr(ACTXT_CAST pctxt,
6444                 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6445                 "References from this schema to components in no "
6446                 "namespace are not allowed, since not indicated by an "
6447                 "import statement", NULL, NULL);
6448         else
6449             xmlSchemaCustomErr(ACTXT_CAST pctxt,
6450                 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6451                 "References from this schema to components in the "
6452                 "namespace '%s' are not allowed, since not indicated by an "
6453                 "import statement", namespaceName, NULL);
6454     }
6455     return (XML_SCHEMAP_SRC_RESOLVE);
6456 }
6457
6458 /**
6459  * xmlSchemaParseLocalAttributes:
6460  * @ctxt:  a schema validation context
6461  * @schema:  the schema being built
6462  * @node:  a subtree containing XML Schema informations
6463  * @type:  the hosting type where the attributes will be anchored
6464  *
6465  * Parses attribute uses and attribute declarations and
6466  * attribute group references.
6467  */
6468 static int
6469 xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6470                         xmlNodePtr *child, xmlSchemaItemListPtr *list,
6471                         int parentType, int *hasRefs)
6472 {
6473     void *item;
6474
6475     while ((IS_SCHEMA((*child), "attribute")) ||
6476            (IS_SCHEMA((*child), "attributeGroup"))) {
6477         if (IS_SCHEMA((*child), "attribute")) {
6478             item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6479                 *list, parentType);
6480         } else {
6481             item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6482             if ((item != NULL) && (hasRefs != NULL))
6483                 *hasRefs = 1;
6484         }
6485         if (item != NULL) {
6486             if (*list == NULL) {
6487                 /* TODO: Customize grow factor. */
6488                 *list = xmlSchemaItemListCreate();
6489                 if (*list == NULL)
6490                     return(-1);
6491             }
6492             if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6493                 return(-1);
6494         }
6495         *child = (*child)->next;
6496     }
6497     return (0);
6498 }
6499
6500 /**
6501  * xmlSchemaParseAnnotation:
6502  * @ctxt:  a schema validation context
6503  * @schema:  the schema being built
6504  * @node:  a subtree containing XML Schema informations
6505  *
6506  * parse a XML schema Attrribute declaration
6507  * *WARNING* this interface is highly subject to change
6508  *
6509  * Returns -1 in case of error, 0 if the declaration is improper and
6510  *         1 in case of success.
6511  */
6512 static xmlSchemaAnnotPtr
6513 xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed)
6514 {
6515     xmlSchemaAnnotPtr ret;
6516     xmlNodePtr child = NULL;
6517     xmlAttrPtr attr;
6518     int barked = 0;
6519
6520     /*
6521     * INFO: S4S completed.
6522     */
6523     /*
6524     * id = ID
6525     * {any attributes with non-schema namespace . . .}>
6526     * Content: (appinfo | documentation)*
6527     */
6528     if ((ctxt == NULL) || (node == NULL))
6529         return (NULL);
6530     if (needed)
6531         ret = xmlSchemaNewAnnot(ctxt, node);
6532     else
6533         ret = NULL;
6534     attr = node->properties;
6535     while (attr != NULL) {
6536         if (((attr->ns == NULL) &&
6537             (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
6538             ((attr->ns != NULL) &&
6539             xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6540
6541             xmlSchemaPIllegalAttrErr(ctxt,
6542                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6543         }
6544         attr = attr->next;
6545     }
6546     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6547     /*
6548     * And now for the children...
6549     */
6550     child = node->children;
6551     while (child != NULL) {
6552         if (IS_SCHEMA(child, "appinfo")) {
6553             /* TODO: make available the content of "appinfo". */
6554             /*
6555             * source = anyURI
6556             * {any attributes with non-schema namespace . . .}>
6557             * Content: ({any})*
6558             */
6559             attr = child->properties;
6560             while (attr != NULL) {
6561                 if (((attr->ns == NULL) &&
6562                      (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
6563                      ((attr->ns != NULL) &&
6564                       xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6565
6566                     xmlSchemaPIllegalAttrErr(ctxt,
6567                         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6568                 }
6569                 attr = attr->next;
6570             }
6571             xmlSchemaPValAttr(ctxt, NULL, child, "source",
6572                 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
6573             child = child->next;
6574         } else if (IS_SCHEMA(child, "documentation")) {
6575             /* TODO: make available the content of "documentation". */
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                     if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
6585                         xmlSchemaPIllegalAttrErr(ctxt,
6586                             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6587                     }
6588                 } else {
6589                     if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6590                         (xmlStrEqual(attr->name, BAD_CAST "lang") &&
6591                         (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
6592
6593                         xmlSchemaPIllegalAttrErr(ctxt,
6594                             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6595                     }
6596                 }
6597                 attr = attr->next;
6598             }
6599             /*
6600             * Attribute "xml:lang".
6601             */
6602             attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6603             if (attr != NULL)
6604                 xmlSchemaPValAttrNode(ctxt, NULL, attr,
6605                 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
6606             child = child->next;
6607         } else {
6608             if (!barked)
6609                 xmlSchemaPContentErr(ctxt,
6610                     XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6611                     NULL, node, child, NULL, "(appinfo | documentation)*");
6612             barked = 1;
6613             child = child->next;
6614         }
6615     }
6616
6617     return (ret);
6618 }
6619
6620 /**
6621  * xmlSchemaParseFacet:
6622  * @ctxt:  a schema validation context
6623  * @schema:  the schema being built
6624  * @node:  a subtree containing XML Schema informations
6625  *
6626  * parse a XML schema Facet declaration
6627  * *WARNING* this interface is highly subject to change
6628  *
6629  * Returns the new type structure or NULL in case of error
6630  */
6631 static xmlSchemaFacetPtr
6632 xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6633                     xmlNodePtr node)
6634 {
6635     xmlSchemaFacetPtr facet;
6636     xmlNodePtr child = NULL;
6637     const xmlChar *value;
6638
6639     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6640         return (NULL);
6641
6642     facet = xmlSchemaNewFacet();
6643     if (facet == NULL) {
6644         xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6645         return (NULL);
6646     }
6647     facet->node = node;
6648     value = xmlSchemaGetProp(ctxt, node, "value");
6649     if (value == NULL) {
6650         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6651                        "Facet %s has no value\n", node->name, NULL);
6652         xmlSchemaFreeFacet(facet);
6653         return (NULL);
6654     }
6655     if (IS_SCHEMA(node, "minInclusive")) {
6656         facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
6657     } else if (IS_SCHEMA(node, "minExclusive")) {
6658         facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
6659     } else if (IS_SCHEMA(node, "maxInclusive")) {
6660         facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
6661     } else if (IS_SCHEMA(node, "maxExclusive")) {
6662         facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
6663     } else if (IS_SCHEMA(node, "totalDigits")) {
6664         facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
6665     } else if (IS_SCHEMA(node, "fractionDigits")) {
6666         facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
6667     } else if (IS_SCHEMA(node, "pattern")) {
6668         facet->type = XML_SCHEMA_FACET_PATTERN;
6669     } else if (IS_SCHEMA(node, "enumeration")) {
6670         facet->type = XML_SCHEMA_FACET_ENUMERATION;
6671     } else if (IS_SCHEMA(node, "whiteSpace")) {
6672         facet->type = XML_SCHEMA_FACET_WHITESPACE;
6673     } else if (IS_SCHEMA(node, "length")) {
6674         facet->type = XML_SCHEMA_FACET_LENGTH;
6675     } else if (IS_SCHEMA(node, "maxLength")) {
6676         facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6677     } else if (IS_SCHEMA(node, "minLength")) {
6678         facet->type = XML_SCHEMA_FACET_MINLENGTH;
6679     } else {
6680         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6681                        "Unknown facet type %s\n", node->name, NULL);
6682         xmlSchemaFreeFacet(facet);
6683         return (NULL);
6684     }
6685     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6686     facet->value = value;
6687     if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6688         (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6689         const xmlChar *fixed;
6690
6691         fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6692         if (fixed != NULL) {
6693             if (xmlStrEqual(fixed, BAD_CAST "true"))
6694                 facet->fixed = 1;
6695         }
6696     }
6697     child = node->children;
6698
6699     if (IS_SCHEMA(child, "annotation")) {
6700         facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6701         child = child->next;
6702     }
6703     if (child != NULL) {
6704         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6705                        "Facet %s has unexpected child content\n",
6706                        node->name, NULL);
6707     }
6708     return (facet);
6709 }
6710
6711 /**
6712  * xmlSchemaParseWildcardNs:
6713  * @ctxt:  a schema parser context
6714  * @wildc:  the wildcard, already created
6715  * @node:  a subtree containing XML Schema informations
6716  *
6717  * Parses the attribute "processContents" and "namespace"
6718  * of a xsd:anyAttribute and xsd:any.
6719  * *WARNING* this interface is highly subject to change
6720  *
6721  * Returns 0 if everything goes fine, a positive error code
6722  * if something is not valid and -1 if an internal error occurs.
6723  */
6724 static int
6725 xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
6726                          xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6727                          xmlSchemaWildcardPtr wildc,
6728                          xmlNodePtr node)
6729 {
6730     const xmlChar *pc, *ns, *dictnsItem;
6731     int ret = 0;
6732     xmlChar *nsItem;
6733     xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6734     xmlAttrPtr attr;
6735
6736     pc = xmlSchemaGetProp(ctxt, node, "processContents");
6737     if ((pc == NULL)
6738         || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6739         wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6740     } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6741         wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6742     } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6743         wildc->processContents = XML_SCHEMAS_ANY_LAX;
6744     } else {
6745         xmlSchemaPSimpleTypeErr(ctxt,
6746             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6747             NULL, node,
6748             NULL, "(strict | skip | lax)", pc,
6749             NULL, NULL, NULL);
6750         wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6751         ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6752     }
6753     /*
6754      * Build the namespace constraints.
6755      */
6756     attr = xmlSchemaGetPropNode(node, "namespace");
6757     ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6758     if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
6759         wildc->any = 1;
6760     else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6761         wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6762         if (wildc->negNsSet == NULL) {
6763             return (-1);
6764         }
6765         wildc->negNsSet->value = ctxt->targetNamespace;
6766     } else {
6767         const xmlChar *end, *cur;
6768
6769         cur = ns;
6770         do {
6771             while (IS_BLANK_CH(*cur))
6772                 cur++;
6773             end = cur;
6774             while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6775                 end++;
6776             if (end == cur)
6777                 break;
6778             nsItem = xmlStrndup(cur, end - cur);
6779             if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6780                     (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
6781                 xmlSchemaPSimpleTypeErr(ctxt,
6782                     XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
6783                     NULL, (xmlNodePtr) attr,
6784                     NULL,
6785                     "((##any | ##other) | List of (xs:anyURI | "
6786                     "(##targetNamespace | ##local)))",
6787                     nsItem, NULL, NULL, NULL);
6788                 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6789             } else {
6790                 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
6791                     dictnsItem = ctxt->targetNamespace;
6792                 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6793                     dictnsItem = NULL;
6794                 } else {
6795                     /*
6796                     * Validate the item (anyURI).
6797                     */
6798                     xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
6799                         nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6800                     dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6801                 }
6802                 /*
6803                 * Avoid dublicate namespaces.
6804                 */
6805                 tmp = wildc->nsSet;
6806                 while (tmp != NULL) {
6807                     if (dictnsItem == tmp->value)
6808                         break;
6809                     tmp = tmp->next;
6810                 }
6811                 if (tmp == NULL) {
6812                     tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6813                     if (tmp == NULL) {
6814                         xmlFree(nsItem);
6815                         return (-1);
6816                     }
6817                     tmp->value = dictnsItem;
6818                     tmp->next = NULL;
6819                     if (wildc->nsSet == NULL)
6820                         wildc->nsSet = tmp;
6821                     else if (lastNs != NULL)
6822                         lastNs->next = tmp;
6823                     lastNs = tmp;
6824                 }
6825
6826             }
6827             xmlFree(nsItem);
6828             cur = end;
6829         } while (*cur != 0);
6830     }
6831     return (ret);
6832 }
6833
6834 static int
6835 xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6836                                  xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
6837                                  xmlNodePtr node,
6838                                  int minOccurs,
6839                                  int maxOccurs) {
6840
6841     if ((maxOccurs == 0) && ( minOccurs == 0))
6842         return (0);
6843     if (maxOccurs != UNBOUNDED) {
6844         /*
6845         * TODO: Maybe we should better not create the particle,
6846         * if min/max is invalid, since it could confuse the build of the
6847         * content model.
6848         */
6849         /*
6850         * 3.9.6 Schema Component Constraint: Particle Correct
6851         *
6852         */
6853         if (maxOccurs < 1) {
6854             /*
6855             * 2.2 {max occurs} must be greater than or equal to 1.
6856             */
6857             xmlSchemaPCustomAttrErr(ctxt,
6858                 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
6859                 NULL, NULL,
6860                 xmlSchemaGetPropNode(node, "maxOccurs"),
6861                 "The value must be greater than or equal to 1");
6862             return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6863         } else if (minOccurs > maxOccurs) {
6864             /*
6865             * 2.1 {min occurs} must not be greater than {max occurs}.
6866             */
6867             xmlSchemaPCustomAttrErr(ctxt,
6868                 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
6869                 NULL, NULL,
6870                 xmlSchemaGetPropNode(node, "minOccurs"),
6871                 "The value must not be greater than the value of 'maxOccurs'");
6872             return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6873         }
6874     }
6875     return (0);
6876 }
6877
6878 /**
6879  * xmlSchemaParseAny:
6880  * @ctxt:  a schema validation context
6881  * @schema:  the schema being built
6882  * @node:  a subtree containing XML Schema informations
6883  *
6884  * Parsea a XML schema <any> element. A particle and wildcard
6885  * will be created (except if minOccurs==maxOccurs==0, in this case
6886  * nothing will be created).
6887  * *WARNING* this interface is highly subject to change
6888  *
6889  * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
6890  */
6891 static xmlSchemaParticlePtr
6892 xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6893                   xmlNodePtr node)
6894 {
6895     xmlSchemaParticlePtr particle;
6896     xmlNodePtr child = NULL;
6897     xmlSchemaWildcardPtr wild;
6898     int min, max;
6899     xmlAttrPtr attr;
6900     xmlSchemaAnnotPtr annot = NULL;
6901
6902     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6903         return (NULL);
6904     /*
6905     * Check for illegal attributes.
6906     */
6907     attr = node->properties;
6908     while (attr != NULL) {
6909         if (attr->ns == NULL) {
6910             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6911                 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6912                 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6913                 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6914                 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
6915                 xmlSchemaPIllegalAttrErr(ctxt,
6916                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6917             }
6918         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6919             xmlSchemaPIllegalAttrErr(ctxt,
6920                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6921         }
6922         attr = attr->next;
6923     }
6924     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6925     /*
6926     * minOccurs/maxOccurs.
6927     */
6928     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6929         "(xs:nonNegativeInteger | unbounded)");
6930     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6931         "xs:nonNegativeInteger");
6932     xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6933     /*
6934     * Create & parse the wildcard.
6935     */
6936     wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6937     if (wild == NULL)
6938         return (NULL);
6939     xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
6940     /*
6941     * And now for the children...
6942     */
6943     child = node->children;
6944     if (IS_SCHEMA(child, "annotation")) {
6945         annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6946         child = child->next;
6947     }
6948     if (child != NULL) {
6949         xmlSchemaPContentErr(ctxt,
6950             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6951             NULL, node, child,
6952             NULL, "(annotation?)");
6953     }
6954     /*
6955     * No component if minOccurs==maxOccurs==0.
6956     */
6957     if ((min == 0) && (max == 0)) {
6958         /* Don't free the wildcard, since it's already on the list. */
6959         return (NULL);
6960     }
6961     /*
6962     * Create the particle.
6963     */
6964     particle = xmlSchemaAddParticle(ctxt, node, min, max);
6965     if (particle == NULL)
6966         return (NULL);
6967     particle->annot = annot;
6968     particle->children = (xmlSchemaTreeItemPtr) wild;
6969
6970     return (particle);
6971 }
6972
6973 /**
6974  * xmlSchemaParseNotation:
6975  * @ctxt:  a schema validation context
6976  * @schema:  the schema being built
6977  * @node:  a subtree containing XML Schema informations
6978  *
6979  * parse a XML schema Notation declaration
6980  *
6981  * Returns the new structure or NULL in case of error
6982  */
6983 static xmlSchemaNotationPtr
6984 xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6985                        xmlNodePtr node)
6986 {
6987     const xmlChar *name;
6988     xmlSchemaNotationPtr ret;
6989     xmlNodePtr child = NULL;
6990
6991     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6992         return (NULL);
6993     name = xmlSchemaGetProp(ctxt, node, "name");
6994     if (name == NULL) {
6995         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6996                        "Notation has no name\n", NULL, NULL);
6997         return (NULL);
6998     }
6999     ret = xmlSchemaAddNotation(ctxt, schema, name,
7000         ctxt->targetNamespace, node);
7001     if (ret == NULL)
7002         return (NULL);
7003     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7004
7005     child = node->children;
7006     if (IS_SCHEMA(child, "annotation")) {
7007         ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7008         child = child->next;
7009     }
7010     if (child != NULL) {
7011         xmlSchemaPContentErr(ctxt,
7012             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7013             NULL, node, child,
7014             NULL, "(annotation?)");
7015     }
7016
7017     return (ret);
7018 }
7019
7020 /**
7021  * xmlSchemaParseAnyAttribute:
7022  * @ctxt:  a schema validation context
7023  * @schema:  the schema being built
7024  * @node:  a subtree containing XML Schema informations
7025  *
7026  * parse a XML schema AnyAttrribute declaration
7027  * *WARNING* this interface is highly subject to change
7028  *
7029  * Returns a wildcard or NULL.
7030  */
7031 static xmlSchemaWildcardPtr
7032 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
7033                            xmlSchemaPtr schema, xmlNodePtr node)
7034 {
7035     xmlSchemaWildcardPtr ret;
7036     xmlNodePtr child = NULL;
7037     xmlAttrPtr attr;
7038
7039     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7040         return (NULL);
7041
7042     ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
7043         node);
7044     if (ret == NULL) {
7045         return (NULL);
7046     }
7047     /*
7048     * Check for illegal attributes.
7049     */
7050     attr = node->properties;
7051     while (attr != NULL) {
7052         if (attr->ns == NULL) {
7053             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7054                 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7055                 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
7056                 xmlSchemaPIllegalAttrErr(ctxt,
7057                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7058             }
7059         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7060             xmlSchemaPIllegalAttrErr(ctxt,
7061                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7062         }
7063         attr = attr->next;
7064     }
7065     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7066     /*
7067     * Parse the namespace list.
7068     */
7069     if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
7070         return (NULL);
7071     /*
7072     * And now for the children...
7073     */
7074     child = node->children;
7075     if (IS_SCHEMA(child, "annotation")) {
7076         ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7077         child = child->next;
7078     }
7079     if (child != NULL) {
7080         xmlSchemaPContentErr(ctxt,
7081             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7082             NULL, node, child,
7083             NULL, "(annotation?)");
7084     }
7085
7086     return (ret);
7087 }
7088
7089
7090 /**
7091  * xmlSchemaParseAttribute:
7092  * @ctxt:  a schema validation context
7093  * @schema:  the schema being built
7094  * @node:  a subtree containing XML Schema informations
7095  *
7096  * parse a XML schema Attrribute declaration
7097  * *WARNING* this interface is highly subject to change
7098  *
7099  * Returns the attribute declaration.
7100  */
7101 static xmlSchemaBasicItemPtr
7102 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7103                              xmlSchemaPtr schema,
7104                              xmlNodePtr node,
7105                              xmlSchemaItemListPtr uses,
7106                              int parentType)
7107 {
7108     const xmlChar *attrValue, *name = NULL, *ns = NULL;
7109     xmlSchemaAttributeUsePtr use = NULL;
7110     xmlNodePtr child = NULL;
7111     xmlAttrPtr attr;
7112     const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7113     int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7114     int nberrors, hasForm = 0, defValueType = 0;
7115
7116 #define WXS_ATTR_DEF_VAL_DEFAULT 1
7117 #define WXS_ATTR_DEF_VAL_FIXED 2
7118
7119     /*
7120      * 3.2.3 Constraints on XML Representations of Attribute Declarations
7121      */
7122
7123     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7124         return (NULL);
7125     attr = xmlSchemaGetPropNode(node, "ref");
7126     if (attr != NULL) {
7127         if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7128             NULL, attr, &tmpNs, &tmpName) != 0) {
7129             return (NULL);
7130         }
7131         if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7132             return(NULL);
7133         isRef = 1;
7134     }
7135     nberrors = pctxt->nberrors;
7136     /*
7137     * Check for illegal attributes.
7138     */
7139     attr = node->properties;
7140     while (attr != NULL) {
7141         if (attr->ns == NULL) {
7142             if (isRef) {
7143                 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7144                     xmlSchemaPValAttrNodeID(pctxt, attr);
7145                     goto attr_next;
7146                 } else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7147                     goto attr_next;
7148                 }
7149             } else {
7150                 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7151                     goto attr_next;
7152                 } else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7153                     xmlSchemaPValAttrNodeID(pctxt, attr);
7154                     goto attr_next;
7155                 } else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7156                     xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7157                         attr, &tmpNs, &tmpName);
7158                     goto attr_next;
7159                 } else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7160                     /*
7161                     * Evaluate the target namespace
7162                     */
7163                     hasForm = 1;
7164                     attrValue = xmlSchemaGetNodeContent(pctxt,
7165                         (xmlNodePtr) attr);
7166                     if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7167                         ns = pctxt->targetNamespace;
7168                     } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7169                     {
7170                         xmlSchemaPSimpleTypeErr(pctxt,
7171                             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7172                             NULL, (xmlNodePtr) attr,
7173                             NULL, "(qualified | unqualified)",
7174                             attrValue, NULL, NULL, NULL);
7175                     }
7176                     goto attr_next;
7177                 }
7178             }
7179             if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7180
7181                 attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7182                 /* TODO: Maybe we need to normalize the value beforehand. */
7183                 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7184                     occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7185                 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7186                     occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7187                 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7188                     occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7189                 else {
7190                     xmlSchemaPSimpleTypeErr(pctxt,
7191                         XML_SCHEMAP_INVALID_ATTR_USE,
7192                         NULL, (xmlNodePtr) attr,
7193                         NULL, "(optional | prohibited | required)",
7194                         attrValue, NULL, NULL, NULL);
7195                 }
7196                 goto attr_next;
7197             } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7198                 /*
7199                 * 3.2.3 : 1
7200                 * default and fixed must not both be present.
7201                 */
7202                 if (defValue) {
7203                     xmlSchemaPMutualExclAttrErr(pctxt,
7204                         XML_SCHEMAP_SRC_ATTRIBUTE_1,
7205                         NULL, attr, "default", "fixed");
7206                 } else {
7207                     defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7208                     defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7209                 }
7210                 goto attr_next;
7211             } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7212                 /*
7213                 * 3.2.3 : 1
7214                 * default and fixed must not both be present.
7215                 */
7216                 if (defValue) {
7217                     xmlSchemaPMutualExclAttrErr(pctxt,
7218                         XML_SCHEMAP_SRC_ATTRIBUTE_1,
7219                         NULL, attr, "default", "fixed");
7220                 } else {
7221                     defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7222                     defValueType = WXS_ATTR_DEF_VAL_FIXED;
7223                 }
7224                 goto attr_next;
7225             }
7226         } else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7227             goto attr_next;
7228
7229         xmlSchemaPIllegalAttrErr(pctxt,
7230             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7231
7232 attr_next:
7233         attr = attr->next;
7234     }
7235     /*
7236     * 3.2.3 : 2
7237     * If default and use are both present, use must have
7238     * the actual value optional.
7239     */
7240     if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7241         (occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7242         xmlSchemaPSimpleTypeErr(pctxt,
7243             XML_SCHEMAP_SRC_ATTRIBUTE_2,
7244             NULL, node, NULL,
7245             "(optional | prohibited | required)", NULL,
7246             "The value of the attribute 'use' must be 'optional' "
7247             "if the attribute 'default' is present",
7248             NULL, NULL);
7249     }
7250     /*
7251     * We want correct attributes.
7252     */
7253     if (nberrors != pctxt->nberrors)
7254         return(NULL);
7255     if (! isRef) {
7256         xmlSchemaAttributePtr attrDecl;
7257
7258         /* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7259         if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7260             ns = pctxt->targetNamespace;
7261         /*
7262         * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7263         * TODO: Move this to the component layer.
7264         */
7265         if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7266             xmlSchemaCustomErr(ACTXT_CAST pctxt,
7267                 XML_SCHEMAP_NO_XSI,
7268                 node, NULL,
7269                 "The target namespace must not match '%s'",
7270                 xmlSchemaInstanceNs, NULL);
7271         }
7272         attr = xmlSchemaGetPropNode(node, "name");
7273         if (attr == NULL) {
7274             xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7275                 NULL, node, "name", NULL);
7276             return (NULL);
7277         }
7278         if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7279             xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7280             return (NULL);
7281         }
7282         /*
7283         * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7284         * TODO: Move this to the component layer.
7285         */
7286         if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7287             xmlSchemaPSimpleTypeErr(pctxt,
7288                 XML_SCHEMAP_NO_XMLNS,
7289                 NULL, (xmlNodePtr) attr,
7290                 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7291                 "The value of the attribute must not match 'xmlns'",
7292                 NULL, NULL);
7293             return (NULL);
7294         }
7295         if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7296             goto check_children;
7297         /*
7298         * Create the attribute use component.
7299         */
7300         use = xmlSchemaAddAttributeUse(pctxt, node);
7301         if (use == NULL)
7302             return(NULL);
7303         use->occurs = occurs;
7304         /*
7305         * Create the attribute declaration.
7306         */
7307         attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7308         if (attrDecl == NULL)
7309             return (NULL);
7310         if (tmpName != NULL) {
7311             attrDecl->typeName = tmpName;
7312             attrDecl->typeNs = tmpNs;
7313         }
7314         use->attrDecl = attrDecl;
7315         /*
7316         * Value constraint.
7317         */
7318         if (defValue != NULL) {
7319             attrDecl->defValue = defValue;
7320             if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7321                 attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7322         }
7323     } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7324         xmlSchemaQNameRefPtr ref;
7325
7326         /*
7327         * Create the attribute use component.
7328         */
7329         use = xmlSchemaAddAttributeUse(pctxt, node);
7330         if (use == NULL)
7331             return(NULL);
7332         /*
7333         * We need to resolve the reference at later stage.
7334         */
7335         WXS_ADD_PENDING(pctxt, use);
7336         use->occurs = occurs;
7337         /*
7338         * Create a QName reference to the attribute declaration.
7339         */
7340         ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7341             tmpName, tmpNs);
7342         if (ref == NULL)
7343             return(NULL);
7344         /*
7345         * Assign the reference. This will be substituted for the
7346         * referenced attribute declaration when the QName is resolved.
7347         */
7348         use->attrDecl = WXS_ATTR_CAST ref;
7349         /*
7350         * Value constraint.
7351         */
7352         if (defValue != NULL)
7353             use->defValue = defValue;
7354             if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7355                 use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7356     }
7357
7358 check_children:
7359     /*
7360     * And now for the children...
7361     */
7362     child = node->children;
7363     if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7364         xmlSchemaAttributeUseProhibPtr prohib;
7365
7366         if (IS_SCHEMA(child, "annotation")) {
7367             xmlSchemaParseAnnotation(pctxt, child, 0);
7368             child = child->next;
7369         }
7370         if (child != NULL) {
7371             xmlSchemaPContentErr(pctxt,
7372                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7373                 NULL, node, child, NULL,
7374                 "(annotation?)");
7375         }
7376         /*
7377         * Check for pointlessness of attribute prohibitions.
7378         */
7379         if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7380             xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7381                 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7382                 node, NULL,
7383                 "Skipping attribute use prohibition, since it is "
7384                 "pointless inside an <attributeGroup>",
7385                 NULL, NULL, NULL);
7386             return(NULL);
7387         } else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7388             xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7389                 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7390                 node, NULL,
7391                 "Skipping attribute use prohibition, since it is "
7392                 "pointless when extending a type",
7393                 NULL, NULL, NULL);
7394             return(NULL);
7395         }
7396         if (! isRef) {
7397             tmpName = name;
7398             tmpNs = ns;
7399         }
7400         /*
7401         * Check for duplicate attribute prohibitions.
7402         */
7403         if (uses) {
7404             int i;
7405
7406             for (i = 0; i < uses->nbItems; i++) {
7407                 use = uses->items[i];
7408                 if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7409                     (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7410                     (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7411                 {
7412                     xmlChar *str = NULL;
7413
7414                     xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7415                         XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7416                         node, NULL,
7417                         "Skipping duplicate attribute use prohibition '%s'",
7418                         xmlSchemaFormatQName(&str, tmpNs, tmpName),
7419                         NULL, NULL);
7420                     FREE_AND_NULL(str)
7421                     return(NULL);
7422                 }
7423             }
7424         }
7425         /*
7426         * Create the attribute prohibition helper component.
7427         */
7428         prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7429         if (prohib == NULL)
7430             return(NULL);
7431         prohib->node = node;
7432         prohib->name = tmpName;
7433         prohib->targetNamespace = tmpNs;
7434         if (isRef) {
7435             /*
7436             * We need at least to resolve to the attribute declaration.
7437             */
7438             WXS_ADD_PENDING(pctxt, prohib);
7439         }
7440         return(WXS_BASIC_CAST prohib);
7441     } else {
7442         if (IS_SCHEMA(child, "annotation")) {
7443             /*
7444             * TODO: Should this go into the attr decl?
7445             */
7446             use->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7447             child = child->next;
7448         }
7449         if (isRef) {
7450             if (child != NULL) {
7451                 if (IS_SCHEMA(child, "simpleType"))
7452                     /*
7453                     * 3.2.3 : 3.2
7454                     * If ref is present, then all of <simpleType>,
7455                     * form and type must be absent.
7456                     */
7457                     xmlSchemaPContentErr(pctxt,
7458                         XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7459                         NULL, node, child, NULL,
7460                         "(annotation?)");
7461                 else
7462                     xmlSchemaPContentErr(pctxt,
7463                         XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7464                         NULL, node, child, NULL,
7465                         "(annotation?)");
7466             }
7467         } else {
7468             if (IS_SCHEMA(child, "simpleType")) {
7469                 if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7470                     /*
7471                     * 3.2.3 : 4
7472                     * type and <simpleType> must not both be present.
7473                     */
7474                     xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7475                         NULL, node, child,
7476                         "The attribute 'type' and the <simpleType> child "
7477                         "are mutually exclusive", NULL);
7478                 } else
7479                     WXS_ATTRUSE_TYPEDEF(use) =
7480                         xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7481                 child = child->next;
7482             }
7483             if (child != NULL)
7484                 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7485                 NULL, node, child, NULL,
7486                 "(annotation?, simpleType?)");
7487         }
7488     }
7489     return (WXS_BASIC_CAST use);
7490 }
7491
7492
7493 static xmlSchemaAttributePtr
7494 xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7495                               xmlSchemaPtr schema,
7496                               xmlNodePtr node)
7497 {
7498     const xmlChar *attrValue;
7499     xmlSchemaAttributePtr ret;
7500     xmlNodePtr child = NULL;
7501     xmlAttrPtr attr;
7502
7503     /*
7504      * Note that the w3c spec assumes the schema to be validated with schema
7505      * for schemas beforehand.
7506      *
7507      * 3.2.3 Constraints on XML Representations of Attribute Declarations
7508      */
7509     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7510         return (NULL);
7511     /*
7512     * 3.2.3 : 3.1
7513     * One of ref or name must be present, but not both
7514     */
7515     attr = xmlSchemaGetPropNode(node, "name");
7516     if (attr == NULL) {
7517         xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7518             NULL, node, "name", NULL);
7519         return (NULL);
7520     }
7521     if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7522         xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7523         return (NULL);
7524     }
7525     /*
7526     * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7527     * TODO: Move this to the component layer.
7528     */
7529     if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7530         xmlSchemaPSimpleTypeErr(pctxt,
7531             XML_SCHEMAP_NO_XMLNS,
7532             NULL, (xmlNodePtr) attr,
7533             xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7534             "The value of the attribute must not match 'xmlns'",
7535             NULL, NULL);
7536         return (NULL);
7537     }
7538     /*
7539     * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7540     * TODO: Move this to the component layer.
7541     *       Or better leave it here and add it to the component layer
7542     *       if we have a schema construction API.
7543     */
7544     if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7545         xmlSchemaCustomErr(ACTXT_CAST pctxt,
7546             XML_SCHEMAP_NO_XSI, node, NULL,
7547             "The target namespace must not match '%s'",
7548             xmlSchemaInstanceNs, NULL);
7549     }
7550
7551     ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7552         pctxt->targetNamespace, node, 1);
7553     if (ret == NULL)
7554         return (NULL);
7555     ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7556
7557     /*
7558     * Check for illegal attributes.
7559     */
7560     attr = node->properties;
7561     while (attr != NULL) {
7562         if (attr->ns == NULL) {
7563             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7564                 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7565                 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7566                 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7567                 (!xmlStrEqual(attr->name, BAD_CAST "type")))
7568             {
7569                 xmlSchemaPIllegalAttrErr(pctxt,
7570                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7571             }
7572         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7573             xmlSchemaPIllegalAttrErr(pctxt,
7574                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7575         }
7576         attr = attr->next;
7577     }
7578     xmlSchemaPValAttrQName(pctxt, schema, NULL,
7579         node, "type", &ret->typeNs, &ret->typeName);
7580
7581     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7582     /*
7583     * Attribute "fixed".
7584     */
7585     ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
7586     if (ret->defValue != NULL)
7587         ret->flags |= XML_SCHEMAS_ATTR_FIXED;
7588     /*
7589     * Attribute "default".
7590     */
7591     attr = xmlSchemaGetPropNode(node, "default");
7592     if (attr != NULL) {
7593         /*
7594         * 3.2.3 : 1
7595         * default and fixed must not both be present.
7596         */
7597         if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
7598             xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7599                 WXS_BASIC_CAST ret, attr, "default", "fixed");
7600         } else
7601             ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7602     }
7603     /*
7604     * And now for the children...
7605     */
7606     child = node->children;
7607     if (IS_SCHEMA(child, "annotation")) {
7608         ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7609         child = child->next;
7610     }
7611     if (IS_SCHEMA(child, "simpleType")) {
7612         if (ret->typeName != NULL) {
7613             /*
7614             * 3.2.3 : 4
7615             * type and <simpleType> must not both be present.
7616             */
7617             xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7618                 NULL, node, child,
7619                 "The attribute 'type' and the <simpleType> child "
7620                 "are mutually exclusive", NULL);
7621         } else
7622             ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7623         child = child->next;
7624     }
7625     if (child != NULL)
7626         xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7627             NULL, node, child, NULL,
7628             "(annotation?, simpleType?)");
7629
7630     return (ret);
7631 }
7632
7633 /**
7634  * xmlSchemaParseAttributeGroupRef:
7635  * @ctxt:  a schema validation context
7636  * @schema:  the schema being built
7637  * @node:  a subtree containing XML Schema informations
7638  *
7639  * Parse an attribute group definition reference.
7640  * Note that a reference to an attribute group does not
7641  * correspond to any component at all.
7642  * *WARNING* this interface is highly subject to change
7643  *
7644  * Returns the attribute group or NULL in case of error.
7645  */
7646 static xmlSchemaQNameRefPtr
7647 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7648                                 xmlSchemaPtr schema,
7649                                 xmlNodePtr node)
7650 {
7651     xmlSchemaQNameRefPtr ret;
7652     xmlNodePtr child = NULL;
7653     xmlAttrPtr attr;
7654     const xmlChar *refNs = NULL, *ref = NULL;
7655
7656     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7657         return (NULL);
7658
7659     attr = xmlSchemaGetPropNode(node, "ref");
7660     if (attr == NULL) {
7661         xmlSchemaPMissingAttrErr(pctxt,
7662             XML_SCHEMAP_S4S_ATTR_MISSING,
7663             NULL, node, "ref", NULL);
7664         return (NULL);
7665     }
7666     xmlSchemaPValAttrNodeQName(pctxt, schema,
7667         NULL, attr, &refNs, &ref);
7668     if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7669         return(NULL);
7670
7671     /*
7672     * Check for illegal attributes.
7673     */
7674     attr = node->properties;
7675     while (attr != NULL) {
7676         if (attr->ns == NULL) {
7677             if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
7678                 (!xmlStrEqual(attr->name, BAD_CAST "id")))
7679             {
7680                 xmlSchemaPIllegalAttrErr(pctxt,
7681                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7682             }
7683         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7684             xmlSchemaPIllegalAttrErr(pctxt,
7685                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7686         }
7687         attr = attr->next;
7688     }
7689     /* Attribute ID */
7690     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7691
7692     /*
7693     * And now for the children...
7694     */
7695     child = node->children;
7696     if (IS_SCHEMA(child, "annotation")) {
7697         /*
7698         * TODO: We do not have a place to store the annotation, do we?
7699         */
7700         xmlSchemaParseAnnotation(pctxt, child, 0);
7701         child = child->next;
7702     }
7703     if (child != NULL) {
7704         xmlSchemaPContentErr(pctxt,
7705             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7706             NULL, node, child, NULL,
7707             "(annotation?)");
7708     }
7709
7710     /*
7711     * Handle attribute group redefinitions.
7712     */
7713     if (pctxt->isRedefine && pctxt->redef &&
7714         (pctxt->redef->item->type ==
7715             XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7716         (ref == pctxt->redef->refName) &&
7717         (refNs == pctxt->redef->refTargetNs))
7718     {
7719         /*
7720         * SPEC src-redefine:
7721         * (7.1) "If it has an <attributeGroup> among its contents
7722         * the `actual value` of whose ref [attribute] is the same
7723         * as the `actual value` of its own name attribute plus
7724         * target namespace, then it must have exactly one such group."
7725         */
7726         if (pctxt->redefCounter != 0) {
7727             xmlChar *str = NULL;
7728
7729             xmlSchemaCustomErr(ACTXT_CAST pctxt,
7730                 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7731                 "The redefining attribute group definition "
7732                 "'%s' must not contain more than one "
7733                 "reference to the redefined definition",
7734                 xmlSchemaFormatQName(&str, refNs, ref), NULL);
7735             FREE_AND_NULL(str);
7736             return(NULL);
7737         }
7738         pctxt->redefCounter++;
7739         /*
7740         * URGENT TODO: How to ensure that the reference will not be
7741         * handled by the normal component resolution mechanism?
7742         */
7743         ret = xmlSchemaNewQNameRef(pctxt,
7744             XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7745         if (ret == NULL)
7746             return(NULL);
7747         ret->node = node;
7748         pctxt->redef->reference = WXS_BASIC_CAST ret;
7749     } else {
7750         /*
7751         * Create a QName-reference helper component. We will substitute this
7752         * component for the attribute uses of the referenced attribute group
7753         * definition.
7754         */
7755         ret = xmlSchemaNewQNameRef(pctxt,
7756             XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7757         if (ret == NULL)
7758             return(NULL);
7759         ret->node = node;
7760         /* Add to pending items, to be able to resolve the reference. */
7761         WXS_ADD_PENDING(pctxt, ret);
7762     }
7763     return (ret);
7764 }
7765
7766 /**
7767  * xmlSchemaParseAttributeGroupDefinition:
7768  * @pctxt:  a schema validation context
7769  * @schema:  the schema being built
7770  * @node:  a subtree containing XML Schema informations
7771  *
7772  * parse a XML schema Attribute Group declaration
7773  * *WARNING* this interface is highly subject to change
7774  *
7775  * Returns the attribute group definition or NULL in case of error.
7776  */
7777 static xmlSchemaAttributeGroupPtr
7778 xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7779                                        xmlSchemaPtr schema,
7780                                        xmlNodePtr node)
7781 {
7782     const xmlChar *name;
7783     xmlSchemaAttributeGroupPtr ret;
7784     xmlNodePtr child = NULL;
7785     xmlAttrPtr attr;
7786     int hasRefs = 0;
7787
7788     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7789         return (NULL);
7790
7791     attr = xmlSchemaGetPropNode(node, "name");
7792     if (attr == NULL) {
7793         xmlSchemaPMissingAttrErr(pctxt,
7794             XML_SCHEMAP_S4S_ATTR_MISSING,
7795             NULL, node, "name", NULL);
7796         return (NULL);
7797     }
7798     /*
7799     * The name is crucial, exit if invalid.
7800     */
7801     if (xmlSchemaPValAttrNode(pctxt,
7802         NULL, attr,
7803         xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7804         return (NULL);
7805     }
7806     ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7807         name, pctxt->targetNamespace, node);
7808     if (ret == NULL)
7809         return (NULL);
7810     /*
7811     * Check for illegal attributes.
7812     */
7813     attr = node->properties;
7814     while (attr != NULL) {
7815         if (attr->ns == NULL) {
7816             if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7817                 (!xmlStrEqual(attr->name, BAD_CAST "id")))
7818             {
7819                 xmlSchemaPIllegalAttrErr(pctxt,
7820                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7821             }
7822         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7823             xmlSchemaPIllegalAttrErr(pctxt,
7824                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7825         }
7826         attr = attr->next;
7827     }
7828     /* Attribute ID */
7829     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7830     /*
7831     * And now for the children...
7832     */
7833     child = node->children;
7834     if (IS_SCHEMA(child, "annotation")) {
7835         ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7836         child = child->next;
7837     }
7838     /*
7839     * Parse contained attribute decls/refs.
7840     */
7841     if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7842         (xmlSchemaItemListPtr *) &(ret->attrUses),
7843         XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7844         return(NULL);
7845     if (hasRefs)
7846         ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7847     /*
7848     * Parse the attribute wildcard.
7849     */
7850     if (IS_SCHEMA(child, "anyAttribute")) {
7851         ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7852             schema, child);
7853         child = child->next;
7854     }
7855     if (child != NULL) {
7856         xmlSchemaPContentErr(pctxt,
7857             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7858             NULL, node, child, NULL,
7859             "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
7860     }
7861     return (ret);
7862 }
7863
7864 /**
7865  * xmlSchemaPValAttrFormDefault:
7866  * @value:  the value
7867  * @flags: the flags to be modified
7868  * @flagQualified: the specific flag for "qualified"
7869  *
7870  * Returns 0 if the value is valid, 1 otherwise.
7871  */
7872 static int
7873 xmlSchemaPValAttrFormDefault(const xmlChar *value,
7874                              int *flags,
7875                              int flagQualified)
7876 {
7877     if (xmlStrEqual(value, BAD_CAST "qualified")) {
7878         if  ((*flags & flagQualified) == 0)
7879             *flags |= flagQualified;
7880     } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
7881         return (1);
7882
7883     return (0);
7884 }
7885
7886 /**
7887  * xmlSchemaPValAttrBlockFinal:
7888  * @value:  the value
7889  * @flags: the flags to be modified
7890  * @flagAll: the specific flag for "#all"
7891  * @flagExtension: the specific flag for "extension"
7892  * @flagRestriction: the specific flag for "restriction"
7893  * @flagSubstitution: the specific flag for "substitution"
7894  * @flagList: the specific flag for "list"
7895  * @flagUnion: the specific flag for "union"
7896  *
7897  * Validates the value of the attribute "final" and "block". The value
7898  * is converted into the specified flag values and returned in @flags.
7899  *
7900  * Returns 0 if the value is valid, 1 otherwise.
7901  */
7902
7903 static int
7904 xmlSchemaPValAttrBlockFinal(const xmlChar *value,
7905                             int *flags,
7906                             int flagAll,
7907                             int flagExtension,
7908                             int flagRestriction,
7909                             int flagSubstitution,
7910                             int flagList,
7911                             int flagUnion)
7912 {
7913     int ret = 0;
7914
7915     /*
7916     * TODO: This does not check for dublicate entries.
7917     */
7918     if ((flags == NULL) || (value == NULL))
7919         return (-1);
7920     if (value[0] == 0)
7921         return (0);
7922     if (xmlStrEqual(value, BAD_CAST "#all")) {
7923         if (flagAll != -1)
7924             *flags |= flagAll;
7925         else {
7926             if (flagExtension != -1)
7927                 *flags |= flagExtension;
7928             if (flagRestriction != -1)
7929                 *flags |= flagRestriction;
7930             if (flagSubstitution != -1)
7931                 *flags |= flagSubstitution;
7932             if (flagList != -1)
7933                 *flags |= flagList;
7934             if (flagUnion != -1)
7935                 *flags |= flagUnion;
7936         }
7937     } else {
7938         const xmlChar *end, *cur = value;
7939         xmlChar *item;
7940
7941         do {
7942             while (IS_BLANK_CH(*cur))
7943                 cur++;
7944             end = cur;
7945             while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7946                 end++;
7947             if (end == cur)
7948                 break;
7949             item = xmlStrndup(cur, end - cur);
7950             if (xmlStrEqual(item, BAD_CAST "extension")) {
7951                 if (flagExtension != -1) {
7952                     if ((*flags & flagExtension) == 0)
7953                         *flags |= flagExtension;
7954                 } else
7955                     ret = 1;
7956             } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
7957                 if (flagRestriction != -1) {
7958                     if ((*flags & flagRestriction) == 0)
7959                         *flags |= flagRestriction;
7960                 } else
7961                     ret = 1;
7962             } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
7963                 if (flagSubstitution != -1) {
7964                     if ((*flags & flagSubstitution) == 0)
7965                         *flags |= flagSubstitution;
7966                 } else
7967                     ret = 1;
7968             } else if (xmlStrEqual(item, BAD_CAST "list")) {
7969                 if (flagList != -1) {
7970                     if ((*flags & flagList) == 0)
7971                         *flags |= flagList;
7972                 } else
7973                     ret = 1;
7974             } else if (xmlStrEqual(item, BAD_CAST "union")) {
7975                 if (flagUnion != -1) {
7976                     if ((*flags & flagUnion) == 0)
7977                         *flags |= flagUnion;
7978                 } else
7979                     ret = 1;
7980             } else
7981                 ret = 1;
7982             if (item != NULL)
7983                 xmlFree(item);
7984             cur = end;
7985         } while ((ret == 0) && (*cur != 0));
7986     }
7987
7988     return (ret);
7989 }
7990
7991 static int
7992 xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
7993                              xmlSchemaIDCPtr idc,
7994                              xmlSchemaIDCSelectPtr selector,
7995                              xmlAttrPtr attr,
7996                              int isField)
7997 {
7998     xmlNodePtr node;
7999
8000     /*
8001     * c-selector-xpath:
8002     * Schema Component Constraint: Selector Value OK
8003     *
8004     * TODO: 1 The {selector} must be a valid XPath expression, as defined
8005     * in [XPath].
8006     */
8007     if (selector == NULL) {
8008         xmlSchemaPErr(ctxt, idc->node,
8009             XML_SCHEMAP_INTERNAL,
8010             "Internal error: xmlSchemaCheckCSelectorXPath, "
8011             "the selector is not specified.\n", NULL, NULL);
8012         return (-1);
8013     }
8014     if (attr == NULL)
8015         node = idc->node;
8016     else
8017         node = (xmlNodePtr) attr;
8018     if (selector->xpath == NULL) {
8019         xmlSchemaPCustomErr(ctxt,
8020             /* TODO: Adjust error code. */
8021             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8022             NULL, node,
8023             "The XPath expression of the selector is not valid", NULL);
8024         return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8025     } else {
8026         const xmlChar **nsArray = NULL;
8027         xmlNsPtr *nsList = NULL;
8028         /*
8029         * Compile the XPath expression.
8030         */
8031         /*
8032         * TODO: We need the array of in-scope namespaces for compilation.
8033         * TODO: Call xmlPatterncompile with different options for selector/
8034         * field.
8035         */
8036         if (attr == NULL)
8037             nsList = NULL;
8038         else
8039             nsList = xmlGetNsList(attr->doc, attr->parent);
8040         /*
8041         * Build an array of prefixes and namespaces.
8042         */
8043         if (nsList != NULL) {
8044             int i, count = 0;
8045
8046             for (i = 0; nsList[i] != NULL; i++)
8047                 count++;
8048
8049             nsArray = (const xmlChar **) xmlMalloc(
8050                 (count * 2 + 1) * sizeof(const xmlChar *));
8051             if (nsArray == NULL) {
8052                 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
8053                     NULL);
8054                 xmlFree(nsList);
8055                 return (-1);
8056             }
8057             for (i = 0; i < count; i++) {
8058                 nsArray[2 * i] = nsList[i]->href;
8059                 nsArray[2 * i + 1] = nsList[i]->prefix;
8060             }
8061             nsArray[count * 2] = NULL;
8062             xmlFree(nsList);
8063         }
8064         /*
8065         * TODO: Differentiate between "selector" and "field".
8066         */
8067         if (isField)
8068             selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8069                 NULL, XML_PATTERN_XSFIELD, nsArray);
8070         else
8071             selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8072                 NULL, XML_PATTERN_XSSEL, nsArray);
8073         if (nsArray != NULL)
8074             xmlFree((xmlChar **) nsArray);
8075
8076         if (selector->xpathComp == NULL) {
8077             xmlSchemaPCustomErr(ctxt,
8078                 /* TODO: Adjust error code? */
8079                 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8080                 NULL, node,
8081                 "The XPath expression '%s' could not be "
8082                 "compiled", selector->xpath);
8083             return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8084         }
8085     }
8086     return (0);
8087 }
8088
8089 #define ADD_ANNOTATION(annot)   \
8090     xmlSchemaAnnotPtr cur = item->annot; \
8091     if (item->annot == NULL) {  \
8092         item->annot = annot;    \
8093         return (annot);         \
8094     }                           \
8095     cur = item->annot;          \
8096     if (cur->next != NULL) {    \
8097         cur = cur->next;        \
8098     }                           \
8099     cur->next = annot;
8100
8101 /**
8102  * xmlSchemaAssignAnnotation:
8103  * @item: the schema component
8104  * @annot: the annotation
8105  *
8106  * Adds the annotation to the given schema component.
8107  *
8108  * Returns the given annotaion.
8109  */
8110 static xmlSchemaAnnotPtr
8111 xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8112                        xmlSchemaAnnotPtr annot)
8113 {
8114     if ((annItem == NULL) || (annot == NULL))
8115         return (NULL);
8116     switch (annItem->type) {
8117         case XML_SCHEMA_TYPE_ELEMENT: {
8118                 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8119                 ADD_ANNOTATION(annot)
8120             }
8121             break;
8122         case XML_SCHEMA_TYPE_ATTRIBUTE: {
8123                 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8124                 ADD_ANNOTATION(annot)
8125             }
8126             break;
8127         case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8128         case XML_SCHEMA_TYPE_ANY: {
8129                 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8130                 ADD_ANNOTATION(annot)
8131             }
8132             break;
8133         case XML_SCHEMA_TYPE_PARTICLE:
8134         case XML_SCHEMA_TYPE_IDC_KEY:
8135         case XML_SCHEMA_TYPE_IDC_KEYREF:
8136         case XML_SCHEMA_TYPE_IDC_UNIQUE: {
8137                 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8138                 ADD_ANNOTATION(annot)
8139             }
8140             break;
8141         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8142                 xmlSchemaAttributeGroupPtr item =
8143                     (xmlSchemaAttributeGroupPtr) annItem;
8144                 ADD_ANNOTATION(annot)
8145             }
8146             break;
8147         case XML_SCHEMA_TYPE_NOTATION: {
8148                 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8149                 ADD_ANNOTATION(annot)
8150             }
8151             break;
8152         case XML_SCHEMA_FACET_MININCLUSIVE:
8153         case XML_SCHEMA_FACET_MINEXCLUSIVE:
8154         case XML_SCHEMA_FACET_MAXINCLUSIVE:
8155         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8156         case XML_SCHEMA_FACET_TOTALDIGITS:
8157         case XML_SCHEMA_FACET_FRACTIONDIGITS:
8158         case XML_SCHEMA_FACET_PATTERN:
8159         case XML_SCHEMA_FACET_ENUMERATION:
8160         case XML_SCHEMA_FACET_WHITESPACE:
8161         case XML_SCHEMA_FACET_LENGTH:
8162         case XML_SCHEMA_FACET_MAXLENGTH:
8163         case XML_SCHEMA_FACET_MINLENGTH: {
8164                 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8165                 ADD_ANNOTATION(annot)
8166             }
8167             break;
8168         case XML_SCHEMA_TYPE_SIMPLE:
8169         case XML_SCHEMA_TYPE_COMPLEX: {
8170                 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8171                 ADD_ANNOTATION(annot)
8172             }
8173             break;
8174         case XML_SCHEMA_TYPE_GROUP: {
8175                 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8176                 ADD_ANNOTATION(annot)
8177             }
8178             break;
8179         case XML_SCHEMA_TYPE_SEQUENCE:
8180         case XML_SCHEMA_TYPE_CHOICE:
8181         case XML_SCHEMA_TYPE_ALL: {
8182                 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8183                 ADD_ANNOTATION(annot)
8184             }
8185             break;
8186         default:
8187              xmlSchemaPCustomErr(NULL,
8188                 XML_SCHEMAP_INTERNAL,
8189                 NULL, NULL,
8190                 "Internal error: xmlSchemaAddAnnotation, "
8191                 "The item is not a annotated schema component", NULL);
8192              break;
8193     }
8194     return (annot);
8195 }
8196
8197 /**
8198  * xmlSchemaParseIDCSelectorAndField:
8199  * @ctxt:  a schema validation context
8200  * @schema:  the schema being built
8201  * @node:  a subtree containing XML Schema informations
8202  *
8203  * Parses a XML Schema identity-contraint definition's
8204  * <selector> and <field> elements.
8205  *
8206  * Returns the parsed identity-constraint definition.
8207  */
8208 static xmlSchemaIDCSelectPtr
8209 xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
8210                           xmlSchemaIDCPtr idc,
8211                           xmlNodePtr node,
8212                           int isField)
8213 {
8214     xmlSchemaIDCSelectPtr item;
8215     xmlNodePtr child = NULL;
8216     xmlAttrPtr attr;
8217
8218     /*
8219     * Check for illegal attributes.
8220     */
8221     attr = node->properties;
8222     while (attr != NULL) {
8223         if (attr->ns == NULL) {
8224             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8225                 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
8226                 xmlSchemaPIllegalAttrErr(ctxt,
8227                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8228             }
8229         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8230             xmlSchemaPIllegalAttrErr(ctxt,
8231                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8232         }
8233         attr = attr->next;
8234     }
8235     /*
8236     * Create the item.
8237     */
8238     item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8239     if (item == NULL) {
8240         xmlSchemaPErrMemory(ctxt,
8241             "allocating a 'selector' of an identity-constraint definition",
8242             NULL);
8243         return (NULL);
8244     }
8245     memset(item, 0, sizeof(xmlSchemaIDCSelect));
8246     /*
8247     * Attribute "xpath" (mandatory).
8248     */
8249     attr = xmlSchemaGetPropNode(node, "xpath");
8250     if (attr == NULL) {
8251         xmlSchemaPMissingAttrErr(ctxt,
8252             XML_SCHEMAP_S4S_ATTR_MISSING,
8253             NULL, node,
8254             "name", NULL);
8255     } else {
8256         item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8257         /*
8258         * URGENT TODO: "field"s have an other syntax than "selector"s.
8259         */
8260
8261         if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8262             isField) == -1) {
8263             xmlSchemaPErr(ctxt,
8264                 (xmlNodePtr) attr,
8265                 XML_SCHEMAP_INTERNAL,
8266                 "Internal error: xmlSchemaParseIDCSelectorAndField, "
8267                 "validating the XPath expression of a IDC selector.\n",
8268                 NULL, NULL);
8269         }
8270
8271     }
8272     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8273     /*
8274     * And now for the children...
8275     */
8276     child = node->children;
8277     if (IS_SCHEMA(child, "annotation")) {
8278         /*
8279         * Add the annotation to the parent IDC.
8280         */
8281         xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
8282             xmlSchemaParseAnnotation(ctxt, child, 1));
8283         child = child->next;
8284     }
8285     if (child != NULL) {
8286         xmlSchemaPContentErr(ctxt,
8287             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8288             NULL, node, child,
8289             NULL, "(annotation?)");
8290     }
8291
8292     return (item);
8293 }
8294
8295 /**
8296  * xmlSchemaParseIDC:
8297  * @ctxt:  a schema validation context
8298  * @schema:  the schema being built
8299  * @node:  a subtree containing XML Schema informations
8300  *
8301  * Parses a XML Schema identity-contraint definition.
8302  *
8303  * Returns the parsed identity-constraint definition.
8304  */
8305 static xmlSchemaIDCPtr
8306 xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
8307                   xmlSchemaPtr schema,
8308                   xmlNodePtr node,
8309                   xmlSchemaTypeType idcCategory,
8310                   const xmlChar *targetNamespace)
8311 {
8312     xmlSchemaIDCPtr item = NULL;
8313     xmlNodePtr child = NULL;
8314     xmlAttrPtr attr;
8315     const xmlChar *name = NULL;
8316     xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
8317
8318     /*
8319     * Check for illegal attributes.
8320     */
8321     attr = node->properties;
8322     while (attr != NULL) {
8323         if (attr->ns == NULL) {
8324             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8325                 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8326                 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8327                  (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
8328                 xmlSchemaPIllegalAttrErr(ctxt,
8329                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8330             }
8331         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8332             xmlSchemaPIllegalAttrErr(ctxt,
8333                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8334         }
8335         attr = attr->next;
8336     }
8337     /*
8338     * Attribute "name" (mandatory).
8339     */
8340     attr = xmlSchemaGetPropNode(node, "name");
8341     if (attr == NULL) {
8342         xmlSchemaPMissingAttrErr(ctxt,
8343             XML_SCHEMAP_S4S_ATTR_MISSING,
8344             NULL, node,
8345             "name", NULL);
8346         return (NULL);
8347     } else if (xmlSchemaPValAttrNode(ctxt,
8348         NULL, attr,
8349         xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8350         return (NULL);
8351     }
8352     /* Create the component. */
8353     item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8354         idcCategory, node);
8355     if (item == NULL)
8356         return(NULL);
8357
8358     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8359     if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8360         /*
8361         * Attribute "refer" (mandatory).
8362         */
8363         attr = xmlSchemaGetPropNode(node, "refer");
8364         if (attr == NULL) {
8365             xmlSchemaPMissingAttrErr(ctxt,
8366                 XML_SCHEMAP_S4S_ATTR_MISSING,
8367                 NULL, node,
8368                 "refer", NULL);
8369         } else {
8370             /*
8371             * Create a reference item.
8372             */
8373             item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
8374                 NULL, NULL);
8375             if (item->ref == NULL)
8376                 return (NULL);
8377             xmlSchemaPValAttrNodeQName(ctxt, schema,
8378                 NULL, attr,
8379                 &(item->ref->targetNamespace),
8380                 &(item->ref->name));
8381             xmlSchemaCheckReference(ctxt, schema, node, attr,
8382                 item->ref->targetNamespace);
8383         }
8384     }
8385     /*
8386     * And now for the children...
8387     */
8388     child = node->children;
8389     if (IS_SCHEMA(child, "annotation")) {
8390         item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8391         child = child->next;
8392     }
8393     if (child == NULL) {
8394         xmlSchemaPContentErr(ctxt,
8395                 XML_SCHEMAP_S4S_ELEM_MISSING,
8396                 NULL, node, child,
8397                 "A child element is missing",
8398                 "(annotation?, (selector, field+))");
8399     }
8400     /*
8401     * Child element <selector>.
8402     */
8403     if (IS_SCHEMA(child, "selector")) {
8404         item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
8405             item, child, 0);
8406         child = child->next;
8407         /*
8408         * Child elements <field>.
8409         */
8410         if (IS_SCHEMA(child, "field")) {
8411             do {
8412                 field = xmlSchemaParseIDCSelectorAndField(ctxt,
8413                     item, child, 1);
8414                 if (field != NULL) {
8415                     field->index = item->nbFields;
8416                     item->nbFields++;
8417                     if (lastField != NULL)
8418                         lastField->next = field;
8419                     else
8420                         item->fields = field;
8421                     lastField = field;
8422                 }
8423                 child = child->next;
8424             } while (IS_SCHEMA(child, "field"));
8425         } else {
8426             xmlSchemaPContentErr(ctxt,
8427                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8428                 NULL, node, child,
8429                 NULL, "(annotation?, (selector, field+))");
8430         }
8431     }
8432     if (child != NULL) {
8433         xmlSchemaPContentErr(ctxt,
8434             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8435             NULL, node, child,
8436             NULL, "(annotation?, (selector, field+))");
8437     }
8438
8439     return (item);
8440 }
8441
8442 /**
8443  * xmlSchemaParseElement:
8444  * @ctxt:  a schema validation context
8445  * @schema:  the schema being built
8446  * @node:  a subtree containing XML Schema informations
8447  * @topLevel: indicates if this is global declaration
8448  *
8449  * Parses a XML schema element declaration.
8450  * *WARNING* this interface is highly subject to change
8451  *
8452  * Returns the element declaration or a particle; NULL in case
8453  * of an error or if the particle has minOccurs==maxOccurs==0.
8454  */
8455 static xmlSchemaBasicItemPtr
8456 xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8457                       xmlNodePtr node, int *isElemRef, int topLevel)
8458 {
8459     xmlSchemaElementPtr decl = NULL;
8460     xmlSchemaParticlePtr particle = NULL;
8461     xmlSchemaAnnotPtr annot = NULL;
8462     xmlNodePtr child = NULL;
8463     xmlAttrPtr attr, nameAttr;
8464     int min, max, isRef = 0;
8465     xmlChar *des = NULL;
8466
8467     /* 3.3.3 Constraints on XML Representations of Element Declarations */
8468     /* TODO: Complete implementation of 3.3.6 */
8469
8470     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8471         return (NULL);
8472
8473     if (isElemRef != NULL)
8474         *isElemRef = 0;
8475     /*
8476     * If we get a "ref" attribute on a local <element> we will assume it's
8477     * a reference - even if there's a "name" attribute; this seems to be more
8478     * robust.
8479     */
8480     nameAttr = xmlSchemaGetPropNode(node, "name");
8481     attr = xmlSchemaGetPropNode(node, "ref");
8482     if ((topLevel) || (attr == NULL)) {
8483         if (nameAttr == NULL) {
8484             xmlSchemaPMissingAttrErr(ctxt,
8485                 XML_SCHEMAP_S4S_ATTR_MISSING,
8486                 NULL, node, "name", NULL);
8487             return (NULL);
8488         }
8489     } else
8490         isRef = 1;
8491
8492     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8493     child = node->children;
8494     if (IS_SCHEMA(child, "annotation")) {
8495         annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8496         child = child->next;
8497     }
8498     /*
8499     * Skip particle part if a global declaration.
8500     */
8501     if (topLevel)
8502         goto declaration_part;
8503     /*
8504     * The particle part ==================================================
8505     */
8506     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8507     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8508     xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
8509     particle = xmlSchemaAddParticle(ctxt, node, min, max);
8510     if (particle == NULL)
8511         goto return_null;
8512
8513     /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8514
8515     if (isRef) {
8516         const xmlChar *refNs = NULL, *ref = NULL;
8517         xmlSchemaQNameRefPtr refer = NULL;
8518         /*
8519         * The reference part =============================================
8520         */
8521         if (isElemRef != NULL)
8522             *isElemRef = 1;
8523
8524         xmlSchemaPValAttrNodeQName(ctxt, schema,
8525             NULL, attr, &refNs, &ref);
8526         xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
8527         /*
8528         * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
8529         */
8530         if (nameAttr != NULL) {
8531             xmlSchemaPMutualExclAttrErr(ctxt,
8532                 XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
8533         }
8534         /*
8535         * Check for illegal attributes.
8536         */
8537         attr = node->properties;
8538         while (attr != NULL) {
8539             if (attr->ns == NULL) {
8540                 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8541                     xmlStrEqual(attr->name, BAD_CAST "name") ||
8542                     xmlStrEqual(attr->name, BAD_CAST "id") ||
8543                     xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8544                     xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8545                 {
8546                     attr = attr->next;
8547                     continue;
8548                 } else {
8549                     /* SPEC (3.3.3 : 2.2) */
8550                     xmlSchemaPCustomAttrErr(ctxt,
8551                         XML_SCHEMAP_SRC_ELEMENT_2_2,
8552                         NULL, NULL, attr,
8553                         "Only the attributes 'minOccurs', 'maxOccurs' and "
8554                         "'id' are allowed in addition to 'ref'");
8555                     break;
8556                 }
8557             } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8558                 xmlSchemaPIllegalAttrErr(ctxt,
8559                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8560             }
8561             attr = attr->next;
8562         }
8563         /*
8564         * No children except <annotation> expected.
8565         */
8566         if (child != NULL) {
8567             xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8568                 NULL, node, child, NULL, "(annotation?)");
8569         }
8570         if ((min == 0) && (max == 0))
8571             goto return_null;
8572         /*
8573         * Create the reference item and attach it to the particle.
8574         */
8575         refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
8576             ref, refNs);
8577         if (refer == NULL)
8578             goto return_null;
8579         particle->children = (xmlSchemaTreeItemPtr) refer;
8580         particle->annot = annot;
8581         /*
8582         * Add the particle to pending components, since the reference
8583         * need to be resolved.
8584         */
8585         WXS_ADD_PENDING(ctxt, particle);
8586         return ((xmlSchemaBasicItemPtr) particle);
8587     }
8588     /*
8589     * The declaration part ===============================================
8590     */
8591 declaration_part:
8592     {
8593         const xmlChar *ns = NULL, *fixed, *name, *attrValue;
8594         xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8595
8596         if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
8597             xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
8598             goto return_null;
8599         /*
8600         * Evaluate the target namespace.
8601         */
8602         if (topLevel) {
8603             ns = ctxt->targetNamespace;
8604         } else {
8605             attr = xmlSchemaGetPropNode(node, "form");
8606             if (attr != NULL) {
8607                 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8608                 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
8609                     ns = ctxt->targetNamespace;
8610                 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
8611                     xmlSchemaPSimpleTypeErr(ctxt,
8612                         XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8613                         NULL, (xmlNodePtr) attr,
8614                         NULL, "(qualified | unqualified)",
8615                         attrValue, NULL, NULL, NULL);
8616                 }
8617             } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8618                 ns = ctxt->targetNamespace;
8619         }
8620         decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
8621         if (decl == NULL) {
8622             goto return_null;
8623         }
8624         /*
8625         * Check for illegal attributes.
8626         */
8627         attr = node->properties;
8628         while (attr != NULL) {
8629             if (attr->ns == NULL) {
8630                 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8631                     (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
8632                     (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8633                     (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
8634                     (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
8635                     (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
8636                     (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8637                 {
8638                     if (topLevel == 0) {
8639                         if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8640                             (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8641                             (!xmlStrEqual(attr->name, BAD_CAST "form")))
8642                         {
8643                             xmlSchemaPIllegalAttrErr(ctxt,
8644                                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8645                         }
8646                     } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8647                         (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
8648                         (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8649
8650                         xmlSchemaPIllegalAttrErr(ctxt,
8651                             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8652                     }
8653                 }
8654             } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8655
8656                 xmlSchemaPIllegalAttrErr(ctxt,
8657                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8658             }
8659             attr = attr->next;
8660         }
8661         /*
8662         * Extract/validate attributes.
8663         */
8664         if (topLevel) {
8665             /*
8666             * Process top attributes of global element declarations here.
8667             */
8668             decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8669             decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
8670             xmlSchemaPValAttrQName(ctxt, schema,
8671                 NULL, node, "substitutionGroup",
8672                 &(decl->substGroupNs), &(decl->substGroup));
8673             if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
8674                 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
8675             /*
8676             * Attribute "final".
8677             */
8678             attr = xmlSchemaGetPropNode(node, "final");
8679             if (attr == NULL) {
8680                 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8681                     decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8682                 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8683                     decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
8684             } else {
8685                 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8686                 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8687                     -1,
8688                     XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8689                     XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
8690                     xmlSchemaPSimpleTypeErr(ctxt,
8691                         XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8692                         NULL, (xmlNodePtr) attr,
8693                         NULL, "(#all | List of (extension | restriction))",
8694                         attrValue, NULL, NULL, NULL);
8695                 }
8696             }
8697         }
8698         /*
8699         * Attribute "block".
8700         */
8701         attr = xmlSchemaGetPropNode(node, "block");
8702         if (attr == NULL) {
8703             /*
8704             * Apply default "block" values.
8705             */
8706             if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8707                 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8708             if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8709                 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8710             if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8711                 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
8712         } else {
8713             attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8714             if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8715                 -1,
8716                 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
8717                 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
8718                 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8719                 xmlSchemaPSimpleTypeErr(ctxt,
8720                     XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8721                     NULL, (xmlNodePtr) attr,
8722                     NULL, "(#all | List of (extension | "
8723                     "restriction | substitution))", attrValue,
8724                     NULL, NULL, NULL);
8725             }
8726         }
8727         if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
8728             decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
8729
8730         attr = xmlSchemaGetPropNode(node, "type");
8731         if (attr != NULL) {
8732             xmlSchemaPValAttrNodeQName(ctxt, schema,
8733                 NULL, attr,
8734                 &(decl->namedTypeNs), &(decl->namedType));
8735             xmlSchemaCheckReference(ctxt, schema, node,
8736                 attr, decl->namedTypeNs);
8737         }
8738         decl->value = xmlSchemaGetProp(ctxt, node, "default");
8739         attr = xmlSchemaGetPropNode(node, "fixed");
8740         if (attr != NULL) {
8741             fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8742             if (decl->value != NULL) {
8743                 /*
8744                 * 3.3.3 : 1
8745                 * default and fixed must not both be present.
8746                 */
8747                 xmlSchemaPMutualExclAttrErr(ctxt,
8748                     XML_SCHEMAP_SRC_ELEMENT_1,
8749                     NULL, attr, "default", "fixed");
8750             } else {
8751                 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8752                 decl->value = fixed;
8753             }
8754         }
8755         /*
8756         * And now for the children...
8757         */
8758         if (IS_SCHEMA(child, "complexType")) {
8759             /*
8760             * 3.3.3 : 3
8761             * "type" and either <simpleType> or <complexType> are mutually
8762             * exclusive
8763             */
8764             if (decl->namedType != NULL) {
8765                 xmlSchemaPContentErr(ctxt,
8766                     XML_SCHEMAP_SRC_ELEMENT_3,
8767                     NULL, node, child,
8768                     "The attribute 'type' and the <complexType> child are "
8769                     "mutually exclusive", NULL);
8770             } else
8771                 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
8772             child = child->next;
8773         } else if (IS_SCHEMA(child, "simpleType")) {
8774             /*
8775             * 3.3.3 : 3
8776             * "type" and either <simpleType> or <complexType> are
8777             * mutually exclusive
8778             */
8779             if (decl->namedType != NULL) {
8780                 xmlSchemaPContentErr(ctxt,
8781                     XML_SCHEMAP_SRC_ELEMENT_3,
8782                     NULL, node, child,
8783                     "The attribute 'type' and the <simpleType> child are "
8784                     "mutually exclusive", NULL);
8785             } else
8786                 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8787             child = child->next;
8788         }
8789         while ((IS_SCHEMA(child, "unique")) ||
8790             (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
8791             if (IS_SCHEMA(child, "unique")) {
8792                 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8793                     XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
8794             } else if (IS_SCHEMA(child, "key")) {
8795                 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8796                     XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
8797             } else if (IS_SCHEMA(child, "keyref")) {
8798                 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8799                     XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
8800             }
8801             if (lastIDC != NULL)
8802                 lastIDC->next = curIDC;
8803             else
8804                 decl->idcs = (void *) curIDC;
8805             lastIDC = curIDC;
8806             child = child->next;
8807         }
8808         if (child != NULL) {
8809             xmlSchemaPContentErr(ctxt,
8810                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8811                 NULL, node, child,
8812                 NULL, "(annotation?, ((simpleType | complexType)?, "
8813                 "(unique | key | keyref)*))");
8814         }
8815         decl->annot = annot;
8816     }
8817     /*
8818     * NOTE: Element Declaration Representation OK 4. will be checked at a
8819     * different layer.
8820     */
8821     FREE_AND_NULL(des)
8822     if (topLevel)
8823         return ((xmlSchemaBasicItemPtr) decl);
8824     else {
8825         particle->children = (xmlSchemaTreeItemPtr) decl;
8826         return ((xmlSchemaBasicItemPtr) particle);
8827     }
8828
8829 return_null:
8830     FREE_AND_NULL(des);
8831     if (annot != NULL) {
8832         if (particle != NULL)
8833             particle->annot = NULL;
8834         if (decl != NULL)
8835             decl->annot = NULL;
8836         xmlSchemaFreeAnnot(annot);
8837     }
8838     return (NULL);
8839 }
8840
8841 /**
8842  * xmlSchemaParseUnion:
8843  * @ctxt:  a schema validation context
8844  * @schema:  the schema being built
8845  * @node:  a subtree containing XML Schema informations
8846  *
8847  * parse a XML schema Union definition
8848  * *WARNING* this interface is highly subject to change
8849  *
8850  * Returns -1 in case of internal error, 0 in case of success and a positive
8851  * error code otherwise.
8852  */
8853 static int
8854 xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8855                     xmlNodePtr node)
8856 {
8857     xmlSchemaTypePtr type;
8858     xmlNodePtr child = NULL;
8859     xmlAttrPtr attr;
8860     const xmlChar *cur = NULL;
8861
8862     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8863         return (-1);
8864     /* Not a component, don't create it. */
8865     type = ctxt->ctxtType;
8866     /*
8867     * Mark the simple type as being of variety "union".
8868     */
8869     type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
8870     /*
8871     * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8872     * then the `simple ur-type definition`."
8873     */
8874     type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8875     /*
8876     * Check for illegal attributes.
8877     */
8878     attr = node->properties;
8879     while (attr != NULL) {
8880         if (attr->ns == NULL) {
8881             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8882                 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
8883                 xmlSchemaPIllegalAttrErr(ctxt,
8884                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8885             }
8886         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8887             xmlSchemaPIllegalAttrErr(ctxt,
8888                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8889         }
8890         attr = attr->next;
8891     }
8892     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8893     /*
8894     * Attribute "memberTypes". This is a list of QNames.
8895     * TODO: Check the value to contain anything.
8896     */
8897     attr = xmlSchemaGetPropNode(node, "memberTypes");
8898     if (attr != NULL) {
8899         const xmlChar *end;
8900         xmlChar *tmp;
8901         const xmlChar *localName, *nsName;
8902         xmlSchemaTypeLinkPtr link, lastLink = NULL;
8903         xmlSchemaQNameRefPtr ref;
8904
8905         cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8906         type->base = cur;
8907         do {
8908             while (IS_BLANK_CH(*cur))
8909                 cur++;
8910             end = cur;
8911             while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8912                 end++;
8913             if (end == cur)
8914                 break;
8915             tmp = xmlStrndup(cur, end - cur);
8916             if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
8917                 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
8918                 /*
8919                 * Create the member type link.
8920                 */
8921                 link = (xmlSchemaTypeLinkPtr)
8922                     xmlMalloc(sizeof(xmlSchemaTypeLink));
8923                 if (link == NULL) {
8924                     xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8925                         "allocating a type link", NULL);
8926                     return (-1);
8927                 }
8928                 link->type = NULL;
8929                 link->next = NULL;
8930                 if (lastLink == NULL)
8931                     type->memberTypes = link;
8932                 else
8933                     lastLink->next = link;
8934                 lastLink = link;
8935                 /*
8936                 * Create a reference item.
8937                 */
8938                 ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
8939                     localName, nsName);
8940                 if (ref == NULL) {
8941                     FREE_AND_NULL(tmp)
8942                     return (-1);
8943                 }
8944                 /*
8945                 * Assign the reference to the link, it will be resolved
8946                 * later during fixup of the union simple type.
8947                 */
8948                 link->type = (xmlSchemaTypePtr) ref;
8949             }
8950             FREE_AND_NULL(tmp)
8951             cur = end;
8952         } while (*cur != 0);
8953
8954     }
8955     /*
8956     * And now for the children...
8957     */
8958     child = node->children;
8959     if (IS_SCHEMA(child, "annotation")) {
8960         /*
8961         * Add the annotation to the simple type ancestor.
8962         */
8963         xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8964             xmlSchemaParseAnnotation(ctxt, child, 1));
8965         child = child->next;
8966     }
8967     if (IS_SCHEMA(child, "simpleType")) {
8968         xmlSchemaTypePtr subtype, last = NULL;
8969
8970         /*
8971         * Anchor the member types in the "subtypes" field of the
8972         * simple type.
8973         */
8974         while (IS_SCHEMA(child, "simpleType")) {
8975             subtype = (xmlSchemaTypePtr)
8976                 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8977             if (subtype != NULL) {
8978                 if (last == NULL) {
8979                     type->subtypes = subtype;
8980                     last = subtype;
8981                 } else {
8982                     last->next = subtype;
8983                     last = subtype;
8984                 }
8985                 last->next = NULL;
8986             }
8987             child = child->next;
8988         }
8989     }
8990     if (child != NULL) {
8991         xmlSchemaPContentErr(ctxt,
8992             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8993             NULL, node, child, NULL, "(annotation?, simpleType*)");
8994     }
8995     if ((attr == NULL) && (type->subtypes == NULL)) {
8996          /*
8997         * src-union-memberTypes-or-simpleTypes
8998         * Either the memberTypes [attribute] of the <union> element must
8999         * be non-empty or there must be at least one simpleType [child].
9000         */
9001         xmlSchemaPCustomErr(ctxt,
9002             XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
9003             NULL, node,
9004             "Either the attribute 'memberTypes' or "
9005             "at least one <simpleType> child must be present", NULL);
9006     }
9007     return (0);
9008 }
9009
9010 /**
9011  * xmlSchemaParseList:
9012  * @ctxt:  a schema validation context
9013  * @schema:  the schema being built
9014  * @node:  a subtree containing XML Schema informations
9015  *
9016  * parse a XML schema List definition
9017  * *WARNING* this interface is highly subject to change
9018  *
9019  * Returns -1 in case of error, 0 if the declaration is improper and
9020  *         1 in case of success.
9021  */
9022 static xmlSchemaTypePtr
9023 xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9024                    xmlNodePtr node)
9025 {
9026     xmlSchemaTypePtr type;
9027     xmlNodePtr child = NULL;
9028     xmlAttrPtr attr;
9029
9030     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9031         return (NULL);
9032     /* Not a component, don't create it. */
9033     type = ctxt->ctxtType;
9034     /*
9035     * Mark the type as being of variety "list".
9036     */
9037     type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
9038     /*
9039     * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
9040     * then the `simple ur-type definition`."
9041     */
9042     type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
9043     /*
9044     * Check for illegal attributes.
9045     */
9046     attr = node->properties;
9047     while (attr != NULL) {
9048         if (attr->ns == NULL) {
9049             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9050                 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
9051                 xmlSchemaPIllegalAttrErr(ctxt,
9052                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9053             }
9054         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9055             xmlSchemaPIllegalAttrErr(ctxt,
9056                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9057         }
9058         attr = attr->next;
9059     }
9060
9061     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9062
9063     /*
9064     * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9065     * fields for holding the reference to the itemType.
9066     *
9067     * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9068     * the "ref" fields.
9069     */
9070     xmlSchemaPValAttrQName(ctxt, schema, NULL,
9071         node, "itemType", &(type->baseNs), &(type->base));
9072     /*
9073     * And now for the children...
9074     */
9075     child = node->children;
9076     if (IS_SCHEMA(child, "annotation")) {
9077         xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9078             xmlSchemaParseAnnotation(ctxt, child, 1));
9079         child = child->next;
9080     }
9081     if (IS_SCHEMA(child, "simpleType")) {
9082         /*
9083         * src-list-itemType-or-simpleType
9084         * Either the itemType [attribute] or the <simpleType> [child] of
9085         * the <list> element must be present, but not both.
9086         */
9087         if (type->base != NULL) {
9088             xmlSchemaPCustomErr(ctxt,
9089                 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9090                 NULL, node,
9091                 "The attribute 'itemType' and the <simpleType> child "
9092                 "are mutually exclusive", NULL);
9093         } else {
9094             type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9095         }
9096         child = child->next;
9097     } else if (type->base == NULL) {
9098         xmlSchemaPCustomErr(ctxt,
9099             XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9100             NULL, node,
9101             "Either the attribute 'itemType' or the <simpleType> child "
9102             "must be present", NULL);
9103     }
9104     if (child != NULL) {
9105         xmlSchemaPContentErr(ctxt,
9106             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9107             NULL, node, child, NULL, "(annotation?, simpleType?)");
9108     }
9109     if ((type->base == NULL) &&
9110         (type->subtypes == NULL) &&
9111         (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
9112         xmlSchemaPCustomErr(ctxt,
9113             XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9114             NULL, node,
9115             "Either the attribute 'itemType' or the <simpleType> child "
9116             "must be present", NULL);
9117     }
9118     return (NULL);
9119 }
9120
9121 /**
9122  * xmlSchemaParseSimpleType:
9123  * @ctxt:  a schema validation context
9124  * @schema:  the schema being built
9125  * @node:  a subtree containing XML Schema informations
9126  *
9127  * parse a XML schema Simple Type definition
9128  * *WARNING* this interface is highly subject to change
9129  *
9130  * Returns -1 in case of error, 0 if the declaration is improper and
9131  * 1 in case of success.
9132  */
9133 static xmlSchemaTypePtr
9134 xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9135                          xmlNodePtr node, int topLevel)
9136 {
9137     xmlSchemaTypePtr type, oldCtxtType;
9138     xmlNodePtr child = NULL;
9139     const xmlChar *attrValue = NULL;
9140     xmlAttrPtr attr;
9141     int hasRestriction = 0;
9142
9143     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9144         return (NULL);
9145
9146     if (topLevel) {
9147         attr = xmlSchemaGetPropNode(node, "name");
9148         if (attr == NULL) {
9149             xmlSchemaPMissingAttrErr(ctxt,
9150                 XML_SCHEMAP_S4S_ATTR_MISSING,
9151                 NULL, node,
9152                 "name", NULL);
9153             return (NULL);
9154         } else {
9155             if (xmlSchemaPValAttrNode(ctxt,
9156                 NULL, attr,
9157                 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9158                 return (NULL);
9159             /*
9160             * Skip built-in types.
9161             */
9162             if (ctxt->isS4S) {
9163                 xmlSchemaTypePtr biType;
9164
9165                 if (ctxt->isRedefine) {
9166                     /*
9167                     * REDEFINE: Disallow redefinition of built-in-types.
9168                     * TODO: It seems that the spec does not say anything
9169                     * about this case.
9170                     */
9171                     xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9172                         NULL, node,
9173                         "Redefinition of built-in simple types is not "
9174                         "supported", NULL);
9175                     return(NULL);
9176                 }
9177                 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9178                 if (biType != NULL)
9179                     return (biType);
9180             }
9181         }
9182     }
9183     /*
9184     * TargetNamespace:
9185     * SPEC "The `actual value` of the targetNamespace [attribute]
9186     * of the <schema> ancestor element information item if present,
9187     * otherwise `absent`.
9188     */
9189     if (topLevel == 0) {
9190 #ifdef ENABLE_NAMED_LOCALS
9191         char buf[40];
9192 #endif
9193         /*
9194         * Parse as local simple type definition.
9195         */
9196 #ifdef ENABLE_NAMED_LOCALS
9197         snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
9198         type = xmlSchemaAddType(ctxt, schema,
9199             XML_SCHEMA_TYPE_SIMPLE,
9200             xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
9201             ctxt->targetNamespace, node, 0);
9202 #else
9203         type = xmlSchemaAddType(ctxt, schema,
9204             XML_SCHEMA_TYPE_SIMPLE,
9205             NULL, ctxt->targetNamespace, node, 0);
9206 #endif
9207         if (type == NULL)
9208             return (NULL);
9209         type->type = XML_SCHEMA_TYPE_SIMPLE;
9210         type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9211         /*
9212         * Check for illegal attributes.
9213         */
9214         attr = node->properties;
9215         while (attr != NULL) {
9216             if (attr->ns == NULL) {
9217                 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
9218                     xmlSchemaPIllegalAttrErr(ctxt,
9219                         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9220                 }
9221             } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9222                     xmlSchemaPIllegalAttrErr(ctxt,
9223                         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9224             }
9225             attr = attr->next;
9226         }
9227     } else {
9228         /*
9229         * Parse as global simple type definition.
9230         *
9231         * Note that attrValue is the value of the attribute "name" here.
9232         */
9233         type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9234             attrValue, ctxt->targetNamespace, node, 1);
9235         if (type == NULL)
9236             return (NULL);
9237         type->type = XML_SCHEMA_TYPE_SIMPLE;
9238         type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9239         type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9240         /*
9241         * Check for illegal attributes.
9242         */
9243         attr = node->properties;
9244         while (attr != NULL) {
9245             if (attr->ns == NULL) {
9246                 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9247                     (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9248                     (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
9249                     xmlSchemaPIllegalAttrErr(ctxt,
9250                         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9251                 }
9252             } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9253                 xmlSchemaPIllegalAttrErr(ctxt,
9254                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9255             }
9256             attr = attr->next;
9257         }
9258         /*
9259         * Attribute "final".
9260         */
9261         attr = xmlSchemaGetPropNode(node, "final");
9262         if (attr == NULL) {
9263             if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9264                 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9265             if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9266                 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9267             if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9268                 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
9269         } else {
9270             attrValue = xmlSchemaGetProp(ctxt, node, "final");
9271             if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9272                 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
9273                 XML_SCHEMAS_TYPE_FINAL_LIST,
9274                 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9275
9276                 xmlSchemaPSimpleTypeErr(ctxt,
9277                     XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9278                     WXS_BASIC_CAST type, (xmlNodePtr) attr,
9279                     NULL, "(#all | List of (list | union | restriction)",
9280                     attrValue, NULL, NULL, NULL);
9281             }
9282         }
9283     }
9284     type->targetNamespace = ctxt->targetNamespace;
9285     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9286     /*
9287     * And now for the children...
9288     */
9289     oldCtxtType = ctxt->ctxtType;
9290
9291     ctxt->ctxtType = type;
9292
9293     child = node->children;
9294     if (IS_SCHEMA(child, "annotation")) {
9295         type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9296         child = child->next;
9297     }
9298     if (child == NULL) {
9299         xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
9300             NULL, node, child, NULL,
9301             "(annotation?, (restriction | list | union))");
9302     } else if (IS_SCHEMA(child, "restriction")) {
9303         xmlSchemaParseRestriction(ctxt, schema, child,
9304             XML_SCHEMA_TYPE_SIMPLE);
9305         hasRestriction = 1;
9306         child = child->next;
9307     } else if (IS_SCHEMA(child, "list")) {
9308         xmlSchemaParseList(ctxt, schema, child);
9309         child = child->next;
9310     } else if (IS_SCHEMA(child, "union")) {
9311         xmlSchemaParseUnion(ctxt, schema, child);
9312         child = child->next;
9313     }
9314     if (child != NULL) {
9315         xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9316             NULL, node, child, NULL,
9317             "(annotation?, (restriction | list | union))");
9318     }
9319     /*
9320     * REDEFINE: SPEC src-redefine (5)
9321     * "Within the [children], each <simpleType> must have a
9322     * <restriction> among its [children] ... the `actual value` of whose
9323     * base [attribute] must be the same as the `actual value` of its own
9324     * name attribute plus target namespace;"
9325     */
9326     if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9327         xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9328             NULL, node, "This is a redefinition, thus the "
9329             "<simpleType> must have a <restriction> child", NULL);
9330     }
9331
9332     ctxt->ctxtType = oldCtxtType;
9333     return (type);
9334 }
9335
9336 /**
9337  * xmlSchemaParseModelGroupDefRef:
9338  * @ctxt:  the parser context
9339  * @schema: the schema being built
9340  * @node:  the node
9341  *
9342  * Parses a reference to a model group definition.
9343  *
9344  * We will return a particle component with a qname-component or
9345  * NULL in case of an error.
9346  */
9347 static xmlSchemaTreeItemPtr
9348 xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9349                                xmlSchemaPtr schema,
9350                                xmlNodePtr node)
9351 {
9352     xmlSchemaParticlePtr item;
9353     xmlNodePtr child = NULL;
9354     xmlAttrPtr attr;
9355     const xmlChar *ref = NULL, *refNs = NULL;
9356     int min, max;
9357
9358     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9359         return (NULL);
9360
9361     attr = xmlSchemaGetPropNode(node, "ref");
9362     if (attr == NULL) {
9363         xmlSchemaPMissingAttrErr(ctxt,
9364             XML_SCHEMAP_S4S_ATTR_MISSING,
9365             NULL, node, "ref", NULL);
9366         return (NULL);
9367     } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
9368         attr, &refNs, &ref) != 0) {
9369         return (NULL);
9370     }
9371     xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
9372     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9373     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9374         "(xs:nonNegativeInteger | unbounded)");
9375     /*
9376     * Check for illegal attributes.
9377     */
9378     attr = node->properties;
9379     while (attr != NULL) {
9380         if (attr->ns == NULL) {
9381             if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
9382                 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9383                 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9384                 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
9385                 xmlSchemaPIllegalAttrErr(ctxt,
9386                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9387             }
9388         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9389             xmlSchemaPIllegalAttrErr(ctxt,
9390                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9391         }
9392         attr = attr->next;
9393     }
9394     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9395     item = xmlSchemaAddParticle(ctxt, node, min, max);
9396     if (item == NULL)
9397         return (NULL);
9398     /*
9399     * Create a qname-reference and set as the term; it will be substituted
9400     * for the model group after the reference has been resolved.
9401     */
9402     item->children = (xmlSchemaTreeItemPtr)
9403         xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
9404     xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9405     /*
9406     * And now for the children...
9407     */
9408     child = node->children;
9409     /* TODO: Is annotation even allowed for a model group reference? */
9410     if (IS_SCHEMA(child, "annotation")) {
9411         /*
9412         * TODO: What to do exactly with the annotation?
9413         */
9414         item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9415         child = child->next;
9416     }
9417     if (child != NULL) {
9418         xmlSchemaPContentErr(ctxt,
9419             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9420             NULL, node, child, NULL,
9421             "(annotation?)");
9422     }
9423     /*
9424     * Corresponds to no component at all if minOccurs==maxOccurs==0.
9425     */
9426     if ((min == 0) && (max == 0))
9427         return (NULL);
9428
9429     return ((xmlSchemaTreeItemPtr) item);
9430 }
9431
9432 /**
9433  * xmlSchemaParseModelGroupDefinition:
9434  * @ctxt:  a schema validation context
9435  * @schema:  the schema being built
9436  * @node:  a subtree containing XML Schema informations
9437  *
9438  * Parses a XML schema model group definition.
9439  *
9440  * Note that the contraint src-redefine (6.2) can't be applied until
9441  * references have been resolved. So we will do this at the
9442  * component fixup level.
9443  *
9444  * *WARNING* this interface is highly subject to change
9445  *
9446  * Returns -1 in case of error, 0 if the declaration is improper and
9447  *         1 in case of success.
9448  */
9449 static xmlSchemaModelGroupDefPtr
9450 xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9451                                    xmlSchemaPtr schema,
9452                                    xmlNodePtr node)
9453 {
9454     xmlSchemaModelGroupDefPtr item;
9455     xmlNodePtr child = NULL;
9456     xmlAttrPtr attr;
9457     const xmlChar *name;
9458
9459     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9460         return (NULL);
9461
9462     attr = xmlSchemaGetPropNode(node, "name");
9463     if (attr == NULL) {
9464         xmlSchemaPMissingAttrErr(ctxt,
9465             XML_SCHEMAP_S4S_ATTR_MISSING,
9466             NULL, node,
9467             "name", NULL);
9468         return (NULL);
9469     } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
9470         xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9471         return (NULL);
9472     }
9473     item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9474         ctxt->targetNamespace, node);
9475     if (item == NULL)
9476         return (NULL);
9477     /*
9478     * Check for illegal attributes.
9479     */
9480     attr = node->properties;
9481     while (attr != NULL) {
9482         if (attr->ns == NULL) {
9483             if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9484                 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
9485                 xmlSchemaPIllegalAttrErr(ctxt,
9486                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9487             }
9488         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9489             xmlSchemaPIllegalAttrErr(ctxt,
9490                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9491         }
9492         attr = attr->next;
9493     }
9494     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9495     /*
9496     * And now for the children...
9497     */
9498     child = node->children;
9499     if (IS_SCHEMA(child, "annotation")) {
9500         item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9501         child = child->next;
9502     }
9503     if (IS_SCHEMA(child, "all")) {
9504         item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9505             XML_SCHEMA_TYPE_ALL, 0);
9506         child = child->next;
9507     } else if (IS_SCHEMA(child, "choice")) {
9508         item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9509             XML_SCHEMA_TYPE_CHOICE, 0);
9510         child = child->next;
9511     } else if (IS_SCHEMA(child, "sequence")) {
9512         item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9513             XML_SCHEMA_TYPE_SEQUENCE, 0);
9514         child = child->next;
9515     }
9516
9517
9518
9519     if (child != NULL) {
9520         xmlSchemaPContentErr(ctxt,
9521             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9522             NULL, node, child, NULL,
9523             "(annotation?, (all | choice | sequence)?)");
9524     }
9525     return (item);
9526 }
9527
9528 /**
9529  * xmlSchemaCleanupDoc:
9530  * @ctxt:  a schema validation context
9531  * @node:  the root of the document.
9532  *
9533  * removes unwanted nodes in a schemas document tree
9534  */
9535 static void
9536 xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9537 {
9538     xmlNodePtr delete, cur;
9539
9540     if ((ctxt == NULL) || (root == NULL)) return;
9541
9542     /*
9543      * Remove all the blank text nodes
9544      */
9545     delete = NULL;
9546     cur = root;
9547     while (cur != NULL) {
9548         if (delete != NULL) {
9549             xmlUnlinkNode(delete);
9550             xmlFreeNode(delete);
9551             delete = NULL;
9552         }
9553         if (cur->type == XML_TEXT_NODE) {
9554             if (IS_BLANK_NODE(cur)) {
9555                 if (xmlNodeGetSpacePreserve(cur) != 1) {
9556                     delete = cur;
9557                 }
9558             }
9559         } else if ((cur->type != XML_ELEMENT_NODE) &&
9560                    (cur->type != XML_CDATA_SECTION_NODE)) {
9561             delete = cur;
9562             goto skip_children;
9563         }
9564
9565         /*
9566          * Skip to next node
9567          */
9568         if (cur->children != NULL) {
9569             if ((cur->children->type != XML_ENTITY_DECL) &&
9570                 (cur->children->type != XML_ENTITY_REF_NODE) &&
9571                 (cur->children->type != XML_ENTITY_NODE)) {
9572                 cur = cur->children;
9573                 continue;
9574             }
9575         }
9576       skip_children:
9577         if (cur->next != NULL) {
9578             cur = cur->next;
9579             continue;
9580         }
9581
9582         do {
9583             cur = cur->parent;
9584             if (cur == NULL)
9585                 break;
9586             if (cur == root) {
9587                 cur = NULL;
9588                 break;
9589             }
9590             if (cur->next != NULL) {
9591                 cur = cur->next;
9592                 break;
9593             }
9594         } while (cur != NULL);
9595     }
9596     if (delete != NULL) {
9597         xmlUnlinkNode(delete);
9598         xmlFreeNode(delete);
9599         delete = NULL;
9600     }
9601 }
9602
9603
9604 static void
9605 xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9606 {
9607     if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9608         schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9609
9610     if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9611         schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9612
9613     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9614         schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9615     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9616         schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9617     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9618         schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9619     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9620         schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9621
9622     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9623         schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9624     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9625         schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9626     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9627         schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9628 }
9629
9630 static int
9631 xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
9632                              xmlSchemaPtr schema,
9633                              xmlNodePtr node)
9634 {
9635     xmlAttrPtr attr;
9636     const xmlChar *val;
9637     int res = 0, oldErrs = ctxt->nberrors;
9638
9639     /*
9640     * Those flags should be moved to the parser context flags,
9641     * since they are not visible at the component level. I.e.
9642     * they are used if processing schema *documents* only.
9643     */
9644     res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9645     HFAILURE;
9646
9647     /*
9648     * Since the version is of type xs:token, we won't bother to
9649     * check it.
9650     */
9651     /* REMOVED:
9652     attr = xmlSchemaGetPropNode(node, "version");
9653     if (attr != NULL) {
9654         res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9655             xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9656         HFAILURE;
9657     }
9658     */
9659     attr = xmlSchemaGetPropNode(node, "targetNamespace");
9660     if (attr != NULL) {
9661         res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
9662             xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9663         HFAILURE;
9664         if (res != 0) {
9665             ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9666             goto exit;
9667         }
9668     }
9669     attr = xmlSchemaGetPropNode(node, "elementFormDefault");
9670     if (attr != NULL) {
9671         val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9672         res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9673             XML_SCHEMAS_QUALIF_ELEM);
9674         HFAILURE;
9675         if (res != 0) {
9676             xmlSchemaPSimpleTypeErr(ctxt,
9677                 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
9678                 NULL, (xmlNodePtr) attr, NULL,
9679                 "(qualified | unqualified)", val, NULL, NULL, NULL);
9680         }
9681     }
9682     attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
9683     if (attr != NULL) {
9684         val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9685         res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9686             XML_SCHEMAS_QUALIF_ATTR);
9687         HFAILURE;
9688         if (res != 0) {
9689             xmlSchemaPSimpleTypeErr(ctxt,
9690                 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
9691                 NULL, (xmlNodePtr) attr, NULL,
9692                 "(qualified | unqualified)", val, NULL, NULL, NULL);
9693         }
9694     }
9695     attr = xmlSchemaGetPropNode(node, "finalDefault");
9696     if (attr != NULL) {
9697         val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9698         res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9699             XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9700             XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9701             -1,
9702             XML_SCHEMAS_FINAL_DEFAULT_LIST,
9703             XML_SCHEMAS_FINAL_DEFAULT_UNION);
9704         HFAILURE;
9705         if (res != 0) {
9706             xmlSchemaPSimpleTypeErr(ctxt,
9707                 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9708                 NULL, (xmlNodePtr) attr, NULL,
9709                 "(#all | List of (extension | restriction | list | union))",
9710                 val, NULL, NULL, NULL);
9711         }
9712     }
9713     attr = xmlSchemaGetPropNode(node, "blockDefault");
9714     if (attr != NULL) {
9715         val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9716         res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9717             XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9718             XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
9719             XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9720         HFAILURE;
9721         if (res != 0) {
9722             xmlSchemaPSimpleTypeErr(ctxt,
9723                 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9724                 NULL, (xmlNodePtr) attr, NULL,
9725                 "(#all | List of (extension | restriction | substitution))",
9726                 val, NULL, NULL, NULL);
9727         }
9728     }
9729
9730 exit:
9731     if (oldErrs != ctxt->nberrors)
9732         res = ctxt->err;
9733     return(res);
9734 exit_failure:
9735     return(-1);
9736 }
9737
9738 /**
9739  * xmlSchemaParseSchemaTopLevel:
9740  * @ctxt:  a schema validation context
9741  * @schema:  the schemas
9742  * @nodes:  the list of top level nodes
9743  *
9744  * Returns the internal XML Schema structure built from the resource or
9745  *         NULL in case of error
9746  */
9747 static int
9748 xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9749                              xmlSchemaPtr schema, xmlNodePtr nodes)
9750 {
9751     xmlNodePtr child;
9752     xmlSchemaAnnotPtr annot;
9753     int res = 0, oldErrs, tmpOldErrs;
9754
9755     if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
9756         return(-1);
9757
9758     oldErrs = ctxt->nberrors;
9759     child = nodes;
9760     while ((IS_SCHEMA(child, "include")) ||
9761            (IS_SCHEMA(child, "import")) ||
9762            (IS_SCHEMA(child, "redefine")) ||
9763            (IS_SCHEMA(child, "annotation"))) {
9764         if (IS_SCHEMA(child, "annotation")) {
9765             annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9766             if (schema->annot == NULL)
9767                 schema->annot = annot;
9768             else
9769                 xmlSchemaFreeAnnot(annot);
9770         } else if (IS_SCHEMA(child, "import")) {
9771             tmpOldErrs = ctxt->nberrors;
9772             res = xmlSchemaParseImport(ctxt, schema, child);
9773             HFAILURE;
9774             HSTOP(ctxt);
9775             if (tmpOldErrs != ctxt->nberrors)
9776                 goto exit;
9777         } else if (IS_SCHEMA(child, "include")) {
9778             tmpOldErrs = ctxt->nberrors;
9779             res = xmlSchemaParseInclude(ctxt, schema, child);
9780             HFAILURE;
9781             HSTOP(ctxt);
9782             if (tmpOldErrs != ctxt->nberrors)
9783                 goto exit;
9784         } else if (IS_SCHEMA(child, "redefine")) {
9785             tmpOldErrs = ctxt->nberrors;
9786             res = xmlSchemaParseRedefine(ctxt, schema, child);
9787             HFAILURE;
9788             HSTOP(ctxt);
9789             if (tmpOldErrs != ctxt->nberrors)
9790                 goto exit;
9791         }
9792         child = child->next;
9793     }
9794     /*
9795     * URGENT TODO: Change the functions to return int results.
9796     * We need especially to catch internal errors.
9797     */
9798     while (child != NULL) {
9799         if (IS_SCHEMA(child, "complexType")) {
9800             xmlSchemaParseComplexType(ctxt, schema, child, 1);
9801             child = child->next;
9802         } else if (IS_SCHEMA(child, "simpleType")) {
9803             xmlSchemaParseSimpleType(ctxt, schema, child, 1);
9804             child = child->next;
9805         } else if (IS_SCHEMA(child, "element")) {
9806             xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
9807             child = child->next;
9808         } else if (IS_SCHEMA(child, "attribute")) {
9809             xmlSchemaParseGlobalAttribute(ctxt, schema, child);
9810             child = child->next;
9811         } else if (IS_SCHEMA(child, "attributeGroup")) {
9812             xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
9813             child = child->next;
9814         } else if (IS_SCHEMA(child, "group")) {
9815             xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
9816             child = child->next;
9817         } else if (IS_SCHEMA(child, "notation")) {
9818             xmlSchemaParseNotation(ctxt, schema, child);
9819             child = child->next;
9820         } else {
9821             xmlSchemaPContentErr(ctxt,
9822                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9823                 NULL, child->parent, child,
9824                 NULL, "((include | import | redefine | annotation)*, "
9825                 "(((simpleType | complexType | group | attributeGroup) "
9826                 "| element | attribute | notation), annotation*)*)");
9827             child = child->next;
9828         }
9829         while (IS_SCHEMA(child, "annotation")) {
9830             /*
9831             * TODO: We should add all annotations.
9832             */
9833             annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9834             if (schema->annot == NULL)
9835                 schema->annot = annot;
9836             else
9837                 xmlSchemaFreeAnnot(annot);
9838             child = child->next;
9839         }
9840     }
9841 exit:
9842     ctxt->ctxtType = NULL;
9843     if (oldErrs != ctxt->nberrors)
9844         res = ctxt->err;
9845     return(res);
9846 exit_failure:
9847     return(-1);
9848 }
9849
9850 static xmlSchemaSchemaRelationPtr
9851 xmlSchemaSchemaRelationCreate(void)
9852 {
9853     xmlSchemaSchemaRelationPtr ret;
9854
9855     ret = (xmlSchemaSchemaRelationPtr)
9856         xmlMalloc(sizeof(xmlSchemaSchemaRelation));
9857     if (ret == NULL) {
9858         xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
9859         return(NULL);
9860     }
9861     memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
9862     return(ret);
9863 }
9864
9865 #if 0
9866 static void
9867 xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
9868 {
9869     xmlFree(rel);
9870 }
9871 #endif
9872
9873 static void
9874 xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9875 {
9876     xmlSchemaRedefPtr prev;
9877
9878     while (redef != NULL) {
9879         prev = redef;
9880         redef = redef->next;
9881         xmlFree(prev);
9882     }
9883 }
9884
9885 static void
9886 xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9887 {
9888     /*
9889     * After the construction context has been freed, there will be
9890     * no schema graph available any more. Only the schema buckets
9891     * will stay alive, which are put into the "schemasImports" and
9892     * "includes" slots of the xmlSchema.
9893     */
9894     if (con->buckets != NULL)
9895         xmlSchemaItemListFree(con->buckets);
9896     if (con->pending != NULL)
9897         xmlSchemaItemListFree(con->pending);
9898     if (con->substGroups != NULL)
9899         xmlHashFree(con->substGroups,
9900             (xmlHashDeallocator) xmlSchemaSubstGroupFree);
9901     if (con->redefs != NULL)
9902         xmlSchemaRedefListFree(con->redefs);
9903     if (con->dict != NULL)
9904         xmlDictFree(con->dict);
9905     xmlFree(con);
9906 }
9907
9908 static xmlSchemaConstructionCtxtPtr
9909 xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9910 {
9911     xmlSchemaConstructionCtxtPtr ret;
9912
9913     ret = (xmlSchemaConstructionCtxtPtr)
9914         xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9915     if (ret == NULL) {
9916         xmlSchemaPErrMemory(NULL,
9917             "allocating schema construction context", NULL);
9918         return (NULL);
9919     }
9920     memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
9921
9922     ret->buckets = xmlSchemaItemListCreate();
9923     if (ret->buckets == NULL) {
9924         xmlSchemaPErrMemory(NULL,
9925             "allocating list of schema buckets", NULL);
9926         xmlFree(ret);
9927         return (NULL);
9928     }
9929     ret->pending = xmlSchemaItemListCreate();
9930     if (ret->pending == NULL) {
9931         xmlSchemaPErrMemory(NULL,
9932             "allocating list of pending global components", NULL);
9933         xmlSchemaConstructionCtxtFree(ret);
9934         return (NULL);
9935     }
9936     ret->dict = dict;
9937     xmlDictReference(dict);
9938     return(ret);
9939 }
9940
9941 static xmlSchemaParserCtxtPtr
9942 xmlSchemaParserCtxtCreate(void)
9943 {
9944     xmlSchemaParserCtxtPtr ret;
9945
9946     ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9947     if (ret == NULL) {
9948         xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9949                             NULL);
9950         return (NULL);
9951     }
9952     memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9953     ret->type = XML_SCHEMA_CTXT_PARSER;
9954     ret->attrProhibs = xmlSchemaItemListCreate();
9955     if (ret->attrProhibs == NULL) {
9956         xmlFree(ret);
9957         return(NULL);
9958     }
9959     return(ret);
9960 }
9961
9962 /**
9963  * xmlSchemaNewParserCtxtUseDict:
9964  * @URL:  the location of the schema
9965  * @dict: the dictionary to be used
9966  *
9967  * Create an XML Schemas parse context for that file/resource expected
9968  * to contain an XML Schemas file.
9969  *
9970  * Returns the parser context or NULL in case of error
9971  */
9972 static xmlSchemaParserCtxtPtr
9973 xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9974 {
9975     xmlSchemaParserCtxtPtr ret;
9976
9977     ret = xmlSchemaParserCtxtCreate();
9978     if (ret == NULL)
9979         return (NULL);
9980     ret->dict = dict;
9981     xmlDictReference(dict);
9982     if (URL != NULL)
9983         ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
9984     return (ret);
9985 }
9986
9987 static int
9988 xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
9989 {
9990     if (vctxt->pctxt == NULL) {
9991         if (vctxt->schema != NULL)
9992             vctxt->pctxt =
9993                 xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
9994         else
9995             vctxt->pctxt = xmlSchemaNewParserCtxt("*");
9996         if (vctxt->pctxt == NULL) {
9997             VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
9998                 "failed to create a temp. parser context");
9999             return (-1);
10000         }
10001         /* TODO: Pass user data. */
10002         xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
10003             vctxt->warning, vctxt->errCtxt);
10004         xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
10005             vctxt->errCtxt);
10006     }
10007     return (0);
10008 }
10009
10010 /**
10011  * xmlSchemaGetSchemaBucket:
10012  * @pctxt: the schema parser context
10013  * @schemaLocation: the URI of the schema document
10014  *
10015  * Returns a schema bucket if it was already parsed.
10016  *
10017  * Returns a schema bucket if it was already parsed from
10018  *         @schemaLocation, NULL otherwise.
10019  */
10020 static xmlSchemaBucketPtr
10021 xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10022                             const xmlChar *schemaLocation)
10023 {
10024     xmlSchemaBucketPtr cur;
10025     xmlSchemaItemListPtr list;
10026
10027     list = pctxt->constructor->buckets;
10028     if (list->nbItems == 0)
10029         return(NULL);
10030     else {
10031         int i;
10032         for (i = 0; i < list->nbItems; i++) {
10033             cur = (xmlSchemaBucketPtr) list->items[i];
10034             /* Pointer comparison! */
10035             if (cur->schemaLocation == schemaLocation)
10036                 return(cur);
10037         }
10038     }
10039     return(NULL);
10040 }
10041
10042 static xmlSchemaBucketPtr
10043 xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10044                                      const xmlChar *schemaLocation,
10045                                      const xmlChar *targetNamespace)
10046 {
10047     xmlSchemaBucketPtr cur;
10048     xmlSchemaItemListPtr list;
10049
10050     list = pctxt->constructor->buckets;
10051     if (list->nbItems == 0)
10052         return(NULL);
10053     else {
10054         int i;
10055         for (i = 0; i < list->nbItems; i++) {
10056             cur = (xmlSchemaBucketPtr) list->items[i];
10057             /* Pointer comparison! */
10058             if ((cur->origTargetNamespace == NULL) &&
10059                 (cur->schemaLocation == schemaLocation) &&
10060                 (cur->targetNamespace == targetNamespace))
10061                 return(cur);
10062         }
10063     }
10064     return(NULL);
10065 }
10066
10067
10068 #define IS_BAD_SCHEMA_DOC(b) \
10069     (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10070
10071 static xmlSchemaBucketPtr
10072 xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10073                                  const xmlChar *targetNamespace,
10074                                  int imported)
10075 {
10076     xmlSchemaBucketPtr cur;
10077     xmlSchemaItemListPtr list;
10078
10079     list = pctxt->constructor->buckets;
10080     if (list->nbItems == 0)
10081         return(NULL);
10082     else {
10083         int i;
10084         for (i = 0; i < list->nbItems; i++) {
10085             cur = (xmlSchemaBucketPtr) list->items[i];
10086             if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10087                 (cur->origTargetNamespace == targetNamespace) &&
10088                 ((imported && cur->imported) ||
10089                  ((!imported) && (!cur->imported))))
10090                 return(cur);
10091         }
10092     }
10093     return(NULL);
10094 }
10095
10096 static int
10097 xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10098                      xmlSchemaPtr schema,
10099                      xmlSchemaBucketPtr bucket)
10100 {
10101     int oldFlags;
10102     xmlDocPtr oldDoc;
10103     xmlNodePtr node;
10104     int ret, oldErrs;
10105     xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10106
10107     /*
10108     * Save old values; reset the *main* schema.
10109     * URGENT TODO: This is not good; move the per-document information
10110     * to the parser. Get rid of passing the main schema to the
10111     * parsing functions.
10112     */
10113     oldFlags = schema->flags;
10114     oldDoc = schema->doc;
10115     if (schema->flags != 0)
10116         xmlSchemaClearSchemaDefaults(schema);
10117     schema->doc = bucket->doc;
10118     pctxt->schema = schema;
10119     /*
10120     * Keep the current target namespace on the parser *not* on the
10121     * main schema.
10122     */
10123     pctxt->targetNamespace = bucket->targetNamespace;
10124     WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
10125
10126     if ((bucket->targetNamespace != NULL) &&
10127         xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
10128         /*
10129         * We are parsing the schema for schemas!
10130         */
10131         pctxt->isS4S = 1;
10132     }
10133     /* Mark it as parsed, even if parsing fails. */
10134     bucket->parsed++;
10135     /* Compile the schema doc. */
10136     node = xmlDocGetRootElement(bucket->doc);
10137     ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10138     if (ret != 0)
10139         goto exit;
10140     /* An empty schema; just get out. */
10141     if (node->children == NULL)
10142         goto exit;
10143     oldErrs = pctxt->nberrors;
10144     ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10145     if (ret != 0)
10146         goto exit;
10147     /*
10148     * TODO: Not nice, but I'm not 100% sure we will get always an error
10149     * as a result of the obove functions; so better rely on pctxt->err
10150     * as well.
10151     */
10152     if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10153         ret = pctxt->err;
10154         goto exit;
10155     }
10156
10157 exit:
10158     WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10159     /* Restore schema values. */
10160     schema->doc = oldDoc;
10161     schema->flags = oldFlags;
10162     return(ret);
10163 }
10164
10165 static int
10166 xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10167                      xmlSchemaPtr schema,
10168                      xmlSchemaBucketPtr bucket)
10169 {
10170     xmlSchemaParserCtxtPtr newpctxt;
10171     int res = 0;
10172
10173     if (bucket == NULL)
10174         return(0);
10175     if (bucket->parsed) {
10176         PERROR_INT("xmlSchemaParseNewDoc",
10177             "reparsing a schema doc");
10178         return(-1);
10179     }
10180     if (bucket->doc == NULL) {
10181         PERROR_INT("xmlSchemaParseNewDoc",
10182             "parsing a schema doc, but there's no doc");
10183         return(-1);
10184     }
10185     if (pctxt->constructor == NULL) {
10186         PERROR_INT("xmlSchemaParseNewDoc",
10187             "no constructor");
10188         return(-1);
10189     }
10190     /* Create and init the temporary parser context. */
10191     newpctxt = xmlSchemaNewParserCtxtUseDict(
10192         (const char *) bucket->schemaLocation, pctxt->dict);
10193     if (newpctxt == NULL)
10194         return(-1);
10195     newpctxt->constructor = pctxt->constructor;
10196     /*
10197     * TODO: Can we avoid that the parser knows about the main schema?
10198     * It would be better if he knows about the current schema bucket
10199     * only.
10200     */
10201     newpctxt->schema = schema;
10202     xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
10203         pctxt->errCtxt);
10204     xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10205         pctxt->errCtxt);
10206     newpctxt->counter = pctxt->counter;
10207
10208
10209     res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10210
10211     /* Channel back errors and cleanup the temporary parser context. */
10212     if (res != 0)
10213         pctxt->err = res;
10214     pctxt->nberrors += newpctxt->nberrors;
10215     pctxt->counter = newpctxt->counter;
10216     newpctxt->constructor = NULL;
10217     /* Free the parser context. */
10218     xmlSchemaFreeParserCtxt(newpctxt);
10219     return(res);
10220 }
10221
10222 static void
10223 xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10224                                 xmlSchemaSchemaRelationPtr rel)
10225 {
10226     xmlSchemaSchemaRelationPtr cur = bucket->relations;
10227
10228     if (cur == NULL) {
10229         bucket->relations = rel;
10230         return;
10231     }
10232     while (cur->next != NULL)
10233         cur = cur->next;
10234     cur->next = rel;
10235 }
10236
10237
10238 static const xmlChar *
10239 xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10240                           xmlNodePtr ctxtNode)
10241 {
10242     /*
10243     * Build an absolue location URI.
10244     */
10245     if (location != NULL) {
10246         if (ctxtNode == NULL)
10247             return(location);
10248         else {
10249             xmlChar *base, *URI;
10250             const xmlChar *ret = NULL;
10251
10252             base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10253             if (base == NULL) {
10254                 URI = xmlBuildURI(location, ctxtNode->doc->URL);
10255             } else {
10256                 URI = xmlBuildURI(location, base);
10257                 xmlFree(base);
10258             }
10259             if (URI != NULL) {
10260                 ret = xmlDictLookup(dict, URI, -1);
10261                 xmlFree(URI);
10262                 return(ret);
10263             }
10264         }
10265     }
10266     return(NULL);
10267 }
10268
10269
10270
10271 /**
10272  * xmlSchemaAddSchemaDoc:
10273  * @pctxt:  a schema validation context
10274  * @schema:  the schema being built
10275  * @node:  a subtree containing XML Schema informations
10276  *
10277  * Parse an included (and to-be-redefined) XML schema document.
10278  *
10279  * Returns 0 on success, a positive error code on errors and
10280  *         -1 in case of an internal or API error.
10281  */
10282
10283 static int
10284 xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10285                 int type, /* import or include or redefine */
10286                 const xmlChar *schemaLocation,
10287                 xmlDocPtr schemaDoc,
10288                 const char *schemaBuffer,
10289                 int schemaBufferLen,
10290                 xmlNodePtr invokingNode,
10291                 const xmlChar *sourceTargetNamespace,
10292                 const xmlChar *importNamespace,
10293                 xmlSchemaBucketPtr *bucket)
10294 {
10295     const xmlChar *targetNamespace = NULL;
10296     xmlSchemaSchemaRelationPtr relation = NULL;
10297     xmlDocPtr doc = NULL;
10298     int res = 0, err = 0, located = 0, preserveDoc = 0;
10299     xmlSchemaBucketPtr bkt = NULL;
10300
10301     if (bucket != NULL)
10302         *bucket = NULL;
10303
10304     switch (type) {
10305         case XML_SCHEMA_SCHEMA_IMPORT:
10306         case XML_SCHEMA_SCHEMA_MAIN:
10307             err = XML_SCHEMAP_SRC_IMPORT;
10308             break;
10309         case XML_SCHEMA_SCHEMA_INCLUDE:
10310             err = XML_SCHEMAP_SRC_INCLUDE;
10311             break;
10312         case XML_SCHEMA_SCHEMA_REDEFINE:
10313             err = XML_SCHEMAP_SRC_REDEFINE;
10314             break;
10315     }
10316
10317
10318     /* Special handling for the main schema:
10319     * skip the location and relation logic and just parse the doc.
10320     * We need just a bucket to be returned in this case.
10321     */
10322     if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10323         goto doc_load;
10324
10325     /* Note that we expect the location to be an absulute URI. */
10326     if (schemaLocation != NULL) {
10327         bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10328         if ((bkt != NULL) &&
10329             (pctxt->constructor->bucket == bkt)) {
10330             /* Report self-imports/inclusions/redefinitions. */
10331
10332             xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10333                 invokingNode, NULL,
10334                 "The schema must not import/include/redefine itself",
10335                 NULL, NULL);
10336             goto exit;
10337         }
10338     }
10339     /*
10340     * Create a relation for the graph of schemas.
10341     */
10342     relation = xmlSchemaSchemaRelationCreate();
10343     if (relation == NULL)
10344         return(-1);
10345     xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10346         relation);
10347     relation->type = type;
10348
10349     /*
10350     * Save the namespace import information.
10351     */
10352     if (WXS_IS_BUCKET_IMPMAIN(type)) {
10353         relation->importNamespace = importNamespace;
10354         if (schemaLocation == NULL) {
10355             /*
10356             * No location; this is just an import of the namespace.
10357             * Note that we don't assign a bucket to the relation
10358             * in this case.
10359             */
10360             goto exit;
10361         }
10362         targetNamespace = importNamespace;
10363     }
10364
10365     /* Did we already fetch the doc? */
10366     if (bkt != NULL) {
10367         if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
10368             /*
10369             * We included/redefined and then try to import a schema,
10370             * but the new location provided for import was different.
10371             */
10372             if (schemaLocation == NULL)
10373                 schemaLocation = BAD_CAST "in_memory_buffer";
10374             if (!xmlStrEqual(schemaLocation,
10375                 bkt->schemaLocation)) {
10376                 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10377                     invokingNode, NULL,
10378                     "The schema document '%s' cannot be imported, since "
10379                     "it was already included or redefined",
10380                     schemaLocation, NULL);
10381                 goto exit;
10382             }
10383         } else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
10384             /*
10385             * We imported and then try to include/redefine a schema,
10386             * but the new location provided for the include/redefine
10387             * was different.
10388             */
10389             if (schemaLocation == NULL)
10390                 schemaLocation = BAD_CAST "in_memory_buffer";
10391             if (!xmlStrEqual(schemaLocation,
10392                 bkt->schemaLocation)) {
10393                 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10394                     invokingNode, NULL,
10395                     "The schema document '%s' cannot be included or "
10396                     "redefined, since it was already imported",
10397                     schemaLocation, NULL);
10398                 goto exit;
10399             }
10400         }
10401     }
10402
10403     if (WXS_IS_BUCKET_IMPMAIN(type)) {
10404         /*
10405         * Given that the schemaLocation [attribute] is only a hint, it is open
10406         * to applications to ignore all but the first <import> for a given
10407         * namespace, regardless of the `actual value` of schemaLocation, but
10408         * such a strategy risks missing useful information when new
10409         * schemaLocations are offered.
10410         *
10411         * We will use the first <import> that comes with a location.
10412         * Further <import>s *with* a location, will result in an error.
10413         * TODO: Better would be to just report a warning here, but
10414         * we'll try it this way until someone complains.
10415         *
10416         * Schema Document Location Strategy:
10417         * 3 Based on the namespace name, identify an existing schema document,
10418         * either as a resource which is an XML document or a <schema> element
10419         * information item, in some local schema repository;
10420         * 5 Attempt to resolve the namespace name to locate such a resource.
10421         *
10422         * NOTE: (3) and (5) are not supported.
10423         */
10424         if (bkt != NULL) {
10425             relation->bucket = bkt;
10426             goto exit;
10427         }
10428         bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10429             importNamespace, 1);
10430
10431         if (bkt != NULL) {
10432             relation->bucket = bkt;
10433             if (bkt->schemaLocation == NULL) {
10434                 /* First given location of the schema; load the doc. */
10435                 bkt->schemaLocation = schemaLocation;
10436             } else {
10437                 if (!xmlStrEqual(schemaLocation,
10438                     bkt->schemaLocation)) {
10439                     /*
10440                     * Additional location given; just skip it.
10441                     * URGENT TODO: We should report a warning here.
10442                     * res = XML_SCHEMAP_SRC_IMPORT;
10443                     */
10444                     if (schemaLocation == NULL)
10445                         schemaLocation = BAD_CAST "in_memory_buffer";
10446
10447                     xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10448                         XML_SCHEMAP_WARN_SKIP_SCHEMA,
10449                         invokingNode, NULL,
10450                         "Skipping import of schema located at '%s' for the "
10451                         "namespace '%s', since this namespace was already "
10452                         "imported with the schema located at '%s'",
10453                         schemaLocation, importNamespace, bkt->schemaLocation);
10454                 }
10455                 goto exit;
10456             }
10457         }
10458         /*
10459         * No bucket + first location: load the doc and create a
10460         * bucket.
10461         */
10462     } else {
10463         /* <include> and <redefine> */
10464         if (bkt != NULL) {
10465
10466             if ((bkt->origTargetNamespace == NULL) &&
10467                 (bkt->targetNamespace != sourceTargetNamespace)) {
10468                 xmlSchemaBucketPtr chamel;
10469
10470                 /*
10471                 * Chameleon include/redefine: skip loading only if it was
10472                 * aleady build for the targetNamespace of the including
10473                 * schema.
10474                 */
10475                 /*
10476                 * URGENT TODO: If the schema is a chameleon-include then copy
10477                 * the components into the including schema and modify the
10478                 * targetNamespace of those components, do nothing otherwise.
10479                 * NOTE: This is currently worked-around by compiling the
10480                 * chameleon for every destinct including targetNamespace; thus
10481                 * not performant at the moment.
10482                 * TODO: Check when the namespace in wildcards for chameleons
10483                 * needs to be converted: before we built wildcard intersections
10484                 * or after.
10485                 *   Answer: after!
10486                 */
10487                 chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10488                     schemaLocation, sourceTargetNamespace);
10489                 if (chamel != NULL) {
10490                     /* A fitting chameleon was already parsed; NOP. */
10491                     relation->bucket = chamel;
10492                     goto exit;
10493                 }
10494                 /*
10495                 * We need to parse the chameleon again for a different
10496                 * targetNamespace.
10497                 * CHAMELEON TODO: Optimize this by only parsing the
10498                 * chameleon once, and then copying the components to
10499                 * the new targetNamespace.
10500                 */
10501                 bkt = NULL;
10502             } else {
10503                 relation->bucket = bkt;
10504                 goto exit;
10505             }
10506         }
10507     }
10508     if ((bkt != NULL) && (bkt->doc != NULL)) {
10509         PERROR_INT("xmlSchemaAddSchemaDoc",
10510             "trying to load a schema doc, but a doc is already "
10511             "assigned to the schema bucket");
10512         goto exit_failure;
10513     }
10514
10515 doc_load:
10516     /*
10517     * Load the document.
10518     */
10519     if (schemaDoc != NULL) {
10520         doc = schemaDoc;
10521         /* Don' free this one, since it was provided by the caller. */
10522         preserveDoc = 1;
10523         /* TODO: Does the context or the doc hold the location? */
10524         if (schemaDoc->URL != NULL)
10525             schemaLocation = xmlDictLookup(pctxt->dict,
10526                 schemaDoc->URL, -1);
10527         else
10528             schemaLocation = BAD_CAST "in_memory_buffer";
10529     } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10530         xmlParserCtxtPtr parserCtxt;
10531
10532         parserCtxt = xmlNewParserCtxt();
10533         if (parserCtxt == NULL) {
10534             xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10535                 "allocating a parser context", NULL);
10536             goto exit_failure;
10537         }
10538         if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10539             /*
10540             * TODO: Do we have to burden the schema parser dict with all
10541             * the content of the schema doc?
10542             */
10543             xmlDictFree(parserCtxt->dict);
10544             parserCtxt->dict = pctxt->dict;
10545             xmlDictReference(parserCtxt->dict);
10546         }
10547         if (schemaLocation != NULL) {
10548             /* Parse from file. */
10549             doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10550                 NULL, SCHEMAS_PARSE_OPTIONS);
10551         } else if (schemaBuffer != NULL) {
10552             /* Parse from memory buffer. */
10553             doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10554                 NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10555             schemaLocation = BAD_CAST "in_memory_buffer";
10556             if (doc != NULL)
10557                 doc->URL = xmlStrdup(schemaLocation);
10558         }
10559         /*
10560         * For <import>:
10561         * 2.1 The referent is (a fragment of) a resource which is an
10562         * XML document (see clause 1.1), which in turn corresponds to
10563         * a <schema> element information item in a well-formed information
10564         * set, which in turn corresponds to a valid schema.
10565         * TODO: (2.1) fragments of XML documents are not supported.
10566         *
10567         * 2.2 The referent is a <schema> element information item in
10568         * a well-formed information set, which in turn corresponds
10569         * to a valid schema.
10570         * TODO: (2.2) is not supported.
10571         */
10572         if (doc == NULL) {
10573             xmlErrorPtr lerr;
10574             lerr = xmlGetLastError();
10575             /*
10576             * Check if this a parser error, or if the document could
10577             * just not be located.
10578             * TODO: Try to find specific error codes to react only on
10579             * localisation failures.
10580             */
10581             if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10582                 /*
10583                 * We assume a parser error here.
10584                 */
10585                 located = 1;
10586                 /* TODO: Error code ?? */
10587                 res = XML_SCHEMAP_SRC_IMPORT_2_1;
10588                 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10589                     invokingNode, NULL,
10590                     "Failed to parse the XML resource '%s'",
10591                     schemaLocation, NULL);
10592             }
10593         }
10594         xmlFreeParserCtxt(parserCtxt);
10595         if ((doc == NULL) && located)
10596             goto exit_error;
10597     } else {
10598         xmlSchemaPErr(pctxt, NULL,
10599             XML_SCHEMAP_NOTHING_TO_PARSE,
10600             "No information for parsing was provided with the "
10601             "given schema parser context.\n",
10602             NULL, NULL);
10603         goto exit_failure;
10604     }
10605     /*
10606     * Preprocess the document.
10607     */
10608     if (doc != NULL) {
10609         xmlNodePtr docElem = NULL;
10610
10611         located = 1;
10612         docElem = xmlDocGetRootElement(doc);
10613         if (docElem == NULL) {
10614             xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10615                 invokingNode, NULL,
10616                 "The document '%s' has no document element",
10617                 schemaLocation, NULL);
10618             goto exit_error;
10619         }
10620         /*
10621         * Remove all the blank text nodes.
10622         */
10623         xmlSchemaCleanupDoc(pctxt, docElem);
10624         /*
10625         * Check the schema's top level element.
10626         */
10627         if (!IS_SCHEMA(docElem, "schema")) {
10628             xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10629                 invokingNode, NULL,
10630                 "The XML document '%s' is not a schema document",
10631                 schemaLocation, NULL);
10632             goto exit_error;
10633         }
10634         /*
10635         * Note that we don't apply a type check for the
10636         * targetNamespace value here.
10637         */
10638         targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10639             "targetNamespace");
10640     }
10641
10642 /* after_doc_loading: */
10643     if ((bkt == NULL) && located) {
10644         /* Only create a bucket if the schema was located. */
10645         bkt = xmlSchemaBucketCreate(pctxt, type,
10646             targetNamespace);
10647         if (bkt == NULL)
10648             goto exit_failure;
10649     }
10650     if (bkt != NULL) {
10651         bkt->schemaLocation = schemaLocation;
10652         bkt->located = located;
10653         if (doc != NULL) {
10654             bkt->doc = doc;
10655             bkt->targetNamespace = targetNamespace;
10656             bkt->origTargetNamespace = targetNamespace;
10657             if (preserveDoc)
10658                 bkt->preserveDoc = 1;
10659         }
10660         if (WXS_IS_BUCKET_IMPMAIN(type))
10661             bkt->imported++;
10662             /*
10663             * Add it to the graph of schemas.
10664             */
10665         if (relation != NULL)
10666             relation->bucket = bkt;
10667     }
10668
10669 exit:
10670     /*
10671     * Return the bucket explicitely; this is needed for the
10672     * main schema.
10673     */
10674     if (bucket != NULL)
10675         *bucket = bkt;
10676     return (0);
10677
10678 exit_error:
10679     if ((doc != NULL) && (! preserveDoc)) {
10680         xmlFreeDoc(doc);
10681         if (bkt != NULL)
10682             bkt->doc = NULL;
10683     }
10684     return(pctxt->err);
10685
10686 exit_failure:
10687     if ((doc != NULL) && (! preserveDoc)) {
10688         xmlFreeDoc(doc);
10689         if (bkt != NULL)
10690             bkt->doc = NULL;
10691     }
10692     return (-1);
10693 }
10694
10695 /**
10696  * xmlSchemaParseImport:
10697  * @ctxt:  a schema validation context
10698  * @schema:  the schema being built
10699  * @node:  a subtree containing XML Schema informations
10700  *
10701  * parse a XML schema Import definition
10702  * *WARNING* this interface is highly subject to change
10703  *
10704  * Returns 0 in case of success, a positive error code if
10705  * not valid and -1 in case of an internal error.
10706  */
10707 static int
10708 xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
10709                      xmlNodePtr node)
10710 {
10711     xmlNodePtr child;
10712     const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10713     const xmlChar *thisTargetNamespace;
10714     xmlAttrPtr attr;
10715     int ret = 0;
10716     xmlSchemaBucketPtr bucket = NULL;
10717
10718     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10719         return (-1);
10720
10721     /*
10722     * Check for illegal attributes.
10723     */
10724     attr = node->properties;
10725     while (attr != NULL) {
10726         if (attr->ns == NULL) {
10727             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10728                 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10729                 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10730                 xmlSchemaPIllegalAttrErr(pctxt,
10731                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10732             }
10733         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10734             xmlSchemaPIllegalAttrErr(pctxt,
10735                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10736         }
10737         attr = attr->next;
10738     }
10739     /*
10740     * Extract and validate attributes.
10741     */
10742     if (xmlSchemaPValAttr(pctxt, NULL, node,
10743         "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10744         &namespaceName) != 0) {
10745         xmlSchemaPSimpleTypeErr(pctxt,
10746             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10747             NULL, node,
10748             xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10749             NULL, namespaceName, NULL, NULL, NULL);
10750         return (pctxt->err);
10751     }
10752
10753     if (xmlSchemaPValAttr(pctxt, NULL, node,
10754         "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10755         &schemaLocation) != 0) {
10756         xmlSchemaPSimpleTypeErr(pctxt,
10757             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10758             NULL, node,
10759             xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10760             NULL, schemaLocation, NULL, NULL, NULL);
10761         return (pctxt->err);
10762     }
10763     /*
10764     * And now for the children...
10765     */
10766     child = node->children;
10767     if (IS_SCHEMA(child, "annotation")) {
10768         /*
10769          * the annotation here is simply discarded ...
10770          * TODO: really?
10771          */
10772         child = child->next;
10773     }
10774     if (child != NULL) {
10775         xmlSchemaPContentErr(pctxt,
10776             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10777             NULL, node, child, NULL,
10778             "(annotation?)");
10779     }
10780     /*
10781     * Apply additional constraints.
10782     *
10783     * Note that it is important to use the original @targetNamespace
10784     * (or none at all), to rule out imports of schemas _with_ a
10785     * @targetNamespace if the importing schema is a chameleon schema
10786     * (with no @targetNamespace).
10787     */
10788     thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
10789     if (namespaceName != NULL) {
10790         /*
10791         * 1.1 If the namespace [attribute] is present, then its `actual value`
10792         * must not match the `actual value` of the enclosing <schema>'s
10793         * targetNamespace [attribute].
10794         */
10795         if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
10796             xmlSchemaPCustomErr(pctxt,
10797                 XML_SCHEMAP_SRC_IMPORT_1_1,
10798                 NULL, node,
10799                 "The value of the attribute 'namespace' must not match "
10800                 "the target namespace '%s' of the importing schema",
10801                 thisTargetNamespace);
10802             return (pctxt->err);
10803         }
10804     } else {
10805         /*
10806         * 1.2 If the namespace [attribute] is not present, then the enclosing
10807         * <schema> must have a targetNamespace [attribute].
10808         */
10809         if (thisTargetNamespace == NULL) {
10810             xmlSchemaPCustomErr(pctxt,
10811                 XML_SCHEMAP_SRC_IMPORT_1_2,
10812                 NULL, node,
10813                 "The attribute 'namespace' must be existent if "
10814                 "the importing schema has no target namespace",
10815                 NULL);
10816             return (pctxt->err);
10817         }
10818     }
10819     /*
10820     * Locate and acquire the schema document.
10821     */
10822     if (schemaLocation != NULL)
10823         schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10824             schemaLocation, node);
10825     ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
10826         schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
10827         namespaceName, &bucket);
10828
10829     if (ret != 0)
10830         return(ret);
10831
10832     /*
10833     * For <import>: "It is *not* an error for the application
10834     * schema reference strategy to fail."
10835     * So just don't parse if no schema document was found.
10836     * Note that we will get no bucket if the schema could not be
10837     * located or if there was no schemaLocation.
10838     */
10839     if ((bucket == NULL) && (schemaLocation != NULL)) {
10840         xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10841             XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10842             node, NULL,
10843             "Failed to locate a schema at location '%s'. "
10844             "Skipping the import", schemaLocation, NULL, NULL);
10845     }
10846
10847     if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10848         ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10849     }
10850
10851     return (ret);
10852 }
10853
10854 static int
10855 xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10856                                      xmlSchemaPtr schema,
10857                                      xmlNodePtr node,
10858                                      xmlChar **schemaLocation,
10859                                      int type)
10860 {
10861     xmlAttrPtr attr;
10862
10863     if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10864         (schemaLocation == NULL))
10865         return (-1);
10866
10867     *schemaLocation = NULL;
10868     /*
10869     * Check for illegal attributes.
10870     * Applies for both <include> and <redefine>.
10871     */
10872     attr = node->properties;
10873     while (attr != NULL) {
10874         if (attr->ns == NULL) {
10875             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10876                 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10877                 xmlSchemaPIllegalAttrErr(pctxt,
10878                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10879             }
10880         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10881             xmlSchemaPIllegalAttrErr(pctxt,
10882                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10883         }
10884         attr = attr->next;
10885     }
10886     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
10887     /*
10888     * Preliminary step, extract the URI-Reference and make an URI
10889     * from the base.
10890     */
10891     /*
10892     * Attribute "schemaLocation" is mandatory.
10893     */
10894     attr = xmlSchemaGetPropNode(node, "schemaLocation");
10895     if (attr != NULL) {
10896         xmlChar *base = NULL;
10897         xmlChar *uri = NULL;
10898
10899         if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
10900             xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10901             (const xmlChar **) schemaLocation) != 0)
10902             goto exit_error;
10903         base = xmlNodeGetBase(node->doc, node);
10904         if (base == NULL) {
10905             uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10906         } else {
10907             uri = xmlBuildURI(*schemaLocation, base);
10908             xmlFree(base);
10909         }
10910         if (uri == NULL) {
10911             PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10912                 "could not build an URI from the schemaLocation")
10913             goto exit_failure;
10914         }
10915         (*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10916         xmlFree(uri);
10917     } else {
10918         xmlSchemaPMissingAttrErr(pctxt,
10919             XML_SCHEMAP_S4S_ATTR_MISSING,
10920             NULL, node, "schemaLocation", NULL);
10921         goto exit_error;
10922     }
10923     /*
10924     * Report self-inclusion and self-redefinition.
10925     */
10926     if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
10927         if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
10928             xmlSchemaPCustomErr(pctxt,
10929                 XML_SCHEMAP_SRC_REDEFINE,
10930                 NULL, node,
10931                 "The schema document '%s' cannot redefine itself.",
10932                 *schemaLocation);
10933         } else {
10934             xmlSchemaPCustomErr(pctxt,
10935                 XML_SCHEMAP_SRC_INCLUDE,
10936                 NULL, node,
10937                 "The schema document '%s' cannot include itself.",
10938                 *schemaLocation);
10939         }
10940         goto exit_error;
10941     }
10942
10943     return(0);
10944 exit_error:
10945     return(pctxt->err);
10946 exit_failure:
10947     return(-1);
10948 }
10949
10950 static int
10951 xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
10952                                 xmlSchemaPtr schema,
10953                                 xmlNodePtr node,
10954                                 int type)
10955 {
10956     xmlNodePtr child = NULL;
10957     const xmlChar *schemaLocation = NULL;
10958     int res = 0; /* hasRedefinitions = 0 */
10959     int isChameleon = 0, wasChameleon = 0;
10960     xmlSchemaBucketPtr bucket = NULL;
10961
10962     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10963         return (-1);
10964
10965     /*
10966     * Parse attributes. Note that the returned schemaLocation will
10967     * be already converted to an absolute URI.
10968     */
10969     res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
10970         node, (xmlChar **) (&schemaLocation), type);
10971     if (res != 0)
10972         return(res);
10973     /*
10974     * Load and add the schema document.
10975     */
10976     res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
10977         NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
10978     if (res != 0)
10979         return(res);
10980     /*
10981     * If we get no schema bucket back, then this means that the schema
10982     * document could not be located or was broken XML or was not
10983     * a schema document.
10984     */
10985     if ((bucket == NULL) || (bucket->doc == NULL)) {
10986         if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
10987             /*
10988             * WARNING for <include>:
10989             * We will raise an error if the schema cannot be located
10990             * for inclusions, since the that was the feedback from the
10991             * schema people. I.e. the following spec piece will *not* be
10992             * satisfied:
10993             * SPEC src-include: "It is not an error for the `actual value` of the
10994             * schemaLocation [attribute] to fail to resolve it all, in which
10995             * case no corresponding inclusion is performed.
10996             * So do we need a warning report here?"
10997             */
10998             res = XML_SCHEMAP_SRC_INCLUDE;
10999             xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
11000                 node, NULL,
11001                 "Failed to load the document '%s' for inclusion",
11002                 schemaLocation, NULL);
11003         } else {
11004             /*
11005             * NOTE: This was changed to raise an error even if no redefinitions
11006             * are specified.
11007             *
11008             * SPEC src-redefine (1)
11009             * "If there are any element information items among the [children]
11010             * other than <annotation> then the `actual value` of the
11011             * schemaLocation [attribute] must successfully resolve."
11012             * TODO: Ask the WG if a the location has always to resolve
11013             * here as well!
11014             */
11015             res = XML_SCHEMAP_SRC_REDEFINE;
11016             xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
11017                 node, NULL,
11018                 "Failed to load the document '%s' for redefinition",
11019                 schemaLocation, NULL);
11020         }
11021     } else {
11022         /*
11023         * Check targetNamespace sanity before parsing the new schema.
11024         * TODO: Note that we won't check further content if the
11025         * targetNamespace was bad.
11026         */
11027         if (bucket->origTargetNamespace != NULL) {
11028             /*
11029             * SPEC src-include (2.1)
11030             * "SII has a targetNamespace [attribute], and its `actual
11031             * value` is identical to the `actual value` of the targetNamespace
11032             * [attribute] of SII' (which must have such an [attribute])."
11033             */
11034             if (pctxt->targetNamespace == NULL) {
11035                 xmlSchemaCustomErr(ACTXT_CAST pctxt,
11036                     XML_SCHEMAP_SRC_INCLUDE,
11037                     node, NULL,
11038                     "The target namespace of the included/redefined schema "
11039                     "'%s' has to be absent, since the including/redefining "
11040                     "schema has no target namespace",
11041                     schemaLocation, NULL);
11042                 goto exit_error;
11043             } else if (!xmlStrEqual(bucket->origTargetNamespace,
11044                 pctxt->targetNamespace)) {
11045                 /* TODO: Change error function. */
11046                 xmlSchemaPCustomErrExt(pctxt,
11047                     XML_SCHEMAP_SRC_INCLUDE,
11048                     NULL, node,
11049                     "The target namespace '%s' of the included/redefined "
11050                     "schema '%s' differs from '%s' of the "
11051                     "including/redefining schema",
11052                     bucket->origTargetNamespace, schemaLocation,
11053                     pctxt->targetNamespace);
11054                 goto exit_error;
11055             }
11056         } else if (pctxt->targetNamespace != NULL) {
11057             /*
11058             * Chameleons: the original target namespace will
11059             * differ from the resulting namespace.
11060             */
11061             isChameleon = 1;
11062             if (bucket->parsed &&
11063                 bucket->origTargetNamespace != NULL) {
11064                 xmlSchemaCustomErr(ACTXT_CAST pctxt,
11065                     XML_SCHEMAP_SRC_INCLUDE,
11066                     node, NULL,
11067                     "The target namespace of the included/redefined schema "
11068                     "'%s' has to be absent or the same as the "
11069                     "including/redefining schema's target namespace",
11070                     schemaLocation, NULL);
11071                 goto exit_error;
11072             }
11073             bucket->targetNamespace = pctxt->targetNamespace;
11074         }
11075     }
11076     /*
11077     * Parse the schema.
11078     */
11079     if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11080         if (isChameleon) {
11081             /* TODO: Get rid of this flag on the schema itself. */
11082             if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11083                 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11084             } else
11085                 wasChameleon = 1;
11086         }
11087         xmlSchemaParseNewDoc(pctxt, schema, bucket);
11088         /* Restore chameleon flag. */
11089         if (isChameleon && (!wasChameleon))
11090             schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11091     }
11092     /*
11093     * And now for the children...
11094     */
11095     child = node->children;
11096     if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11097         /*
11098         * Parse (simpleType | complexType | group | attributeGroup))*
11099         */
11100         pctxt->redefined = bucket;
11101         /*
11102         * How to proceed if the redefined schema was not located?
11103         */
11104         pctxt->isRedefine = 1;
11105         while (IS_SCHEMA(child, "annotation") ||
11106             IS_SCHEMA(child, "simpleType") ||
11107             IS_SCHEMA(child, "complexType") ||
11108             IS_SCHEMA(child, "group") ||
11109             IS_SCHEMA(child, "attributeGroup")) {
11110             if (IS_SCHEMA(child, "annotation")) {
11111                 /*
11112                 * TODO: discard or not?
11113                 */
11114             } else if (IS_SCHEMA(child, "simpleType")) {
11115                 xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11116             } else if (IS_SCHEMA(child, "complexType")) {
11117                 xmlSchemaParseComplexType(pctxt, schema, child, 1);
11118                 /* hasRedefinitions = 1; */
11119             } else if (IS_SCHEMA(child, "group")) {
11120                 /* hasRedefinitions = 1; */
11121                 xmlSchemaParseModelGroupDefinition(pctxt,
11122                     schema, child);
11123             } else if (IS_SCHEMA(child, "attributeGroup")) {
11124                 /* hasRedefinitions = 1; */
11125                 xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11126                     child);
11127             }
11128             child = child->next;
11129         }
11130         pctxt->redefined = NULL;
11131         pctxt->isRedefine = 0;
11132     } else {
11133         if (IS_SCHEMA(child, "annotation")) {
11134             /*
11135             * TODO: discard or not?
11136             */
11137             child = child->next;
11138         }
11139     }
11140     if (child != NULL) {
11141         res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
11142         if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11143             xmlSchemaPContentErr(pctxt, res,
11144                 NULL, node, child, NULL,
11145                 "(annotation | (simpleType | complexType | group | attributeGroup))*");
11146         } else {
11147              xmlSchemaPContentErr(pctxt, res,
11148                 NULL, node, child, NULL,
11149                 "(annotation?)");
11150         }
11151     }
11152     return(res);
11153
11154 exit_error:
11155     return(pctxt->err);
11156 }
11157
11158 static int
11159 xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11160                        xmlNodePtr node)
11161 {
11162     int res;
11163 #ifndef ENABLE_REDEFINE
11164     TODO
11165     return(0);
11166 #endif
11167     res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11168         XML_SCHEMA_SCHEMA_REDEFINE);
11169     if (res != 0)
11170         return(res);
11171     return(0);
11172 }
11173
11174 static int
11175 xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11176                        xmlNodePtr node)
11177 {
11178     int res;
11179
11180     res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11181         XML_SCHEMA_SCHEMA_INCLUDE);
11182     if (res != 0)
11183         return(res);
11184     return(0);
11185 }
11186
11187 /**
11188  * xmlSchemaParseModelGroup:
11189  * @ctxt:  a schema validation context
11190  * @schema:  the schema being built
11191  * @node:  a subtree containing XML Schema informations
11192  * @type: the "compositor" type
11193  * @particleNeeded: if a a model group with a particle
11194  *
11195  * parse a XML schema Sequence definition.
11196  * Applies parts of:
11197  *   Schema Representation Constraint:
11198  *     Redefinition Constraints and Semantics (src-redefine)
11199  *     (6.1), (6.1.1), (6.1.2)
11200  *
11201  *   Schema Component Constraint:
11202  *     All Group Limited (cos-all-limited) (2)
11203  *     TODO: Actually this should go to component-level checks,
11204  *     but is done here due to performance. Move it to an other layer
11205  *     is schema construction via an API is implemented.
11206  *
11207  * *WARNING* this interface is highly subject to change
11208  *
11209  * Returns -1 in case of error, 0 if the declaration is improper and
11210  *         1 in case of success.
11211  */
11212 static xmlSchemaTreeItemPtr
11213 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11214                          xmlNodePtr node, xmlSchemaTypeType type,
11215                          int withParticle)
11216 {
11217     xmlSchemaModelGroupPtr item;
11218     xmlSchemaParticlePtr particle = NULL;
11219     xmlNodePtr child = NULL;
11220     xmlAttrPtr attr;
11221     int min = 1, max = 1, isElemRef, hasRefs = 0;
11222
11223     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11224         return (NULL);
11225     /*
11226     * Create a model group with the given compositor.
11227     */
11228     item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
11229     if (item == NULL)
11230         return (NULL);
11231
11232     if (withParticle) {
11233         if (type == XML_SCHEMA_TYPE_ALL) {
11234             min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
11235             max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
11236         } else {
11237             /* choice + sequence */
11238             min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11239             max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11240                 "(xs:nonNegativeInteger | unbounded)");
11241         }
11242         xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11243         /*
11244         * Create a particle
11245         */
11246         particle = xmlSchemaAddParticle(ctxt, node, min, max);
11247         if (particle == NULL)
11248             return (NULL);
11249         particle->children = (xmlSchemaTreeItemPtr) item;
11250         /*
11251         * Check for illegal attributes.
11252         */
11253         attr = node->properties;
11254         while (attr != NULL) {
11255             if (attr->ns == NULL) {
11256                 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11257                     (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11258                     (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
11259                     xmlSchemaPIllegalAttrErr(ctxt,
11260                         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11261                 }
11262             } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11263                 xmlSchemaPIllegalAttrErr(ctxt,
11264                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11265             }
11266             attr = attr->next;
11267         }
11268     } else {
11269         /*
11270         * Check for illegal attributes.
11271         */
11272         attr = node->properties;
11273         while (attr != NULL) {
11274             if (attr->ns == NULL) {
11275                 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
11276                     xmlSchemaPIllegalAttrErr(ctxt,
11277                         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11278                 }
11279             } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11280                 xmlSchemaPIllegalAttrErr(ctxt,
11281                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11282             }
11283             attr = attr->next;
11284         }
11285     }
11286
11287     /*
11288     * Extract and validate attributes.
11289     */
11290     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11291     /*
11292     * And now for the children...
11293     */
11294     child = node->children;
11295     if (IS_SCHEMA(child, "annotation")) {
11296         item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
11297         child = child->next;
11298     }
11299     if (type == XML_SCHEMA_TYPE_ALL) {
11300         xmlSchemaParticlePtr part, last = NULL;
11301
11302         while (IS_SCHEMA(child, "element")) {
11303             part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
11304                 schema, child, &isElemRef, 0);
11305             /*
11306             * SPEC cos-all-limited (2)
11307             * "The {max occurs} of all the particles in the {particles}
11308             * of the ('all') group must be 0 or 1.
11309             */
11310             if (part != NULL) {
11311                 if (isElemRef)
11312                     hasRefs++;
11313                 if (part->minOccurs > 1) {
11314                     xmlSchemaPCustomErr(ctxt,
11315                         XML_SCHEMAP_COS_ALL_LIMITED,
11316                         NULL, child,
11317                         "Invalid value for minOccurs (must be 0 or 1)",
11318                         NULL);
11319                     /* Reset to 1. */
11320                     part->minOccurs = 1;
11321                 }
11322                 if (part->maxOccurs > 1) {
11323                     xmlSchemaPCustomErr(ctxt,
11324                         XML_SCHEMAP_COS_ALL_LIMITED,
11325                         NULL, child,
11326                         "Invalid value for maxOccurs (must be 0 or 1)",
11327                         NULL);
11328                     /* Reset to 1. */
11329                     part->maxOccurs = 1;
11330                 }
11331                 if (last == NULL)
11332                     item->children = (xmlSchemaTreeItemPtr) part;
11333                 else
11334                     last->next = (xmlSchemaTreeItemPtr) part;
11335                 last = part;
11336             }
11337             child = child->next;
11338         }
11339         if (child != NULL) {
11340             xmlSchemaPContentErr(ctxt,
11341                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11342                 NULL, node, child, NULL,
11343                 "(annotation?, (annotation?, element*)");
11344         }
11345     } else {
11346         /* choice + sequence */
11347         xmlSchemaTreeItemPtr part = NULL, last = NULL;
11348
11349         while ((IS_SCHEMA(child, "element")) ||
11350             (IS_SCHEMA(child, "group")) ||
11351             (IS_SCHEMA(child, "any")) ||
11352             (IS_SCHEMA(child, "choice")) ||
11353             (IS_SCHEMA(child, "sequence"))) {
11354
11355             if (IS_SCHEMA(child, "element")) {
11356                 part = (xmlSchemaTreeItemPtr)
11357                     xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11358                 if (part && isElemRef)
11359                     hasRefs++;
11360             } else if (IS_SCHEMA(child, "group")) {
11361                 part =
11362                     xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11363                 if (part != NULL)
11364                     hasRefs++;
11365                 /*
11366                 * Handle redefinitions.
11367                 */
11368                 if (ctxt->isRedefine && ctxt->redef &&
11369                     (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11370                     part && part->children)
11371                 {
11372                     if ((xmlSchemaGetQNameRefName(part->children) ==
11373                             ctxt->redef->refName) &&
11374                         (xmlSchemaGetQNameRefTargetNs(part->children) ==
11375                             ctxt->redef->refTargetNs))
11376                     {
11377                         /*
11378                         * SPEC src-redefine:
11379                         * (6.1) "If it has a <group> among its contents at
11380                         * some level the `actual value` of whose ref
11381                         * [attribute] is the same as the `actual value` of
11382                         * its own name attribute plus target namespace, then
11383                         * all of the following must be true:"
11384                         * (6.1.1) "It must have exactly one such group."
11385                         */
11386                         if (ctxt->redefCounter != 0) {
11387                             xmlChar *str = NULL;
11388
11389                             xmlSchemaCustomErr(ACTXT_CAST ctxt,
11390                                 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11391                                 "The redefining model group definition "
11392                                 "'%s' must not contain more than one "
11393                                 "reference to the redefined definition",
11394                                 xmlSchemaFormatQName(&str,
11395                                     ctxt->redef->refTargetNs,
11396                                     ctxt->redef->refName),
11397                                 NULL);
11398                             FREE_AND_NULL(str)
11399                             part = NULL;
11400                         } else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11401                             ((WXS_PARTICLE(part))->maxOccurs != 1))
11402                         {
11403                             xmlChar *str = NULL;
11404                             /*
11405                             * SPEC src-redefine:
11406                             * (6.1.2) "The `actual value` of both that
11407                             * group's minOccurs and maxOccurs [attribute]
11408                             * must be 1 (or `absent`).
11409                             */
11410                             xmlSchemaCustomErr(ACTXT_CAST ctxt,
11411                                 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11412                                 "The redefining model group definition "
11413                                 "'%s' must not contain a reference to the "
11414                                 "redefined definition with a "
11415                                 "maxOccurs/minOccurs other than 1",
11416                                 xmlSchemaFormatQName(&str,
11417                                     ctxt->redef->refTargetNs,
11418                                     ctxt->redef->refName),
11419                                 NULL);
11420                             FREE_AND_NULL(str)
11421                             part = NULL;
11422                         }
11423                         ctxt->redef->reference = WXS_BASIC_CAST part;
11424                         ctxt->redefCounter++;
11425                     }
11426                 }
11427             } else if (IS_SCHEMA(child, "any")) {
11428                 part = (xmlSchemaTreeItemPtr)
11429                     xmlSchemaParseAny(ctxt, schema, child);
11430             } else if (IS_SCHEMA(child, "choice")) {
11431                 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11432                     XML_SCHEMA_TYPE_CHOICE, 1);
11433             } else if (IS_SCHEMA(child, "sequence")) {
11434                 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11435                     XML_SCHEMA_TYPE_SEQUENCE, 1);
11436             }
11437             if (part != NULL) {
11438                 if (last == NULL)
11439                     item->children = part;
11440                 else
11441                     last->next = part;
11442                 last = part;
11443             }
11444             child = child->next;
11445         }
11446         if (child != NULL) {
11447             xmlSchemaPContentErr(ctxt,
11448                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11449                 NULL, node, child, NULL,
11450                 "(annotation?, (element | group | choice | sequence | any)*)");
11451         }
11452     }
11453     if ((max == 0) && (min == 0))
11454         return (NULL);
11455     if (hasRefs) {
11456         /*
11457         * We need to resolve references.
11458         */
11459         WXS_ADD_PENDING(ctxt, item);
11460     }
11461     if (withParticle)
11462         return ((xmlSchemaTreeItemPtr) particle);
11463     else
11464         return ((xmlSchemaTreeItemPtr) item);
11465 }
11466
11467 /**
11468  * xmlSchemaParseRestriction:
11469  * @ctxt:  a schema validation context
11470  * @schema:  the schema being built
11471  * @node:  a subtree containing XML Schema informations
11472  *
11473  * parse a XML schema Restriction definition
11474  * *WARNING* this interface is highly subject to change
11475  *
11476  * Returns the type definition or NULL in case of error
11477  */
11478 static xmlSchemaTypePtr
11479 xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11480                           xmlNodePtr node, xmlSchemaTypeType parentType)
11481 {
11482     xmlSchemaTypePtr type;
11483     xmlNodePtr child = NULL;
11484     xmlAttrPtr attr;
11485
11486     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11487         return (NULL);
11488     /* Not a component, don't create it. */
11489     type = ctxt->ctxtType;
11490     type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
11491
11492     /*
11493     * Check for illegal attributes.
11494     */
11495     attr = node->properties;
11496     while (attr != NULL) {
11497         if (attr->ns == NULL) {
11498             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11499                 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11500                 xmlSchemaPIllegalAttrErr(ctxt,
11501                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11502             }
11503         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11504             xmlSchemaPIllegalAttrErr(ctxt,
11505                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11506         }
11507         attr = attr->next;
11508     }
11509     /*
11510     * Extract and validate attributes.
11511     */
11512     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11513     /*
11514     * Attribute
11515     */
11516     /*
11517     * Extract the base type. The "base" attribute is mandatory if inside
11518     * a complex type or if redefining.
11519     *
11520     * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
11521     * among its [children]), the simple type definition which is
11522     * the {content type} of the type definition `resolved` to by
11523     * the `actual value` of the base [attribute]"
11524     */
11525     if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
11526         &(type->baseNs), &(type->base)) == 0)
11527     {
11528         if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11529             xmlSchemaPMissingAttrErr(ctxt,
11530                 XML_SCHEMAP_S4S_ATTR_MISSING,
11531                 NULL, node, "base", NULL);
11532         } else if ((ctxt->isRedefine) &&
11533             (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11534         {
11535             if (type->base == NULL) {
11536                 xmlSchemaPMissingAttrErr(ctxt,
11537                     XML_SCHEMAP_S4S_ATTR_MISSING,
11538                     NULL, node, "base", NULL);
11539             } else if ((! xmlStrEqual(type->base, type->name)) ||
11540                 (! xmlStrEqual(type->baseNs, type->targetNamespace)))
11541             {
11542                 xmlChar *str1 = NULL, *str2 = NULL;
11543                 /*
11544                 * REDEFINE: SPEC src-redefine (5)
11545                 * "Within the [children], each <simpleType> must have a
11546                 * <restriction> among its [children] ... the `actual value` of
11547                 * whose base [attribute] must be the same as the `actual value`
11548                 * of its own name attribute plus target namespace;"
11549                 */
11550                 xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
11551                     NULL, node, "This is a redefinition, but the QName "
11552                     "value '%s' of the 'base' attribute does not match the "
11553                     "type's designation '%s'",
11554                     xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11555                     xmlSchemaFormatQName(&str2, type->targetNamespace,
11556                         type->name), NULL);
11557                 FREE_AND_NULL(str1);
11558                 FREE_AND_NULL(str2);
11559                 /* Avoid confusion and erase the values. */
11560                 type->base = NULL;
11561                 type->baseNs = NULL;
11562             }
11563         }
11564     }
11565     /*
11566     * And now for the children...
11567     */
11568     child = node->children;
11569     if (IS_SCHEMA(child, "annotation")) {
11570         /*
11571         * Add the annotation to the simple type ancestor.
11572         */
11573         xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11574             xmlSchemaParseAnnotation(ctxt, child, 1));
11575         child = child->next;
11576     }
11577     if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11578         /*
11579         * Corresponds to <simpleType><restriction><simpleType>.
11580         */
11581         if (IS_SCHEMA(child, "simpleType")) {
11582             if (type->base != NULL) {
11583                 /*
11584                 * src-restriction-base-or-simpleType
11585                 * Either the base [attribute] or the simpleType [child] of the
11586                 * <restriction> element must be present, but not both.
11587                 */
11588                 xmlSchemaPContentErr(ctxt,
11589                     XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11590                     NULL, node, child,
11591                     "The attribute 'base' and the <simpleType> child are "
11592                     "mutually exclusive", NULL);
11593             } else {
11594                 type->baseType = (xmlSchemaTypePtr)
11595                     xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11596             }
11597             child = child->next;
11598         } else if (type->base == NULL) {
11599             xmlSchemaPContentErr(ctxt,
11600                 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11601                 NULL, node, child,
11602                 "Either the attribute 'base' or a <simpleType> child "
11603                 "must be present", NULL);
11604         }
11605     } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11606         /*
11607         * Corresponds to <complexType><complexContent><restriction>...
11608         * followed by:
11609         *
11610         * Model groups <all>, <choice> and <sequence>.
11611         */
11612         if (IS_SCHEMA(child, "all")) {
11613             type->subtypes = (xmlSchemaTypePtr)
11614                 xmlSchemaParseModelGroup(ctxt, schema, child,
11615                     XML_SCHEMA_TYPE_ALL, 1);
11616             child = child->next;
11617         } else if (IS_SCHEMA(child, "choice")) {
11618             type->subtypes = (xmlSchemaTypePtr)
11619                 xmlSchemaParseModelGroup(ctxt,
11620                     schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11621             child = child->next;
11622         } else if (IS_SCHEMA(child, "sequence")) {
11623             type->subtypes = (xmlSchemaTypePtr)
11624                 xmlSchemaParseModelGroup(ctxt, schema, child,
11625                     XML_SCHEMA_TYPE_SEQUENCE, 1);
11626             child = child->next;
11627         /*
11628         * Model group reference <group>.
11629         */
11630         } else if (IS_SCHEMA(child, "group")) {
11631             type->subtypes = (xmlSchemaTypePtr)
11632                 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11633             /*
11634             * Note that the reference will be resolved in
11635             * xmlSchemaResolveTypeReferences();
11636             */
11637             child = child->next;
11638         }
11639     } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11640         /*
11641         * Corresponds to <complexType><simpleContent><restriction>...
11642         *
11643         * "1.1 the simple type definition corresponding to the <simpleType>
11644         * among the [children] of <restriction> if there is one;"
11645         */
11646         if (IS_SCHEMA(child, "simpleType")) {
11647             /*
11648             * We will store the to-be-restricted simple type in
11649             * type->contentTypeDef *temporarily*.
11650             */
11651             type->contentTypeDef = (xmlSchemaTypePtr)
11652                 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11653             if ( type->contentTypeDef == NULL)
11654                 return (NULL);
11655             child = child->next;
11656         }
11657     }
11658
11659     if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
11660         (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
11661         xmlSchemaFacetPtr facet, lastfacet = NULL;
11662         /*
11663         * Corresponds to <complexType><simpleContent><restriction>...
11664         * <simpleType><restriction>...
11665         */
11666
11667         /*
11668         * Add the facets to the simple type ancestor.
11669         */
11670         /*
11671         * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11672         * Simple Type Definition Schema Representation Constraint:
11673         * *Single Facet Value*
11674         */
11675         while ((IS_SCHEMA(child, "minInclusive")) ||
11676             (IS_SCHEMA(child, "minExclusive")) ||
11677             (IS_SCHEMA(child, "maxInclusive")) ||
11678             (IS_SCHEMA(child, "maxExclusive")) ||
11679             (IS_SCHEMA(child, "totalDigits")) ||
11680             (IS_SCHEMA(child, "fractionDigits")) ||
11681             (IS_SCHEMA(child, "pattern")) ||
11682             (IS_SCHEMA(child, "enumeration")) ||
11683             (IS_SCHEMA(child, "whiteSpace")) ||
11684             (IS_SCHEMA(child, "length")) ||
11685             (IS_SCHEMA(child, "maxLength")) ||
11686             (IS_SCHEMA(child, "minLength"))) {
11687             facet = xmlSchemaParseFacet(ctxt, schema, child);
11688             if (facet != NULL) {
11689                 if (lastfacet == NULL)
11690                     type->facets = facet;
11691                 else
11692                     lastfacet->next = facet;
11693                 lastfacet = facet;
11694                 lastfacet->next = NULL;
11695             }
11696             child = child->next;
11697         }
11698         /*
11699         * Create links for derivation and validation.
11700         */
11701         if (type->facets != NULL) {
11702             xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11703
11704             facet = type->facets;
11705             do {
11706                 facetLink = (xmlSchemaFacetLinkPtr)
11707                     xmlMalloc(sizeof(xmlSchemaFacetLink));
11708                 if (facetLink == NULL) {
11709                     xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
11710                     xmlFree(facetLink);
11711                     return (NULL);
11712                 }
11713                 facetLink->facet = facet;
11714                 facetLink->next = NULL;
11715                 if (lastFacetLink == NULL)
11716                     type->facetSet = facetLink;
11717                 else
11718                     lastFacetLink->next = facetLink;
11719                 lastFacetLink = facetLink;
11720                 facet = facet->next;
11721             } while (facet != NULL);
11722         }
11723     }
11724     if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11725         /*
11726         * Attribute uses/declarations.
11727         */
11728         if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11729             (xmlSchemaItemListPtr *) &(type->attrUses),
11730             XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11731             return(NULL);
11732         /*
11733         * Attribute wildcard.
11734         */
11735         if (IS_SCHEMA(child, "anyAttribute")) {
11736             type->attributeWildcard =
11737                 xmlSchemaParseAnyAttribute(ctxt, schema, child);
11738             child = child->next;
11739         }
11740     }
11741     if (child != NULL) {
11742         if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11743             xmlSchemaPContentErr(ctxt,
11744                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11745                 NULL, node, child, NULL,
11746                 "annotation?, (group | all | choice | sequence)?, "
11747                 "((attribute | attributeGroup)*, anyAttribute?))");
11748         } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11749              xmlSchemaPContentErr(ctxt,
11750                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11751                 NULL, node, child, NULL,
11752                 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11753                 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11754                 "length | minLength | maxLength | enumeration | whiteSpace | "
11755                 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11756         } else {
11757             /* Simple type */
11758             xmlSchemaPContentErr(ctxt,
11759                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11760                 NULL, node, child, NULL,
11761                 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11762                 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11763                 "length | minLength | maxLength | enumeration | whiteSpace | "
11764                 "pattern)*))");
11765         }
11766     }
11767     return (NULL);
11768 }
11769
11770 /**
11771  * xmlSchemaParseExtension:
11772  * @ctxt:  a schema validation context
11773  * @schema:  the schema being built
11774  * @node:  a subtree containing XML Schema informations
11775  *
11776  * Parses an <extension>, which is found inside a
11777  * <simpleContent> or <complexContent>.
11778  * *WARNING* this interface is highly subject to change.
11779  *
11780  * TODO: Returns the type definition or NULL in case of error
11781  */
11782 static xmlSchemaTypePtr
11783 xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11784                         xmlNodePtr node, xmlSchemaTypeType parentType)
11785 {
11786     xmlSchemaTypePtr type;
11787     xmlNodePtr child = NULL;
11788     xmlAttrPtr attr;
11789
11790     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11791         return (NULL);
11792     /* Not a component, don't create it. */
11793     type = ctxt->ctxtType;
11794     type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
11795
11796     /*
11797     * Check for illegal attributes.
11798     */
11799     attr = node->properties;
11800     while (attr != NULL) {
11801         if (attr->ns == NULL) {
11802             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11803                 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11804                 xmlSchemaPIllegalAttrErr(ctxt,
11805                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11806             }
11807         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11808             xmlSchemaPIllegalAttrErr(ctxt,
11809                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11810         }
11811         attr = attr->next;
11812     }
11813
11814     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11815
11816     /*
11817     * Attribute "base" - mandatory.
11818     */
11819     if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11820         "base", &(type->baseNs), &(type->base)) == 0) &&
11821         (type->base == NULL)) {
11822         xmlSchemaPMissingAttrErr(ctxt,
11823             XML_SCHEMAP_S4S_ATTR_MISSING,
11824             NULL, node, "base", NULL);
11825     }
11826     /*
11827     * And now for the children...
11828     */
11829     child = node->children;
11830     if (IS_SCHEMA(child, "annotation")) {
11831         /*
11832         * Add the annotation to the type ancestor.
11833         */
11834         xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11835             xmlSchemaParseAnnotation(ctxt, child, 1));
11836         child = child->next;
11837     }
11838     if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11839         /*
11840         * Corresponds to <complexType><complexContent><extension>... and:
11841         *
11842         * Model groups <all>, <choice>, <sequence> and <group>.
11843         */
11844         if (IS_SCHEMA(child, "all")) {
11845             type->subtypes = (xmlSchemaTypePtr)
11846                 xmlSchemaParseModelGroup(ctxt, schema,
11847                     child, XML_SCHEMA_TYPE_ALL, 1);
11848             child = child->next;
11849         } else if (IS_SCHEMA(child, "choice")) {
11850             type->subtypes = (xmlSchemaTypePtr)
11851                 xmlSchemaParseModelGroup(ctxt, schema,
11852                     child, XML_SCHEMA_TYPE_CHOICE, 1);
11853             child = child->next;
11854         } else if (IS_SCHEMA(child, "sequence")) {
11855             type->subtypes = (xmlSchemaTypePtr)
11856                 xmlSchemaParseModelGroup(ctxt, schema,
11857                 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11858             child = child->next;
11859         } else if (IS_SCHEMA(child, "group")) {
11860             type->subtypes = (xmlSchemaTypePtr)
11861                 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11862             /*
11863             * Note that the reference will be resolved in
11864             * xmlSchemaResolveTypeReferences();
11865             */
11866             child = child->next;
11867         }
11868     }
11869     if (child != NULL) {
11870         /*
11871         * Attribute uses/declarations.
11872         */
11873         if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11874             (xmlSchemaItemListPtr *) &(type->attrUses),
11875             XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11876             return(NULL);
11877         /*
11878         * Attribute wildcard.
11879         */
11880         if (IS_SCHEMA(child, "anyAttribute")) {
11881             ctxt->ctxtType->attributeWildcard =
11882                 xmlSchemaParseAnyAttribute(ctxt, schema, child);
11883             child = child->next;
11884         }
11885     }
11886     if (child != NULL) {
11887         if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11888             /* Complex content extension. */
11889             xmlSchemaPContentErr(ctxt,
11890                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11891                 NULL, node, child, NULL,
11892                 "(annotation?, ((group | all | choice | sequence)?, "
11893                 "((attribute | attributeGroup)*, anyAttribute?)))");
11894         } else {
11895             /* Simple content extension. */
11896             xmlSchemaPContentErr(ctxt,
11897                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11898                 NULL, node, child, NULL,
11899                 "(annotation?, ((attribute | attributeGroup)*, "
11900                 "anyAttribute?))");
11901         }
11902     }
11903     return (NULL);
11904 }
11905
11906 /**
11907  * xmlSchemaParseSimpleContent:
11908  * @ctxt:  a schema validation context
11909  * @schema:  the schema being built
11910  * @node:  a subtree containing XML Schema informations
11911  *
11912  * parse a XML schema SimpleContent definition
11913  * *WARNING* this interface is highly subject to change
11914  *
11915  * Returns the type definition or NULL in case of error
11916  */
11917 static int
11918 xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
11919                             xmlSchemaPtr schema, xmlNodePtr node,
11920                             int *hasRestrictionOrExtension)
11921 {
11922     xmlSchemaTypePtr type;
11923     xmlNodePtr child = NULL;
11924     xmlAttrPtr attr;
11925
11926     if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11927         (hasRestrictionOrExtension == NULL))
11928         return (-1);
11929     *hasRestrictionOrExtension = 0;
11930     /* Not a component, don't create it. */
11931     type = ctxt->ctxtType;
11932     type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11933     /*
11934     * Check for illegal attributes.
11935     */
11936     attr = node->properties;
11937     while (attr != NULL) {
11938         if (attr->ns == NULL) {
11939             if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
11940                 xmlSchemaPIllegalAttrErr(ctxt,
11941                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11942             }
11943         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11944             xmlSchemaPIllegalAttrErr(ctxt,
11945                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11946         }
11947         attr = attr->next;
11948     }
11949
11950     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11951
11952     /*
11953     * And now for the children...
11954     */
11955     child = node->children;
11956     if (IS_SCHEMA(child, "annotation")) {
11957         /*
11958         * Add the annotation to the complex type ancestor.
11959         */
11960         xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11961             xmlSchemaParseAnnotation(ctxt, child, 1));
11962         child = child->next;
11963     }
11964     if (child == NULL) {
11965         xmlSchemaPContentErr(ctxt,
11966             XML_SCHEMAP_S4S_ELEM_MISSING,
11967             NULL, node, NULL, NULL,
11968             "(annotation?, (restriction | extension))");
11969     }
11970     if (child == NULL) {
11971         xmlSchemaPContentErr(ctxt,
11972             XML_SCHEMAP_S4S_ELEM_MISSING,
11973             NULL, node, NULL, NULL,
11974             "(annotation?, (restriction | extension))");
11975     }
11976     if (IS_SCHEMA(child, "restriction")) {
11977         xmlSchemaParseRestriction(ctxt, schema, child,
11978             XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11979         (*hasRestrictionOrExtension) = 1;
11980         child = child->next;
11981     } else if (IS_SCHEMA(child, "extension")) {
11982         xmlSchemaParseExtension(ctxt, schema, child,
11983             XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11984         (*hasRestrictionOrExtension) = 1;
11985         child = child->next;
11986     }
11987     if (child != NULL) {
11988         xmlSchemaPContentErr(ctxt,
11989             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11990             NULL, node, child, NULL,
11991             "(annotation?, (restriction | extension))");
11992     }
11993     return (0);
11994 }
11995
11996 /**
11997  * xmlSchemaParseComplexContent:
11998  * @ctxt:  a schema validation context
11999  * @schema:  the schema being built
12000  * @node:  a subtree containing XML Schema informations
12001  *
12002  * parse a XML schema ComplexContent definition
12003  * *WARNING* this interface is highly subject to change
12004  *
12005  * Returns the type definition or NULL in case of error
12006  */
12007 static int
12008 xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
12009                              xmlSchemaPtr schema, xmlNodePtr node,
12010                              int *hasRestrictionOrExtension)
12011 {
12012     xmlSchemaTypePtr type;
12013     xmlNodePtr child = NULL;
12014     xmlAttrPtr attr;
12015
12016     if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
12017         (hasRestrictionOrExtension == NULL))
12018         return (-1);
12019     *hasRestrictionOrExtension = 0;
12020     /* Not a component, don't create it. */
12021     type = ctxt->ctxtType;
12022     /*
12023     * Check for illegal attributes.
12024     */
12025     attr = node->properties;
12026     while (attr != NULL) {
12027         if (attr->ns == NULL) {
12028             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
12029                 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
12030             {
12031                 xmlSchemaPIllegalAttrErr(ctxt,
12032                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12033             }
12034         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12035             xmlSchemaPIllegalAttrErr(ctxt,
12036                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12037         }
12038         attr = attr->next;
12039     }
12040
12041     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12042
12043     /*
12044     * Set the 'mixed' on the complex type ancestor.
12045     */
12046     if (xmlGetBooleanProp(ctxt, node, "mixed", 0))  {
12047         if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
12048             type->flags |= XML_SCHEMAS_TYPE_MIXED;
12049     }
12050     child = node->children;
12051     if (IS_SCHEMA(child, "annotation")) {
12052         /*
12053         * Add the annotation to the complex type ancestor.
12054         */
12055         xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12056             xmlSchemaParseAnnotation(ctxt, child, 1));
12057         child = child->next;
12058     }
12059     if (child == NULL) {
12060         xmlSchemaPContentErr(ctxt,
12061             XML_SCHEMAP_S4S_ELEM_MISSING,
12062             NULL, node, NULL,
12063             NULL, "(annotation?, (restriction | extension))");
12064     }
12065     if (child == NULL) {
12066         xmlSchemaPContentErr(ctxt,
12067             XML_SCHEMAP_S4S_ELEM_MISSING,
12068             NULL, node, NULL,
12069             NULL, "(annotation?, (restriction | extension))");
12070     }
12071     if (IS_SCHEMA(child, "restriction")) {
12072         xmlSchemaParseRestriction(ctxt, schema, child,
12073             XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12074         (*hasRestrictionOrExtension) = 1;
12075         child = child->next;
12076     } else if (IS_SCHEMA(child, "extension")) {
12077         xmlSchemaParseExtension(ctxt, schema, child,
12078             XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12079         (*hasRestrictionOrExtension) = 1;
12080         child = child->next;
12081     }
12082     if (child != NULL) {
12083         xmlSchemaPContentErr(ctxt,
12084             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12085             NULL, node, child,
12086             NULL, "(annotation?, (restriction | extension))");
12087     }
12088     return (0);
12089 }
12090
12091 /**
12092  * xmlSchemaParseComplexType:
12093  * @ctxt:  a schema validation context
12094  * @schema:  the schema being built
12095  * @node:  a subtree containing XML Schema informations
12096  *
12097  * parse a XML schema Complex Type definition
12098  * *WARNING* this interface is highly subject to change
12099  *
12100  * Returns the type definition or NULL in case of error
12101  */
12102 static xmlSchemaTypePtr
12103 xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
12104                           xmlNodePtr node, int topLevel)
12105 {
12106     xmlSchemaTypePtr type, ctxtType;
12107     xmlNodePtr child = NULL;
12108     const xmlChar *name = NULL;
12109     xmlAttrPtr attr;
12110     const xmlChar *attrValue;
12111 #ifdef ENABLE_NAMED_LOCALS
12112     char buf[40];
12113 #endif
12114     int final = 0, block = 0, hasRestrictionOrExtension = 0;
12115
12116
12117     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12118         return (NULL);
12119
12120     ctxtType = ctxt->ctxtType;
12121
12122     if (topLevel) {
12123         attr = xmlSchemaGetPropNode(node, "name");
12124         if (attr == NULL) {
12125             xmlSchemaPMissingAttrErr(ctxt,
12126                 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
12127             return (NULL);
12128         } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
12129             xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12130             return (NULL);
12131         }
12132     }
12133
12134     if (topLevel == 0) {
12135         /*
12136         * Parse as local complex type definition.
12137         */
12138 #ifdef ENABLE_NAMED_LOCALS
12139         snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
12140         type = xmlSchemaAddType(ctxt, schema,
12141             XML_SCHEMA_TYPE_COMPLEX,
12142             xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
12143             ctxt->targetNamespace, node, 0);
12144 #else
12145         type = xmlSchemaAddType(ctxt, schema,
12146             XML_SCHEMA_TYPE_COMPLEX,
12147             NULL, ctxt->targetNamespace, node, 0);
12148 #endif
12149         if (type == NULL)
12150             return (NULL);
12151         name = type->name;
12152         type->node = node;
12153         type->type = XML_SCHEMA_TYPE_COMPLEX;
12154         /*
12155         * TODO: We need the target namespace.
12156         */
12157     } else {
12158         /*
12159         * Parse as global complex type definition.
12160         */
12161         type = xmlSchemaAddType(ctxt, schema,
12162             XML_SCHEMA_TYPE_COMPLEX,
12163             name, ctxt->targetNamespace, node, 1);
12164         if (type == NULL)
12165             return (NULL);
12166         type->node = node;
12167         type->type = XML_SCHEMA_TYPE_COMPLEX;
12168         type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
12169     }
12170     type->targetNamespace = ctxt->targetNamespace;
12171     /*
12172     * Handle attributes.
12173     */
12174     attr = node->properties;
12175     while (attr != NULL) {
12176         if (attr->ns == NULL) {
12177             if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12178                 /*
12179                 * Attribute "id".
12180                 */
12181                 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12182             } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12183                 /*
12184                 * Attribute "mixed".
12185                 */
12186                 if (xmlSchemaPGetBoolNodeValue(ctxt,
12187                         NULL, (xmlNodePtr) attr))
12188                     type->flags |= XML_SCHEMAS_TYPE_MIXED;
12189             } else if (topLevel) {
12190                 /*
12191                 * Attributes of global complex type definitions.
12192                 */
12193                 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12194                     /* Pass. */
12195                 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12196                     /*
12197                     * Attribute "abstract".
12198                     */
12199                     if (xmlSchemaPGetBoolNodeValue(ctxt,
12200                             NULL, (xmlNodePtr) attr))
12201                         type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12202                 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12203                     /*
12204                     * Attribute "final".
12205                     */
12206                     attrValue = xmlSchemaGetNodeContent(ctxt,
12207                         (xmlNodePtr) attr);
12208                     if (xmlSchemaPValAttrBlockFinal(attrValue,
12209                         &(type->flags),
12210                         -1,
12211                         XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12212                         XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12213                         -1, -1, -1) != 0)
12214                     {
12215                         xmlSchemaPSimpleTypeErr(ctxt,
12216                             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12217                             NULL, (xmlNodePtr) attr, NULL,
12218                             "(#all | List of (extension | restriction))",
12219                             attrValue, NULL, NULL, NULL);
12220                     } else
12221                         final = 1;
12222                 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12223                     /*
12224                     * Attribute "block".
12225                     */
12226                     attrValue = xmlSchemaGetNodeContent(ctxt,
12227                         (xmlNodePtr) attr);
12228                     if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
12229                         -1,
12230                         XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
12231                         XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
12232                         -1, -1, -1) != 0) {
12233                         xmlSchemaPSimpleTypeErr(ctxt,
12234                             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12235                             NULL, (xmlNodePtr) attr, NULL,
12236                             "(#all | List of (extension | restriction)) ",
12237                             attrValue, NULL, NULL, NULL);
12238                     } else
12239                         block = 1;
12240                 } else {
12241                         xmlSchemaPIllegalAttrErr(ctxt,
12242                             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12243                 }
12244             } else {
12245                 xmlSchemaPIllegalAttrErr(ctxt,
12246                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12247             }
12248         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12249             xmlSchemaPIllegalAttrErr(ctxt,
12250                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12251         }
12252         attr = attr->next;
12253     }
12254     if (! block) {
12255         /*
12256         * Apply default "block" values.
12257         */
12258         if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12259             type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12260         if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12261             type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12262     }
12263     if (! final) {
12264         /*
12265         * Apply default "block" values.
12266         */
12267         if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12268             type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12269         if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12270             type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12271     }
12272     /*
12273     * And now for the children...
12274     */
12275     child = node->children;
12276     if (IS_SCHEMA(child, "annotation")) {
12277         type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
12278         child = child->next;
12279     }
12280     ctxt->ctxtType = type;
12281     if (IS_SCHEMA(child, "simpleContent")) {
12282         /*
12283         * <complexType><simpleContent>...
12284         * 3.4.3 : 2.2
12285         * Specifying mixed='true' when the <simpleContent>
12286         * alternative is chosen has no effect
12287         */
12288         if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12289             type->flags ^= XML_SCHEMAS_TYPE_MIXED;
12290         xmlSchemaParseSimpleContent(ctxt, schema, child,
12291             &hasRestrictionOrExtension);
12292         child = child->next;
12293     } else if (IS_SCHEMA(child, "complexContent")) {
12294         /*
12295         * <complexType><complexContent>...
12296         */
12297         type->contentType = XML_SCHEMA_CONTENT_EMPTY;
12298         xmlSchemaParseComplexContent(ctxt, schema, child,
12299             &hasRestrictionOrExtension);
12300         child = child->next;
12301     } else {
12302         /*
12303         * E.g <complexType><sequence>... or <complexType><attribute>... etc.
12304         *
12305         * SPEC
12306         * "...the third alternative (neither <simpleContent> nor
12307         * <complexContent>) is chosen. This case is understood as shorthand
12308         * for complex content restricting the `ur-type definition`, and the
12309         * details of the mappings should be modified as necessary.
12310         */
12311         type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12312         type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
12313         /*
12314         * Parse model groups.
12315         */
12316         if (IS_SCHEMA(child, "all")) {
12317             type->subtypes = (xmlSchemaTypePtr)
12318                 xmlSchemaParseModelGroup(ctxt, schema, child,
12319                     XML_SCHEMA_TYPE_ALL, 1);
12320             child = child->next;
12321         } else if (IS_SCHEMA(child, "choice")) {
12322             type->subtypes = (xmlSchemaTypePtr)
12323                 xmlSchemaParseModelGroup(ctxt, schema, child,
12324                     XML_SCHEMA_TYPE_CHOICE, 1);
12325             child = child->next;
12326         } else if (IS_SCHEMA(child, "sequence")) {
12327             type->subtypes = (xmlSchemaTypePtr)
12328                 xmlSchemaParseModelGroup(ctxt, schema, child,
12329                     XML_SCHEMA_TYPE_SEQUENCE, 1);
12330             child = child->next;
12331         } else if (IS_SCHEMA(child, "group")) {
12332             type->subtypes = (xmlSchemaTypePtr)
12333                 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
12334             /*
12335             * Note that the reference will be resolved in
12336             * xmlSchemaResolveTypeReferences();
12337             */
12338             child = child->next;
12339         }
12340         /*
12341         * Parse attribute decls/refs.
12342         */
12343         if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12344             (xmlSchemaItemListPtr *) &(type->attrUses),
12345             XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12346             return(NULL);
12347         /*
12348         * Parse attribute wildcard.
12349         */
12350         if (IS_SCHEMA(child, "anyAttribute")) {
12351             type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12352             child = child->next;
12353         }
12354     }
12355     if (child != NULL) {
12356         xmlSchemaPContentErr(ctxt,
12357             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12358             NULL, node, child,
12359             NULL, "(annotation?, (simpleContent | complexContent | "
12360             "((group | all | choice | sequence)?, ((attribute | "
12361             "attributeGroup)*, anyAttribute?))))");
12362     }
12363     /*
12364     * REDEFINE: SPEC src-redefine (5)
12365     */
12366     if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12367         xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
12368             NULL, node, "This is a redefinition, thus the "
12369             "<complexType> must have a <restriction> or <extension> "
12370             "grand-child", NULL);
12371     }
12372     ctxt->ctxtType = ctxtType;
12373     return (type);
12374 }
12375
12376 /************************************************************************
12377  *                                                                      *
12378  *                      Validating using Schemas                        *
12379  *                                                                      *
12380  ************************************************************************/
12381
12382 /************************************************************************
12383  *                                                                      *
12384  *                      Reading/Writing Schemas                         *
12385  *                                                                      *
12386  ************************************************************************/
12387
12388 #if 0 /* Will be enabled if it is clear what options are needed. */
12389 /**
12390  * xmlSchemaParserCtxtSetOptions:
12391  * @ctxt:       a schema parser context
12392  * @options: a combination of xmlSchemaParserOption
12393  *
12394  * Sets the options to be used during the parse.
12395  *
12396  * Returns 0 in case of success, -1 in case of an
12397  * API error.
12398  */
12399 static int
12400 xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12401                               int options)
12402
12403 {
12404     int i;
12405
12406     if (ctxt == NULL)
12407         return (-1);
12408     /*
12409     * WARNING: Change the start value if adding to the
12410     * xmlSchemaParseOption.
12411     */
12412     for (i = 1; i < (int) sizeof(int) * 8; i++) {
12413         if (options & 1<<i) {
12414             return (-1);
12415         }
12416     }
12417     ctxt->options = options;
12418     return (0);
12419 }
12420
12421 /**
12422  * xmlSchemaValidCtxtGetOptions:
12423  * @ctxt: a schema parser context
12424  *
12425  * Returns the option combination of the parser context.
12426  */
12427 static int
12428 xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
12429
12430 {
12431     if (ctxt == NULL)
12432         return (-1);
12433     else
12434         return (ctxt->options);
12435 }
12436 #endif
12437
12438 /**
12439  * xmlSchemaNewParserCtxt:
12440  * @URL:  the location of the schema
12441  *
12442  * Create an XML Schemas parse context for that file/resource expected
12443  * to contain an XML Schemas file.
12444  *
12445  * Returns the parser context or NULL in case of error
12446  */
12447 xmlSchemaParserCtxtPtr
12448 xmlSchemaNewParserCtxt(const char *URL)
12449 {
12450     xmlSchemaParserCtxtPtr ret;
12451
12452     if (URL == NULL)
12453         return (NULL);
12454
12455     ret = xmlSchemaParserCtxtCreate();
12456     if (ret == NULL)
12457         return(NULL);
12458     ret->dict = xmlDictCreate();
12459     ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
12460     return (ret);
12461 }
12462
12463 /**
12464  * xmlSchemaNewMemParserCtxt:
12465  * @buffer:  a pointer to a char array containing the schemas
12466  * @size:  the size of the array
12467  *
12468  * Create an XML Schemas parse context for that memory buffer expected
12469  * to contain an XML Schemas file.
12470  *
12471  * Returns the parser context or NULL in case of error
12472  */
12473 xmlSchemaParserCtxtPtr
12474 xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12475 {
12476     xmlSchemaParserCtxtPtr ret;
12477
12478     if ((buffer == NULL) || (size <= 0))
12479         return (NULL);
12480     ret = xmlSchemaParserCtxtCreate();
12481     if (ret == NULL)
12482         return(NULL);
12483     ret->buffer = buffer;
12484     ret->size = size;
12485     ret->dict = xmlDictCreate();
12486     return (ret);
12487 }
12488
12489 /**
12490  * xmlSchemaNewDocParserCtxt:
12491  * @doc:  a preparsed document tree
12492  *
12493  * Create an XML Schemas parse context for that document.
12494  * NB. The document may be modified during the parsing process.
12495  *
12496  * Returns the parser context or NULL in case of error
12497  */
12498 xmlSchemaParserCtxtPtr
12499 xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12500 {
12501     xmlSchemaParserCtxtPtr ret;
12502
12503     if (doc == NULL)
12504       return (NULL);
12505     ret = xmlSchemaParserCtxtCreate();
12506     if (ret == NULL)
12507         return(NULL);
12508     ret->doc = doc;
12509     ret->dict = xmlDictCreate();
12510     /* The application has responsibility for the document */
12511     ret->preserve = 1;
12512
12513     return (ret);
12514 }
12515
12516 /**
12517  * xmlSchemaFreeParserCtxt:
12518  * @ctxt:  the schema parser context
12519  *
12520  * Free the resources associated to the schema parser context
12521  */
12522 void
12523 xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12524 {
12525     if (ctxt == NULL)
12526         return;
12527     if (ctxt->doc != NULL && !ctxt->preserve)
12528         xmlFreeDoc(ctxt->doc);
12529     if (ctxt->vctxt != NULL) {
12530         xmlSchemaFreeValidCtxt(ctxt->vctxt);
12531     }
12532     if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12533         xmlSchemaConstructionCtxtFree(ctxt->constructor);
12534         ctxt->constructor = NULL;
12535         ctxt->ownsConstructor = 0;
12536     }
12537     if (ctxt->attrProhibs != NULL)
12538         xmlSchemaItemListFree(ctxt->attrProhibs);
12539     xmlDictFree(ctxt->dict);
12540     xmlFree(ctxt);
12541 }
12542
12543 /************************************************************************
12544  *                                                                      *
12545  *                      Building the content models                     *
12546  *                                                                      *
12547  ************************************************************************/
12548
12549 /**
12550  * xmlSchemaBuildContentModelForSubstGroup:
12551  *
12552  * Returns 1 if nillable, 0 otherwise
12553  */
12554 static int
12555 xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
12556         xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
12557 {
12558     xmlAutomataStatePtr start, tmp;
12559     xmlSchemaElementPtr elemDecl, member;
12560     xmlSchemaSubstGroupPtr substGroup;
12561     int i;
12562     int ret = 0;
12563
12564     elemDecl = (xmlSchemaElementPtr) particle->children;
12565     /*
12566     * Wrap the substitution group with a CHOICE.
12567     */
12568     start = pctxt->state;
12569     if (end == NULL)
12570         end = xmlAutomataNewState(pctxt->am);
12571     substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
12572     if (substGroup == NULL) {
12573         xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
12574             XML_SCHEMAP_INTERNAL,
12575             "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12576             "declaration is marked having a subst. group but none "
12577             "available.\n", elemDecl->name, NULL);
12578         return(0);
12579     }
12580     if (counter >= 0) {
12581         /*
12582         * NOTE that we put the declaration in, even if it's abstract.
12583         * However, an error will be raised during *validation* if an element
12584         * information item shall be validated against an abstract element
12585         * declaration.
12586         */
12587         tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12588         xmlAutomataNewTransition2(pctxt->am, tmp, end,
12589                     elemDecl->name, elemDecl->targetNamespace, elemDecl);
12590         /*
12591         * Add subst. group members.
12592         */
12593         for (i = 0; i < substGroup->members->nbItems; i++) {
12594             member = (xmlSchemaElementPtr) substGroup->members->items[i];
12595             xmlAutomataNewTransition2(pctxt->am, tmp, end,
12596                                member->name, member->targetNamespace, member);
12597         }
12598     } else if (particle->maxOccurs == 1) {
12599         /*
12600         * NOTE that we put the declaration in, even if it's abstract,
12601         */
12602         xmlAutomataNewEpsilon(pctxt->am,
12603             xmlAutomataNewTransition2(pctxt->am,
12604             start, NULL,
12605             elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12606         /*
12607         * Add subst. group members.
12608         */
12609         for (i = 0; i < substGroup->members->nbItems; i++) {
12610             member = (xmlSchemaElementPtr) substGroup->members->items[i];
12611             /*
12612             * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2()
12613             *  was incorrectly used instead of xmlAutomataNewTransition2()
12614             *  (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL
12615             *  section in xmlSchemaBuildAContentModel() ).
12616             * TODO: Check if xmlAutomataNewOnceTrans2() was instead
12617             *  intended for the above "counter" section originally. I.e.,
12618             *  check xs:all with subst-groups.
12619             *
12620             * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12621             *                  member->name, member->targetNamespace,
12622             *                  1, 1, member);
12623             */
12624             tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL,
12625                 member->name, member->targetNamespace, member);
12626             xmlAutomataNewEpsilon(pctxt->am, tmp, end);
12627         }
12628     } else {
12629         xmlAutomataStatePtr hop;
12630         int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12631             UNBOUNDED : particle->maxOccurs - 1;
12632         int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12633
12634         counter =
12635             xmlAutomataNewCounter(pctxt->am, minOccurs,
12636             maxOccurs);
12637         hop = xmlAutomataNewState(pctxt->am);
12638
12639         xmlAutomataNewEpsilon(pctxt->am,
12640             xmlAutomataNewTransition2(pctxt->am,
12641             start, NULL,
12642             elemDecl->name, elemDecl->targetNamespace, elemDecl),
12643             hop);
12644         /*
12645          * Add subst. group members.
12646          */
12647         for (i = 0; i < substGroup->members->nbItems; i++) {
12648             member = (xmlSchemaElementPtr) substGroup->members->items[i];
12649             xmlAutomataNewEpsilon(pctxt->am,
12650                 xmlAutomataNewTransition2(pctxt->am,
12651                 start, NULL,
12652                 member->name, member->targetNamespace, member),
12653                 hop);
12654         }
12655         xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12656         xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12657     }
12658     if (particle->minOccurs == 0) {
12659         xmlAutomataNewEpsilon(pctxt->am, start, end);
12660         ret = 1;
12661     }
12662     pctxt->state = end;
12663     return(ret);
12664 }
12665
12666 /**
12667  * xmlSchemaBuildContentModelForElement:
12668  *
12669  * Returns 1 if nillable, 0 otherwise
12670  */
12671 static int
12672 xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12673                                      xmlSchemaParticlePtr particle)
12674 {
12675     int ret = 0;
12676
12677     if (((xmlSchemaElementPtr) particle->children)->flags &
12678         XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12679         /*
12680         * Substitution groups.
12681         */
12682         ret = xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
12683     } else {
12684         xmlSchemaElementPtr elemDecl;
12685         xmlAutomataStatePtr start;
12686
12687         elemDecl = (xmlSchemaElementPtr) particle->children;
12688
12689         if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
12690             return(0);
12691         if (particle->maxOccurs == 1) {
12692             start = ctxt->state;
12693             ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12694                     elemDecl->name, elemDecl->targetNamespace, elemDecl);
12695         } else if ((particle->maxOccurs >= UNBOUNDED) &&
12696                    (particle->minOccurs < 2)) {
12697             /* Special case. */
12698             start = ctxt->state;
12699             ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12700                 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12701             ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
12702                 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12703         } else {
12704             int counter;
12705             int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12706                             UNBOUNDED : particle->maxOccurs - 1;
12707             int minOccurs = particle->minOccurs < 1 ?
12708                             0 : particle->minOccurs - 1;
12709
12710             start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
12711             counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12712             ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12713                 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12714             xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12715             ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12716                 NULL, counter);
12717         }
12718         if (particle->minOccurs == 0) {
12719             xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12720             ret = 1;
12721         }
12722     }
12723     return(ret);
12724 }
12725
12726 /**
12727  * xmlSchemaBuildAContentModel:
12728  * @ctxt:  the schema parser context
12729  * @particle:  the particle component
12730  * @name:  the complex type's name whose content is being built
12731  *
12732  * Create the automaton for the {content type} of a complex type.
12733  *
12734  * Returns 1 if the content is nillable, 0 otherwise
12735  */
12736 static int
12737 xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
12738                             xmlSchemaParticlePtr particle)
12739 {
12740     int ret = 0, tmp2;
12741
12742     if (particle == NULL) {
12743         PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
12744         return(1);
12745     }
12746     if (particle->children == NULL) {
12747         /*
12748         * Just return in this case. A missing "term" of the particle
12749         * might arise due to an invalid "term" component.
12750         */
12751         return(1);
12752     }
12753
12754     switch (particle->children->type) {
12755         case XML_SCHEMA_TYPE_ANY: {
12756             xmlAutomataStatePtr start, end;
12757             xmlSchemaWildcardPtr wild;
12758             xmlSchemaWildcardNsPtr ns;
12759
12760             wild = (xmlSchemaWildcardPtr) particle->children;
12761
12762             start = pctxt->state;
12763             end = xmlAutomataNewState(pctxt->am);
12764
12765             if (particle->maxOccurs == 1) {
12766                 if (wild->any == 1) {
12767                     /*
12768                     * We need to add both transitions:
12769                     *
12770                     * 1. the {"*", "*"} for elements in a namespace.
12771                     */
12772                     pctxt->state =
12773                         xmlAutomataNewTransition2(pctxt->am,
12774                         start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12775                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12776                     /*
12777                     * 2. the {"*"} for elements in no namespace.
12778                     */
12779                     pctxt->state =
12780                         xmlAutomataNewTransition2(pctxt->am,
12781                         start, NULL, BAD_CAST "*", NULL, wild);
12782                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12783
12784                 } else if (wild->nsSet != NULL) {
12785                     ns = wild->nsSet;
12786                     do {
12787                         pctxt->state = start;
12788                         pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12789                             pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12790                         xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12791                         ns = ns->next;
12792                     } while (ns != NULL);
12793
12794                 } else if (wild->negNsSet != NULL) {
12795                     pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12796                         start, end, BAD_CAST "*", wild->negNsSet->value,
12797                         wild);
12798                 }
12799             } else {
12800                 int counter;
12801                 xmlAutomataStatePtr hop;
12802                 int maxOccurs =
12803                     particle->maxOccurs == UNBOUNDED ? UNBOUNDED :
12804                                            particle->maxOccurs - 1;
12805                 int minOccurs =
12806                     particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12807
12808                 counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12809                 hop = xmlAutomataNewState(pctxt->am);
12810                 if (wild->any == 1) {
12811                     pctxt->state =
12812                         xmlAutomataNewTransition2(pctxt->am,
12813                         start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12814                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12815                     pctxt->state =
12816                         xmlAutomataNewTransition2(pctxt->am,
12817                         start, NULL, BAD_CAST "*", NULL, wild);
12818                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12819                 } else if (wild->nsSet != NULL) {
12820                     ns = wild->nsSet;
12821                     do {
12822                         pctxt->state =
12823                             xmlAutomataNewTransition2(pctxt->am,
12824                                 start, NULL, BAD_CAST "*", ns->value, wild);
12825                         xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12826                         ns = ns->next;
12827                     } while (ns != NULL);
12828
12829                 } else if (wild->negNsSet != NULL) {
12830                     pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12831                         start, hop, BAD_CAST "*", wild->negNsSet->value,
12832                         wild);
12833                 }
12834                 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12835                 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12836             }
12837             if (particle->minOccurs == 0) {
12838                 xmlAutomataNewEpsilon(pctxt->am, start, end);
12839                 ret = 1;
12840             }
12841             pctxt->state = end;
12842             break;
12843         }
12844         case XML_SCHEMA_TYPE_ELEMENT:
12845             ret = xmlSchemaBuildContentModelForElement(pctxt, particle);
12846             break;
12847         case XML_SCHEMA_TYPE_SEQUENCE:{
12848             xmlSchemaTreeItemPtr sub;
12849
12850             ret = 1;
12851             /*
12852              * If max and min occurances are default (1) then
12853              * simply iterate over the particles of the <sequence>.
12854              */
12855             if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12856                 sub = particle->children->children;
12857
12858                 while (sub != NULL) {
12859                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
12860                                         (xmlSchemaParticlePtr) sub);
12861                     if (tmp2 != 1) ret = 0;
12862                     sub = sub->next;
12863                 }
12864             } else {
12865                 xmlAutomataStatePtr oldstate = pctxt->state;
12866
12867                 if (particle->maxOccurs >= UNBOUNDED) {
12868                     if (particle->minOccurs > 1) {
12869                         xmlAutomataStatePtr tmp;
12870                         int counter;
12871
12872                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12873                             oldstate, NULL);
12874                         oldstate = pctxt->state;
12875
12876                         counter = xmlAutomataNewCounter(pctxt->am,
12877                             particle->minOccurs - 1, UNBOUNDED);
12878
12879                         sub = particle->children->children;
12880                         while (sub != NULL) {
12881                             tmp2 = xmlSchemaBuildAContentModel(pctxt,
12882                                             (xmlSchemaParticlePtr) sub);
12883                             if (tmp2 != 1) ret = 0;
12884                             sub = sub->next;
12885                         }
12886                         tmp = pctxt->state;
12887                         xmlAutomataNewCountedTrans(pctxt->am, tmp,
12888                                                    oldstate, counter);
12889                         pctxt->state =
12890                             xmlAutomataNewCounterTrans(pctxt->am, tmp,
12891                                                        NULL, counter);
12892                         if (ret == 1)
12893                             xmlAutomataNewEpsilon(pctxt->am,
12894                                                 oldstate, pctxt->state);
12895
12896                     } else {
12897                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12898                             oldstate, NULL);
12899                         oldstate = pctxt->state;
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                         xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
12909                                               oldstate);
12910                         /*
12911                          * epsilon needed to block previous trans from
12912                          * being allowed to enter back from another
12913                          * construct
12914                          */
12915                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12916                                             pctxt->state, NULL);
12917                         if (particle->minOccurs == 0) {
12918                             xmlAutomataNewEpsilon(pctxt->am,
12919                                 oldstate, pctxt->state);
12920                             ret = 1;
12921                         }
12922                     }
12923                 } else if ((particle->maxOccurs > 1)
12924                            || (particle->minOccurs > 1)) {
12925                     xmlAutomataStatePtr tmp;
12926                     int counter;
12927
12928                     pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12929                         oldstate, NULL);
12930                     oldstate = pctxt->state;
12931
12932                     counter = xmlAutomataNewCounter(pctxt->am,
12933                         particle->minOccurs - 1,
12934                         particle->maxOccurs - 1);
12935
12936                     sub = particle->children->children;
12937                     while (sub != NULL) {
12938                         tmp2 = xmlSchemaBuildAContentModel(pctxt,
12939                                         (xmlSchemaParticlePtr) sub);
12940                         if (tmp2 != 1) ret = 0;
12941                         sub = sub->next;
12942                     }
12943                     tmp = pctxt->state;
12944                     xmlAutomataNewCountedTrans(pctxt->am,
12945                         tmp, oldstate, counter);
12946                     pctxt->state =
12947                         xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
12948                                                    counter);
12949                     if ((particle->minOccurs == 0) || (ret == 1)) {
12950                         xmlAutomataNewEpsilon(pctxt->am,
12951                                             oldstate, pctxt->state);
12952                         ret = 1;
12953                     }
12954                 } else {
12955                     sub = particle->children->children;
12956                     while (sub != NULL) {
12957                         tmp2 = xmlSchemaBuildAContentModel(pctxt,
12958                                         (xmlSchemaParticlePtr) sub);
12959                         if (tmp2 != 1) ret = 0;
12960                         sub = sub->next;
12961                     }
12962
12963                     /*
12964                      * epsilon needed to block previous trans from
12965                      * being allowed to enter back from another
12966                      * construct
12967                      */
12968                     pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12969                                         pctxt->state, NULL);
12970
12971                     if (particle->minOccurs == 0) {
12972                         xmlAutomataNewEpsilon(pctxt->am, oldstate,
12973                                               pctxt->state);
12974                         ret = 1;
12975                     }
12976                 }
12977             }
12978             break;
12979         }
12980         case XML_SCHEMA_TYPE_CHOICE:{
12981             xmlSchemaTreeItemPtr sub;
12982             xmlAutomataStatePtr start, end;
12983
12984             ret = 0;
12985             start = pctxt->state;
12986             end = xmlAutomataNewState(pctxt->am);
12987
12988             /*
12989              * iterate over the subtypes and remerge the end with an
12990              * epsilon transition
12991              */
12992             if (particle->maxOccurs == 1) {
12993                 sub = particle->children->children;
12994                 while (sub != NULL) {
12995                     pctxt->state = start;
12996                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
12997                                         (xmlSchemaParticlePtr) sub);
12998                     if (tmp2 == 1) ret = 1;
12999                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
13000                     sub = sub->next;
13001                 }
13002             } else {
13003                 int counter;
13004                 xmlAutomataStatePtr hop, base;
13005                 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
13006                     UNBOUNDED : particle->maxOccurs - 1;
13007                 int minOccurs =
13008                     particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
13009
13010                 /*
13011                  * use a counter to keep track of the number of transtions
13012                  * which went through the choice.
13013                  */
13014                 counter =
13015                     xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
13016                 hop = xmlAutomataNewState(pctxt->am);
13017                 base = xmlAutomataNewState(pctxt->am);
13018
13019                 sub = particle->children->children;
13020                 while (sub != NULL) {
13021                     pctxt->state = base;
13022                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
13023                                         (xmlSchemaParticlePtr) sub);
13024                     if (tmp2 == 1) ret = 1;
13025                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
13026                     sub = sub->next;
13027                 }
13028                 xmlAutomataNewEpsilon(pctxt->am, start, base);
13029                 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
13030                 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
13031                 if (ret == 1)
13032                     xmlAutomataNewEpsilon(pctxt->am, base, end);
13033             }
13034             if (particle->minOccurs == 0) {
13035                 xmlAutomataNewEpsilon(pctxt->am, start, end);
13036                 ret = 1;
13037             }
13038             pctxt->state = end;
13039             break;
13040         }
13041         case XML_SCHEMA_TYPE_ALL:{
13042             xmlAutomataStatePtr start, tmp;
13043             xmlSchemaParticlePtr sub;
13044             xmlSchemaElementPtr elemDecl;
13045
13046             ret = 1;
13047
13048             sub = (xmlSchemaParticlePtr) particle->children->children;
13049             if (sub == NULL)
13050                 break;
13051
13052             ret = 0;
13053
13054             start = pctxt->state;
13055             tmp = xmlAutomataNewState(pctxt->am);
13056             xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp);
13057             pctxt->state = tmp;
13058             while (sub != NULL) {
13059                 pctxt->state = tmp;
13060
13061                 elemDecl = (xmlSchemaElementPtr) sub->children;
13062                 if (elemDecl == NULL) {
13063                     PERROR_INT("xmlSchemaBuildAContentModel",
13064                         "<element> particle has no term");
13065                     return(ret);
13066                 };
13067                 /*
13068                 * NOTE: The {max occurs} of all the particles in the
13069                 * {particles} of the group must be 0 or 1; this is
13070                 * already ensured during the parse of the content of
13071                 * <all>.
13072                 */
13073                 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
13074                     int counter;
13075
13076                     /*
13077                      * This is an abstract group, we need to share
13078                      * the same counter for all the element transitions
13079                      * derived from the group
13080                      */
13081                     counter = xmlAutomataNewCounter(pctxt->am,
13082                                        sub->minOccurs, sub->maxOccurs);
13083                     xmlSchemaBuildContentModelForSubstGroup(pctxt,
13084                                        sub, counter, pctxt->state);
13085                 } else {
13086                     if ((sub->minOccurs == 1) &&
13087                         (sub->maxOccurs == 1)) {
13088                         xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
13089                                                 pctxt->state,
13090                                                 elemDecl->name,
13091                                                 elemDecl->targetNamespace,
13092                                                 1, 1, elemDecl);
13093                     } else if ((sub->minOccurs == 0) &&
13094                         (sub->maxOccurs == 1)) {
13095
13096                         xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
13097                                                  pctxt->state,
13098                                                  elemDecl->name,
13099                                                  elemDecl->targetNamespace,
13100                                                  0,
13101                                                  1,
13102                                                  elemDecl);
13103                     }
13104                 }
13105                 sub = (xmlSchemaParticlePtr) sub->next;
13106             }
13107             pctxt->state =
13108                 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0);
13109             if (particle->minOccurs == 0) {
13110                 xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state);
13111                 ret = 1;
13112             }
13113             break;
13114         }
13115         case XML_SCHEMA_TYPE_GROUP:
13116             /*
13117             * If we hit a model group definition, then this means that
13118             * it was empty, thus was not substituted for the containing
13119             * model group. Just do nothing in this case.
13120             * TODO: But the group should be substituted and not occur at
13121             * all in the content model at this point. Fix this.
13122             */
13123             ret = 1;
13124             break;
13125         default:
13126             xmlSchemaInternalErr2(ACTXT_CAST pctxt,
13127                 "xmlSchemaBuildAContentModel",
13128                 "found unexpected term of type '%s' in content model",
13129                 WXS_ITEM_TYPE_NAME(particle->children), NULL);
13130             return(ret);
13131     }
13132     return(ret);
13133 }
13134
13135 /**
13136  * xmlSchemaBuildContentModel:
13137  * @ctxt:  the schema parser context
13138  * @type:  the complex type definition
13139  * @name:  the element name
13140  *
13141  * Builds the content model of the complex type.
13142  */
13143 static void
13144 xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
13145                            xmlSchemaParserCtxtPtr ctxt)
13146 {
13147     if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13148         (type->contModel != NULL) ||
13149         ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13150         (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
13151         return;
13152
13153 #ifdef DEBUG_CONTENT
13154     xmlGenericError(xmlGenericErrorContext,
13155                     "Building content model for %s\n", name);
13156 #endif
13157     ctxt->am = NULL;
13158     ctxt->am = xmlNewAutomata();
13159     if (ctxt->am == NULL) {
13160         xmlGenericError(xmlGenericErrorContext,
13161             "Cannot create automata for complex type %s\n", type->name);
13162         return;
13163     }
13164     ctxt->state = xmlAutomataGetInitState(ctxt->am);
13165     /*
13166     * Build the automaton.
13167     */
13168     xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
13169     xmlAutomataSetFinalState(ctxt->am, ctxt->state);
13170     type->contModel = xmlAutomataCompile(ctxt->am);
13171     if (type->contModel == NULL) {
13172         xmlSchemaPCustomErr(ctxt,
13173             XML_SCHEMAP_INTERNAL,
13174             WXS_BASIC_CAST type, type->node,
13175             "Failed to compile the content model", NULL);
13176     } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
13177         xmlSchemaPCustomErr(ctxt,
13178             XML_SCHEMAP_NOT_DETERMINISTIC,
13179             /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
13180             WXS_BASIC_CAST type, type->node,
13181             "The content model is not determinist", NULL);
13182     } else {
13183 #ifdef DEBUG_CONTENT_REGEXP
13184         xmlGenericError(xmlGenericErrorContext,
13185                         "Content model of %s:\n", type->name);
13186         xmlRegexpPrint(stderr, type->contModel);
13187 #endif
13188     }
13189     ctxt->state = NULL;
13190     xmlFreeAutomata(ctxt->am);
13191     ctxt->am = NULL;
13192 }
13193
13194 /**
13195  * xmlSchemaResolveElementReferences:
13196  * @elem:  the schema element context
13197  * @ctxt:  the schema parser context
13198  *
13199  * Resolves the references of an element declaration
13200  * or particle, which has an element declaration as it's
13201  * term.
13202  */
13203 static void
13204 xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13205                                   xmlSchemaParserCtxtPtr ctxt)
13206 {
13207     if ((ctxt == NULL) || (elemDecl == NULL) ||
13208         ((elemDecl != NULL) &&
13209         (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
13210         return;
13211     elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
13212
13213     if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
13214         xmlSchemaTypePtr type;
13215
13216         /* (type definition) ... otherwise the type definition `resolved`
13217         * to by the `actual value` of the type [attribute] ...
13218         */
13219         type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
13220             elemDecl->namedTypeNs);
13221         if (type == NULL) {
13222             xmlSchemaPResCompAttrErr(ctxt,
13223                 XML_SCHEMAP_SRC_RESOLVE,
13224                 WXS_BASIC_CAST elemDecl, elemDecl->node,
13225                 "type", elemDecl->namedType, elemDecl->namedTypeNs,
13226                 XML_SCHEMA_TYPE_BASIC, "type definition");
13227         } else
13228             elemDecl->subtypes = type;
13229     }
13230     if (elemDecl->substGroup != NULL) {
13231         xmlSchemaElementPtr substHead;
13232
13233         /*
13234         * FIXME TODO: Do we need a new field in _xmlSchemaElement for
13235         * substitutionGroup?
13236         */
13237         substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13238             elemDecl->substGroupNs);
13239         if (substHead == NULL) {
13240             xmlSchemaPResCompAttrErr(ctxt,
13241                 XML_SCHEMAP_SRC_RESOLVE,
13242                 WXS_BASIC_CAST elemDecl, NULL,
13243                 "substitutionGroup", elemDecl->substGroup,
13244                 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
13245         } else {
13246             xmlSchemaResolveElementReferences(substHead, ctxt);
13247             /*
13248             * Set the "substitution group affiliation".
13249             * NOTE that now we use the "refDecl" field for this.
13250             */
13251             WXS_SUBST_HEAD(elemDecl) = substHead;
13252             /*
13253             * The type definitions is set to:
13254             * SPEC "...the {type definition} of the element
13255             * declaration `resolved` to by the `actual value`
13256             * of the substitutionGroup [attribute], if present"
13257             */
13258             if (elemDecl->subtypes == NULL)
13259                 elemDecl->subtypes = substHead->subtypes;
13260         }
13261     }
13262     /*
13263     * SPEC "The definition of anyType serves as the default type definition
13264     * for element declarations whose XML representation does not specify one."
13265     */
13266     if ((elemDecl->subtypes == NULL) &&
13267         (elemDecl->namedType == NULL) &&
13268         (elemDecl->substGroup == NULL))
13269         elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13270 }
13271
13272 /**
13273  * xmlSchemaResolveUnionMemberTypes:
13274  * @ctxt:  the schema parser context
13275  * @type:  the schema simple type definition
13276  *
13277  * Checks and builds the "member type definitions" property of the union
13278  * simple type. This handles part (1), part (2) is done in
13279  * xmlSchemaFinishMemberTypeDefinitionsProperty()
13280  *
13281  * Returns -1 in case of an internal error, 0 otherwise.
13282  */
13283 static int
13284 xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13285                                  xmlSchemaTypePtr type)
13286 {
13287
13288     xmlSchemaTypeLinkPtr link, lastLink, newLink;
13289     xmlSchemaTypePtr memberType;
13290
13291     /*
13292     * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13293     * define the explicit members as the type definitions `resolved`
13294     * to by the items in the `actual value` of the memberTypes [attribute],
13295     * if any, followed by the type definitions corresponding to the
13296     * <simpleType>s among the [children] of <union>, if any."
13297     */
13298     /*
13299     * Resolve references.
13300     */
13301     link = type->memberTypes;
13302     lastLink = NULL;
13303     while (link != NULL) {
13304         const xmlChar *name, *nsName;
13305
13306         name = ((xmlSchemaQNameRefPtr) link->type)->name;
13307         nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13308
13309         memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
13310         if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
13311             xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
13312                 WXS_BASIC_CAST type, type->node, "memberTypes",
13313                 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13314             /*
13315             * Remove the member type link.
13316             */
13317             if (lastLink == NULL)
13318                 type->memberTypes = link->next;
13319             else
13320                 lastLink->next = link->next;
13321             newLink = link;
13322             link = link->next;
13323             xmlFree(newLink);
13324         } else {
13325             link->type = memberType;
13326             lastLink = link;
13327             link = link->next;
13328         }
13329     }
13330     /*
13331     * Add local simple types,
13332     */
13333     memberType = type->subtypes;
13334     while (memberType != NULL) {
13335         link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13336         if (link == NULL) {
13337             xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13338             return (-1);
13339         }
13340         link->type = memberType;
13341         link->next = NULL;
13342         if (lastLink == NULL)
13343             type->memberTypes = link;
13344         else
13345             lastLink->next = link;
13346         lastLink = link;
13347         memberType = memberType->next;
13348     }
13349     return (0);
13350 }
13351
13352 /**
13353  * xmlSchemaIsDerivedFromBuiltInType:
13354  * @ctxt:  the schema parser context
13355  * @type:  the type definition
13356  * @valType: the value type
13357  *
13358  *
13359  * Returns 1 if the type has the given value type, or
13360  * is derived from such a type.
13361  */
13362 static int
13363 xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13364 {
13365     if (type == NULL)
13366         return (0);
13367     if (WXS_IS_COMPLEX(type))
13368         return (0);
13369     if (type->type == XML_SCHEMA_TYPE_BASIC) {
13370         if (type->builtInType == valType)
13371             return(1);
13372         if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13373             (type->builtInType == XML_SCHEMAS_ANYTYPE))
13374             return (0);
13375         return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13376     }
13377     return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13378 }
13379
13380 #if 0
13381 /**
13382  * xmlSchemaIsDerivedFromBuiltInType:
13383  * @ctxt:  the schema parser context
13384  * @type:  the type definition
13385  * @valType: the value type
13386  *
13387  *
13388  * Returns 1 if the type has the given value type, or
13389  * is derived from such a type.
13390  */
13391 static int
13392 xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13393 {
13394     if (type == NULL)
13395         return (0);
13396     if (WXS_IS_COMPLEX(type))
13397         return (0);
13398     if (type->type == XML_SCHEMA_TYPE_BASIC) {
13399         if (type->builtInType == valType)
13400             return(1);
13401         return (0);
13402     } else
13403         return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13404
13405     return (0);
13406 }
13407
13408 static xmlSchemaTypePtr
13409 xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13410 {
13411     if (type == NULL)
13412         return (NULL);
13413     if (WXS_IS_COMPLEX(type))
13414         return (NULL);
13415     if (type->type == XML_SCHEMA_TYPE_BASIC)
13416         return(type);
13417     return(xmlSchemaQueryBuiltInType(type->subtypes));
13418 }
13419 #endif
13420
13421 /**
13422  * xmlSchemaGetPrimitiveType:
13423  * @type:  the simpleType definition
13424  *
13425  * Returns the primitive type of the given type or
13426  * NULL in case of error.
13427  */
13428 static xmlSchemaTypePtr
13429 xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13430 {
13431
13432     while (type != NULL) {
13433         /*
13434         * Note that anySimpleType is actually not a primitive type
13435         * but we need that here.
13436         */
13437         if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13438            (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
13439             return (type);
13440         type = type->baseType;
13441     }
13442
13443     return (NULL);
13444 }
13445
13446 #if 0
13447 /**
13448  * xmlSchemaGetBuiltInTypeAncestor:
13449  * @type:  the simpleType definition
13450  *
13451  * Returns the primitive type of the given type or
13452  * NULL in case of error.
13453  */
13454 static xmlSchemaTypePtr
13455 xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13456 {
13457     if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
13458         return (0);
13459     while (type != NULL) {
13460         if (type->type == XML_SCHEMA_TYPE_BASIC)
13461             return (type);
13462         type = type->baseType;
13463     }
13464
13465     return (NULL);
13466 }
13467 #endif
13468
13469 /**
13470  * xmlSchemaCloneWildcardNsConstraints:
13471  * @ctxt:  the schema parser context
13472  * @dest:  the destination wildcard
13473  * @source: the source wildcard
13474  *
13475  * Clones the namespace constraints of source
13476  * and assignes them to dest.
13477  * Returns -1 on internal error, 0 otherwise.
13478  */
13479 static int
13480 xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
13481                                     xmlSchemaWildcardPtr dest,
13482                                     xmlSchemaWildcardPtr source)
13483 {
13484     xmlSchemaWildcardNsPtr cur, tmp, last;
13485
13486     if ((source == NULL) || (dest == NULL))
13487         return(-1);
13488     dest->any = source->any;
13489     cur = source->nsSet;
13490     last = NULL;
13491     while (cur != NULL) {
13492         tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13493         if (tmp == NULL)
13494             return(-1);
13495         tmp->value = cur->value;
13496         if (last == NULL)
13497             dest->nsSet = tmp;
13498         else
13499             last->next = tmp;
13500         last = tmp;
13501         cur = cur->next;
13502     }
13503     if (dest->negNsSet != NULL)
13504         xmlSchemaFreeWildcardNsSet(dest->negNsSet);
13505     if (source->negNsSet != NULL) {
13506         dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13507         if (dest->negNsSet == NULL)
13508             return(-1);
13509         dest->negNsSet->value = source->negNsSet->value;
13510     } else
13511         dest->negNsSet = NULL;
13512     return(0);
13513 }
13514
13515 /**
13516  * xmlSchemaUnionWildcards:
13517  * @ctxt:  the schema parser context
13518  * @completeWild:  the first wildcard
13519  * @curWild: the second wildcard
13520  *
13521  * Unions the namespace constraints of the given wildcards.
13522  * @completeWild will hold the resulting union.
13523  * Returns a positive error code on failure, -1 in case of an
13524  * internal error, 0 otherwise.
13525  */
13526 static int
13527 xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
13528                             xmlSchemaWildcardPtr completeWild,
13529                             xmlSchemaWildcardPtr curWild)
13530 {
13531     xmlSchemaWildcardNsPtr cur, curB, tmp;
13532
13533     /*
13534     * 1 If O1 and O2 are the same value, then that value must be the
13535     * value.
13536     */
13537     if ((completeWild->any == curWild->any) &&
13538         ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13539         ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13540
13541         if ((completeWild->negNsSet == NULL) ||
13542             (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13543
13544             if (completeWild->nsSet != NULL) {
13545                 int found = 0;
13546
13547                 /*
13548                 * Check equality of sets.
13549                 */
13550                 cur = completeWild->nsSet;
13551                 while (cur != NULL) {
13552                     found = 0;
13553                     curB = curWild->nsSet;
13554                     while (curB != NULL) {
13555                         if (cur->value == curB->value) {
13556                             found = 1;
13557                             break;
13558                         }
13559                         curB = curB->next;
13560                     }
13561                     if (!found)
13562                         break;
13563                     cur = cur->next;
13564                 }
13565                 if (found)
13566                     return(0);
13567             } else
13568                 return(0);
13569         }
13570     }
13571     /*
13572     * 2 If either O1 or O2 is any, then any must be the value
13573     */
13574     if (completeWild->any != curWild->any) {
13575         if (completeWild->any == 0) {
13576             completeWild->any = 1;
13577             if (completeWild->nsSet != NULL) {
13578                 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13579                 completeWild->nsSet = NULL;
13580             }
13581             if (completeWild->negNsSet != NULL) {
13582                 xmlFree(completeWild->negNsSet);
13583                 completeWild->negNsSet = NULL;
13584             }
13585         }
13586         return (0);
13587     }
13588     /*
13589     * 3 If both O1 and O2 are sets of (namespace names or `absent`),
13590     * then the union of those sets must be the value.
13591     */
13592     if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13593         int found;
13594         xmlSchemaWildcardNsPtr start;
13595
13596         cur = curWild->nsSet;
13597         start = completeWild->nsSet;
13598         while (cur != NULL) {
13599             found = 0;
13600             curB = start;
13601             while (curB != NULL) {
13602                 if (cur->value == curB->value) {
13603                     found = 1;
13604                     break;
13605                 }
13606                 curB = curB->next;
13607             }
13608             if (!found) {
13609                 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13610                 if (tmp == NULL)
13611                     return (-1);
13612                 tmp->value = cur->value;
13613                 tmp->next = completeWild->nsSet;
13614                 completeWild->nsSet = tmp;
13615             }
13616             cur = cur->next;
13617         }
13618
13619         return(0);
13620     }
13621     /*
13622     * 4 If the two are negations of different values (namespace names
13623     * or `absent`), then a pair of not and `absent` must be the value.
13624     */
13625     if ((completeWild->negNsSet != NULL) &&
13626         (curWild->negNsSet != NULL) &&
13627         (completeWild->negNsSet->value != curWild->negNsSet->value)) {
13628         completeWild->negNsSet->value = NULL;
13629
13630         return(0);
13631     }
13632     /*
13633      * 5.
13634      */
13635     if (((completeWild->negNsSet != NULL) &&
13636         (completeWild->negNsSet->value != NULL) &&
13637         (curWild->nsSet != NULL)) ||
13638         ((curWild->negNsSet != NULL) &&
13639         (curWild->negNsSet->value != NULL) &&
13640         (completeWild->nsSet != NULL))) {
13641
13642         int nsFound, absentFound = 0;
13643
13644         if (completeWild->nsSet != NULL) {
13645             cur = completeWild->nsSet;
13646             curB = curWild->negNsSet;
13647         } else {
13648             cur = curWild->nsSet;
13649             curB = completeWild->negNsSet;
13650         }
13651         nsFound = 0;
13652         while (cur != NULL) {
13653             if (cur->value == NULL)
13654                 absentFound = 1;
13655             else if (cur->value == curB->value)
13656                 nsFound = 1;
13657             if (nsFound && absentFound)
13658                 break;
13659             cur = cur->next;
13660         }
13661
13662         if (nsFound && absentFound) {
13663             /*
13664             * 5.1 If the set S includes both the negated namespace
13665             * name and `absent`, then any must be the value.
13666             */
13667             completeWild->any = 1;
13668             if (completeWild->nsSet != NULL) {
13669                 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13670                 completeWild->nsSet = NULL;
13671             }
13672             if (completeWild->negNsSet != NULL) {
13673                 xmlFree(completeWild->negNsSet);
13674                 completeWild->negNsSet = NULL;
13675             }
13676         } else if (nsFound && (!absentFound)) {
13677             /*
13678             * 5.2 If the set S includes the negated namespace name
13679             * but not `absent`, then a pair of not and `absent` must
13680             * be the value.
13681             */
13682             if (completeWild->nsSet != NULL) {
13683                 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13684                 completeWild->nsSet = NULL;
13685             }
13686             if (completeWild->negNsSet == NULL) {
13687                 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13688                 if (completeWild->negNsSet == NULL)
13689                     return (-1);
13690             }
13691             completeWild->negNsSet->value = NULL;
13692         } else if ((!nsFound) && absentFound) {
13693             /*
13694             * 5.3 If the set S includes `absent` but not the negated
13695             * namespace name, then the union is not expressible.
13696             */
13697             xmlSchemaPErr(ctxt, completeWild->node,
13698                 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
13699                 "The union of the wilcard is not expressible.\n",
13700                 NULL, NULL);
13701             return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
13702         } else if ((!nsFound) && (!absentFound)) {
13703             /*
13704             * 5.4 If the set S does not include either the negated namespace
13705             * name or `absent`, then whichever of O1 or O2 is a pair of not
13706             * and a namespace name must be the value.
13707             */
13708             if (completeWild->negNsSet == NULL) {
13709                 if (completeWild->nsSet != NULL) {
13710                     xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13711                     completeWild->nsSet = NULL;
13712                 }
13713                 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13714                 if (completeWild->negNsSet == NULL)
13715                     return (-1);
13716                 completeWild->negNsSet->value = curWild->negNsSet->value;
13717             }
13718         }
13719         return (0);
13720     }
13721     /*
13722      * 6.
13723      */
13724     if (((completeWild->negNsSet != NULL) &&
13725         (completeWild->negNsSet->value == NULL) &&
13726         (curWild->nsSet != NULL)) ||
13727         ((curWild->negNsSet != NULL) &&
13728         (curWild->negNsSet->value == NULL) &&
13729         (completeWild->nsSet != NULL))) {
13730
13731         if (completeWild->nsSet != NULL) {
13732             cur = completeWild->nsSet;
13733         } else {
13734             cur = curWild->nsSet;
13735         }
13736         while (cur != NULL) {
13737             if (cur->value == NULL) {
13738                 /*
13739                 * 6.1 If the set S includes `absent`, then any must be the
13740                 * value.
13741                 */
13742                 completeWild->any = 1;
13743                 if (completeWild->nsSet != NULL) {
13744                     xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13745                     completeWild->nsSet = NULL;
13746                 }
13747                 if (completeWild->negNsSet != NULL) {
13748                     xmlFree(completeWild->negNsSet);
13749                     completeWild->negNsSet = NULL;
13750                 }
13751                 return (0);
13752             }
13753             cur = cur->next;
13754         }
13755         if (completeWild->negNsSet == NULL) {
13756             /*
13757             * 6.2 If the set S does not include `absent`, then a pair of not
13758             * and `absent` must be the value.
13759             */
13760             if (completeWild->nsSet != NULL) {
13761                 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13762                 completeWild->nsSet = NULL;
13763             }
13764             completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13765             if (completeWild->negNsSet == NULL)
13766                 return (-1);
13767             completeWild->negNsSet->value = NULL;
13768         }
13769         return (0);
13770     }
13771     return (0);
13772
13773 }
13774
13775 /**
13776  * xmlSchemaIntersectWildcards:
13777  * @ctxt:  the schema parser context
13778  * @completeWild:  the first wildcard
13779  * @curWild: the second wildcard
13780  *
13781  * Intersects the namespace constraints of the given wildcards.
13782  * @completeWild will hold the resulting intersection.
13783  * Returns a positive error code on failure, -1 in case of an
13784  * internal error, 0 otherwise.
13785  */
13786 static int
13787 xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
13788                             xmlSchemaWildcardPtr completeWild,
13789                             xmlSchemaWildcardPtr curWild)
13790 {
13791     xmlSchemaWildcardNsPtr cur, curB, prev,  tmp;
13792
13793     /*
13794     * 1 If O1 and O2 are the same value, then that value must be the
13795     * value.
13796     */
13797     if ((completeWild->any == curWild->any) &&
13798         ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13799         ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13800
13801         if ((completeWild->negNsSet == NULL) ||
13802             (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13803
13804             if (completeWild->nsSet != NULL) {
13805                 int found = 0;
13806
13807                 /*
13808                 * Check equality of sets.
13809                 */
13810                 cur = completeWild->nsSet;
13811                 while (cur != NULL) {
13812                     found = 0;
13813                     curB = curWild->nsSet;
13814                     while (curB != NULL) {
13815                         if (cur->value == curB->value) {
13816                             found = 1;
13817                             break;
13818                         }
13819                         curB = curB->next;
13820                     }
13821                     if (!found)
13822                         break;
13823                     cur = cur->next;
13824                 }
13825                 if (found)
13826                     return(0);
13827             } else
13828                 return(0);
13829         }
13830     }
13831     /*
13832     * 2 If either O1 or O2 is any, then the other must be the value.
13833     */
13834     if ((completeWild->any != curWild->any) && (completeWild->any)) {
13835         if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13836             return(-1);
13837         return(0);
13838     }
13839     /*
13840     * 3 If either O1 or O2 is a pair of not and a value (a namespace
13841     * name or `absent`) and the other is a set of (namespace names or
13842     * `absent`), then that set, minus the negated value if it was in
13843     * the set, minus `absent` if it was in the set, must be the value.
13844     */
13845     if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13846         ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13847         const xmlChar *neg;
13848
13849         if (completeWild->nsSet == NULL) {
13850             neg = completeWild->negNsSet->value;
13851             if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13852                 return(-1);
13853         } else
13854             neg = curWild->negNsSet->value;
13855         /*
13856         * Remove absent and negated.
13857         */
13858         prev = NULL;
13859         cur = completeWild->nsSet;
13860         while (cur != NULL) {
13861             if (cur->value == NULL) {
13862                 if (prev == NULL)
13863                     completeWild->nsSet = cur->next;
13864                 else
13865                     prev->next = cur->next;
13866                 xmlFree(cur);
13867                 break;
13868             }
13869             prev = cur;
13870             cur = cur->next;
13871         }
13872         if (neg != NULL) {
13873             prev = NULL;
13874             cur = completeWild->nsSet;
13875             while (cur != NULL) {
13876                 if (cur->value == neg) {
13877                     if (prev == NULL)
13878                         completeWild->nsSet = cur->next;
13879                     else
13880                         prev->next = cur->next;
13881                     xmlFree(cur);
13882                     break;
13883                 }
13884                 prev = cur;
13885                 cur = cur->next;
13886             }
13887         }
13888
13889         return(0);
13890     }
13891     /*
13892     * 4 If both O1 and O2 are sets of (namespace names or `absent`),
13893     * then the intersection of those sets must be the value.
13894     */
13895     if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13896         int found;
13897
13898         cur = completeWild->nsSet;
13899         prev = NULL;
13900         while (cur != NULL) {
13901             found = 0;
13902             curB = curWild->nsSet;
13903             while (curB != NULL) {
13904                 if (cur->value == curB->value) {
13905                     found = 1;
13906                     break;
13907                 }
13908                 curB = curB->next;
13909             }
13910             if (!found) {
13911                 if (prev == NULL)
13912                     completeWild->nsSet = cur->next;
13913                 else
13914                     prev->next = cur->next;
13915                 tmp = cur->next;
13916                 xmlFree(cur);
13917                 cur = tmp;
13918                 continue;
13919             }
13920             prev = cur;
13921             cur = cur->next;
13922         }
13923
13924         return(0);
13925     }
13926     /* 5 If the two are negations of different namespace names,
13927     * then the intersection is not expressible
13928     */
13929     if ((completeWild->negNsSet != NULL) &&
13930         (curWild->negNsSet != NULL) &&
13931         (completeWild->negNsSet->value != curWild->negNsSet->value) &&
13932         (completeWild->negNsSet->value != NULL) &&
13933         (curWild->negNsSet->value != NULL)) {
13934
13935         xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
13936             "The intersection of the wilcard is not expressible.\n",
13937             NULL, NULL);
13938         return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
13939     }
13940     /*
13941     * 6 If the one is a negation of a namespace name and the other
13942     * is a negation of `absent`, then the one which is the negation
13943     * of a namespace name must be the value.
13944     */
13945     if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
13946         (completeWild->negNsSet->value != curWild->negNsSet->value) &&
13947         (completeWild->negNsSet->value == NULL)) {
13948         completeWild->negNsSet->value =  curWild->negNsSet->value;
13949     }
13950     return(0);
13951 }
13952
13953 /**
13954  * xmlSchemaIsWildcardNsConstraintSubset:
13955  * @ctxt:  the schema parser context
13956  * @sub:  the first wildcard
13957  * @super: the second wildcard
13958  *
13959  * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
13960  *
13961  * Returns 0 if the namespace constraint of @sub is an intensional
13962  * subset of @super, 1 otherwise.
13963  */
13964 static int
13965 xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
13966                           xmlSchemaWildcardPtr super)
13967 {
13968     /*
13969     * 1 super must be any.
13970     */
13971     if (super->any)
13972         return (0);
13973     /*
13974     * 2.1 sub must be a pair of not and a namespace name or `absent`.
13975     * 2.2 super must be a pair of not and the same value.
13976     */
13977     if ((sub->negNsSet != NULL) &&
13978         (super->negNsSet != NULL) &&
13979         (sub->negNsSet->value == super->negNsSet->value))
13980         return (0);
13981     /*
13982     * 3.1 sub must be a set whose members are either namespace names or `absent`.
13983     */
13984     if (sub->nsSet != NULL) {
13985         /*
13986         * 3.2.1 super must be the same set or a superset thereof.
13987         */
13988         if (super->nsSet != NULL) {
13989             xmlSchemaWildcardNsPtr cur, curB;
13990             int found = 0;
13991
13992             cur = sub->nsSet;
13993             while (cur != NULL) {
13994                 found = 0;
13995                 curB = super->nsSet;
13996                 while (curB != NULL) {
13997                     if (cur->value == curB->value) {
13998                         found = 1;
13999                         break;
14000                     }
14001                     curB = curB->next;
14002                 }
14003                 if (!found)
14004                     return (1);
14005                 cur = cur->next;
14006             }
14007             if (found)
14008                 return (0);
14009         } else if (super->negNsSet != NULL) {
14010             xmlSchemaWildcardNsPtr cur;
14011             /*
14012             * 3.2.2 super must be a pair of not and a namespace name or
14013             * `absent` and that value must not be in sub's set.
14014             */
14015             cur = sub->nsSet;
14016             while (cur != NULL) {
14017                 if (cur->value == super->negNsSet->value)
14018                     return (1);
14019                 cur = cur->next;
14020             }
14021             return (0);
14022         }
14023     }
14024     return (1);
14025 }
14026
14027 static int
14028 xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
14029                                      int *fixed,
14030                                      const xmlChar **value,
14031                                      xmlSchemaValPtr *val)
14032 {
14033     *fixed = 0;
14034     *value = NULL;
14035     if (val != 0)
14036         *val = NULL;
14037
14038     if (attruse->defValue != NULL) {
14039         *value = attruse->defValue;
14040         if (val != NULL)
14041             *val = attruse->defVal;
14042         if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
14043             *fixed = 1;
14044         return(1);
14045     } else if ((attruse->attrDecl != NULL) &&
14046         (attruse->attrDecl->defValue != NULL)) {
14047         *value = attruse->attrDecl->defValue;
14048         if (val != NULL)
14049             *val = attruse->attrDecl->defVal;
14050         if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
14051             *fixed = 1;
14052         return(1);
14053     }
14054     return(0);
14055 }
14056 /**
14057  * xmlSchemaCheckCVCWildcardNamespace:
14058  * @wild:  the wildcard
14059  * @ns:  the namespace
14060  *
14061  * Validation Rule: Wildcard allows Namespace Name
14062  * (cvc-wildcard-namespace)
14063  *
14064  * Returns 0 if the given namespace matches the wildcard,
14065  * 1 otherwise and -1 on API errors.
14066  */
14067 static int
14068 xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
14069                                    const xmlChar* ns)
14070 {
14071     if (wild == NULL)
14072         return(-1);
14073
14074     if (wild->any)
14075         return(0);
14076     else if (wild->nsSet != NULL) {
14077         xmlSchemaWildcardNsPtr cur;
14078
14079         cur = wild->nsSet;
14080         while (cur != NULL) {
14081             if (xmlStrEqual(cur->value, ns))
14082                 return(0);
14083             cur = cur->next;
14084         }
14085     } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
14086         (!xmlStrEqual(wild->negNsSet->value, ns)))
14087         return(0);
14088
14089     return(1);
14090 }
14091
14092 #define XML_SCHEMA_ACTION_DERIVE 0
14093 #define XML_SCHEMA_ACTION_REDEFINE 1
14094
14095 #define WXS_ACTION_STR(a) \
14096 ((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
14097
14098 /*
14099 * Schema Component Constraint:
14100 *   Derivation Valid (Restriction, Complex)
14101 *   derivation-ok-restriction (2) - (4)
14102 *
14103 * ATTENTION:
14104 * In XML Schema 1.1 this will be:
14105 * Validation Rule:
14106 *     Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
14107 *
14108 */
14109 static int
14110 xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
14111                                        int action,
14112                                        xmlSchemaBasicItemPtr item,
14113                                        xmlSchemaBasicItemPtr baseItem,
14114                                        xmlSchemaItemListPtr uses,
14115                                        xmlSchemaItemListPtr baseUses,
14116                                        xmlSchemaWildcardPtr wild,
14117                                        xmlSchemaWildcardPtr baseWild)
14118 {
14119     xmlSchemaAttributeUsePtr cur = NULL, bcur;
14120     int i, j, found; /* err = 0; */
14121     const xmlChar *bEffValue;
14122     int effFixed;
14123
14124     if (uses != NULL) {
14125         for (i = 0; i < uses->nbItems; i++) {
14126             cur = uses->items[i];
14127             found = 0;
14128             if (baseUses == NULL)
14129                 goto not_found;
14130             for (j = 0; j < baseUses->nbItems; j++) {
14131                 bcur = baseUses->items[j];
14132                 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14133                         WXS_ATTRUSE_DECL_NAME(bcur)) &&
14134                     (WXS_ATTRUSE_DECL_TNS(cur) ==
14135                         WXS_ATTRUSE_DECL_TNS(bcur)))
14136                 {
14137                     /*
14138                     * (2.1) "If there is an attribute use in the {attribute
14139                     * uses} of the {base type definition} (call this B) whose
14140                     * {attribute declaration} has the same {name} and {target
14141                     * namespace}, then  all of the following must be true:"
14142                     */
14143                     found = 1;
14144
14145                     if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14146                         (bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14147                     {
14148                         xmlChar *str = NULL;
14149                         /*
14150                         * (2.1.1) "one of the following must be true:"
14151                         * (2.1.1.1) "B's {required} is false."
14152                         * (2.1.1.2) "R's {required} is true."
14153                         */
14154                         xmlSchemaPAttrUseErr4(pctxt,
14155                             XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14156                             WXS_ITEM_NODE(item), item, cur,
14157                             "The 'optional' attribute use is inconsistent "
14158                             "with the corresponding 'required' attribute use of "
14159                             "the %s %s",
14160                             WXS_ACTION_STR(action),
14161                             xmlSchemaGetComponentDesignation(&str, baseItem),
14162                             NULL, NULL);
14163                         FREE_AND_NULL(str);
14164                         /* err = pctxt->err; */
14165                     } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
14166                         WXS_ATTRUSE_TYPEDEF(cur),
14167                         WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14168                     {
14169                         xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14170
14171                         /*
14172                         * SPEC (2.1.2) "R's {attribute declaration}'s
14173                         * {type definition} must be validly derived from
14174                         * B's {type definition} given the empty set as
14175                         * defined in Type Derivation OK (Simple) ($3.14.6)."
14176                         */
14177                         xmlSchemaPAttrUseErr4(pctxt,
14178                             XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14179                             WXS_ITEM_NODE(item), item, cur,
14180                             "The attribute declaration's %s "
14181                             "is not validly derived from "
14182                             "the corresponding %s of the "
14183                             "attribute declaration in the %s %s",
14184                             xmlSchemaGetComponentDesignation(&strA,
14185                                 WXS_ATTRUSE_TYPEDEF(cur)),
14186                             xmlSchemaGetComponentDesignation(&strB,
14187                                 WXS_ATTRUSE_TYPEDEF(bcur)),
14188                             WXS_ACTION_STR(action),
14189                             xmlSchemaGetComponentDesignation(&strC, baseItem));
14190                             /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14191                         FREE_AND_NULL(strA);
14192                         FREE_AND_NULL(strB);
14193                         FREE_AND_NULL(strC);
14194                         /* err = pctxt->err; */
14195                     } else {
14196                         /*
14197                         * 2.1.3 [Definition:]  Let the effective value
14198                         * constraint of an attribute use be its {value
14199                         * constraint}, if present, otherwise its {attribute
14200                         * declaration}'s {value constraint} .
14201                         */
14202                         xmlSchemaGetEffectiveValueConstraint(bcur,
14203                             &effFixed, &bEffValue, NULL);
14204                         /*
14205                         * 2.1.3 ... one of the following must be true
14206                         *
14207                         * 2.1.3.1 B's `effective value constraint` is
14208                         * `absent` or default.
14209                         */
14210                         if ((bEffValue != NULL) &&
14211                             (effFixed == 1)) {
14212                             const xmlChar *rEffValue = NULL;
14213
14214                             xmlSchemaGetEffectiveValueConstraint(bcur,
14215                                 &effFixed, &rEffValue, NULL);
14216                             /*
14217                             * 2.1.3.2 R's `effective value constraint` is
14218                             * fixed with the same string as B's.
14219                             * MAYBE TODO: Compare the computed values.
14220                             *       Hmm, it says "same string" so
14221                             *       string-equality might really be sufficient.
14222                             */
14223                             if ((effFixed == 0) ||
14224                                 (! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14225                             {
14226                                 xmlChar *str = NULL;
14227
14228                                 xmlSchemaPAttrUseErr4(pctxt,
14229                                     XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14230                                     WXS_ITEM_NODE(item), item, cur,
14231                                     "The effective value constraint of the "
14232                                     "attribute use is inconsistent with "
14233                                     "its correspondent in the %s %s",
14234                                     WXS_ACTION_STR(action),
14235                                     xmlSchemaGetComponentDesignation(&str,
14236                                         baseItem),
14237                                     NULL, NULL);
14238                                 FREE_AND_NULL(str);
14239                                 /* err = pctxt->err; */
14240                             }
14241                         }
14242                     }
14243                     break;
14244                 }
14245             }
14246 not_found:
14247             if (!found) {
14248                 /*
14249                 * (2.2) "otherwise the {base type definition} must have an
14250                 * {attribute wildcard} and the {target namespace} of the
14251                 * R's {attribute declaration} must be `valid` with respect
14252                 * to that wildcard, as defined in Wildcard allows Namespace
14253                 * Name ($3.10.4)."
14254                 */
14255                 if ((baseWild == NULL) ||
14256                     (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14257                     (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14258                 {
14259                     xmlChar *str = NULL;
14260
14261                     xmlSchemaPAttrUseErr4(pctxt,
14262                         XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14263                         WXS_ITEM_NODE(item), item, cur,
14264                         "Neither a matching attribute use, "
14265                         "nor a matching wildcard exists in the %s %s",
14266                         WXS_ACTION_STR(action),
14267                         xmlSchemaGetComponentDesignation(&str, baseItem),
14268                         NULL, NULL);
14269                     FREE_AND_NULL(str);
14270                     /* err = pctxt->err; */
14271                 }
14272             }
14273         }
14274     }
14275     /*
14276     * SPEC derivation-ok-restriction (3):
14277     * (3) "For each attribute use in the {attribute uses} of the {base type
14278     * definition} whose {required} is true, there must be an attribute
14279     * use with an {attribute declaration} with the same {name} and
14280     * {target namespace} as its {attribute declaration} in the {attribute
14281     * uses} of the complex type definition itself whose {required} is true.
14282     */
14283     if (baseUses != NULL) {
14284         for (j = 0; j < baseUses->nbItems; j++) {
14285             bcur = baseUses->items[j];
14286             if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14287                 continue;
14288             found = 0;
14289             if (uses != NULL) {
14290                 for (i = 0; i < uses->nbItems; i++) {
14291                     cur = uses->items[i];
14292                     if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14293                         WXS_ATTRUSE_DECL_NAME(bcur)) &&
14294                         (WXS_ATTRUSE_DECL_TNS(cur) ==
14295                         WXS_ATTRUSE_DECL_TNS(bcur))) {
14296                         found = 1;
14297                         break;
14298                     }
14299                 }
14300             }
14301             if (!found) {
14302                 xmlChar *strA = NULL, *strB = NULL;
14303
14304                 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14305                     XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14306                     NULL, item,
14307                     "A matching attribute use for the "
14308                     "'required' %s of the %s %s is missing",
14309                     xmlSchemaGetComponentDesignation(&strA, bcur),
14310                     WXS_ACTION_STR(action),
14311                     xmlSchemaGetComponentDesignation(&strB, baseItem),
14312                     NULL);
14313                 FREE_AND_NULL(strA);
14314                 FREE_AND_NULL(strB);
14315             }
14316         }
14317     }
14318     /*
14319     * derivation-ok-restriction (4)
14320     */
14321     if (wild != NULL) {
14322         /*
14323         * (4) "If there is an {attribute wildcard}, all of the
14324         * following must be true:"
14325         */
14326         if (baseWild == NULL) {
14327             xmlChar *str = NULL;
14328
14329             /*
14330             * (4.1) "The {base type definition} must also have one."
14331             */
14332             xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14333                 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14334                 NULL, item,
14335                 "The %s has an attribute wildcard, "
14336                 "but the %s %s '%s' does not have one",
14337                 WXS_ITEM_TYPE_NAME(item),
14338                 WXS_ACTION_STR(action),
14339                 WXS_ITEM_TYPE_NAME(baseItem),
14340                 xmlSchemaGetComponentQName(&str, baseItem));
14341             FREE_AND_NULL(str);
14342             return(pctxt->err);
14343         } else if ((baseWild->any == 0) &&
14344                 xmlSchemaCheckCOSNSSubset(wild, baseWild))
14345         {
14346             xmlChar *str = NULL;
14347             /*
14348             * (4.2) "The complex type definition's {attribute wildcard}'s
14349             * {namespace constraint} must be a subset of the {base type
14350             * definition}'s {attribute wildcard}'s {namespace constraint},
14351             * as defined by Wildcard Subset ($3.10.6)."
14352             */
14353             xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14354                 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14355                 NULL, item,
14356                 "The attribute wildcard is not a valid "
14357                 "subset of the wildcard in the %s %s '%s'",
14358                 WXS_ACTION_STR(action),
14359                 WXS_ITEM_TYPE_NAME(baseItem),
14360                 xmlSchemaGetComponentQName(&str, baseItem),
14361                 NULL);
14362             FREE_AND_NULL(str);
14363             return(pctxt->err);
14364         }
14365         /* 4.3 Unless the {base type definition} is the `ur-type
14366         * definition`, the complex type definition's {attribute
14367         * wildcard}'s {process contents} must be identical to or
14368         * stronger than the {base type definition}'s {attribute
14369         * wildcard}'s {process contents}, where strict is stronger
14370         * than lax is stronger than skip.
14371         */
14372         if ((! WXS_IS_ANYTYPE(baseItem)) &&
14373             (wild->processContents < baseWild->processContents)) {
14374             xmlChar *str = NULL;
14375             xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14376                 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14377                 NULL, baseItem,
14378                 "The {process contents} of the attribute wildcard is "
14379                 "weaker than the one 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     }
14388     return(0);
14389 }
14390
14391
14392 static int
14393 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14394                                   xmlSchemaBasicItemPtr item,
14395                                   xmlSchemaWildcardPtr *completeWild,
14396                                   xmlSchemaItemListPtr list,
14397                                   xmlSchemaItemListPtr prohibs);
14398 /**
14399  * xmlSchemaFixupTypeAttributeUses:
14400  * @ctxt:  the schema parser context
14401  * @type:  the complex type definition
14402  *
14403  *
14404  * Builds the wildcard and the attribute uses on the given complex type.
14405  * Returns -1 if an internal error occurs, 0 otherwise.
14406  *
14407  * ATTENTION TODO: Experimantally this uses pointer comparisons for
14408  * strings, so recheck this if we start to hardcode some schemata, since
14409  * they might not be in the same dict.
14410  * NOTE: It is allowed to "extend" the xs:anyType type.
14411  */
14412 static int
14413 xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
14414                                   xmlSchemaTypePtr type)
14415 {
14416     xmlSchemaTypePtr baseType = NULL;
14417     xmlSchemaAttributeUsePtr use;
14418     xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
14419
14420     if (type->baseType == NULL) {
14421         PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14422             "no base type");
14423         return (-1);
14424     }
14425     baseType = type->baseType;
14426     if (WXS_IS_TYPE_NOT_FIXED(baseType))
14427         if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
14428             return(-1);
14429
14430     uses = type->attrUses;
14431     baseUses = baseType->attrUses;
14432     /*
14433     * Expand attribute group references. And build the 'complete'
14434     * wildcard, i.e. intersect multiple wildcards.
14435     * Move attribute prohibitions into a separate list.
14436     */
14437     if (uses != NULL) {
14438         if (WXS_IS_RESTRICTION(type)) {
14439             /*
14440             * This one will transfer all attr. prohibitions
14441             * into pctxt->attrProhibs.
14442             */
14443             if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14444                 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14445                 pctxt->attrProhibs) == -1)
14446             {
14447                 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14448                 "failed to expand attributes");
14449             }
14450             if (pctxt->attrProhibs->nbItems != 0)
14451                 prohibs = pctxt->attrProhibs;
14452         } else {
14453             if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14454                 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14455                 NULL) == -1)
14456             {
14457                 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14458                 "failed to expand attributes");
14459             }
14460         }
14461     }
14462     /*
14463     * Inherit the attribute uses of the base type.
14464     */
14465     if (baseUses != NULL) {
14466         int i, j;
14467         xmlSchemaAttributeUseProhibPtr pro;
14468
14469         if (WXS_IS_RESTRICTION(type)) {
14470             int usesCount;
14471             xmlSchemaAttributeUsePtr tmp;
14472
14473             if (uses != NULL)
14474                 usesCount = uses->nbItems;
14475             else
14476                 usesCount = 0;
14477
14478             /* Restriction. */
14479             for (i = 0; i < baseUses->nbItems; i++) {
14480                 use = baseUses->items[i];
14481                 if (prohibs) {
14482                     /*
14483                     * Filter out prohibited uses.
14484                     */
14485                     for (j = 0; j < prohibs->nbItems; j++) {
14486                         pro = prohibs->items[j];
14487                         if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14488                             (WXS_ATTRUSE_DECL_TNS(use) ==
14489                                 pro->targetNamespace))
14490                         {
14491                             goto inherit_next;
14492                         }
14493                     }
14494                 }
14495                 if (usesCount) {
14496                     /*
14497                     * Filter out existing uses.
14498                     */
14499                     for (j = 0; j < usesCount; j++) {
14500                         tmp = uses->items[j];
14501                         if ((WXS_ATTRUSE_DECL_NAME(use) ==
14502                                 WXS_ATTRUSE_DECL_NAME(tmp)) &&
14503                             (WXS_ATTRUSE_DECL_TNS(use) ==
14504                                 WXS_ATTRUSE_DECL_TNS(tmp)))
14505                         {
14506                             goto inherit_next;
14507                         }
14508                     }
14509                 }
14510                 if (uses == NULL) {
14511                     type->attrUses = xmlSchemaItemListCreate();
14512                     if (type->attrUses == NULL)
14513                         goto exit_failure;
14514                     uses = type->attrUses;
14515                 }
14516                 xmlSchemaItemListAddSize(uses, 2, use);
14517 inherit_next: {}
14518             }
14519         } else {
14520             /* Extension. */
14521             for (i = 0; i < baseUses->nbItems; i++) {
14522                 use = baseUses->items[i];
14523                 if (uses == NULL) {
14524                     type->attrUses = xmlSchemaItemListCreate();
14525                     if (type->attrUses == NULL)
14526                         goto exit_failure;
14527                     uses = type->attrUses;
14528                 }
14529                 xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14530             }
14531         }
14532     }
14533     /*
14534     * Shrink attr. uses.
14535     */
14536     if (uses) {
14537         if (uses->nbItems == 0) {
14538             xmlSchemaItemListFree(uses);
14539             type->attrUses = NULL;
14540         }
14541         /*
14542         * TODO: We could shrink the size of the array
14543         * to fit the actual number of items.
14544         */
14545     }
14546     /*
14547     * Compute the complete wildcard.
14548     */
14549     if (WXS_IS_EXTENSION(type)) {
14550         if (baseType->attributeWildcard != NULL) {
14551             /*
14552             * (3.2.2.1) "If the `base wildcard` is non-`absent`, then
14553             * the appropriate case among the following:"
14554             */
14555             if (type->attributeWildcard != NULL) {
14556                 /*
14557                 * Union the complete wildcard with the base wildcard.
14558                 * SPEC {attribute wildcard}
14559                 * (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14560                 * and {annotation} are those of the `complete wildcard`,
14561                 * and whose {namespace constraint} is the intensional union
14562                 * of the {namespace constraint} of the `complete wildcard`
14563                 * and of the `base wildcard`, as defined in Attribute
14564                 * Wildcard Union ($3.10.6)."
14565                 */
14566                 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14567                     baseType->attributeWildcard) == -1)
14568                     goto exit_failure;
14569             } else {
14570                 /*
14571                 * (3.2.2.1.1) "If the `complete wildcard` is `absent`,
14572                 * then the `base wildcard`."
14573                 */
14574                 type->attributeWildcard = baseType->attributeWildcard;
14575             }
14576         } else {
14577             /*
14578             * (3.2.2.2) "otherwise (the `base wildcard` is `absent`) the
14579             * `complete wildcard`"
14580             * NOOP
14581             */
14582         }
14583     } else {
14584         /*
14585         * SPEC {attribute wildcard}
14586         * (3.1) "If the <restriction> alternative is chosen, then the
14587         * `complete wildcard`;"
14588         * NOOP
14589         */
14590     }
14591
14592     return (0);
14593
14594 exit_failure:
14595     return(-1);
14596 }
14597
14598 /**
14599  * xmlSchemaTypeFinalContains:
14600  * @schema:  the schema
14601  * @type:  the type definition
14602  * @final: the final
14603  *
14604  * Evaluates if a type definition contains the given "final".
14605  * This does take "finalDefault" into account as well.
14606  *
14607  * Returns 1 if the type does containt the given "final",
14608  * 0 otherwise.
14609  */
14610 static int
14611 xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
14612 {
14613     if (type == NULL)
14614         return (0);
14615     if (type->flags & final)
14616         return (1);
14617     else
14618         return (0);
14619 }
14620
14621 /**
14622  * xmlSchemaGetUnionSimpleTypeMemberTypes:
14623  * @type:  the Union Simple Type
14624  *
14625  * Returns a list of member types of @type if existing,
14626  * returns NULL otherwise.
14627  */
14628 static xmlSchemaTypeLinkPtr
14629 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14630 {
14631     while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
14632         if (type->memberTypes != NULL)
14633             return (type->memberTypes);
14634         else
14635             type = type->baseType;
14636     }
14637     return (NULL);
14638 }
14639
14640 /**
14641  * xmlSchemaGetParticleTotalRangeMin:
14642  * @particle: the particle
14643  *
14644  * Schema Component Constraint: Effective Total Range
14645  * (all and sequence) + (choice)
14646  *
14647  * Returns the minimun Effective Total Range.
14648  */
14649 static int
14650 xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
14651 {
14652     if ((particle->children == NULL) ||
14653         (particle->minOccurs == 0))
14654         return (0);
14655     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14656         int min = -1, cur;
14657         xmlSchemaParticlePtr part =
14658             (xmlSchemaParticlePtr) particle->children->children;
14659
14660         if (part == NULL)
14661             return (0);
14662         while (part != NULL) {
14663             if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14664                 (part->children->type == XML_SCHEMA_TYPE_ANY))
14665                 cur = part->minOccurs;
14666             else
14667                 cur = xmlSchemaGetParticleTotalRangeMin(part);
14668             if (cur == 0)
14669                 return (0);
14670             if ((min > cur) || (min == -1))
14671                 min = cur;
14672             part = (xmlSchemaParticlePtr) part->next;
14673         }
14674         return (particle->minOccurs * min);
14675     } else {
14676         /* <all> and <sequence> */
14677         int sum = 0;
14678         xmlSchemaParticlePtr part =
14679             (xmlSchemaParticlePtr) particle->children->children;
14680
14681         if (part == NULL)
14682             return (0);
14683         do {
14684             if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14685                 (part->children->type == XML_SCHEMA_TYPE_ANY))
14686                 sum += part->minOccurs;
14687             else
14688                 sum += xmlSchemaGetParticleTotalRangeMin(part);
14689             part = (xmlSchemaParticlePtr) part->next;
14690         } while (part != NULL);
14691         return (particle->minOccurs * sum);
14692     }
14693 }
14694
14695 #if 0
14696 /**
14697  * xmlSchemaGetParticleTotalRangeMax:
14698  * @particle: the particle
14699  *
14700  * Schema Component Constraint: Effective Total Range
14701  * (all and sequence) + (choice)
14702  *
14703  * Returns the maximum Effective Total Range.
14704  */
14705 static int
14706 xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14707 {
14708     if ((particle->children == NULL) ||
14709         (particle->children->children == NULL))
14710         return (0);
14711     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14712         int max = -1, cur;
14713         xmlSchemaParticlePtr part =
14714             (xmlSchemaParticlePtr) particle->children->children;
14715
14716         for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14717             if (part->children == NULL)
14718                 continue;
14719             if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14720                 (part->children->type == XML_SCHEMA_TYPE_ANY))
14721                 cur = part->maxOccurs;
14722             else
14723                 cur = xmlSchemaGetParticleTotalRangeMax(part);
14724             if (cur == UNBOUNDED)
14725                 return (UNBOUNDED);
14726             if ((max < cur) || (max == -1))
14727                 max = cur;
14728         }
14729         /* TODO: Handle overflows? */
14730         return (particle->maxOccurs * max);
14731     } else {
14732         /* <all> and <sequence> */
14733         int sum = 0, cur;
14734         xmlSchemaParticlePtr part =
14735             (xmlSchemaParticlePtr) particle->children->children;
14736
14737         for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14738             if (part->children == NULL)
14739                 continue;
14740             if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14741                 (part->children->type == XML_SCHEMA_TYPE_ANY))
14742                 cur = part->maxOccurs;
14743             else
14744                 cur = xmlSchemaGetParticleTotalRangeMax(part);
14745             if (cur == UNBOUNDED)
14746                 return (UNBOUNDED);
14747             if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14748                 return (UNBOUNDED);
14749             sum += cur;
14750         }
14751         /* TODO: Handle overflows? */
14752         return (particle->maxOccurs * sum);
14753     }
14754 }
14755 #endif
14756
14757 /**
14758  * xmlSchemaIsParticleEmptiable:
14759  * @particle: the particle
14760  *
14761  * Schema Component Constraint: Particle Emptiable
14762  * Checks whether the given particle is emptiable.
14763  *
14764  * Returns 1 if emptiable, 0 otherwise.
14765  */
14766 static int
14767 xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14768 {
14769     /*
14770     * SPEC (1) "Its {min occurs} is 0."
14771     */
14772     if ((particle == NULL) || (particle->minOccurs == 0) ||
14773         (particle->children == NULL))
14774         return (1);
14775     /*
14776     * SPEC (2) "Its {term} is a group and the minimum part of the
14777     * effective total range of that group, [...] is 0."
14778     */
14779     if (WXS_IS_MODEL_GROUP(particle->children)) {
14780         if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
14781             return (1);
14782     }
14783     return (0);
14784 }
14785
14786 /**
14787  * xmlSchemaCheckCOSSTDerivedOK:
14788  * @actxt: a context
14789  * @type:  the derived simple type definition
14790  * @baseType:  the base type definition
14791  * @subset: the subset of ('restriction', ect.)
14792  *
14793  * Schema Component Constraint:
14794  * Type Derivation OK (Simple) (cos-st-derived-OK)
14795  *
14796  * Checks wheter @type can be validly
14797  * derived from @baseType.
14798  *
14799  * Returns 0 on success, an positive error code otherwise.
14800  */
14801 static int
14802 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
14803                              xmlSchemaTypePtr type,
14804                              xmlSchemaTypePtr baseType,
14805                              int subset)
14806 {
14807     /*
14808     * 1 They are the same type definition.
14809     * TODO: The identy check might have to be more complex than this.
14810     */
14811     if (type == baseType)
14812         return (0);
14813     /*
14814     * 2.1 restriction is not in the subset, or in the {final}
14815     * of its own {base type definition};
14816     *
14817     * NOTE that this will be used also via "xsi:type".
14818     *
14819     * TODO: Revise this, it looks strange. How can the "type"
14820     * not be fixed or *in* fixing?
14821     */
14822     if (WXS_IS_TYPE_NOT_FIXED(type))
14823         if (xmlSchemaTypeFixup(type, actxt) == -1)
14824             return(-1);
14825     if (WXS_IS_TYPE_NOT_FIXED(baseType))
14826         if (xmlSchemaTypeFixup(baseType, actxt) == -1)
14827             return(-1);
14828     if ((subset & SUBSET_RESTRICTION) ||
14829         (xmlSchemaTypeFinalContains(type->baseType,
14830             XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14831         return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
14832     }
14833     /* 2.2 */
14834     if (type->baseType == baseType) {
14835         /*
14836         * 2.2.1 D's `base type definition` is B.
14837         */
14838         return (0);
14839     }
14840     /*
14841     * 2.2.2 D's `base type definition` is not the `ur-type definition`
14842     * and is validly derived from B given the subset, as defined by this
14843     * constraint.
14844     */
14845     if ((! WXS_IS_ANYTYPE(type->baseType)) &&
14846         (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
14847             baseType, subset) == 0)) {
14848         return (0);
14849     }
14850     /*
14851     * 2.2.3 D's {variety} is list or union and B is the `simple ur-type
14852     * definition`.
14853     */
14854     if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14855         (WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
14856         return (0);
14857     }
14858     /*
14859     * 2.2.4 B's {variety} is union and D is validly derived from a type
14860     * definition in B's {member type definitions} given the subset, as
14861     * defined by this constraint.
14862     *
14863     * NOTE: This seems not to involve built-in types, since there is no
14864     * built-in Union Simple Type.
14865     */
14866     if (WXS_IS_UNION(baseType)) {
14867         xmlSchemaTypeLinkPtr cur;
14868
14869         cur = baseType->memberTypes;
14870         while (cur != NULL) {
14871             if (WXS_IS_TYPE_NOT_FIXED(cur->type))
14872                 if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
14873                     return(-1);
14874             if (xmlSchemaCheckCOSSTDerivedOK(actxt,
14875                     type, cur->type, subset) == 0)
14876             {
14877                 /*
14878                 * It just has to be validly derived from at least one
14879                 * member-type.
14880                 */
14881                 return (0);
14882             }
14883             cur = cur->next;
14884         }
14885     }
14886     return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14887 }
14888
14889 /**
14890  * xmlSchemaCheckTypeDefCircularInternal:
14891  * @pctxt:  the schema parser context
14892  * @ctxtType:  the type definition
14893  * @ancestor: an ancestor of @ctxtType
14894  *
14895  * Checks st-props-correct (2) + ct-props-correct (3).
14896  * Circular type definitions are not allowed.
14897  *
14898  * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
14899  * circular, 0 otherwise.
14900  */
14901 static int
14902 xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14903                            xmlSchemaTypePtr ctxtType,
14904                            xmlSchemaTypePtr ancestor)
14905 {
14906     int ret;
14907
14908     if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14909         return (0);
14910
14911     if (ctxtType == ancestor) {
14912         xmlSchemaPCustomErr(pctxt,
14913             XML_SCHEMAP_ST_PROPS_CORRECT_2,
14914             WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
14915             "The definition is circular", NULL);
14916         return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14917     }
14918     if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14919         /*
14920         * Avoid inifinite recursion on circular types not yet checked.
14921         */
14922         return (0);
14923     }
14924     ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14925     ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14926         ancestor->baseType);
14927     ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14928     return (ret);
14929 }
14930
14931 /**
14932  * xmlSchemaCheckTypeDefCircular:
14933  * @item:  the complex/simple type definition
14934  * @ctxt:  the parser context
14935  * @name:  the name
14936  *
14937  * Checks for circular type definitions.
14938  */
14939 static void
14940 xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
14941                               xmlSchemaParserCtxtPtr ctxt)
14942 {
14943     if ((item == NULL) ||
14944         (item->type == XML_SCHEMA_TYPE_BASIC) ||
14945         (item->baseType == NULL))
14946         return;
14947     xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
14948         item->baseType);
14949 }
14950
14951 /*
14952 * Simple Type Definition Representation OK (src-simple-type) 4
14953 *
14954 * "4 Circular union type definition is disallowed. That is, if the
14955 * <union> alternative is chosen, there must not be any entries in the
14956 * memberTypes [attribute] at any depth which resolve to the component
14957 * corresponding to the <simpleType>."
14958 *
14959 * Note that this should work on the *representation* of a component,
14960 * thus assumes any union types in the member types not being yet
14961 * substituted. At this stage we need the variety of the types
14962 * to be already computed.
14963 */
14964 static int
14965 xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
14966                                         xmlSchemaTypePtr ctxType,
14967                                         xmlSchemaTypeLinkPtr members)
14968 {
14969     xmlSchemaTypeLinkPtr member;
14970     xmlSchemaTypePtr memberType;
14971
14972     member = members;
14973     while (member != NULL) {
14974         memberType = member->type;
14975         while ((memberType != NULL) &&
14976             (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
14977             if (memberType == ctxType) {
14978                 xmlSchemaPCustomErr(pctxt,
14979                     XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
14980                     WXS_BASIC_CAST ctxType, NULL,
14981                     "The union type definition is circular", NULL);
14982                 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
14983             }
14984             if ((WXS_IS_UNION(memberType)) &&
14985                 ((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
14986             {
14987                 int res;
14988                 memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
14989                 res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
14990                     ctxType,
14991                     xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
14992                 memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
14993                 if (res != 0)
14994                     return(res);
14995             }
14996             memberType = memberType->baseType;
14997         }
14998         member = member->next;
14999     }
15000     return(0);
15001 }
15002
15003 static int
15004 xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
15005                                    xmlSchemaTypePtr type)
15006 {
15007     if (! WXS_IS_UNION(type))
15008         return(0);
15009     return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
15010         type->memberTypes));
15011 }
15012
15013 /**
15014  * xmlSchemaResolveTypeReferences:
15015  * @item:  the complex/simple type definition
15016  * @ctxt:  the parser context
15017  * @name:  the name
15018  *
15019  * Resolvese type definition references
15020  */
15021 static void
15022 xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
15023                          xmlSchemaParserCtxtPtr ctxt)
15024 {
15025     if (typeDef == NULL)
15026         return;
15027
15028     /*
15029     * Resolve the base type.
15030     */
15031     if (typeDef->baseType == NULL) {
15032         typeDef->baseType = xmlSchemaGetType(ctxt->schema,
15033             typeDef->base, typeDef->baseNs);
15034         if (typeDef->baseType == NULL) {
15035             xmlSchemaPResCompAttrErr(ctxt,
15036                 XML_SCHEMAP_SRC_RESOLVE,
15037                 WXS_BASIC_CAST typeDef, typeDef->node,
15038                 "base", typeDef->base, typeDef->baseNs,
15039                 XML_SCHEMA_TYPE_SIMPLE, NULL);
15040             return;
15041         }
15042     }
15043     if (WXS_IS_SIMPLE(typeDef)) {
15044         if (WXS_IS_UNION(typeDef)) {
15045             /*
15046             * Resolve the memberTypes.
15047             */
15048             xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
15049             return;
15050         } else if (WXS_IS_LIST(typeDef)) {
15051             /*
15052             * Resolve the itemType.
15053             */
15054             if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
15055
15056                 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
15057                     typeDef->base, typeDef->baseNs);
15058
15059                 if ((typeDef->subtypes == NULL) ||
15060                     (! WXS_IS_SIMPLE(typeDef->subtypes)))
15061                 {
15062                     typeDef->subtypes = NULL;
15063                     xmlSchemaPResCompAttrErr(ctxt,
15064                         XML_SCHEMAP_SRC_RESOLVE,
15065                         WXS_BASIC_CAST typeDef, typeDef->node,
15066                         "itemType", typeDef->base, typeDef->baseNs,
15067                         XML_SCHEMA_TYPE_SIMPLE, NULL);
15068                 }
15069             }
15070             return;
15071         }
15072     }
15073     /*
15074     * The ball of letters below means, that if we have a particle
15075     * which has a QName-helper component as its {term}, we want
15076     * to resolve it...
15077     */
15078     else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
15079         ((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
15080             XML_SCHEMA_TYPE_PARTICLE) &&
15081         (WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
15082         ((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
15083             XML_SCHEMA_EXTRA_QNAMEREF))
15084     {
15085         xmlSchemaQNameRefPtr ref =
15086             WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
15087         xmlSchemaModelGroupDefPtr groupDef;
15088
15089         /*
15090         * URGENT TODO: Test this.
15091         */
15092         WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
15093         /*
15094         * Resolve the MG definition reference.
15095         */
15096         groupDef =
15097             WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
15098                 ref->itemType, ref->name, ref->targetNamespace);
15099         if (groupDef == NULL) {
15100             xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
15101                 NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
15102                 "ref", ref->name, ref->targetNamespace, ref->itemType,
15103                 NULL);
15104             /* Remove the particle. */
15105             WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15106         } else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
15107             /* Remove the particle. */
15108             WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15109         else {
15110             /*
15111             * Assign the MG definition's {model group} to the
15112             * particle's {term}.
15113             */
15114             WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
15115
15116             if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
15117                 /*
15118                 * SPEC cos-all-limited (1.2)
15119                 * "1.2 the {term} property of a particle with
15120                 * {max occurs}=1 which is part of a pair which constitutes
15121                 * the {content type} of a complex type definition."
15122                 */
15123                 if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
15124                     xmlSchemaCustomErr(ACTXT_CAST ctxt,
15125                         /* TODO: error code */
15126                         XML_SCHEMAP_COS_ALL_LIMITED,
15127                         WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
15128                         "The particle's {max occurs} must be 1, since the "
15129                         "reference resolves to an 'all' model group",
15130                         NULL, NULL);
15131                 }
15132             }
15133         }
15134     }
15135 }
15136
15137
15138
15139 /**
15140  * xmlSchemaCheckSTPropsCorrect:
15141  * @ctxt:  the schema parser context
15142  * @type:  the simple type definition
15143  *
15144  * Checks st-props-correct.
15145  *
15146  * Returns 0 if the properties are correct,
15147  * if not, a positive error code and -1 on internal
15148  * errors.
15149  */
15150 static int
15151 xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
15152                              xmlSchemaTypePtr type)
15153 {
15154     xmlSchemaTypePtr baseType = type->baseType;
15155     xmlChar *str = NULL;
15156
15157     /* STATE: error funcs converted. */
15158     /*
15159     * Schema Component Constraint: Simple Type Definition Properties Correct
15160     *
15161     * NOTE: This is somehow redundant, since we actually built a simple type
15162     * to have all the needed information; this acts as an self test.
15163     */
15164     /* Base type: If the datatype has been `derived` by `restriction`
15165     * then the Simple Type Definition component from which it is `derived`,
15166     * otherwise the Simple Type Definition for anySimpleType ($4.1.6).
15167     */
15168     if (baseType == NULL) {
15169         /*
15170         * TODO: Think about: "modulo the impact of Missing
15171         * Sub-components ($5.3)."
15172         */
15173         xmlSchemaPCustomErr(ctxt,
15174             XML_SCHEMAP_ST_PROPS_CORRECT_1,
15175             WXS_BASIC_CAST type, NULL,
15176             "No base type existent", NULL);
15177         return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15178
15179     }
15180     if (! WXS_IS_SIMPLE(baseType)) {
15181         xmlSchemaPCustomErr(ctxt,
15182             XML_SCHEMAP_ST_PROPS_CORRECT_1,
15183             WXS_BASIC_CAST type, NULL,
15184             "The base type '%s' is not a simple type",
15185             xmlSchemaGetComponentQName(&str, baseType));
15186         FREE_AND_NULL(str)
15187         return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15188     }
15189     if ((WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
15190         (WXS_IS_RESTRICTION(type) == 0) &&
15191         ((! WXS_IS_ANY_SIMPLE_TYPE(baseType)) &&
15192          (baseType->type != XML_SCHEMA_TYPE_SIMPLE))) {
15193         xmlSchemaPCustomErr(ctxt,
15194             XML_SCHEMAP_ST_PROPS_CORRECT_1,
15195             WXS_BASIC_CAST type, NULL,
15196             "A type, derived by list or union, must have "
15197             "the simple ur-type definition as base type, not '%s'",
15198             xmlSchemaGetComponentQName(&str, baseType));
15199         FREE_AND_NULL(str)
15200         return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15201     }
15202     /*
15203     * Variety: One of {atomic, list, union}.
15204     */
15205     if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15206         (! WXS_IS_LIST(type))) {
15207         xmlSchemaPCustomErr(ctxt,
15208             XML_SCHEMAP_ST_PROPS_CORRECT_1,
15209             WXS_BASIC_CAST type, NULL,
15210             "The variety is absent", NULL);
15211         return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15212     }
15213     /* TODO: Finish this. Hmm, is this finished? */
15214
15215     /*
15216     * 3 The {final} of the {base type definition} must not contain restriction.
15217     */
15218     if (xmlSchemaTypeFinalContains(baseType,
15219         XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15220         xmlSchemaPCustomErr(ctxt,
15221             XML_SCHEMAP_ST_PROPS_CORRECT_3,
15222             WXS_BASIC_CAST type, NULL,
15223             "The 'final' of its base type '%s' must not contain "
15224             "'restriction'",
15225             xmlSchemaGetComponentQName(&str, baseType));
15226         FREE_AND_NULL(str)
15227         return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
15228     }
15229
15230     /*
15231     * 2 All simple type definitions must be derived ultimately from the `simple
15232     * ur-type definition` (so circular definitions are disallowed). That is, it
15233     * must be possible to reach a built-in primitive datatype or the `simple
15234     * ur-type definition` by repeatedly following the {base type definition}.
15235     *
15236     * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
15237     */
15238     return (0);
15239 }
15240
15241 /**
15242  * xmlSchemaCheckCOSSTRestricts:
15243  * @ctxt:  the schema parser context
15244  * @type:  the simple type definition
15245  *
15246  * Schema Component Constraint:
15247  * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15248
15249  * Checks if the given @type (simpleType) is derived validly by restriction.
15250  * STATUS:
15251  *
15252  * Returns -1 on internal errors, 0 if the type is validly derived,
15253  * a positive error code otherwise.
15254  */
15255 static int
15256 xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
15257                              xmlSchemaTypePtr type)
15258 {
15259     xmlChar *str = NULL;
15260
15261     if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
15262         PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15263             "given type is not a user-derived simpleType");
15264         return (-1);
15265     }
15266
15267     if (WXS_IS_ATOMIC(type)) {
15268         xmlSchemaTypePtr primitive;
15269         /*
15270         * 1.1 The {base type definition} must be an atomic simple
15271         * type definition or a built-in primitive datatype.
15272         */
15273         if (! WXS_IS_ATOMIC(type->baseType)) {
15274             xmlSchemaPCustomErr(pctxt,
15275                 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
15276                 WXS_BASIC_CAST type, NULL,
15277                 "The base type '%s' is not an atomic simple type",
15278                 xmlSchemaGetComponentQName(&str, type->baseType));
15279             FREE_AND_NULL(str)
15280             return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15281         }
15282         /* 1.2 The {final} of the {base type definition} must not contain
15283         * restriction.
15284         */
15285         /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
15286         if (xmlSchemaTypeFinalContains(type->baseType,
15287             XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15288             xmlSchemaPCustomErr(pctxt,
15289                 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
15290                 WXS_BASIC_CAST type, NULL,
15291                 "The final of its base type '%s' must not contain 'restriction'",
15292                 xmlSchemaGetComponentQName(&str, type->baseType));
15293             FREE_AND_NULL(str)
15294             return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15295         }
15296
15297         /*
15298         * 1.3.1 DF must be an allowed constraining facet for the {primitive
15299         * type definition}, as specified in the appropriate subsection of 3.2
15300         * Primitive datatypes.
15301         */
15302         if (type->facets != NULL) {
15303             xmlSchemaFacetPtr facet;
15304             int ok = 1;
15305
15306             primitive = xmlSchemaGetPrimitiveType(type);
15307             if (primitive == NULL) {
15308                 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15309                     "failed to get primitive type");
15310                 return (-1);
15311             }
15312             facet = type->facets;
15313             do {
15314                 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
15315                     ok = 0;
15316                     xmlSchemaPIllegalFacetAtomicErr(pctxt,
15317                         XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
15318                         type, primitive, facet);
15319                 }
15320                 facet = facet->next;
15321             } while (facet != NULL);
15322             if (ok == 0)
15323                 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
15324         }
15325         /*
15326         * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15327         * of the {base type definition} (call this BF),then the DF's {value}
15328         * must be a valid restriction of BF's {value} as defined in
15329         * [XML Schemas: Datatypes]."
15330         *
15331         * NOTE (1.3.2) Facet derivation constraints are currently handled in
15332         * xmlSchemaDeriveAndValidateFacets()
15333         */
15334     } else if (WXS_IS_LIST(type)) {
15335         xmlSchemaTypePtr itemType = NULL;
15336
15337         itemType = type->subtypes;
15338         if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
15339             PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15340                 "failed to evaluate the item type");
15341             return (-1);
15342         }
15343         if (WXS_IS_TYPE_NOT_FIXED(itemType))
15344             xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
15345         /*
15346         * 2.1 The {item type definition} must have a {variety} of atomic or
15347         * union (in which case all the {member type definitions}
15348         * must be atomic).
15349         */
15350         if ((! WXS_IS_ATOMIC(itemType)) &&
15351             (! WXS_IS_UNION(itemType))) {
15352             xmlSchemaPCustomErr(pctxt,
15353                 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15354                 WXS_BASIC_CAST type, NULL,
15355                 "The item type '%s' does not have a variety of atomic or union",
15356                 xmlSchemaGetComponentQName(&str, itemType));
15357             FREE_AND_NULL(str)
15358             return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15359         } else if (WXS_IS_UNION(itemType)) {
15360             xmlSchemaTypeLinkPtr member;
15361
15362             member = itemType->memberTypes;
15363             while (member != NULL) {
15364                 if (! WXS_IS_ATOMIC(member->type)) {
15365                     xmlSchemaPCustomErr(pctxt,
15366                         XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15367                         WXS_BASIC_CAST type, NULL,
15368                         "The item type is a union type, but the "
15369                         "member type '%s' of this item type is not atomic",
15370                         xmlSchemaGetComponentQName(&str, member->type));
15371                     FREE_AND_NULL(str)
15372                     return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15373                 }
15374                 member = member->next;
15375             }
15376         }
15377
15378         if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
15379             xmlSchemaFacetPtr facet;
15380             /*
15381             * This is the case if we have: <simpleType><list ..
15382             */
15383             /*
15384             * 2.3.1
15385             * 2.3.1.1 The {final} of the {item type definition} must not
15386             * contain list.
15387             */
15388             if (xmlSchemaTypeFinalContains(itemType,
15389                 XML_SCHEMAS_TYPE_FINAL_LIST)) {
15390                 xmlSchemaPCustomErr(pctxt,
15391                     XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
15392                     WXS_BASIC_CAST type, NULL,
15393                     "The final of its item type '%s' must not contain 'list'",
15394                     xmlSchemaGetComponentQName(&str, itemType));
15395                 FREE_AND_NULL(str)
15396                 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15397             }
15398             /*
15399             * 2.3.1.2 The {facets} must only contain the whiteSpace
15400             * facet component.
15401             * OPTIMIZE TODO: the S4S already disallows any facet
15402             * to be specified.
15403             */
15404             if (type->facets != NULL) {
15405                 facet = type->facets;
15406                 do {
15407                     if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15408                         xmlSchemaPIllegalFacetListUnionErr(pctxt,
15409                             XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
15410                             type, facet);
15411                         return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15412                     }
15413                     facet = facet->next;
15414                 } while (facet != NULL);
15415             }
15416             /*
15417             * MAYBE TODO: (Hmm, not really) Datatypes states:
15418             * A `list` datatype can be `derived` from an `atomic` datatype
15419             * whose `lexical space` allows space (such as string or anyURI)or
15420             * a `union` datatype any of whose {member type definitions}'s
15421             * `lexical space` allows space.
15422             */
15423         } else {
15424             /*
15425             * This is the case if we have: <simpleType><restriction ...
15426             * I.e. the variety of "list" is inherited.
15427             */
15428             /*
15429             * 2.3.2
15430             * 2.3.2.1 The {base type definition} must have a {variety} of list.
15431             */
15432             if (! WXS_IS_LIST(type->baseType)) {
15433                 xmlSchemaPCustomErr(pctxt,
15434                     XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
15435                     WXS_BASIC_CAST type, NULL,
15436                     "The base type '%s' must be a list type",
15437                     xmlSchemaGetComponentQName(&str, type->baseType));
15438                 FREE_AND_NULL(str)
15439                 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15440             }
15441             /*
15442             * 2.3.2.2 The {final} of the {base type definition} must not
15443             * contain restriction.
15444             */
15445             if (xmlSchemaTypeFinalContains(type->baseType,
15446                 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15447                 xmlSchemaPCustomErr(pctxt,
15448                     XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
15449                     WXS_BASIC_CAST type, NULL,
15450                     "The 'final' of the base type '%s' must not contain 'restriction'",
15451                     xmlSchemaGetComponentQName(&str, type->baseType));
15452                 FREE_AND_NULL(str)
15453                 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15454             }
15455             /*
15456             * 2.3.2.3 The {item type definition} must be validly derived
15457             * from the {base type definition}'s {item type definition} given
15458             * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6).
15459             */
15460             {
15461                 xmlSchemaTypePtr baseItemType;
15462
15463                 baseItemType = type->baseType->subtypes;
15464                 if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
15465                     PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15466                         "failed to eval the item type of a base type");
15467                     return (-1);
15468                 }
15469                 if ((itemType != baseItemType) &&
15470                     (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
15471                         baseItemType, 0) != 0)) {
15472                     xmlChar *strBIT = NULL, *strBT = NULL;
15473                     xmlSchemaPCustomErrExt(pctxt,
15474                         XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
15475                         WXS_BASIC_CAST type, NULL,
15476                         "The item type '%s' is not validly derived from "
15477                         "the item type '%s' of the base type '%s'",
15478                         xmlSchemaGetComponentQName(&str, itemType),
15479                         xmlSchemaGetComponentQName(&strBIT, baseItemType),
15480                         xmlSchemaGetComponentQName(&strBT, type->baseType));
15481
15482                     FREE_AND_NULL(str)
15483                     FREE_AND_NULL(strBIT)
15484                     FREE_AND_NULL(strBT)
15485                     return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15486                 }
15487             }
15488
15489             if (type->facets != NULL) {
15490                 xmlSchemaFacetPtr facet;
15491                 int ok = 1;
15492                 /*
15493                 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
15494                 * and enumeration facet components are allowed among the {facets}.
15495                 */
15496                 facet = type->facets;
15497                 do {
15498                     switch (facet->type) {
15499                         case XML_SCHEMA_FACET_LENGTH:
15500                         case XML_SCHEMA_FACET_MINLENGTH:
15501                         case XML_SCHEMA_FACET_MAXLENGTH:
15502                         case XML_SCHEMA_FACET_WHITESPACE:
15503                             /*
15504                             * TODO: 2.5.1.2 List datatypes
15505                             * The value of `whiteSpace` is fixed to the value collapse.
15506                             */
15507                         case XML_SCHEMA_FACET_PATTERN:
15508                         case XML_SCHEMA_FACET_ENUMERATION:
15509                             break;
15510                         default: {
15511                             xmlSchemaPIllegalFacetListUnionErr(pctxt,
15512                                 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
15513                                 type, facet);
15514                             /*
15515                             * We could return, but it's nicer to report all
15516                             * invalid facets.
15517                             */
15518                             ok = 0;
15519                         }
15520                     }
15521                     facet = facet->next;
15522                 } while (facet != NULL);
15523                 if (ok == 0)
15524                     return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15525                 /*
15526                 * SPEC (2.3.2.5) (same as 1.3.2)
15527                 *
15528                 * NOTE (2.3.2.5) This is currently done in
15529                 * xmlSchemaDeriveAndValidateFacets()
15530                 */
15531             }
15532         }
15533     } else if (WXS_IS_UNION(type)) {
15534         /*
15535         * 3.1 The {member type definitions} must all have {variety} of
15536         * atomic or list.
15537         */
15538         xmlSchemaTypeLinkPtr member;
15539
15540         member = type->memberTypes;
15541         while (member != NULL) {
15542             if (WXS_IS_TYPE_NOT_FIXED(member->type))
15543                 xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
15544
15545             if ((! WXS_IS_ATOMIC(member->type)) &&
15546                 (! WXS_IS_LIST(member->type))) {
15547                 xmlSchemaPCustomErr(pctxt,
15548                     XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
15549                     WXS_BASIC_CAST type, NULL,
15550                     "The member type '%s' is neither an atomic, nor a list type",
15551                     xmlSchemaGetComponentQName(&str, member->type));
15552                 FREE_AND_NULL(str)
15553                 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15554             }
15555             member = member->next;
15556         }
15557         /*
15558         * 3.3.1 If the {base type definition} is the `simple ur-type
15559         * definition`
15560         */
15561         if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
15562             /*
15563             * 3.3.1.1 All of the {member type definitions} must have a
15564             * {final} which does not contain union.
15565             */
15566             member = type->memberTypes;
15567             while (member != NULL) {
15568                 if (xmlSchemaTypeFinalContains(member->type,
15569                     XML_SCHEMAS_TYPE_FINAL_UNION)) {
15570                     xmlSchemaPCustomErr(pctxt,
15571                         XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
15572                         WXS_BASIC_CAST type, NULL,
15573                         "The 'final' of member type '%s' contains 'union'",
15574                         xmlSchemaGetComponentQName(&str, member->type));
15575                     FREE_AND_NULL(str)
15576                     return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15577                 }
15578                 member = member->next;
15579             }
15580             /*
15581             * 3.3.1.2 The {facets} must be empty.
15582             */
15583             if (type->facetSet != NULL) {
15584                 xmlSchemaPCustomErr(pctxt,
15585                     XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
15586                     WXS_BASIC_CAST type, NULL,
15587                     "No facets allowed", NULL);
15588                 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15589             }
15590         } else {
15591             /*
15592             * 3.3.2.1 The {base type definition} must have a {variety} of union.
15593             * I.e. the variety of "list" is inherited.
15594             */
15595             if (! WXS_IS_UNION(type->baseType)) {
15596                 xmlSchemaPCustomErr(pctxt,
15597                     XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
15598                     WXS_BASIC_CAST type, NULL,
15599                     "The base type '%s' is not a union type",
15600                     xmlSchemaGetComponentQName(&str, type->baseType));
15601                 FREE_AND_NULL(str)
15602                 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15603             }
15604             /*
15605             * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15606             */
15607             if (xmlSchemaTypeFinalContains(type->baseType,
15608                 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15609                 xmlSchemaPCustomErr(pctxt,
15610                     XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
15611                     WXS_BASIC_CAST type, NULL,
15612                     "The 'final' of its base type '%s' must not contain 'restriction'",
15613                     xmlSchemaGetComponentQName(&str, type->baseType));
15614                 FREE_AND_NULL(str)
15615                 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15616             }
15617             /*
15618             * 3.3.2.3 The {member type definitions}, in order, must be validly
15619             * derived from the corresponding type definitions in the {base
15620             * type definition}'s {member type definitions} given the empty set,
15621             * as defined in Type Derivation OK (Simple) ($3.14.6).
15622             */
15623             {
15624                 xmlSchemaTypeLinkPtr baseMember;
15625
15626                 /*
15627                 * OPTIMIZE: if the type is restricting, it has no local defined
15628                 * member types and inherits the member types of the base type;
15629                 * thus a check for equality can be skipped.
15630                 */
15631                 /*
15632                 * Even worse: I cannot see a scenario where a restricting
15633                 * union simple type can have other member types as the member
15634                 * types of it's base type. This check seems not necessary with
15635                 * respect to the derivation process in libxml2.
15636                 * But necessary if constructing types with an API.
15637                 */
15638                 if (type->memberTypes != NULL) {
15639                     member = type->memberTypes;
15640                     baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
15641                     if ((member == NULL) && (baseMember != NULL)) {
15642                         PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15643                             "different number of member types in base");
15644                     }
15645                     while (member != NULL) {
15646                         if (baseMember == NULL) {
15647                             PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15648                             "different number of member types in base");
15649                         } else if ((member->type != baseMember->type) &&
15650                             (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
15651                                 member->type, baseMember->type, 0) != 0)) {
15652                             xmlChar *strBMT = NULL, *strBT = NULL;
15653
15654                             xmlSchemaPCustomErrExt(pctxt,
15655                                 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
15656                                 WXS_BASIC_CAST type, NULL,
15657                                 "The member type %s is not validly "
15658                                 "derived from its corresponding member "
15659                                 "type %s of the base type %s",
15660                                 xmlSchemaGetComponentQName(&str, member->type),
15661                                 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15662                                 xmlSchemaGetComponentQName(&strBT, type->baseType));
15663                             FREE_AND_NULL(str)
15664                             FREE_AND_NULL(strBMT)
15665                             FREE_AND_NULL(strBT)
15666                             return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
15667                         }
15668                         member = member->next;
15669                         if (baseMember != NULL)
15670                             baseMember = baseMember->next;
15671                     }
15672                 }
15673             }
15674             /*
15675             * 3.3.2.4 Only pattern and enumeration facet components are
15676             * allowed among the {facets}.
15677             */
15678             if (type->facets != NULL) {
15679                 xmlSchemaFacetPtr facet;
15680                 int ok = 1;
15681
15682                 facet = type->facets;
15683                 do {
15684                     if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15685                         (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
15686                         xmlSchemaPIllegalFacetListUnionErr(pctxt,
15687                                 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
15688                                 type, facet);
15689                         ok = 0;
15690                     }
15691                     facet = facet->next;
15692                 } while (facet != NULL);
15693                 if (ok == 0)
15694                     return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
15695
15696             }
15697             /*
15698             * SPEC (3.3.2.5) (same as 1.3.2)
15699             *
15700             * NOTE (3.3.2.5) This is currently done in
15701             * xmlSchemaDeriveAndValidateFacets()
15702             */
15703         }
15704     }
15705
15706     return (0);
15707 }
15708
15709 /**
15710  * xmlSchemaCheckSRCSimpleType:
15711  * @ctxt:  the schema parser context
15712  * @type:  the simple type definition
15713  *
15714  * Checks crc-simple-type constraints.
15715  *
15716  * Returns 0 if the constraints are satisfied,
15717  * if not a positive error code and -1 on internal
15718  * errors.
15719  */
15720 #if 0
15721 static int
15722 xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15723                             xmlSchemaTypePtr type)
15724 {
15725     /*
15726     * src-simple-type.1 The corresponding simple type definition, if any,
15727     * must satisfy the conditions set out in Constraints on Simple Type
15728     * Definition Schema Components ($3.14.6).
15729     */
15730     if (WXS_IS_RESTRICTION(type)) {
15731         /*
15732         * src-simple-type.2 "If the <restriction> alternative is chosen,
15733         * either it must have a base [attribute] or a <simpleType> among its
15734         * [children], but not both."
15735         * NOTE: This is checked in the parse function of <restriction>.
15736         */
15737         /*
15738         *
15739         */
15740     } else if (WXS_IS_LIST(type)) {
15741         /* src-simple-type.3 "If the <list> alternative is chosen, either it must have
15742         * an itemType [attribute] or a <simpleType> among its [children],
15743         * but not both."
15744         *
15745         * NOTE: This is checked in the parse function of <list>.
15746         */
15747     } else if (WXS_IS_UNION(type)) {
15748         /*
15749         * src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
15750         */
15751     }
15752     return (0);
15753 }
15754 #endif
15755
15756 static int
15757 xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15758 {
15759    if (ctxt->vctxt == NULL) {
15760         ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15761         if (ctxt->vctxt == NULL) {
15762             xmlSchemaPErr(ctxt, NULL,
15763                 XML_SCHEMAP_INTERNAL,
15764                 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
15765                 "failed to create a temp. validation context.\n",
15766                 NULL, NULL);
15767             return (-1);
15768         }
15769         /* TODO: Pass user data. */
15770         xmlSchemaSetValidErrors(ctxt->vctxt,
15771             ctxt->error, ctxt->warning, ctxt->errCtxt);
15772         xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15773             ctxt->serror, ctxt->errCtxt);
15774     }
15775     return (0);
15776 }
15777
15778 static int
15779 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15780                              xmlNodePtr node,
15781                              xmlSchemaTypePtr type,
15782                              const xmlChar *value,
15783                              xmlSchemaValPtr *retVal,
15784                              int fireErrors,
15785                              int normalize,
15786                              int isNormalized);
15787
15788 /**
15789  * xmlSchemaParseCheckCOSValidDefault:
15790  * @pctxt:  the schema parser context
15791  * @type:  the simple type definition
15792  * @value: the default value
15793  * @node: an optional node (the holder of the value)
15794  *
15795  * Schema Component Constraint: Element Default Valid (Immediate)
15796  * (cos-valid-default)
15797  * This will be used by the parser only. For the validator there's
15798  * an other version.
15799  *
15800  * Returns 0 if the constraints are satisfied,
15801  * if not, a positive error code and -1 on internal
15802  * errors.
15803  */
15804 static int
15805 xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15806                                    xmlNodePtr node,
15807                                    xmlSchemaTypePtr type,
15808                                    const xmlChar *value,
15809                                    xmlSchemaValPtr *val)
15810 {
15811     int ret = 0;
15812
15813     /*
15814     * cos-valid-default:
15815     * Schema Component Constraint: Element Default Valid (Immediate)
15816     * For a string to be a valid default with respect to a type
15817     * definition the appropriate case among the following must be true:
15818     */
15819     if WXS_IS_COMPLEX(type) {
15820         /*
15821         * Complex type.
15822         *
15823         * SPEC (2.1) "its {content type} must be a simple type definition
15824         * or mixed."
15825         * SPEC (2.2.2) "If the {content type} is mixed, then the {content
15826         * type}'s particle must be `emptiable` as defined by
15827         * Particle Emptiable ($3.9.6)."
15828         */
15829         if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15830             ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
15831             /* NOTE that this covers (2.2.2) as well. */
15832             xmlSchemaPCustomErr(pctxt,
15833                 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
15834                 WXS_BASIC_CAST type, type->node,
15835                 "For a string to be a valid default, the type definition "
15836                 "must be a simple type or a complex type with mixed content "
15837                 "and a particle emptiable", NULL);
15838             return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15839         }
15840     }
15841     /*
15842     * 1 If the type definition is a simple type definition, then the string
15843     * must be `valid` with respect to that definition as defined by String
15844     * Valid ($3.14.4).
15845     *
15846     * AND
15847     *
15848     * 2.2.1 If the {content type} is a simple type definition, then the
15849     * string must be `valid` with respect to that simple type definition
15850     * as defined by String Valid ($3.14.4).
15851     */
15852     if (WXS_IS_SIMPLE(type))
15853         ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15854             type, value, val, 1, 1, 0);
15855     else if (WXS_HAS_SIMPLE_CONTENT(type))
15856         ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15857             type->contentTypeDef, value, val, 1, 1, 0);
15858     else
15859         return (ret);
15860
15861     if (ret < 0) {
15862         PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15863             "calling xmlSchemaVCheckCVCSimpleType()");
15864     }
15865
15866     return (ret);
15867 }
15868
15869 /**
15870  * xmlSchemaCheckCTPropsCorrect:
15871  * @ctxt:  the schema parser context
15872  * @type:  the complex type definition
15873  *
15874  *.(4.6) Constraints on Complex Type Definition Schema Components
15875  * Schema Component Constraint:
15876  * Complex Type Definition Properties Correct (ct-props-correct)
15877  * STATUS: (seems) complete
15878  *
15879  * Returns 0 if the constraints are satisfied, a positive
15880  * error code if not and -1 if an internal error occured.
15881  */
15882 static int
15883 xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15884                              xmlSchemaTypePtr type)
15885 {
15886     /*
15887     * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15888     *
15889     * SPEC (1) "The values of the properties of a complex type definition must
15890     * be as described in the property tableau in The Complex Type Definition
15891     * Schema Component ($3.4.1), modulo the impact of Missing
15892     * Sub-components ($5.3)."
15893     */
15894     if ((type->baseType != NULL) &&
15895         (WXS_IS_SIMPLE(type->baseType)) &&
15896         (WXS_IS_EXTENSION(type) == 0)) {
15897         /*
15898         * SPEC (2) "If the {base type definition} is a simple type definition,
15899         * the {derivation method} must be extension."
15900         */
15901         xmlSchemaCustomErr(ACTXT_CAST pctxt,
15902             XML_SCHEMAP_SRC_CT_1,
15903             NULL, WXS_BASIC_CAST type,
15904             "If the base type is a simple type, the derivation method must be "
15905             "'extension'", NULL, NULL);
15906         return (XML_SCHEMAP_SRC_CT_1);
15907     }
15908     /*
15909     * SPEC (3) "Circular definitions are disallowed, except for the `ur-type
15910     * definition`. That is, it must be possible to reach the `ur-type
15911     * definition` by repeatedly following the {base type definition}."
15912     *
15913     * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
15914     */
15915     /*
15916     * NOTE that (4) and (5) need the following:
15917     *   - attribute uses need to be already inherited (apply attr. prohibitions)
15918     *   - attribute group references need to be expanded already
15919     *   - simple types need to be typefixed already
15920     */
15921     if (type->attrUses &&
15922         (((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15923     {
15924         xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15925         xmlSchemaAttributeUsePtr use, tmp;
15926         int i, j, hasId = 0;
15927
15928         for (i = uses->nbItems -1; i >= 0; i--) {
15929             use = uses->items[i];
15930
15931             /*
15932             * SPEC ct-props-correct
15933             * (4) "Two distinct attribute declarations in the
15934             * {attribute uses} must not have identical {name}s and
15935             * {target namespace}s."
15936             */
15937             if (i > 0) {
15938                 for (j = i -1; j >= 0; j--) {
15939                     tmp = uses->items[j];
15940                     if ((WXS_ATTRUSE_DECL_NAME(use) ==
15941                         WXS_ATTRUSE_DECL_NAME(tmp)) &&
15942                         (WXS_ATTRUSE_DECL_TNS(use) ==
15943                         WXS_ATTRUSE_DECL_TNS(tmp)))
15944                     {
15945                         xmlChar *str = NULL;
15946
15947                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
15948                             XML_SCHEMAP_AG_PROPS_CORRECT,
15949                             NULL, WXS_BASIC_CAST type,
15950                             "Duplicate %s",
15951                             xmlSchemaGetComponentDesignation(&str, use),
15952                             NULL);
15953                         FREE_AND_NULL(str);
15954                         /*
15955                         * Remove the duplicate.
15956                         */
15957                         if (xmlSchemaItemListRemove(uses, i) == -1)
15958                             goto exit_failure;
15959                         goto next_use;
15960                     }
15961                 }
15962             }
15963             /*
15964             * SPEC ct-props-correct
15965             * (5) "Two distinct attribute declarations in the
15966             * {attribute uses} must not have {type definition}s which
15967             * are or are derived from ID."
15968             */
15969             if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15970                 if (xmlSchemaIsDerivedFromBuiltInType(
15971                     WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
15972                 {
15973                     if (hasId) {
15974                         xmlChar *str = NULL;
15975
15976                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
15977                             XML_SCHEMAP_AG_PROPS_CORRECT,
15978                             NULL, WXS_BASIC_CAST type,
15979                             "There must not exist more than one attribute "
15980                             "declaration of type 'xs:ID' "
15981                             "(or derived from 'xs:ID'). The %s violates this "
15982                             "constraint",
15983                             xmlSchemaGetComponentDesignation(&str, use),
15984                             NULL);
15985                         FREE_AND_NULL(str);
15986                         if (xmlSchemaItemListRemove(uses, i) == -1)
15987                             goto exit_failure;
15988                     }
15989
15990                     hasId = 1;
15991                 }
15992             }
15993 next_use: {}
15994         }
15995     }
15996     return (0);
15997 exit_failure:
15998     return(-1);
15999 }
16000
16001 static int
16002 xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
16003                        xmlSchemaTypePtr typeB)
16004 {
16005     /*
16006     * TODO: This should implement component-identity
16007     * in the future.
16008     */
16009     if ((typeA == NULL) || (typeB == NULL))
16010         return (0);
16011     return (typeA == typeB);
16012 }
16013
16014 /**
16015  * xmlSchemaCheckCOSCTDerivedOK:
16016  * @ctxt:  the schema parser context
16017  * @type:  the to-be derived complex type definition
16018  * @baseType:  the base complex type definition
16019  * @set: the given set
16020  *
16021  * Schema Component Constraint:
16022  * Type Derivation OK (Complex) (cos-ct-derived-ok)
16023  *
16024  * STATUS: completed
16025  *
16026  * Returns 0 if the constraints are satisfied, or 1
16027  * if not.
16028  */
16029 static int
16030 xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16031                              xmlSchemaTypePtr type,
16032                              xmlSchemaTypePtr baseType,
16033                              int set)
16034 {
16035     int equal = xmlSchemaAreEqualTypes(type, baseType);
16036     /* TODO: Error codes. */
16037     /*
16038     * SPEC "For a complex type definition (call it D, for derived)
16039     * to be validly derived from a type definition (call this
16040     * B, for base) given a subset of {extension, restriction}
16041     * all of the following must be true:"
16042     */
16043     if (! equal) {
16044         /*
16045         * SPEC (1) "If B and D are not the same type definition, then the
16046         * {derivation method} of D must not be in the subset."
16047         */
16048         if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
16049             ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
16050             return (1);
16051     } else {
16052         /*
16053         * SPEC (2.1) "B and D must be the same type definition."
16054         */
16055         return (0);
16056     }
16057     /*
16058     * SPEC (2.2) "B must be D's {base type definition}."
16059     */
16060     if (type->baseType == baseType)
16061         return (0);
16062     /*
16063     * SPEC (2.3.1) "D's {base type definition} must not be the `ur-type
16064     * definition`."
16065     */
16066     if (WXS_IS_ANYTYPE(type->baseType))
16067         return (1);
16068
16069     if (WXS_IS_COMPLEX(type->baseType)) {
16070         /*
16071         * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
16072         * must be validly derived from B given the subset as defined by this
16073         * constraint."
16074         */
16075         return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
16076             baseType, set));
16077     } else {
16078         /*
16079         * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
16080         * must be validly derived from B given the subset as defined in Type
16081         * Derivation OK (Simple) ($3.14.6).
16082         */
16083         return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
16084             baseType, set));
16085     }
16086 }
16087
16088 /**
16089  * xmlSchemaCheckCOSDerivedOK:
16090  * @type:  the derived simple type definition
16091  * @baseType:  the base type definition
16092  *
16093  * Calls:
16094  * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
16095  *
16096  * Checks wheter @type can be validly derived from @baseType.
16097  *
16098  * Returns 0 on success, an positive error code otherwise.
16099  */
16100 static int
16101 xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16102                            xmlSchemaTypePtr type,
16103                            xmlSchemaTypePtr baseType,
16104                            int set)
16105 {
16106     if (WXS_IS_SIMPLE(type))
16107         return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
16108     else
16109         return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
16110 }
16111
16112 /**
16113  * xmlSchemaCheckCOSCTExtends:
16114  * @ctxt:  the schema parser context
16115  * @type:  the complex type definition
16116  *
16117  * (3.4.6) Constraints on Complex Type Definition Schema Components
16118  * Schema Component Constraint:
16119  * Derivation Valid (Extension) (cos-ct-extends)
16120  *
16121  * STATUS:
16122  *   missing:
16123  *     (1.5)
16124  *     (1.4.3.2.2.2) "Particle Valid (Extension)"
16125  *
16126  * Returns 0 if the constraints are satisfied, a positive
16127  * error code if not and -1 if an internal error occured.
16128  */
16129 static int
16130 xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16131                            xmlSchemaTypePtr type)
16132 {
16133     xmlSchemaTypePtr base = type->baseType;
16134     /*
16135     * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16136     * temporarily only.
16137     */
16138     /*
16139     * SPEC (1) "If the {base type definition} is a complex type definition,
16140     * then all of the following must be true:"
16141     */
16142     if (WXS_IS_COMPLEX(base)) {
16143         /*
16144         * SPEC (1.1) "The {final} of the {base type definition} must not
16145         * contain extension."
16146         */
16147         if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16148             xmlSchemaPCustomErr(ctxt,
16149                 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16150                 WXS_BASIC_CAST type, NULL,
16151                 "The 'final' of the base type definition "
16152                 "contains 'extension'", NULL);
16153             return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16154         }
16155
16156         /*
16157         * ATTENTION: The constrains (1.2) and (1.3) are not applied,
16158         * since they are automatically satisfied through the
16159         * inheriting mechanism.
16160         * Note that even if redefining components, the inheriting mechanism
16161         * is used.
16162         */
16163 #if 0
16164         /*
16165         * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
16166         * uses}
16167         * of the complex type definition itself, that is, for every attribute
16168         * use in the {attribute uses} of the {base type definition}, there
16169         * must be an attribute use in the {attribute uses} of the complex
16170         * type definition itself whose {attribute declaration} has the same
16171         * {name}, {target namespace} and {type definition} as its attribute
16172         * declaration"
16173         */
16174         if (base->attrUses != NULL) {
16175             int i, j, found;
16176             xmlSchemaAttributeUsePtr use, buse;
16177
16178             for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16179                 buse = (WXS_LIST_CAST base->attrUses)->items[i];
16180                 found = 0;
16181                 if (type->attrUses != NULL) {
16182                     use = (WXS_LIST_CAST type->attrUses)->items[j];
16183                     for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16184                     {
16185                         if ((WXS_ATTRUSE_DECL_NAME(use) ==
16186                                 WXS_ATTRUSE_DECL_NAME(buse)) &&
16187                             (WXS_ATTRUSE_DECL_TNS(use) ==
16188                                 WXS_ATTRUSE_DECL_TNS(buse)) &&
16189                             (WXS_ATTRUSE_TYPEDEF(use) ==
16190                                 WXS_ATTRUSE_TYPEDEF(buse))
16191                         {
16192                             found = 1;
16193                             break;
16194                         }
16195                     }
16196                 }
16197                 if (! found) {
16198                     xmlChar *str = NULL;
16199
16200                     xmlSchemaCustomErr(ACTXT_CAST ctxt,
16201                         XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16202                         NULL, WXS_BASIC_CAST type,
16203                         /*
16204                         * TODO: The report does not indicate that also the
16205                         * type needs to be the same.
16206                         */
16207                         "This type is missing a matching correspondent "
16208                         "for its {base type}'s %s in its {attribute uses}",
16209                         xmlSchemaGetComponentDesignation(&str,
16210                             buse->children),
16211                         NULL);
16212                     FREE_AND_NULL(str)
16213                 }
16214             }
16215         }
16216         /*
16217         * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16218         * definition must also have one, and the base type definition's
16219         * {attribute  wildcard}'s {namespace constraint} must be a subset
16220         * of the complex  type definition's {attribute wildcard}'s {namespace
16221         * constraint}, as defined by Wildcard Subset ($3.10.6)."
16222         */
16223
16224         /*
16225         * MAYBE TODO: Enable if ever needed. But this will be needed only
16226         * if created the type via a schema construction API.
16227         */
16228         if (base->attributeWildcard != NULL) {
16229             if (type->attributeWilcard == NULL) {
16230                 xmlChar *str = NULL;
16231
16232                 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16233                     XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16234                     NULL, type,
16235                     "The base %s has an attribute wildcard, "
16236                     "but this type is missing an attribute wildcard",
16237                     xmlSchemaGetComponentDesignation(&str, base));
16238                 FREE_AND_NULL(str)
16239
16240             } else if (xmlSchemaCheckCOSNSSubset(
16241                 base->attributeWildcard, type->attributeWildcard))
16242             {
16243                 xmlChar *str = NULL;
16244
16245                 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16246                     XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16247                     NULL, type,
16248                     "The attribute wildcard is not a valid "
16249                     "superset of the one in the base %s",
16250                     xmlSchemaGetComponentDesignation(&str, base));
16251                 FREE_AND_NULL(str)
16252             }
16253         }
16254 #endif
16255         /*
16256         * SPEC (1.4) "One of the following must be true:"
16257         */
16258         if ((type->contentTypeDef != NULL) &&
16259             (type->contentTypeDef == base->contentTypeDef)) {
16260             /*
16261             * SPEC (1.4.1) "The {content type} of the {base type definition}
16262             * and the {content type} of the complex type definition itself
16263             * must be the same simple type definition"
16264             * PASS
16265             */
16266         } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16267             (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16268             /*
16269             * SPEC (1.4.2) "The {content type} of both the {base type
16270             * definition} and the complex type definition itself must
16271             * be empty."
16272             * PASS
16273             */
16274         } else {
16275             /*
16276             * SPEC (1.4.3) "All of the following must be true:"
16277             */
16278             if (type->subtypes == NULL) {
16279                 /*
16280                 * SPEC 1.4.3.1 The {content type} of the complex type
16281                 * definition itself must specify a particle.
16282                 */
16283                 xmlSchemaPCustomErr(ctxt,
16284                     XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16285                     WXS_BASIC_CAST type, NULL,
16286                     "The content type must specify a particle", NULL);
16287                 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16288             }
16289             /*
16290             * SPEC (1.4.3.2) "One of the following must be true:"
16291             */
16292             if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16293                 /*
16294                 * SPEC (1.4.3.2.1) "The {content type} of the {base type
16295                 * definition} must be empty.
16296                 * PASS
16297                 */
16298             } else {
16299                 /*
16300                 * SPEC (1.4.3.2.2) "All of the following must be true:"
16301                 */
16302                 if ((type->contentType != base->contentType) ||
16303                     ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16304                     (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16305                     /*
16306                     * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16307                     * or both must be element-only."
16308                     */
16309                     xmlSchemaPCustomErr(ctxt,
16310                         XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16311                         WXS_BASIC_CAST type, NULL,
16312                         "The content type of both, the type and its base "
16313                         "type, must either 'mixed' or 'element-only'", NULL);
16314                     return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16315                 }
16316                 /*
16317                 * URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
16318                 * complex type definition must be a `valid extension`
16319                 * of the {base type definition}'s particle, as defined
16320                 * in Particle Valid (Extension) ($3.9.6)."
16321                 *
16322                 * NOTE that we won't check "Particle Valid (Extension)",
16323                 * since it is ensured by the derivation process in
16324                 * xmlSchemaTypeFixup(). We need to implement this when heading
16325                 * for a construction API
16326                 * TODO: !! This is needed to be checked if redefining a type !!
16327                 */
16328             }
16329             /*
16330             * URGENT TODO (1.5)
16331             */
16332         }
16333     } else {
16334         /*
16335         * SPEC (2) "If the {base type definition} is a simple type definition,
16336         * then all of the following must be true:"
16337         */
16338         if (type->contentTypeDef != base) {
16339             /*
16340             * SPEC (2.1) "The {content type} must be the same simple type
16341             * definition."
16342             */
16343             xmlSchemaPCustomErr(ctxt,
16344                 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16345                 WXS_BASIC_CAST type, NULL,
16346                 "The content type must be the simple base type", NULL);
16347             return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16348         }
16349         if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16350             /*
16351             * SPEC (2.2) "The {final} of the {base type definition} must not
16352             * contain extension"
16353             * NOTE that this is the same as (1.1).
16354             */
16355             xmlSchemaPCustomErr(ctxt,
16356                 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16357                 WXS_BASIC_CAST type, NULL,
16358                 "The 'final' of the base type definition "
16359                 "contains 'extension'", NULL);
16360             return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16361         }
16362     }
16363     return (0);
16364 }
16365
16366 /**
16367  * xmlSchemaCheckDerivationOKRestriction:
16368  * @ctxt:  the schema parser context
16369  * @type:  the complex type definition
16370  *
16371  * (3.4.6) Constraints on Complex Type Definition Schema Components
16372  * Schema Component Constraint:
16373  * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16374  *
16375  * STATUS:
16376  *   missing:
16377  *     (5.4.2) ???
16378  *
16379  * ATTENTION:
16380  * In XML Schema 1.1 this will be:
16381  * Validation Rule: Checking complex type subsumption
16382  *
16383  * Returns 0 if the constraints are satisfied, a positive
16384  * error code if not and -1 if an internal error occured.
16385  */
16386 static int
16387 xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16388                                       xmlSchemaTypePtr type)
16389 {
16390     xmlSchemaTypePtr base;
16391
16392     /*
16393     * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
16394     * temporarily only.
16395     */
16396     base = type->baseType;
16397     if (! WXS_IS_COMPLEX(base)) {
16398         xmlSchemaCustomErr(ACTXT_CAST ctxt,
16399             XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16400             type->node, WXS_BASIC_CAST type,
16401             "The base type must be a complex type", NULL, NULL);
16402         return(ctxt->err);
16403     }
16404     if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16405         /*
16406         * SPEC (1) "The {base type definition} must be a complex type
16407         * definition whose {final} does not contain restriction."
16408         */
16409         xmlSchemaCustomErr(ACTXT_CAST ctxt,
16410             XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16411             type->node, WXS_BASIC_CAST type,
16412             "The 'final' of the base type definition "
16413             "contains 'restriction'", NULL, NULL);
16414         return (ctxt->err);
16415     }
16416     /*
16417     * SPEC (2), (3) and (4)
16418     * Those are handled in a separate function, since the
16419     * same constraints are needed for redefinition of
16420     * attribute groups as well.
16421     */
16422     if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16423         XML_SCHEMA_ACTION_DERIVE,
16424         WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16425         type->attrUses, base->attrUses,
16426         type->attributeWildcard,
16427         base->attributeWildcard) == -1)
16428     {
16429         return(-1);
16430     }
16431     /*
16432     * SPEC (5) "One of the following must be true:"
16433     */
16434     if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16435         /*
16436         * SPEC (5.1) "The {base type definition} must be the
16437         * `ur-type definition`."
16438         * PASS
16439         */
16440     } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16441             (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16442         /*
16443         * SPEC (5.2.1) "The {content type} of the complex type definition
16444         * must be a simple type definition"
16445         *
16446         * SPEC (5.2.2) "One of the following must be true:"
16447         */
16448         if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16449             (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16450         {
16451             int err;
16452             /*
16453             * SPEC (5.2.2.1) "The {content type} of the {base type
16454             * definition} must be a simple type definition from which
16455             * the {content type} is validly derived given the empty
16456             * set as defined in Type Derivation OK (Simple) ($3.14.6)."
16457             *
16458             * ATTENTION TODO: This seems not needed if the type implicitely
16459             * derived from the base type.
16460             *
16461             */
16462             err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16463                 type->contentTypeDef, base->contentTypeDef, 0);
16464             if (err != 0) {
16465                 xmlChar *strA = NULL, *strB = NULL;
16466
16467                 if (err == -1)
16468                     return(-1);
16469                 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16470                     XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16471                     NULL, WXS_BASIC_CAST type,
16472                     "The {content type} %s is not validly derived from the "
16473                     "base type's {content type} %s",
16474                     xmlSchemaGetComponentDesignation(&strA,
16475                         type->contentTypeDef),
16476                     xmlSchemaGetComponentDesignation(&strB,
16477                         base->contentTypeDef));
16478                 FREE_AND_NULL(strA);
16479                 FREE_AND_NULL(strB);
16480                 return(ctxt->err);
16481             }
16482         } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16483             (xmlSchemaIsParticleEmptiable(
16484                 (xmlSchemaParticlePtr) base->subtypes))) {
16485             /*
16486             * SPEC (5.2.2.2) "The {base type definition} must be mixed
16487             * and have a particle which is `emptiable` as defined in
16488             * Particle Emptiable ($3.9.6)."
16489             * PASS
16490             */
16491         } else {
16492             xmlSchemaPCustomErr(ctxt,
16493                 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16494                 WXS_BASIC_CAST type, NULL,
16495                 "The content type of the base type must be either "
16496                 "a simple type or 'mixed' and an emptiable particle", NULL);
16497             return (ctxt->err);
16498         }
16499     } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16500         /*
16501         * SPEC (5.3.1) "The {content type} of the complex type itself must
16502         * be empty"
16503         */
16504         if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16505             /*
16506             * SPEC (5.3.2.1) "The {content type} of the {base type
16507             * definition} must also be empty."
16508             * PASS
16509             */
16510         } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16511             (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16512             xmlSchemaIsParticleEmptiable(
16513                 (xmlSchemaParticlePtr) base->subtypes)) {
16514             /*
16515             * SPEC (5.3.2.2) "The {content type} of the {base type
16516             * definition} must be elementOnly or mixed and have a particle
16517             * which is `emptiable` as defined in Particle Emptiable ($3.9.6)."
16518             * PASS
16519             */
16520         } else {
16521             xmlSchemaPCustomErr(ctxt,
16522                 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16523                 WXS_BASIC_CAST type, NULL,
16524                 "The content type of the base type must be either "
16525                 "empty or 'mixed' (or 'elements-only') and an emptiable "
16526                 "particle", NULL);
16527             return (ctxt->err);
16528         }
16529     } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16530         WXS_HAS_MIXED_CONTENT(type)) {
16531         /*
16532         * SPEC (5.4.1.1) "The {content type} of the complex type definition
16533         * itself must be element-only"
16534         */
16535         if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
16536             /*
16537             * SPEC (5.4.1.2) "The {content type} of the complex type
16538             * definition itself and of the {base type definition} must be
16539             * mixed"
16540             */
16541             xmlSchemaPCustomErr(ctxt,
16542                 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16543                 WXS_BASIC_CAST type, NULL,
16544                 "If the content type is 'mixed', then the content type of the "
16545                 "base type must also be 'mixed'", NULL);
16546             return (ctxt->err);
16547         }
16548         /*
16549         * SPEC (5.4.2) "The particle of the complex type definition itself
16550         * must be a `valid restriction` of the particle of the {content
16551         * type} of the {base type definition} as defined in Particle Valid
16552         * (Restriction) ($3.9.6).
16553         *
16554         * URGENT TODO: (5.4.2)
16555         */
16556     } else {
16557         xmlSchemaPCustomErr(ctxt,
16558             XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16559             WXS_BASIC_CAST type, NULL,
16560             "The type is not a valid restriction of its base type", NULL);
16561         return (ctxt->err);
16562     }
16563     return (0);
16564 }
16565
16566 /**
16567  * xmlSchemaCheckCTComponent:
16568  * @ctxt:  the schema parser context
16569  * @type:  the complex type definition
16570  *
16571  * (3.4.6) Constraints on Complex Type Definition Schema Components
16572  *
16573  * Returns 0 if the constraints are satisfied, a positive
16574  * error code if not and -1 if an internal error occured.
16575  */
16576 static int
16577 xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16578                           xmlSchemaTypePtr type)
16579 {
16580     int ret;
16581     /*
16582     * Complex Type Definition Properties Correct
16583     */
16584     ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16585     if (ret != 0)
16586         return (ret);
16587     if (WXS_IS_EXTENSION(type))
16588         ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16589     else
16590         ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16591     return (ret);
16592 }
16593
16594 /**
16595  * xmlSchemaCheckSRCCT:
16596  * @ctxt:  the schema parser context
16597  * @type:  the complex type definition
16598  *
16599  * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
16600  * Schema Representation Constraint:
16601  * Complex Type Definition Representation OK (src-ct)
16602  *
16603  * Returns 0 if the constraints are satisfied, a positive
16604  * error code if not and -1 if an internal error occured.
16605  */
16606 static int
16607 xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
16608                     xmlSchemaTypePtr type)
16609 {
16610     xmlSchemaTypePtr base;
16611     int ret = 0;
16612
16613     /*
16614     * TODO: Adjust the error codes here, as I used
16615     * XML_SCHEMAP_SRC_CT_1 only yet.
16616     */
16617     base = type->baseType;
16618     if (! WXS_HAS_SIMPLE_CONTENT(type)) {
16619         /*
16620         * 1 If the <complexContent> alternative is chosen, the type definition
16621         * `resolved` to by the `actual value` of the base [attribute]
16622         * must be a complex type definition;
16623         */
16624         if (! WXS_IS_COMPLEX(base)) {
16625             xmlChar *str = NULL;
16626             xmlSchemaPCustomErr(ctxt,
16627                 XML_SCHEMAP_SRC_CT_1,
16628                 WXS_BASIC_CAST type, type->node,
16629                 "If using <complexContent>, the base type is expected to be "
16630                 "a complex type. The base type '%s' is a simple type",
16631                 xmlSchemaFormatQName(&str, base->targetNamespace,
16632                 base->name));
16633             FREE_AND_NULL(str)
16634             return (XML_SCHEMAP_SRC_CT_1);
16635         }
16636     } else {
16637         /*
16638         * SPEC
16639         * 2 If the <simpleContent> alternative is chosen, all of the
16640         * following must be true:
16641         * 2.1 The type definition `resolved` to by the `actual value` of the
16642         * base [attribute] must be one of the following:
16643         */
16644         if (WXS_IS_SIMPLE(base)) {
16645             if (WXS_IS_EXTENSION(type) == 0) {
16646                 xmlChar *str = NULL;
16647                 /*
16648                 * 2.1.3 only if the <extension> alternative is also
16649                 * chosen, a simple type definition.
16650                 */
16651                 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
16652                 xmlSchemaPCustomErr(ctxt,
16653                     XML_SCHEMAP_SRC_CT_1,
16654                     WXS_BASIC_CAST type, NULL,
16655                     "If using <simpleContent> and <restriction>, the base "
16656                     "type must be a complex type. The base type '%s' is "
16657                     "a simple type",
16658                     xmlSchemaFormatQName(&str, base->targetNamespace,
16659                         base->name));
16660                 FREE_AND_NULL(str)
16661                 return (XML_SCHEMAP_SRC_CT_1);
16662             }
16663         } else {
16664             /* Base type is a complex type. */
16665             if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16666                 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16667                 /*
16668                 * 2.1.1 a complex type definition whose {content type} is a
16669                 * simple type definition;
16670                 * PASS
16671                 */
16672                 if (base->contentTypeDef == NULL) {
16673                     xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16674                         WXS_BASIC_CAST type, NULL,
16675                         "Internal error: xmlSchemaCheckSRCCT, "
16676                         "'%s', base type has no content type",
16677                         type->name);
16678                     return (-1);
16679                 }
16680             } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16681                 (WXS_IS_RESTRICTION(type))) {
16682
16683                 /*
16684                 * 2.1.2 only if the <restriction> alternative is also
16685                 * chosen, a complex type definition whose {content type}
16686                 * is mixed and a particle emptiable.
16687                 */
16688                 if (! xmlSchemaIsParticleEmptiable(
16689                     (xmlSchemaParticlePtr) base->subtypes)) {
16690                     ret = XML_SCHEMAP_SRC_CT_1;
16691                 } else
16692                     /*
16693                     * Attention: at this point the <simpleType> child is in
16694                     * ->contentTypeDef (put there during parsing).
16695                     */
16696                     if (type->contentTypeDef == NULL) {
16697                     xmlChar *str = NULL;
16698                     /*
16699                     * 2.2 If clause 2.1.2 above is satisfied, then there
16700                     * must be a <simpleType> among the [children] of
16701                     * <restriction>.
16702                     */
16703                     /* TODO: Change error code to ..._SRC_CT_2_2. */
16704                     xmlSchemaPCustomErr(ctxt,
16705                         XML_SCHEMAP_SRC_CT_1,
16706                         WXS_BASIC_CAST type, NULL,
16707                         "A <simpleType> is expected among the children "
16708                         "of <restriction>, if <simpleContent> is used and "
16709                         "the base type '%s' is a complex type",
16710                         xmlSchemaFormatQName(&str, base->targetNamespace,
16711                         base->name));
16712                     FREE_AND_NULL(str)
16713                     return (XML_SCHEMAP_SRC_CT_1);
16714                 }
16715             } else {
16716                 ret = XML_SCHEMAP_SRC_CT_1;
16717             }
16718         }
16719         if (ret > 0) {
16720             xmlChar *str = NULL;
16721             if (WXS_IS_RESTRICTION(type)) {
16722                 xmlSchemaPCustomErr(ctxt,
16723                     XML_SCHEMAP_SRC_CT_1,
16724                     WXS_BASIC_CAST type, NULL,
16725                     "If <simpleContent> and <restriction> is used, the "
16726                     "base type must be a simple type or a complex type with "
16727                     "mixed content and particle emptiable. The base type "
16728                     "'%s' is none of those",
16729                     xmlSchemaFormatQName(&str, base->targetNamespace,
16730                     base->name));
16731             } else {
16732                 xmlSchemaPCustomErr(ctxt,
16733                     XML_SCHEMAP_SRC_CT_1,
16734                     WXS_BASIC_CAST type, NULL,
16735                     "If <simpleContent> and <extension> is used, the "
16736                     "base type must be a simple type. The base type '%s' "
16737                     "is a complex type",
16738                     xmlSchemaFormatQName(&str, base->targetNamespace,
16739                     base->name));
16740             }
16741             FREE_AND_NULL(str)
16742         }
16743     }
16744     /*
16745     * SPEC (3) "The corresponding complex type definition component must
16746     * satisfy the conditions set out in Constraints on Complex Type
16747     * Definition Schema Components ($3.4.6);"
16748     * NOTE (3) will be done in xmlSchemaTypeFixup().
16749     */
16750     /*
16751     * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
16752     * above for {attribute wildcard} is satisfied, the intensional
16753     * intersection must be expressible, as defined in Attribute Wildcard
16754     * Intersection ($3.10.6).
16755     * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
16756     */
16757     return (ret);
16758 }
16759
16760 #ifdef ENABLE_PARTICLE_RESTRICTION
16761 /**
16762  * xmlSchemaCheckParticleRangeOK:
16763  * @ctxt:  the schema parser context
16764  * @type:  the complex type definition
16765  *
16766  * (3.9.6) Constraints on Particle Schema Components
16767  * Schema Component Constraint:
16768  * Occurrence Range OK (range-ok)
16769  *
16770  * STATUS: complete
16771  *
16772  * Returns 0 if the constraints are satisfied, a positive
16773  * error code if not and -1 if an internal error occured.
16774  */
16775 static int
16776 xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16777                               int bmin, int bmax)
16778 {
16779     if (rmin < bmin)
16780         return (1);
16781     if ((bmax != UNBOUNDED) &&
16782         (rmax > bmax))
16783         return (1);
16784     return (0);
16785 }
16786
16787 /**
16788  * xmlSchemaCheckRCaseNameAndTypeOK:
16789  * @ctxt:  the schema parser context
16790  * @r: the restricting element declaration particle
16791  * @b: the base element declaration particle
16792  *
16793  * (3.9.6) Constraints on Particle Schema Components
16794  * Schema Component Constraint:
16795  * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16796  * (rcase-NameAndTypeOK)
16797  *
16798  * STATUS:
16799  *   MISSING (3.2.3)
16800  *   CLARIFY: (3.2.2)
16801  *
16802  * Returns 0 if the constraints are satisfied, a positive
16803  * error code if not and -1 if an internal error occured.
16804  */
16805 static int
16806 xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16807                                  xmlSchemaParticlePtr r,
16808                                  xmlSchemaParticlePtr b)
16809 {
16810     xmlSchemaElementPtr elemR, elemB;
16811
16812     /* TODO: Error codes (rcase-NameAndTypeOK). */
16813     elemR = (xmlSchemaElementPtr) r->children;
16814     elemB = (xmlSchemaElementPtr) b->children;
16815     /*
16816     * SPEC (1) "The declarations' {name}s and {target namespace}s are
16817     * the same."
16818     */
16819     if ((elemR != elemB) &&
16820         ((! xmlStrEqual(elemR->name, elemB->name)) ||
16821         (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16822         return (1);
16823     /*
16824     * SPEC (2) "R's occurrence range is a valid restriction of B's
16825     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
16826     */
16827     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16828             b->minOccurs, b->maxOccurs) != 0)
16829         return (1);
16830     /*
16831     * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16832     * {scope} are global."
16833     */
16834     if (elemR == elemB)
16835         return (0);
16836     /*
16837     * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16838     */
16839     if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16840         (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16841          return (1);
16842     /*
16843     * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16844     * or is not fixed, or R's declaration's {value constraint} is fixed
16845     * with the same value."
16846     */
16847     if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16848         ((elemR->value == NULL) ||
16849          ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16850          /* TODO: Equality of the initial value or normalized or canonical? */
16851          (! xmlStrEqual(elemR->value, elemB->value))))
16852          return (1);
16853     /*
16854     * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16855     * definitions} is a subset of B's declaration's {identity-constraint
16856     * definitions}, if any."
16857     */
16858     if (elemB->idcs != NULL) {
16859         /* TODO */
16860     }
16861     /*
16862     * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16863     * superset of B's declaration's {disallowed substitutions}."
16864     */
16865     if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16866          ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16867         ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16868          ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16869         ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16870          ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16871          return (1);
16872     /*
16873     * SPEC (3.2.5) "R's {type definition} is validly derived given
16874     * {extension, list, union} from B's {type definition}"
16875     *
16876     * BADSPEC TODO: What's the point of adding "list" and "union" to the
16877     * set, if the corresponding constraints handle "restriction" and
16878     * "extension" only?
16879     *
16880     */
16881     {
16882         int set = 0;
16883
16884         set |= SUBSET_EXTENSION;
16885         set |= SUBSET_LIST;
16886         set |= SUBSET_UNION;
16887         if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
16888             elemB->subtypes, set) != 0)
16889             return (1);
16890     }
16891     return (0);
16892 }
16893
16894 /**
16895  * xmlSchemaCheckRCaseNSCompat:
16896  * @ctxt:  the schema parser context
16897  * @r: the restricting element declaration particle
16898  * @b: the base wildcard particle
16899  *
16900  * (3.9.6) Constraints on Particle Schema Components
16901  * Schema Component Constraint:
16902  * Particle Derivation OK (Elt:Any -- NSCompat)
16903  * (rcase-NSCompat)
16904  *
16905  * STATUS: complete
16906  *
16907  * Returns 0 if the constraints are satisfied, a positive
16908  * error code if not and -1 if an internal error occured.
16909  */
16910 static int
16911 xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16912                             xmlSchemaParticlePtr r,
16913                             xmlSchemaParticlePtr b)
16914 {
16915     /* TODO:Error codes (rcase-NSCompat). */
16916     /*
16917     * SPEC "For an element declaration particle to be a `valid restriction`
16918     * of a wildcard particle all of the following must be true:"
16919     *
16920     * SPEC (1) "The element declaration's {target namespace} is `valid`
16921     * with respect to the wildcard's {namespace constraint} as defined by
16922     * Wildcard allows Namespace Name ($3.10.4)."
16923     */
16924     if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
16925         ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16926         return (1);
16927     /*
16928     * SPEC (2) "R's occurrence range is a valid restriction of B's
16929     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
16930     */
16931     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16932             b->minOccurs, b->maxOccurs) != 0)
16933         return (1);
16934
16935     return (0);
16936 }
16937
16938 /**
16939  * xmlSchemaCheckRCaseRecurseAsIfGroup:
16940  * @ctxt:  the schema parser context
16941  * @r: the restricting element declaration particle
16942  * @b: the base model group particle
16943  *
16944  * (3.9.6) Constraints on Particle Schema Components
16945  * Schema Component Constraint:
16946  * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
16947  * (rcase-RecurseAsIfGroup)
16948  *
16949  * STATUS: TODO
16950  *
16951  * Returns 0 if the constraints are satisfied, a positive
16952  * error code if not and -1 if an internal error occured.
16953  */
16954 static int
16955 xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16956                                     xmlSchemaParticlePtr r,
16957                                     xmlSchemaParticlePtr b)
16958 {
16959     /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16960     TODO
16961     return (0);
16962 }
16963
16964 /**
16965  * xmlSchemaCheckRCaseNSSubset:
16966  * @ctxt:  the schema parser context
16967  * @r: the restricting wildcard particle
16968  * @b: the base wildcard particle
16969  *
16970  * (3.9.6) Constraints on Particle Schema Components
16971  * Schema Component Constraint:
16972  * Particle Derivation OK (Any:Any -- NSSubset)
16973  * (rcase-NSSubset)
16974  *
16975  * STATUS: complete
16976  *
16977  * Returns 0 if the constraints are satisfied, a positive
16978  * error code if not and -1 if an internal error occured.
16979  */
16980 static int
16981 xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
16982                                     xmlSchemaParticlePtr r,
16983                                     xmlSchemaParticlePtr b,
16984                                     int isAnyTypeBase)
16985 {
16986     /* TODO: Error codes (rcase-NSSubset). */
16987     /*
16988     * SPEC (1) "R's occurrence range is a valid restriction of B's
16989     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
16990     */
16991     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16992             b->minOccurs, b->maxOccurs))
16993         return (1);
16994     /*
16995     * SPEC (2) "R's {namespace constraint} must be an intensional subset
16996     * of B's {namespace constraint} as defined by Wildcard Subset ($3.10.6)."
16997     */
16998     if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
16999         (xmlSchemaWildcardPtr) b->children))
17000         return (1);
17001     /*
17002     * SPEC (3) "Unless B is the content model wildcard of the `ur-type
17003     * definition`, R's {process contents} must be identical to or stronger
17004     * than B's {process contents}, where strict is stronger than lax is
17005     * stronger than skip."
17006     */
17007     if (! isAnyTypeBase) {
17008         if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
17009             ((xmlSchemaWildcardPtr) b->children)->processContents)
17010             return (1);
17011     }
17012
17013     return (0);
17014 }
17015
17016 /**
17017  * xmlSchemaCheckCOSParticleRestrict:
17018  * @ctxt:  the schema parser context
17019  * @type:  the complex type definition
17020  *
17021  * (3.9.6) Constraints on Particle Schema Components
17022  * Schema Component Constraint:
17023  * Particle Valid (Restriction) (cos-particle-restrict)
17024  *
17025  * STATUS: TODO
17026  *
17027  * Returns 0 if the constraints are satisfied, a positive
17028  * error code if not and -1 if an internal error occured.
17029  */
17030 static int
17031 xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
17032                                   xmlSchemaParticlePtr r,
17033                                   xmlSchemaParticlePtr b)
17034 {
17035     int ret = 0;
17036
17037     /*part = WXS_TYPE_PARTICLE(type);
17038     basePart = WXS_TYPE_PARTICLE(base);
17039     */
17040
17041     TODO
17042
17043     /*
17044     * SPEC (1) "They are the same particle."
17045     */
17046     if (r == b)
17047         return (0);
17048
17049
17050     return (0);
17051 }
17052
17053 #if 0
17054 /**
17055  * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
17056  * @ctxt:  the schema parser context
17057  * @r: the model group particle
17058  * @b: the base wildcard particle
17059  *
17060  * (3.9.6) Constraints on Particle Schema Components
17061  * Schema Component Constraint:
17062  * Particle Derivation OK (All/Choice/Sequence:Any --
17063  *                         NSRecurseCheckCardinality)
17064  * (rcase-NSRecurseCheckCardinality)
17065  *
17066  * STATUS: TODO: subst-groups
17067  *
17068  * Returns 0 if the constraints are satisfied, a positive
17069  * error code if not and -1 if an internal error occured.
17070  */
17071 static int
17072 xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
17073                                              xmlSchemaParticlePtr r,
17074                                              xmlSchemaParticlePtr b)
17075 {
17076     xmlSchemaParticlePtr part;
17077     /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
17078     if ((r->children == NULL) || (r->children->children == NULL))
17079         return (-1);
17080     /*
17081     * SPEC "For a group particle to be a `valid restriction` of a
17082     * wildcard particle..."
17083     *
17084     * SPEC (1) "Every member of the {particles} of the group is a `valid
17085     * restriction` of the wildcard as defined by
17086     * Particle Valid (Restriction) ($3.9.6)."
17087     */
17088     part = (xmlSchemaParticlePtr) r->children->children;
17089     do {
17090         if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
17091             return (1);
17092         part = (xmlSchemaParticlePtr) part->next;
17093     } while (part != NULL);
17094     /*
17095     * SPEC (2) "The effective total range of the group [...] is a
17096     * valid restriction of B's occurrence range as defined by
17097     * Occurrence Range OK ($3.9.6)."
17098     */
17099     if (xmlSchemaCheckParticleRangeOK(
17100             xmlSchemaGetParticleTotalRangeMin(r),
17101             xmlSchemaGetParticleTotalRangeMax(r),
17102             b->minOccurs, b->maxOccurs) != 0)
17103         return (1);
17104     return (0);
17105 }
17106 #endif
17107
17108 /**
17109  * xmlSchemaCheckRCaseRecurse:
17110  * @ctxt:  the schema parser context
17111  * @r: the <all> or <sequence> model group particle
17112  * @b: the base <all> or <sequence> model group particle
17113  *
17114  * (3.9.6) Constraints on Particle Schema Components
17115  * Schema Component Constraint:
17116  * Particle Derivation OK (All:All,Sequence:Sequence --
17117                            Recurse)
17118  * (rcase-Recurse)
17119  *
17120  * STATUS:  ?
17121  * TODO: subst-groups
17122  *
17123  * Returns 0 if the constraints are satisfied, a positive
17124  * error code if not and -1 if an internal error occured.
17125  */
17126 static int
17127 xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17128                            xmlSchemaParticlePtr r,
17129                            xmlSchemaParticlePtr b)
17130 {
17131     /* xmlSchemaParticlePtr part; */
17132     /* TODO: Error codes (rcase-Recurse). */
17133     if ((r->children == NULL) || (b->children == NULL) ||
17134         (r->children->type != b->children->type))
17135         return (-1);
17136     /*
17137     * SPEC "For an all or sequence group particle to be a `valid
17138     * restriction` of another group particle with the same {compositor}..."
17139     *
17140     * SPEC (1) "R's occurrence range is a valid restriction of B's
17141     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17142     */
17143     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17144             b->minOccurs, b->maxOccurs))
17145         return (1);
17146
17147
17148     return (0);
17149 }
17150
17151 #endif
17152
17153 #define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17154     xmlSchemaPCustomErrExt(pctxt,      \
17155         XML_SCHEMAP_INVALID_FACET_VALUE, \
17156         WXS_BASIC_CAST fac1, fac1->node, \
17157         "It is an error for both '%s' and '%s' to be specified on the "\
17158         "same type definition", \
17159         BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17160         BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17161
17162 #define FACET_RESTR_ERR(fac1, msg) \
17163     xmlSchemaPCustomErr(pctxt,      \
17164         XML_SCHEMAP_INVALID_FACET_VALUE, \
17165         WXS_BASIC_CAST fac1, fac1->node, \
17166         msg, NULL);
17167
17168 #define FACET_RESTR_FIXED_ERR(fac) \
17169     xmlSchemaPCustomErr(pctxt, \
17170         XML_SCHEMAP_INVALID_FACET_VALUE, \
17171         WXS_BASIC_CAST fac, fac->node, \
17172         "The base type's facet is 'fixed', thus the value must not " \
17173         "differ", NULL);
17174
17175 static void
17176 xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17177                         xmlSchemaFacetPtr facet1,
17178                         xmlSchemaFacetPtr facet2,
17179                         int lessGreater,
17180                         int orEqual,
17181                         int ofBase)
17182 {
17183     xmlChar *msg = NULL;
17184
17185     msg = xmlStrdup(BAD_CAST "'");
17186     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17187     msg = xmlStrcat(msg, BAD_CAST "' has to be");
17188     if (lessGreater == 0)
17189         msg = xmlStrcat(msg, BAD_CAST " equal to");
17190     if (lessGreater == 1)
17191         msg = xmlStrcat(msg, BAD_CAST " greater than");
17192     else
17193         msg = xmlStrcat(msg, BAD_CAST " less than");
17194
17195     if (orEqual)
17196         msg = xmlStrcat(msg, BAD_CAST " or equal to");
17197     msg = xmlStrcat(msg, BAD_CAST " '");
17198     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17199     if (ofBase)
17200         msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17201     else
17202         msg = xmlStrcat(msg, BAD_CAST "'");
17203
17204     xmlSchemaPCustomErr(pctxt,
17205         XML_SCHEMAP_INVALID_FACET_VALUE,
17206         WXS_BASIC_CAST facet1, NULL,
17207         (const char *) msg, NULL);
17208
17209     if (msg != NULL)
17210         xmlFree(msg);
17211 }
17212
17213 /*
17214 * xmlSchemaDeriveAndValidateFacets:
17215 *
17216 * Schema Component Constraint: Simple Type Restriction (Facets)
17217 * (st-restrict-facets)
17218 */
17219 static int
17220 xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17221                                  xmlSchemaTypePtr type)
17222 {
17223     xmlSchemaTypePtr base = type->baseType;
17224     xmlSchemaFacetLinkPtr link, cur, last = NULL;
17225     xmlSchemaFacetPtr facet, bfacet,
17226         flength = NULL, ftotdig = NULL, ffracdig = NULL,
17227         fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17228         fmininc = NULL, fmaxinc = NULL,
17229         fminexc = NULL, fmaxexc = NULL,
17230         bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17231         bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17232         bfmininc = NULL, bfmaxinc = NULL,
17233         bfminexc = NULL, bfmaxexc = NULL;
17234     int res; /* err = 0, fixedErr; */
17235
17236     /*
17237     * SPEC st-restrict-facets 1:
17238     * "The {variety} of R is the same as that of B."
17239     */
17240     /*
17241     * SPEC st-restrict-facets 2:
17242     * "If {variety} is atomic, the {primitive type definition}
17243     * of R is the same as that of B."
17244     *
17245     * NOTE: we leave 1 & 2 out for now, since this will be
17246     * satisfied by the derivation process.
17247     * CONSTRUCTION TODO: Maybe needed if using a construction API.
17248     */
17249     /*
17250     * SPEC st-restrict-facets 3:
17251     * "The {facets} of R are the union of S and the {facets}
17252     * of B, eliminating duplicates. To eliminate duplicates,
17253     * when a facet of the same kind occurs in both S and the
17254     * {facets} of B, the one in the {facets} of B is not
17255     * included, with the exception of enumeration and pattern
17256     * facets, for which multiple occurrences with distinct values
17257     * are allowed."
17258     */
17259
17260     if ((type->facetSet == NULL) && (base->facetSet == NULL))
17261         return (0);
17262
17263     last = type->facetSet;
17264     if (last != NULL)
17265         while (last->next != NULL)
17266             last = last->next;
17267
17268     for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17269         facet = cur->facet;
17270         switch (facet->type) {
17271             case XML_SCHEMA_FACET_LENGTH:
17272                 flength = facet; break;
17273             case XML_SCHEMA_FACET_MINLENGTH:
17274                 fminlen = facet; break;
17275             case XML_SCHEMA_FACET_MININCLUSIVE:
17276                 fmininc = facet; break;
17277             case XML_SCHEMA_FACET_MINEXCLUSIVE:
17278                 fminexc = facet; break;
17279             case XML_SCHEMA_FACET_MAXLENGTH:
17280                 fmaxlen = facet; break;
17281             case XML_SCHEMA_FACET_MAXINCLUSIVE:
17282                 fmaxinc = facet; break;
17283             case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17284                 fmaxexc = facet; break;
17285             case XML_SCHEMA_FACET_TOTALDIGITS:
17286                 ftotdig = facet; break;
17287             case XML_SCHEMA_FACET_FRACTIONDIGITS:
17288                 ffracdig = facet; break;
17289             default:
17290                 break;
17291         }
17292     }
17293     for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17294         facet = cur->facet;
17295         switch (facet->type) {
17296             case XML_SCHEMA_FACET_LENGTH:
17297                 bflength = facet; break;
17298             case XML_SCHEMA_FACET_MINLENGTH:
17299                 bfminlen = facet; break;
17300             case XML_SCHEMA_FACET_MININCLUSIVE:
17301                 bfmininc = facet; break;
17302             case XML_SCHEMA_FACET_MINEXCLUSIVE:
17303                 bfminexc = facet; break;
17304             case XML_SCHEMA_FACET_MAXLENGTH:
17305                 bfmaxlen = facet; break;
17306             case XML_SCHEMA_FACET_MAXINCLUSIVE:
17307                 bfmaxinc = facet; break;
17308             case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17309                 bfmaxexc = facet; break;
17310             case XML_SCHEMA_FACET_TOTALDIGITS:
17311                 bftotdig = facet; break;
17312             case XML_SCHEMA_FACET_FRACTIONDIGITS:
17313                 bffracdig = facet; break;
17314             default:
17315                 break;
17316         }
17317     }
17318     /*
17319     * length and minLength or maxLength (2.2) + (3.2)
17320     */
17321     if (flength && (fminlen || fmaxlen)) {
17322         FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17323             "either of 'minLength' or 'maxLength' to be specified on "
17324             "the same type definition")
17325     }
17326     /*
17327     * Mutual exclusions in the same derivation step.
17328     */
17329     if ((fmaxinc) && (fmaxexc)) {
17330         /*
17331         * SCC "maxInclusive and maxExclusive"
17332         */
17333         FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17334     }
17335     if ((fmininc) && (fminexc)) {
17336         /*
17337         * SCC "minInclusive and minExclusive"
17338         */
17339         FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
17340     }
17341
17342     if (flength && bflength) {
17343         /*
17344         * SCC "length valid restriction"
17345         * The values have to be equal.
17346         */
17347         res = xmlSchemaCompareValues(flength->val, bflength->val);
17348         if (res == -2)
17349             goto internal_error;
17350         if (res != 0)
17351             xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17352         if ((res != 0) && (bflength->fixed)) {
17353             FACET_RESTR_FIXED_ERR(flength)
17354         }
17355
17356     }
17357     if (fminlen && bfminlen) {
17358         /*
17359         * SCC "minLength valid restriction"
17360         * minLength >= BASE minLength
17361         */
17362         res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17363         if (res == -2)
17364             goto internal_error;
17365         if (res == -1)
17366             xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17367         if ((res != 0) && (bfminlen->fixed)) {
17368             FACET_RESTR_FIXED_ERR(fminlen)
17369         }
17370     }
17371     if (fmaxlen && bfmaxlen) {
17372         /*
17373         * SCC "maxLength valid restriction"
17374         * maxLength <= BASE minLength
17375         */
17376         res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17377         if (res == -2)
17378             goto internal_error;
17379         if (res == 1)
17380             xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17381         if ((res != 0) && (bfmaxlen->fixed)) {
17382             FACET_RESTR_FIXED_ERR(fmaxlen)
17383         }
17384     }
17385     /*
17386     * SCC "length and minLength or maxLength"
17387     */
17388     if (! flength)
17389         flength = bflength;
17390     if (flength) {
17391         if (! fminlen)
17392             fminlen = bfminlen;
17393         if (fminlen) {
17394             /* (1.1) length >= minLength */
17395             res = xmlSchemaCompareValues(flength->val, fminlen->val);
17396             if (res == -2)
17397                 goto internal_error;
17398             if (res == -1)
17399                 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17400         }
17401         if (! fmaxlen)
17402             fmaxlen = bfmaxlen;
17403         if (fmaxlen) {
17404             /* (2.1) length <= maxLength */
17405             res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17406             if (res == -2)
17407                 goto internal_error;
17408             if (res == 1)
17409                 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17410         }
17411     }
17412     if (fmaxinc) {
17413         /*
17414         * "maxInclusive"
17415         */
17416         if (fmininc) {
17417             /* SCC "maxInclusive >= minInclusive" */
17418             res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17419             if (res == -2)
17420                 goto internal_error;
17421             if (res == -1) {
17422                 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17423             }
17424         }
17425         /*
17426         * SCC "maxInclusive valid restriction"
17427         */
17428         if (bfmaxinc) {
17429             /* maxInclusive <= BASE maxInclusive */
17430             res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17431             if (res == -2)
17432                 goto internal_error;
17433             if (res == 1)
17434                 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17435             if ((res != 0) && (bfmaxinc->fixed)) {
17436                 FACET_RESTR_FIXED_ERR(fmaxinc)
17437             }
17438         }
17439         if (bfmaxexc) {
17440             /* maxInclusive < BASE maxExclusive */
17441             res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17442             if (res == -2)
17443                 goto internal_error;
17444             if (res != -1) {
17445                 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17446             }
17447         }
17448         if (bfmininc) {
17449             /* maxInclusive >= BASE minInclusive */
17450             res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17451             if (res == -2)
17452                 goto internal_error;
17453             if (res == -1) {
17454                 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17455             }
17456         }
17457         if (bfminexc) {
17458             /* maxInclusive > BASE minExclusive */
17459             res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17460             if (res == -2)
17461                 goto internal_error;
17462             if (res != 1) {
17463                 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17464             }
17465         }
17466     }
17467     if (fmaxexc) {
17468         /*
17469         * "maxExclusive >= minExclusive"
17470         */
17471         if (fminexc) {
17472             res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17473             if (res == -2)
17474                 goto internal_error;
17475             if (res == -1) {
17476                 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17477             }
17478         }
17479         /*
17480         * "maxExclusive valid restriction"
17481         */
17482         if (bfmaxexc) {
17483             /* maxExclusive <= BASE maxExclusive */
17484             res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17485             if (res == -2)
17486                 goto internal_error;
17487             if (res == 1) {
17488                 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17489             }
17490             if ((res != 0) && (bfmaxexc->fixed)) {
17491                 FACET_RESTR_FIXED_ERR(fmaxexc)
17492             }
17493         }
17494         if (bfmaxinc) {
17495             /* maxExclusive <= BASE maxInclusive */
17496             res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17497             if (res == -2)
17498                 goto internal_error;
17499             if (res == 1) {
17500                 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17501             }
17502         }
17503         if (bfmininc) {
17504             /* maxExclusive > BASE minInclusive */
17505             res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17506             if (res == -2)
17507                 goto internal_error;
17508             if (res != 1) {
17509                 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17510             }
17511         }
17512         if (bfminexc) {
17513             /* maxExclusive > BASE minExclusive */
17514             res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17515             if (res == -2)
17516                 goto internal_error;
17517             if (res != 1) {
17518                 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17519             }
17520         }
17521     }
17522     if (fminexc) {
17523         /*
17524         * "minExclusive < maxInclusive"
17525         */
17526         if (fmaxinc) {
17527             res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17528             if (res == -2)
17529                 goto internal_error;
17530             if (res != -1) {
17531                 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17532             }
17533         }
17534         /*
17535         * "minExclusive valid restriction"
17536         */
17537         if (bfminexc) {
17538             /* minExclusive >= BASE minExclusive */
17539             res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17540             if (res == -2)
17541                 goto internal_error;
17542             if (res == -1) {
17543                 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17544             }
17545             if ((res != 0) && (bfminexc->fixed)) {
17546                 FACET_RESTR_FIXED_ERR(fminexc)
17547             }
17548         }
17549         if (bfmaxinc) {
17550             /* minExclusive <= BASE maxInclusive */
17551             res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17552             if (res == -2)
17553                 goto internal_error;
17554             if (res == 1) {
17555                 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17556             }
17557         }
17558         if (bfmininc) {
17559             /* minExclusive >= BASE minInclusive */
17560             res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17561             if (res == -2)
17562                 goto internal_error;
17563             if (res == -1) {
17564                 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17565             }
17566         }
17567         if (bfmaxexc) {
17568             /* minExclusive < BASE maxExclusive */
17569             res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17570             if (res == -2)
17571                 goto internal_error;
17572             if (res != -1) {
17573                 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17574             }
17575         }
17576     }
17577     if (fmininc) {
17578         /*
17579         * "minInclusive < maxExclusive"
17580         */
17581         if (fmaxexc) {
17582             res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17583             if (res == -2)
17584                 goto internal_error;
17585             if (res != -1) {
17586                 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17587             }
17588         }
17589         /*
17590         * "minExclusive valid restriction"
17591         */
17592         if (bfmininc) {
17593             /* minInclusive >= BASE minInclusive */
17594             res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17595             if (res == -2)
17596                 goto internal_error;
17597             if (res == -1) {
17598                 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17599             }
17600             if ((res != 0) && (bfmininc->fixed)) {
17601                 FACET_RESTR_FIXED_ERR(fmininc)
17602             }
17603         }
17604         if (bfmaxinc) {
17605             /* minInclusive <= BASE maxInclusive */
17606             res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17607             if (res == -2)
17608                 goto internal_error;
17609             if (res == 1) {
17610                 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17611             }
17612         }
17613         if (bfminexc) {
17614             /* minInclusive > BASE minExclusive */
17615             res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17616             if (res == -2)
17617                 goto internal_error;
17618             if (res != 1)
17619                 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17620         }
17621         if (bfmaxexc) {
17622             /* minInclusive < BASE maxExclusive */
17623             res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17624             if (res == -2)
17625                 goto internal_error;
17626             if (res != -1)
17627                 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17628         }
17629     }
17630     if (ftotdig && bftotdig) {
17631         /*
17632         * SCC " totalDigits valid restriction"
17633         * totalDigits <= BASE totalDigits
17634         */
17635         res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17636         if (res == -2)
17637             goto internal_error;
17638         if (res == 1)
17639             xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17640             -1, 1, 1);
17641         if ((res != 0) && (bftotdig->fixed)) {
17642             FACET_RESTR_FIXED_ERR(ftotdig)
17643         }
17644     }
17645     if (ffracdig && bffracdig) {
17646         /*
17647         * SCC  "fractionDigits valid restriction"
17648         * fractionDigits <= BASE fractionDigits
17649         */
17650         res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17651         if (res == -2)
17652             goto internal_error;
17653         if (res == 1)
17654             xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17655             -1, 1, 1);
17656         if ((res != 0) && (bffracdig->fixed)) {
17657             FACET_RESTR_FIXED_ERR(ffracdig)
17658         }
17659     }
17660     /*
17661     * SCC "fractionDigits less than or equal to totalDigits"
17662     */
17663     if (! ftotdig)
17664         ftotdig = bftotdig;
17665     if (! ffracdig)
17666         ffracdig = bffracdig;
17667     if (ftotdig && ffracdig) {
17668         res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17669         if (res == -2)
17670             goto internal_error;
17671         if (res == 1)
17672             xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17673                 -1, 1, 0);
17674     }
17675     /*
17676     * *Enumerations* won' be added here, since only the first set
17677     * of enumerations in the ancestor-or-self axis is used
17678     * for validation, plus we need to use the base type of those
17679     * enumerations for whitespace.
17680     *
17681     * *Patterns*: won't be add here, since they are ORed at
17682     * type level and ANDed at ancestor level. This will
17683     * happed during validation by walking the base axis
17684     * of the type.
17685     */
17686     for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17687         bfacet = cur->facet;
17688         /*
17689         * Special handling of enumerations and patterns.
17690         * TODO: hmm, they should not appear in the set, so remove this.
17691         */
17692         if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
17693             (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
17694             continue;
17695         /*
17696         * Search for a duplicate facet in the current type.
17697         */
17698         link = type->facetSet;
17699         /* err = 0; */
17700         /* fixedErr = 0; */
17701         while (link != NULL) {
17702             facet = link->facet;
17703             if (facet->type == bfacet->type) {
17704                 switch (facet->type) {
17705                     case XML_SCHEMA_FACET_WHITESPACE:
17706                         /*
17707                         * The whitespace must be stronger.
17708                         */
17709                         if (facet->whitespace < bfacet->whitespace) {
17710                             FACET_RESTR_ERR(facet,
17711                                 "The 'whitespace' value has to be equal to "
17712                                 "or stronger than the 'whitespace' value of "
17713                                 "the base type")
17714                         }
17715                         if ((bfacet->fixed) &&
17716                             (facet->whitespace != bfacet->whitespace)) {
17717                             FACET_RESTR_FIXED_ERR(facet)
17718                         }
17719                         break;
17720                     default:
17721                         break;
17722                 }
17723                 /* Duplicate found. */
17724                 break;
17725             }
17726             link = link->next;
17727         }
17728         /*
17729         * If no duplicate was found: add the base types's facet
17730         * to the set.
17731         */
17732         if (link == NULL) {
17733             link = (xmlSchemaFacetLinkPtr)
17734                 xmlMalloc(sizeof(xmlSchemaFacetLink));
17735             if (link == NULL) {
17736                 xmlSchemaPErrMemory(pctxt,
17737                     "deriving facets, creating a facet link", NULL);
17738                 return (-1);
17739             }
17740             link->facet = cur->facet;
17741             link->next = NULL;
17742             if (last == NULL)
17743                 type->facetSet = link;
17744             else
17745                 last->next = link;
17746             last = link;
17747         }
17748
17749     }
17750
17751     return (0);
17752 internal_error:
17753     PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17754         "an error occured");
17755     return (-1);
17756 }
17757
17758 static int
17759 xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17760                                              xmlSchemaTypePtr type)
17761 {
17762     xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17763     /*
17764     * The actual value is then formed by replacing any union type
17765     * definition in the `explicit members` with the members of their
17766     * {member type definitions}, in order.
17767     *
17768     * TODO: There's a bug entry at
17769     * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17770     * which indicates that we'll keep the union types the future.
17771     */
17772     link = type->memberTypes;
17773     while (link != NULL) {
17774
17775         if (WXS_IS_TYPE_NOT_FIXED(link->type))
17776             xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
17777
17778         if (WXS_IS_UNION(link->type)) {
17779             subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
17780             if (subLink != NULL) {
17781                 link->type = subLink->type;
17782                 if (subLink->next != NULL) {
17783                     lastLink = link->next;
17784                     subLink = subLink->next;
17785                     prevLink = link;
17786                     while (subLink != NULL) {
17787                         newLink = (xmlSchemaTypeLinkPtr)
17788                             xmlMalloc(sizeof(xmlSchemaTypeLink));
17789                         if (newLink == NULL) {
17790                             xmlSchemaPErrMemory(pctxt, "allocating a type link",
17791                                 NULL);
17792                             return (-1);
17793                         }
17794                         newLink->type = subLink->type;
17795                         prevLink->next = newLink;
17796                         prevLink = newLink;
17797                         newLink->next = lastLink;
17798
17799                         subLink = subLink->next;
17800                     }
17801                 }
17802             }
17803         }
17804         link = link->next;
17805     }
17806     return (0);
17807 }
17808
17809 static void
17810 xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17811 {
17812     int has = 0, needVal = 0, normVal = 0;
17813
17814     has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17815     if (has) {
17816         needVal = (type->baseType->flags &
17817             XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17818         normVal = (type->baseType->flags &
17819             XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17820     }
17821     if (type->facets != NULL) {
17822         xmlSchemaFacetPtr fac;
17823
17824         for (fac = type->facets; fac != NULL; fac = fac->next) {
17825             switch (fac->type) {
17826                 case XML_SCHEMA_FACET_WHITESPACE:
17827                     break;
17828                 case XML_SCHEMA_FACET_PATTERN:
17829                     normVal = 1;
17830                     has = 1;
17831                     break;
17832                 case XML_SCHEMA_FACET_ENUMERATION:
17833                     needVal = 1;
17834                     normVal = 1;
17835                     has = 1;
17836                     break;
17837                 default:
17838                     has = 1;
17839                     break;
17840             }
17841         }
17842     }
17843     if (normVal)
17844         type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17845     if (needVal)
17846         type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17847     if (has)
17848         type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17849
17850     if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
17851         xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17852         /*
17853         * OPTIMIZE VAL TODO: Some facets need a computed value.
17854         */
17855         if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17856             (prim->builtInType != XML_SCHEMAS_STRING)) {
17857             type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17858         }
17859     }
17860 }
17861
17862 static int
17863 xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17864 {
17865
17866
17867     /*
17868     * Evaluate the whitespace-facet value.
17869     */
17870     if (WXS_IS_LIST(type)) {
17871         type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17872         return (0);
17873     } else if (WXS_IS_UNION(type))
17874         return (0);
17875
17876     if (type->facetSet != NULL) {
17877         xmlSchemaFacetLinkPtr lin;
17878
17879         for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17880             if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17881                 switch (lin->facet->whitespace) {
17882                 case XML_SCHEMAS_FACET_PRESERVE:
17883                     type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17884                     break;
17885                 case XML_SCHEMAS_FACET_REPLACE:
17886                     type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17887                     break;
17888                 case XML_SCHEMAS_FACET_COLLAPSE:
17889                     type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17890                     break;
17891                 default:
17892                     return (-1);
17893                 }
17894                 return (0);
17895             }
17896         }
17897     }
17898     /*
17899     * For all `atomic` datatypes other than string (and types `derived`
17900     * by `restriction` from it) the value of whiteSpace is fixed to
17901     * collapse
17902     */
17903     {
17904         xmlSchemaTypePtr anc;
17905
17906         for (anc = type->baseType; anc != NULL &&
17907                 anc->builtInType != XML_SCHEMAS_ANYTYPE;
17908                 anc = anc->baseType) {
17909
17910             if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17911                 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17912                     type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17913
17914                 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17915                     (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17916                     type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17917
17918                 } else
17919                     type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17920                 break;
17921             }
17922         }
17923     }
17924     return (0);
17925 }
17926
17927 static int
17928 xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17929                           xmlSchemaTypePtr type)
17930 {
17931     if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17932         return(0);
17933     if (! WXS_IS_TYPE_NOT_FIXED_1(type))
17934         return(0);
17935     type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
17936
17937     if (WXS_IS_LIST(type)) {
17938         /*
17939         * Corresponds to <simpleType><list>...
17940         */
17941         if (type->subtypes == NULL) {
17942             /*
17943             * This one is really needed, so get out.
17944             */
17945             PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17946                 "list type has no item-type assigned");
17947             return(-1);
17948         }
17949     } else if (WXS_IS_UNION(type)) {
17950         /*
17951         * Corresponds to <simpleType><union>...
17952         */
17953         if (type->memberTypes == NULL) {
17954             /*
17955             * This one is really needed, so get out.
17956             */
17957             PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17958                 "union type has no member-types assigned");
17959             return(-1);
17960         }
17961     } else {
17962         /*
17963         * Corresponds to <simpleType><restriction>...
17964         */
17965         if (type->baseType == NULL) {
17966             PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17967                 "type has no base-type assigned");
17968             return(-1);
17969         }
17970         if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
17971             if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17972                 return(-1);
17973         /*
17974         * Variety
17975         * If the <restriction> alternative is chosen, then the
17976         * {variety} of the {base type definition}.
17977         */
17978         if (WXS_IS_ATOMIC(type->baseType))
17979             type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
17980         else if (WXS_IS_LIST(type->baseType)) {
17981             type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
17982             /*
17983             * Inherit the itemType.
17984             */
17985             type->subtypes = type->baseType->subtypes;
17986         } else if (WXS_IS_UNION(type->baseType)) {
17987             type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
17988             /*
17989             * NOTE that we won't assign the memberTypes of the base,
17990             * since this will make trouble when freeing them; we will
17991             * use a lookup function to access them instead.
17992             */
17993         }
17994     }
17995     return(0);
17996 }
17997
17998 #ifdef DEBUG_TYPE
17999 static void
18000 xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
18001                        xmlSchemaTypePtr type)
18002 {
18003     if (type->node != NULL) {
18004         xmlGenericError(xmlGenericErrorContext,
18005                         "Type of %s : %s:%d :", name,
18006                         type->node->doc->URL,
18007                         xmlGetLineNo(type->node));
18008     } else {
18009         xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
18010     }
18011     if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
18012         switch (type->contentType) {
18013             case XML_SCHEMA_CONTENT_SIMPLE:
18014                 xmlGenericError(xmlGenericErrorContext, "simple\n");
18015                 break;
18016             case XML_SCHEMA_CONTENT_ELEMENTS:
18017                 xmlGenericError(xmlGenericErrorContext, "elements\n");
18018                 break;
18019             case XML_SCHEMA_CONTENT_UNKNOWN:
18020                 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
18021                 break;
18022             case XML_SCHEMA_CONTENT_EMPTY:
18023                 xmlGenericError(xmlGenericErrorContext, "empty\n");
18024                 break;
18025             case XML_SCHEMA_CONTENT_MIXED:
18026                 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
18027                     type->subtypes))
18028                     xmlGenericError(xmlGenericErrorContext,
18029                         "mixed as emptiable particle\n");
18030                 else
18031                     xmlGenericError(xmlGenericErrorContext, "mixed\n");
18032                 break;
18033                 /* Removed, since not used. */
18034                 /*
18035                 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
18036                 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
18037                 break;
18038                 */
18039             case XML_SCHEMA_CONTENT_BASIC:
18040                 xmlGenericError(xmlGenericErrorContext, "basic\n");
18041                 break;
18042             default:
18043                 xmlGenericError(xmlGenericErrorContext,
18044                     "not registered !!!\n");
18045                 break;
18046         }
18047     }
18048 }
18049 #endif
18050
18051 /*
18052 * 3.14.6 Constraints on Simple Type Definition Schema Components
18053 */
18054 static int
18055 xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
18056                                  xmlSchemaTypePtr type)
18057 {
18058     int res, olderrs = pctxt->nberrors;
18059
18060     if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18061         return(-1);
18062
18063     if (! WXS_IS_TYPE_NOT_FIXED(type))
18064         return(0);
18065
18066     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18067     type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
18068
18069     if (type->baseType == NULL) {
18070         PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
18071             "missing baseType");
18072         goto exit_failure;
18073     }
18074     if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
18075         xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
18076     /*
18077     * If a member type of a union is a union itself, we need to substitute
18078     * that member type for its member types.
18079     * NOTE that this might change in WXS 1.1; i.e. we will keep the union
18080     * types in WXS 1.1.
18081     */
18082     if ((type->memberTypes != NULL) &&
18083         (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
18084         return(-1);
18085     /*
18086     * SPEC src-simple-type 1
18087     * "The corresponding simple type definition, if any, must satisfy
18088     * the conditions set out in Constraints on Simple Type Definition
18089     * Schema Components ($3.14.6)."
18090     */
18091     /*
18092     * Schema Component Constraint: Simple Type Definition Properties Correct
18093     * (st-props-correct)
18094     */
18095     res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
18096     HFAILURE HERROR
18097     /*
18098     * Schema Component Constraint: Derivation Valid (Restriction, Simple)
18099     * (cos-st-restricts)
18100     */
18101     res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
18102     HFAILURE HERROR
18103     /*
18104     * TODO: Removed the error report, since it got annoying to get an
18105     * extra error report, if anything failed until now.
18106     * Enable this if needed.
18107     *
18108     * xmlSchemaPErr(ctxt, type->node,
18109     *    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
18110     *    "Simple type '%s' does not satisfy the constraints "
18111     *    "on simple type definitions.\n",
18112     *    type->name, NULL);
18113     */
18114     /*
18115     * Schema Component Constraint: Simple Type Restriction (Facets)
18116     * (st-restrict-facets)
18117     */
18118     res = xmlSchemaCheckFacetValues(type, pctxt);
18119     HFAILURE HERROR
18120     if ((type->facetSet != NULL) ||
18121         (type->baseType->facetSet != NULL)) {
18122         res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18123         HFAILURE HERROR
18124     }
18125     /*
18126     * Whitespace value.
18127     */
18128     res = xmlSchemaTypeFixupWhitespace(type);
18129     HFAILURE HERROR
18130     xmlSchemaTypeFixupOptimFacets(type);
18131
18132 exit_error:
18133 #ifdef DEBUG_TYPE
18134     xmlSchemaDebugFixedType(pctxt, type);
18135 #endif
18136     if (olderrs != pctxt->nberrors)
18137         return(pctxt->err);
18138     return(0);
18139
18140 exit_failure:
18141 #ifdef DEBUG_TYPE
18142     xmlSchemaDebugFixedType(pctxt, type);
18143 #endif
18144     return(-1);
18145 }
18146
18147 static int
18148 xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18149                           xmlSchemaTypePtr type)
18150 {
18151     int res = 0, olderrs = pctxt->nberrors;
18152     xmlSchemaTypePtr baseType = type->baseType;
18153
18154     if (! WXS_IS_TYPE_NOT_FIXED(type))
18155         return(0);
18156     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18157     if (baseType == NULL) {
18158         PERROR_INT("xmlSchemaFixupComplexType",
18159             "missing baseType");
18160         goto exit_failure;
18161     }
18162     /*
18163     * Fixup the base type.
18164     */
18165     if (WXS_IS_TYPE_NOT_FIXED(baseType))
18166         xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
18167     if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18168         /*
18169         * Skip fixup if the base type is invalid.
18170         * TODO: Generate a warning!
18171         */
18172         return(0);
18173     }
18174     /*
18175     * This basically checks if the base type can be derived.
18176     */
18177     res = xmlSchemaCheckSRCCT(pctxt, type);
18178     HFAILURE HERROR
18179     /*
18180     * Fixup the content type.
18181     */
18182     if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18183         /*
18184         * Corresponds to <complexType><simpleContent>...
18185         */
18186         if ((WXS_IS_COMPLEX(baseType)) &&
18187             (baseType->contentTypeDef != NULL) &&
18188             (WXS_IS_RESTRICTION(type))) {
18189             xmlSchemaTypePtr contentBase, content;
18190 #ifdef ENABLE_NAMED_LOCALS
18191             char buf[30];
18192             const xmlChar *tmpname;
18193 #endif
18194             /*
18195             * SPEC (1) If <restriction> + base type is <complexType>,
18196             * "whose own {content type} is a simple type..."
18197             */
18198             if (type->contentTypeDef != NULL) {
18199                 /*
18200                 * SPEC (1.1) "the simple type definition corresponding to the
18201                 * <simpleType> among the [children] of <restriction> if there
18202                 * is one;"
18203                 * Note that this "<simpleType> among the [children]" was put
18204                 * into ->contentTypeDef during parsing.
18205                 */
18206                 contentBase = type->contentTypeDef;
18207                 type->contentTypeDef = NULL;
18208             } else {
18209                 /*
18210                 * (1.2) "...otherwise (<restriction> has no <simpleType>
18211                 * among its [children]), the simple type definition which
18212                 * is the {content type} of the ... base type."
18213                 */
18214                 contentBase = baseType->contentTypeDef;
18215             }
18216             /*
18217             * SPEC
18218             * "... a simple type definition which restricts the simple
18219             * type definition identified in clause 1.1 or clause 1.2
18220             * with a set of facet components"
18221             *
18222             * Create the anonymous simple type, which will be the content
18223             * type of the complex type.
18224             */
18225 #ifdef ENABLE_NAMED_LOCALS
18226             snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18227             tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
18228             content = xmlSchemaAddType(pctxt, pctxt->schema,
18229                 XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
18230                 type->node, 0);
18231 #else
18232             content = xmlSchemaAddType(pctxt, pctxt->schema,
18233                 XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
18234                 type->node, 0);
18235 #endif
18236             if (content == NULL)
18237                 goto exit_failure;
18238             /*
18239             * We will use the same node as for the <complexType>
18240             * to have it somehow anchored in the schema doc.
18241             */
18242             content->type = XML_SCHEMA_TYPE_SIMPLE;
18243             content->baseType = contentBase;
18244             /*
18245             * Move the facets, previously anchored on the
18246             * complexType during parsing.
18247             */
18248             content->facets = type->facets;
18249             type->facets = NULL;
18250             content->facetSet = type->facetSet;
18251             type->facetSet = NULL;
18252
18253             type->contentTypeDef = content;
18254             if (WXS_IS_TYPE_NOT_FIXED(contentBase))
18255                 xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
18256             /*
18257             * Fixup the newly created type. We don't need to check
18258             * for circularity here.
18259             */
18260             res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18261             HFAILURE HERROR
18262             res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18263             HFAILURE HERROR
18264
18265         } else if ((WXS_IS_COMPLEX(baseType)) &&
18266             (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18267             (WXS_IS_RESTRICTION(type))) {
18268             /*
18269             * SPEC (2) If <restriction> + base is a mixed <complexType> with
18270             * an emptiable particle, then a simple type definition which
18271             * restricts the <restriction>'s <simpleType> child.
18272             */
18273             if ((type->contentTypeDef == NULL) ||
18274                 (type->contentTypeDef->baseType == NULL)) {
18275                 /*
18276                 * TODO: Check if this ever happens.
18277                 */
18278                 xmlSchemaPCustomErr(pctxt,
18279                     XML_SCHEMAP_INTERNAL,
18280                     WXS_BASIC_CAST type, NULL,
18281                     "Internal error: xmlSchemaTypeFixup, "
18282                     "complex type '%s': the <simpleContent><restriction> "
18283                     "is missing a <simpleType> child, but was not catched "
18284                     "by xmlSchemaCheckSRCCT()", type->name);
18285                 goto exit_failure;
18286             }
18287         } else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
18288             /*
18289             * SPEC (3) If <extension> + base is <complexType> with
18290             * <simpleType> content, "...then the {content type} of that
18291             * complex type definition"
18292             */
18293             if (baseType->contentTypeDef == NULL) {
18294                 /*
18295                 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18296                 * should have catched this already.
18297                 */
18298                 xmlSchemaPCustomErr(pctxt,
18299                     XML_SCHEMAP_INTERNAL,
18300                     WXS_BASIC_CAST type, NULL,
18301                     "Internal error: xmlSchemaTypeFixup, "
18302                     "complex type '%s': the <extension>ed base type is "
18303                     "a complex type with no simple content type",
18304                     type->name);
18305                 goto exit_failure;
18306             }
18307             type->contentTypeDef = baseType->contentTypeDef;
18308         } else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
18309             /*
18310             * SPEC (4) <extension> + base is <simpleType>
18311             * "... then that simple type definition"
18312             */
18313             type->contentTypeDef = baseType;
18314         } else {
18315             /*
18316             * TODO: Check if this ever happens.
18317             */
18318             xmlSchemaPCustomErr(pctxt,
18319                 XML_SCHEMAP_INTERNAL,
18320                 WXS_BASIC_CAST type, NULL,
18321                 "Internal error: xmlSchemaTypeFixup, "
18322                 "complex type '%s' with <simpleContent>: unhandled "
18323                 "derivation case", type->name);
18324             goto exit_failure;
18325         }
18326     } else {
18327         int dummySequence = 0;
18328         xmlSchemaParticlePtr particle =
18329             (xmlSchemaParticlePtr) type->subtypes;
18330         /*
18331         * Corresponds to <complexType><complexContent>...
18332         *
18333         * NOTE that the effective mixed was already set during parsing of
18334         * <complexType> and <complexContent>; its flag value is
18335         * XML_SCHEMAS_TYPE_MIXED.
18336         *
18337         * Compute the "effective content":
18338         * (2.1.1) + (2.1.2) + (2.1.3)
18339         */
18340         if ((particle == NULL) ||
18341             ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18342             ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18343             (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18344             ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18345             (particle->minOccurs == 0))) &&
18346             ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18347             if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18348                 /*
18349                 * SPEC (2.1.4) "If the `effective mixed` is true, then
18350                 * a particle whose properties are as follows:..."
18351                 *
18352                 * Empty sequence model group with
18353                 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18354                 * NOTE that we sill assign it the <complexType> node to
18355                 * somehow anchor it in the doc.
18356                 */
18357                 if ((particle == NULL) ||
18358                     (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18359                     /*
18360                     * Create the particle.
18361                     */
18362                     particle = xmlSchemaAddParticle(pctxt,
18363                         type->node, 1, 1);
18364                     if (particle == NULL)
18365                         goto exit_failure;
18366                     /*
18367                     * Create the model group.
18368                     */ /* URGENT TODO: avoid adding to pending items. */
18369                     particle->children = (xmlSchemaTreeItemPtr)
18370                         xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18371                         XML_SCHEMA_TYPE_SEQUENCE, type->node);
18372                     if (particle->children == NULL)
18373                         goto exit_failure;
18374
18375                     type->subtypes = (xmlSchemaTypePtr) particle;
18376                 }
18377                 dummySequence = 1;
18378                 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18379             } else {
18380                 /*
18381                 * SPEC (2.1.5) "otherwise empty"
18382                 */
18383                 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18384             }
18385         } else {
18386             /*
18387             * SPEC (2.2) "otherwise the particle corresponding to the
18388             * <all>, <choice>, <group> or <sequence> among the
18389             * [children]."
18390             */
18391             type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18392         }
18393         /*
18394         * Compute the "content type".
18395         */
18396         if (WXS_IS_RESTRICTION(type)) {
18397             /*
18398             * SPEC (3.1) "If <restriction>..."
18399             * (3.1.1) + (3.1.2) */
18400             if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18401                 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18402                     type->contentType = XML_SCHEMA_CONTENT_MIXED;
18403             }
18404         } else {
18405             /*
18406             * SPEC (3.2) "If <extension>..."
18407             */
18408             if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18409                 /*
18410                 * SPEC (3.2.1)
18411                 * "If the `effective content` is empty, then the
18412                 *  {content type} of the [...] base ..."
18413                 */
18414                 type->contentType = baseType->contentType;
18415                 type->subtypes = baseType->subtypes;
18416                 /*
18417                 * Fixes bug #347316:
18418                 * This is the case when the base type has a simple
18419                 * type definition as content.
18420                 */
18421                 type->contentTypeDef = baseType->contentTypeDef;
18422                 /*
18423                 * NOTE that the effective mixed is ignored here.
18424                 */
18425             } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18426                 /*
18427                 * SPEC (3.2.2)
18428                 */
18429                 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18430                     type->contentType = XML_SCHEMA_CONTENT_MIXED;
18431             } else {
18432                 /*
18433                 * SPEC (3.2.3)
18434                 */
18435                 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18436                     type->contentType = XML_SCHEMA_CONTENT_MIXED;
18437                     /*
18438                     * "A model group whose {compositor} is sequence and whose
18439                     * {particles} are..."
18440                     */
18441                 if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18442                     (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18443                     ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18444                         XML_SCHEMA_TYPE_ALL))
18445                 {
18446                     /*
18447                     * SPEC cos-all-limited (1)
18448                     */
18449                     xmlSchemaCustomErr(ACTXT_CAST pctxt,
18450                         /* TODO: error code */
18451                         XML_SCHEMAP_COS_ALL_LIMITED,
18452                         WXS_ITEM_NODE(type), NULL,
18453                         "The type has an 'all' model group in its "
18454                         "{content type} and thus cannot be derived from "
18455                         "a non-empty type, since this would produce a "
18456                         "'sequence' model group containing the 'all' "
18457                         "model group; 'all' model groups are not "
18458                         "allowed to appear inside other model groups",
18459                         NULL, NULL);
18460
18461                 } else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18462                     (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18463                     ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18464                         XML_SCHEMA_TYPE_ALL))
18465                 {
18466                     /*
18467                     * SPEC cos-all-limited (1)
18468                     */
18469                     xmlSchemaCustomErr(ACTXT_CAST pctxt,
18470                         /* TODO: error code */
18471                         XML_SCHEMAP_COS_ALL_LIMITED,
18472                         WXS_ITEM_NODE(type), NULL,
18473                         "A type cannot be derived by extension from a type "
18474                         "which has an 'all' model group in its "
18475                         "{content type}, since this would produce a "
18476                         "'sequence' model group containing the 'all' "
18477                         "model group; 'all' model groups are not "
18478                         "allowed to appear inside other model groups",
18479                         NULL, NULL);
18480
18481                 } else if (! dummySequence) {
18482                     xmlSchemaTreeItemPtr effectiveContent =
18483                         (xmlSchemaTreeItemPtr) type->subtypes;
18484                     /*
18485                     * Create the particle.
18486                     */
18487                     particle = xmlSchemaAddParticle(pctxt,
18488                         type->node, 1, 1);
18489                     if (particle == NULL)
18490                         goto exit_failure;
18491                     /*
18492                     * Create the "sequence" model group.
18493                     */
18494                     particle->children = (xmlSchemaTreeItemPtr)
18495                         xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18496                         XML_SCHEMA_TYPE_SEQUENCE, type->node);
18497                     if (particle->children == NULL)
18498                         goto exit_failure;
18499                     WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
18500                     /*
18501                     * SPEC "the particle of the {content type} of
18502                     * the ... base ..."
18503                     * Create a duplicate of the base type's particle
18504                     * and assign its "term" to it.
18505                     */
18506                     particle->children->children =
18507                         (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18508                         type->node,
18509                         ((xmlSchemaParticlePtr) baseType->subtypes)->minOccurs,
18510                         ((xmlSchemaParticlePtr) baseType->subtypes)->maxOccurs);
18511                     if (particle->children->children == NULL)
18512                         goto exit_failure;
18513                     particle = (xmlSchemaParticlePtr)
18514                         particle->children->children;
18515                     particle->children =
18516                         ((xmlSchemaParticlePtr) baseType->subtypes)->children;
18517                     /*
18518                     * SPEC "followed by the `effective content`."
18519                     */
18520                     particle->next = effectiveContent;
18521                     /*
18522                     * This all will result in:
18523                     * new-particle
18524                     *   --> new-sequence(
18525                     *         new-particle
18526                     *           --> base-model,
18527                     *         this-particle
18528                     *           --> this-model
18529                     *       )
18530                     */
18531                 } else {
18532                     /*
18533                     * This is the case when there is already an empty
18534                     * <sequence> with minOccurs==maxOccurs==1.
18535                     * Just add the base types's content type.
18536                     * NOTE that, although we miss to add an intermediate
18537                     * <sequence>, this should produce no difference to
18538                     * neither the regex compilation of the content model,
18539                     * nor to the complex type contraints.
18540                     */
18541                     particle->children->children =
18542                         (xmlSchemaTreeItemPtr) baseType->subtypes;
18543                 }
18544             }
18545         }
18546     }
18547     /*
18548     * Now fixup attribute uses:
18549     *   - expand attr. group references
18550     *     - intersect attribute wildcards
18551     *   - inherit attribute uses of the base type
18552     *   - inherit or union attr. wildcards if extending
18553     *   - apply attr. use prohibitions if restricting
18554     */
18555     res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
18556     HFAILURE HERROR
18557     /*
18558     * Apply the complex type component constraints; this will not
18559     * check attributes, since this is done in
18560     * xmlSchemaFixupTypeAttributeUses().
18561     */
18562     res = xmlSchemaCheckCTComponent(pctxt, type);
18563     HFAILURE HERROR
18564
18565 #ifdef DEBUG_TYPE
18566     xmlSchemaDebugFixedType(pctxt, type);
18567 #endif
18568     if (olderrs != pctxt->nberrors)
18569         return(pctxt->err);
18570     else
18571         return(0);
18572
18573 exit_error:
18574     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18575 #ifdef DEBUG_TYPE
18576     xmlSchemaDebugFixedType(pctxt, type);
18577 #endif
18578     return(pctxt->err);
18579
18580 exit_failure:
18581     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18582 #ifdef DEBUG_TYPE
18583     xmlSchemaDebugFixedType(pctxt, type);
18584 #endif
18585     return(-1);
18586 }
18587
18588
18589 /**
18590  * xmlSchemaTypeFixup:
18591  * @typeDecl:  the schema type definition
18592  * @ctxt:  the schema parser context
18593  *
18594  * Fixes the content model of the type.
18595  * URGENT TODO: We need an int result!
18596  */
18597 static int
18598 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
18599                    xmlSchemaAbstractCtxtPtr actxt)
18600 {
18601     if (type == NULL)
18602         return(0);
18603     if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18604         AERROR_INT("xmlSchemaTypeFixup",
18605             "this function needs a parser context");
18606         return(-1);
18607     }
18608     if (! WXS_IS_TYPE_NOT_FIXED(type))
18609         return(0);
18610     if (type->type == XML_SCHEMA_TYPE_COMPLEX)
18611         return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
18612     else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
18613         return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
18614     return(0);
18615 }
18616
18617 /**
18618  * xmlSchemaCheckFacet:
18619  * @facet:  the facet
18620  * @typeDecl:  the schema type definition
18621  * @pctxt:  the schema parser context or NULL
18622  * @name: the optional name of the type
18623  *
18624  * Checks and computes the values of facets.
18625  *
18626  * Returns 0 if valid, a positive error code if not valid and
18627  *         -1 in case of an internal or API error.
18628  */
18629 int
18630 xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
18631                     xmlSchemaTypePtr typeDecl,
18632                     xmlSchemaParserCtxtPtr pctxt,
18633                     const xmlChar * name ATTRIBUTE_UNUSED)
18634 {
18635     int ret = 0, ctxtGiven;
18636
18637     if ((facet == NULL) || (typeDecl == NULL))
18638         return(-1);
18639     /*
18640     * TODO: will the parser context be given if used from
18641     * the relaxNG module?
18642     */
18643     if (pctxt == NULL)
18644         ctxtGiven = 0;
18645     else
18646         ctxtGiven = 1;
18647
18648     switch (facet->type) {
18649         case XML_SCHEMA_FACET_MININCLUSIVE:
18650         case XML_SCHEMA_FACET_MINEXCLUSIVE:
18651         case XML_SCHEMA_FACET_MAXINCLUSIVE:
18652         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18653         case XML_SCHEMA_FACET_ENUMERATION: {
18654                 /*
18655                  * Okay we need to validate the value
18656                  * at that point.
18657                  */
18658                 xmlSchemaTypePtr base;
18659
18660                 /* 4.3.5.5 Constraints on enumeration Schema Components
18661                 * Schema Component Constraint: enumeration valid restriction
18662                 * It is an `error` if any member of {value} is not in the
18663                 * `value space` of {base type definition}.
18664                 *
18665                 * minInclusive, maxInclusive, minExclusive, maxExclusive:
18666                 * The value `must` be in the
18667                 * `value space` of the `base type`.
18668                 */
18669                 /*
18670                 * This function is intended to deliver a compiled value
18671                 * on the facet. In this implementation of XML Schemata the
18672                 * type holding a facet, won't be a built-in type.
18673                 * Thus to ensure that other API
18674                 * calls (relaxng) do work, if the given type is a built-in
18675                 * type, we will assume that the given built-in type *is
18676                 * already* the base type.
18677                 */
18678                 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18679                     base = typeDecl->baseType;
18680                     if (base == NULL) {
18681                         PERROR_INT("xmlSchemaCheckFacet",
18682                             "a type user derived type has no base type");
18683                         return (-1);
18684                     }
18685                 } else
18686                     base = typeDecl;
18687
18688                 if (! ctxtGiven) {
18689                     /*
18690                     * A context is needed if called from RelaxNG.
18691                     */
18692                     pctxt = xmlSchemaNewParserCtxt("*");
18693                     if (pctxt == NULL)
18694                         return (-1);
18695                 }
18696                 /*
18697                 * NOTE: This call does not check the content nodes,
18698                 * since they are not available:
18699                 * facet->node is just the node holding the facet
18700                 * definition, *not* the attribute holding the *value*
18701                 * of the facet.
18702                 */
18703                 ret = xmlSchemaVCheckCVCSimpleType(
18704                     ACTXT_CAST pctxt, facet->node, base,
18705                     facet->value, &(facet->val), 1, 1, 0);
18706                 if (ret != 0) {
18707                     if (ret < 0) {
18708                         /* No error message for RelaxNG. */
18709                         if (ctxtGiven) {
18710                             xmlSchemaCustomErr(ACTXT_CAST pctxt,
18711                                 XML_SCHEMAP_INTERNAL, facet->node, NULL,
18712                                 "Internal error: xmlSchemaCheckFacet, "
18713                                 "failed to validate the value '%s' of the "
18714                                 "facet '%s' against the base type",
18715                                 facet->value, xmlSchemaFacetTypeToString(facet->type));
18716                         }
18717                         goto internal_error;
18718                     }
18719                     ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18720                     /* No error message for RelaxNG. */
18721                     if (ctxtGiven) {
18722                         xmlChar *str = NULL;
18723
18724                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
18725                             ret, facet->node, WXS_BASIC_CAST facet,
18726                             "The value '%s' of the facet does not validate "
18727                             "against the base type '%s'",
18728                             facet->value,
18729                             xmlSchemaFormatQName(&str,
18730                                 base->targetNamespace, base->name));
18731                         FREE_AND_NULL(str);
18732                     }
18733                     goto exit;
18734                 } else if (facet->val == NULL) {
18735                     if (ctxtGiven) {
18736                         PERROR_INT("xmlSchemaCheckFacet",
18737                             "value was not computed");
18738                     }
18739                     TODO
18740                 }
18741                 break;
18742             }
18743         case XML_SCHEMA_FACET_PATTERN:
18744             facet->regexp = xmlRegexpCompile(facet->value);
18745             if (facet->regexp == NULL) {
18746                 ret = XML_SCHEMAP_REGEXP_INVALID;
18747                 /* No error message for RelaxNG. */
18748                 if (ctxtGiven) {
18749                     xmlSchemaCustomErr(ACTXT_CAST pctxt,
18750                         ret, facet->node, WXS_BASIC_CAST typeDecl,
18751                         "The value '%s' of the facet 'pattern' is not a "
18752                         "valid regular expression",
18753                         facet->value, NULL);
18754                 }
18755             }
18756             break;
18757         case XML_SCHEMA_FACET_TOTALDIGITS:
18758         case XML_SCHEMA_FACET_FRACTIONDIGITS:
18759         case XML_SCHEMA_FACET_LENGTH:
18760         case XML_SCHEMA_FACET_MAXLENGTH:
18761         case XML_SCHEMA_FACET_MINLENGTH:
18762
18763             if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18764                 ret = xmlSchemaValidatePredefinedType(
18765                     xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18766                     facet->value, &(facet->val));
18767             } else {
18768                 ret = xmlSchemaValidatePredefinedType(
18769                     xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18770                     facet->value, &(facet->val));
18771             }
18772             if (ret != 0) {
18773                 if (ret < 0) {
18774                     /* No error message for RelaxNG. */
18775                     if (ctxtGiven) {
18776                         PERROR_INT("xmlSchemaCheckFacet",
18777                             "validating facet value");
18778                     }
18779                     goto internal_error;
18780                 }
18781                 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18782                 /* No error message for RelaxNG. */
18783                 if (ctxtGiven) {
18784                     /* error code */
18785                     xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18786                         ret, facet->node, WXS_BASIC_CAST typeDecl,
18787                         "The value '%s' of the facet '%s' is not a valid '%s'",
18788                         facet->value,
18789                         xmlSchemaFacetTypeToString(facet->type),
18790                         (facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18791                             BAD_CAST "nonNegativeInteger" :
18792                             BAD_CAST "positiveInteger",
18793                         NULL);
18794                 }
18795             }
18796             break;
18797
18798         case XML_SCHEMA_FACET_WHITESPACE:{
18799                 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18800                     facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18801                 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18802                     facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18803                 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18804                     facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18805                 } else {
18806                     ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18807                     /* No error message for RelaxNG. */
18808                     if (ctxtGiven) {
18809                         /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
18810                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
18811                             ret, facet->node, WXS_BASIC_CAST typeDecl,
18812                             "The value '%s' of the facet 'whitespace' is not "
18813                             "valid", facet->value, NULL);
18814                     }
18815                 }
18816             }
18817         default:
18818             break;
18819     }
18820 exit:
18821     if ((! ctxtGiven) && (pctxt != NULL))
18822         xmlSchemaFreeParserCtxt(pctxt);
18823     return (ret);
18824 internal_error:
18825     if ((! ctxtGiven) && (pctxt != NULL))
18826         xmlSchemaFreeParserCtxt(pctxt);
18827     return (-1);
18828 }
18829
18830 /**
18831  * xmlSchemaCheckFacetValues:
18832  * @typeDecl:  the schema type definition
18833  * @ctxt:  the schema parser context
18834  *
18835  * Checks the default values types, especially for facets
18836  */
18837 static int
18838 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
18839                           xmlSchemaParserCtxtPtr pctxt)
18840 {
18841     int res, olderrs = pctxt->nberrors;
18842     const xmlChar *name = typeDecl->name;
18843     /*
18844     * NOTE: It is intended to use the facets list, instead
18845     * of facetSet.
18846     */
18847     if (typeDecl->facets != NULL) {
18848         xmlSchemaFacetPtr facet = typeDecl->facets;
18849
18850         /*
18851         * Temporarily assign the "schema" to the validation context
18852         * of the parser context. This is needed for NOTATION validation.
18853         */
18854         if (pctxt->vctxt == NULL) {
18855             if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18856                 return(-1);
18857         }
18858         pctxt->vctxt->schema = pctxt->schema;
18859         while (facet != NULL) {
18860             res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18861             HFAILURE
18862             facet = facet->next;
18863         }
18864         pctxt->vctxt->schema = NULL;
18865     }
18866     if (olderrs != pctxt->nberrors)
18867         return(pctxt->err);
18868     return(0);
18869 exit_failure:
18870     return(-1);
18871 }
18872
18873 /**
18874  * xmlSchemaGetCircModelGrDefRef:
18875  * @ctxtMGroup: the searched model group
18876  * @selfMGroup: the second searched model group
18877  * @particle: the first particle
18878  *
18879  * This one is intended to be used by
18880  * xmlSchemaCheckGroupDefCircular only.
18881  *
18882  * Returns the particle with the circular model group definition reference,
18883  * otherwise NULL.
18884  */
18885 static xmlSchemaTreeItemPtr
18886 xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
18887                               xmlSchemaTreeItemPtr particle)
18888 {
18889     xmlSchemaTreeItemPtr circ = NULL;
18890     xmlSchemaTreeItemPtr term;
18891     xmlSchemaModelGroupDefPtr gdef;
18892
18893     for (; particle != NULL; particle = particle->next) {
18894         term = particle->children;
18895         if (term == NULL)
18896             continue;
18897         switch (term->type) {
18898             case XML_SCHEMA_TYPE_GROUP:
18899                 gdef = (xmlSchemaModelGroupDefPtr) term;
18900                 if (gdef == groupDef)
18901                     return (particle);
18902                 /*
18903                 * Mark this model group definition to avoid infinite
18904                 * recursion on circular references not yet examined.
18905                 */
18906                 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18907                     continue;
18908                 if (gdef->children != NULL) {
18909                     gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18910                     circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18911                         gdef->children->children);
18912                     gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18913                     if (circ != NULL)
18914                         return (circ);
18915                 }
18916                 break;
18917             case XML_SCHEMA_TYPE_SEQUENCE:
18918             case XML_SCHEMA_TYPE_CHOICE:
18919             case XML_SCHEMA_TYPE_ALL:
18920                 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18921                 if (circ != NULL)
18922                     return (circ);
18923                 break;
18924             default:
18925                 break;
18926         }
18927     }
18928     return (NULL);
18929 }
18930
18931 /**
18932  * xmlSchemaCheckGroupDefCircular:
18933  * @item:  the model group definition
18934  * @ctxt:  the parser context
18935  * @name:  the name
18936  *
18937  * Checks for circular references to model group definitions.
18938  */
18939 static void
18940 xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
18941                                xmlSchemaParserCtxtPtr ctxt)
18942 {
18943     /*
18944     * Schema Component Constraint: Model Group Correct
18945     * 2 Circular groups are disallowed. That is, within the {particles}
18946     * of a group there must not be at any depth a particle whose {term}
18947     * is the group itself.
18948     */
18949     if ((item == NULL) ||
18950         (item->type != XML_SCHEMA_TYPE_GROUP) ||
18951         (item->children == NULL))
18952         return;
18953     {
18954         xmlSchemaTreeItemPtr circ;
18955
18956         circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
18957         if (circ != NULL) {
18958             xmlChar *str = NULL;
18959             /*
18960             * TODO: The error report is not adequate: this constraint
18961             * is defined for model groups but not definitions, but since
18962             * there cannot be any circular model groups without a model group
18963             * definition (if not using a construction API), we check those
18964             * defintions only.
18965             */
18966             xmlSchemaPCustomErr(ctxt,
18967                 XML_SCHEMAP_MG_PROPS_CORRECT_2,
18968                 NULL, WXS_ITEM_NODE(circ),
18969                 "Circular reference to the model group definition '%s' "
18970                 "defined", xmlSchemaFormatQName(&str,
18971                     item->targetNamespace, item->name));
18972             FREE_AND_NULL(str)
18973             /*
18974             * NOTE: We will cut the reference to avoid further
18975             * confusion of the processor. This is a fatal error.
18976             */
18977             circ->children = NULL;
18978         }
18979     }
18980 }
18981
18982 /**
18983  * xmlSchemaModelGroupToModelGroupDefFixup:
18984  * @ctxt:  the parser context
18985  * @mg:  the model group
18986  *
18987  * Assigns the model group of model group definitions to the "term"
18988  * of the referencing particle.
18989  * In xmlSchemaResolveModelGroupParticleReferences the model group
18990  * definitions were assigned to the "term", since needed for the
18991  * circularity check.
18992  *
18993  * Schema Component Constraint:
18994  *     All Group Limited (cos-all-limited) (1.2)
18995  */
18996 static void
18997 xmlSchemaModelGroupToModelGroupDefFixup(
18998     xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
18999     xmlSchemaModelGroupPtr mg)
19000 {
19001     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19002
19003     while (particle != NULL) {
19004         if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19005             ((WXS_PARTICLE_TERM(particle))->type !=
19006                 XML_SCHEMA_TYPE_GROUP))
19007         {
19008             particle = WXS_PTC_CAST particle->next;
19009             continue;
19010         }
19011         if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
19012             /*
19013             * TODO: Remove the particle.
19014             */
19015             WXS_PARTICLE_TERM(particle) = NULL;
19016             particle = WXS_PTC_CAST particle->next;
19017             continue;
19018         }
19019         /*
19020         * Assign the model group to the {term} of the particle.
19021         */
19022         WXS_PARTICLE_TERM(particle) =
19023             WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
19024
19025         particle = WXS_PTC_CAST particle->next;
19026     }
19027 }
19028
19029 /**
19030  * xmlSchemaCheckAttrGroupCircularRecur:
19031  * @ctxtGr: the searched attribute group
19032  * @attr: the current attribute list to be processed
19033  *
19034  * This one is intended to be used by
19035  * xmlSchemaCheckAttrGroupCircular only.
19036  *
19037  * Returns the circular attribute grou reference, otherwise NULL.
19038  */
19039 static xmlSchemaQNameRefPtr
19040 xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
19041                                      xmlSchemaItemListPtr list)
19042 {
19043     xmlSchemaAttributeGroupPtr gr;
19044     xmlSchemaQNameRefPtr ref, circ;
19045     int i;
19046     /*
19047     * We will search for an attribute group reference which
19048     * references the context attribute group.
19049     */
19050     for (i = 0; i < list->nbItems; i++) {
19051         ref = list->items[i];
19052         if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19053             (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
19054             (ref->item != NULL))
19055         {
19056             gr = WXS_ATTR_GROUP_CAST ref->item;
19057             if (gr == ctxtGr)
19058                 return(ref);
19059             if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
19060                 continue;
19061             /*
19062             * Mark as visited to avoid infinite recursion on
19063             * circular references not yet examined.
19064             */
19065             if ((gr->attrUses) &&
19066                 (gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
19067             {
19068                 gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
19069                 circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
19070                     (xmlSchemaItemListPtr) gr->attrUses);
19071                 gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
19072                 if (circ != NULL)
19073                     return (circ);
19074             }
19075
19076         }
19077     }
19078     return (NULL);
19079 }
19080
19081 /**
19082  * xmlSchemaCheckAttrGroupCircular:
19083  * attrGr:  the attribute group definition
19084  * @ctxt:  the parser context
19085  * @name:  the name
19086  *
19087  * Checks for circular references of attribute groups.
19088  */
19089 static int
19090 xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
19091                                 xmlSchemaParserCtxtPtr ctxt)
19092 {
19093     /*
19094     * Schema Representation Constraint:
19095     * Attribute Group Definition Representation OK
19096     * 3 Circular group reference is disallowed outside <redefine>.
19097     * That is, unless this element information item's parent is
19098     * <redefine>, then among the [children], if any, there must
19099     * not be an <attributeGroup> with ref [attribute] which resolves
19100     * to the component corresponding to this <attributeGroup>. Indirect
19101     * circularity is also ruled out. That is, when QName resolution
19102     * (Schema Document) ($3.15.3) is applied to a `QName` arising from
19103     * any <attributeGroup>s with a ref [attribute] among the [children],
19104     * it must not be the case that a `QName` is encountered at any depth
19105     * which resolves to the component corresponding to this <attributeGroup>.
19106     */
19107     if (attrGr->attrUses == NULL)
19108         return(0);
19109     else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
19110         return(0);
19111     else {
19112         xmlSchemaQNameRefPtr circ;
19113
19114         circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
19115             (xmlSchemaItemListPtr) attrGr->attrUses);
19116         if (circ != NULL) {
19117             xmlChar *str = NULL;
19118             /*
19119             * TODO: Report the referenced attr group as QName.
19120             */
19121             xmlSchemaPCustomErr(ctxt,
19122                 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
19123                 NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
19124                 "Circular reference to the attribute group '%s' "
19125                 "defined", xmlSchemaGetComponentQName(&str, attrGr));
19126             FREE_AND_NULL(str);
19127             /*
19128             * NOTE: We will cut the reference to avoid further
19129             * confusion of the processor.
19130             * BADSPEC TODO: The spec should define how to process in this case.
19131             */
19132             circ->item = NULL;
19133             return(ctxt->err);
19134         }
19135     }
19136     return(0);
19137 }
19138
19139 static int
19140 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19141                                   xmlSchemaAttributeGroupPtr attrGr);
19142
19143 /**
19144  * xmlSchemaExpandAttributeGroupRefs:
19145  * @pctxt: the parser context
19146  * @node: the node of the component holding the attribute uses
19147  * @completeWild: the intersected wildcard to be returned
19148  * @list: the attribute uses
19149  *
19150  * Substitutes contained attribute group references
19151  * for their attribute uses. Wilcards are intersected.
19152  * Attribute use prohibitions are removed from the list
19153  * and returned via the @prohibs list.
19154  * Pointlessness of attr. prohibs, if a matching attr. decl
19155  * is existent a well, are checked.
19156  */
19157 static int
19158 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19159                                   xmlSchemaBasicItemPtr item,
19160                                   xmlSchemaWildcardPtr *completeWild,
19161                                   xmlSchemaItemListPtr list,
19162                                   xmlSchemaItemListPtr prohibs)
19163 {
19164     xmlSchemaAttributeGroupPtr gr;
19165     xmlSchemaAttributeUsePtr use;
19166     xmlSchemaItemListPtr sublist;
19167     int i, j;
19168     int created = (*completeWild == NULL) ? 0 : 1;
19169
19170     if (prohibs)
19171         prohibs->nbItems = 0;
19172
19173     for (i = 0; i < list->nbItems; i++) {
19174         use = list->items[i];
19175
19176         if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19177             if (prohibs == NULL) {
19178                 PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19179                     "unexpected attr prohibition found");
19180                 return(-1);
19181             }
19182             /*
19183             * Remove from attribute uses.
19184             */
19185             if (xmlSchemaItemListRemove(list, i) == -1)
19186                 return(-1);
19187             i--;
19188             /*
19189             * Note that duplicate prohibitions were already
19190             * handled at parsing time.
19191             */
19192             /*
19193             * Add to list of prohibitions.
19194             */
19195             xmlSchemaItemListAddSize(prohibs, 2, use);
19196             continue;
19197         }
19198         if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19199             ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19200         {
19201             if ((WXS_QNAME_CAST use)->item == NULL)
19202                 return(-1);
19203             gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19204             /*
19205             * Expand the referenced attr. group.
19206             * TODO: remove this, this is done in a previous step, so
19207             * already done here.
19208             */
19209             if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19210                 if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19211                     return(-1);
19212             }
19213             /*
19214             * Build the 'complete' wildcard; i.e. intersect multiple
19215             * wildcards.
19216             */
19217             if (gr->attributeWildcard != NULL) {
19218                 if (*completeWild == NULL) {
19219                     *completeWild = gr->attributeWildcard;
19220                 } else {
19221                     if (! created) {
19222                         xmlSchemaWildcardPtr tmpWild;
19223
19224                          /*
19225                         * Copy the first encountered wildcard as context,
19226                         * except for the annotation.
19227                         *
19228                         * Although the complete wildcard might not correspond
19229                         * to any node in the schema, we will anchor it on
19230                         * the node of the owner component.
19231                         */
19232                         tmpWild =  xmlSchemaAddWildcard(pctxt, pctxt->schema,
19233                             XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19234                             WXS_ITEM_NODE(item));
19235                         if (tmpWild == NULL)
19236                             return(-1);
19237                         if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19238                             tmpWild, *completeWild) == -1)
19239                             return (-1);
19240                         tmpWild->processContents = (*completeWild)->processContents;
19241                         *completeWild = tmpWild;
19242                         created = 1;
19243                     }
19244
19245                     if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19246                         gr->attributeWildcard) == -1)
19247                         return(-1);
19248                 }
19249             }
19250             /*
19251             * Just remove the reference if the referenced group does not
19252             * contain any attribute uses.
19253             */
19254             sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19255             if ((sublist == NULL) || sublist->nbItems == 0) {
19256                 if (xmlSchemaItemListRemove(list, i) == -1)
19257                     return(-1);
19258                 i--;
19259                 continue;
19260             }
19261             /*
19262             * Add the attribute uses.
19263             */
19264             list->items[i] = sublist->items[0];
19265             if (sublist->nbItems != 1) {
19266                 for (j = 1; j < sublist->nbItems; j++) {
19267                     i++;
19268                     if (xmlSchemaItemListInsert(list,
19269                             sublist->items[j], i) == -1)
19270                         return(-1);
19271                 }
19272             }
19273         }
19274
19275     }
19276     /*
19277     * Handle pointless prohibitions of declared attributes.
19278     */
19279     if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19280         xmlSchemaAttributeUseProhibPtr prohib;
19281
19282         for (i = prohibs->nbItems -1; i >= 0; i--) {
19283             prohib = prohibs->items[i];
19284             for (j = 0; j < list->nbItems; j++) {
19285                 use = list->items[j];
19286
19287                 if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19288                     (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19289                 {
19290                     xmlChar *str = NULL;
19291
19292                     xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19293                         XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19294                         prohib->node, NULL,
19295                         "Skipping pointless attribute use prohibition "
19296                         "'%s', since a corresponding attribute use "
19297                         "exists already in the type definition",
19298                         xmlSchemaFormatQName(&str,
19299                             prohib->targetNamespace, prohib->name),
19300                         NULL, NULL);
19301                     FREE_AND_NULL(str);
19302                     /*
19303                     * Remove the prohibition.
19304                     */
19305                     if (xmlSchemaItemListRemove(prohibs, i) == -1)
19306                         return(-1);
19307                     break;
19308                 }
19309             }
19310         }
19311     }
19312     return(0);
19313 }
19314
19315 /**
19316  * xmlSchemaAttributeGroupExpandRefs:
19317  * @pctxt:  the parser context
19318  * @attrGr:  the attribute group definition
19319  *
19320  * Computation of:
19321  * {attribute uses} property
19322  * {attribute wildcard} property
19323  *
19324  * Substitutes contained attribute group references
19325  * for their attribute uses. Wilcards are intersected.
19326  */
19327 static int
19328 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19329                                   xmlSchemaAttributeGroupPtr attrGr)
19330 {
19331     if ((attrGr->attrUses == NULL) ||
19332         (attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19333         return(0);
19334
19335     attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19336     if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19337         &(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19338         return(-1);
19339     return(0);
19340 }
19341
19342 /**
19343  * xmlSchemaAttributeGroupExpandRefs:
19344  * @pctxt:  the parser context
19345  * @attrGr:  the attribute group definition
19346  *
19347  * Substitutes contained attribute group references
19348  * for their attribute uses. Wilcards are intersected.
19349  *
19350  * Schema Component Constraint:
19351  *    Attribute Group Definition Properties Correct (ag-props-correct)
19352  */
19353 static int
19354 xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19355                                   xmlSchemaAttributeGroupPtr attrGr)
19356 {
19357     /*
19358     * SPEC ag-props-correct
19359     * (1) "The values of the properties of an attribute group definition
19360     * must be as described in the property tableau in The Attribute
19361     * Group Definition Schema Component ($3.6.1), modulo the impact of
19362     * Missing Sub-components ($5.3);"
19363     */
19364
19365     if ((attrGr->attrUses != NULL) &&
19366         (WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19367     {
19368         xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19369         xmlSchemaAttributeUsePtr use, tmp;
19370         int i, j, hasId = 0;
19371
19372         for (i = uses->nbItems -1; i >= 0; i--) {
19373             use = uses->items[i];
19374             /*
19375             * SPEC ag-props-correct
19376             * (2) "Two distinct members of the {attribute uses} must not have
19377             * {attribute declaration}s both of whose {name}s match and whose
19378             * {target namespace}s are identical."
19379             */
19380             if (i > 0) {
19381                 for (j = i -1; j >= 0; j--) {
19382                     tmp = uses->items[j];
19383                     if ((WXS_ATTRUSE_DECL_NAME(use) ==
19384                         WXS_ATTRUSE_DECL_NAME(tmp)) &&
19385                         (WXS_ATTRUSE_DECL_TNS(use) ==
19386                         WXS_ATTRUSE_DECL_TNS(tmp)))
19387                     {
19388                         xmlChar *str = NULL;
19389
19390                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
19391                             XML_SCHEMAP_AG_PROPS_CORRECT,
19392                             attrGr->node, WXS_BASIC_CAST attrGr,
19393                             "Duplicate %s",
19394                             xmlSchemaGetComponentDesignation(&str, use),
19395                             NULL);
19396                         FREE_AND_NULL(str);
19397                         /*
19398                         * Remove the duplicate.
19399                         */
19400                         if (xmlSchemaItemListRemove(uses, i) == -1)
19401                             return(-1);
19402                         goto next_use;
19403                     }
19404                 }
19405             }
19406             /*
19407             * SPEC ag-props-correct
19408             * (3) "Two distinct members of the {attribute uses} must not have
19409             * {attribute declaration}s both of whose {type definition}s are or
19410             * are derived from ID."
19411             * TODO: Does 'derived' include member-types of unions?
19412             */
19413             if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19414                 if (xmlSchemaIsDerivedFromBuiltInType(
19415                     WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19416                 {
19417                     if (hasId) {
19418                         xmlChar *str = NULL;
19419
19420                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
19421                             XML_SCHEMAP_AG_PROPS_CORRECT,
19422                             attrGr->node, WXS_BASIC_CAST attrGr,
19423                             "There must not exist more than one attribute "
19424                             "declaration of type 'xs:ID' "
19425                             "(or derived from 'xs:ID'). The %s violates this "
19426                             "constraint",
19427                             xmlSchemaGetComponentDesignation(&str, use),
19428                             NULL);
19429                         FREE_AND_NULL(str);
19430                         if (xmlSchemaItemListRemove(uses, i) == -1)
19431                             return(-1);
19432                     }
19433                     hasId = 1;
19434                 }
19435             }
19436 next_use: {}
19437         }
19438     }
19439     return(0);
19440 }
19441
19442 /**
19443  * xmlSchemaResolveAttrGroupReferences:
19444  * @attrgrpDecl:  the schema attribute definition
19445  * @ctxt:  the schema parser context
19446  * @name:  the attribute name
19447  *
19448  * Resolves references to attribute group definitions.
19449  */
19450 static int
19451 xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19452                                     xmlSchemaParserCtxtPtr ctxt)
19453 {
19454     xmlSchemaAttributeGroupPtr group;
19455
19456     if (ref->item != NULL)
19457         return(0);
19458     group = xmlSchemaGetAttributeGroup(ctxt->schema,
19459         ref->name,
19460         ref->targetNamespace);
19461     if (group == NULL) {
19462         xmlSchemaPResCompAttrErr(ctxt,
19463             XML_SCHEMAP_SRC_RESOLVE,
19464             NULL, ref->node,
19465             "ref", ref->name, ref->targetNamespace,
19466             ref->itemType, NULL);
19467         return(ctxt->err);
19468     }
19469     ref->item = WXS_BASIC_CAST group;
19470     return(0);
19471 }
19472
19473 /**
19474  * xmlSchemaCheckAttrPropsCorrect:
19475  * @item:  an schema attribute declaration/use
19476  * @ctxt:  a schema parser context
19477  * @name:  the name of the attribute
19478  *
19479  *
19480  * Schema Component Constraint:
19481  *    Attribute Declaration Properties Correct (a-props-correct)
19482  *
19483  * Validates the value constraints of an attribute declaration/use.
19484  * NOTE that this needs the simle type definitions to be already
19485  *   builded and checked.
19486  */
19487 static int
19488 xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19489                                xmlSchemaAttributePtr attr)
19490 {
19491
19492     /*
19493     * SPEC a-props-correct (1)
19494     * "The values of the properties of an attribute declaration must
19495     * be as described in the property tableau in The Attribute
19496     * Declaration Schema Component ($3.2.1), modulo the impact of
19497     * Missing Sub-components ($5.3)."
19498     */
19499
19500     if (WXS_ATTR_TYPEDEF(attr) == NULL)
19501         return(0);
19502
19503     if (attr->defValue != NULL) {
19504         int ret;
19505
19506         /*
19507         * SPEC a-props-correct (3)
19508         * "If the {type definition} is or is derived from ID then there
19509         * must not be a {value constraint}."
19510         */
19511         if (xmlSchemaIsDerivedFromBuiltInType(
19512             WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19513         {
19514             xmlSchemaCustomErr(ACTXT_CAST pctxt,
19515                 XML_SCHEMAP_A_PROPS_CORRECT_3,
19516                 NULL, WXS_BASIC_CAST attr,
19517                 "Value constraints are not allowed if the type definition "
19518                 "is or is derived from xs:ID",
19519                 NULL, NULL);
19520             return(pctxt->err);
19521         }
19522         /*
19523         * SPEC a-props-correct (2)
19524         * "if there is a {value constraint}, the canonical lexical
19525         * representation of its value must be `valid` with respect
19526         * to the {type definition} as defined in String Valid ($3.14.4)."
19527         * TODO: Don't care about the *canonical* stuff here, this requirement
19528         * will be removed in WXS 1.1 anyway.
19529         */
19530         ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
19531             attr->node, WXS_ATTR_TYPEDEF(attr),
19532             attr->defValue, &(attr->defVal),
19533             1, 1, 0);
19534         if (ret != 0) {
19535             if (ret < 0) {
19536                 PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
19537                     "calling xmlSchemaVCheckCVCSimpleType()");
19538                 return(-1);
19539             }
19540             xmlSchemaCustomErr(ACTXT_CAST pctxt,
19541                 XML_SCHEMAP_A_PROPS_CORRECT_2,
19542                 NULL, WXS_BASIC_CAST attr,
19543                 "The value of the value constraint is not valid",
19544                 NULL, NULL);
19545             return(pctxt->err);
19546         }
19547     }
19548
19549     return(0);
19550 }
19551
19552 static xmlSchemaElementPtr
19553 xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19554                                  xmlSchemaElementPtr ancestor)
19555 {
19556     xmlSchemaElementPtr ret;
19557
19558     if (WXS_SUBST_HEAD(ancestor) == NULL)
19559         return (NULL);
19560     if (WXS_SUBST_HEAD(ancestor) == elemDecl)
19561         return (ancestor);
19562
19563     if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
19564         return (NULL);
19565     WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
19566     ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
19567         WXS_SUBST_HEAD(ancestor));
19568     WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
19569
19570     return (ret);
19571 }
19572
19573 /**
19574  * xmlSchemaCheckElemPropsCorrect:
19575  * @ctxt:  a schema parser context
19576  * @decl: the element declaration
19577  * @name:  the name of the attribute
19578  *
19579  * Schema Component Constraint:
19580  * Element Declaration Properties Correct (e-props-correct)
19581  *
19582  * STATUS:
19583  *   missing: (6)
19584  */
19585 static int
19586 xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19587                                xmlSchemaElementPtr elemDecl)
19588 {
19589     int ret = 0;
19590     xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
19591     /*
19592     * SPEC (1) "The values of the properties of an element declaration
19593     * must be as described in the property tableau in The Element
19594     * Declaration Schema Component ($3.3.1), modulo the impact of Missing
19595     * Sub-components ($5.3)."
19596     */
19597     if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19598         xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
19599
19600         xmlSchemaCheckElementDeclComponent(head, pctxt);
19601         /*
19602         * SPEC (3) "If there is a non-`absent` {substitution group
19603         * affiliation}, then {scope} must be global."
19604         */
19605         if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19606             xmlSchemaPCustomErr(pctxt,
19607                 XML_SCHEMAP_E_PROPS_CORRECT_3,
19608                 WXS_BASIC_CAST elemDecl, NULL,
19609                 "Only global element declarations can have a "
19610                 "substitution group affiliation", NULL);
19611             ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
19612         }
19613         /*
19614         * TODO: SPEC (6) "Circular substitution groups are disallowed.
19615         * That is, it must not be possible to return to an element declaration
19616         * by repeatedly following the {substitution group affiliation}
19617         * property."
19618         */
19619         if (head == elemDecl)
19620             circ = head;
19621         else if (WXS_SUBST_HEAD(head) != NULL)
19622             circ = xmlSchemaCheckSubstGroupCircular(head, head);
19623         else
19624             circ = NULL;
19625         if (circ != NULL) {
19626             xmlChar *strA = NULL, *strB = NULL;
19627
19628             xmlSchemaPCustomErrExt(pctxt,
19629                 XML_SCHEMAP_E_PROPS_CORRECT_6,
19630                 WXS_BASIC_CAST circ, NULL,
19631                 "The element declaration '%s' defines a circular "
19632                 "substitution group to element declaration '%s'",
19633                 xmlSchemaGetComponentQName(&strA, circ),
19634                 xmlSchemaGetComponentQName(&strB, head),
19635                 NULL);
19636             FREE_AND_NULL(strA)
19637             FREE_AND_NULL(strB)
19638             ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19639         }
19640         /*
19641         * SPEC (4) "If there is a {substitution group affiliation},
19642         * the {type definition}
19643         * of the element declaration must be validly derived from the {type
19644         * definition} of the {substitution group affiliation}, given the value
19645         * of the {substitution group exclusions} of the {substitution group
19646         * affiliation}, as defined in Type Derivation OK (Complex) ($3.4.6)
19647         * (if the {type definition} is complex) or as defined in
19648         * Type Derivation OK (Simple) ($3.14.6) (if the {type definition} is
19649         * simple)."
19650         *
19651         * NOTE: {substitution group exclusions} means the values of the
19652         * attribute "final".
19653         */
19654
19655         if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
19656             int set = 0;
19657
19658             if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19659                 set |= SUBSET_EXTENSION;
19660             if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19661                 set |= SUBSET_RESTRICTION;
19662
19663             if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
19664                 WXS_ELEM_TYPEDEF(head), set) != 0) {
19665                 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19666
19667                 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
19668                 xmlSchemaPCustomErrExt(pctxt,
19669                     XML_SCHEMAP_E_PROPS_CORRECT_4,
19670                     WXS_BASIC_CAST elemDecl, NULL,
19671                     "The type definition '%s' was "
19672                     "either rejected by the substitution group "
19673                     "affiliation '%s', or not validly derived from its type "
19674                     "definition '%s'",
19675                     xmlSchemaGetComponentQName(&strA, typeDef),
19676                     xmlSchemaGetComponentQName(&strB, head),
19677                     xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
19678                 FREE_AND_NULL(strA)
19679                 FREE_AND_NULL(strB)
19680                 FREE_AND_NULL(strC)
19681             }
19682         }
19683     }
19684     /*
19685     * SPEC (5) "If the {type definition} or {type definition}'s
19686     * {content type}
19687     * is or is derived from ID then there must not be a {value constraint}.
19688     * Note: The use of ID as a type definition for elements goes beyond
19689     * XML 1.0, and should be avoided if backwards compatibility is desired"
19690     */
19691     if ((elemDecl->value != NULL) &&
19692         ((WXS_IS_SIMPLE(typeDef) &&
19693           xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
19694          (WXS_IS_COMPLEX(typeDef) &&
19695           WXS_HAS_SIMPLE_CONTENT(typeDef) &&
19696           xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19697             XML_SCHEMAS_ID)))) {
19698
19699         ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19700         xmlSchemaPCustomErr(pctxt,
19701             XML_SCHEMAP_E_PROPS_CORRECT_5,
19702             WXS_BASIC_CAST elemDecl, NULL,
19703             "The type definition (or type definition's content type) is or "
19704             "is derived from ID; value constraints are not allowed in "
19705             "conjunction with such a type definition", NULL);
19706     } else if (elemDecl->value != NULL) {
19707         int vcret;
19708         xmlNodePtr node = NULL;
19709
19710         /*
19711         * SPEC (2) "If there is a {value constraint}, the canonical lexical
19712         * representation of its value must be `valid` with respect to the
19713         * {type definition} as defined in Element Default Valid (Immediate)
19714         * ($3.3.6)."
19715         */
19716         if (typeDef == NULL) {
19717             xmlSchemaPErr(pctxt, elemDecl->node,
19718                 XML_SCHEMAP_INTERNAL,
19719                 "Internal error: xmlSchemaCheckElemPropsCorrect, "
19720                 "type is missing... skipping validation of "
19721                 "the value constraint", NULL, NULL);
19722             return (-1);
19723         }
19724         if (elemDecl->node != NULL) {
19725             if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19726                 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19727                     BAD_CAST "fixed");
19728             else
19729                 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19730                     BAD_CAST "default");
19731         }
19732         vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19733             typeDef, elemDecl->value, &(elemDecl->defVal));
19734         if (vcret != 0) {
19735             if (vcret < 0) {
19736                 PERROR_INT("xmlSchemaElemCheckValConstr",
19737                     "failed to validate the value constraint of an "
19738                     "element declaration");
19739                 return (-1);
19740             }
19741             return (vcret);
19742         }
19743     }
19744
19745     return (ret);
19746 }
19747
19748 /**
19749  * xmlSchemaCheckElemSubstGroup:
19750  * @ctxt:  a schema parser context
19751  * @decl: the element declaration
19752  * @name:  the name of the attribute
19753  *
19754  * Schema Component Constraint:
19755  * Substitution Group (cos-equiv-class)
19756  *
19757  * In Libxml2 the subst. groups will be precomputed, in terms of that
19758  * a list will be built for each subst. group head, holding all direct
19759  * referents to this head.
19760  * NOTE that this function needs:
19761  *   1. circular subst. groups to be checked beforehand
19762  *   2. the declaration's type to be derived from the head's type
19763  *
19764  * STATUS:
19765  *
19766  */
19767 static void
19768 xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19769                              xmlSchemaElementPtr elemDecl)
19770 {
19771     if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
19772         /* SPEC (1) "Its {abstract} is false." */
19773         (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19774         return;
19775     {
19776         xmlSchemaElementPtr head;
19777         xmlSchemaTypePtr headType, type;
19778         int set, methSet;
19779         /*
19780         * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19781         * {disallowed substitutions} as the blocking constraint, as defined in
19782         * Substitution Group OK (Transitive) ($3.3.6)."
19783         */
19784         for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19785             head = WXS_SUBST_HEAD(head)) {
19786             set = 0;
19787             methSet = 0;
19788             /*
19789             * The blocking constraints.
19790             */
19791             if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19792                 continue;
19793             headType = head->subtypes;
19794             type = elemDecl->subtypes;
19795             if (headType == type)
19796                 goto add_member;
19797             if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19798                 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19799             if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19800                 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19801             /*
19802             * SPEC: Substitution Group OK (Transitive) (2.3)
19803             * "The set of all {derivation method}s involved in the
19804             * derivation of D's {type definition} from C's {type definition}
19805             * does not intersect with the union of the blocking constraint,
19806             * C's {prohibited substitutions} (if C is complex, otherwise the
19807             * empty set) and the {prohibited substitutions} (respectively the
19808             * empty set) of any intermediate {type definition}s in the
19809             * derivation of D's {type definition} from C's {type definition}."
19810             */
19811             /*
19812             * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19813             * subst.head axis, the methSet does not need to be computed for
19814             * the full depth over and over.
19815             */
19816             /*
19817             * The set of all {derivation method}s involved in the derivation
19818             */
19819             while ((type != NULL) && (type != headType)) {
19820                 if ((WXS_IS_EXTENSION(type)) &&
19821                     ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19822                     methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19823
19824                 if (WXS_IS_RESTRICTION(type) &&
19825                     ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19826                     methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19827
19828                 type = type->baseType;
19829             }
19830             /*
19831             * The {prohibited substitutions} of all intermediate types +
19832             * the head's type.
19833             */
19834             type = elemDecl->subtypes->baseType;
19835             while (type != NULL) {
19836                 if (WXS_IS_COMPLEX(type)) {
19837                     if ((type->flags &
19838                             XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19839                         ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19840                     set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19841                     if ((type->flags &
19842                             XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19843                         ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19844                     set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19845                 } else
19846                     break;
19847                 if (type == headType)
19848                     break;
19849                 type = type->baseType;
19850             }
19851             if ((set != 0) &&
19852                 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19853                 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19854                 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19855                 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19856                 continue;
19857             }
19858 add_member:
19859             xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19860             if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19861                 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19862         }
19863     }
19864 }
19865
19866 #ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */
19867 /**
19868  * xmlSchemaCheckElementDeclComponent
19869  * @pctxt: the schema parser context
19870  * @ctxtComponent: the context component (an element declaration)
19871  * @ctxtParticle: the first particle of the context component
19872  * @searchParticle: the element declaration particle to be analysed
19873  *
19874  * Schema Component Constraint: Element Declarations Consistent
19875  */
19876 static int
19877 xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,
19878                                     xmlSchemaBasicItemPtr ctxtComponent,
19879                                     xmlSchemaParticlePtr ctxtParticle,
19880                                     xmlSchemaParticlePtr searchParticle,
19881                                     xmlSchemaParticlePtr curParticle,
19882                                     int search)
19883 {
19884     return(0);
19885
19886     int ret = 0;
19887     xmlSchemaParticlePtr cur = curParticle;
19888     if (curParticle == NULL) {
19889         return(0);
19890     }
19891     if (WXS_PARTICLE_TERM(curParticle) == NULL) {
19892         /*
19893         * Just return in this case. A missing "term" of the particle
19894         * might arise due to an invalid "term" component.
19895         */
19896         return(0);
19897     }
19898     while (cur != NULL) {
19899         switch (WXS_PARTICLE_TERM(cur)->type) {
19900             case XML_SCHEMA_TYPE_ANY:
19901                 break;
19902             case XML_SCHEMA_TYPE_ELEMENT:
19903                 if (search == 0) {
19904                     ret = xmlSchemaCheckElementDeclConsistent(pctxt,
19905                         ctxtComponent, ctxtParticle, cur, ctxtParticle, 1);
19906                     if (ret != 0)
19907                         return(ret);
19908                 } else {
19909                     xmlSchemaElementPtr elem =
19910                         WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur));
19911                     /*
19912                     * SPEC Element Declarations Consistent:
19913                     * "If the {particles} contains, either directly,
19914                     * indirectly (that is, within the {particles} of a
19915                     * contained model group, recursively) or `implicitly`
19916                     * two or more element declaration particles with
19917                     * the same {name} and {target namespace}, then
19918                     * all their type definitions must be the same
19919                     * top-level definition [...]"
19920                     */
19921                     if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name,
19922                             WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) &&
19923                         xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19924                             WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace))
19925                     {
19926                         xmlChar *strA = NULL, *strB = NULL;
19927
19928                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
19929                             /* TODO: error code */
19930                             XML_SCHEMAP_COS_NONAMBIG,
19931                             WXS_ITEM_NODE(cur), NULL,
19932                             "In the content model of %s, there are multiple "
19933                             "element declarations for '%s' with different "
19934                             "type definitions",
19935                             xmlSchemaGetComponentDesignation(&strA,
19936                                 ctxtComponent),
19937                             xmlSchemaFormatQName(&strB,
19938                                 WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19939                                 WXS_PARTICLE_TERM_AS_ELEM(cur)->name));
19940                         FREE_AND_NULL(strA);
19941                         FREE_AND_NULL(strB);
19942                         return(XML_SCHEMAP_COS_NONAMBIG);
19943                     }
19944                 }
19945                 break;
19946             case XML_SCHEMA_TYPE_SEQUENCE: {
19947                 break;
19948                 }
19949             case XML_SCHEMA_TYPE_CHOICE:{
19950                 /*
19951                 xmlSchemaTreeItemPtr sub;
19952
19953                 sub = WXS_PARTICLE_TERM(particle)->children;  (xmlSchemaParticlePtr)
19954                 while (sub != NULL) {
19955                     ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent,
19956                         ctxtParticle, ctxtElem);
19957                     if (ret != 0)
19958                         return(ret);
19959                     sub = sub->next;
19960                 }
19961                 */
19962                 break;
19963                 }
19964             case XML_SCHEMA_TYPE_ALL:
19965                 break;
19966             case XML_SCHEMA_TYPE_GROUP:
19967                 break;
19968             default:
19969                 xmlSchemaInternalErr2(ACTXT_CAST pctxt,
19970                     "xmlSchemaCheckElementDeclConsistent",
19971                     "found unexpected term of type '%s' in content model",
19972                     WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL);
19973                 return(-1);
19974         }
19975         cur = (xmlSchemaParticlePtr) cur->next;
19976     }
19977
19978 exit:
19979     return(ret);
19980 }
19981 #endif
19982
19983 /**
19984  * xmlSchemaCheckElementDeclComponent
19985  * @item:  an schema element declaration/particle
19986  * @ctxt:  a schema parser context
19987  * @name:  the name of the attribute
19988  *
19989  * Validates the value constraints of an element declaration.
19990  * Adds substitution group members.
19991  */
19992 static void
19993 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
19994                                    xmlSchemaParserCtxtPtr ctxt)
19995 {
19996     if (elemDecl == NULL)
19997         return;
19998     if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
19999         return;
20000     elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
20001     if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) {
20002         /*
20003         * Adds substitution group members.
20004         */
20005         xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
20006     }
20007 }
20008
20009 /**
20010  * xmlSchemaResolveModelGroupParticleReferences:
20011  * @particle:  a particle component
20012  * @ctxt:  a parser context
20013  *
20014  * Resolves references of a model group's {particles} to
20015  * model group definitions and to element declarations.
20016  */
20017 static void
20018 xmlSchemaResolveModelGroupParticleReferences(
20019     xmlSchemaParserCtxtPtr ctxt,
20020     xmlSchemaModelGroupPtr mg)
20021 {
20022     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
20023     xmlSchemaQNameRefPtr ref;
20024     xmlSchemaBasicItemPtr refItem;
20025
20026     /*
20027     * URGENT TODO: Test this.
20028     */
20029     while (particle != NULL) {
20030         if ((WXS_PARTICLE_TERM(particle) == NULL) ||
20031             ((WXS_PARTICLE_TERM(particle))->type !=
20032                 XML_SCHEMA_EXTRA_QNAMEREF))
20033         {
20034             goto next_particle;
20035         }
20036         ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
20037         /*
20038         * Resolve the reference.
20039         * NULL the {term} by default.
20040         */
20041         particle->children = NULL;
20042
20043         refItem = xmlSchemaGetNamedComponent(ctxt->schema,
20044             ref->itemType, ref->name, ref->targetNamespace);
20045         if (refItem == NULL) {
20046             xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
20047                 NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
20048                 ref->targetNamespace, ref->itemType, NULL);
20049             /* TODO: remove the particle. */
20050             goto next_particle;
20051         }
20052         if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
20053             if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
20054                 /* TODO: remove the particle. */
20055                 goto next_particle;
20056             /*
20057             * NOTE that we will assign the model group definition
20058             * itself to the "term" of the particle. This will ease
20059             * the check for circular model group definitions. After
20060             * that the "term" will be assigned the model group of the
20061             * model group definition.
20062             */
20063             if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
20064                     XML_SCHEMA_TYPE_ALL) {
20065                 /*
20066                 * SPEC cos-all-limited (1)
20067                 * SPEC cos-all-limited (1.2)
20068                 * "It appears only as the value of one or both of the
20069                 * following properties:"
20070                 * (1.1) "the {model group} property of a model group
20071                 *        definition."
20072                 * (1.2) "the {term} property of a particle [... of] the "
20073                 * {content type} of a complex type definition."
20074                 */
20075                 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20076                     /* TODO: error code */
20077                     XML_SCHEMAP_COS_ALL_LIMITED,
20078                     WXS_ITEM_NODE(particle), NULL,
20079                     "A model group definition is referenced, but "
20080                     "it contains an 'all' model group, which "
20081                     "cannot be contained by model groups",
20082                     NULL, NULL);
20083                 /* TODO: remove the particle. */
20084                 goto next_particle;
20085             }
20086             particle->children = (xmlSchemaTreeItemPtr) refItem;
20087         } else {
20088             /*
20089             * TODO: Are referenced element declarations the only
20090             * other components we expect here?
20091             */
20092             particle->children = (xmlSchemaTreeItemPtr) refItem;
20093         }
20094 next_particle:
20095         particle = WXS_PTC_CAST particle->next;
20096     }
20097 }
20098
20099 static int
20100 xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
20101                        xmlSchemaValPtr y)
20102 {
20103     xmlSchemaTypePtr tx, ty, ptx, pty;
20104     int ret;
20105
20106     while (x != NULL) {
20107         /* Same types. */
20108         tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
20109         ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
20110         ptx = xmlSchemaGetPrimitiveType(tx);
20111         pty = xmlSchemaGetPrimitiveType(ty);
20112         /*
20113         * (1) if a datatype T' is `derived` by `restriction` from an
20114         * atomic datatype T then the `value space` of T' is a subset of
20115         * the `value space` of T. */
20116         /*
20117         * (2) if datatypes T' and T'' are `derived` by `restriction`
20118         * from a common atomic ancestor T then the `value space`s of T'
20119         * and T'' may overlap.
20120         */
20121         if (ptx != pty)
20122             return(0);
20123         /*
20124         * We assume computed values to be normalized, so do a fast
20125         * string comparison for string based types.
20126         */
20127         if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
20128             WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
20129             if (! xmlStrEqual(
20130                 xmlSchemaValueGetAsString(x),
20131                 xmlSchemaValueGetAsString(y)))
20132                 return (0);
20133         } else {
20134             ret = xmlSchemaCompareValuesWhtsp(
20135                 x, XML_SCHEMA_WHITESPACE_PRESERVE,
20136                 y, XML_SCHEMA_WHITESPACE_PRESERVE);
20137             if (ret == -2)
20138                 return(-1);
20139             if (ret != 0)
20140                 return(0);
20141         }
20142         /*
20143         * Lists.
20144         */
20145         x = xmlSchemaValueGetNext(x);
20146         if (x != NULL) {
20147             y = xmlSchemaValueGetNext(y);
20148             if (y == NULL)
20149                 return (0);
20150         } else if (xmlSchemaValueGetNext(y) != NULL)
20151             return (0);
20152         else
20153             return (1);
20154     }
20155     return (0);
20156 }
20157
20158 /**
20159  * xmlSchemaResolveAttrUseReferences:
20160  * @item:  an attribute use
20161  * @ctxt:  a parser context
20162  *
20163  * Resolves the referenced attribute declaration.
20164  */
20165 static int
20166 xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
20167                                   xmlSchemaParserCtxtPtr ctxt)
20168 {
20169     if ((ctxt == NULL) || (ause == NULL))
20170         return(-1);
20171     if ((ause->attrDecl == NULL) ||
20172         (ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
20173         return(0);
20174
20175     {
20176         xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
20177
20178         /*
20179         * TODO: Evaluate, what errors could occur if the declaration is not
20180         * found.
20181         */
20182         ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
20183             ref->name, ref->targetNamespace);
20184         if (ause->attrDecl == NULL) {
20185             xmlSchemaPResCompAttrErr(ctxt,
20186                 XML_SCHEMAP_SRC_RESOLVE,
20187                 WXS_BASIC_CAST ause, ause->node,
20188                 "ref", ref->name, ref->targetNamespace,
20189                 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20190             return(ctxt->err);;
20191         }
20192     }
20193     return(0);
20194 }
20195
20196 /**
20197  * xmlSchemaCheckAttrUsePropsCorrect:
20198  * @ctxt:  a parser context
20199  * @use:  an attribute use
20200  *
20201  * Schema Component Constraint:
20202  * Attribute Use Correct (au-props-correct)
20203  *
20204  */
20205 static int
20206 xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
20207                              xmlSchemaAttributeUsePtr use)
20208 {
20209     if ((ctxt == NULL) || (use == NULL))
20210         return(-1);
20211     if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
20212         ((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
20213         return(0);
20214
20215     /*
20216     * SPEC au-props-correct (1)
20217     * "The values of the properties of an attribute use must be as
20218     * described in the property tableau in The Attribute Use Schema
20219     * Component ($3.5.1), modulo the impact of Missing
20220     * Sub-components ($5.3)."
20221     */
20222
20223     if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
20224         ((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
20225         ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20226     {
20227         xmlSchemaPCustomErr(ctxt,
20228             XML_SCHEMAP_AU_PROPS_CORRECT_2,
20229             WXS_BASIC_CAST use, NULL,
20230             "The attribute declaration has a 'fixed' value constraint "
20231             ", thus the attribute use must also have a 'fixed' value "
20232             "constraint",
20233             NULL);
20234         return(ctxt->err);
20235     }
20236     /*
20237     * Compute and check the value constraint's value.
20238     */
20239     if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
20240         int ret;
20241         /*
20242         * TODO: The spec seems to be missing a check of the
20243         * value constraint of the attribute use. We will do it here.
20244         */
20245         /*
20246         * SPEC a-props-correct (3)
20247         */
20248         if (xmlSchemaIsDerivedFromBuiltInType(
20249             WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20250         {
20251             xmlSchemaCustomErr(ACTXT_CAST ctxt,
20252                 XML_SCHEMAP_AU_PROPS_CORRECT,
20253                 NULL, WXS_BASIC_CAST use,
20254                 "Value constraints are not allowed if the type definition "
20255                 "is or is derived from xs:ID",
20256                 NULL, NULL);
20257             return(ctxt->err);
20258         }
20259
20260         ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20261             use->node, WXS_ATTRUSE_TYPEDEF(use),
20262             use->defValue, &(use->defVal),
20263             1, 1, 0);
20264         if (ret != 0) {
20265             if (ret < 0) {
20266                 PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20267                     "calling xmlSchemaVCheckCVCSimpleType()");
20268                 return(-1);
20269             }
20270             xmlSchemaCustomErr(ACTXT_CAST ctxt,
20271                 XML_SCHEMAP_AU_PROPS_CORRECT,
20272                 NULL, WXS_BASIC_CAST use,
20273                 "The value of the value constraint is not valid",
20274                 NULL, NULL);
20275             return(ctxt->err);
20276         }
20277     }
20278     /*
20279     * SPEC au-props-correct (2)
20280     * "If the {attribute declaration} has a fixed
20281     * {value constraint}, then if the attribute use itself has a
20282     * {value constraint}, it must also be fixed and its value must match
20283     * that of the {attribute declaration}'s {value constraint}."
20284     */
20285     if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20286         (((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20287     {
20288         if (! xmlSchemaAreValuesEqual(use->defVal,
20289                 (WXS_ATTRUSE_DECL(use))->defVal))
20290         {
20291             xmlSchemaPCustomErr(ctxt,
20292                 XML_SCHEMAP_AU_PROPS_CORRECT_2,
20293                 WXS_BASIC_CAST use, NULL,
20294                 "The 'fixed' value constraint of the attribute use "
20295                 "must match the attribute declaration's value "
20296                 "constraint '%s'",
20297                 (WXS_ATTRUSE_DECL(use))->defValue);
20298         }
20299         return(ctxt->err);
20300     }
20301     return(0);
20302 }
20303
20304
20305
20306
20307 /**
20308  * xmlSchemaResolveAttrTypeReferences:
20309  * @item:  an attribute declaration
20310  * @ctxt:  a parser context
20311  *
20312  * Resolves the referenced type definition component.
20313  */
20314 static int
20315 xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20316                                    xmlSchemaParserCtxtPtr ctxt)
20317 {
20318     /*
20319     * The simple type definition corresponding to the <simpleType> element
20320     * information item in the [children], if present, otherwise the simple
20321     * type definition `resolved` to by the `actual value` of the type
20322     * [attribute], if present, otherwise the `simple ur-type definition`.
20323     */
20324     if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
20325         return(0);
20326     item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20327     if (item->subtypes != NULL)
20328         return(0);
20329     if (item->typeName != NULL) {
20330         xmlSchemaTypePtr type;
20331
20332         type = xmlSchemaGetType(ctxt->schema, item->typeName,
20333             item->typeNs);
20334         if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
20335             xmlSchemaPResCompAttrErr(ctxt,
20336                 XML_SCHEMAP_SRC_RESOLVE,
20337                 WXS_BASIC_CAST item, item->node,
20338                 "type", item->typeName, item->typeNs,
20339                 XML_SCHEMA_TYPE_SIMPLE, NULL);
20340             return(ctxt->err);
20341         } else
20342             item->subtypes = type;
20343
20344     } else {
20345         /*
20346         * The type defaults to the xs:anySimpleType.
20347         */
20348         item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20349     }
20350     return(0);
20351 }
20352
20353 /**
20354  * xmlSchemaResolveIDCKeyReferences:
20355  * @idc:  the identity-constraint definition
20356  * @ctxt:  the schema parser context
20357  * @name:  the attribute name
20358  *
20359  * Resolve keyRef references to key/unique IDCs.
20360  * Schema Component Constraint:
20361  *   Identity-constraint Definition Properties Correct (c-props-correct)
20362  */
20363 static int
20364 xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
20365                           xmlSchemaParserCtxtPtr pctxt)
20366 {
20367     if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
20368         return(0);
20369     if (idc->ref->name != NULL) {
20370         idc->ref->item = (xmlSchemaBasicItemPtr)
20371             xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20372                 idc->ref->targetNamespace);
20373         if (idc->ref->item == NULL) {
20374             /*
20375             * TODO: It is actually not an error to fail to resolve
20376             * at this stage. BUT we need to be that strict!
20377             */
20378             xmlSchemaPResCompAttrErr(pctxt,
20379                 XML_SCHEMAP_SRC_RESOLVE,
20380                 WXS_BASIC_CAST idc, idc->node,
20381                 "refer", idc->ref->name,
20382                 idc->ref->targetNamespace,
20383                 XML_SCHEMA_TYPE_IDC_KEY, NULL);
20384             return(pctxt->err);
20385         } else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20386             /*
20387             * SPEC c-props-correct (1)
20388             */
20389             xmlSchemaCustomErr(ACTXT_CAST pctxt,
20390                 XML_SCHEMAP_C_PROPS_CORRECT,
20391                 NULL, WXS_BASIC_CAST idc,
20392                 "The keyref references a keyref",
20393                 NULL, NULL);
20394             idc->ref->item = NULL;
20395             return(pctxt->err);
20396         } else {
20397             if (idc->nbFields !=
20398                 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20399                 xmlChar *str = NULL;
20400                 xmlSchemaIDCPtr refer;
20401
20402                 refer = (xmlSchemaIDCPtr) idc->ref->item;
20403                 /*
20404                 * SPEC c-props-correct(2)
20405                 * "If the {identity-constraint category} is keyref,
20406                 * the cardinality of the {fields} must equal that of
20407                 * the {fields} of the {referenced key}.
20408                 */
20409                 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20410                     XML_SCHEMAP_C_PROPS_CORRECT,
20411                     NULL, WXS_BASIC_CAST idc,
20412                     "The cardinality of the keyref differs from the "
20413                     "cardinality of the referenced key/unique '%s'",
20414                     xmlSchemaFormatQName(&str, refer->targetNamespace,
20415                         refer->name),
20416                     NULL);
20417                 FREE_AND_NULL(str)
20418                 return(pctxt->err);
20419             }
20420         }
20421     }
20422     return(0);
20423 }
20424
20425 static int
20426 xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20427                                        xmlSchemaParserCtxtPtr pctxt)
20428 {
20429     if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20430         prohib->targetNamespace) == NULL) {
20431
20432         xmlSchemaPResCompAttrErr(pctxt,
20433             XML_SCHEMAP_SRC_RESOLVE,
20434             NULL, prohib->node,
20435             "ref", prohib->name, prohib->targetNamespace,
20436             XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20437         return(XML_SCHEMAP_SRC_RESOLVE);
20438     }
20439     return(0);
20440 }
20441
20442 #define WXS_REDEFINED_TYPE(c) \
20443 (((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20444
20445 #define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20446 (((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20447
20448 #define WXS_REDEFINED_ATTR_GROUP(c) \
20449 (((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20450
20451 static int
20452 xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20453 {
20454     int err = 0;
20455     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20456     xmlSchemaBasicItemPtr prev, item;
20457     int wasRedefined;
20458
20459     if (redef == NULL)
20460         return(0);
20461
20462     do {
20463         item = redef->item;
20464         /*
20465         * First try to locate the redefined component in the
20466         * schema graph starting with the redefined schema.
20467         * NOTE: According to this schema bug entry:
20468         *   http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20469         *   it's not clear if the referenced component needs to originate
20470         *   from the <redefine>d schema _document_ or the schema; the latter
20471         *   would include all imported and included sub-schemas of the
20472         *   <redefine>d schema. Currenlty we latter approach is used.
20473         *   SUPPLEMENT: It seems that the WG moves towards the latter
20474         *   approach, so we are doing it right.
20475         *
20476         */
20477         prev = xmlSchemaFindRedefCompInGraph(
20478             redef->targetBucket, item->type,
20479             redef->refName, redef->refTargetNs);
20480         if (prev == NULL) {
20481             xmlChar *str = NULL;
20482             xmlNodePtr node;
20483
20484             /*
20485             * SPEC src-redefine:
20486             * (6.2.1) "The `actual value` of its own name attribute plus
20487             * target namespace must successfully `resolve` to a model
20488             * group definition in I."
20489             * (7.2.1) "The `actual value` of its own name attribute plus
20490             * target namespace must successfully `resolve` to an attribute
20491             * group definition in I."
20492
20493             *
20494             * Note that, if we are redefining with the use of references
20495             * to components, the spec assumes the src-resolve to be used;
20496             * but this won't assure that we search only *inside* the
20497             * redefined schema.
20498             */
20499             if (redef->reference)
20500                 node = WXS_ITEM_NODE(redef->reference);
20501             else
20502                 node = WXS_ITEM_NODE(item);
20503             xmlSchemaCustomErr(ACTXT_CAST pctxt,
20504                 /*
20505                 * TODO: error code.
20506                 * Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20507                 * reference kind.
20508                 */
20509                 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
20510                 "The %s '%s' to be redefined could not be found in "
20511                 "the redefined schema",
20512                 WXS_ITEM_TYPE_NAME(item),
20513                 xmlSchemaFormatQName(&str, redef->refTargetNs,
20514                     redef->refName));
20515             FREE_AND_NULL(str);
20516             err = pctxt->err;
20517             redef = redef->next;
20518             continue;
20519         }
20520         /*
20521         * TODO: Obtaining and setting the redefinition state is really
20522         * clumsy.
20523         */
20524         wasRedefined = 0;
20525         switch (item->type) {
20526             case XML_SCHEMA_TYPE_COMPLEX:
20527             case XML_SCHEMA_TYPE_SIMPLE:
20528                 if ((WXS_TYPE_CAST prev)->flags &
20529                     XML_SCHEMAS_TYPE_REDEFINED)
20530                 {
20531                     wasRedefined = 1;
20532                     break;
20533                 }
20534                 /* Mark it as redefined. */
20535                 (WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20536                 /*
20537                 * Assign the redefined type to the
20538                 * base type of the redefining type.
20539                 * TODO: How
20540                 */
20541                 ((xmlSchemaTypePtr) item)->baseType =
20542                     (xmlSchemaTypePtr) prev;
20543                 break;
20544             case XML_SCHEMA_TYPE_GROUP:
20545                 if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20546                     XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20547                 {
20548                     wasRedefined = 1;
20549                     break;
20550                 }
20551                 /* Mark it as redefined. */
20552                 (WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20553                     XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20554                 if (redef->reference != NULL) {
20555                     /*
20556                     * Overwrite the QName-reference with the
20557                     * referenced model group def.
20558                     */
20559                     (WXS_PTC_CAST redef->reference)->children =
20560                         WXS_TREE_CAST prev;
20561                 }
20562                 redef->target = prev;
20563                 break;
20564             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20565                 if ((WXS_ATTR_GROUP_CAST prev)->flags &
20566                     XML_SCHEMAS_ATTRGROUP_REDEFINED)
20567                 {
20568                     wasRedefined = 1;
20569                     break;
20570                 }
20571                 (WXS_ATTR_GROUP_CAST prev)->flags |=
20572                     XML_SCHEMAS_ATTRGROUP_REDEFINED;
20573                 if (redef->reference != NULL) {
20574                     /*
20575                     * Assign the redefined attribute group to the
20576                     * QName-reference component.
20577                     * This is the easy case, since we will just
20578                     * expand the redefined group.
20579                     */
20580                     (WXS_QNAME_CAST redef->reference)->item = prev;
20581                     redef->target = NULL;
20582                 } else {
20583                     /*
20584                     * This is the complicated case: we need
20585                     * to apply src-redefine (7.2.2) at a later
20586                     * stage, i.e. when attribute group references
20587                     * have beed expanded and simple types have
20588                     * beed fixed.
20589                     */
20590                     redef->target = prev;
20591                 }
20592                 break;
20593             default:
20594                 PERROR_INT("xmlSchemaResolveRedefReferences",
20595                     "Unexpected redefined component type");
20596                 return(-1);
20597         }
20598         if (wasRedefined) {
20599             xmlChar *str = NULL;
20600             xmlNodePtr node;
20601
20602             if (redef->reference)
20603                 node = WXS_ITEM_NODE(redef->reference);
20604             else
20605                 node = WXS_ITEM_NODE(redef->item);
20606
20607             xmlSchemaCustomErr(ACTXT_CAST pctxt,
20608                 /* TODO: error code. */
20609                 XML_SCHEMAP_SRC_REDEFINE,
20610                 node, NULL,
20611                 "The referenced %s was already redefined. Multiple "
20612                 "redefinition of the same component is not supported",
20613                 xmlSchemaGetComponentDesignation(&str, prev),
20614                 NULL);
20615             FREE_AND_NULL(str)
20616             err = pctxt->err;
20617             redef = redef->next;
20618             continue;
20619         }
20620         redef = redef->next;
20621     } while (redef != NULL);
20622
20623     return(err);
20624 }
20625
20626 static int
20627 xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20628 {
20629     int err = 0;
20630     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20631     xmlSchemaBasicItemPtr item;
20632
20633     if (redef == NULL)
20634         return(0);
20635
20636     do {
20637         if (redef->target == NULL) {
20638             redef = redef->next;
20639             continue;
20640         }
20641         item = redef->item;
20642
20643         switch (item->type) {
20644             case XML_SCHEMA_TYPE_SIMPLE:
20645             case XML_SCHEMA_TYPE_COMPLEX:
20646                 /*
20647                 * Since the spec wants the {name} of the redefined
20648                 * type to be 'absent', we'll NULL it.
20649                 */
20650                 (WXS_TYPE_CAST redef->target)->name = NULL;
20651
20652                 /*
20653                 * TODO: Seems like there's nothing more to do. The normal
20654                 * inheritance mechanism is used. But not 100% sure.
20655                 */
20656                 break;
20657             case XML_SCHEMA_TYPE_GROUP:
20658                 /*
20659                 * URGENT TODO:
20660                 * SPEC src-redefine:
20661                 * (6.2.2) "The {model group} of the model group definition
20662                 * which corresponds to it per XML Representation of Model
20663                 * Group Definition Schema Components ($3.7.2) must be a
20664                 * `valid restriction` of the {model group} of that model
20665                 * group definition in I, as defined in Particle Valid
20666                 * (Restriction) ($3.9.6)."
20667                 */
20668                 break;
20669             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20670                 /*
20671                 * SPEC src-redefine:
20672                 * (7.2.2) "The {attribute uses} and {attribute wildcard} of
20673                 * the attribute group definition which corresponds to it
20674                 * per XML Representation of Attribute Group Definition Schema
20675                 * Components ($3.6.2) must be `valid restrictions` of the
20676                 * {attribute uses} and {attribute wildcard} of that attribute
20677                 * group definition in I, as defined in clause 2, clause 3 and
20678                 * clause 4 of Derivation Valid (Restriction, Complex)
20679                 * ($3.4.6) (where references to the base type definition are
20680                 * understood as references to the attribute group definition
20681                 * in I)."
20682                 */
20683                 err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20684                     XML_SCHEMA_ACTION_REDEFINE,
20685                     item, redef->target,
20686                     (WXS_ATTR_GROUP_CAST item)->attrUses,
20687                     (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20688                     (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20689                     (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20690                 if (err == -1)
20691                     return(-1);
20692                 break;
20693             default:
20694                 break;
20695         }
20696         redef = redef->next;
20697     } while (redef != NULL);
20698     return(0);
20699 }
20700
20701
20702 static int
20703 xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20704                        xmlSchemaBucketPtr bucket)
20705 {
20706     xmlSchemaBasicItemPtr item;
20707     int err;
20708     xmlHashTablePtr *table;
20709     const xmlChar *name;
20710     int i;
20711
20712 #define WXS_GET_GLOBAL_HASH(c, slot) { \
20713     if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20714         table = &(WXS_IMPBUCKET((c))->schema->slot); \
20715     else \
20716         table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20717
20718     /*
20719     * Add global components to the schema's hash tables.
20720     * This is the place where duplicate components will be
20721     * detected.
20722     * TODO: I think normally we should support imports of the
20723     *   same namespace from multiple locations. We don't do currently,
20724     *   but if we do then according to:
20725     *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20726     *   we would need, if imported directly, to import redefined
20727     *   components as well to be able to catch clashing components.
20728     *   (I hope I'll still know what this means after some months :-()
20729     */
20730     if (bucket == NULL)
20731         return(-1);
20732     if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20733         return(0);
20734     bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20735
20736     for (i = 0; i < bucket->globals->nbItems; i++) {
20737         item = bucket->globals->items[i];
20738         table = NULL;
20739         switch (item->type) {
20740             case XML_SCHEMA_TYPE_COMPLEX:
20741             case XML_SCHEMA_TYPE_SIMPLE:
20742                 if (WXS_REDEFINED_TYPE(item))
20743                     continue;
20744                 name = (WXS_TYPE_CAST item)->name;
20745                 WXS_GET_GLOBAL_HASH(bucket, typeDecl)
20746                 break;
20747             case XML_SCHEMA_TYPE_ELEMENT:
20748                 name = (WXS_ELEM_CAST item)->name;
20749                 WXS_GET_GLOBAL_HASH(bucket, elemDecl)
20750                 break;
20751             case XML_SCHEMA_TYPE_ATTRIBUTE:
20752                 name = (WXS_ATTR_CAST item)->name;
20753                 WXS_GET_GLOBAL_HASH(bucket, attrDecl)
20754                 break;
20755             case XML_SCHEMA_TYPE_GROUP:
20756                 if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20757                     continue;
20758                 name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20759                 WXS_GET_GLOBAL_HASH(bucket, groupDecl)
20760                 break;
20761             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20762                 if (WXS_REDEFINED_ATTR_GROUP(item))
20763                     continue;
20764                 name = (WXS_ATTR_GROUP_CAST item)->name;
20765                 WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
20766                 break;
20767             case XML_SCHEMA_TYPE_IDC_KEY:
20768             case XML_SCHEMA_TYPE_IDC_UNIQUE:
20769             case XML_SCHEMA_TYPE_IDC_KEYREF:
20770                 name = (WXS_IDC_CAST item)->name;
20771                 WXS_GET_GLOBAL_HASH(bucket, idcDef)
20772                 break;
20773             case XML_SCHEMA_TYPE_NOTATION:
20774                 name = ((xmlSchemaNotationPtr) item)->name;
20775                 WXS_GET_GLOBAL_HASH(bucket, notaDecl)
20776                 break;
20777             default:
20778                 PERROR_INT("xmlSchemaAddComponents",
20779                     "Unexpected global component type");
20780                 continue;
20781         }
20782         if (*table == NULL) {
20783             *table = xmlHashCreateDict(10, pctxt->dict);
20784             if (*table == NULL) {
20785                 PERROR_INT("xmlSchemaAddComponents",
20786                     "failed to create a component hash table");
20787                 return(-1);
20788             }
20789         }
20790         err = xmlHashAddEntry(*table, name, item);
20791         if (err != 0) {
20792             xmlChar *str = NULL;
20793
20794             xmlSchemaCustomErr(ACTXT_CAST pctxt,
20795                 XML_SCHEMAP_REDEFINED_TYPE,
20796                 WXS_ITEM_NODE(item),
20797                 WXS_BASIC_CAST item,
20798                 "A global %s '%s' does already exist",
20799                 WXS_ITEM_TYPE_NAME(item),
20800                 xmlSchemaGetComponentQName(&str, item));
20801             FREE_AND_NULL(str);
20802         }
20803     }
20804     /*
20805     * Process imported/included schemas.
20806     */
20807     if (bucket->relations != NULL) {
20808         xmlSchemaSchemaRelationPtr rel = bucket->relations;
20809         do {
20810             if ((rel->bucket != NULL) &&
20811                 ((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20812                 if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20813                     return(-1);
20814             }
20815             rel = rel->next;
20816         } while (rel != NULL);
20817     }
20818     return(0);
20819 }
20820
20821 static int
20822 xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20823                          xmlSchemaBucketPtr rootBucket)
20824 {
20825     xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20826     xmlSchemaTreeItemPtr item, *items;
20827     int nbItems, i, ret = 0;
20828     xmlSchemaBucketPtr oldbucket = con->bucket;
20829     xmlSchemaElementPtr elemDecl;
20830
20831 #define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20832
20833     if ((con->pending == NULL) ||
20834         (con->pending->nbItems == 0))
20835         return(0);
20836
20837     /*
20838     * Since xmlSchemaFixupComplexType() will create new particles
20839     * (local components), and those particle components need a bucket
20840     * on the constructor, we'll assure here that the constructor has
20841     * a bucket.
20842     * TODO: Think about storing locals _only_ on the main bucket.
20843     */
20844     if (con->bucket == NULL)
20845         con->bucket = rootBucket;
20846
20847     /* TODO:
20848     * SPEC (src-redefine):
20849     * (6.2) "If it has no such self-reference, then all of the
20850     * following must be true:"
20851
20852     * (6.2.2) The {model group} of the model group definition which
20853     * corresponds to it per XML Representation of Model Group
20854     * Definition Schema Components ($3.7.2) must be a `valid
20855     * restriction` of the {model group} of that model group definition
20856     * in I, as defined in Particle Valid (Restriction) ($3.9.6)."
20857     */
20858     xmlSchemaCheckSRCRedefineFirst(pctxt);
20859
20860     /*
20861     * Add global components to the schemata's hash tables.
20862     */
20863     xmlSchemaAddComponents(pctxt, rootBucket);
20864
20865     pctxt->ctxtType = NULL;
20866     items = (xmlSchemaTreeItemPtr *) con->pending->items;
20867     nbItems = con->pending->nbItems;
20868     /*
20869     * Now that we have parsed *all* the schema document(s) and converted
20870     * them to schema components, we can resolve references, apply component
20871     * constraints, create the FSA from the content model, etc.
20872     */
20873     /*
20874     * Resolve references of..
20875     *
20876     * 1. element declarations:
20877     *   - the type definition
20878     *   - the substitution group affiliation
20879     * 2. simple/complex types:
20880     *   - the base type definition
20881     *   - the memberTypes of union types
20882     *   - the itemType of list types
20883     * 3. attributes declarations and attribute uses:
20884     *   - the type definition
20885     *   - if an attribute use, then the attribute declaration
20886     * 4. attribute group references:
20887     *   - the attribute group definition
20888     * 5. particles:
20889     *   - the term of the particle (e.g. a model group)
20890     * 6. IDC key-references:
20891     *   - the referenced IDC 'key' or 'unique' definition
20892     * 7. Attribute prohibitions which had a "ref" attribute.
20893     */
20894     for (i = 0; i < nbItems; i++) {
20895         item = items[i];
20896         switch (item->type) {
20897             case XML_SCHEMA_TYPE_ELEMENT:
20898                 xmlSchemaResolveElementReferences(
20899                     (xmlSchemaElementPtr) item, pctxt);
20900                 FIXHFAILURE;
20901                 break;
20902             case XML_SCHEMA_TYPE_COMPLEX:
20903             case XML_SCHEMA_TYPE_SIMPLE:
20904                 xmlSchemaResolveTypeReferences(
20905                     (xmlSchemaTypePtr) item, pctxt);
20906                 FIXHFAILURE;
20907                 break;
20908             case XML_SCHEMA_TYPE_ATTRIBUTE:
20909                 xmlSchemaResolveAttrTypeReferences(
20910                     (xmlSchemaAttributePtr) item, pctxt);
20911                 FIXHFAILURE;
20912                 break;
20913             case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20914                 xmlSchemaResolveAttrUseReferences(
20915                     (xmlSchemaAttributeUsePtr) item, pctxt);
20916                 FIXHFAILURE;
20917                 break;
20918             case XML_SCHEMA_EXTRA_QNAMEREF:
20919                 if ((WXS_QNAME_CAST item)->itemType ==
20920                     XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20921                 {
20922                     xmlSchemaResolveAttrGroupReferences(
20923                         WXS_QNAME_CAST item, pctxt);
20924                 }
20925                 FIXHFAILURE;
20926                 break;
20927             case XML_SCHEMA_TYPE_SEQUENCE:
20928             case XML_SCHEMA_TYPE_CHOICE:
20929             case XML_SCHEMA_TYPE_ALL:
20930                 xmlSchemaResolveModelGroupParticleReferences(pctxt,
20931                     WXS_MODEL_GROUP_CAST item);
20932                 FIXHFAILURE;
20933                 break;
20934             case XML_SCHEMA_TYPE_IDC_KEY:
20935             case XML_SCHEMA_TYPE_IDC_UNIQUE:
20936             case XML_SCHEMA_TYPE_IDC_KEYREF:
20937                 xmlSchemaResolveIDCKeyReferences(
20938                     (xmlSchemaIDCPtr) item, pctxt);
20939                 FIXHFAILURE;
20940                 break;
20941             case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20942                 /*
20943                 * Handle attribue prohibition which had a
20944                 * "ref" attribute.
20945                 */
20946                 xmlSchemaResolveAttrUseProhibReferences(
20947                     WXS_ATTR_PROHIB_CAST item, pctxt);
20948                 FIXHFAILURE;
20949                 break;
20950             default:
20951                 break;
20952         }
20953     }
20954     if (pctxt->nberrors != 0)
20955         goto exit_error;
20956
20957     /*
20958     * Now that all references are resolved we
20959     * can check for circularity of...
20960     * 1. the base axis of type definitions
20961     * 2. nested model group definitions
20962     * 3. nested attribute group definitions
20963     * TODO: check for circual substitution groups.
20964     */
20965     for (i = 0; i < nbItems; i++) {
20966         item = items[i];
20967         /*
20968         * Let's better stop on the first error here.
20969         */
20970         switch (item->type) {
20971             case XML_SCHEMA_TYPE_COMPLEX:
20972             case XML_SCHEMA_TYPE_SIMPLE:
20973                 xmlSchemaCheckTypeDefCircular(
20974                     (xmlSchemaTypePtr) item, pctxt);
20975                 FIXHFAILURE;
20976                 if (pctxt->nberrors != 0)
20977                     goto exit_error;
20978                 break;
20979             case XML_SCHEMA_TYPE_GROUP:
20980                 xmlSchemaCheckGroupDefCircular(
20981                     (xmlSchemaModelGroupDefPtr) item, pctxt);
20982                 FIXHFAILURE;
20983                 if (pctxt->nberrors != 0)
20984                     goto exit_error;
20985                 break;
20986             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20987                 xmlSchemaCheckAttrGroupCircular(
20988                     (xmlSchemaAttributeGroupPtr) item, pctxt);
20989                 FIXHFAILURE;
20990                 if (pctxt->nberrors != 0)
20991                     goto exit_error;
20992                 break;
20993             default:
20994                 break;
20995         }
20996     }
20997     if (pctxt->nberrors != 0)
20998         goto exit_error;
20999     /*
21000     * Model group definition references:
21001     * Such a reference is reflected by a particle at the component
21002     * level. Until now the 'term' of such particles pointed
21003     * to the model group definition; this was done, in order to
21004     * ease circularity checks. Now we need to set the 'term' of
21005     * such particles to the model group of the model group definition.
21006     */
21007     for (i = 0; i < nbItems; i++) {
21008         item = items[i];
21009         switch (item->type) {
21010             case XML_SCHEMA_TYPE_SEQUENCE:
21011             case XML_SCHEMA_TYPE_CHOICE:
21012                 xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
21013                     WXS_MODEL_GROUP_CAST item);
21014                 break;
21015             default:
21016                 break;
21017         }
21018     }
21019     if (pctxt->nberrors != 0)
21020         goto exit_error;
21021     /*
21022     * Expand attribute group references of attribute group definitions.
21023     */
21024     for (i = 0; i < nbItems; i++) {
21025         item = items[i];
21026         switch (item->type) {
21027             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21028                 if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
21029                     WXS_ATTR_GROUP_HAS_REFS(item))
21030                 {
21031                     xmlSchemaAttributeGroupExpandRefs(pctxt,
21032                         WXS_ATTR_GROUP_CAST item);
21033                     FIXHFAILURE;
21034                 }
21035                 break;
21036             default:
21037                 break;
21038         }
21039     }
21040     if (pctxt->nberrors != 0)
21041         goto exit_error;
21042     /*
21043     * First compute the variety of simple types. This is needed as
21044     * a seperate step, since otherwise we won't be able to detect
21045     * circular union types in all cases.
21046     */
21047     for (i = 0; i < nbItems; i++) {
21048         item = items[i];
21049         switch (item->type) {
21050             case XML_SCHEMA_TYPE_SIMPLE:
21051                 if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
21052                     xmlSchemaFixupSimpleTypeStageOne(pctxt,
21053                         (xmlSchemaTypePtr) item);
21054                     FIXHFAILURE;
21055                 }
21056                 break;
21057             default:
21058                 break;
21059         }
21060     }
21061     if (pctxt->nberrors != 0)
21062         goto exit_error;
21063     /*
21064     * Detect circular union types. Note that this needs the variety to
21065     * be already computed.
21066     */
21067     for (i = 0; i < nbItems; i++) {
21068         item = items[i];
21069         switch (item->type) {
21070             case XML_SCHEMA_TYPE_SIMPLE:
21071                 if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
21072                     xmlSchemaCheckUnionTypeDefCircular(pctxt,
21073                         (xmlSchemaTypePtr) item);
21074                     FIXHFAILURE;
21075                 }
21076                 break;
21077             default:
21078                 break;
21079         }
21080     }
21081     if (pctxt->nberrors != 0)
21082         goto exit_error;
21083
21084     /*
21085     * Do the complete type fixup for simple types.
21086     */
21087     for (i = 0; i < nbItems; i++) {
21088         item = items[i];
21089         switch (item->type) {
21090             case XML_SCHEMA_TYPE_SIMPLE:
21091                 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21092                     xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
21093                     FIXHFAILURE;
21094                 }
21095                 break;
21096             default:
21097                 break;
21098         }
21099     }
21100     if (pctxt->nberrors != 0)
21101         goto exit_error;
21102     /*
21103     * At this point we need build and check all simple types.
21104     */
21105     /*
21106     * Apply contraints for attribute declarations.
21107     */
21108     for (i = 0; i < nbItems; i++) {
21109         item = items[i];
21110         switch (item->type) {
21111             case XML_SCHEMA_TYPE_ATTRIBUTE:
21112                 xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
21113                 FIXHFAILURE;
21114                 break;
21115             default:
21116                 break;
21117         }
21118     }
21119     if (pctxt->nberrors != 0)
21120         goto exit_error;
21121     /*
21122     * Apply constraints for attribute uses.
21123     */
21124     for (i = 0; i < nbItems; i++) {
21125         item = items[i];
21126         switch (item->type) {
21127             case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21128                 if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
21129                     xmlSchemaCheckAttrUsePropsCorrect(pctxt,
21130                         WXS_ATTR_USE_CAST item);
21131                     FIXHFAILURE;
21132                 }
21133                 break;
21134             default:
21135                 break;
21136         }
21137     }
21138     if (pctxt->nberrors != 0)
21139         goto exit_error;
21140
21141     /*
21142     * Apply constraints for attribute group definitions.
21143     */
21144     for (i = 0; i < nbItems; i++) {
21145         item = items[i];
21146         switch (item->type) {
21147         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21148             if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
21149                 ( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
21150             {
21151                 xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
21152                 FIXHFAILURE;
21153             }
21154             break;
21155         default:
21156             break;
21157         }
21158     }
21159     if (pctxt->nberrors != 0)
21160         goto exit_error;
21161
21162     /*
21163     * Apply constraints for redefinitions.
21164     */
21165     if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
21166         xmlSchemaCheckSRCRedefineSecond(pctxt);
21167     if (pctxt->nberrors != 0)
21168         goto exit_error;
21169
21170     /*
21171     * Complex types are builded and checked.
21172     */
21173     for (i = 0; i < nbItems; i++) {
21174         item = con->pending->items[i];
21175         switch (item->type) {
21176             case XML_SCHEMA_TYPE_COMPLEX:
21177                 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21178                     xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
21179                     FIXHFAILURE;
21180                 }
21181                 break;
21182             default:
21183                 break;
21184         }
21185     }
21186     if (pctxt->nberrors != 0)
21187         goto exit_error;
21188
21189     /*
21190     * The list could have changed, since xmlSchemaFixupComplexType()
21191     * will create particles and model groups in some cases.
21192     */
21193     items = (xmlSchemaTreeItemPtr *) con->pending->items;
21194     nbItems = con->pending->nbItems;
21195
21196     /*
21197     * Apply some constraints for element declarations.
21198     */
21199     for (i = 0; i < nbItems; i++) {
21200         item = items[i];
21201         switch (item->type) {
21202             case XML_SCHEMA_TYPE_ELEMENT:
21203                 elemDecl = (xmlSchemaElementPtr) item;
21204
21205                 if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
21206                 {
21207                     xmlSchemaCheckElementDeclComponent(
21208                         (xmlSchemaElementPtr) elemDecl, pctxt);
21209                     FIXHFAILURE;
21210                 }
21211
21212 #ifdef WXS_ELEM_DECL_CONS_ENABLED
21213                 /*
21214                 * Schema Component Constraint: Element Declarations Consistent
21215                 * Apply this constraint to local types of element declarations.
21216                 */
21217                 if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
21218                     (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
21219                     (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
21220                 {
21221                     xmlSchemaCheckElementDeclConsistent(pctxt,
21222                         WXS_BASIC_CAST elemDecl,
21223                         WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
21224                         NULL, NULL, 0);
21225                 }
21226 #endif
21227                 break;
21228             default:
21229                 break;
21230         }
21231     }
21232     if (pctxt->nberrors != 0)
21233         goto exit_error;
21234
21235     /*
21236     * Finally we can build the automaton from the content model of
21237     * complex types.
21238     */
21239
21240     for (i = 0; i < nbItems; i++) {
21241         item = items[i];
21242         switch (item->type) {
21243             case XML_SCHEMA_TYPE_COMPLEX:
21244                 xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
21245                 /* FIXHFAILURE; */
21246                 break;
21247             default:
21248                 break;
21249         }
21250     }
21251     if (pctxt->nberrors != 0)
21252         goto exit_error;
21253     /*
21254     * URGENT TODO: cos-element-consistent
21255     */
21256     goto exit;
21257
21258 exit_error:
21259     ret = pctxt->err;
21260     goto exit;
21261
21262 exit_failure:
21263     ret = -1;
21264
21265 exit:
21266     /*
21267     * Reset the constructor. This is needed for XSI acquisition, since
21268     * those items will be processed over and over again for every XSI
21269     * if not cleared here.
21270     */
21271     con->bucket = oldbucket;
21272     con->pending->nbItems = 0;
21273     if (con->substGroups != NULL) {
21274         xmlHashFree(con->substGroups,
21275             (xmlHashDeallocator) xmlSchemaSubstGroupFree);
21276         con->substGroups = NULL;
21277     }
21278     if (con->redefs != NULL) {
21279         xmlSchemaRedefListFree(con->redefs);
21280         con->redefs = NULL;
21281     }
21282     return(ret);
21283 }
21284 /**
21285  * xmlSchemaParse:
21286  * @ctxt:  a schema validation context
21287  *
21288  * parse a schema definition resource and build an internal
21289  * XML Shema struture which can be used to validate instances.
21290  *
21291  * Returns the internal XML Schema structure built from the resource or
21292  *         NULL in case of error
21293  */
21294 xmlSchemaPtr
21295 xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21296 {
21297     xmlSchemaPtr mainSchema = NULL;
21298     xmlSchemaBucketPtr bucket = NULL;
21299     int res;
21300
21301     /*
21302     * This one is used if the schema to be parsed was specified via
21303     * the API; i.e. not automatically by the validated instance document.
21304     */
21305
21306     xmlSchemaInitTypes();
21307
21308     if (ctxt == NULL)
21309         return (NULL);
21310
21311     /* TODO: Init the context. Is this all we need?*/
21312     ctxt->nberrors = 0;
21313     ctxt->err = 0;
21314     ctxt->counter = 0;
21315
21316     /* Create the *main* schema. */
21317     mainSchema = xmlSchemaNewSchema(ctxt);
21318     if (mainSchema == NULL)
21319         goto exit_failure;
21320     /*
21321     * Create the schema constructor.
21322     */
21323     if (ctxt->constructor == NULL) {
21324         ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21325         if (ctxt->constructor == NULL)
21326             return(NULL);
21327         /* Take ownership of the constructor to be able to free it. */
21328         ctxt->ownsConstructor = 1;
21329     }
21330     ctxt->constructor->mainSchema = mainSchema;
21331     /*
21332     * Locate and add the schema document.
21333     */
21334     res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21335         ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21336         NULL, NULL, &bucket);
21337     if (res == -1)
21338         goto exit_failure;
21339     if (res != 0)
21340         goto exit;
21341
21342     if (bucket == NULL) {
21343         /* TODO: Error code, actually we failed to *locate* the schema. */
21344         if (ctxt->URL)
21345             xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21346                 NULL, NULL,
21347                 "Failed to locate the main schema resource at '%s'",
21348                 ctxt->URL, NULL);
21349         else
21350             xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21351                 NULL, NULL,
21352                 "Failed to locate the main schema resource",
21353                     NULL, NULL);
21354         goto exit;
21355     }
21356     /* Then do the parsing for good. */
21357     if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
21358         goto exit_failure;
21359     if (ctxt->nberrors != 0)
21360         goto exit;
21361
21362     mainSchema->doc = bucket->doc;
21363     mainSchema->preserve = ctxt->preserve;
21364
21365     ctxt->schema = mainSchema;
21366
21367     if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
21368         goto exit_failure;
21369
21370     /*
21371     * TODO: This is not nice, since we cannot distinguish from the
21372     * result if there was an internal error or not.
21373     */
21374 exit:
21375     if (ctxt->nberrors != 0) {
21376         if (mainSchema) {
21377             xmlSchemaFree(mainSchema);
21378             mainSchema = NULL;
21379         }
21380         if (ctxt->constructor) {
21381             xmlSchemaConstructionCtxtFree(ctxt->constructor);
21382             ctxt->constructor = NULL;
21383             ctxt->ownsConstructor = 0;
21384         }
21385     }
21386     ctxt->schema = NULL;
21387     return(mainSchema);
21388 exit_failure:
21389     /*
21390     * Quite verbose, but should catch internal errors, which were
21391     * not communitated.
21392     */
21393     if (mainSchema) {
21394         xmlSchemaFree(mainSchema);
21395         mainSchema = NULL;
21396     }
21397     if (ctxt->constructor) {
21398         xmlSchemaConstructionCtxtFree(ctxt->constructor);
21399         ctxt->constructor = NULL;
21400         ctxt->ownsConstructor = 0;
21401     }
21402     PERROR_INT2("xmlSchemaParse",
21403         "An internal error occured");
21404     ctxt->schema = NULL;
21405     return(NULL);
21406 }
21407
21408 /**
21409  * xmlSchemaSetParserErrors:
21410  * @ctxt:  a schema validation context
21411  * @err:  the error callback
21412  * @warn:  the warning callback
21413  * @ctx:  contextual data for the callbacks
21414  *
21415  * Set the callback functions used to handle errors for a validation context
21416  */
21417 void
21418 xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21419                          xmlSchemaValidityErrorFunc err,
21420                          xmlSchemaValidityWarningFunc warn, void *ctx)
21421 {
21422     if (ctxt == NULL)
21423         return;
21424     ctxt->error = err;
21425     ctxt->warning = warn;
21426     ctxt->errCtxt = ctx;
21427     if (ctxt->vctxt != NULL)
21428         xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21429 }
21430
21431 /**
21432  * xmlSchemaSetParserStructuredErrors:
21433  * @ctxt:  a schema parser context
21434  * @serror:  the structured error function
21435  * @ctx: the functions context
21436  *
21437  * Set the structured error callback
21438  */
21439 void
21440 xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21441                                    xmlStructuredErrorFunc serror,
21442                                    void *ctx)
21443 {
21444     if (ctxt == NULL)
21445         return;
21446     ctxt->serror = serror;
21447     ctxt->errCtxt = ctx;
21448     if (ctxt->vctxt != NULL)
21449         xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
21450 }
21451
21452 /**
21453  * xmlSchemaGetParserErrors:
21454  * @ctxt:  a XMl-Schema parser context
21455  * @err: the error callback result
21456  * @warn: the warning callback result
21457  * @ctx: contextual data for the callbacks result
21458  *
21459  * Get the callback information used to handle errors for a parser context
21460  *
21461  * Returns -1 in case of failure, 0 otherwise
21462  */
21463 int
21464 xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21465                          xmlSchemaValidityErrorFunc * err,
21466                          xmlSchemaValidityWarningFunc * warn, void **ctx)
21467 {
21468         if (ctxt == NULL)
21469                 return(-1);
21470         if (err != NULL)
21471                 *err = ctxt->error;
21472         if (warn != NULL)
21473                 *warn = ctxt->warning;
21474         if (ctx != NULL)
21475                 *ctx = ctxt->errCtxt;
21476         return(0);
21477 }
21478
21479 /**
21480  * xmlSchemaFacetTypeToString:
21481  * @type:  the facet type
21482  *
21483  * Convert the xmlSchemaTypeType to a char string.
21484  *
21485  * Returns the char string representation of the facet type if the
21486  *     type is a facet and an "Internal Error" string otherwise.
21487  */
21488 static const xmlChar *
21489 xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21490 {
21491     switch (type) {
21492         case XML_SCHEMA_FACET_PATTERN:
21493             return (BAD_CAST "pattern");
21494         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
21495             return (BAD_CAST "maxExclusive");
21496         case XML_SCHEMA_FACET_MAXINCLUSIVE:
21497             return (BAD_CAST "maxInclusive");
21498         case XML_SCHEMA_FACET_MINEXCLUSIVE:
21499             return (BAD_CAST "minExclusive");
21500         case XML_SCHEMA_FACET_MININCLUSIVE:
21501             return (BAD_CAST "minInclusive");
21502         case XML_SCHEMA_FACET_WHITESPACE:
21503             return (BAD_CAST "whiteSpace");
21504         case XML_SCHEMA_FACET_ENUMERATION:
21505             return (BAD_CAST "enumeration");
21506         case XML_SCHEMA_FACET_LENGTH:
21507             return (BAD_CAST "length");
21508         case XML_SCHEMA_FACET_MAXLENGTH:
21509             return (BAD_CAST "maxLength");
21510         case XML_SCHEMA_FACET_MINLENGTH:
21511             return (BAD_CAST "minLength");
21512         case XML_SCHEMA_FACET_TOTALDIGITS:
21513             return (BAD_CAST "totalDigits");
21514         case XML_SCHEMA_FACET_FRACTIONDIGITS:
21515             return (BAD_CAST "fractionDigits");
21516         default:
21517             break;
21518     }
21519     return (BAD_CAST "Internal Error");
21520 }
21521
21522 static xmlSchemaWhitespaceValueType
21523 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21524 {
21525     /*
21526     * The normalization type can be changed only for types which are derived
21527     * from xsd:string.
21528     */
21529     if (type->type == XML_SCHEMA_TYPE_BASIC) {
21530         /*
21531         * Note that we assume a whitespace of preserve for anySimpleType.
21532         */
21533         if ((type->builtInType == XML_SCHEMAS_STRING) ||
21534             (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21535             return(XML_SCHEMA_WHITESPACE_PRESERVE);
21536         else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
21537             return(XML_SCHEMA_WHITESPACE_REPLACE);
21538         else {
21539             /*
21540             * For all `atomic` datatypes other than string (and types `derived`
21541             * by `restriction` from it) the value of whiteSpace is fixed to
21542             * collapse
21543             * Note that this includes built-in list datatypes.
21544             */
21545             return(XML_SCHEMA_WHITESPACE_COLLAPSE);
21546         }
21547     } else if (WXS_IS_LIST(type)) {
21548         /*
21549         * For list types the facet "whiteSpace" is fixed to "collapse".
21550         */
21551         return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21552     } else if (WXS_IS_UNION(type)) {
21553         return (XML_SCHEMA_WHITESPACE_UNKNOWN);
21554     } else if (WXS_IS_ATOMIC(type)) {
21555         if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21556             return (XML_SCHEMA_WHITESPACE_PRESERVE);
21557         else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21558             return (XML_SCHEMA_WHITESPACE_REPLACE);
21559         else
21560             return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21561     }
21562     return (-1);
21563 }
21564
21565 /************************************************************************
21566  *                                                                      *
21567  *                      Simple type validation                          *
21568  *                                                                      *
21569  ************************************************************************/
21570
21571
21572 /************************************************************************
21573  *                                                                      *
21574  *                      DOM Validation code                             *
21575  *                                                                      *
21576  ************************************************************************/
21577
21578 /**
21579  * xmlSchemaAssembleByLocation:
21580  * @pctxt:  a schema parser context
21581  * @vctxt:  a schema validation context
21582  * @schema: the existing schema
21583  * @node: the node that fired the assembling
21584  * @nsName: the namespace name of the new schema
21585  * @location: the location of the schema
21586  *
21587  * Expands an existing schema by an additional schema.
21588  *
21589  * Returns 0 if the new schema is correct, a positive error code
21590  * number otherwise and -1 in case of an internal or API error.
21591  */
21592 static int
21593 xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
21594                             xmlSchemaPtr schema,
21595                             xmlNodePtr node,
21596                             const xmlChar *nsName,
21597                             const xmlChar *location)
21598 {
21599     int ret = 0;
21600     xmlSchemaParserCtxtPtr pctxt;
21601     xmlSchemaBucketPtr bucket = NULL;
21602
21603     if ((vctxt == NULL) || (schema == NULL))
21604         return (-1);
21605
21606     if (vctxt->pctxt == NULL) {
21607         VERROR_INT("xmlSchemaAssembleByLocation",
21608             "no parser context available");
21609         return(-1);
21610     }
21611     pctxt = vctxt->pctxt;
21612     if (pctxt->constructor == NULL) {
21613         PERROR_INT("xmlSchemaAssembleByLocation",
21614             "no constructor");
21615         return(-1);
21616     }
21617     /*
21618     * Acquire the schema document.
21619     */
21620     location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21621         location, node);
21622     /*
21623     * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21624     * the process will automatically change this to
21625     * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21626     */
21627     ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21628         location, NULL, NULL, 0, node, NULL, nsName,
21629         &bucket);
21630     if (ret != 0)
21631         return(ret);
21632     if (bucket == NULL) {
21633         /*
21634         * Generate a warning that the document could not be located.
21635         */
21636         xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21637             node, NULL,
21638             "The document at location '%s' could not be acquired",
21639             location, NULL, NULL);
21640         return(ret);
21641     }
21642     /*
21643     * The first located schema will be handled as if all other
21644     * schemas imported by XSI were imported by this first schema.
21645     */
21646     if ((bucket != NULL) &&
21647         (WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21648         WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21649     /*
21650     * TODO: Is this handled like an import? I.e. is it not an error
21651     * if the schema cannot be located?
21652     */
21653     if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21654         return(0);
21655     /*
21656     * We will reuse the parser context for every schema imported
21657     * directly via XSI. So reset the context.
21658     */
21659     pctxt->nberrors = 0;
21660     pctxt->err = 0;
21661     pctxt->doc = bucket->doc;
21662
21663     ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21664     if (ret == -1) {
21665         pctxt->doc = NULL;
21666         goto exit_failure;
21667     }
21668     /* Paranoid error channelling. */
21669     if ((ret == 0) && (pctxt->nberrors != 0))
21670         ret = pctxt->err;
21671     if (pctxt->nberrors == 0) {
21672         /*
21673         * Only bother to fixup pending components, if there was
21674         * no error yet.
21675         * For every XSI acquired schema (and its sub-schemata) we will
21676         * fixup the components.
21677         */
21678         xmlSchemaFixupComponents(pctxt, bucket);
21679         ret = pctxt->err;
21680         /*
21681         * Not nice, but we need somehow to channel the schema parser
21682         * error to the validation context.
21683         */
21684         if ((ret != 0) && (vctxt->err == 0))
21685             vctxt->err = ret;
21686         vctxt->nberrors += pctxt->nberrors;
21687     } else {
21688         /* Add to validation error sum. */
21689         vctxt->nberrors += pctxt->nberrors;
21690     }
21691     pctxt->doc = NULL;
21692     return(ret);
21693 exit_failure:
21694     pctxt->doc = NULL;
21695     return (-1);
21696 }
21697
21698 static xmlSchemaAttrInfoPtr
21699 xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21700                          int metaType)
21701 {
21702     if (vctxt->nbAttrInfos == 0)
21703         return (NULL);
21704     {
21705         int i;
21706         xmlSchemaAttrInfoPtr iattr;
21707
21708         for (i = 0; i < vctxt->nbAttrInfos; i++) {
21709             iattr = vctxt->attrInfos[i];
21710             if (iattr->metaType == metaType)
21711                 return (iattr);
21712         }
21713
21714     }
21715     return (NULL);
21716 }
21717
21718 /**
21719  * xmlSchemaAssembleByXSI:
21720  * @vctxt:  a schema validation context
21721  *
21722  * Expands an existing schema by an additional schema using
21723  * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21724  * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21725  * must be set to 1.
21726  *
21727  * Returns 0 if the new schema is correct, a positive error code
21728  * number otherwise and -1 in case of an internal or API error.
21729  */
21730 static int
21731 xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
21732 {
21733     const xmlChar *cur, *end;
21734     const xmlChar *nsname = NULL, *location;
21735     int count = 0;
21736     int ret = 0;
21737     xmlSchemaAttrInfoPtr iattr;
21738
21739     /*
21740     * Parse the value; we will assume an even number of values
21741     * to be given (this is how Xerces and XSV work).
21742     *
21743     * URGENT TODO: !! This needs to work for both
21744     * @noNamespaceSchemaLocation AND @schemaLocation on the same
21745     * element !!
21746     */
21747     iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21748         XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21749     if (iattr == NULL)
21750         iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21751         XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21752     if (iattr == NULL)
21753         return (0);
21754     cur = iattr->value;
21755     do {
21756         /*
21757         * TODO: Move the string parsing mechanism away from here.
21758         */
21759         if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
21760             /*
21761             * Get the namespace name.
21762             */
21763             while (IS_BLANK_CH(*cur))
21764                 cur++;
21765             end = cur;
21766             while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21767                 end++;
21768             if (end == cur)
21769                 break;
21770             count++; /* TODO: Don't use the schema's dict. */
21771             nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21772             cur = end;
21773         }
21774         /*
21775         * Get the URI.
21776         */
21777         while (IS_BLANK_CH(*cur))
21778             cur++;
21779         end = cur;
21780         while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21781             end++;
21782         if (end == cur) {
21783             if (iattr->metaType ==
21784                 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21785             {
21786                 /*
21787                 * If using @schemaLocation then tuples are expected.
21788                 * I.e. the namespace name *and* the document's URI.
21789                 */
21790                 xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21791                     iattr->node, NULL,
21792                     "The value must consist of tuples: the target namespace "
21793                     "name and the document's URI", NULL, NULL, NULL);
21794             }
21795             break;
21796         }
21797         count++; /* TODO: Don't use the schema's dict. */
21798         location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21799         cur = end;
21800         ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21801             iattr->node, nsname, location);
21802         if (ret == -1) {
21803             VERROR_INT("xmlSchemaAssembleByXSI",
21804                 "assembling schemata");
21805             return (-1);
21806         }
21807     } while (*cur != 0);
21808     return (ret);
21809 }
21810
21811 static const xmlChar *
21812 xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21813                          const xmlChar *prefix)
21814 {
21815     if (vctxt->sax != NULL) {
21816         int i, j;
21817         xmlSchemaNodeInfoPtr inode;
21818
21819         for (i = vctxt->depth; i >= 0; i--) {
21820             if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21821                 inode = vctxt->elemInfos[i];
21822                 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21823                     if (((prefix == NULL) &&
21824                             (inode->nsBindings[j] == NULL)) ||
21825                         ((prefix != NULL) && xmlStrEqual(prefix,
21826                             inode->nsBindings[j]))) {
21827
21828                         /*
21829                         * Note that the namespace bindings are already
21830                         * in a string dict.
21831                         */
21832                         return (inode->nsBindings[j+1]);
21833                     }
21834                 }
21835             }
21836         }
21837         return (NULL);
21838 #ifdef LIBXML_READER_ENABLED
21839     } else if (vctxt->reader != NULL) {
21840         xmlChar *nsName;
21841
21842         nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21843         if (nsName != NULL) {
21844             const xmlChar *ret;
21845
21846             ret = xmlDictLookup(vctxt->dict, nsName, -1);
21847             xmlFree(nsName);
21848             return (ret);
21849         } else
21850             return (NULL);
21851 #endif
21852     } else {
21853         xmlNsPtr ns;
21854
21855         if ((vctxt->inode->node == NULL) ||
21856             (vctxt->inode->node->doc == NULL)) {
21857             VERROR_INT("xmlSchemaLookupNamespace",
21858                 "no node or node's doc avaliable");
21859             return (NULL);
21860         }
21861         ns = xmlSearchNs(vctxt->inode->node->doc,
21862             vctxt->inode->node, prefix);
21863         if (ns != NULL)
21864             return (ns->href);
21865         return (NULL);
21866     }
21867 }
21868
21869 /*
21870 * This one works on the schema of the validation context.
21871 */
21872 static int
21873 xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21874                           xmlSchemaPtr schema,
21875                           xmlNodePtr node,
21876                           const xmlChar *value,
21877                           xmlSchemaValPtr *val,
21878                           int valNeeded)
21879 {
21880     int ret;
21881
21882     if (vctxt && (vctxt->schema == NULL)) {
21883         VERROR_INT("xmlSchemaValidateNotation",
21884             "a schema is needed on the validation context");
21885         return (-1);
21886     }
21887     ret = xmlValidateQName(value, 1);
21888     if (ret != 0)
21889         return (ret);
21890     {
21891         xmlChar *localName = NULL;
21892         xmlChar *prefix = NULL;
21893
21894         localName = xmlSplitQName2(value, &prefix);
21895         if (prefix != NULL) {
21896             const xmlChar *nsName = NULL;
21897
21898             if (vctxt != NULL)
21899                 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21900             else if (node != NULL) {
21901                 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21902                 if (ns != NULL)
21903                     nsName = ns->href;
21904             } else {
21905                 xmlFree(prefix);
21906                 xmlFree(localName);
21907                 return (1);
21908             }
21909             if (nsName == NULL) {
21910                 xmlFree(prefix);
21911                 xmlFree(localName);
21912                 return (1);
21913             }
21914             if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
21915                 if ((valNeeded) && (val != NULL)) {
21916                     (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName),
21917                                                        xmlStrdup(nsName));
21918                     if (*val == NULL)
21919                         ret = -1;
21920                 }
21921             } else
21922                 ret = 1;
21923             xmlFree(prefix);
21924             xmlFree(localName);
21925         } else {
21926             if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
21927                 if (valNeeded && (val != NULL)) {
21928                     (*val) = xmlSchemaNewNOTATIONValue(
21929                         BAD_CAST xmlStrdup(value), NULL);
21930                     if (*val == NULL)
21931                         ret = -1;
21932                 }
21933             } else
21934                 return (1);
21935         }
21936     }
21937     return (ret);
21938 }
21939
21940 static int
21941 xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21942                        const xmlChar* lname,
21943                        const xmlChar* nsname)
21944 {
21945     int i;
21946
21947     lname = xmlDictLookup(vctxt->dict, lname, -1);
21948     if (lname == NULL)
21949         return(-1);
21950     if (nsname != NULL) {
21951         nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21952         if (nsname == NULL)
21953             return(-1);
21954     }
21955     for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21956         if ((vctxt->nodeQNames->items [i] == lname) &&
21957             (vctxt->nodeQNames->items[i +1] == nsname))
21958             /* Already there */
21959             return(i);
21960     }
21961     /* Add new entry. */
21962     i = vctxt->nodeQNames->nbItems;
21963     xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21964     xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21965     return(i);
21966 }
21967
21968 /************************************************************************
21969  *                                                                      *
21970  *  Validation of identity-constraints (IDC)                            *
21971  *                                                                      *
21972  ************************************************************************/
21973
21974 /**
21975  * xmlSchemaAugmentIDC:
21976  * @idcDef: the IDC definition
21977  *
21978  * Creates an augmented IDC definition item.
21979  *
21980  * Returns the item, or NULL on internal errors.
21981  */
21982 static void
21983 xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
21984                     xmlSchemaValidCtxtPtr vctxt)
21985 {
21986     xmlSchemaIDCAugPtr aidc;
21987
21988     aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
21989     if (aidc == NULL) {
21990         xmlSchemaVErrMemory(vctxt,
21991             "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
21992             NULL);
21993         return;
21994     }
21995     aidc->keyrefDepth = -1;
21996     aidc->def = idcDef;
21997     aidc->next = NULL;
21998     if (vctxt->aidcs == NULL)
21999         vctxt->aidcs = aidc;
22000     else {
22001         aidc->next = vctxt->aidcs;
22002         vctxt->aidcs = aidc;
22003     }
22004     /*
22005     * Save if we have keyrefs at all.
22006     */
22007     if ((vctxt->hasKeyrefs == 0) &&
22008         (idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
22009         vctxt->hasKeyrefs = 1;
22010 }
22011
22012 /**
22013  * xmlSchemaAugmentImportedIDC:
22014  * @imported: the imported schema
22015  *
22016  * Creates an augmented IDC definition for the imported schema.
22017  */
22018 static void
22019 xmlSchemaAugmentImportedIDC(xmlSchemaImportPtr imported, xmlSchemaValidCtxtPtr vctxt) {
22020     if (imported->schema->idcDef != NULL) {
22021             xmlHashScan(imported->schema->idcDef ,
22022             (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
22023     }
22024 }
22025
22026 /**
22027  * xmlSchemaIDCNewBinding:
22028  * @idcDef: the IDC definition of this binding
22029  *
22030  * Creates a new IDC binding.
22031  *
22032  * Returns the new IDC binding, NULL on internal errors.
22033  */
22034 static xmlSchemaPSVIIDCBindingPtr
22035 xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
22036 {
22037     xmlSchemaPSVIIDCBindingPtr ret;
22038
22039     ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
22040             sizeof(xmlSchemaPSVIIDCBinding));
22041     if (ret == NULL) {
22042         xmlSchemaVErrMemory(NULL,
22043             "allocating a PSVI IDC binding item", NULL);
22044         return (NULL);
22045     }
22046     memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
22047     ret->definition = idcDef;
22048     return (ret);
22049 }
22050
22051 /**
22052  * xmlSchemaIDCStoreNodeTableItem:
22053  * @vctxt: the WXS validation context
22054  * @item: the IDC node table item
22055  *
22056  * The validation context is used to store IDC node table items.
22057  * They are stored to avoid copying them if IDC node-tables are merged
22058  * with corresponding parent IDC node-tables (bubbling).
22059  *
22060  * Returns 0 if succeeded, -1 on internal errors.
22061  */
22062 static int
22063 xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
22064                                xmlSchemaPSVIIDCNodePtr item)
22065 {
22066     /*
22067     * Add to gobal list.
22068     */
22069     if (vctxt->idcNodes == NULL) {
22070         vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22071             xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
22072         if (vctxt->idcNodes == NULL) {
22073             xmlSchemaVErrMemory(vctxt,
22074                 "allocating the IDC node table item list", NULL);
22075             return (-1);
22076         }
22077         vctxt->sizeIdcNodes = 20;
22078     } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
22079         vctxt->sizeIdcNodes *= 2;
22080         vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22081             xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
22082             sizeof(xmlSchemaPSVIIDCNodePtr));
22083         if (vctxt->idcNodes == NULL) {
22084             xmlSchemaVErrMemory(vctxt,
22085                 "re-allocating the IDC node table item list", NULL);
22086             return (-1);
22087         }
22088     }
22089     vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
22090
22091     return (0);
22092 }
22093
22094 /**
22095  * xmlSchemaIDCStoreKey:
22096  * @vctxt: the WXS validation context
22097  * @item: the IDC key
22098  *
22099  * The validation context is used to store an IDC key.
22100  *
22101  * Returns 0 if succeeded, -1 on internal errors.
22102  */
22103 static int
22104 xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
22105                      xmlSchemaPSVIIDCKeyPtr key)
22106 {
22107     /*
22108     * Add to gobal list.
22109     */
22110     if (vctxt->idcKeys == NULL) {
22111         vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22112             xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
22113         if (vctxt->idcKeys == NULL) {
22114             xmlSchemaVErrMemory(vctxt,
22115                 "allocating the IDC key storage list", NULL);
22116             return (-1);
22117         }
22118         vctxt->sizeIdcKeys = 40;
22119     } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
22120         vctxt->sizeIdcKeys *= 2;
22121         vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22122             xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
22123             sizeof(xmlSchemaPSVIIDCKeyPtr));
22124         if (vctxt->idcKeys == NULL) {
22125             xmlSchemaVErrMemory(vctxt,
22126                 "re-allocating the IDC key storage list", NULL);
22127             return (-1);
22128         }
22129     }
22130     vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
22131
22132     return (0);
22133 }
22134
22135 /**
22136  * xmlSchemaIDCAppendNodeTableItem:
22137  * @bind: the IDC binding
22138  * @ntItem: the node-table item
22139  *
22140  * Appends the IDC node-table item to the binding.
22141  *
22142  * Returns 0 on success and -1 on internal errors.
22143  */
22144 static int
22145 xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
22146                                 xmlSchemaPSVIIDCNodePtr ntItem)
22147 {
22148     if (bind->nodeTable == NULL) {
22149         bind->sizeNodes = 10;
22150         bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22151             xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
22152         if (bind->nodeTable == NULL) {
22153             xmlSchemaVErrMemory(NULL,
22154                 "allocating an array of IDC node-table items", NULL);
22155             return(-1);
22156         }
22157     } else if (bind->sizeNodes <= bind->nbNodes) {
22158         bind->sizeNodes *= 2;
22159         bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22160             xmlRealloc(bind->nodeTable, bind->sizeNodes *
22161                 sizeof(xmlSchemaPSVIIDCNodePtr));
22162         if (bind->nodeTable == NULL) {
22163             xmlSchemaVErrMemory(NULL,
22164                 "re-allocating an array of IDC node-table items", NULL);
22165             return(-1);
22166         }
22167     }
22168     bind->nodeTable[bind->nbNodes++] = ntItem;
22169     return(0);
22170 }
22171
22172 /**
22173  * xmlSchemaIDCAcquireBinding:
22174  * @vctxt: the WXS validation context
22175  * @matcher: the IDC matcher
22176  *
22177  * Looks up an PSVI IDC binding, for the IDC definition and
22178  * of the given matcher. If none found, a new one is created
22179  * and added to the IDC table.
22180  *
22181  * Returns an IDC binding or NULL on internal errors.
22182  */
22183 static xmlSchemaPSVIIDCBindingPtr
22184 xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
22185                           xmlSchemaIDCMatcherPtr matcher)
22186 {
22187     xmlSchemaNodeInfoPtr ielem;
22188
22189     ielem = vctxt->elemInfos[matcher->depth];
22190
22191     if (ielem->idcTable == NULL) {
22192         ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
22193         if (ielem->idcTable == NULL)
22194             return (NULL);
22195         return(ielem->idcTable);
22196     } else {
22197         xmlSchemaPSVIIDCBindingPtr bind = NULL;
22198
22199         bind = ielem->idcTable;
22200         do {
22201             if (bind->definition == matcher->aidc->def)
22202                 return(bind);
22203             if (bind->next == NULL) {
22204                 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
22205                 if (bind->next == NULL)
22206                     return (NULL);
22207                 return(bind->next);
22208             }
22209             bind = bind->next;
22210         } while (bind != NULL);
22211     }
22212     return (NULL);
22213 }
22214
22215 static xmlSchemaItemListPtr
22216 xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22217                              xmlSchemaIDCMatcherPtr matcher)
22218 {
22219     if (matcher->targets == NULL)
22220         matcher->targets = xmlSchemaItemListCreate();
22221     return(matcher->targets);
22222 }
22223
22224 /**
22225  * xmlSchemaIDCFreeKey:
22226  * @key: the IDC key
22227  *
22228  * Frees an IDC key together with its compiled value.
22229  */
22230 static void
22231 xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
22232 {
22233     if (key->val != NULL)
22234         xmlSchemaFreeValue(key->val);
22235     xmlFree(key);
22236 }
22237
22238 /**
22239  * xmlSchemaIDCFreeBinding:
22240  *
22241  * Frees an IDC binding. Note that the node table-items
22242  * are not freed.
22243  */
22244 static void
22245 xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
22246 {
22247     if (bind->nodeTable != NULL)
22248         xmlFree(bind->nodeTable);
22249     if (bind->dupls != NULL)
22250         xmlSchemaItemListFree(bind->dupls);
22251     xmlFree(bind);
22252 }
22253
22254 /**
22255  * xmlSchemaIDCFreeIDCTable:
22256  * @bind: the first IDC binding in the list
22257  *
22258  * Frees an IDC table, i.e. all the IDC bindings in the list.
22259  */
22260 static void
22261 xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
22262 {
22263     xmlSchemaPSVIIDCBindingPtr prev;
22264
22265     while (bind != NULL) {
22266         prev = bind;
22267         bind = bind->next;
22268         xmlSchemaIDCFreeBinding(prev);
22269     }
22270 }
22271
22272 /**
22273  * xmlSchemaIDCFreeMatcherList:
22274  * @matcher: the first IDC matcher in the list
22275  *
22276  * Frees a list of IDC matchers.
22277  */
22278 static void
22279 xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22280 {
22281     xmlSchemaIDCMatcherPtr next;
22282
22283     while (matcher != NULL) {
22284         next = matcher->next;
22285         if (matcher->keySeqs != NULL) {
22286             int i;
22287             for (i = 0; i < matcher->sizeKeySeqs; i++)
22288                 if (matcher->keySeqs[i] != NULL)
22289                     xmlFree(matcher->keySeqs[i]);
22290             xmlFree(matcher->keySeqs);
22291         }
22292         if (matcher->targets != NULL) {
22293             if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22294                 int i;
22295                 xmlSchemaPSVIIDCNodePtr idcNode;
22296                 /*
22297                 * Node-table items for keyrefs are not stored globally
22298                 * to the validation context, since they are not bubbled.
22299                 * We need to free them here.
22300                 */
22301                 for (i = 0; i < matcher->targets->nbItems; i++) {
22302                     idcNode =
22303                         (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22304                     xmlFree(idcNode->keys);
22305                     xmlFree(idcNode);
22306                 }
22307             }
22308             xmlSchemaItemListFree(matcher->targets);
22309         }
22310         xmlFree(matcher);
22311         matcher = next;
22312     }
22313 }
22314
22315 /**
22316  * xmlSchemaIDCReleaseMatcherList:
22317  * @vctxt: the WXS validation context
22318  * @matcher: the first IDC matcher in the list
22319  *
22320  * Caches a list of IDC matchers for reuse.
22321  */
22322 static void
22323 xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
22324                                xmlSchemaIDCMatcherPtr matcher)
22325 {
22326     xmlSchemaIDCMatcherPtr next;
22327
22328     while (matcher != NULL) {
22329         next = matcher->next;
22330         if (matcher->keySeqs != NULL) {
22331             int i;
22332             /*
22333             * Don't free the array, but only the content.
22334             */
22335             for (i = 0; i < matcher->sizeKeySeqs; i++)
22336                 if (matcher->keySeqs[i] != NULL) {
22337                     xmlFree(matcher->keySeqs[i]);
22338                     matcher->keySeqs[i] = NULL;
22339                 }
22340         }
22341         if (matcher->targets) {
22342             if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22343                 int i;
22344                 xmlSchemaPSVIIDCNodePtr idcNode;
22345                 /*
22346                 * Node-table items for keyrefs are not stored globally
22347                 * to the validation context, since they are not bubbled.
22348                 * We need to free them here.
22349                 */
22350                 for (i = 0; i < matcher->targets->nbItems; i++) {
22351                     idcNode =
22352                         (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22353                     xmlFree(idcNode->keys);
22354                     xmlFree(idcNode);
22355                 }
22356             }
22357             xmlSchemaItemListFree(matcher->targets);
22358             matcher->targets = NULL;
22359         }
22360         matcher->next = NULL;
22361         /*
22362         * Cache the matcher.
22363         */
22364         if (vctxt->idcMatcherCache != NULL)
22365             matcher->nextCached = vctxt->idcMatcherCache;
22366         vctxt->idcMatcherCache = matcher;
22367
22368         matcher = next;
22369     }
22370 }
22371
22372 /**
22373  * xmlSchemaIDCAddStateObject:
22374  * @vctxt: the WXS validation context
22375  * @matcher: the IDC matcher
22376  * @sel: the XPath information
22377  * @parent: the parent "selector" state object if any
22378  * @type: "selector" or "field"
22379  *
22380  * Creates/reuses and activates state objects for the given
22381  * XPath information; if the XPath expression consists of unions,
22382  * multiple state objects are created for every unioned expression.
22383  *
22384  * Returns 0 on success and -1 on internal errors.
22385  */
22386 static int
22387 xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22388                         xmlSchemaIDCMatcherPtr matcher,
22389                         xmlSchemaIDCSelectPtr sel,
22390                         int type)
22391 {
22392     xmlSchemaIDCStateObjPtr sto;
22393
22394     /*
22395     * Reuse the state objects from the pool.
22396     */
22397     if (vctxt->xpathStatePool != NULL) {
22398         sto = vctxt->xpathStatePool;
22399         vctxt->xpathStatePool = sto->next;
22400         sto->next = NULL;
22401     } else {
22402         /*
22403         * Create a new state object.
22404         */
22405         sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22406         if (sto == NULL) {
22407             xmlSchemaVErrMemory(NULL,
22408                 "allocating an IDC state object", NULL);
22409             return (-1);
22410         }
22411         memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22412     }
22413     /*
22414     * Add to global list.
22415     */
22416     if (vctxt->xpathStates != NULL)
22417         sto->next = vctxt->xpathStates;
22418     vctxt->xpathStates = sto;
22419
22420     /*
22421     * Free the old xpath validation context.
22422     */
22423     if (sto->xpathCtxt != NULL)
22424         xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22425
22426     /*
22427     * Create a new XPath (pattern) validation context.
22428     */
22429     sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22430         (xmlPatternPtr) sel->xpathComp);
22431     if (sto->xpathCtxt == NULL) {
22432         VERROR_INT("xmlSchemaIDCAddStateObject",
22433             "failed to create an XPath validation context");
22434         return (-1);
22435     }
22436     sto->type = type;
22437     sto->depth = vctxt->depth;
22438     sto->matcher = matcher;
22439     sto->sel = sel;
22440     sto->nbHistory = 0;
22441
22442 #ifdef DEBUG_IDC
22443     xmlGenericError(xmlGenericErrorContext, "IDC:   STO push '%s'\n",
22444         sto->sel->xpath);
22445 #endif
22446     return (0);
22447 }
22448
22449 /**
22450  * xmlSchemaXPathEvaluate:
22451  * @vctxt: the WXS validation context
22452  * @nodeType: the nodeType of the current node
22453  *
22454  * Evaluates all active XPath state objects.
22455  *
22456  * Returns the number of IC "field" state objects which resolved to
22457  * this node, 0 if none resolved and -1 on internal errors.
22458  */
22459 static int
22460 xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
22461                        xmlElementType nodeType)
22462 {
22463     xmlSchemaIDCStateObjPtr sto, head = NULL, first;
22464     int res, resolved = 0, depth = vctxt->depth;
22465
22466     if (vctxt->xpathStates == NULL)
22467         return (0);
22468
22469     if (nodeType == XML_ATTRIBUTE_NODE)
22470         depth++;
22471 #ifdef DEBUG_IDC
22472     {
22473         xmlChar *str = NULL;
22474         xmlGenericError(xmlGenericErrorContext,
22475             "IDC: EVAL on %s, depth %d, type %d\n",
22476             xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22477                 vctxt->inode->localName), depth, nodeType);
22478         FREE_AND_NULL(str)
22479     }
22480 #endif
22481     /*
22482     * Process all active XPath state objects.
22483     */
22484     first = vctxt->xpathStates;
22485     sto = first;
22486     while (sto != head) {
22487 #ifdef DEBUG_IDC
22488         if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
22489             xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] selector '%s'\n",
22490                 sto->matcher->aidc->def->name, sto->sel->xpath);
22491         else
22492             xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] field '%s'\n",
22493                 sto->matcher->aidc->def->name, sto->sel->xpath);
22494 #endif
22495         if (nodeType == XML_ELEMENT_NODE)
22496             res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
22497                 vctxt->inode->localName, vctxt->inode->nsName);
22498         else
22499             res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
22500                 vctxt->inode->localName, vctxt->inode->nsName);
22501
22502         if (res == -1) {
22503             VERROR_INT("xmlSchemaXPathEvaluate",
22504                 "calling xmlStreamPush()");
22505             return (-1);
22506         }
22507         if (res == 0)
22508             goto next_sto;
22509         /*
22510         * Full match.
22511         */
22512 #ifdef DEBUG_IDC
22513         xmlGenericError(xmlGenericErrorContext, "IDC:     "
22514             "MATCH\n");
22515 #endif
22516         /*
22517         * Register a match in the state object history.
22518         */
22519         if (sto->history == NULL) {
22520             sto->history = (int *) xmlMalloc(5 * sizeof(int));
22521             if (sto->history == NULL) {
22522                 xmlSchemaVErrMemory(NULL,
22523                     "allocating the state object history", NULL);
22524                 return(-1);
22525             }
22526             sto->sizeHistory = 5;
22527         } else if (sto->sizeHistory <= sto->nbHistory) {
22528             sto->sizeHistory *= 2;
22529             sto->history = (int *) xmlRealloc(sto->history,
22530                 sto->sizeHistory * sizeof(int));
22531             if (sto->history == NULL) {
22532                 xmlSchemaVErrMemory(NULL,
22533                     "re-allocating the state object history", NULL);
22534                 return(-1);
22535             }
22536         }
22537         sto->history[sto->nbHistory++] = depth;
22538
22539 #ifdef DEBUG_IDC
22540         xmlGenericError(xmlGenericErrorContext, "IDC:       push match '%d'\n",
22541             vctxt->depth);
22542 #endif
22543
22544         if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22545             xmlSchemaIDCSelectPtr sel;
22546             /*
22547             * Activate state objects for the IDC fields of
22548             * the IDC selector.
22549             */
22550 #ifdef DEBUG_IDC
22551             xmlGenericError(xmlGenericErrorContext, "IDC:     "
22552                 "activating field states\n");
22553 #endif
22554             sel = sto->matcher->aidc->def->fields;
22555             while (sel != NULL) {
22556                 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22557                     sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22558                     return (-1);
22559                 sel = sel->next;
22560             }
22561         } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22562             /*
22563             * An IDC key node was found by the IDC field.
22564             */
22565 #ifdef DEBUG_IDC
22566             xmlGenericError(xmlGenericErrorContext,
22567                 "IDC:     key found\n");
22568 #endif
22569             /*
22570             * Notify that the character value of this node is
22571             * needed.
22572             */
22573             if (resolved == 0) {
22574                 if ((vctxt->inode->flags &
22575                     XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22576                 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22577             }
22578             resolved++;
22579         }
22580 next_sto:
22581         if (sto->next == NULL) {
22582             /*
22583             * Evaluate field state objects created on this node as well.
22584             */
22585             head = first;
22586             sto = vctxt->xpathStates;
22587         } else
22588             sto = sto->next;
22589     }
22590     return (resolved);
22591 }
22592
22593 static const xmlChar *
22594 xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
22595                               xmlChar **buf,
22596                               xmlSchemaPSVIIDCKeyPtr *seq,
22597                               int count)
22598 {
22599     int i, res;
22600     xmlChar *value = NULL;
22601
22602     *buf = xmlStrdup(BAD_CAST "[");
22603     for (i = 0; i < count; i++) {
22604         *buf = xmlStrcat(*buf, BAD_CAST "'");
22605         res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22606             xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22607             &value);
22608         if (res == 0)
22609             *buf = xmlStrcat(*buf, BAD_CAST value);
22610         else {
22611             VERROR_INT("xmlSchemaFormatIDCKeySequence",
22612                 "failed to compute a canonical value");
22613             *buf = xmlStrcat(*buf, BAD_CAST "???");
22614         }
22615         if (i < count -1)
22616             *buf = xmlStrcat(*buf, BAD_CAST "', ");
22617         else
22618             *buf = xmlStrcat(*buf, BAD_CAST "'");
22619         if (value != NULL) {
22620             xmlFree(value);
22621             value = NULL;
22622         }
22623     }
22624     *buf = xmlStrcat(*buf, BAD_CAST "]");
22625
22626     return (BAD_CAST *buf);
22627 }
22628
22629 /**
22630  * xmlSchemaXPathPop:
22631  * @vctxt: the WXS validation context
22632  *
22633  * Pops all XPath states.
22634  *
22635  * Returns 0 on success and -1 on internal errors.
22636  */
22637 static int
22638 xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22639 {
22640     xmlSchemaIDCStateObjPtr sto;
22641     int res;
22642
22643     if (vctxt->xpathStates == NULL)
22644         return(0);
22645     sto = vctxt->xpathStates;
22646     do {
22647         res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22648         if (res == -1)
22649             return (-1);
22650         sto = sto->next;
22651     } while (sto != NULL);
22652     return(0);
22653 }
22654
22655 /**
22656  * xmlSchemaXPathProcessHistory:
22657  * @vctxt: the WXS validation context
22658  * @type: the simple/complex type of the current node if any at all
22659  * @val: the precompiled value
22660  *
22661  * Processes and pops the history items of the IDC state objects.
22662  * IDC key-sequences are validated/created on IDC bindings.
22663  *
22664  * Returns 0 on success and -1 on internal errors.
22665  */
22666 static int
22667 xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
22668                              int depth)
22669 {
22670     xmlSchemaIDCStateObjPtr sto, nextsto;
22671     int res, matchDepth;
22672     xmlSchemaPSVIIDCKeyPtr key = NULL;
22673     xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
22674
22675     if (vctxt->xpathStates == NULL)
22676         return (0);
22677     sto = vctxt->xpathStates;
22678
22679 #ifdef DEBUG_IDC
22680     {
22681         xmlChar *str = NULL;
22682         xmlGenericError(xmlGenericErrorContext,
22683             "IDC: BACK on %s, depth %d\n",
22684             xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22685                 vctxt->inode->localName), vctxt->depth);
22686         FREE_AND_NULL(str)
22687     }
22688 #endif
22689     /*
22690     * Evaluate the state objects.
22691     */
22692     while (sto != NULL) {
22693         res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22694         if (res == -1) {
22695             VERROR_INT("xmlSchemaXPathProcessHistory",
22696                 "calling xmlStreamPop()");
22697             return (-1);
22698         }
22699 #ifdef DEBUG_IDC
22700         xmlGenericError(xmlGenericErrorContext, "IDC:   stream pop '%s'\n",
22701             sto->sel->xpath);
22702 #endif
22703         if (sto->nbHistory == 0)
22704             goto deregister_check;
22705
22706         matchDepth = sto->history[sto->nbHistory -1];
22707
22708         /*
22709         * Only matches at the current depth are of interest.
22710         */
22711         if (matchDepth != depth) {
22712             sto = sto->next;
22713             continue;
22714         }
22715         if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22716             /*
22717             * NOTE: According to
22718             *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22719             *   ... the simple-content of complex types is also allowed.
22720             */
22721
22722             if (WXS_IS_COMPLEX(type)) {
22723                 if (WXS_HAS_SIMPLE_CONTENT(type)) {
22724                     /*
22725                     * Sanity check for complex types with simple content.
22726                     */
22727                     simpleType = type->contentTypeDef;
22728                     if (simpleType == NULL) {
22729                         VERROR_INT("xmlSchemaXPathProcessHistory",
22730                             "field resolves to a CT with simple content "
22731                             "but the CT is missing the ST definition");
22732                         return (-1);
22733                     }
22734                 } else
22735                     simpleType = NULL;
22736             } else
22737                 simpleType = type;
22738             if (simpleType == NULL) {
22739                 xmlChar *str = NULL;
22740
22741                 /*
22742                 * Not qualified if the field resolves to a node of non
22743                 * simple type.
22744                 */
22745                 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22746                     XML_SCHEMAV_CVC_IDC, NULL,
22747                     WXS_BASIC_CAST sto->matcher->aidc->def,
22748                     "The XPath '%s' of a field of %s does evaluate to a node of "
22749                     "non-simple type",
22750                     sto->sel->xpath,
22751                     xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22752                 FREE_AND_NULL(str);
22753                 sto->nbHistory--;
22754                 goto deregister_check;
22755             }
22756
22757             if ((key == NULL) && (vctxt->inode->val == NULL)) {
22758                 /*
22759                 * Failed to provide the normalized value; maybe
22760                 * the value was invalid.
22761                 */
22762                 VERROR(XML_SCHEMAV_CVC_IDC,
22763                     WXS_BASIC_CAST sto->matcher->aidc->def,
22764                     "Warning: No precomputed value available, the value "
22765                     "was either invalid or something strange happend");
22766                 sto->nbHistory--;
22767                 goto deregister_check;
22768             } else {
22769                 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22770                 xmlSchemaPSVIIDCKeyPtr *keySeq;
22771                 int pos, idx;
22772
22773                 /*
22774                 * The key will be anchored on the matcher's list of
22775                 * key-sequences. The position in this list is determined
22776                 * by the target node's depth relative to the matcher's
22777                 * depth of creation (i.e. the depth of the scope element).
22778                 *
22779                 * Element        Depth    Pos   List-entries
22780                 * <scope>          0              NULL
22781                 *   <bar>          1              NULL
22782                 *     <target/>    2       2      target
22783                 *   <bar>
22784                 * </scope>
22785                 *
22786                 * The size of the list is only dependant on the depth of
22787                 * the tree.
22788                 * An entry will be NULLed in selector_leave, i.e. when
22789                 * we hit the target's
22790                 */
22791                 pos = sto->depth - matcher->depth;
22792                 idx = sto->sel->index;
22793
22794                 /*
22795                 * Create/grow the array of key-sequences.
22796                 */
22797                 if (matcher->keySeqs == NULL) {
22798                     if (pos > 9)
22799                         matcher->sizeKeySeqs = pos * 2;
22800                     else
22801                         matcher->sizeKeySeqs = 10;
22802                     matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22803                         xmlMalloc(matcher->sizeKeySeqs *
22804                         sizeof(xmlSchemaPSVIIDCKeyPtr *));
22805                     if (matcher->keySeqs == NULL) {
22806                         xmlSchemaVErrMemory(NULL,
22807                             "allocating an array of key-sequences",
22808                             NULL);
22809                         return(-1);
22810                     }
22811                     memset(matcher->keySeqs, 0,
22812                         matcher->sizeKeySeqs *
22813                         sizeof(xmlSchemaPSVIIDCKeyPtr *));
22814                 } else if (pos >= matcher->sizeKeySeqs) {
22815                     int i = matcher->sizeKeySeqs;
22816
22817                     matcher->sizeKeySeqs *= 2;
22818                     matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22819                         xmlRealloc(matcher->keySeqs,
22820                         matcher->sizeKeySeqs *
22821                         sizeof(xmlSchemaPSVIIDCKeyPtr *));
22822                     if (matcher->keySeqs == NULL) {
22823                         xmlSchemaVErrMemory(NULL,
22824                             "reallocating an array of key-sequences",
22825                             NULL);
22826                         return (-1);
22827                     }
22828                     /*
22829                     * The array needs to be NULLed.
22830                     * TODO: Use memset?
22831                     */
22832                     for (; i < matcher->sizeKeySeqs; i++)
22833                         matcher->keySeqs[i] = NULL;
22834                 }
22835
22836                 /*
22837                 * Get/create the key-sequence.
22838                 */
22839                 keySeq = matcher->keySeqs[pos];
22840                 if (keySeq == NULL) {
22841                     goto create_sequence;
22842                 } else if (keySeq[idx] != NULL) {
22843                     xmlChar *str = NULL;
22844                     /*
22845                     * cvc-identity-constraint:
22846                     * 3 For each node in the `target node set` all
22847                     * of the {fields}, with that node as the context
22848                     * node, evaluate to either an empty node-set or
22849                     * a node-set with exactly one member, which must
22850                     * have a simple type.
22851                     *
22852                     * The key was already set; report an error.
22853                     */
22854                     xmlSchemaCustomErr(ACTXT_CAST vctxt,
22855                         XML_SCHEMAV_CVC_IDC, NULL,
22856                         WXS_BASIC_CAST matcher->aidc->def,
22857                         "The XPath '%s' of a field of %s evaluates to a "
22858                         "node-set with more than one member",
22859                         sto->sel->xpath,
22860                         xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22861                     FREE_AND_NULL(str);
22862                     sto->nbHistory--;
22863                     goto deregister_check;
22864                 } else
22865                     goto create_key;
22866
22867 create_sequence:
22868                 /*
22869                 * Create a key-sequence.
22870                 */
22871                 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22872                     matcher->aidc->def->nbFields *
22873                     sizeof(xmlSchemaPSVIIDCKeyPtr));
22874                 if (keySeq == NULL) {
22875                     xmlSchemaVErrMemory(NULL,
22876                         "allocating an IDC key-sequence", NULL);
22877                     return(-1);
22878                 }
22879                 memset(keySeq, 0, matcher->aidc->def->nbFields *
22880                     sizeof(xmlSchemaPSVIIDCKeyPtr));
22881                 matcher->keySeqs[pos] = keySeq;
22882 create_key:
22883                 /*
22884                 * Create a key once per node only.
22885                 */
22886                 if (key == NULL) {
22887                     key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22888                         sizeof(xmlSchemaPSVIIDCKey));
22889                     if (key == NULL) {
22890                         xmlSchemaVErrMemory(NULL,
22891                             "allocating a IDC key", NULL);
22892                         xmlFree(keySeq);
22893                         matcher->keySeqs[pos] = NULL;
22894                         return(-1);
22895                     }
22896                     /*
22897                     * Consume the compiled value.
22898                     */
22899                     key->type = simpleType;
22900                     key->val = vctxt->inode->val;
22901                     vctxt->inode->val = NULL;
22902                     /*
22903                     * Store the key in a global list.
22904                     */
22905                     if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22906                         xmlSchemaIDCFreeKey(key);
22907                         return (-1);
22908                     }
22909                 }
22910                 keySeq[idx] = key;
22911             }
22912         } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22913
22914             xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
22915             /* xmlSchemaPSVIIDCBindingPtr bind; */
22916             xmlSchemaPSVIIDCNodePtr ntItem;
22917             xmlSchemaIDCMatcherPtr matcher;
22918             xmlSchemaIDCPtr idc;
22919             xmlSchemaItemListPtr targets;
22920             int pos, i, j, nbKeys;
22921             /*
22922             * Here we have the following scenario:
22923             * An IDC 'selector' state object resolved to a target node,
22924             * during the time this target node was in the
22925             * ancestor-or-self axis, the 'field' state object(s) looked
22926             * out for matching nodes to create a key-sequence for this
22927             * target node. Now we are back to this target node and need
22928             * to put the key-sequence, together with the target node
22929             * itself, into the node-table of the corresponding IDC
22930             * binding.
22931             */
22932             matcher = sto->matcher;
22933             idc = matcher->aidc->def;
22934             nbKeys = idc->nbFields;
22935             pos = depth - matcher->depth;
22936             /*
22937             * Check if the matcher has any key-sequences at all, plus
22938             * if it has a key-sequence for the current target node.
22939             */
22940             if ((matcher->keySeqs == NULL) ||
22941                 (matcher->sizeKeySeqs <= pos)) {
22942                 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22943                     goto selector_key_error;
22944                 else
22945                     goto selector_leave;
22946             }
22947
22948             keySeq = &(matcher->keySeqs[pos]);
22949             if (*keySeq == NULL) {
22950                 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22951                     goto selector_key_error;
22952                 else
22953                     goto selector_leave;
22954             }
22955
22956             for (i = 0; i < nbKeys; i++) {
22957                 if ((*keySeq)[i] == NULL) {
22958                     /*
22959                     * Not qualified, if not all fields did resolve.
22960                     */
22961                     if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22962                         /*
22963                         * All fields of a "key" IDC must resolve.
22964                         */
22965                         goto selector_key_error;
22966                     }
22967                     goto selector_leave;
22968                 }
22969             }
22970             /*
22971             * All fields did resolve.
22972             */
22973
22974             /*
22975             * 4.1 If the {identity-constraint category} is unique(/key),
22976             * then no two members of the `qualified node set` have
22977             * `key-sequences` whose members are pairwise equal, as
22978             * defined by Equal in [XML Schemas: Datatypes].
22979             *
22980             * Get the IDC binding from the matcher and check for
22981             * duplicate key-sequences.
22982             */
22983 #if 0
22984             bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22985 #endif
22986             targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
22987             if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
22988                 (targets->nbItems != 0)) {
22989                 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
22990
22991                 i = 0;
22992                 res = 0;
22993                 /*
22994                 * Compare the key-sequences, key by key.
22995                 */
22996                 do {
22997                     bkeySeq =
22998                         ((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys;
22999                     for (j = 0; j < nbKeys; j++) {
23000                         ckey = (*keySeq)[j];
23001                         bkey = bkeySeq[j];
23002                         res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
23003                         if (res == -1) {
23004                             return (-1);
23005                         } else if (res == 0) {
23006                             /*
23007                             * One of the keys differs, so the key-sequence
23008                             * won't be equal; get out.
23009                             */
23010                             break;
23011                         }
23012                     }
23013                     if (res == 1) {
23014                         /*
23015                         * Duplicate key-sequence found.
23016                         */
23017                         break;
23018                     }
23019                     i++;
23020                 } while (i < targets->nbItems);
23021                 if (i != targets->nbItems) {
23022                     xmlChar *str = NULL, *strB = NULL;
23023                     /*
23024                     * TODO: Try to report the key-sequence.
23025                     */
23026                     xmlSchemaCustomErr(ACTXT_CAST vctxt,
23027                         XML_SCHEMAV_CVC_IDC, NULL,
23028                         WXS_BASIC_CAST idc,
23029                         "Duplicate key-sequence %s in %s",
23030                         xmlSchemaFormatIDCKeySequence(vctxt, &str,
23031                             (*keySeq), nbKeys),
23032                         xmlSchemaGetIDCDesignation(&strB, idc));
23033                     FREE_AND_NULL(str);
23034                     FREE_AND_NULL(strB);
23035                     goto selector_leave;
23036                 }
23037             }
23038             /*
23039             * Add a node-table item to the IDC binding.
23040             */
23041             ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
23042                 sizeof(xmlSchemaPSVIIDCNode));
23043             if (ntItem == NULL) {
23044                 xmlSchemaVErrMemory(NULL,
23045                     "allocating an IDC node-table item", NULL);
23046                 xmlFree(*keySeq);
23047                 *keySeq = NULL;
23048                 return(-1);
23049             }
23050             memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
23051
23052             /*
23053             * Store the node-table item in a global list.
23054             */
23055             if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23056                 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
23057                     xmlFree(ntItem);
23058                     xmlFree(*keySeq);
23059                     *keySeq = NULL;
23060                     return (-1);
23061                 }
23062                 ntItem->nodeQNameID = -1;
23063             } else {
23064                 /*
23065                 * Save a cached QName for this node on the IDC node, to be
23066                 * able to report it, even if the node is not saved.
23067                 */
23068                 ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
23069                     vctxt->inode->localName, vctxt->inode->nsName);
23070                 if (ntItem->nodeQNameID == -1) {
23071                     xmlFree(ntItem);
23072                     xmlFree(*keySeq);
23073                     *keySeq = NULL;
23074                     return (-1);
23075                 }
23076             }
23077             /*
23078             * Init the node-table item: Save the node, position and
23079             * consume the key-sequence.
23080             */
23081             ntItem->node = vctxt->node;
23082             ntItem->nodeLine = vctxt->inode->nodeLine;
23083             ntItem->keys = *keySeq;
23084             *keySeq = NULL;
23085 #if 0
23086             if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1)
23087 #endif
23088             if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
23089                 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23090                     /*
23091                     * Free the item, since keyref items won't be
23092                     * put on a global list.
23093                     */
23094                     xmlFree(ntItem->keys);
23095                     xmlFree(ntItem);
23096                 }
23097                 return (-1);
23098             }
23099
23100             goto selector_leave;
23101 selector_key_error:
23102             {
23103                 xmlChar *str = NULL;
23104                 /*
23105                 * 4.2.1 (KEY) The `target node set` and the
23106                 * `qualified node set` are equal, that is, every
23107                 * member of the `target node set` is also a member
23108                 * of the `qualified node set` and vice versa.
23109                 */
23110                 xmlSchemaCustomErr(ACTXT_CAST vctxt,
23111                     XML_SCHEMAV_CVC_IDC, NULL,
23112                     WXS_BASIC_CAST idc,
23113                     "Not all fields of %s evaluate to a node",
23114                     xmlSchemaGetIDCDesignation(&str, idc), NULL);
23115                 FREE_AND_NULL(str);
23116             }
23117 selector_leave:
23118             /*
23119             * Free the key-sequence if not added to the IDC table.
23120             */
23121             if ((keySeq != NULL) && (*keySeq != NULL)) {
23122                 xmlFree(*keySeq);
23123                 *keySeq = NULL;
23124             }
23125         } /* if selector */
23126
23127         sto->nbHistory--;
23128
23129 deregister_check:
23130         /*
23131         * Deregister state objects if they reach the depth of creation.
23132         */
23133         if ((sto->nbHistory == 0) && (sto->depth == depth)) {
23134 #ifdef DEBUG_IDC
23135             xmlGenericError(xmlGenericErrorContext, "IDC:   STO pop '%s'\n",
23136                 sto->sel->xpath);
23137 #endif
23138             if (vctxt->xpathStates != sto) {
23139                 VERROR_INT("xmlSchemaXPathProcessHistory",
23140                     "The state object to be removed is not the first "
23141                     "in the list");
23142             }
23143             nextsto = sto->next;
23144             /*
23145             * Unlink from the list of active XPath state objects.
23146             */
23147             vctxt->xpathStates = sto->next;
23148             sto->next = vctxt->xpathStatePool;
23149             /*
23150             * Link it to the pool of reusable state objects.
23151             */
23152             vctxt->xpathStatePool = sto;
23153             sto = nextsto;
23154         } else
23155             sto = sto->next;
23156     } /* while (sto != NULL) */
23157     return (0);
23158 }
23159
23160 /**
23161  * xmlSchemaIDCRegisterMatchers:
23162  * @vctxt: the WXS validation context
23163  * @elemDecl: the element declaration
23164  *
23165  * Creates helper objects to evaluate IDC selectors/fields
23166  * successively.
23167  *
23168  * Returns 0 if OK and -1 on internal errors.
23169  */
23170 static int
23171 xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
23172                              xmlSchemaElementPtr elemDecl)
23173 {
23174     xmlSchemaIDCMatcherPtr matcher, last = NULL;
23175     xmlSchemaIDCPtr idc, refIdc;
23176     xmlSchemaIDCAugPtr aidc;
23177
23178     idc = (xmlSchemaIDCPtr) elemDecl->idcs;
23179     if (idc == NULL)
23180         return (0);
23181
23182 #ifdef DEBUG_IDC
23183     {
23184         xmlChar *str = NULL;
23185         xmlGenericError(xmlGenericErrorContext,
23186             "IDC: REGISTER on %s, depth %d\n",
23187             (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
23188                 vctxt->inode->localName), vctxt->depth);
23189         FREE_AND_NULL(str)
23190     }
23191 #endif
23192     if (vctxt->inode->idcMatchers != NULL) {
23193         VERROR_INT("xmlSchemaIDCRegisterMatchers",
23194             "The chain of IDC matchers is expected to be empty");
23195         return (-1);
23196     }
23197     do {
23198         if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23199             /*
23200             * Since IDCs bubbles are expensive we need to know the
23201             * depth at which the bubbles should stop; this will be
23202             * the depth of the top-most keyref IDC. If no keyref
23203             * references a key/unique IDC, the keyrefDepth will
23204             * be -1, indicating that no bubbles are needed.
23205             */
23206             refIdc = (xmlSchemaIDCPtr) idc->ref->item;
23207             if (refIdc != NULL) {
23208                 /*
23209                 * Remember that we have keyrefs on this node.
23210                 */
23211                 vctxt->inode->hasKeyrefs = 1;
23212                 /*
23213                 * Lookup the referenced augmented IDC info.
23214                 */
23215                 aidc = vctxt->aidcs;
23216                 while (aidc != NULL) {
23217                     if (aidc->def == refIdc)
23218                         break;
23219                     aidc = aidc->next;
23220                 }
23221                 if (aidc == NULL) {
23222                     VERROR_INT("xmlSchemaIDCRegisterMatchers",
23223                         "Could not find an augmented IDC item for an IDC "
23224                         "definition");
23225                     return (-1);
23226                 }
23227                 if ((aidc->keyrefDepth == -1) ||
23228                     (vctxt->depth < aidc->keyrefDepth))
23229                     aidc->keyrefDepth = vctxt->depth;
23230             }
23231         }
23232         /*
23233         * Lookup the augmented IDC item for the IDC definition.
23234         */
23235         aidc = vctxt->aidcs;
23236         while (aidc != NULL) {
23237             if (aidc->def == idc)
23238                 break;
23239             aidc = aidc->next;
23240         }
23241         if (aidc == NULL) {
23242             VERROR_INT("xmlSchemaIDCRegisterMatchers",
23243                 "Could not find an augmented IDC item for an IDC definition");
23244             return (-1);
23245         }
23246         /*
23247         * Create an IDC matcher for every IDC definition.
23248         */
23249         if (vctxt->idcMatcherCache != NULL) {
23250             /*
23251             * Reuse a cached matcher.
23252             */
23253             matcher = vctxt->idcMatcherCache;
23254             vctxt->idcMatcherCache = matcher->nextCached;
23255             matcher->nextCached = NULL;
23256         } else {
23257             matcher = (xmlSchemaIDCMatcherPtr)
23258                 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
23259             if (matcher == NULL) {
23260                 xmlSchemaVErrMemory(vctxt,
23261                     "allocating an IDC matcher", NULL);
23262                 return (-1);
23263             }
23264             memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
23265         }
23266         if (last == NULL)
23267             vctxt->inode->idcMatchers = matcher;
23268         else
23269             last->next = matcher;
23270         last = matcher;
23271
23272         matcher->type = IDC_MATCHER;
23273         matcher->depth = vctxt->depth;
23274         matcher->aidc = aidc;
23275         matcher->idcType = aidc->def->type;
23276 #ifdef DEBUG_IDC
23277         xmlGenericError(xmlGenericErrorContext, "IDC:   register matcher\n");
23278 #endif
23279         /*
23280         * Init the automaton state object.
23281         */
23282         if (xmlSchemaIDCAddStateObject(vctxt, matcher,
23283             idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
23284             return (-1);
23285
23286         idc = idc->next;
23287     } while (idc != NULL);
23288     return (0);
23289 }
23290
23291 static int
23292 xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
23293                            xmlSchemaNodeInfoPtr ielem)
23294 {
23295     xmlSchemaPSVIIDCBindingPtr bind;
23296     int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
23297     xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
23298     xmlSchemaPSVIIDCNodePtr *targets, *dupls;
23299
23300     xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
23301     /* vctxt->createIDCNodeTables */
23302     while (matcher != NULL) {
23303         /*
23304         * Skip keyref IDCs and empty IDC target-lists.
23305         */
23306         if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
23307             WXS_ILIST_IS_EMPTY(matcher->targets))
23308         {
23309             matcher = matcher->next;
23310             continue;
23311         }
23312         /*
23313         * If we _want_ the IDC node-table to be created in any case
23314         * then do so. Otherwise create them only if keyrefs need them.
23315         */
23316         if ((! vctxt->createIDCNodeTables) &&
23317             ((matcher->aidc->keyrefDepth == -1) ||
23318              (matcher->aidc->keyrefDepth > vctxt->depth)))
23319         {
23320             matcher = matcher->next;
23321             continue;
23322         }
23323         /*
23324         * Get/create the IDC binding on this element for the IDC definition.
23325         */
23326         bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23327
23328         if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
23329             dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23330             nbDupls = bind->dupls->nbItems;
23331         } else {
23332             dupls = NULL;
23333             nbDupls = 0;
23334         }
23335         if (bind->nodeTable != NULL) {
23336             nbNodeTable = bind->nbNodes;
23337         } else {
23338             nbNodeTable = 0;
23339         }
23340
23341         if ((nbNodeTable == 0) && (nbDupls == 0)) {
23342             /*
23343             * Transfer all IDC target-nodes to the IDC node-table.
23344             */
23345             bind->nodeTable =
23346                 (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23347             bind->sizeNodes = matcher->targets->sizeItems;
23348             bind->nbNodes = matcher->targets->nbItems;
23349
23350             matcher->targets->items = NULL;
23351             matcher->targets->sizeItems = 0;
23352             matcher->targets->nbItems = 0;
23353         } else {
23354             /*
23355             * Compare the key-sequences and add to the IDC node-table.
23356             */
23357             nbTargets = matcher->targets->nbItems;
23358             targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23359             nbFields = matcher->aidc->def->nbFields;
23360             i = 0;
23361             do {
23362                 keys = targets[i]->keys;
23363                 if (nbDupls) {
23364                     /*
23365                     * Search in already found duplicates first.
23366                     */
23367                     j = 0;
23368                     do {
23369                         if (nbFields == 1) {
23370                             res = xmlSchemaAreValuesEqual(keys[0]->val,
23371                                 dupls[j]->keys[0]->val);
23372                             if (res == -1)
23373                                 goto internal_error;
23374                             if (res == 1) {
23375                                 /*
23376                                 * Equal key-sequence.
23377                                 */
23378                                 goto next_target;
23379                             }
23380                         } else {
23381                             res = 0;
23382                             ntkeys = dupls[j]->keys;
23383                             for (k = 0; k < nbFields; k++) {
23384                                 res = xmlSchemaAreValuesEqual(keys[k]->val,
23385                                     ntkeys[k]->val);
23386                                 if (res == -1)
23387                                     goto internal_error;
23388                                 if (res == 0) {
23389                                     /*
23390                                     * One of the keys differs.
23391                                     */
23392                                     break;
23393                                 }
23394                             }
23395                             if (res == 1) {
23396                                 /*
23397                                 * Equal key-sequence found.
23398                                 */
23399                                 goto next_target;
23400                             }
23401                         }
23402                         j++;
23403                     } while (j < nbDupls);
23404                 }
23405                 if (nbNodeTable) {
23406                     j = 0;
23407                     do {
23408                         if (nbFields == 1) {
23409                             res = xmlSchemaAreValuesEqual(keys[0]->val,
23410                                 bind->nodeTable[j]->keys[0]->val);
23411                             if (res == -1)
23412                                 goto internal_error;
23413                             if (res == 0) {
23414                                 /*
23415                                 * The key-sequence differs.
23416                                 */
23417                                 goto next_node_table_entry;
23418                             }
23419                         } else {
23420                             res = 0;
23421                             ntkeys = bind->nodeTable[j]->keys;
23422                             for (k = 0; k < nbFields; k++) {
23423                                 res = xmlSchemaAreValuesEqual(keys[k]->val,
23424                                     ntkeys[k]->val);
23425                                 if (res == -1)
23426                                     goto internal_error;
23427                                 if (res == 0) {
23428                                     /*
23429                                     * One of the keys differs.
23430                                     */
23431                                     goto next_node_table_entry;
23432                                 }
23433                             }
23434                         }
23435                         /*
23436                         * Add the duplicate to the list of duplicates.
23437                         */
23438                         if (bind->dupls == NULL) {
23439                             bind->dupls = xmlSchemaItemListCreate();
23440                             if (bind->dupls == NULL)
23441                                 goto internal_error;
23442                         }
23443                         if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23444                             goto internal_error;
23445                         /*
23446                         * Remove the duplicate entry from the IDC node-table.
23447                         */
23448                         bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23449                         bind->nbNodes--;
23450
23451                         goto next_target;
23452
23453 next_node_table_entry:
23454                         j++;
23455                     } while (j < nbNodeTable);
23456                 }
23457                 /*
23458                 * If everything is fine, then add the IDC target-node to
23459                 * the IDC node-table.
23460                 */
23461                 if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23462                     goto internal_error;
23463
23464 next_target:
23465                 i++;
23466             } while (i < nbTargets);
23467         }
23468         matcher = matcher->next;
23469     }
23470     return(0);
23471
23472 internal_error:
23473     return(-1);
23474 }
23475
23476 /**
23477  * xmlSchemaBubbleIDCNodeTables:
23478  * @depth: the current tree depth
23479  *
23480  * Merges IDC bindings of an element at @depth into the corresponding IDC
23481  * bindings of its parent element. If a duplicate note-table entry is found,
23482  * both, the parent node-table entry and child entry are discarded from the
23483  * node-table of the parent.
23484  *
23485  * Returns 0 if OK and -1 on internal errors.
23486  */
23487 static int
23488 xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23489 {
23490     xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
23491     xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23492     xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
23493     xmlSchemaIDCAugPtr aidc;
23494     int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
23495
23496     bind = vctxt->inode->idcTable;
23497     if (bind == NULL) {
23498         /* Fine, no table, no bubbles. */
23499         return (0);
23500     }
23501
23502     parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23503     /*
23504     * Walk all bindings; create new or add to existing bindings.
23505     * Remove duplicate key-sequences.
23506     */
23507     while (bind != NULL) {
23508
23509         if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23510             goto next_binding;
23511         /*
23512         * Check if the key/unique IDC table needs to be bubbled.
23513         */
23514         if (! vctxt->createIDCNodeTables) {
23515             aidc = vctxt->aidcs;
23516             do {
23517                 if (aidc->def == bind->definition) {
23518                     if ((aidc->keyrefDepth == -1) ||
23519                         (aidc->keyrefDepth >= vctxt->depth)) {
23520                         goto next_binding;
23521                     }
23522                     break;
23523                 }
23524                 aidc = aidc->next;
23525             } while (aidc != NULL);
23526         }
23527
23528         if (parTable != NULL)
23529             parBind = *parTable;
23530         /*
23531         * Search a matching parent binding for the
23532         * IDC definition.
23533         */
23534         while (parBind != NULL) {
23535             if (parBind->definition == bind->definition)
23536                 break;
23537             parBind = parBind->next;
23538         }
23539
23540         if (parBind != NULL) {
23541             /*
23542             * Compare every node-table entry of the child node,
23543             * i.e. the key-sequence within, ...
23544             */
23545             oldNum = parBind->nbNodes; /* Skip newly added items. */
23546
23547             if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23548                 oldDupls = parBind->dupls->nbItems;
23549                 dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23550             } else {
23551                 dupls = NULL;
23552                 oldDupls = 0;
23553             }
23554
23555             parNodes = parBind->nodeTable;
23556             nbFields = bind->definition->nbFields;
23557
23558             for (i = 0; i < bind->nbNodes; i++) {
23559                 node = bind->nodeTable[i];
23560                 if (node == NULL)
23561                     continue;
23562                 /*
23563                 * ...with every key-sequence of the parent node, already
23564                 * evaluated to be a duplicate key-sequence.
23565                 */
23566                 if (oldDupls) {
23567                     j = 0;
23568                     while (j < oldDupls) {
23569                         if (nbFields == 1) {
23570                             ret = xmlSchemaAreValuesEqual(
23571                                 node->keys[0]->val,
23572                                 dupls[j]->keys[0]->val);
23573                             if (ret == -1)
23574                                 goto internal_error;
23575                             if (ret == 0) {
23576                                 j++;
23577                                 continue;
23578                             }
23579                         } else {
23580                             parNode = dupls[j];
23581                             for (k = 0; k < nbFields; k++) {
23582                                 ret = xmlSchemaAreValuesEqual(
23583                                     node->keys[k]->val,
23584                                     parNode->keys[k]->val);
23585                                 if (ret == -1)
23586                                     goto internal_error;
23587                                 if (ret == 0)
23588                                     break;
23589                             }
23590                         }
23591                         if (ret == 1)
23592                             /* Duplicate found. */
23593                             break;
23594                         j++;
23595                     }
23596                     if (j != oldDupls) {
23597                         /* Duplicate found. Skip this entry. */
23598                         continue;
23599                     }
23600                 }
23601                 /*
23602                 * ... and with every key-sequence of the parent node.
23603                 */
23604                 if (oldNum) {
23605                     j = 0;
23606                     while (j < oldNum) {
23607                         parNode = parNodes[j];
23608                         if (nbFields == 1) {
23609                             ret = xmlSchemaAreValuesEqual(
23610                                 node->keys[0]->val,
23611                                 parNode->keys[0]->val);
23612                             if (ret == -1)
23613                                 goto internal_error;
23614                             if (ret == 0) {
23615                                 j++;
23616                                 continue;
23617                             }
23618                         } else {
23619                             for (k = 0; k < nbFields; k++) {
23620                                 ret = xmlSchemaAreValuesEqual(
23621                                     node->keys[k]->val,
23622                                     parNode->keys[k]->val);
23623                                 if (ret == -1)
23624                                     goto internal_error;
23625                                 if (ret == 0)
23626                                     break;
23627                             }
23628                         }
23629                         if (ret == 1)
23630                             /* Duplicate found. */
23631                             break;
23632                         j++;
23633                     }
23634                     if (j != oldNum) {
23635                         /*
23636                         * Handle duplicates. Move the duplicate in
23637                         * the parent's node-table to the list of
23638                         * duplicates.
23639                         */
23640                         oldNum--;
23641                         parBind->nbNodes--;
23642                         /*
23643                         * Move last old item to pos of duplicate.
23644                         */
23645                         parNodes[j] = parNodes[oldNum];
23646
23647                         if (parBind->nbNodes != oldNum) {
23648                             /*
23649                             * If new items exist, move last new item to
23650                             * last of old items.
23651                             */
23652                             parNodes[oldNum] =
23653                                 parNodes[parBind->nbNodes];
23654                         }
23655                         if (parBind->dupls == NULL) {
23656                             parBind->dupls = xmlSchemaItemListCreate();
23657                             if (parBind->dupls == NULL)
23658                                 goto internal_error;
23659                         }
23660                         xmlSchemaItemListAdd(parBind->dupls, parNode);
23661                     } else {
23662                         /*
23663                         * Add the node-table entry (node and key-sequence) of
23664                         * the child node to the node table of the parent node.
23665                         */
23666                         if (parBind->nodeTable == NULL) {
23667                             parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23668                                 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
23669                             if (parBind->nodeTable == NULL) {
23670                                 xmlSchemaVErrMemory(NULL,
23671                                     "allocating IDC list of node-table items", NULL);
23672                                 goto internal_error;
23673                             }
23674                             parBind->sizeNodes = 1;
23675                         } else if (parBind->nbNodes >= parBind->sizeNodes) {
23676                             parBind->sizeNodes *= 2;
23677                             parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23678                                 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23679                                 sizeof(xmlSchemaPSVIIDCNodePtr));
23680                             if (parBind->nodeTable == NULL) {
23681                                 xmlSchemaVErrMemory(NULL,
23682                                     "re-allocating IDC list of node-table items", NULL);
23683                                 goto internal_error;
23684                             }
23685                         }
23686                         parNodes = parBind->nodeTable;
23687                         /*
23688                         * Append the new node-table entry to the 'new node-table
23689                         * entries' section.
23690                         */
23691                         parNodes[parBind->nbNodes++] = node;
23692                     }
23693
23694                 }
23695
23696             }
23697         } else {
23698             /*
23699             * No binding for the IDC was found: create a new one and
23700             * copy all node-tables.
23701             */
23702             parBind = xmlSchemaIDCNewBinding(bind->definition);
23703             if (parBind == NULL)
23704                 goto internal_error;
23705
23706             /*
23707             * TODO: Hmm, how to optimize the initial number of
23708             * allocated entries?
23709             */
23710             if (bind->nbNodes != 0) {
23711                 /*
23712                 * Add all IDC node-table entries.
23713                 */
23714                 if (! vctxt->psviExposeIDCNodeTables) {
23715                     /*
23716                     * Just move the entries.
23717                     * NOTE: this is quite save here, since
23718                     * all the keyref lookups have already been
23719                     * performed.
23720                     */
23721                     parBind->nodeTable = bind->nodeTable;
23722                     bind->nodeTable = NULL;
23723                     parBind->sizeNodes = bind->sizeNodes;
23724                     bind->sizeNodes = 0;
23725                     parBind->nbNodes = bind->nbNodes;
23726                     bind->nbNodes = 0;
23727                 } else {
23728                     /*
23729                     * Copy the entries.
23730                     */
23731                     parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23732                         xmlMalloc(bind->nbNodes *
23733                         sizeof(xmlSchemaPSVIIDCNodePtr));
23734                     if (parBind->nodeTable == NULL) {
23735                         xmlSchemaVErrMemory(NULL,
23736                             "allocating an array of IDC node-table "
23737                             "items", NULL);
23738                         xmlSchemaIDCFreeBinding(parBind);
23739                         goto internal_error;
23740                     }
23741                     parBind->sizeNodes = bind->nbNodes;
23742                     parBind->nbNodes = bind->nbNodes;
23743                     memcpy(parBind->nodeTable, bind->nodeTable,
23744                         bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23745                 }
23746             }
23747             if (bind->dupls) {
23748                 /*
23749                 * Move the duplicates.
23750                 */
23751                 if (parBind->dupls != NULL)
23752                     xmlSchemaItemListFree(parBind->dupls);
23753                 parBind->dupls = bind->dupls;
23754                 bind->dupls = NULL;
23755             }
23756             if (parTable != NULL) {
23757                 if (*parTable == NULL)
23758                     *parTable = parBind;
23759                 else {
23760                     parBind->next = *parTable;
23761                     *parTable = parBind;
23762                 }
23763             }
23764         }
23765
23766 next_binding:
23767         bind = bind->next;
23768     }
23769     return (0);
23770
23771 internal_error:
23772     return(-1);
23773 }
23774
23775 /**
23776  * xmlSchemaCheckCVCIDCKeyRef:
23777  * @vctxt: the WXS validation context
23778  * @elemDecl: the element declaration
23779  *
23780  * Check the cvc-idc-keyref constraints.
23781  */
23782 static int
23783 xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23784 {
23785     xmlSchemaIDCMatcherPtr matcher;
23786     xmlSchemaPSVIIDCBindingPtr bind;
23787
23788     matcher = vctxt->inode->idcMatchers;
23789     /*
23790     * Find a keyref.
23791     */
23792     while (matcher != NULL) {
23793         if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23794             matcher->targets &&
23795             matcher->targets->nbItems)
23796         {
23797             int i, j, k, res, nbFields, hasDupls;
23798             xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
23799             xmlSchemaPSVIIDCNodePtr refNode = NULL;
23800
23801             nbFields = matcher->aidc->def->nbFields;
23802
23803             /*
23804             * Find the IDC node-table for the referenced IDC key/unique.
23805             */
23806             bind = vctxt->inode->idcTable;
23807             while (bind != NULL) {
23808                 if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
23809                     bind->definition)
23810                     break;
23811                 bind = bind->next;
23812             }
23813             hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
23814             /*
23815             * Search for a matching key-sequences.
23816             */
23817             for (i = 0; i < matcher->targets->nbItems; i++) {
23818                 res = 0;
23819                 refNode = matcher->targets->items[i];
23820                 if (bind != NULL) {
23821                     refKeys = refNode->keys;
23822                     for (j = 0; j < bind->nbNodes; j++) {
23823                         keys = bind->nodeTable[j]->keys;
23824                         for (k = 0; k < nbFields; k++) {
23825                             res = xmlSchemaAreValuesEqual(keys[k]->val,
23826                                 refKeys[k]->val);
23827                             if (res == 0)
23828                                 break;
23829                             else if (res == -1) {
23830                                 return (-1);
23831                             }
23832                         }
23833                         if (res == 1) {
23834                             /*
23835                             * Match found.
23836                             */
23837                             break;
23838                         }
23839                     }
23840                     if ((res == 0) && hasDupls) {
23841                         /*
23842                         * Search in duplicates
23843                         */
23844                         for (j = 0; j < bind->dupls->nbItems; j++) {
23845                             keys = ((xmlSchemaPSVIIDCNodePtr)
23846                                 bind->dupls->items[j])->keys;
23847                             for (k = 0; k < nbFields; k++) {
23848                                 res = xmlSchemaAreValuesEqual(keys[k]->val,
23849                                     refKeys[k]->val);
23850                                 if (res == 0)
23851                                     break;
23852                                 else if (res == -1) {
23853                                     return (-1);
23854                                 }
23855                             }
23856                             if (res == 1) {
23857                                 /*
23858                                 * Match in duplicates found.
23859                                 */
23860                                 xmlChar *str = NULL, *strB = NULL;
23861                                 xmlSchemaKeyrefErr(vctxt,
23862                                     XML_SCHEMAV_CVC_IDC, refNode,
23863                                     (xmlSchemaTypePtr) matcher->aidc->def,
23864                                     "More than one match found for "
23865                                     "key-sequence %s of keyref '%s'",
23866                                     xmlSchemaFormatIDCKeySequence(vctxt, &str,
23867                                         refNode->keys, nbFields),
23868                                     xmlSchemaGetComponentQName(&strB,
23869                                         matcher->aidc->def));
23870                                 FREE_AND_NULL(str);
23871                                 FREE_AND_NULL(strB);
23872                                 break;
23873                             }
23874                         }
23875                     }
23876                 }
23877
23878                 if (res == 0) {
23879                     xmlChar *str = NULL, *strB = NULL;
23880                     xmlSchemaKeyrefErr(vctxt,
23881                         XML_SCHEMAV_CVC_IDC, refNode,
23882                         (xmlSchemaTypePtr) matcher->aidc->def,
23883                         "No match found for key-sequence %s of keyref '%s'",
23884                         xmlSchemaFormatIDCKeySequence(vctxt, &str,
23885                             refNode->keys, nbFields),
23886                         xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
23887                     FREE_AND_NULL(str);
23888                     FREE_AND_NULL(strB);
23889                 }
23890             }
23891         }
23892         matcher = matcher->next;
23893     }
23894     /* TODO: Return an error if any error encountered. */
23895     return (0);
23896 }
23897
23898 /************************************************************************
23899  *                                                                      *
23900  *                      XML Reader validation code                      *
23901  *                                                                      *
23902  ************************************************************************/
23903
23904 static xmlSchemaAttrInfoPtr
23905 xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
23906 {
23907     xmlSchemaAttrInfoPtr iattr;
23908     /*
23909     * Grow/create list of attribute infos.
23910     */
23911     if (vctxt->attrInfos == NULL) {
23912         vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23913             xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23914         vctxt->sizeAttrInfos = 1;
23915         if (vctxt->attrInfos == NULL) {
23916             xmlSchemaVErrMemory(vctxt,
23917                 "allocating attribute info list", NULL);
23918             return (NULL);
23919         }
23920     } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23921         vctxt->sizeAttrInfos++;
23922         vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23923             xmlRealloc(vctxt->attrInfos,
23924                 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23925         if (vctxt->attrInfos == NULL) {
23926             xmlSchemaVErrMemory(vctxt,
23927                 "re-allocating attribute info list", NULL);
23928             return (NULL);
23929         }
23930     } else {
23931         iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23932         if (iattr->localName != NULL) {
23933             VERROR_INT("xmlSchemaGetFreshAttrInfo",
23934                 "attr info not cleared");
23935             return (NULL);
23936         }
23937         iattr->nodeType = XML_ATTRIBUTE_NODE;
23938         return (iattr);
23939     }
23940     /*
23941     * Create an attribute info.
23942     */
23943     iattr = (xmlSchemaAttrInfoPtr)
23944         xmlMalloc(sizeof(xmlSchemaAttrInfo));
23945     if (iattr == NULL) {
23946         xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
23947         return (NULL);
23948     }
23949     memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23950     iattr->nodeType = XML_ATTRIBUTE_NODE;
23951     vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23952
23953     return (iattr);
23954 }
23955
23956 static int
23957 xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23958                         xmlNodePtr attrNode,
23959                         int nodeLine,
23960                         const xmlChar *localName,
23961                         const xmlChar *nsName,
23962                         int ownedNames,
23963                         xmlChar *value,
23964                         int ownedValue)
23965 {
23966     xmlSchemaAttrInfoPtr attr;
23967
23968     attr = xmlSchemaGetFreshAttrInfo(vctxt);
23969     if (attr == NULL) {
23970         VERROR_INT("xmlSchemaPushAttribute",
23971             "calling xmlSchemaGetFreshAttrInfo()");
23972         return (-1);
23973     }
23974     attr->node = attrNode;
23975     attr->nodeLine = nodeLine;
23976     attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23977     attr->localName = localName;
23978     attr->nsName = nsName;
23979     if (ownedNames)
23980         attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23981     /*
23982     * Evaluate if it's an XSI attribute.
23983     */
23984     if (nsName != NULL) {
23985         if (xmlStrEqual(localName, BAD_CAST "nil")) {
23986             if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23987                 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
23988             }
23989         } else if (xmlStrEqual(localName, BAD_CAST "type")) {
23990             if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23991                 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
23992             }
23993         } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
23994             if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23995                 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
23996             }
23997         } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
23998             if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23999                 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
24000             }
24001         } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
24002             attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
24003         }
24004     }
24005     attr->value = value;
24006     if (ownedValue)
24007         attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
24008     if (attr->metaType != 0)
24009         attr->state = XML_SCHEMAS_ATTR_META;
24010     return (0);
24011 }
24012
24013 /**
24014  * xmlSchemaClearElemInfo:
24015  * @vctxt: the WXS validation context
24016  * @ielem: the element information item
24017  */
24018 static void
24019 xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,
24020                        xmlSchemaNodeInfoPtr ielem)
24021 {
24022     ielem->hasKeyrefs = 0;
24023     ielem->appliedXPath = 0;
24024     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
24025         FREE_AND_NULL(ielem->localName);
24026         FREE_AND_NULL(ielem->nsName);
24027     } else {
24028         ielem->localName = NULL;
24029         ielem->nsName = NULL;
24030     }
24031     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24032         FREE_AND_NULL(ielem->value);
24033     } else {
24034         ielem->value = NULL;
24035     }
24036     if (ielem->val != NULL) {
24037         /*
24038         * PSVI TODO: Be careful not to free it when the value is
24039         * exposed via PSVI.
24040         */
24041         xmlSchemaFreeValue(ielem->val);
24042         ielem->val = NULL;
24043     }
24044     if (ielem->idcMatchers != NULL) {
24045         /*
24046         * REVISIT OPTIMIZE TODO: Use a pool of IDC matchers.
24047         *   Does it work?
24048         */
24049         xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers);
24050 #if 0
24051         xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
24052 #endif
24053         ielem->idcMatchers = NULL;
24054     }
24055     if (ielem->idcTable != NULL) {
24056         /*
24057         * OPTIMIZE TODO: Use a pool of IDC tables??.
24058         */
24059         xmlSchemaIDCFreeIDCTable(ielem->idcTable);
24060         ielem->idcTable = NULL;
24061     }
24062     if (ielem->regexCtxt != NULL) {
24063         xmlRegFreeExecCtxt(ielem->regexCtxt);
24064         ielem->regexCtxt = NULL;
24065     }
24066     if (ielem->nsBindings != NULL) {
24067         xmlFree((xmlChar **)ielem->nsBindings);
24068         ielem->nsBindings = NULL;
24069         ielem->nbNsBindings = 0;
24070         ielem->sizeNsBindings = 0;
24071     }
24072 }
24073
24074 /**
24075  * xmlSchemaGetFreshElemInfo:
24076  * @vctxt: the schema validation context
24077  *
24078  * Creates/reuses and initializes the element info item for
24079  * the currect tree depth.
24080  *
24081  * Returns the element info item or NULL on API or internal errors.
24082  */
24083 static xmlSchemaNodeInfoPtr
24084 xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
24085 {
24086     xmlSchemaNodeInfoPtr info = NULL;
24087
24088     if (vctxt->depth > vctxt->sizeElemInfos) {
24089         VERROR_INT("xmlSchemaGetFreshElemInfo",
24090             "inconsistent depth encountered");
24091         return (NULL);
24092     }
24093     if (vctxt->elemInfos == NULL) {
24094         vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24095             xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
24096         if (vctxt->elemInfos == NULL) {
24097             xmlSchemaVErrMemory(vctxt,
24098                 "allocating the element info array", NULL);
24099             return (NULL);
24100         }
24101         memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
24102         vctxt->sizeElemInfos = 10;
24103     } else if (vctxt->sizeElemInfos <= vctxt->depth) {
24104         int i = vctxt->sizeElemInfos;
24105
24106         vctxt->sizeElemInfos *= 2;
24107         vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24108             xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
24109             sizeof(xmlSchemaNodeInfoPtr));
24110         if (vctxt->elemInfos == NULL) {
24111             xmlSchemaVErrMemory(vctxt,
24112                 "re-allocating the element info array", NULL);
24113             return (NULL);
24114         }
24115         /*
24116         * We need the new memory to be NULLed.
24117         * TODO: Use memset instead?
24118         */
24119         for (; i < vctxt->sizeElemInfos; i++)
24120             vctxt->elemInfos[i] = NULL;
24121     } else
24122         info = vctxt->elemInfos[vctxt->depth];
24123
24124     if (info == NULL) {
24125         info = (xmlSchemaNodeInfoPtr)
24126             xmlMalloc(sizeof(xmlSchemaNodeInfo));
24127         if (info == NULL) {
24128             xmlSchemaVErrMemory(vctxt,
24129                 "allocating an element info", NULL);
24130             return (NULL);
24131         }
24132         vctxt->elemInfos[vctxt->depth] = info;
24133     } else {
24134         if (info->localName != NULL) {
24135             VERROR_INT("xmlSchemaGetFreshElemInfo",
24136                 "elem info has not been cleared");
24137             return (NULL);
24138         }
24139     }
24140     memset(info, 0, sizeof(xmlSchemaNodeInfo));
24141     info->nodeType = XML_ELEMENT_NODE;
24142     info->depth = vctxt->depth;
24143
24144     return (info);
24145 }
24146
24147 #define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
24148 #define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
24149 #define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
24150
24151 static int
24152 xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
24153                         xmlNodePtr node,
24154                         xmlSchemaTypePtr type,
24155                         xmlSchemaValType valType,
24156                         const xmlChar * value,
24157                         xmlSchemaValPtr val,
24158                         unsigned long length,
24159                         int fireErrors)
24160 {
24161     int ret, error = 0;
24162
24163     xmlSchemaTypePtr tmpType;
24164     xmlSchemaFacetLinkPtr facetLink;
24165     xmlSchemaFacetPtr facet;
24166     unsigned long len = 0;
24167     xmlSchemaWhitespaceValueType ws;
24168
24169     /*
24170     * In Libxml2, derived built-in types have currently no explicit facets.
24171     */
24172     if (type->type == XML_SCHEMA_TYPE_BASIC)
24173         return (0);
24174
24175     /*
24176     * NOTE: Do not jump away, if the facetSet of the given type is
24177     * empty: until now, "pattern" and "enumeration" facets of the
24178     * *base types* need to be checked as well.
24179     */
24180     if (type->facetSet == NULL)
24181         goto pattern_and_enum;
24182
24183     if (! WXS_IS_ATOMIC(type)) {
24184         if (WXS_IS_LIST(type))
24185             goto WXS_IS_LIST;
24186         else
24187             goto pattern_and_enum;
24188     }
24189     /*
24190     * Whitespace handling is only of importance for string-based
24191     * types.
24192     */
24193     tmpType = xmlSchemaGetPrimitiveType(type);
24194     if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
24195         WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
24196         ws = xmlSchemaGetWhiteSpaceFacetValue(type);
24197     } else
24198         ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
24199     /*
24200     * If the value was not computed (for string or
24201     * anySimpleType based types), then use the provided
24202     * type.
24203     */
24204     if (val == NULL)
24205         valType = valType;
24206     else
24207         valType = xmlSchemaGetValType(val);
24208
24209     ret = 0;
24210     for (facetLink = type->facetSet; facetLink != NULL;
24211         facetLink = facetLink->next) {
24212         /*
24213         * Skip the pattern "whiteSpace": it is used to
24214         * format the character content beforehand.
24215         */
24216         switch (facetLink->facet->type) {
24217             case XML_SCHEMA_FACET_WHITESPACE:
24218             case XML_SCHEMA_FACET_PATTERN:
24219             case XML_SCHEMA_FACET_ENUMERATION:
24220                 continue;
24221             case XML_SCHEMA_FACET_LENGTH:
24222             case XML_SCHEMA_FACET_MINLENGTH:
24223             case XML_SCHEMA_FACET_MAXLENGTH:
24224                 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
24225                     valType, value, val, &len, ws);
24226                 break;
24227             default:
24228                 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
24229                     valType, value, val, ws);
24230                 break;
24231         }
24232         if (ret < 0) {
24233             AERROR_INT("xmlSchemaValidateFacets",
24234                 "validating against a atomic type facet");
24235             return (-1);
24236         } else if (ret > 0) {
24237             if (fireErrors)
24238                 xmlSchemaFacetErr(actxt, ret, node,
24239                 value, len, type, facetLink->facet, NULL, NULL, NULL);
24240             else
24241                 return (ret);
24242             if (error == 0)
24243                 error = ret;
24244         }
24245         ret = 0;
24246     }
24247
24248 WXS_IS_LIST:
24249     if (! WXS_IS_LIST(type))
24250         goto pattern_and_enum;
24251     /*
24252     * "length", "minLength" and "maxLength" of list types.
24253     */
24254     ret = 0;
24255     for (facetLink = type->facetSet; facetLink != NULL;
24256         facetLink = facetLink->next) {
24257
24258         switch (facetLink->facet->type) {
24259             case XML_SCHEMA_FACET_LENGTH:
24260             case XML_SCHEMA_FACET_MINLENGTH:
24261             case XML_SCHEMA_FACET_MAXLENGTH:
24262                 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
24263                     value, length, NULL);
24264                 break;
24265             default:
24266                 continue;
24267         }
24268         if (ret < 0) {
24269             AERROR_INT("xmlSchemaValidateFacets",
24270                 "validating against a list type facet");
24271             return (-1);
24272         } else if (ret > 0) {
24273             if (fireErrors)
24274                 xmlSchemaFacetErr(actxt, ret, node,
24275                 value, length, type, facetLink->facet, NULL, NULL, NULL);
24276             else
24277                 return (ret);
24278             if (error == 0)
24279                 error = ret;
24280         }
24281         ret = 0;
24282     }
24283
24284 pattern_and_enum:
24285     if (error >= 0) {
24286         int found = 0;
24287         /*
24288         * Process enumerations. Facet values are in the value space
24289         * of the defining type's base type. This seems to be a bug in the
24290         * XML Schema 1.0 spec. Use the whitespace type of the base type.
24291         * Only the first set of enumerations in the ancestor-or-self axis
24292         * is used for validation.
24293         */
24294         ret = 0;
24295         tmpType = type;
24296         do {
24297             for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
24298                 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
24299                     continue;
24300                 found = 1;
24301                 ret = xmlSchemaAreValuesEqual(facet->val, val);
24302                 if (ret == 1)
24303                     break;
24304                 else if (ret < 0) {
24305                     AERROR_INT("xmlSchemaValidateFacets",
24306                         "validating against an enumeration facet");
24307                     return (-1);
24308                 }
24309             }
24310             if (ret != 0)
24311                 break;
24312             /*
24313             * Break on the first set of enumerations. Any additional
24314             *  enumerations which might be existent on the ancestors
24315             *  of the current type are restricted by this set; thus
24316             *  *must* *not* be taken into account.
24317             */
24318             if (found)
24319                 break;
24320             tmpType = tmpType->baseType;
24321         } while ((tmpType != NULL) &&
24322             (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24323         if (found && (ret == 0)) {
24324             ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
24325             if (fireErrors) {
24326                 xmlSchemaFacetErr(actxt, ret, node,
24327                     value, 0, type, NULL, NULL, NULL, NULL);
24328             } else
24329                 return (ret);
24330             if (error == 0)
24331                 error = ret;
24332         }
24333     }
24334
24335     if (error >= 0) {
24336         int found;
24337         /*
24338         * Process patters. Pattern facets are ORed at type level
24339         * and ANDed if derived. Walk the base type axis.
24340         */
24341         tmpType = type;
24342         facet = NULL;
24343         do {
24344             found = 0;
24345             for (facetLink = tmpType->facetSet; facetLink != NULL;
24346                 facetLink = facetLink->next) {
24347                 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
24348                     continue;
24349                 found = 1;
24350                 /*
24351                 * NOTE that for patterns, @value needs to be the
24352                 * normalized vaule.
24353                 */
24354                 ret = xmlRegexpExec(facetLink->facet->regexp, value);
24355                 if (ret == 1)
24356                     break;
24357                 else if (ret < 0) {
24358                     AERROR_INT("xmlSchemaValidateFacets",
24359                         "validating against a pattern facet");
24360                     return (-1);
24361                 } else {
24362                     /*
24363                     * Save the last non-validating facet.
24364                     */
24365                     facet = facetLink->facet;
24366                 }
24367             }
24368             if (found && (ret != 1)) {
24369                 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
24370                 if (fireErrors) {
24371                     xmlSchemaFacetErr(actxt, ret, node,
24372                         value, 0, type, facet, NULL, NULL, NULL);
24373                 } else
24374                     return (ret);
24375                 if (error == 0)
24376                     error = ret;
24377                 break;
24378             }
24379             tmpType = tmpType->baseType;
24380         } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24381     }
24382
24383     return (error);
24384 }
24385
24386 static xmlChar *
24387 xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24388                         const xmlChar *value)
24389 {
24390     switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
24391         case XML_SCHEMA_WHITESPACE_COLLAPSE:
24392             return (xmlSchemaCollapseString(value));
24393         case XML_SCHEMA_WHITESPACE_REPLACE:
24394             return (xmlSchemaWhiteSpaceReplace(value));
24395         default:
24396             return (NULL);
24397     }
24398 }
24399
24400 static int
24401 xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24402                        const xmlChar *value,
24403                        xmlSchemaValPtr *val,
24404                        int valNeeded)
24405 {
24406     int ret;
24407     const xmlChar *nsName;
24408     xmlChar *local, *prefix = NULL;
24409
24410     ret = xmlValidateQName(value, 1);
24411     if (ret != 0) {
24412         if (ret == -1) {
24413             VERROR_INT("xmlSchemaValidateQName",
24414                 "calling xmlValidateQName()");
24415             return (-1);
24416         }
24417         return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24418     }
24419     /*
24420     * NOTE: xmlSplitQName2 will always return a duplicated
24421     * strings.
24422     */
24423     local = xmlSplitQName2(value, &prefix);
24424     if (local == NULL)
24425         local = xmlStrdup(value);
24426     /*
24427     * OPTIMIZE TODO: Use flags for:
24428     *  - is there any namespace binding?
24429     *  - is there a default namespace?
24430     */
24431     nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24432
24433     if (prefix != NULL) {
24434         xmlFree(prefix);
24435         /*
24436         * A namespace must be found if the prefix is
24437         * NOT NULL.
24438         */
24439         if (nsName == NULL) {
24440             ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24441             xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
24442                 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24443                 "The QName value '%s' has no "
24444                 "corresponding namespace declaration in "
24445                 "scope", value, NULL);
24446             if (local != NULL)
24447                 xmlFree(local);
24448             return (ret);
24449         }
24450     }
24451     if (valNeeded && val) {
24452         if (nsName != NULL)
24453             *val = xmlSchemaNewQNameValue(
24454                 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24455         else
24456             *val = xmlSchemaNewQNameValue(NULL,
24457                 BAD_CAST local);
24458     } else
24459         xmlFree(local);
24460     return (0);
24461 }
24462
24463 /*
24464 * cvc-simple-type
24465 */
24466 static int
24467 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24468                              xmlNodePtr node,
24469                              xmlSchemaTypePtr type,
24470                              const xmlChar *value,
24471                              xmlSchemaValPtr *retVal,
24472                              int fireErrors,
24473                              int normalize,
24474                              int isNormalized)
24475 {
24476     int ret = 0, valNeeded = (retVal) ? 1 : 0;
24477     xmlSchemaValPtr val = NULL;
24478     /* xmlSchemaWhitespaceValueType ws; */
24479     xmlChar *normValue = NULL;
24480
24481 #define NORMALIZE(atype) \
24482     if ((! isNormalized) && \
24483     (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24484         normValue = xmlSchemaNormalizeValue(atype, value); \
24485         if (normValue != NULL) \
24486             value = normValue; \
24487         isNormalized = 1; \
24488     }
24489
24490     if ((retVal != NULL) && (*retVal != NULL)) {
24491         xmlSchemaFreeValue(*retVal);
24492         *retVal = NULL;
24493     }
24494     /*
24495     * 3.14.4 Simple Type Definition Validation Rules
24496     * Validation Rule: String Valid
24497     */
24498     /*
24499     * 1 It is schema-valid with respect to that definition as defined
24500     * by Datatype Valid in [XML Schemas: Datatypes].
24501     */
24502     /*
24503     * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24504     * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6), then
24505     * the string must be a `declared entity name`.
24506     */
24507     /*
24508     * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24509     * given the empty set, as defined in Type Derivation OK (Simple) ($3.14.6),
24510     * then every whitespace-delimited substring of the string must be a `declared
24511     * entity name`.
24512     */
24513     /*
24514     * 2.3 otherwise no further condition applies.
24515     */
24516     if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24517         valNeeded = 1;
24518     if (value == NULL)
24519         value = BAD_CAST "";
24520     if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
24521         xmlSchemaTypePtr biType; /* The built-in type. */
24522         /*
24523         * SPEC (1.2.1) "if {variety} is `atomic` then the string must `match`
24524         * a literal in the `lexical space` of {base type definition}"
24525         */
24526         /*
24527         * Whitespace-normalize.
24528         */
24529         NORMALIZE(type);
24530         if (type->type != XML_SCHEMA_TYPE_BASIC) {
24531             /*
24532             * Get the built-in type.
24533             */
24534             biType = type->baseType;
24535             while ((biType != NULL) &&
24536                 (biType->type != XML_SCHEMA_TYPE_BASIC))
24537                 biType = biType->baseType;
24538
24539             if (biType == NULL) {
24540                 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24541                     "could not get the built-in type");
24542                 goto internal_error;
24543             }
24544         } else
24545             biType = type;
24546         /*
24547         * NOTATIONs need to be processed here, since they need
24548         * to lookup in the hashtable of NOTATION declarations of the schema.
24549         */
24550         if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24551             switch (biType->builtInType) {
24552                 case XML_SCHEMAS_NOTATION:
24553                     ret = xmlSchemaValidateNotation(
24554                         (xmlSchemaValidCtxtPtr) actxt,
24555                         ((xmlSchemaValidCtxtPtr) actxt)->schema,
24556                         NULL, value, &val, valNeeded);
24557                     break;
24558                 case XML_SCHEMAS_QNAME:
24559                     ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24560                         value, &val, valNeeded);
24561                     break;
24562                 default:
24563                     /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24564                     if (valNeeded)
24565                         ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24566                             value, &val, node);
24567                     else
24568                         ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24569                             value, NULL, node);
24570                     break;
24571             }
24572         } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24573             switch (biType->builtInType) {
24574                 case XML_SCHEMAS_NOTATION:
24575                     ret = xmlSchemaValidateNotation(NULL,
24576                         ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24577                         value, &val, valNeeded);
24578                     break;
24579                 default:
24580                     /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24581                     if (valNeeded)
24582                         ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24583                             value, &val, node);
24584                     else
24585                         ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24586                             value, NULL, node);
24587                     break;
24588             }
24589         } else {
24590             /*
24591             * Validation via a public API is not implemented yet.
24592             */
24593             TODO
24594             goto internal_error;
24595         }
24596         if (ret != 0) {
24597             if (ret < 0) {
24598                 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24599                     "validating against a built-in type");
24600                 goto internal_error;
24601             }
24602             if (WXS_IS_LIST(type))
24603                 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24604             else
24605                 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24606         }
24607         if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24608             /*
24609             * Check facets.
24610             */
24611             ret = xmlSchemaValidateFacets(actxt, node, type,
24612                 (xmlSchemaValType) biType->builtInType, value, val,
24613                 0, fireErrors);
24614             if (ret != 0) {
24615                 if (ret < 0) {
24616                     AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24617                         "validating facets of atomic simple type");
24618                     goto internal_error;
24619                 }
24620                 if (WXS_IS_LIST(type))
24621                     ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24622                 else
24623                     ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24624             }
24625         }
24626         if (fireErrors && (ret > 0))
24627             xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24628     } else if (WXS_IS_LIST(type)) {
24629
24630         xmlSchemaTypePtr itemType;
24631         const xmlChar *cur, *end;
24632         xmlChar *tmpValue = NULL;
24633         unsigned long len = 0;
24634         xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24635         /* 1.2.2 if {variety} is `list` then the string must be a sequence
24636         * of white space separated tokens, each of which `match`es a literal
24637         * in the `lexical space` of {item type definition}
24638         */
24639         /*
24640         * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24641         * the list type has an enum or pattern facet.
24642         */
24643         NORMALIZE(type);
24644         /*
24645         * VAL TODO: Optimize validation of empty values.
24646         * VAL TODO: We do not have computed values for lists.
24647         */
24648         itemType = WXS_LIST_ITEMTYPE(type);
24649         cur = value;
24650         do {
24651             while (IS_BLANK_CH(*cur))
24652                 cur++;
24653             end = cur;
24654             while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24655                 end++;
24656             if (end == cur)
24657                 break;
24658             tmpValue = xmlStrndup(cur, end - cur);
24659             len++;
24660
24661             if (valNeeded)
24662                 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24663                     tmpValue, &curVal, fireErrors, 0, 1);
24664             else
24665                 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24666                     tmpValue, NULL, fireErrors, 0, 1);
24667             FREE_AND_NULL(tmpValue);
24668             if (curVal != NULL) {
24669                 /*
24670                 * Add to list of computed values.
24671                 */
24672                 if (val == NULL)
24673                     val = curVal;
24674                 else
24675                     xmlSchemaValueAppend(prevVal, curVal);
24676                 prevVal = curVal;
24677                 curVal = NULL;
24678             }
24679             if (ret != 0) {
24680                 if (ret < 0) {
24681                     AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24682                         "validating an item of list simple type");
24683                     goto internal_error;
24684                 }
24685                 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24686                 break;
24687             }
24688             cur = end;
24689         } while (*cur != 0);
24690         FREE_AND_NULL(tmpValue);
24691         if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24692             /*
24693             * Apply facets (pattern, enumeration).
24694             */
24695             ret = xmlSchemaValidateFacets(actxt, node, type,
24696                 XML_SCHEMAS_UNKNOWN, value, val,
24697                 len, fireErrors);
24698             if (ret != 0) {
24699                 if (ret < 0) {
24700                     AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24701                         "validating facets of list simple type");
24702                     goto internal_error;
24703                 }
24704                 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24705             }
24706         }
24707         if (fireErrors && (ret > 0)) {
24708             /*
24709             * Report the normalized value.
24710             */
24711             normalize = 1;
24712             NORMALIZE(type);
24713             xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24714         }
24715     } else if (WXS_IS_UNION(type)) {
24716         xmlSchemaTypeLinkPtr memberLink;
24717         /*
24718         * TODO: For all datatypes `derived` by `union`  whiteSpace does
24719         * not apply directly; however, the normalization behavior of `union`
24720         * types is controlled by the value of whiteSpace on that one of the
24721         * `memberTypes` against which the `union` is successfully validated.
24722         *
24723         * This means that the value is normalized by the first validating
24724         * member type, then the facets of the union type are applied. This
24725         * needs changing of the value!
24726         */
24727
24728         /*
24729         * 1.2.3 if {variety} is `union` then the string must `match` a
24730         * literal in the `lexical space` of at least one member of
24731         * {member type definitions}
24732         */
24733         memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24734         if (memberLink == NULL) {
24735             AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24736                 "union simple type has no member types");
24737             goto internal_error;
24738         }
24739         /*
24740         * Always normalize union type values, since we currently
24741         * cannot store the whitespace information with the value
24742         * itself; otherwise a later value-comparison would be
24743         * not possible.
24744         */
24745         while (memberLink != NULL) {
24746             if (valNeeded)
24747                 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24748                     memberLink->type, value, &val, 0, 1, 0);
24749             else
24750                 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24751                     memberLink->type, value, NULL, 0, 1, 0);
24752             if (ret <= 0)
24753                 break;
24754             memberLink = memberLink->next;
24755         }
24756         if (ret != 0) {
24757             if (ret < 0) {
24758                 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24759                     "validating members of union simple type");
24760                 goto internal_error;
24761             }
24762             ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24763         }
24764         /*
24765         * Apply facets (pattern, enumeration).
24766         */
24767         if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24768             /*
24769             * The normalization behavior of `union` types is controlled by
24770             * the value of whiteSpace on that one of the `memberTypes`
24771             * against which the `union` is successfully validated.
24772             */
24773             NORMALIZE(memberLink->type);
24774             ret = xmlSchemaValidateFacets(actxt, node, type,
24775                 XML_SCHEMAS_UNKNOWN, value, val,
24776                 0, fireErrors);
24777             if (ret != 0) {
24778                 if (ret < 0) {
24779                     AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24780                         "validating facets of union simple type");
24781                     goto internal_error;
24782                 }
24783                 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24784             }
24785         }
24786         if (fireErrors && (ret > 0))
24787             xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24788     }
24789
24790     if (normValue != NULL)
24791         xmlFree(normValue);
24792     if (ret == 0) {
24793         if (retVal != NULL)
24794             *retVal = val;
24795         else if (val != NULL)
24796             xmlSchemaFreeValue(val);
24797     } else if (val != NULL)
24798         xmlSchemaFreeValue(val);
24799     return (ret);
24800 internal_error:
24801     if (normValue != NULL)
24802         xmlFree(normValue);
24803     if (val != NULL)
24804         xmlSchemaFreeValue(val);
24805     return (-1);
24806 }
24807
24808 static int
24809 xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24810                            const xmlChar *value,
24811                            const xmlChar **nsName,
24812                            const xmlChar **localName)
24813 {
24814     int ret = 0;
24815
24816     if ((nsName == NULL) || (localName == NULL))
24817         return (-1);
24818     *nsName = NULL;
24819     *localName = NULL;
24820
24821     ret = xmlValidateQName(value, 1);
24822     if (ret == -1)
24823         return (-1);
24824     if (ret > 0) {
24825         xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
24826             XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24827             value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24828         return (1);
24829     }
24830     {
24831         xmlChar *local = NULL;
24832         xmlChar *prefix;
24833
24834         /*
24835         * NOTE: xmlSplitQName2 will return a duplicated
24836         * string.
24837         */
24838         local = xmlSplitQName2(value, &prefix);
24839         if (local == NULL)
24840             *localName = xmlDictLookup(vctxt->dict, value, -1);
24841         else {
24842             *localName = xmlDictLookup(vctxt->dict, local, -1);
24843             xmlFree(local);
24844         }
24845
24846         *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24847
24848         if (prefix != NULL) {
24849             xmlFree(prefix);
24850             /*
24851             * A namespace must be found if the prefix is NOT NULL.
24852             */
24853             if (*nsName == NULL) {
24854                 xmlSchemaCustomErr(ACTXT_CAST vctxt,
24855                     XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24856                     WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24857                     "The QName value '%s' has no "
24858                     "corresponding namespace declaration in scope",
24859                     value, NULL);
24860                 return (2);
24861             }
24862         }
24863     }
24864     return (0);
24865 }
24866
24867 static int
24868 xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24869                         xmlSchemaAttrInfoPtr iattr,
24870                         xmlSchemaTypePtr *localType,
24871                         xmlSchemaElementPtr elemDecl)
24872 {
24873     int ret = 0;
24874     /*
24875     * cvc-elt (3.3.4) : (4)
24876     * AND
24877     * Schema-Validity Assessment (Element) (cvc-assess-elt)
24878     *   (1.2.1.2.1) - (1.2.1.2.4)
24879     * Handle 'xsi:type'.
24880     */
24881     if (localType == NULL)
24882         return (-1);
24883     *localType = NULL;
24884     if (iattr == NULL)
24885         return (0);
24886     else {
24887         const xmlChar *nsName = NULL, *local = NULL;
24888         /*
24889         * TODO: We should report a *warning* that the type was overriden
24890         * by the instance.
24891         */
24892         ACTIVATE_ATTRIBUTE(iattr);
24893         /*
24894         * (cvc-elt) (3.3.4) : (4.1)
24895         * (cvc-assess-elt) (1.2.1.2.2)
24896         */
24897         ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24898             &nsName, &local);
24899         if (ret != 0) {
24900             if (ret < 0) {
24901                 VERROR_INT("xmlSchemaValidateElementByDeclaration",
24902                     "calling xmlSchemaQNameExpand() to validate the "
24903                     "attribute 'xsi:type'");
24904                 goto internal_error;
24905             }
24906             goto exit;
24907         }
24908         /*
24909         * (cvc-elt) (3.3.4) : (4.2)
24910         * (cvc-assess-elt) (1.2.1.2.3)
24911         */
24912         *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24913         if (*localType == NULL) {
24914             xmlChar *str = NULL;
24915
24916             xmlSchemaCustomErr(ACTXT_CAST vctxt,
24917                 XML_SCHEMAV_CVC_ELT_4_2, NULL,
24918                 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24919                 "The QName value '%s' of the xsi:type attribute does not "
24920                 "resolve to a type definition",
24921                 xmlSchemaFormatQName(&str, nsName, local), NULL);
24922             FREE_AND_NULL(str);
24923             ret = vctxt->err;
24924             goto exit;
24925         }
24926         if (elemDecl != NULL) {
24927             int set = 0;
24928
24929             /*
24930             * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
24931             * "The `local type definition` must be validly
24932             * derived from the {type definition} given the union of
24933             * the {disallowed substitutions} and the {type definition}'s
24934             * {prohibited substitutions}, as defined in
24935             * Type Derivation OK (Complex) ($3.4.6)
24936             * (if it is a complex type definition),
24937             * or given {disallowed substitutions} as defined in Type
24938             * Derivation OK (Simple) ($3.14.6) (if it is a simple type
24939             * definition)."
24940             *
24941             * {disallowed substitutions}: the "block" on the element decl.
24942             * {prohibited substitutions}: the "block" on the type def.
24943             */
24944             /*
24945             * OPTIMIZE TODO: We could map types already evaluated
24946             * to be validly derived from other types to avoid checking
24947             * this over and over for the same types.
24948             */
24949             if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24950                 (elemDecl->subtypes->flags &
24951                     XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24952                 set |= SUBSET_EXTENSION;
24953
24954             if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24955                 (elemDecl->subtypes->flags &
24956                     XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24957                 set |= SUBSET_RESTRICTION;
24958
24959             /*
24960             * REMOVED and CHANGED since this produced a parser context
24961             * which adds to the string dict of the schema. So this would
24962             * change the schema and we don't want this. We don't need
24963             * the parser context anymore.
24964             *
24965             * if ((vctxt->pctxt == NULL) &&
24966             *   (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24967             *       return (-1);
24968             */
24969
24970             if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
24971                 elemDecl->subtypes, set) != 0) {
24972                 xmlChar *str = NULL;
24973
24974                 xmlSchemaCustomErr(ACTXT_CAST vctxt,
24975                     XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24976                     "The type definition '%s', specified by xsi:type, is "
24977                     "blocked or not validly derived from the type definition "
24978                     "of the element declaration",
24979                     xmlSchemaFormatQName(&str,
24980                         (*localType)->targetNamespace,
24981                         (*localType)->name),
24982                     NULL);
24983                 FREE_AND_NULL(str);
24984                 ret = vctxt->err;
24985                 *localType = NULL;
24986             }
24987         }
24988     }
24989 exit:
24990     ACTIVATE_ELEM;
24991     return (ret);
24992 internal_error:
24993     ACTIVATE_ELEM;
24994     return (-1);
24995 }
24996
24997 static int
24998 xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
24999 {
25000     xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
25001     xmlSchemaTypePtr actualType;
25002
25003     /*
25004     * cvc-elt (3.3.4) : 1
25005     */
25006     if (elemDecl == NULL) {
25007         VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
25008             "No matching declaration available");
25009         return (vctxt->err);
25010     }
25011     actualType = WXS_ELEM_TYPEDEF(elemDecl);
25012     /*
25013     * cvc-elt (3.3.4) : 2
25014     */
25015     if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
25016         VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
25017             "The element declaration is abstract");
25018         return (vctxt->err);
25019     }
25020     if (actualType == NULL) {
25021         VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25022             "The type definition is absent");
25023         return (XML_SCHEMAV_CVC_TYPE_1);
25024     }
25025     if (vctxt->nbAttrInfos != 0) {
25026         int ret;
25027         xmlSchemaAttrInfoPtr iattr;
25028         /*
25029         * cvc-elt (3.3.4) : 3
25030         * Handle 'xsi:nil'.
25031         */
25032         iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25033             XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
25034         if (iattr) {
25035             ACTIVATE_ATTRIBUTE(iattr);
25036             /*
25037             * Validate the value.
25038             */
25039             ret = xmlSchemaVCheckCVCSimpleType(
25040                 ACTXT_CAST vctxt, NULL,
25041                 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
25042                 iattr->value, &(iattr->val), 1, 0, 0);
25043             ACTIVATE_ELEM;
25044             if (ret < 0) {
25045                 VERROR_INT("xmlSchemaValidateElemDecl",
25046                     "calling xmlSchemaVCheckCVCSimpleType() to "
25047                     "validate the attribute 'xsi:nil'");
25048                 return (-1);
25049             }
25050             if (ret == 0) {
25051                 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
25052                     /*
25053                     * cvc-elt (3.3.4) : 3.1
25054                     */
25055                     VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
25056                         "The element is not 'nillable'");
25057                     /* Does not return an error on purpose. */
25058                 } else {
25059                     if (xmlSchemaValueGetAsBoolean(iattr->val)) {
25060                         /*
25061                         * cvc-elt (3.3.4) : 3.2.2
25062                         */
25063                         if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
25064                             (elemDecl->value != NULL)) {
25065                             VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
25066                                 "The element cannot be 'nilled' because "
25067                                 "there is a fixed value constraint defined "
25068                                 "for it");
25069                              /* Does not return an error on purpose. */
25070                         } else
25071                             vctxt->inode->flags |=
25072                                 XML_SCHEMA_ELEM_INFO_NILLED;
25073                     }
25074                 }
25075             }
25076         }
25077         /*
25078         * cvc-elt (3.3.4) : 4
25079         * Handle 'xsi:type'.
25080         */
25081         iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25082             XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25083         if (iattr) {
25084             xmlSchemaTypePtr localType = NULL;
25085
25086             ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
25087                 elemDecl);
25088             if (ret != 0) {
25089                 if (ret == -1) {
25090                     VERROR_INT("xmlSchemaValidateElemDecl",
25091                         "calling xmlSchemaProcessXSIType() to "
25092                         "process the attribute 'xsi:type'");
25093                     return (-1);
25094                 }
25095                 /* Does not return an error on purpose. */
25096             }
25097             if (localType != NULL) {
25098                 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
25099                 actualType = localType;
25100             }
25101         }
25102     }
25103     /*
25104     * IDC: Register identity-constraint XPath matchers.
25105     */
25106     if ((elemDecl->idcs != NULL) &&
25107         (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
25108             return (-1);
25109     /*
25110     * No actual type definition.
25111     */
25112     if (actualType == NULL) {
25113         VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25114             "The type definition is absent");
25115         return (XML_SCHEMAV_CVC_TYPE_1);
25116     }
25117     /*
25118     * Remember the actual type definition.
25119     */
25120     vctxt->inode->typeDef = actualType;
25121
25122     return (0);
25123 }
25124
25125 static int
25126 xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
25127 {
25128     xmlSchemaAttrInfoPtr iattr;
25129     int ret = 0, i;
25130
25131     /*
25132     * SPEC cvc-type (3.1.1)
25133     * "The attributes of must be empty, excepting those whose namespace
25134     * name is identical to http://www.w3.org/2001/XMLSchema-instance and
25135     * whose local name is one of type, nil, schemaLocation or
25136     * noNamespaceSchemaLocation."
25137     */
25138     if (vctxt->nbAttrInfos == 0)
25139         return (0);
25140     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25141         iattr = vctxt->attrInfos[i];
25142         if (! iattr->metaType) {
25143             ACTIVATE_ATTRIBUTE(iattr)
25144             xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25145                 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
25146             ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
25147         }
25148     }
25149     ACTIVATE_ELEM
25150     return (ret);
25151 }
25152
25153 /*
25154 * Cleanup currently used attribute infos.
25155 */
25156 static void
25157 xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
25158 {
25159     int i;
25160     xmlSchemaAttrInfoPtr attr;
25161
25162     if (vctxt->nbAttrInfos == 0)
25163         return;
25164     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25165         attr = vctxt->attrInfos[i];
25166         if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
25167             if (attr->localName != NULL)
25168                 xmlFree((xmlChar *) attr->localName);
25169             if (attr->nsName != NULL)
25170                 xmlFree((xmlChar *) attr->nsName);
25171         }
25172         if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
25173             if (attr->value != NULL)
25174                 xmlFree((xmlChar *) attr->value);
25175         }
25176         if (attr->val != NULL) {
25177             xmlSchemaFreeValue(attr->val);
25178             attr->val = NULL;
25179         }
25180         memset(attr, 0, sizeof(xmlSchemaAttrInfo));
25181     }
25182     vctxt->nbAttrInfos = 0;
25183 }
25184
25185 /*
25186 * 3.4.4 Complex Type Definition Validation Rules
25187 *   Element Locally Valid (Complex Type) (cvc-complex-type)
25188 * 3.2.4 Attribute Declaration Validation Rules
25189 *   Validation Rule: Attribute Locally Valid (cvc-attribute)
25190 *   Attribute Locally Valid (Use) (cvc-au)
25191 *
25192 * Only "assessed" attribute information items will be visible to
25193 * IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
25194 */
25195 static int
25196 xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
25197 {
25198     xmlSchemaTypePtr type = vctxt->inode->typeDef;
25199     xmlSchemaItemListPtr attrUseList;
25200     xmlSchemaAttributeUsePtr attrUse = NULL;
25201     xmlSchemaAttributePtr attrDecl = NULL;
25202     xmlSchemaAttrInfoPtr iattr, tmpiattr;
25203     int i, j, found, nbAttrs, nbUses;
25204     int xpathRes = 0, res, wildIDs = 0, fixed;
25205     xmlNodePtr defAttrOwnerElem = NULL;
25206
25207     /*
25208     * SPEC (cvc-attribute)
25209     * (1) "The declaration must not be `absent` (see Missing
25210     * Sub-components ($5.3) for how this can fail to be
25211     * the case)."
25212     * (2) "Its {type definition} must not be absent."
25213     *
25214     * NOTE (1) + (2): This is not handled here, since we currently do not
25215     * allow validation against schemas which have missing sub-components.
25216     *
25217     * SPEC (cvc-complex-type)
25218     * (3) "For each attribute information item in the element information
25219     * item's [attributes] excepting those whose [namespace name] is
25220     * identical to http://www.w3.org/2001/XMLSchema-instance and whose
25221     * [local name] is one of type, nil, schemaLocation or
25222     * noNamespaceSchemaLocation, the appropriate case among the following
25223     * must be true:
25224     *
25225     */
25226     attrUseList = (xmlSchemaItemListPtr) type->attrUses;
25227     /*
25228     * @nbAttrs is the number of attributes present in the instance.
25229     */
25230     nbAttrs = vctxt->nbAttrInfos;
25231     if (attrUseList != NULL)
25232         nbUses = attrUseList->nbItems;
25233     else
25234         nbUses = 0;
25235     for (i = 0; i < nbUses; i++) {
25236         found = 0;
25237         attrUse = attrUseList->items[i];
25238         attrDecl = WXS_ATTRUSE_DECL(attrUse);
25239         for (j = 0; j < nbAttrs; j++) {
25240             iattr = vctxt->attrInfos[j];
25241             /*
25242             * SPEC (cvc-complex-type) (3)
25243             * Skip meta attributes.
25244             */
25245             if (iattr->metaType)
25246                 continue;
25247             if (iattr->localName[0] != attrDecl->name[0])
25248                 continue;
25249             if (!xmlStrEqual(iattr->localName, attrDecl->name))
25250                 continue;
25251             if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
25252                 continue;
25253             found = 1;
25254             /*
25255             * SPEC (cvc-complex-type)
25256             * (3.1) "If there is among the {attribute uses} an attribute
25257             * use with an {attribute declaration} whose {name} matches
25258             * the attribute information item's [local name] and whose
25259             * {target namespace} is identical to the attribute information
25260             * item's [namespace name] (where an `absent` {target namespace}
25261             * is taken to be identical to a [namespace name] with no value),
25262             * then the attribute information must be `valid` with respect
25263             * to that attribute use as per Attribute Locally Valid (Use)
25264             * ($3.5.4). In this case the {attribute declaration} of that
25265             * attribute use is the `context-determined declaration` for the
25266             * attribute information item with respect to Schema-Validity
25267             * Assessment (Attribute) ($3.2.4) and
25268             * Assessment Outcome (Attribute) ($3.2.5).
25269             */
25270             iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25271             iattr->use = attrUse;
25272             /*
25273             * Context-determined declaration.
25274             */
25275             iattr->decl = attrDecl;
25276             iattr->typeDef = attrDecl->subtypes;
25277             break;
25278         }
25279
25280         if (found)
25281             continue;
25282
25283         if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
25284             /*
25285             * Handle non-existent, required attributes.
25286             *
25287             * SPEC (cvc-complex-type)
25288             * (4) "The {attribute declaration} of each attribute use in
25289             * the {attribute uses} whose {required} is true matches one
25290             * of the attribute information items in the element information
25291             * item's [attributes] as per clause 3.1 above."
25292             */
25293             tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25294             if (tmpiattr == NULL) {
25295                 VERROR_INT(
25296                     "xmlSchemaVAttributesComplex",
25297                     "calling xmlSchemaGetFreshAttrInfo()");
25298                 return (-1);
25299             }
25300             tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
25301             tmpiattr->use = attrUse;
25302             tmpiattr->decl = attrDecl;
25303         } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
25304             ((attrUse->defValue != NULL) ||
25305              (attrDecl->defValue != NULL))) {
25306             /*
25307             * Handle non-existent, optional, default/fixed attributes.
25308             */
25309             tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25310             if (tmpiattr == NULL) {
25311                 VERROR_INT(
25312                     "xmlSchemaVAttributesComplex",
25313                     "calling xmlSchemaGetFreshAttrInfo()");
25314                 return (-1);
25315             }
25316             tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
25317             tmpiattr->use = attrUse;
25318             tmpiattr->decl = attrDecl;
25319             tmpiattr->typeDef = attrDecl->subtypes;
25320             tmpiattr->localName = attrDecl->name;
25321             tmpiattr->nsName = attrDecl->targetNamespace;
25322         }
25323     }
25324
25325     if (vctxt->nbAttrInfos == 0)
25326         return (0);
25327     /*
25328     * Validate against the wildcard.
25329     */
25330     if (type->attributeWildcard != NULL) {
25331         /*
25332         * SPEC (cvc-complex-type)
25333         * (3.2.1) "There must be an {attribute wildcard}."
25334         */
25335         for (i = 0; i < nbAttrs; i++) {
25336             iattr = vctxt->attrInfos[i];
25337             /*
25338             * SPEC (cvc-complex-type) (3)
25339             * Skip meta attributes.
25340             */
25341             if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
25342                 continue;
25343             /*
25344             * SPEC (cvc-complex-type)
25345             * (3.2.2) "The attribute information item must be `valid` with
25346             * respect to it as defined in Item Valid (Wildcard) ($3.10.4)."
25347             *
25348             * SPEC Item Valid (Wildcard) (cvc-wildcard)
25349             * "... its [namespace name] must be `valid` with respect to
25350             * the wildcard constraint, as defined in Wildcard allows
25351             * Namespace Name ($3.10.4)."
25352             */
25353             if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
25354                     iattr->nsName) == 0) {
25355                 /*
25356                 * Handle processContents.
25357                 *
25358                 * SPEC (cvc-wildcard):
25359                 * processContents | context-determined declaration:
25360                 * "strict"          "mustFind"
25361                 * "lax"             "none"
25362                 * "skip"            "skip"
25363                 */
25364                 if (type->attributeWildcard->processContents ==
25365                     XML_SCHEMAS_ANY_SKIP) {
25366                      /*
25367                     * context-determined declaration = "skip"
25368                     *
25369                     * SPEC PSVI Assessment Outcome (Attribute)
25370                     * [validity] = "notKnown"
25371                     * [validation attempted] = "none"
25372                     */
25373                     iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
25374                     continue;
25375                 }
25376                 /*
25377                 * Find an attribute declaration.
25378                 */
25379                 iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25380                     iattr->localName, iattr->nsName);
25381                 if (iattr->decl != NULL) {
25382                     iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25383                     /*
25384                     * SPEC (cvc-complex-type)
25385                     * (5) "Let [Definition:]  the wild IDs be the set of
25386                     * all attribute information item to which clause 3.2
25387                     * applied and whose `validation` resulted in a
25388                     * `context-determined declaration` of mustFind or no
25389                     * `context-determined declaration` at all, and whose
25390                     * [local name] and [namespace name] resolve (as
25391                     * defined by QName resolution (Instance) ($3.15.4)) to
25392                     * an attribute declaration whose {type definition} is
25393                     * or is derived from ID. Then all of the following
25394                     * must be true:"
25395                     */
25396                     iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
25397                     if (xmlSchemaIsDerivedFromBuiltInType(
25398                         iattr->typeDef, XML_SCHEMAS_ID)) {
25399                         /*
25400                         * SPEC (5.1) "There must be no more than one
25401                         * item in `wild IDs`."
25402                         */
25403                         if (wildIDs != 0) {
25404                             /* VAL TODO */
25405                             iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
25406                             TODO
25407                             continue;
25408                         }
25409                         wildIDs++;
25410                         /*
25411                         * SPEC (cvc-complex-type)
25412                         * (5.2) "If `wild IDs` is non-empty, there must not
25413                         * be any attribute uses among the {attribute uses}
25414                         * whose {attribute declaration}'s {type definition}
25415                         * is or is derived from ID."
25416                         */
25417                         if (attrUseList != NULL) {
25418                             for (j = 0; j < attrUseList->nbItems; j++) {
25419                                 if (xmlSchemaIsDerivedFromBuiltInType(
25420                                     WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25421                                     XML_SCHEMAS_ID)) {
25422                                     /* URGENT VAL TODO: implement */
25423                             iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25424                                     TODO
25425                                     break;
25426                                 }
25427                             }
25428                         }
25429                     }
25430                 } else if (type->attributeWildcard->processContents ==
25431                     XML_SCHEMAS_ANY_LAX) {
25432                     iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
25433                     /*
25434                     * SPEC PSVI Assessment Outcome (Attribute)
25435                     * [validity] = "notKnown"
25436                     * [validation attempted] = "none"
25437                     */
25438                 } else {
25439                     iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
25440                 }
25441             }
25442         }
25443     }
25444
25445     if (vctxt->nbAttrInfos == 0)
25446         return (0);
25447
25448     /*
25449     * Get the owner element; needed for creation of default attributes.
25450     * This fixes bug #341337, reported by David Grohmann.
25451     */
25452     if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25453         xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25454         if (ielem && ielem->node && ielem->node->doc)
25455             defAttrOwnerElem = ielem->node;
25456     }
25457     /*
25458     * Validate values, create default attributes, evaluate IDCs.
25459     */
25460     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25461         iattr = vctxt->attrInfos[i];
25462         /*
25463         * VAL TODO: Note that we won't try to resolve IDCs to
25464         * "lax" and "skip" validated attributes. Check what to
25465         * do in this case.
25466         */
25467         if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25468             (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
25469             continue;
25470         /*
25471         * VAL TODO: What to do if the type definition is missing?
25472         */
25473         if (iattr->typeDef == NULL) {
25474             iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
25475             continue;
25476         }
25477
25478         ACTIVATE_ATTRIBUTE(iattr);
25479         fixed = 0;
25480         xpathRes = 0;
25481
25482         if (vctxt->xpathStates != NULL) {
25483             /*
25484             * Evaluate IDCs.
25485             */
25486             xpathRes = xmlSchemaXPathEvaluate(vctxt,
25487                 XML_ATTRIBUTE_NODE);
25488             if (xpathRes == -1) {
25489                 VERROR_INT("xmlSchemaVAttributesComplex",
25490                     "calling xmlSchemaXPathEvaluate()");
25491                 goto internal_error;
25492             }
25493         }
25494
25495         if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
25496             /*
25497             * Default/fixed attributes.
25498             * We need the value only if we need to resolve IDCs or
25499             * will create default attributes.
25500             */
25501             if ((xpathRes) || (defAttrOwnerElem)) {
25502                 if (iattr->use->defValue != NULL) {
25503                     iattr->value = (xmlChar *) iattr->use->defValue;
25504                     iattr->val = iattr->use->defVal;
25505                 } else {
25506                     iattr->value = (xmlChar *) iattr->decl->defValue;
25507                     iattr->val = iattr->decl->defVal;
25508                 }
25509                 /*
25510                 * IDCs will consume the precomputed default value,
25511                 * so we need to clone it.
25512                 */
25513                 if (iattr->val == NULL) {
25514                     VERROR_INT("xmlSchemaVAttributesComplex",
25515                         "default/fixed value on an attribute use was "
25516                         "not precomputed");
25517                     goto internal_error;
25518                 }
25519                 iattr->val = xmlSchemaCopyValue(iattr->val);
25520                 if (iattr->val == NULL) {
25521                     VERROR_INT("xmlSchemaVAttributesComplex",
25522                         "calling xmlSchemaCopyValue()");
25523                     goto internal_error;
25524                 }
25525             }
25526             /*
25527             * PSVI: Add the default attribute to the current element.
25528             * VAL TODO: Should we use the *normalized* value? This currently
25529             *   uses the *initial* value.
25530             */
25531
25532             if (defAttrOwnerElem) {
25533                 xmlChar *normValue;
25534                 const xmlChar *value;
25535
25536                 value = iattr->value;
25537                 /*
25538                 * Normalize the value.
25539                 */
25540                 normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25541                     iattr->value);
25542                 if (normValue != NULL)
25543                     value = BAD_CAST normValue;
25544
25545                 if (iattr->nsName == NULL) {
25546                     if (xmlNewProp(defAttrOwnerElem,
25547                         iattr->localName, value) == NULL) {
25548                         VERROR_INT("xmlSchemaVAttributesComplex",
25549                             "callling xmlNewProp()");
25550                         if (normValue != NULL)
25551                             xmlFree(normValue);
25552                         goto internal_error;
25553                     }
25554                 } else {
25555                     xmlNsPtr ns;
25556
25557                     ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25558                         defAttrOwnerElem, iattr->nsName);
25559                     if (ns == NULL) {
25560                         xmlChar prefix[12];
25561                         int counter = 0;
25562
25563                         /*
25564                         * Create a namespace declaration on the validation
25565                         * root node if no namespace declaration is in scope.
25566                         */
25567                         do {
25568                             snprintf((char *) prefix, 12, "p%d", counter++);
25569                             ns = xmlSearchNs(defAttrOwnerElem->doc,
25570                                 defAttrOwnerElem, BAD_CAST prefix);
25571                             if (counter > 1000) {
25572                                 VERROR_INT(
25573                                     "xmlSchemaVAttributesComplex",
25574                                     "could not compute a ns prefix for a "
25575                                     "default/fixed attribute");
25576                                 if (normValue != NULL)
25577                                     xmlFree(normValue);
25578                                 goto internal_error;
25579                             }
25580                         } while (ns != NULL);
25581                         ns = xmlNewNs(vctxt->validationRoot,
25582                             iattr->nsName, BAD_CAST prefix);
25583                     }
25584                     /*
25585                     * TODO:
25586                     * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25587                     * If we have QNames: do we need to ensure there's a
25588                     * prefix defined for the QName?
25589                     */
25590                     xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
25591                 }
25592                 if (normValue != NULL)
25593                     xmlFree(normValue);
25594             }
25595             /*
25596             * Go directly to IDC evaluation.
25597             */
25598             goto eval_idcs;
25599         }
25600         /*
25601         * Validate the value.
25602         */
25603         if (vctxt->value != NULL) {
25604             /*
25605             * Free last computed value; just for safety reasons.
25606             */
25607             xmlSchemaFreeValue(vctxt->value);
25608             vctxt->value = NULL;
25609         }
25610         /*
25611         * Note that the attribute *use* can be unavailable, if
25612         * the attribute was a wild attribute.
25613         */
25614         if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25615             ((iattr->use != NULL) &&
25616              (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
25617             fixed = 1;
25618         else
25619             fixed = 0;
25620         /*
25621         * SPEC (cvc-attribute)
25622         * (3) "The item's `normalized value` must be locally `valid`
25623         * with respect to that {type definition} as per
25624         * String Valid ($3.14.4)."
25625         *
25626         * VAL TODO: Do we already have the
25627         * "normalized attribute value" here?
25628         */
25629         if (xpathRes || fixed) {
25630             iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
25631             /*
25632             * Request a computed value.
25633             */
25634             res = xmlSchemaVCheckCVCSimpleType(
25635                 ACTXT_CAST vctxt,
25636                 iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
25637                 1, 1, 0);
25638         } else {
25639             res = xmlSchemaVCheckCVCSimpleType(
25640                 ACTXT_CAST vctxt,
25641                 iattr->node, iattr->typeDef, iattr->value, NULL,
25642                 1, 0, 0);
25643         }
25644
25645         if (res != 0) {
25646             if (res == -1) {
25647                 VERROR_INT("xmlSchemaVAttributesComplex",
25648                     "calling xmlSchemaStreamValidateSimpleTypeValue()");
25649                 goto internal_error;
25650             }
25651             iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
25652             /*
25653             * SPEC PSVI Assessment Outcome (Attribute)
25654             * [validity] = "invalid"
25655             */
25656             goto eval_idcs;
25657         }
25658
25659         if (fixed) {
25660             /*
25661             * SPEC Attribute Locally Valid (Use) (cvc-au)
25662             * "For an attribute information item to be `valid`
25663             * with respect to an attribute use its *normalized*
25664             * value must match the *canonical* lexical
25665             * representation of the attribute use's {value
25666             * constraint}value, if it is present and fixed."
25667             *
25668             * VAL TODO: The requirement for the *canonical* value
25669             * will be removed in XML Schema 1.1.
25670             */
25671             /*
25672             * SPEC Attribute Locally Valid (cvc-attribute)
25673             * (4) "The item's *actual* value must match the *value* of
25674             * the {value constraint}, if it is present and fixed."
25675             */
25676             if (iattr->val == NULL) {
25677                 /* VAL TODO: A value was not precomputed. */
25678                 TODO
25679                 goto eval_idcs;
25680             }
25681             if ((iattr->use != NULL) &&
25682                 (iattr->use->defValue != NULL)) {
25683                 if (iattr->use->defVal == NULL) {
25684                     /* VAL TODO: A default value was not precomputed. */
25685                     TODO
25686                     goto eval_idcs;
25687                 }
25688                 iattr->vcValue = iattr->use->defValue;
25689                 /*
25690                 if (xmlSchemaCompareValuesWhtsp(attr->val,
25691                     (xmlSchemaWhitespaceValueType) ws,
25692                     attr->use->defVal,
25693                     (xmlSchemaWhitespaceValueType) ws) != 0) {
25694                 */
25695                 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25696                     iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25697             } else {
25698                 if (iattr->decl->defVal == NULL) {
25699                     /* VAL TODO: A default value was not precomputed. */
25700                     TODO
25701                     goto eval_idcs;
25702                 }
25703                 iattr->vcValue = iattr->decl->defValue;
25704                 /*
25705                 if (xmlSchemaCompareValuesWhtsp(attr->val,
25706                     (xmlSchemaWhitespaceValueType) ws,
25707                     attrDecl->defVal,
25708                     (xmlSchemaWhitespaceValueType) ws) != 0) {
25709                 */
25710                 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25711                     iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25712             }
25713             /*
25714             * [validity] = "valid"
25715             */
25716         }
25717 eval_idcs:
25718         /*
25719         * Evaluate IDCs.
25720         */
25721         if (xpathRes) {
25722             if (xmlSchemaXPathProcessHistory(vctxt,
25723                 vctxt->depth +1) == -1) {
25724                 VERROR_INT("xmlSchemaVAttributesComplex",
25725                     "calling xmlSchemaXPathEvaluate()");
25726                 goto internal_error;
25727             }
25728         } else if (vctxt->xpathStates != NULL)
25729             xmlSchemaXPathPop(vctxt);
25730     }
25731
25732     /*
25733     * Report errors.
25734     */
25735     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25736         iattr = vctxt->attrInfos[i];
25737         if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25738             (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25739             (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25740             (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
25741             continue;
25742         ACTIVATE_ATTRIBUTE(iattr);
25743         switch (iattr->state) {
25744             case XML_SCHEMAS_ATTR_ERR_MISSING: {
25745                     xmlChar *str = NULL;
25746                     ACTIVATE_ELEM;
25747                     xmlSchemaCustomErr(ACTXT_CAST vctxt,
25748                         XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25749                         "The attribute '%s' is required but missing",
25750                         xmlSchemaFormatQName(&str,
25751                             iattr->decl->targetNamespace,
25752                             iattr->decl->name),
25753                         NULL);
25754                     FREE_AND_NULL(str)
25755                     break;
25756                 }
25757             case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25758                 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25759                     "The type definition is absent");
25760                 break;
25761             case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
25762                 xmlSchemaCustomErr(ACTXT_CAST vctxt,
25763                     XML_SCHEMAV_CVC_AU, NULL, NULL,
25764                     "The value '%s' does not match the fixed "
25765                     "value constraint '%s'",
25766                     iattr->value, iattr->vcValue);
25767                 break;
25768             case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25769                 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25770                     "No matching global attribute declaration available, but "
25771                     "demanded by the strict wildcard");
25772                 break;
25773             case XML_SCHEMAS_ATTR_UNKNOWN:
25774                 if (iattr->metaType)
25775                     break;
25776                 /*
25777                 * MAYBE VAL TODO: One might report different error messages
25778                 * for the following errors.
25779                 */
25780                 if (type->attributeWildcard == NULL) {
25781                     xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25782                         XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
25783                 } else {
25784                     xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25785                         XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
25786                 }
25787                 break;
25788             default:
25789                 break;
25790         }
25791     }
25792
25793     ACTIVATE_ELEM;
25794     return (0);
25795 internal_error:
25796     ACTIVATE_ELEM;
25797     return (-1);
25798 }
25799
25800 static int
25801 xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25802                               int *skip)
25803 {
25804     xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25805     /*
25806     * The namespace of the element was already identified to be
25807     * matching the wildcard.
25808     */
25809     if ((skip == NULL) || (wild == NULL) ||
25810         (wild->type != XML_SCHEMA_TYPE_ANY)) {
25811         VERROR_INT("xmlSchemaValidateElemWildcard",
25812             "bad arguments");
25813         return (-1);
25814     }
25815     *skip = 0;
25816     if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25817         /*
25818         * URGENT VAL TODO: Either we need to position the stream to the
25819         * next sibling, or walk the whole subtree.
25820         */
25821         *skip = 1;
25822         return (0);
25823     }
25824     {
25825         xmlSchemaElementPtr decl = NULL;
25826
25827         decl = xmlSchemaGetElem(vctxt->schema,
25828             vctxt->inode->localName, vctxt->inode->nsName);
25829         if (decl != NULL) {
25830             vctxt->inode->decl = decl;
25831             return (0);
25832         }
25833     }
25834     if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25835         /* VAL TODO: Change to proper error code. */
25836         VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
25837             "No matching global element declaration available, but "
25838             "demanded by the strict wildcard");
25839         return (vctxt->err);
25840     }
25841     if (vctxt->nbAttrInfos != 0) {
25842         xmlSchemaAttrInfoPtr iattr;
25843         /*
25844         * SPEC Validation Rule: Schema-Validity Assessment (Element)
25845         * (1.2.1.2.1) - (1.2.1.2.3 )
25846         *
25847         * Use the xsi:type attribute for the type definition.
25848         */
25849         iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25850             XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25851         if (iattr != NULL) {
25852             if (xmlSchemaProcessXSIType(vctxt, iattr,
25853                 &(vctxt->inode->typeDef), NULL) == -1) {
25854                 VERROR_INT("xmlSchemaValidateElemWildcard",
25855                     "calling xmlSchemaProcessXSIType() to "
25856                     "process the attribute 'xsi:nil'");
25857                 return (-1);
25858             }
25859             /*
25860             * Don't return an error on purpose.
25861             */
25862             return (0);
25863         }
25864     }
25865     /*
25866     * SPEC Validation Rule: Schema-Validity Assessment (Element)
25867     *
25868     * Fallback to "anyType".
25869     */
25870     vctxt->inode->typeDef =
25871         xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25872     return (0);
25873 }
25874
25875 /*
25876 * xmlSchemaCheckCOSValidDefault:
25877 *
25878 * This will be called if: not nilled, no content and a default/fixed
25879 * value is provided.
25880 */
25881
25882 static int
25883 xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25884                               const xmlChar *value,
25885                               xmlSchemaValPtr *val)
25886 {
25887     int ret = 0;
25888     xmlSchemaNodeInfoPtr inode = vctxt->inode;
25889
25890     /*
25891     * cos-valid-default:
25892     * Schema Component Constraint: Element Default Valid (Immediate)
25893     * For a string to be a valid default with respect to a type
25894     * definition the appropriate case among the following must be true:
25895     */
25896     if WXS_IS_COMPLEX(inode->typeDef) {
25897         /*
25898         * Complex type.
25899         *
25900         * SPEC (2.1) "its {content type} must be a simple type definition
25901         * or mixed."
25902         * SPEC (2.2.2) "If the {content type} is mixed, then the {content
25903         * type}'s particle must be `emptiable` as defined by
25904         * Particle Emptiable ($3.9.6)."
25905         */
25906         if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25907             ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25908              (! WXS_EMPTIABLE(inode->typeDef)))) {
25909             ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25910             /* NOTE that this covers (2.2.2) as well. */
25911             VERROR(ret, NULL,
25912                 "For a string to be a valid default, the type definition "
25913                 "must be a simple type or a complex type with simple content "
25914                 "or mixed content and a particle emptiable");
25915             return(ret);
25916         }
25917     }
25918     /*
25919     * 1 If the type definition is a simple type definition, then the string
25920     * must be `valid` with respect to that definition as defined by String
25921     * Valid ($3.14.4).
25922     *
25923     * AND
25924     *
25925     * 2.2.1 If the {content type} is a simple type definition, then the
25926     * string must be `valid` with respect to that simple type definition
25927     * as defined by String Valid ($3.14.4).
25928     */
25929     if (WXS_IS_SIMPLE(inode->typeDef)) {
25930
25931         ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25932             NULL, inode->typeDef, value, val, 1, 1, 0);
25933
25934     } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
25935
25936         ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25937             NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25938     }
25939     if (ret < 0) {
25940         VERROR_INT("xmlSchemaCheckCOSValidDefault",
25941             "calling xmlSchemaVCheckCVCSimpleType()");
25942     }
25943     return (ret);
25944 }
25945
25946 static void
25947 xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
25948                                const xmlChar * name ATTRIBUTE_UNUSED,
25949                                xmlSchemaElementPtr item,
25950                                xmlSchemaNodeInfoPtr inode)
25951 {
25952     inode->decl = item;
25953 #ifdef DEBUG_CONTENT
25954     {
25955         xmlChar *str = NULL;
25956
25957         if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
25958             xmlGenericError(xmlGenericErrorContext,
25959                 "AUTOMATON callback for '%s' [declaration]\n",
25960                 xmlSchemaFormatQName(&str,
25961                 inode->localName, inode->nsName));
25962         } else {
25963             xmlGenericError(xmlGenericErrorContext,
25964                     "AUTOMATON callback for '%s' [wildcard]\n",
25965                     xmlSchemaFormatQName(&str,
25966                     inode->localName, inode->nsName));
25967
25968         }
25969         FREE_AND_NULL(str)
25970     }
25971 #endif
25972 }
25973
25974 static int
25975 xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
25976 {
25977     vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25978     if (vctxt->inode == NULL) {
25979         VERROR_INT("xmlSchemaValidatorPushElem",
25980             "calling xmlSchemaGetFreshElemInfo()");
25981         return (-1);
25982     }
25983     vctxt->nbAttrInfos = 0;
25984     return (0);
25985 }
25986
25987 static int
25988 xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
25989                              xmlSchemaNodeInfoPtr inode,
25990                              xmlSchemaTypePtr type,
25991                              const xmlChar *value)
25992 {
25993     if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
25994         return (xmlSchemaVCheckCVCSimpleType(
25995             ACTXT_CAST vctxt, NULL,
25996             type, value, &(inode->val), 1, 1, 0));
25997     else
25998         return (xmlSchemaVCheckCVCSimpleType(
25999             ACTXT_CAST vctxt, NULL,
26000             type, value, NULL, 1, 0, 0));
26001 }
26002
26003
26004
26005 /*
26006 * Process END of element.
26007 */
26008 static int
26009 xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
26010 {
26011     int ret = 0;
26012     xmlSchemaNodeInfoPtr inode = vctxt->inode;
26013
26014     if (vctxt->nbAttrInfos != 0)
26015         xmlSchemaClearAttrInfos(vctxt);
26016     if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
26017         /*
26018         * This element was not expected;
26019         * we will not validate child elements of broken parents.
26020         * Skip validation of all content of the parent.
26021         */
26022         vctxt->skipDepth = vctxt->depth -1;
26023         goto end_elem;
26024     }
26025     if ((inode->typeDef == NULL) ||
26026         (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
26027         /*
26028         * 1. the type definition might be missing if the element was
26029         *    error prone
26030         * 2. it might be abstract.
26031         */
26032         goto end_elem;
26033     }
26034     /*
26035     * Check the content model.
26036     */
26037     if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
26038         (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
26039
26040         /*
26041         * Workaround for "anyType".
26042         */
26043         if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
26044             goto character_content;
26045
26046         if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
26047             xmlChar *values[10];
26048             int terminal, nbval = 10, nbneg;
26049
26050             if (inode->regexCtxt == NULL) {
26051                 /*
26052                 * Create the regex context.
26053                 */
26054                 inode->regexCtxt =
26055                     xmlRegNewExecCtxt(inode->typeDef->contModel,
26056                     (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26057                     vctxt);
26058                 if (inode->regexCtxt == NULL) {
26059                     VERROR_INT("xmlSchemaValidatorPopElem",
26060                         "failed to create a regex context");
26061                     goto internal_error;
26062                 }
26063 #ifdef DEBUG_AUTOMATA
26064                 xmlGenericError(xmlGenericErrorContext,
26065                     "AUTOMATON create on '%s'\n", inode->localName);
26066 #endif
26067             }
26068
26069             /*
26070              * Do not check further content if the node has been nilled
26071              */
26072             if (INODE_NILLED(inode)) {
26073                 ret = 0;
26074 #ifdef DEBUG_AUTOMATA
26075                 xmlGenericError(xmlGenericErrorContext,
26076                     "AUTOMATON succeeded on nilled '%s'\n",
26077                     inode->localName);
26078 #endif
26079                 goto skip_nilled;
26080             }
26081
26082             /*
26083             * Get hold of the still expected content, since a further
26084             * call to xmlRegExecPushString() will loose this information.
26085             */
26086             xmlRegExecNextValues(inode->regexCtxt,
26087                 &nbval, &nbneg, &values[0], &terminal);
26088             ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
26089             if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) {
26090                 /*
26091                 * Still missing something.
26092                 */
26093                 ret = 1;
26094                 inode->flags |=
26095                     XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26096                 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26097                     XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
26098                     "Missing child element(s)",
26099                     nbval, nbneg, values);
26100 #ifdef DEBUG_AUTOMATA
26101                 xmlGenericError(xmlGenericErrorContext,
26102                     "AUTOMATON missing ERROR on '%s'\n",
26103                     inode->localName);
26104 #endif
26105             } else {
26106                 /*
26107                 * Content model is satisfied.
26108                 */
26109                 ret = 0;
26110 #ifdef DEBUG_AUTOMATA
26111                 xmlGenericError(xmlGenericErrorContext,
26112                     "AUTOMATON succeeded on '%s'\n",
26113                     inode->localName);
26114 #endif
26115             }
26116
26117         }
26118     }
26119
26120 skip_nilled:
26121
26122     if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
26123         goto end_elem;
26124
26125 character_content:
26126
26127     if (vctxt->value != NULL) {
26128         xmlSchemaFreeValue(vctxt->value);
26129         vctxt->value = NULL;
26130     }
26131     /*
26132     * Check character content.
26133     */
26134     if (inode->decl == NULL) {
26135         /*
26136         * Speedup if no declaration exists.
26137         */
26138         if (WXS_IS_SIMPLE(inode->typeDef)) {
26139             ret = xmlSchemaVCheckINodeDataType(vctxt,
26140                 inode, inode->typeDef, inode->value);
26141         } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26142             ret = xmlSchemaVCheckINodeDataType(vctxt,
26143                 inode, inode->typeDef->contentTypeDef,
26144                 inode->value);
26145         }
26146         if (ret < 0) {
26147             VERROR_INT("xmlSchemaValidatorPopElem",
26148                 "calling xmlSchemaVCheckCVCSimpleType()");
26149             goto internal_error;
26150         }
26151         goto end_elem;
26152     }
26153     /*
26154     * cvc-elt (3.3.4) : 5
26155     * The appropriate case among the following must be true:
26156     */
26157     /*
26158     * cvc-elt (3.3.4) : 5.1
26159     * If the declaration has a {value constraint},
26160     * the item has neither element nor character [children] and
26161     * clause 3.2 has not applied, then all of the following must be true:
26162     */
26163     if ((inode->decl->value != NULL) &&
26164         (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
26165         (! INODE_NILLED(inode))) {
26166         /*
26167         * cvc-elt (3.3.4) : 5.1.1
26168         * If the `actual type definition` is a `local type definition`
26169         * then the canonical lexical representation of the {value constraint}
26170         * value must be a valid default for the `actual type definition` as
26171         * defined in Element Default Valid (Immediate) ($3.3.6).
26172         */
26173         /*
26174         * NOTE: 'local' above means types acquired by xsi:type.
26175         * NOTE: Although the *canonical* value is stated, it is not
26176         * relevant if canonical or not. Additionally XML Schema 1.1
26177         * will removed this requirement as well.
26178         */
26179         if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
26180
26181             ret = xmlSchemaCheckCOSValidDefault(vctxt,
26182                 inode->decl->value, &(inode->val));
26183             if (ret != 0) {
26184                 if (ret < 0) {
26185                     VERROR_INT("xmlSchemaValidatorPopElem",
26186                         "calling xmlSchemaCheckCOSValidDefault()");
26187                     goto internal_error;
26188                 }
26189                 goto end_elem;
26190             }
26191             /*
26192             * Stop here, to avoid redundant validation of the value
26193             * (see following).
26194             */
26195             goto default_psvi;
26196         }
26197         /*
26198         * cvc-elt (3.3.4) : 5.1.2
26199         * The element information item with the canonical lexical
26200         * representation of the {value constraint} value used as its
26201         * `normalized value` must be `valid` with respect to the
26202         * `actual type definition` as defined by Element Locally Valid (Type)
26203         * ($3.3.4).
26204         */
26205         if (WXS_IS_SIMPLE(inode->typeDef)) {
26206             ret = xmlSchemaVCheckINodeDataType(vctxt,
26207                 inode, inode->typeDef, inode->decl->value);
26208         } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26209             ret = xmlSchemaVCheckINodeDataType(vctxt,
26210                 inode, inode->typeDef->contentTypeDef,
26211                 inode->decl->value);
26212         }
26213         if (ret != 0) {
26214             if (ret < 0) {
26215                 VERROR_INT("xmlSchemaValidatorPopElem",
26216                     "calling xmlSchemaVCheckCVCSimpleType()");
26217                 goto internal_error;
26218             }
26219             goto end_elem;
26220         }
26221
26222 default_psvi:
26223         /*
26224         * PSVI: Create a text node on the instance element.
26225         */
26226         if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
26227             (inode->node != NULL)) {
26228             xmlNodePtr textChild;
26229             xmlChar *normValue;
26230             /*
26231             * VAL TODO: Normalize the value.
26232             */
26233             normValue = xmlSchemaNormalizeValue(inode->typeDef,
26234                 inode->decl->value);
26235             if (normValue != NULL) {
26236                 textChild = xmlNewText(BAD_CAST normValue);
26237                 xmlFree(normValue);
26238             } else
26239                 textChild = xmlNewText(inode->decl->value);
26240             if (textChild == NULL) {
26241                 VERROR_INT("xmlSchemaValidatorPopElem",
26242                     "calling xmlNewText()");
26243                 goto internal_error;
26244             } else
26245                 xmlAddChild(inode->node, textChild);
26246         }
26247
26248     } else if (! INODE_NILLED(inode)) {
26249         /*
26250         * 5.2.1 The element information item must be `valid` with respect
26251         * to the `actual type definition` as defined by Element Locally
26252         * Valid (Type) ($3.3.4).
26253         */
26254         if (WXS_IS_SIMPLE(inode->typeDef)) {
26255              /*
26256             * SPEC (cvc-type) (3.1)
26257             * "If the type definition is a simple type definition, ..."
26258             * (3.1.3) "If clause 3.2 of Element Locally Valid
26259             * (Element) ($3.3.4) did not apply, then the `normalized value`
26260             * must be `valid` with respect to the type definition as defined
26261             * by String Valid ($3.14.4).
26262             */
26263             ret = xmlSchemaVCheckINodeDataType(vctxt,
26264                     inode, inode->typeDef, inode->value);
26265         } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26266             /*
26267             * SPEC (cvc-type) (3.2) "If the type definition is a complex type
26268             * definition, then the element information item must be
26269             * `valid` with respect to the type definition as per
26270             * Element Locally Valid (Complex Type) ($3.4.4);"
26271             *
26272             * SPEC (cvc-complex-type) (2.2)
26273             * "If the {content type} is a simple type definition, ...
26274             * the `normalized value` of the element information item is
26275             * `valid` with respect to that simple type definition as
26276             * defined by String Valid ($3.14.4)."
26277             */
26278             ret = xmlSchemaVCheckINodeDataType(vctxt,
26279                 inode, inode->typeDef->contentTypeDef, inode->value);
26280         }
26281         if (ret != 0) {
26282             if (ret < 0) {
26283                 VERROR_INT("xmlSchemaValidatorPopElem",
26284                     "calling xmlSchemaVCheckCVCSimpleType()");
26285                 goto internal_error;
26286             }
26287             goto end_elem;
26288         }
26289         /*
26290         * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
26291         * not applied, all of the following must be true:
26292         */
26293         if ((inode->decl->value != NULL) &&
26294             (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
26295
26296             /*
26297             * TODO: We will need a computed value, when comparison is
26298             * done on computed values.
26299             */
26300             /*
26301             * 5.2.2.1 The element information item must have no element
26302             * information item [children].
26303             */
26304             if (inode->flags &
26305                     XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
26306                 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
26307                 VERROR(ret, NULL,
26308                     "The content must not containt element nodes since "
26309                     "there is a fixed value constraint");
26310                 goto end_elem;
26311             } else {
26312                 /*
26313                 * 5.2.2.2 The appropriate case among the following must
26314                 * be true:
26315                 */
26316                 if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
26317                     /*
26318                     * 5.2.2.2.1 If the {content type} of the `actual type
26319                     * definition` is mixed, then the *initial value* of the
26320                     * item must match the canonical lexical representation
26321                     * of the {value constraint} value.
26322                     *
26323                     * ... the *initial value* of an element information
26324                     * item is the string composed of, in order, the
26325                     * [character code] of each character information item in
26326                     * the [children] of that element information item.
26327                     */
26328                     if (! xmlStrEqual(inode->value, inode->decl->value)){
26329                         /*
26330                         * VAL TODO: Report invalid & expected values as well.
26331                         * VAL TODO: Implement the canonical stuff.
26332                         */
26333                         ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
26334                         xmlSchemaCustomErr(ACTXT_CAST vctxt,
26335                             ret, NULL, NULL,
26336                             "The initial value '%s' does not match the fixed "
26337                             "value constraint '%s'",
26338                             inode->value, inode->decl->value);
26339                         goto end_elem;
26340                     }
26341                 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26342                     /*
26343                     * 5.2.2.2.2 If the {content type} of the `actual type
26344                     * definition` is a simple type definition, then the
26345                     * *actual value* of the item must match the canonical
26346                     * lexical representation of the {value constraint} value.
26347                     */
26348                     /*
26349                     * VAL TODO: *actual value* is the normalized value, impl.
26350                     *           this.
26351                     * VAL TODO: Report invalid & expected values as well.
26352                     * VAL TODO: Implement a comparison with the computed values.
26353                     */
26354                     if (! xmlStrEqual(inode->value,
26355                             inode->decl->value)) {
26356                         ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
26357                         xmlSchemaCustomErr(ACTXT_CAST vctxt,
26358                             ret, NULL, NULL,
26359                             "The actual value '%s' does not match the fixed "
26360                             "value constraint '%s'",
26361                             inode->value,
26362                             inode->decl->value);
26363                         goto end_elem;
26364                     }
26365                 }
26366             }
26367         }
26368     }
26369
26370 end_elem:
26371     if (vctxt->depth < 0) {
26372         /* TODO: raise error? */
26373         return (0);
26374     }
26375     if (vctxt->depth == vctxt->skipDepth)
26376         vctxt->skipDepth = -1;
26377     /*
26378     * Evaluate the history of XPath state objects.
26379     */
26380     if (inode->appliedXPath &&
26381         (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
26382         goto internal_error;
26383     /*
26384     * MAYBE TODO:
26385     * SPEC (6) "The element information item must be `valid` with
26386     * respect to each of the {identity-constraint definitions} as per
26387     * Identity-constraint Satisfied ($3.11.4)."
26388     */
26389     /*
26390     * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26391     *   need to be built in any case.
26392     *   We will currently build IDC node-tables and bubble them only if
26393     *   keyrefs do exist.
26394     */
26395
26396     /*
26397     * Add the current IDC target-nodes to the IDC node-tables.
26398     */
26399     if ((inode->idcMatchers != NULL) &&
26400         (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26401     {
26402         if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26403             goto internal_error;
26404     }
26405     /*
26406     * Validate IDC keyrefs.
26407     */
26408     if (vctxt->inode->hasKeyrefs)
26409         if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26410             goto internal_error;
26411     /*
26412     * Merge/free the IDC table.
26413     */
26414     if (inode->idcTable != NULL) {
26415 #ifdef DEBUG_IDC_NODE_TABLE
26416         xmlSchemaDebugDumpIDCTable(stdout,
26417             inode->nsName,
26418             inode->localName,
26419             inode->idcTable);
26420 #endif
26421         if ((vctxt->depth > 0) &&
26422             (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26423         {
26424             /*
26425             * Merge the IDC node table with the table of the parent node.
26426             */
26427             if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26428                 goto internal_error;
26429         }
26430     }
26431     /*
26432     * Clear the current ielem.
26433     * VAL TODO: Don't free the PSVI IDC tables if they are
26434     * requested for the PSVI.
26435     */
26436     xmlSchemaClearElemInfo(vctxt, inode);
26437     /*
26438     * Skip further processing if we are on the validation root.
26439     */
26440     if (vctxt->depth == 0) {
26441         vctxt->depth--;
26442         vctxt->inode = NULL;
26443         return (0);
26444     }
26445     /*
26446     * Reset the keyrefDepth if needed.
26447     */
26448     if (vctxt->aidcs != NULL) {
26449         xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26450         do {
26451             if (aidc->keyrefDepth == vctxt->depth) {
26452                 /*
26453                 * A 'keyrefDepth' of a key/unique IDC matches the current
26454                 * depth, this means that we are leaving the scope of the
26455                 * top-most keyref IDC which refers to this IDC.
26456                 */
26457                 aidc->keyrefDepth = -1;
26458             }
26459             aidc = aidc->next;
26460         } while (aidc != NULL);
26461     }
26462     vctxt->depth--;
26463     vctxt->inode = vctxt->elemInfos[vctxt->depth];
26464     /*
26465     * VAL TODO: 7 If the element information item is the `validation root`, it must be
26466     * `valid` per Validation Root Valid (ID/IDREF) ($3.3.4).
26467     */
26468     return (ret);
26469
26470 internal_error:
26471     vctxt->err = -1;
26472     return (-1);
26473 }
26474
26475 /*
26476 * 3.4.4 Complex Type Definition Validation Rules
26477 * Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26478 */
26479 static int
26480 xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
26481 {
26482     xmlSchemaNodeInfoPtr pielem;
26483     xmlSchemaTypePtr ptype;
26484     int ret = 0;
26485
26486     if (vctxt->depth <= 0) {
26487         VERROR_INT("xmlSchemaValidateChildElem",
26488             "not intended for the validation root");
26489         return (-1);
26490     }
26491     pielem = vctxt->elemInfos[vctxt->depth -1];
26492     if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26493         pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26494     /*
26495     * Handle 'nilled' elements.
26496     */
26497     if (INODE_NILLED(pielem)) {
26498         /*
26499         * SPEC (cvc-elt) (3.3.4) : (3.2.1)
26500         */
26501         ACTIVATE_PARENT_ELEM;
26502         ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26503         VERROR(ret, NULL,
26504             "Neither character nor element content is allowed, "
26505             "because the element was 'nilled'");
26506         ACTIVATE_ELEM;
26507         goto unexpected_elem;
26508     }
26509
26510     ptype = pielem->typeDef;
26511
26512     if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26513         /*
26514         * Workaround for "anyType": we have currently no content model
26515         * assigned for "anyType", so handle it explicitely.
26516         * "anyType" has an unbounded, lax "any" wildcard.
26517         */
26518         vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26519             vctxt->inode->localName,
26520             vctxt->inode->nsName);
26521
26522         if (vctxt->inode->decl == NULL) {
26523             xmlSchemaAttrInfoPtr iattr;
26524             /*
26525             * Process "xsi:type".
26526             * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
26527             */
26528             iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26529                 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26530             if (iattr != NULL) {
26531                 ret = xmlSchemaProcessXSIType(vctxt, iattr,
26532                     &(vctxt->inode->typeDef), NULL);
26533                 if (ret != 0) {
26534                     if (ret == -1) {
26535                         VERROR_INT("xmlSchemaValidateChildElem",
26536                             "calling xmlSchemaProcessXSIType() to "
26537                             "process the attribute 'xsi:nil'");
26538                         return (-1);
26539                     }
26540                     return (ret);
26541                 }
26542             } else {
26543                  /*
26544                  * Fallback to "anyType".
26545                  *
26546                  * SPEC (cvc-assess-elt)
26547                  * "If the item cannot be `strictly assessed`, [...]
26548                  * an element information item's schema validity may be laxly
26549                  * assessed if its `context-determined declaration` is not
26550                  * skip by `validating` with respect to the `ur-type
26551                  * definition` as per Element Locally Valid (Type) ($3.3.4)."
26552                 */
26553                 vctxt->inode->typeDef =
26554                     xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26555             }
26556         }
26557         return (0);
26558     }
26559
26560     switch (ptype->contentType) {
26561         case XML_SCHEMA_CONTENT_EMPTY:
26562             /*
26563             * SPEC (2.1) "If the {content type} is empty, then the
26564             * element information item has no character or element
26565             * information item [children]."
26566             */
26567             ACTIVATE_PARENT_ELEM
26568             ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26569             VERROR(ret, NULL,
26570                 "Element content is not allowed, "
26571                 "because the content type is empty");
26572             ACTIVATE_ELEM
26573             goto unexpected_elem;
26574             break;
26575
26576         case XML_SCHEMA_CONTENT_MIXED:
26577         case XML_SCHEMA_CONTENT_ELEMENTS: {
26578             xmlRegExecCtxtPtr regexCtxt;
26579             xmlChar *values[10];
26580             int terminal, nbval = 10, nbneg;
26581
26582             /* VAL TODO: Optimized "anyType" validation.*/
26583
26584             if (ptype->contModel == NULL) {
26585                 VERROR_INT("xmlSchemaValidateChildElem",
26586                     "type has elem content but no content model");
26587                 return (-1);
26588             }
26589             /*
26590             * Safety belf for evaluation if the cont. model was already
26591             * examined to be invalid.
26592             */
26593             if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26594                 VERROR_INT("xmlSchemaValidateChildElem",
26595                     "validating elem, but elem content is already invalid");
26596                 return (-1);
26597             }
26598
26599             regexCtxt = pielem->regexCtxt;
26600             if (regexCtxt == NULL) {
26601                 /*
26602                 * Create the regex context.
26603                 */
26604                 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26605                     (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26606                     vctxt);
26607                 if (regexCtxt == NULL) {
26608                     VERROR_INT("xmlSchemaValidateChildElem",
26609                         "failed to create a regex context");
26610                     return (-1);
26611                 }
26612                 pielem->regexCtxt = regexCtxt;
26613 #ifdef DEBUG_AUTOMATA
26614                 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26615                     pielem->localName);
26616 #endif
26617             }
26618
26619             /*
26620             * SPEC (2.4) "If the {content type} is element-only or mixed,
26621             * then the sequence of the element information item's
26622             * element information item [children], if any, taken in
26623             * order, is `valid` with respect to the {content type}'s
26624             * particle, as defined in Element Sequence Locally Valid
26625             * (Particle) ($3.9.4)."
26626             */
26627             ret = xmlRegExecPushString2(regexCtxt,
26628                 vctxt->inode->localName,
26629                 vctxt->inode->nsName,
26630                 vctxt->inode);
26631 #ifdef DEBUG_AUTOMATA
26632             if (ret < 0)
26633                 xmlGenericError(xmlGenericErrorContext,
26634                 "AUTOMATON push ERROR for '%s' on '%s'\n",
26635                 vctxt->inode->localName, pielem->localName);
26636             else
26637                 xmlGenericError(xmlGenericErrorContext,
26638                 "AUTOMATON push OK for '%s' on '%s'\n",
26639                 vctxt->inode->localName, pielem->localName);
26640 #endif
26641             if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26642                 VERROR_INT("xmlSchemaValidateChildElem",
26643                     "calling xmlRegExecPushString2()");
26644                 return (-1);
26645             }
26646             if (ret < 0) {
26647                 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26648                     &values[0], &terminal);
26649                 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26650                     XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26651                     "This element is not expected",
26652                     nbval, nbneg, values);
26653                 ret = vctxt->err;
26654                 goto unexpected_elem;
26655             } else
26656                 ret = 0;
26657         }
26658             break;
26659         case XML_SCHEMA_CONTENT_SIMPLE:
26660         case XML_SCHEMA_CONTENT_BASIC:
26661             ACTIVATE_PARENT_ELEM
26662             if (WXS_IS_COMPLEX(ptype)) {
26663                 /*
26664                 * SPEC (cvc-complex-type) (2.2)
26665                 * "If the {content type} is a simple type definition, then
26666                 * the element information item has no element information
26667                 * item [children], ..."
26668                 */
26669                 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26670                 VERROR(ret, NULL, "Element content is not allowed, "
26671                     "because the content type is a simple type definition");
26672             } else {
26673                 /*
26674                 * SPEC (cvc-type) (3.1.2) "The element information item must
26675                 * have no element information item [children]."
26676                 */
26677                 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26678                 VERROR(ret, NULL, "Element content is not allowed, "
26679                     "because the type definition is simple");
26680             }
26681             ACTIVATE_ELEM
26682             ret = vctxt->err;
26683             goto unexpected_elem;
26684             break;
26685
26686         default:
26687             break;
26688     }
26689     return (ret);
26690 unexpected_elem:
26691     /*
26692     * Pop this element and set the skipDepth to skip
26693     * all further content of the parent element.
26694     */
26695     vctxt->skipDepth = vctxt->depth;
26696     vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26697     pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26698     return (ret);
26699 }
26700
26701 #define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26702 #define XML_SCHEMA_PUSH_TEXT_CREATED 2
26703 #define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26704
26705 static int
26706 xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26707                   int nodeType, const xmlChar *value, int len,
26708                   int mode, int *consumed)
26709 {
26710     /*
26711     * Unfortunately we have to duplicate the text sometimes.
26712     * OPTIMIZE: Maybe we could skip it, if:
26713     *   1. content type is simple
26714     *   2. whitespace is "collapse"
26715     *   3. it consists of whitespace only
26716     *
26717     * Process character content.
26718     */
26719     if (consumed != NULL)
26720         *consumed = 0;
26721     if (INODE_NILLED(vctxt->inode)) {
26722         /*
26723         * SPEC cvc-elt (3.3.4 - 3.2.1)
26724         * "The element information item must have no character or
26725         * element information item [children]."
26726         */
26727         VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26728             "Neither character nor element content is allowed "
26729             "because the element is 'nilled'");
26730         return (vctxt->err);
26731     }
26732     /*
26733     * SPEC (2.1) "If the {content type} is empty, then the
26734     * element information item has no character or element
26735     * information item [children]."
26736     */
26737     if (vctxt->inode->typeDef->contentType ==
26738             XML_SCHEMA_CONTENT_EMPTY) {
26739         VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26740             "Character content is not allowed, "
26741             "because the content type is empty");
26742         return (vctxt->err);
26743     }
26744
26745     if (vctxt->inode->typeDef->contentType ==
26746             XML_SCHEMA_CONTENT_ELEMENTS) {
26747         if ((nodeType != XML_TEXT_NODE) ||
26748             (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26749             /*
26750             * SPEC cvc-complex-type (2.3)
26751             * "If the {content type} is element-only, then the
26752             * element information item has no character information
26753             * item [children] other than those whose [character
26754             * code] is defined as a white space in [XML 1.0 (Second
26755             * Edition)]."
26756             */
26757             VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26758                 "Character content other than whitespace is not allowed "
26759                 "because the content type is 'element-only'");
26760             return (vctxt->err);
26761         }
26762         return (0);
26763     }
26764
26765     if ((value == NULL) || (value[0] == 0))
26766         return (0);
26767     /*
26768     * Save the value.
26769     * NOTE that even if the content type is *mixed*, we need the
26770     * *initial value* for default/fixed value constraints.
26771     */
26772     if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26773         ((vctxt->inode->decl == NULL) ||
26774         (vctxt->inode->decl->value == NULL)))
26775         return (0);
26776
26777     if (vctxt->inode->value == NULL) {
26778         /*
26779         * Set the value.
26780         */
26781         switch (mode) {
26782             case XML_SCHEMA_PUSH_TEXT_PERSIST:
26783                 /*
26784                 * When working on a tree.
26785                 */
26786                 vctxt->inode->value = value;
26787                 break;
26788             case XML_SCHEMA_PUSH_TEXT_CREATED:
26789                 /*
26790                 * When working with the reader.
26791                 * The value will be freed by the element info.
26792                 */
26793                 vctxt->inode->value = value;
26794                 if (consumed != NULL)
26795                     *consumed = 1;
26796                 vctxt->inode->flags |=
26797                     XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26798                 break;
26799             case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26800                 /*
26801                 * When working with SAX.
26802                 * The value will be freed by the element info.
26803                 */
26804                 if (len != -1)
26805                     vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26806                 else
26807                     vctxt->inode->value = BAD_CAST xmlStrdup(value);
26808                 vctxt->inode->flags |=
26809                     XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26810                 break;
26811             default:
26812                 break;
26813         }
26814     } else {
26815         if (len < 0)
26816             len = xmlStrlen(value);
26817         /*
26818         * Concat the value.
26819         */
26820         if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
26821             vctxt->inode->value = BAD_CAST xmlStrncat(
26822                 (xmlChar *) vctxt->inode->value, value, len);
26823         } else {
26824             vctxt->inode->value =
26825                 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
26826             vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26827         }
26828     }
26829
26830     return (0);
26831 }
26832
26833 static int
26834 xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
26835 {
26836     int ret = 0;
26837
26838     if ((vctxt->skipDepth != -1) &&
26839         (vctxt->depth >= vctxt->skipDepth)) {
26840         VERROR_INT("xmlSchemaValidateElem",
26841             "in skip-state");
26842         goto internal_error;
26843     }
26844     if (vctxt->xsiAssemble) {
26845         /*
26846         * We will stop validation if there was an error during
26847         * dynamic schema construction.
26848         * Note that we simply set @skipDepth to 0, this could
26849         * mean that a streaming document via SAX would be
26850         * still read to the end but it won't be validated any more.
26851         * TODO: If we are sure how to stop the validation at once
26852         *   for all input scenarios, then this should be changed to
26853         *   instantly stop the validation.
26854         */
26855         ret = xmlSchemaAssembleByXSI(vctxt);
26856         if (ret != 0) {
26857             if (ret == -1)
26858                 goto internal_error;
26859             vctxt->skipDepth = 0;
26860             return(ret);
26861         }
26862         /*
26863          * Augment the IDC definitions for the main schema and all imported ones
26864          * NOTE: main schema is the first in the imported list
26865          */
26866         xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt);
26867     }
26868     if (vctxt->depth > 0) {
26869         /*
26870         * Validate this element against the content model
26871         * of the parent.
26872         */
26873         ret = xmlSchemaValidateChildElem(vctxt);
26874         if (ret != 0) {
26875             if (ret < 0) {
26876                 VERROR_INT("xmlSchemaValidateElem",
26877                     "calling xmlSchemaStreamValidateChildElement()");
26878                 goto internal_error;
26879             }
26880             goto exit;
26881         }
26882         if (vctxt->depth == vctxt->skipDepth)
26883             goto exit;
26884         if ((vctxt->inode->decl == NULL) &&
26885             (vctxt->inode->typeDef == NULL)) {
26886             VERROR_INT("xmlSchemaValidateElem",
26887                 "the child element was valid but neither the "
26888                 "declaration nor the type was set");
26889             goto internal_error;
26890         }
26891     } else {
26892         /*
26893         * Get the declaration of the validation root.
26894         */
26895         vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26896             vctxt->inode->localName,
26897             vctxt->inode->nsName);
26898         if (vctxt->inode->decl == NULL) {
26899             ret = XML_SCHEMAV_CVC_ELT_1;
26900             VERROR(ret, NULL,
26901                 "No matching global declaration available "
26902                 "for the validation root");
26903             goto exit;
26904         }
26905     }
26906
26907     if (vctxt->inode->decl == NULL)
26908         goto type_validation;
26909
26910     if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26911         int skip;
26912         /*
26913         * Wildcards.
26914         */
26915         ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26916         if (ret != 0) {
26917             if (ret < 0) {
26918                 VERROR_INT("xmlSchemaValidateElem",
26919                     "calling xmlSchemaValidateElemWildcard()");
26920                 goto internal_error;
26921             }
26922             goto exit;
26923         }
26924         if (skip) {
26925             vctxt->skipDepth = vctxt->depth;
26926             goto exit;
26927         }
26928         /*
26929         * The declaration might be set by the wildcard validation,
26930         * when the processContents is "lax" or "strict".
26931         */
26932         if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26933             /*
26934             * Clear the "decl" field to not confuse further processing.
26935             */
26936             vctxt->inode->decl = NULL;
26937             goto type_validation;
26938         }
26939     }
26940     /*
26941     * Validate against the declaration.
26942     */
26943     ret = xmlSchemaValidateElemDecl(vctxt);
26944     if (ret != 0) {
26945         if (ret < 0) {
26946             VERROR_INT("xmlSchemaValidateElem",
26947                 "calling xmlSchemaValidateElemDecl()");
26948             goto internal_error;
26949         }
26950         goto exit;
26951     }
26952     /*
26953     * Validate against the type definition.
26954     */
26955 type_validation:
26956
26957     if (vctxt->inode->typeDef == NULL) {
26958         vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26959         ret = XML_SCHEMAV_CVC_TYPE_1;
26960         VERROR(ret, NULL,
26961             "The type definition is absent");
26962         goto exit;
26963     }
26964     if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26965         vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26966         ret = XML_SCHEMAV_CVC_TYPE_2;
26967             VERROR(ret, NULL,
26968             "The type definition is abstract");
26969         goto exit;
26970     }
26971     /*
26972     * Evaluate IDCs. Do it here, since new IDC matchers are registered
26973     * during validation against the declaration. This must be done
26974     * _before_ attribute validation.
26975     */
26976     if (vctxt->xpathStates != NULL) {
26977         ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
26978         vctxt->inode->appliedXPath = 1;
26979         if (ret == -1) {
26980             VERROR_INT("xmlSchemaValidateElem",
26981                 "calling xmlSchemaXPathEvaluate()");
26982             goto internal_error;
26983         }
26984     }
26985     /*
26986     * Validate attributes.
26987     */
26988     if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
26989         if ((vctxt->nbAttrInfos != 0) ||
26990             (vctxt->inode->typeDef->attrUses != NULL)) {
26991
26992             ret = xmlSchemaVAttributesComplex(vctxt);
26993         }
26994     } else if (vctxt->nbAttrInfos != 0) {
26995
26996         ret = xmlSchemaVAttributesSimple(vctxt);
26997     }
26998     /*
26999     * Clear registered attributes.
27000     */
27001     if (vctxt->nbAttrInfos != 0)
27002         xmlSchemaClearAttrInfos(vctxt);
27003     if (ret == -1) {
27004         VERROR_INT("xmlSchemaValidateElem",
27005             "calling attributes validation");
27006         goto internal_error;
27007     }
27008     /*
27009     * Don't return an error if attributes are invalid on purpose.
27010     */
27011     ret = 0;
27012
27013 exit:
27014     if (ret != 0)
27015         vctxt->skipDepth = vctxt->depth;
27016     return (ret);
27017 internal_error:
27018     return (-1);
27019 }
27020
27021 #ifdef XML_SCHEMA_READER_ENABLED
27022 static int
27023 xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
27024 {
27025     const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
27026     int depth, nodeType, ret = 0, consumed;
27027     xmlSchemaNodeInfoPtr ielem;
27028
27029     vctxt->depth = -1;
27030     ret = xmlTextReaderRead(vctxt->reader);
27031     /*
27032     * Move to the document element.
27033     */
27034     while (ret == 1) {
27035         nodeType = xmlTextReaderNodeType(vctxt->reader);
27036         if (nodeType == XML_ELEMENT_NODE)
27037             goto root_found;
27038         ret = xmlTextReaderRead(vctxt->reader);
27039     }
27040     goto exit;
27041
27042 root_found:
27043
27044     do {
27045         depth = xmlTextReaderDepth(vctxt->reader);
27046         nodeType = xmlTextReaderNodeType(vctxt->reader);
27047
27048         if (nodeType == XML_ELEMENT_NODE) {
27049
27050             vctxt->depth++;
27051             if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27052                 VERROR_INT("xmlSchemaVReaderWalk",
27053                     "calling xmlSchemaValidatorPushElem()");
27054                 goto internal_error;
27055             }
27056             ielem = vctxt->inode;
27057             ielem->localName = xmlTextReaderLocalName(vctxt->reader);
27058             ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
27059             ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
27060             /*
27061             * Is the element empty?
27062             */
27063             ret = xmlTextReaderIsEmptyElement(vctxt->reader);
27064             if (ret == -1) {
27065                 VERROR_INT("xmlSchemaVReaderWalk",
27066                     "calling xmlTextReaderIsEmptyElement()");
27067                 goto internal_error;
27068             }
27069             if (ret) {
27070                 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27071             }
27072             /*
27073             * Register attributes.
27074             */
27075             vctxt->nbAttrInfos = 0;
27076             ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
27077             if (ret == -1) {
27078                 VERROR_INT("xmlSchemaVReaderWalk",
27079                     "calling xmlTextReaderMoveToFirstAttribute()");
27080                 goto internal_error;
27081             }
27082             if (ret == 1) {
27083                 do {
27084                     /*
27085                     * VAL TODO: How do we know that the reader works on a
27086                     * node tree, to be able to pass a node here?
27087                     */
27088                     if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
27089                         (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
27090                         xmlTextReaderNamespaceUri(vctxt->reader), 1,
27091                         xmlTextReaderValue(vctxt->reader), 1) == -1) {
27092
27093                         VERROR_INT("xmlSchemaVReaderWalk",
27094                             "calling xmlSchemaValidatorPushAttribute()");
27095                         goto internal_error;
27096                     }
27097                     ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
27098                     if (ret == -1) {
27099                         VERROR_INT("xmlSchemaVReaderWalk",
27100                             "calling xmlTextReaderMoveToFirstAttribute()");
27101                         goto internal_error;
27102                     }
27103                 } while (ret == 1);
27104                 /*
27105                 * Back to element position.
27106                 */
27107                 ret = xmlTextReaderMoveToElement(vctxt->reader);
27108                 if (ret == -1) {
27109                     VERROR_INT("xmlSchemaVReaderWalk",
27110                         "calling xmlTextReaderMoveToElement()");
27111                     goto internal_error;
27112                 }
27113             }
27114             /*
27115             * Validate the element.
27116             */
27117             ret= xmlSchemaValidateElem(vctxt);
27118             if (ret != 0) {
27119                 if (ret == -1) {
27120                     VERROR_INT("xmlSchemaVReaderWalk",
27121                         "calling xmlSchemaValidateElem()");
27122                     goto internal_error;
27123                 }
27124                 goto exit;
27125             }
27126             if (vctxt->depth == vctxt->skipDepth) {
27127                 int curDepth;
27128                 /*
27129                 * Skip all content.
27130                 */
27131                 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
27132                     ret = xmlTextReaderRead(vctxt->reader);
27133                     curDepth = xmlTextReaderDepth(vctxt->reader);
27134                     while ((ret == 1) && (curDepth != depth)) {
27135                         ret = xmlTextReaderRead(vctxt->reader);
27136                         curDepth = xmlTextReaderDepth(vctxt->reader);
27137                     }
27138                     if (ret < 0) {
27139                         /*
27140                         * VAL TODO: A reader error occured; what to do here?
27141                         */
27142                         ret = 1;
27143                         goto exit;
27144                     }
27145                 }
27146                 goto leave_elem;
27147             }
27148             /*
27149             * READER VAL TODO: Is an END_ELEM really never called
27150             * if the elem is empty?
27151             */
27152             if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27153                 goto leave_elem;
27154         } else if (nodeType == END_ELEM) {
27155             /*
27156             * Process END of element.
27157             */
27158 leave_elem:
27159             ret = xmlSchemaValidatorPopElem(vctxt);
27160             if (ret != 0) {
27161                 if (ret < 0) {
27162                     VERROR_INT("xmlSchemaVReaderWalk",
27163                         "calling xmlSchemaValidatorPopElem()");
27164                     goto internal_error;
27165                 }
27166                 goto exit;
27167             }
27168             if (vctxt->depth >= 0)
27169                 ielem = vctxt->inode;
27170             else
27171                 ielem = NULL;
27172         } else if ((nodeType == XML_TEXT_NODE) ||
27173             (nodeType == XML_CDATA_SECTION_NODE) ||
27174             (nodeType == WHTSP) ||
27175             (nodeType == SIGN_WHTSP)) {
27176             /*
27177             * Process character content.
27178             */
27179             xmlChar *value;
27180
27181             if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
27182                 nodeType = XML_TEXT_NODE;
27183
27184             value = xmlTextReaderValue(vctxt->reader);
27185             ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
27186                 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
27187             if (! consumed)
27188                 xmlFree(value);
27189             if (ret == -1) {
27190                 VERROR_INT("xmlSchemaVReaderWalk",
27191                     "calling xmlSchemaVPushText()");
27192                 goto internal_error;
27193             }
27194         } else if ((nodeType == XML_ENTITY_NODE) ||
27195             (nodeType == XML_ENTITY_REF_NODE)) {
27196             /*
27197             * VAL TODO: What to do with entities?
27198             */
27199             TODO
27200         }
27201         /*
27202         * Read next node.
27203         */
27204         ret = xmlTextReaderRead(vctxt->reader);
27205     } while (ret == 1);
27206
27207 exit:
27208     return (ret);
27209 internal_error:
27210     return (-1);
27211 }
27212 #endif
27213
27214 /************************************************************************
27215  *                                                                      *
27216  *                      SAX validation handlers                         *
27217  *                                                                      *
27218  ************************************************************************/
27219
27220 /*
27221 * Process text content.
27222 */
27223 static void
27224 xmlSchemaSAXHandleText(void *ctx,
27225                        const xmlChar * ch,
27226                        int len)
27227 {
27228     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27229
27230     if (vctxt->depth < 0)
27231         return;
27232     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27233         return;
27234     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27235         vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27236     if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
27237         XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27238         VERROR_INT("xmlSchemaSAXHandleCDataSection",
27239             "calling xmlSchemaVPushText()");
27240         vctxt->err = -1;
27241         xmlStopParser(vctxt->parserCtxt);
27242     }
27243 }
27244
27245 /*
27246 * Process CDATA content.
27247 */
27248 static void
27249 xmlSchemaSAXHandleCDataSection(void *ctx,
27250                              const xmlChar * ch,
27251                              int len)
27252 {
27253     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27254
27255     if (vctxt->depth < 0)
27256         return;
27257     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27258         return;
27259     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27260         vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27261     if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
27262         XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27263         VERROR_INT("xmlSchemaSAXHandleCDataSection",
27264             "calling xmlSchemaVPushText()");
27265         vctxt->err = -1;
27266         xmlStopParser(vctxt->parserCtxt);
27267     }
27268 }
27269
27270 static void
27271 xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
27272                             const xmlChar * name ATTRIBUTE_UNUSED)
27273 {
27274     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27275
27276     if (vctxt->depth < 0)
27277         return;
27278     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27279         return;
27280     /* SAX VAL TODO: What to do here? */
27281     TODO
27282 }
27283
27284 static void
27285 xmlSchemaSAXHandleStartElementNs(void *ctx,
27286                                  const xmlChar * localname,
27287                                  const xmlChar * prefix ATTRIBUTE_UNUSED,
27288                                  const xmlChar * URI,
27289                                  int nb_namespaces,
27290                                  const xmlChar ** namespaces,
27291                                  int nb_attributes,
27292                                  int nb_defaulted ATTRIBUTE_UNUSED,
27293                                  const xmlChar ** attributes)
27294 {
27295     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27296     int ret;
27297     xmlSchemaNodeInfoPtr ielem;
27298     int i, j;
27299
27300     /*
27301     * SAX VAL TODO: What to do with nb_defaulted?
27302     */
27303     /*
27304     * Skip elements if inside a "skip" wildcard or invalid.
27305     */
27306     vctxt->depth++;
27307     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27308         return;
27309     /*
27310     * Push the element.
27311     */
27312     if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27313         VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27314             "calling xmlSchemaValidatorPushElem()");
27315         goto internal_error;
27316     }
27317     ielem = vctxt->inode;
27318     /*
27319     * TODO: Is this OK?
27320     */
27321     ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
27322     ielem->localName = localname;
27323     ielem->nsName = URI;
27324     ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27325     /*
27326     * Register namespaces on the elem info.
27327     */
27328     if (nb_namespaces != 0) {
27329         /*
27330         * Although the parser builds its own namespace list,
27331         * we have no access to it, so we'll use an own one.
27332         */
27333         for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
27334             /*
27335             * Store prefix and namespace name.
27336             */
27337             if (ielem->nsBindings == NULL) {
27338                 ielem->nsBindings =
27339                     (const xmlChar **) xmlMalloc(10 *
27340                         sizeof(const xmlChar *));
27341                 if (ielem->nsBindings == NULL) {
27342                     xmlSchemaVErrMemory(vctxt,
27343                         "allocating namespace bindings for SAX validation",
27344                         NULL);
27345                     goto internal_error;
27346                 }
27347                 ielem->nbNsBindings = 0;
27348                 ielem->sizeNsBindings = 5;
27349             } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
27350                 ielem->sizeNsBindings *= 2;
27351                 ielem->nsBindings =
27352                     (const xmlChar **) xmlRealloc(
27353                         (void *) ielem->nsBindings,
27354                         ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
27355                 if (ielem->nsBindings == NULL) {
27356                     xmlSchemaVErrMemory(vctxt,
27357                         "re-allocating namespace bindings for SAX validation",
27358                         NULL);
27359                     goto internal_error;
27360                 }
27361             }
27362
27363             ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
27364             if (namespaces[j+1][0] == 0) {
27365                 /*
27366                 * Handle xmlns="".
27367                 */
27368                 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
27369             } else
27370                 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
27371                     namespaces[j+1];
27372             ielem->nbNsBindings++;
27373         }
27374     }
27375     /*
27376     * Register attributes.
27377     * SAX VAL TODO: We are not adding namespace declaration
27378     * attributes yet.
27379     */
27380     if (nb_attributes != 0) {
27381         xmlChar *value;
27382
27383         for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27384             /*
27385             * Duplicate the value.
27386             */
27387             value = xmlStrndup(attributes[j+3],
27388                 attributes[j+4] - attributes[j+3]);
27389             /*
27390             * TODO: Set the node line.
27391             */
27392             ret = xmlSchemaValidatorPushAttribute(vctxt,
27393                 NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
27394                 value, 1);
27395             if (ret == -1) {
27396                 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27397                     "calling xmlSchemaValidatorPushAttribute()");
27398                 goto internal_error;
27399             }
27400         }
27401     }
27402     /*
27403     * Validate the element.
27404     */
27405     ret = xmlSchemaValidateElem(vctxt);
27406     if (ret != 0) {
27407         if (ret == -1) {
27408             VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27409                 "calling xmlSchemaValidateElem()");
27410             goto internal_error;
27411         }
27412         goto exit;
27413     }
27414
27415 exit:
27416     return;
27417 internal_error:
27418     vctxt->err = -1;
27419     xmlStopParser(vctxt->parserCtxt);
27420     return;
27421 }
27422
27423 static void
27424 xmlSchemaSAXHandleEndElementNs(void *ctx,
27425                                const xmlChar * localname ATTRIBUTE_UNUSED,
27426                                const xmlChar * prefix ATTRIBUTE_UNUSED,
27427                                const xmlChar * URI ATTRIBUTE_UNUSED)
27428 {
27429     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27430     int res;
27431
27432     /*
27433     * Skip elements if inside a "skip" wildcard or if invalid.
27434     */
27435     if (vctxt->skipDepth != -1) {
27436         if (vctxt->depth > vctxt->skipDepth) {
27437             vctxt->depth--;
27438             return;
27439         } else
27440             vctxt->skipDepth = -1;
27441     }
27442     /*
27443     * SAX VAL TODO: Just a temporary check.
27444     */
27445     if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27446         (!xmlStrEqual(vctxt->inode->nsName, URI))) {
27447         VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27448             "elem pop mismatch");
27449     }
27450     res = xmlSchemaValidatorPopElem(vctxt);
27451     if (res != 0) {
27452         if (res < 0) {
27453             VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27454                 "calling xmlSchemaValidatorPopElem()");
27455             goto internal_error;
27456         }
27457         goto exit;
27458     }
27459 exit:
27460     return;
27461 internal_error:
27462     vctxt->err = -1;
27463     xmlStopParser(vctxt->parserCtxt);
27464     return;
27465 }
27466
27467 /************************************************************************
27468  *                                                                      *
27469  *                      Validation interfaces                           *
27470  *                                                                      *
27471  ************************************************************************/
27472
27473 /**
27474  * xmlSchemaNewValidCtxt:
27475  * @schema:  a precompiled XML Schemas
27476  *
27477  * Create an XML Schemas validation context based on the given schema.
27478  *
27479  * Returns the validation context or NULL in case of error
27480  */
27481 xmlSchemaValidCtxtPtr
27482 xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27483 {
27484     xmlSchemaValidCtxtPtr ret;
27485
27486     ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27487     if (ret == NULL) {
27488         xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
27489         return (NULL);
27490     }
27491     memset(ret, 0, sizeof(xmlSchemaValidCtxt));
27492     ret->type = XML_SCHEMA_CTXT_VALIDATOR;
27493     ret->dict = xmlDictCreate();
27494     ret->nodeQNames = xmlSchemaItemListCreate();
27495     ret->schema = schema;
27496     return (ret);
27497 }
27498
27499 /**
27500  * xmlSchemaValidateSetFilename:
27501  * @vctxt: the schema validation context
27502  * @filename: the file name
27503  *
27504  * Workaround to provide file error reporting information when this is
27505  * not provided by current APIs
27506  */
27507 void
27508 xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt, const char *filename) {
27509     if (vctxt == NULL)
27510         return;
27511     if (vctxt->filename != NULL)
27512         xmlFree(vctxt->filename);
27513     if (filename != NULL)
27514         vctxt->filename = (char *) xmlStrdup((const xmlChar *) filename);
27515     else
27516         vctxt->filename = NULL;
27517 }
27518
27519 /**
27520  * xmlSchemaClearValidCtxt:
27521  * @vctxt: the schema validation context
27522  *
27523  * Free the resources associated to the schema validation context;
27524  * leaves some fields alive intended for reuse of the context.
27525  */
27526 static void
27527 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27528 {
27529     if (vctxt == NULL)
27530         return;
27531
27532     /*
27533     * TODO: Should we clear the flags?
27534     *   Might be problematic if one reuses the context
27535     *   and assumes that the options remain the same.
27536     */
27537     vctxt->flags = 0;
27538     vctxt->validationRoot = NULL;
27539     vctxt->doc = NULL;
27540 #ifdef LIBXML_READER_ENABLED
27541     vctxt->reader = NULL;
27542 #endif
27543     vctxt->hasKeyrefs = 0;
27544
27545     if (vctxt->value != NULL) {
27546         xmlSchemaFreeValue(vctxt->value);
27547         vctxt->value = NULL;
27548     }
27549     /*
27550     * Augmented IDC information.
27551     */
27552     if (vctxt->aidcs != NULL) {
27553         xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27554         do {
27555             next = cur->next;
27556             xmlFree(cur);
27557             cur = next;
27558         } while (cur != NULL);
27559         vctxt->aidcs = NULL;
27560     }
27561     if (vctxt->idcMatcherCache != NULL) {
27562         xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp;
27563
27564         while (matcher) {
27565             tmp = matcher;
27566             matcher = matcher->nextCached;
27567             xmlSchemaIDCFreeMatcherList(tmp);
27568         }
27569         vctxt->idcMatcherCache = NULL;
27570     }
27571
27572
27573     if (vctxt->idcNodes != NULL) {
27574         int i;
27575         xmlSchemaPSVIIDCNodePtr item;
27576
27577         for (i = 0; i < vctxt->nbIdcNodes; i++) {
27578             item = vctxt->idcNodes[i];
27579             xmlFree(item->keys);
27580             xmlFree(item);
27581         }
27582         xmlFree(vctxt->idcNodes);
27583         vctxt->idcNodes = NULL;
27584         vctxt->nbIdcNodes = 0;
27585         vctxt->sizeIdcNodes = 0;
27586     }
27587     /*
27588     * Note that we won't delete the XPath state pool here.
27589     */
27590     if (vctxt->xpathStates != NULL) {
27591         xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27592         vctxt->xpathStates = NULL;
27593     }
27594     /*
27595     * Attribute info.
27596     */
27597     if (vctxt->nbAttrInfos != 0) {
27598         xmlSchemaClearAttrInfos(vctxt);
27599     }
27600     /*
27601     * Element info.
27602     */
27603     if (vctxt->elemInfos != NULL) {
27604         int i;
27605         xmlSchemaNodeInfoPtr ei;
27606
27607         for (i = 0; i < vctxt->sizeElemInfos; i++) {
27608             ei = vctxt->elemInfos[i];
27609             if (ei == NULL)
27610                 break;
27611             xmlSchemaClearElemInfo(vctxt, ei);
27612         }
27613     }
27614     xmlSchemaItemListClear(vctxt->nodeQNames);
27615     /* Recreate the dict. */
27616     xmlDictFree(vctxt->dict);
27617     /*
27618     * TODO: Is is save to recreate it? Do we have a scenario
27619     * where the user provides the dict?
27620     */
27621     vctxt->dict = xmlDictCreate();
27622
27623     if (vctxt->filename != NULL) {
27624         xmlFree(vctxt->filename);
27625         vctxt->filename = NULL;
27626     }
27627 }
27628
27629 /**
27630  * xmlSchemaFreeValidCtxt:
27631  * @ctxt:  the schema validation context
27632  *
27633  * Free the resources associated to the schema validation context
27634  */
27635 void
27636 xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27637 {
27638     if (ctxt == NULL)
27639         return;
27640     if (ctxt->value != NULL)
27641         xmlSchemaFreeValue(ctxt->value);
27642     if (ctxt->pctxt != NULL)
27643         xmlSchemaFreeParserCtxt(ctxt->pctxt);
27644     if (ctxt->idcNodes != NULL) {
27645         int i;
27646         xmlSchemaPSVIIDCNodePtr item;
27647
27648         for (i = 0; i < ctxt->nbIdcNodes; i++) {
27649             item = ctxt->idcNodes[i];
27650             xmlFree(item->keys);
27651             xmlFree(item);
27652         }
27653         xmlFree(ctxt->idcNodes);
27654     }
27655     if (ctxt->idcKeys != NULL) {
27656         int i;
27657         for (i = 0; i < ctxt->nbIdcKeys; i++)
27658             xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27659         xmlFree(ctxt->idcKeys);
27660     }
27661
27662     if (ctxt->xpathStates != NULL) {
27663         xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27664         ctxt->xpathStates = NULL;
27665     }
27666     if (ctxt->xpathStatePool != NULL) {
27667         xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27668         ctxt->xpathStatePool = NULL;
27669     }
27670
27671     /*
27672     * Augmented IDC information.
27673     */
27674     if (ctxt->aidcs != NULL) {
27675         xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27676         do {
27677             next = cur->next;
27678             xmlFree(cur);
27679             cur = next;
27680         } while (cur != NULL);
27681     }
27682     if (ctxt->attrInfos != NULL) {
27683         int i;
27684         xmlSchemaAttrInfoPtr attr;
27685
27686         /* Just a paranoid call to the cleanup. */
27687         if (ctxt->nbAttrInfos != 0)
27688             xmlSchemaClearAttrInfos(ctxt);
27689         for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27690             attr = ctxt->attrInfos[i];
27691             xmlFree(attr);
27692         }
27693         xmlFree(ctxt->attrInfos);
27694     }
27695     if (ctxt->elemInfos != NULL) {
27696         int i;
27697         xmlSchemaNodeInfoPtr ei;
27698
27699         for (i = 0; i < ctxt->sizeElemInfos; i++) {
27700             ei = ctxt->elemInfos[i];
27701             if (ei == NULL)
27702                 break;
27703             xmlSchemaClearElemInfo(ctxt, ei);
27704             xmlFree(ei);
27705         }
27706         xmlFree(ctxt->elemInfos);
27707     }
27708     if (ctxt->nodeQNames != NULL)
27709         xmlSchemaItemListFree(ctxt->nodeQNames);
27710     if (ctxt->dict != NULL)
27711         xmlDictFree(ctxt->dict);
27712     if (ctxt->filename != NULL)
27713         xmlFree(ctxt->filename);
27714     xmlFree(ctxt);
27715 }
27716
27717 /**
27718  * xmlSchemaIsValid:
27719  * @ctxt: the schema validation context
27720  *
27721  * Check if any error was detected during validation.
27722  *
27723  * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27724  *         of internal error.
27725  */
27726 int
27727 xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27728 {
27729     if (ctxt == NULL)
27730         return(-1);
27731     return(ctxt->err == 0);
27732 }
27733
27734 /**
27735  * xmlSchemaSetValidErrors:
27736  * @ctxt:  a schema validation context
27737  * @err:  the error function
27738  * @warn: the warning function
27739  * @ctx: the functions context
27740  *
27741  * Set the error and warning callback informations
27742  */
27743 void
27744 xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27745                         xmlSchemaValidityErrorFunc err,
27746                         xmlSchemaValidityWarningFunc warn, void *ctx)
27747 {
27748     if (ctxt == NULL)
27749         return;
27750     ctxt->error = err;
27751     ctxt->warning = warn;
27752     ctxt->errCtxt = ctx;
27753     if (ctxt->pctxt != NULL)
27754         xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
27755 }
27756
27757 /**
27758  * xmlSchemaSetValidStructuredErrors:
27759  * @ctxt:  a schema validation context
27760  * @serror:  the structured error function
27761  * @ctx: the functions context
27762  *
27763  * Set the structured error callback
27764  */
27765 void
27766 xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
27767                                   xmlStructuredErrorFunc serror, void *ctx)
27768 {
27769     if (ctxt == NULL)
27770         return;
27771         ctxt->serror = serror;
27772     ctxt->error = NULL;
27773     ctxt->warning = NULL;
27774     ctxt->errCtxt = ctx;
27775     if (ctxt->pctxt != NULL)
27776         xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
27777 }
27778
27779 /**
27780  * xmlSchemaGetValidErrors:
27781  * @ctxt: a XML-Schema validation context
27782  * @err: the error function result
27783  * @warn: the warning function result
27784  * @ctx: the functions context result
27785  *
27786  * Get the error and warning callback informations
27787  *
27788  * Returns -1 in case of error and 0 otherwise
27789  */
27790 int
27791 xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27792                         xmlSchemaValidityErrorFunc * err,
27793                         xmlSchemaValidityWarningFunc * warn, void **ctx)
27794 {
27795         if (ctxt == NULL)
27796                 return (-1);
27797         if (err != NULL)
27798                 *err = ctxt->error;
27799         if (warn != NULL)
27800                 *warn = ctxt->warning;
27801         if (ctx != NULL)
27802                 *ctx = ctxt->errCtxt;
27803         return (0);
27804 }
27805
27806
27807 /**
27808  * xmlSchemaSetValidOptions:
27809  * @ctxt:       a schema validation context
27810  * @options: a combination of xmlSchemaValidOption
27811  *
27812  * Sets the options to be used during the validation.
27813  *
27814  * Returns 0 in case of success, -1 in case of an
27815  * API error.
27816  */
27817 int
27818 xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27819                          int options)
27820
27821 {
27822     int i;
27823
27824     if (ctxt == NULL)
27825         return (-1);
27826     /*
27827     * WARNING: Change the start value if adding to the
27828     * xmlSchemaValidOption.
27829     * TODO: Is there an other, more easy to maintain,
27830     * way?
27831     */
27832     for (i = 1; i < (int) sizeof(int) * 8; i++) {
27833         if (options & 1<<i)
27834             return (-1);
27835     }
27836     ctxt->options = options;
27837     return (0);
27838 }
27839
27840 /**
27841  * xmlSchemaValidCtxtGetOptions:
27842  * @ctxt: a schema validation context
27843  *
27844  * Get the validation context options.
27845  *
27846  * Returns the option combination or -1 on error.
27847  */
27848 int
27849 xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
27850
27851 {
27852     if (ctxt == NULL)
27853         return (-1);
27854     else
27855         return (ctxt->options);
27856 }
27857
27858 static int
27859 xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27860 {
27861     xmlAttrPtr attr;
27862     int ret = 0;
27863     xmlSchemaNodeInfoPtr ielem = NULL;
27864     xmlNodePtr node, valRoot;
27865     const xmlChar *nsName;
27866
27867     /* DOC VAL TODO: Move this to the start function. */
27868     if (vctxt->validationRoot != NULL)
27869         valRoot = vctxt->validationRoot;
27870     else
27871         valRoot = xmlDocGetRootElement(vctxt->doc);
27872     if (valRoot == NULL) {
27873         /* VAL TODO: Error code? */
27874         VERROR(1, NULL, "The document has no document element");
27875         return (1);
27876     }
27877     vctxt->depth = -1;
27878     vctxt->validationRoot = valRoot;
27879     node = valRoot;
27880     while (node != NULL) {
27881         if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27882             goto next_sibling;
27883         if (node->type == XML_ELEMENT_NODE) {
27884
27885             /*
27886             * Init the node-info.
27887             */
27888             vctxt->depth++;
27889             if (xmlSchemaValidatorPushElem(vctxt) == -1)
27890                 goto internal_error;
27891             ielem = vctxt->inode;
27892             ielem->node = node;
27893             ielem->nodeLine = node->line;
27894             ielem->localName = node->name;
27895             if (node->ns != NULL)
27896                 ielem->nsName = node->ns->href;
27897             ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27898             /*
27899             * Register attributes.
27900             * DOC VAL TODO: We do not register namespace declaration
27901             * attributes yet.
27902             */
27903             vctxt->nbAttrInfos = 0;
27904             if (node->properties != NULL) {
27905                 attr = node->properties;
27906                 do {
27907                     if (attr->ns != NULL)
27908                         nsName = attr->ns->href;
27909                     else
27910                         nsName = NULL;
27911                     ret = xmlSchemaValidatorPushAttribute(vctxt,
27912                         (xmlNodePtr) attr,
27913                         /*
27914                         * Note that we give it the line number of the
27915                         * parent element.
27916                         */
27917                         ielem->nodeLine,
27918                         attr->name, nsName, 0,
27919                         xmlNodeListGetString(attr->doc, attr->children, 1), 1);
27920                     if (ret == -1) {
27921                         VERROR_INT("xmlSchemaDocWalk",
27922                             "calling xmlSchemaValidatorPushAttribute()");
27923                         goto internal_error;
27924                     }
27925                     attr = attr->next;
27926                 } while (attr);
27927             }
27928             /*
27929             * Validate the element.
27930             */
27931             ret = xmlSchemaValidateElem(vctxt);
27932             if (ret != 0) {
27933                 if (ret == -1) {
27934                     VERROR_INT("xmlSchemaDocWalk",
27935                         "calling xmlSchemaValidateElem()");
27936                     goto internal_error;
27937                 }
27938                 /*
27939                 * Don't stop validation; just skip the content
27940                 * of this element.
27941                 */
27942                 goto leave_node;
27943             }
27944             if ((vctxt->skipDepth != -1) &&
27945                 (vctxt->depth >= vctxt->skipDepth))
27946                 goto leave_node;
27947         } else if ((node->type == XML_TEXT_NODE) ||
27948             (node->type == XML_CDATA_SECTION_NODE)) {
27949             /*
27950             * Process character content.
27951             */
27952             if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
27953                 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27954             ret = xmlSchemaVPushText(vctxt, node->type, node->content,
27955                 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
27956             if (ret < 0) {
27957                 VERROR_INT("xmlSchemaVDocWalk",
27958                     "calling xmlSchemaVPushText()");
27959                 goto internal_error;
27960             }
27961             /*
27962             * DOC VAL TODO: Should we skip further validation of the
27963             * element content here?
27964             */
27965         } else if ((node->type == XML_ENTITY_NODE) ||
27966             (node->type == XML_ENTITY_REF_NODE)) {
27967             /*
27968             * DOC VAL TODO: What to do with entities?
27969             */
27970             VERROR_INT("xmlSchemaVDocWalk",
27971                 "there is at least one entity reference in the node-tree "
27972                 "currently being validated. Processing of entities with "
27973                 "this XML Schema processor is not supported (yet). Please "
27974                 "substitute entities before validation.");
27975             goto internal_error;
27976         } else {
27977             goto leave_node;
27978             /*
27979             * DOC VAL TODO: XInclude nodes, etc.
27980             */
27981         }
27982         /*
27983         * Walk the doc.
27984         */
27985         if (node->children != NULL) {
27986             node = node->children;
27987             continue;
27988         }
27989 leave_node:
27990         if (node->type == XML_ELEMENT_NODE) {
27991             /*
27992             * Leaving the scope of an element.
27993             */
27994             if (node != vctxt->inode->node) {
27995                 VERROR_INT("xmlSchemaVDocWalk",
27996                     "element position mismatch");
27997                 goto internal_error;
27998             }
27999             ret = xmlSchemaValidatorPopElem(vctxt);
28000             if (ret != 0) {
28001                 if (ret < 0) {
28002                     VERROR_INT("xmlSchemaVDocWalk",
28003                         "calling xmlSchemaValidatorPopElem()");
28004                     goto internal_error;
28005                 }
28006             }
28007             if (node == valRoot)
28008                 goto exit;
28009         }
28010 next_sibling:
28011         if (node->next != NULL)
28012             node = node->next;
28013         else {
28014             node = node->parent;
28015             goto leave_node;
28016         }
28017     }
28018
28019 exit:
28020     return (ret);
28021 internal_error:
28022     return (-1);
28023 }
28024
28025 static int
28026 xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
28027     /*
28028     * Some initialization.
28029     */
28030     vctxt->err = 0;
28031     vctxt->nberrors = 0;
28032     vctxt->depth = -1;
28033     vctxt->skipDepth = -1;
28034     vctxt->xsiAssemble = 0;
28035     vctxt->hasKeyrefs = 0;
28036 #ifdef ENABLE_IDC_NODE_TABLES_TEST
28037     vctxt->createIDCNodeTables = 1;
28038 #else
28039     vctxt->createIDCNodeTables = 0;
28040 #endif
28041     /*
28042     * Create a schema + parser if necessary.
28043     */
28044     if (vctxt->schema == NULL) {
28045         xmlSchemaParserCtxtPtr pctxt;
28046
28047         vctxt->xsiAssemble = 1;
28048         /*
28049         * If not schema was given then we will create a schema
28050         * dynamically using XSI schema locations.
28051         *
28052         * Create the schema parser context.
28053         */
28054         if ((vctxt->pctxt == NULL) &&
28055            (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
28056            return (-1);
28057         pctxt = vctxt->pctxt;
28058         pctxt->xsiAssemble = 1;
28059         /*
28060         * Create the schema.
28061         */
28062         vctxt->schema = xmlSchemaNewSchema(pctxt);
28063         if (vctxt->schema == NULL)
28064             return (-1);
28065         /*
28066         * Create the schema construction context.
28067         */
28068         pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
28069         if (pctxt->constructor == NULL)
28070             return(-1);
28071         pctxt->constructor->mainSchema = vctxt->schema;
28072         /*
28073         * Take ownership of the constructor to be able to free it.
28074         */
28075         pctxt->ownsConstructor = 1;
28076     }
28077     /*
28078     * Augment the IDC definitions for the main schema and all imported ones
28079     * NOTE: main schema if the first in the imported list
28080     */
28081     xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt);
28082
28083     return(0);
28084 }
28085
28086 static void
28087 xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
28088     if (vctxt->xsiAssemble) {
28089         if (vctxt->schema != NULL) {
28090             xmlSchemaFree(vctxt->schema);
28091             vctxt->schema = NULL;
28092         }
28093     }
28094     xmlSchemaClearValidCtxt(vctxt);
28095 }
28096
28097 static int
28098 xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
28099 {
28100     int ret = 0;
28101
28102     if (xmlSchemaPreRun(vctxt) < 0)
28103         return(-1);
28104
28105     if (vctxt->doc != NULL) {
28106         /*
28107          * Tree validation.
28108          */
28109         ret = xmlSchemaVDocWalk(vctxt);
28110 #ifdef LIBXML_READER_ENABLED
28111     } else if (vctxt->reader != NULL) {
28112         /*
28113          * XML Reader validation.
28114          */
28115 #ifdef XML_SCHEMA_READER_ENABLED
28116         ret = xmlSchemaVReaderWalk(vctxt);
28117 #endif
28118 #endif
28119     } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
28120         /*
28121          * SAX validation.
28122          */
28123         ret = xmlParseDocument(vctxt->parserCtxt);
28124     } else {
28125         VERROR_INT("xmlSchemaVStart",
28126             "no instance to validate");
28127         ret = -1;
28128     }
28129
28130     xmlSchemaPostRun(vctxt);
28131     if (ret == 0)
28132         ret = vctxt->err;
28133     return (ret);
28134 }
28135
28136 /**
28137  * xmlSchemaValidateOneElement:
28138  * @ctxt:  a schema validation context
28139  * @elem:  an element node
28140  *
28141  * Validate a branch of a tree, starting with the given @elem.
28142  *
28143  * Returns 0 if the element and its subtree is valid, a positive error
28144  * code number otherwise and -1 in case of an internal or API error.
28145  */
28146 int
28147 xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
28148 {
28149     if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
28150         return (-1);
28151
28152     if (ctxt->schema == NULL)
28153         return (-1);
28154
28155     ctxt->doc = elem->doc;
28156     ctxt->node = elem;
28157     ctxt->validationRoot = elem;
28158     return(xmlSchemaVStart(ctxt));
28159 }
28160
28161 /**
28162  * xmlSchemaValidateDoc:
28163  * @ctxt:  a schema validation context
28164  * @doc:  a parsed document tree
28165  *
28166  * Validate a document tree in memory.
28167  *
28168  * Returns 0 if the document is schemas valid, a positive error code
28169  *     number otherwise and -1 in case of internal or API error.
28170  */
28171 int
28172 xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
28173 {
28174     if ((ctxt == NULL) || (doc == NULL))
28175         return (-1);
28176
28177     ctxt->doc = doc;
28178     ctxt->node = xmlDocGetRootElement(doc);
28179     if (ctxt->node == NULL) {
28180         xmlSchemaCustomErr(ACTXT_CAST ctxt,
28181             XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
28182             (xmlNodePtr) doc, NULL,
28183             "The document has no document element", NULL, NULL);
28184         return (ctxt->err);
28185     }
28186     ctxt->validationRoot = ctxt->node;
28187     return (xmlSchemaVStart(ctxt));
28188 }
28189
28190
28191 /************************************************************************
28192  *                                                                      *
28193  *              Function and data for SAX streaming API                 *
28194  *                                                                      *
28195  ************************************************************************/
28196 typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
28197 typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
28198
28199 struct _xmlSchemaSplitSAXData {
28200     xmlSAXHandlerPtr      user_sax;
28201     void                 *user_data;
28202     xmlSchemaValidCtxtPtr ctxt;
28203     xmlSAXHandlerPtr      schemas_sax;
28204 };
28205
28206 #define XML_SAX_PLUG_MAGIC 0xdc43ba21
28207
28208 struct _xmlSchemaSAXPlug {
28209     unsigned int magic;
28210
28211     /* the original callbacks informations */
28212     xmlSAXHandlerPtr     *user_sax_ptr;
28213     xmlSAXHandlerPtr      user_sax;
28214     void                **user_data_ptr;
28215     void                 *user_data;
28216
28217     /* the block plugged back and validation informations */
28218     xmlSAXHandler         schemas_sax;
28219     xmlSchemaValidCtxtPtr ctxt;
28220 };
28221
28222 /* All those functions just bounces to the user provided SAX handlers */
28223 static void
28224 internalSubsetSplit(void *ctx, const xmlChar *name,
28225                const xmlChar *ExternalID, const xmlChar *SystemID)
28226 {
28227     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28228     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28229         (ctxt->user_sax->internalSubset != NULL))
28230         ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
28231                                        SystemID);
28232 }
28233
28234 static int
28235 isStandaloneSplit(void *ctx)
28236 {
28237     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28238     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28239         (ctxt->user_sax->isStandalone != NULL))
28240         return(ctxt->user_sax->isStandalone(ctxt->user_data));
28241     return(0);
28242 }
28243
28244 static int
28245 hasInternalSubsetSplit(void *ctx)
28246 {
28247     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28248     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28249         (ctxt->user_sax->hasInternalSubset != NULL))
28250         return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
28251     return(0);
28252 }
28253
28254 static int
28255 hasExternalSubsetSplit(void *ctx)
28256 {
28257     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28258     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28259         (ctxt->user_sax->hasExternalSubset != NULL))
28260         return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
28261     return(0);
28262 }
28263
28264 static void
28265 externalSubsetSplit(void *ctx, const xmlChar *name,
28266                const xmlChar *ExternalID, const xmlChar *SystemID)
28267 {
28268     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28269     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28270         (ctxt->user_sax->externalSubset != NULL))
28271         ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID,
28272                                        SystemID);
28273 }
28274
28275 static xmlParserInputPtr
28276 resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
28277 {
28278     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28279     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28280         (ctxt->user_sax->resolveEntity != NULL))
28281         return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
28282                                              systemId));
28283     return(NULL);
28284 }
28285
28286 static xmlEntityPtr
28287 getEntitySplit(void *ctx, const xmlChar *name)
28288 {
28289     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28290     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28291         (ctxt->user_sax->getEntity != NULL))
28292         return(ctxt->user_sax->getEntity(ctxt->user_data, name));
28293     return(NULL);
28294 }
28295
28296 static xmlEntityPtr
28297 getParameterEntitySplit(void *ctx, const xmlChar *name)
28298 {
28299     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28300     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28301         (ctxt->user_sax->getParameterEntity != NULL))
28302         return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
28303     return(NULL);
28304 }
28305
28306
28307 static void
28308 entityDeclSplit(void *ctx, const xmlChar *name, int type,
28309           const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
28310 {
28311     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28312     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28313         (ctxt->user_sax->entityDecl != NULL))
28314         ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
28315                                    systemId, content);
28316 }
28317
28318 static void
28319 attributeDeclSplit(void *ctx, const xmlChar * elem,
28320                    const xmlChar * name, int type, int def,
28321                    const xmlChar * defaultValue, xmlEnumerationPtr tree)
28322 {
28323     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28324     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28325         (ctxt->user_sax->attributeDecl != NULL)) {
28326         ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
28327                                       def, defaultValue, tree);
28328     } else {
28329         xmlFreeEnumeration(tree);
28330     }
28331 }
28332
28333 static void
28334 elementDeclSplit(void *ctx, const xmlChar *name, int type,
28335             xmlElementContentPtr content)
28336 {
28337     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28338     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28339         (ctxt->user_sax->elementDecl != NULL))
28340         ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
28341 }
28342
28343 static void
28344 notationDeclSplit(void *ctx, const xmlChar *name,
28345              const xmlChar *publicId, const xmlChar *systemId)
28346 {
28347     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28348     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28349         (ctxt->user_sax->notationDecl != NULL))
28350         ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
28351                                      systemId);
28352 }
28353
28354 static void
28355 unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
28356                    const xmlChar *publicId, const xmlChar *systemId,
28357                    const xmlChar *notationName)
28358 {
28359     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28360     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28361         (ctxt->user_sax->unparsedEntityDecl != NULL))
28362         ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
28363                                            systemId, notationName);
28364 }
28365
28366 static void
28367 setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
28368 {
28369     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28370     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28371         (ctxt->user_sax->setDocumentLocator != NULL))
28372         ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
28373 }
28374
28375 static void
28376 startDocumentSplit(void *ctx)
28377 {
28378     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28379     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28380         (ctxt->user_sax->startDocument != NULL))
28381         ctxt->user_sax->startDocument(ctxt->user_data);
28382 }
28383
28384 static void
28385 endDocumentSplit(void *ctx)
28386 {
28387     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28388     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28389         (ctxt->user_sax->endDocument != NULL))
28390         ctxt->user_sax->endDocument(ctxt->user_data);
28391 }
28392
28393 static void
28394 processingInstructionSplit(void *ctx, const xmlChar *target,
28395                       const xmlChar *data)
28396 {
28397     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28398     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28399         (ctxt->user_sax->processingInstruction != NULL))
28400         ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
28401 }
28402
28403 static void
28404 commentSplit(void *ctx, const xmlChar *value)
28405 {
28406     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28407     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28408         (ctxt->user_sax->comment != NULL))
28409         ctxt->user_sax->comment(ctxt->user_data, value);
28410 }
28411
28412 /*
28413  * Varargs error callbacks to the user application, harder ...
28414  */
28415
28416 static void XMLCDECL
28417 warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28418     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28419     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28420         (ctxt->user_sax->warning != NULL)) {
28421         TODO
28422     }
28423 }
28424 static void XMLCDECL
28425 errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28426     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28427     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28428         (ctxt->user_sax->error != NULL)) {
28429         TODO
28430     }
28431 }
28432 static void XMLCDECL
28433 fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28434     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28435     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28436         (ctxt->user_sax->fatalError != NULL)) {
28437         TODO
28438     }
28439 }
28440
28441 /*
28442  * Those are function where both the user handler and the schemas handler
28443  * need to be called.
28444  */
28445 static void
28446 charactersSplit(void *ctx, const xmlChar *ch, int len)
28447 {
28448     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28449     if (ctxt == NULL)
28450         return;
28451     if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
28452         ctxt->user_sax->characters(ctxt->user_data, ch, len);
28453     if (ctxt->ctxt != NULL)
28454         xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28455 }
28456
28457 static void
28458 ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
28459 {
28460     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28461     if (ctxt == NULL)
28462         return;
28463     if ((ctxt->user_sax != NULL) &&
28464         (ctxt->user_sax->ignorableWhitespace != NULL))
28465         ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
28466     if (ctxt->ctxt != NULL)
28467         xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28468 }
28469
28470 static void
28471 cdataBlockSplit(void *ctx, const xmlChar *value, int len)
28472 {
28473     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28474     if (ctxt == NULL)
28475         return;
28476     if ((ctxt->user_sax != NULL) &&
28477         (ctxt->user_sax->cdataBlock != NULL))
28478         ctxt->user_sax->cdataBlock(ctxt->user_data, value, len);
28479     if (ctxt->ctxt != NULL)
28480         xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28481 }
28482
28483 static void
28484 referenceSplit(void *ctx, const xmlChar *name)
28485 {
28486     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28487     if (ctxt == NULL)
28488         return;
28489     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28490         (ctxt->user_sax->reference != NULL))
28491         ctxt->user_sax->reference(ctxt->user_data, name);
28492     if (ctxt->ctxt != NULL)
28493         xmlSchemaSAXHandleReference(ctxt->user_data, name);
28494 }
28495
28496 static void
28497 startElementNsSplit(void *ctx, const xmlChar * localname,
28498                     const xmlChar * prefix, const xmlChar * URI,
28499                     int nb_namespaces, const xmlChar ** namespaces,
28500                     int nb_attributes, int nb_defaulted,
28501                     const xmlChar ** attributes) {
28502     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28503     if (ctxt == NULL)
28504         return;
28505     if ((ctxt->user_sax != NULL) &&
28506         (ctxt->user_sax->startElementNs != NULL))
28507         ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28508                                        URI, nb_namespaces, namespaces,
28509                                        nb_attributes, nb_defaulted,
28510                                        attributes);
28511     if (ctxt->ctxt != NULL)
28512         xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28513                                          URI, nb_namespaces, namespaces,
28514                                          nb_attributes, nb_defaulted,
28515                                          attributes);
28516 }
28517
28518 static void
28519 endElementNsSplit(void *ctx, const xmlChar * localname,
28520                     const xmlChar * prefix, const xmlChar * URI) {
28521     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28522     if (ctxt == NULL)
28523         return;
28524     if ((ctxt->user_sax != NULL) &&
28525         (ctxt->user_sax->endElementNs != NULL))
28526         ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28527     if (ctxt->ctxt != NULL)
28528         xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28529 }
28530
28531 /**
28532  * xmlSchemaSAXPlug:
28533  * @ctxt:  a schema validation context
28534  * @sax:  a pointer to the original xmlSAXHandlerPtr
28535  * @user_data:  a pointer to the original SAX user data pointer
28536  *
28537  * Plug a SAX based validation layer in a SAX parsing event flow.
28538  * The original @saxptr and @dataptr data are replaced by new pointers
28539  * but the calls to the original will be maintained.
28540  *
28541  * Returns a pointer to a data structure needed to unplug the validation layer
28542  *         or NULL in case of errors.
28543  */
28544 xmlSchemaSAXPlugPtr
28545 xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28546                  xmlSAXHandlerPtr *sax, void **user_data)
28547 {
28548     xmlSchemaSAXPlugPtr ret;
28549     xmlSAXHandlerPtr old_sax;
28550
28551     if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28552         return(NULL);
28553
28554     /*
28555      * We only allow to plug into SAX2 event streams
28556      */
28557     old_sax = *sax;
28558     if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28559         return(NULL);
28560     if ((old_sax != NULL) &&
28561         (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28562         ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28563         return(NULL);
28564
28565     /*
28566      * everything seems right allocate the local data needed for that layer
28567      */
28568     ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28569     if (ret == NULL) {
28570         return(NULL);
28571     }
28572     memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28573     ret->magic = XML_SAX_PLUG_MAGIC;
28574     ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28575     ret->ctxt = ctxt;
28576     ret->user_sax_ptr = sax;
28577     ret->user_sax = old_sax;
28578     if (old_sax == NULL) {
28579         /*
28580          * go direct, no need for the split block and functions.
28581          */
28582         ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28583         ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28584         /*
28585          * Note that we use the same text-function for both, to prevent
28586          * the parser from testing for ignorable whitespace.
28587          */
28588         ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28589         ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28590
28591         ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28592         ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28593
28594         ret->user_data = ctxt;
28595         *user_data = ctxt;
28596     } else {
28597        /*
28598         * for each callback unused by Schemas initialize it to the Split
28599         * routine only if non NULL in the user block, this can speed up
28600         * things at the SAX level.
28601         */
28602         if (old_sax->internalSubset != NULL)
28603             ret->schemas_sax.internalSubset = internalSubsetSplit;
28604         if (old_sax->isStandalone != NULL)
28605             ret->schemas_sax.isStandalone = isStandaloneSplit;
28606         if (old_sax->hasInternalSubset != NULL)
28607             ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28608         if (old_sax->hasExternalSubset != NULL)
28609             ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28610         if (old_sax->resolveEntity != NULL)
28611             ret->schemas_sax.resolveEntity = resolveEntitySplit;
28612         if (old_sax->getEntity != NULL)
28613             ret->schemas_sax.getEntity = getEntitySplit;
28614         if (old_sax->entityDecl != NULL)
28615             ret->schemas_sax.entityDecl = entityDeclSplit;
28616         if (old_sax->notationDecl != NULL)
28617             ret->schemas_sax.notationDecl = notationDeclSplit;
28618         if (old_sax->attributeDecl != NULL)
28619             ret->schemas_sax.attributeDecl = attributeDeclSplit;
28620         if (old_sax->elementDecl != NULL)
28621             ret->schemas_sax.elementDecl = elementDeclSplit;
28622         if (old_sax->unparsedEntityDecl != NULL)
28623             ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28624         if (old_sax->setDocumentLocator != NULL)
28625             ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28626         if (old_sax->startDocument != NULL)
28627             ret->schemas_sax.startDocument = startDocumentSplit;
28628         if (old_sax->endDocument != NULL)
28629             ret->schemas_sax.endDocument = endDocumentSplit;
28630         if (old_sax->processingInstruction != NULL)
28631             ret->schemas_sax.processingInstruction = processingInstructionSplit;
28632         if (old_sax->comment != NULL)
28633             ret->schemas_sax.comment = commentSplit;
28634         if (old_sax->warning != NULL)
28635             ret->schemas_sax.warning = warningSplit;
28636         if (old_sax->error != NULL)
28637             ret->schemas_sax.error = errorSplit;
28638         if (old_sax->fatalError != NULL)
28639             ret->schemas_sax.fatalError = fatalErrorSplit;
28640         if (old_sax->getParameterEntity != NULL)
28641             ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28642         if (old_sax->externalSubset != NULL)
28643             ret->schemas_sax.externalSubset = externalSubsetSplit;
28644
28645         /*
28646          * the 6 schemas callback have to go to the splitter functions
28647          * Note that we use the same text-function for ignorableWhitespace
28648          * if possible, to prevent the parser from testing for ignorable
28649          * whitespace.
28650          */
28651         ret->schemas_sax.characters = charactersSplit;
28652         if ((old_sax->ignorableWhitespace != NULL) &&
28653             (old_sax->ignorableWhitespace != old_sax->characters))
28654             ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28655         else
28656             ret->schemas_sax.ignorableWhitespace = charactersSplit;
28657         ret->schemas_sax.cdataBlock = cdataBlockSplit;
28658         ret->schemas_sax.reference = referenceSplit;
28659         ret->schemas_sax.startElementNs = startElementNsSplit;
28660         ret->schemas_sax.endElementNs = endElementNsSplit;
28661
28662         ret->user_data_ptr = user_data;
28663         ret->user_data = *user_data;
28664         *user_data = ret;
28665     }
28666
28667     /*
28668      * plug the pointers back.
28669      */
28670     *sax = &(ret->schemas_sax);
28671     ctxt->sax = *sax;
28672     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28673     xmlSchemaPreRun(ctxt);
28674     return(ret);
28675 }
28676
28677 /**
28678  * xmlSchemaSAXUnplug:
28679  * @plug:  a data structure returned by xmlSchemaSAXPlug
28680  *
28681  * Unplug a SAX based validation layer in a SAX parsing event flow.
28682  * The original pointers used in the call are restored.
28683  *
28684  * Returns 0 in case of success and -1 in case of failure.
28685  */
28686 int
28687 xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28688 {
28689     xmlSAXHandlerPtr *sax;
28690     void **user_data;
28691
28692     if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28693         return(-1);
28694     plug->magic = 0;
28695
28696     xmlSchemaPostRun(plug->ctxt);
28697     /* restore the data */
28698     sax = plug->user_sax_ptr;
28699     *sax = plug->user_sax;
28700     if (plug->user_sax != NULL) {
28701         user_data = plug->user_data_ptr;
28702         *user_data = plug->user_data;
28703     }
28704
28705     /* free and return */
28706     xmlFree(plug);
28707     return(0);
28708 }
28709
28710 /**
28711  * xmlSchemaValidateSetLocator:
28712  * @vctxt: a schema validation context
28713  * @f: the locator function pointer
28714  * @ctxt: the locator context
28715  *
28716  * Allows to set a locator function to the validation context,
28717  * which will be used to provide file and line information since
28718  * those are not provided as part of the SAX validation flow
28719  * Setting @f to NULL disable the locator.
28720  */
28721
28722 void
28723 xmlSchemaValidateSetLocator(xmlSchemaValidCtxtPtr vctxt,
28724                             xmlSchemaValidityLocatorFunc f,
28725                             void *ctxt)
28726 {
28727     if (vctxt == NULL) return;
28728     vctxt->locFunc = f;
28729     vctxt->locCtxt = ctxt;
28730 }
28731
28732 /**
28733  * xmlSchemaValidateStreamLocator:
28734  * @ctx: the xmlTextReaderPtr used
28735  * @file: returned file information
28736  * @line: returned line information
28737  *
28738  * Internal locator function for the readers
28739  *
28740  * Returns 0 in case the Schema validation could be (des)activated and
28741  *         -1 in case of error.
28742  */
28743 static int
28744 xmlSchemaValidateStreamLocator(void *ctx, const char **file,
28745                                unsigned long *line) {
28746     xmlParserCtxtPtr ctxt;
28747
28748     if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
28749         return(-1);
28750
28751     if (file != NULL)
28752         *file = NULL;
28753     if (line != NULL)
28754         *line = 0;
28755
28756     ctxt = (xmlParserCtxtPtr) ctx;
28757     if (ctxt->input != NULL) {
28758        if (file != NULL)
28759            *file = ctxt->input->filename;
28760        if (line != NULL)
28761            *line = ctxt->input->line;
28762        return(0);
28763     }
28764     return(-1);
28765 }
28766
28767 /**
28768  * xmlSchemaValidateStream:
28769  * @ctxt:  a schema validation context
28770  * @input:  the input to use for reading the data
28771  * @enc:  an optional encoding information
28772  * @sax:  a SAX handler for the resulting events
28773  * @user_data:  the context to provide to the SAX handler.
28774  *
28775  * Validate an input based on a flow of SAX event from the parser
28776  * and forward the events to the @sax handler with the provided @user_data
28777  * the user provided @sax handler must be a SAX2 one.
28778  *
28779  * Returns 0 if the document is schemas valid, a positive error code
28780  *     number otherwise and -1 in case of internal or API error.
28781  */
28782 int
28783 xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
28784                         xmlParserInputBufferPtr input, xmlCharEncoding enc,
28785                         xmlSAXHandlerPtr sax, void *user_data)
28786 {
28787     xmlSchemaSAXPlugPtr plug = NULL;
28788     xmlSAXHandlerPtr old_sax = NULL;
28789     xmlParserCtxtPtr pctxt = NULL;
28790     xmlParserInputPtr inputStream = NULL;
28791     int ret;
28792
28793     if ((ctxt == NULL) || (input == NULL))
28794         return (-1);
28795
28796     /*
28797      * prepare the parser
28798      */
28799     pctxt = xmlNewParserCtxt();
28800     if (pctxt == NULL)
28801         return (-1);
28802     old_sax = pctxt->sax;
28803     pctxt->sax = sax;
28804     pctxt->userData = user_data;
28805 #if 0
28806     if (options)
28807         xmlCtxtUseOptions(pctxt, options);
28808 #endif
28809     pctxt->linenumbers = 1;
28810     xmlSchemaValidateSetLocator(ctxt, xmlSchemaValidateStreamLocator, pctxt);
28811
28812     inputStream = xmlNewIOInputStream(pctxt, input, enc);;
28813     if (inputStream == NULL) {
28814         ret = -1;
28815         goto done;
28816     }
28817     inputPush(pctxt, inputStream);
28818     ctxt->parserCtxt = pctxt;
28819     ctxt->input = input;
28820
28821     /*
28822      * Plug the validation and launch the parsing
28823      */
28824     plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28825     if (plug == NULL) {
28826         ret = -1;
28827         goto done;
28828     }
28829     ctxt->input = input;
28830     ctxt->enc = enc;
28831     ctxt->sax = pctxt->sax;
28832     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28833     ret = xmlSchemaVStart(ctxt);
28834
28835     if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28836         ret = ctxt->parserCtxt->errNo;
28837         if (ret == 0)
28838             ret = 1;
28839     }
28840
28841 done:
28842     ctxt->parserCtxt = NULL;
28843     ctxt->sax = NULL;
28844     ctxt->input = NULL;
28845     if (plug != NULL) {
28846         xmlSchemaSAXUnplug(plug);
28847     }
28848     /* cleanup */
28849     if (pctxt != NULL) {
28850         pctxt->sax = old_sax;
28851         xmlFreeParserCtxt(pctxt);
28852     }
28853     return (ret);
28854 }
28855
28856 /**
28857  * xmlSchemaValidateFile:
28858  * @ctxt: a schema validation context
28859  * @filename: the URI of the instance
28860  * @options: a future set of options, currently unused
28861  *
28862  * Do a schemas validation of the given resource, it will use the
28863  * SAX streamable validation internally.
28864  *
28865  * Returns 0 if the document is valid, a positive error code
28866  *     number otherwise and -1 in case of an internal or API error.
28867  */
28868 int
28869 xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
28870                       const char * filename,
28871                       int options ATTRIBUTE_UNUSED)
28872 {
28873     int ret;
28874     xmlParserInputBufferPtr input;
28875
28876     if ((ctxt == NULL) || (filename == NULL))
28877         return (-1);
28878
28879     input = xmlParserInputBufferCreateFilename(filename,
28880         XML_CHAR_ENCODING_NONE);
28881     if (input == NULL)
28882         return (-1);
28883     ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
28884         NULL, NULL);
28885     return (ret);
28886 }
28887
28888 /**
28889  * xmlSchemaValidCtxtGetParserCtxt:
28890  * @ctxt: a schema validation context
28891  *
28892  * allow access to the parser context of the schema validation context
28893  *
28894  * Returns the parser context of the schema validation context or NULL
28895  *         in case of error.
28896  */
28897 xmlParserCtxtPtr
28898 xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)
28899 {
28900     if (ctxt == NULL)
28901         return(NULL);
28902     return (ctxt->parserCtxt);
28903 }
28904
28905 #define bottom_xmlschemas
28906 #include "elfgcchack.h"
28907 #endif /* LIBXML_SCHEMAS_ENABLED */