Imported Upstream version 2.9.4
[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;            /* dictionary 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) LIBXML_ATTR_FORMAT(3,0);
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 (xmlEscapeFormatString(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 LIBXML_ATTR_FORMAT(4,0)
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 LIBXML_ATTR_FORMAT(5,0)
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 LIBXML_ATTR_FORMAT(7,0)
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 LIBXML_ATTR_FORMAT(2,0)
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  * xmlSchemaErr4Line:
2017  * @ctxt: the validation context
2018  * @errorLevel: the error level
2019  * @error: the error code
2020  * @node: the context node
2021  * @line: the line number
2022  * @msg: the error message
2023  * @str1: extra data
2024  * @str2: extra data
2025  * @str3: extra data
2026  * @str4: extra data
2027  *
2028  * Handle a validation error
2029  */
2030 static void LIBXML_ATTR_FORMAT(6,0)
2031 xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
2032                   xmlErrorLevel errorLevel,
2033                   int error, xmlNodePtr node, int line, const char *msg,
2034                   const xmlChar *str1, const xmlChar *str2,
2035                   const xmlChar *str3, const xmlChar *str4)
2036 {
2037     xmlStructuredErrorFunc schannel = NULL;
2038     xmlGenericErrorFunc channel = NULL;
2039     void *data = NULL;
2040
2041     if (ctxt != NULL) {
2042         if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2043             xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
2044             const char *file = NULL;
2045             int col = 0;
2046             if (errorLevel != XML_ERR_WARNING) {
2047                 vctxt->nberrors++;
2048                 vctxt->err = error;
2049                 channel = vctxt->error;
2050             } else {
2051                 channel = vctxt->warning;
2052             }
2053             schannel = vctxt->serror;
2054             data = vctxt->errCtxt;
2055
2056             /*
2057             * Error node. If we specify a line number, then
2058             * do not channel any node to the error function.
2059             */
2060             if (line == 0) {
2061                 if ((node == NULL) &&
2062                     (vctxt->depth >= 0) &&
2063                     (vctxt->inode != NULL)) {
2064                     node = vctxt->inode->node;
2065                 }
2066                 /*
2067                 * Get filename and line if no node-tree.
2068                 */
2069                 if ((node == NULL) &&
2070                     (vctxt->parserCtxt != NULL) &&
2071                     (vctxt->parserCtxt->input != NULL)) {
2072                     file = vctxt->parserCtxt->input->filename;
2073                     line = vctxt->parserCtxt->input->line;
2074                     col = vctxt->parserCtxt->input->col;
2075                 }
2076             } else {
2077                 /*
2078                 * Override the given node's (if any) position
2079                 * and channel only the given line number.
2080                 */
2081                 node = NULL;
2082                 /*
2083                 * Get filename.
2084                 */
2085                 if (vctxt->doc != NULL)
2086                     file = (const char *) vctxt->doc->URL;
2087                 else if ((vctxt->parserCtxt != NULL) &&
2088                     (vctxt->parserCtxt->input != NULL))
2089                     file = vctxt->parserCtxt->input->filename;
2090             }
2091             if (vctxt->locFunc != NULL) {
2092                 if ((file == NULL) || (line == 0)) {
2093                     unsigned long l;
2094                     const char *f;
2095                     vctxt->locFunc(vctxt->locCtxt, &f, &l);
2096                     if (file == NULL)
2097                         file = f;
2098                     if (line == 0)
2099                         line = (int) l;
2100                 }
2101             }
2102             if ((file == NULL) && (vctxt->filename != NULL))
2103                 file = vctxt->filename;
2104
2105             __xmlRaiseError(schannel, channel, data, ctxt,
2106                 node, XML_FROM_SCHEMASV,
2107                 error, errorLevel, file, line,
2108                 (const char *) str1, (const char *) str2,
2109                 (const char *) str3, 0, col, msg, str1, str2, str3, str4);
2110
2111         } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2112             xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
2113             if (errorLevel != XML_ERR_WARNING) {
2114                 pctxt->nberrors++;
2115                 pctxt->err = error;
2116                 channel = pctxt->error;
2117             } else {
2118                 channel = pctxt->warning;
2119             }
2120             schannel = pctxt->serror;
2121             data = pctxt->errCtxt;
2122             __xmlRaiseError(schannel, channel, data, ctxt,
2123                 node, XML_FROM_SCHEMASP, error,
2124                 errorLevel, NULL, 0,
2125                 (const char *) str1, (const char *) str2,
2126                 (const char *) str3, 0, 0, msg, str1, str2, str3, str4);
2127         } else {
2128             TODO
2129         }
2130     }
2131 }
2132
2133 /**
2134  * xmlSchemaErr3:
2135  * @ctxt: the validation context
2136  * @node: the context node
2137  * @error: the error code
2138  * @msg: the error message
2139  * @str1: extra data
2140  * @str2: extra data
2141  * @str3: extra data
2142  *
2143  * Handle a validation error
2144  */
2145 static void LIBXML_ATTR_FORMAT(4,0)
2146 xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
2147               int error, xmlNodePtr node, const char *msg,
2148               const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
2149 {
2150     xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2151         msg, str1, str2, str3, NULL);
2152 }
2153
2154 static void LIBXML_ATTR_FORMAT(4,0)
2155 xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
2156               int error, xmlNodePtr node, const char *msg,
2157               const xmlChar *str1, const xmlChar *str2,
2158               const xmlChar *str3, const xmlChar *str4)
2159 {
2160     xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2161         msg, str1, str2, str3, str4);
2162 }
2163
2164 static void LIBXML_ATTR_FORMAT(4,0)
2165 xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2166              int error, xmlNodePtr node, const char *msg,
2167              const xmlChar *str1, const xmlChar *str2)
2168 {
2169     xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
2170 }
2171
2172 static xmlChar *
2173 xmlSchemaFormatNodeForError(xmlChar ** msg,
2174                             xmlSchemaAbstractCtxtPtr actxt,
2175                             xmlNodePtr node)
2176 {
2177     xmlChar *str = NULL;
2178
2179     *msg = NULL;
2180     if ((node != NULL) &&
2181         (node->type != XML_ELEMENT_NODE) &&
2182         (node->type != XML_ATTRIBUTE_NODE))
2183     {
2184         /*
2185         * Don't try to format other nodes than element and
2186         * attribute nodes.
2187         * Play safe and return an empty string.
2188         */
2189         *msg = xmlStrdup(BAD_CAST "");
2190         return(*msg);
2191     }
2192     if (node != NULL) {
2193         /*
2194         * Work on tree nodes.
2195         */
2196         if (node->type == XML_ATTRIBUTE_NODE) {
2197             xmlNodePtr elem = node->parent;
2198
2199             *msg = xmlStrdup(BAD_CAST "Element '");
2200             if (elem->ns != NULL)
2201                 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2202                     elem->ns->href, elem->name));
2203             else
2204                 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2205                     NULL, elem->name));
2206             FREE_AND_NULL(str);
2207             *msg = xmlStrcat(*msg, BAD_CAST "', ");
2208             *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2209         } else {
2210             *msg = xmlStrdup(BAD_CAST "Element '");
2211         }
2212         if (node->ns != NULL)
2213             *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2214             node->ns->href, node->name));
2215         else
2216             *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2217             NULL, node->name));
2218         FREE_AND_NULL(str);
2219         *msg = xmlStrcat(*msg, BAD_CAST "': ");
2220     } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2221         xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2222         /*
2223         * Work on node infos.
2224         */
2225         if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2226             xmlSchemaNodeInfoPtr ielem =
2227                 vctxt->elemInfos[vctxt->depth];
2228
2229             *msg = xmlStrdup(BAD_CAST "Element '");
2230             *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2231                 ielem->nsName, ielem->localName));
2232             FREE_AND_NULL(str);
2233             *msg = xmlStrcat(*msg, BAD_CAST "', ");
2234             *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2235         } else {
2236             *msg = xmlStrdup(BAD_CAST "Element '");
2237         }
2238         *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2239             vctxt->inode->nsName, vctxt->inode->localName));
2240         FREE_AND_NULL(str);
2241         *msg = xmlStrcat(*msg, BAD_CAST "': ");
2242     } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
2243         /*
2244         * Hmm, no node while parsing?
2245         * Return an empty string, in case NULL will break something.
2246         */
2247         *msg = xmlStrdup(BAD_CAST "");
2248     } else {
2249         TODO
2250         return (NULL);
2251     }
2252
2253     /*
2254      * xmlSchemaFormatItemForReport() also returns an escaped format
2255      * string, so do this before calling it below (in the future).
2256      */
2257     xmlEscapeFormatString(msg);
2258
2259     /*
2260     * VAL TODO: The output of the given schema component is currently
2261     * disabled.
2262     */
2263 #if 0
2264     if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2265         *msg = xmlStrcat(*msg, BAD_CAST " [");
2266         *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2267             NULL, type, NULL, 0));
2268         FREE_AND_NULL(str)
2269         *msg = xmlStrcat(*msg, BAD_CAST "]");
2270     }
2271 #endif
2272     return (*msg);
2273 }
2274
2275 static void LIBXML_ATTR_FORMAT(3,0)
2276 xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
2277                      const char *funcName,
2278                      const char *message,
2279                      const xmlChar *str1,
2280                      const xmlChar *str2)
2281 {
2282     xmlChar *msg = NULL;
2283
2284     if (actxt == NULL)
2285         return;
2286     msg = xmlStrdup(BAD_CAST "Internal error: %s, ");
2287     msg = xmlStrcat(msg, BAD_CAST message);
2288     msg = xmlStrcat(msg, BAD_CAST ".\n");
2289
2290     if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2291         xmlSchemaErr3(actxt, XML_SCHEMAV_INTERNAL, NULL,
2292             (const char *) msg, (const xmlChar *) funcName, str1, str2);
2293     else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
2294         xmlSchemaErr3(actxt, XML_SCHEMAP_INTERNAL, NULL,
2295             (const char *) msg, (const xmlChar *) funcName, str1, str2);
2296
2297     FREE_AND_NULL(msg)
2298 }
2299
2300 static void LIBXML_ATTR_FORMAT(3,0)
2301 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2302                      const char *funcName,
2303                      const char *message)
2304 {
2305     xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2306 }
2307
2308 #if 0
2309 static void LIBXML_ATTR_FORMAT(3,0)
2310 xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2311                      const char *funcName,
2312                      const char *message,
2313                      const xmlChar *str1,
2314                      const xmlChar *str2)
2315 {
2316     xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
2317         str1, str2);
2318 }
2319 #endif
2320
2321 static void LIBXML_ATTR_FORMAT(5,0)
2322 xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2323                    xmlParserErrors error,
2324                    xmlNodePtr node,
2325                    xmlSchemaBasicItemPtr item,
2326                    const char *message,
2327                    const xmlChar *str1, const xmlChar *str2,
2328                    const xmlChar *str3, const xmlChar *str4)
2329 {
2330     xmlChar *msg = NULL;
2331
2332     if ((node == NULL) && (item != NULL) &&
2333         (actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2334         node = WXS_ITEM_NODE(item);
2335         xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2336         msg = xmlStrcat(msg, BAD_CAST ": ");
2337     } else
2338         xmlSchemaFormatNodeForError(&msg, actxt, node);
2339     msg = xmlStrcat(msg, (const xmlChar *) message);
2340     msg = xmlStrcat(msg, BAD_CAST ".\n");
2341     xmlSchemaErr4(actxt, error, node,
2342         (const char *) msg, str1, str2, str3, str4);
2343     FREE_AND_NULL(msg)
2344 }
2345
2346 static void LIBXML_ATTR_FORMAT(5,0)
2347 xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2348                    xmlParserErrors error,
2349                    xmlNodePtr node,
2350                    xmlSchemaBasicItemPtr item,
2351                    const char *message,
2352                    const xmlChar *str1,
2353                    const xmlChar *str2)
2354 {
2355     xmlSchemaCustomErr4(actxt, error, node, item,
2356         message, str1, str2, NULL, NULL);
2357 }
2358
2359
2360
2361 static void LIBXML_ATTR_FORMAT(5,0)
2362 xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2363                    xmlParserErrors error,
2364                    xmlNodePtr node,
2365                    xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2366                    const char *message,
2367                    const xmlChar *str1,
2368                    const xmlChar *str2,
2369                    const xmlChar *str3)
2370 {
2371     xmlChar *msg = NULL;
2372
2373     xmlSchemaFormatNodeForError(&msg, actxt, node);
2374     msg = xmlStrcat(msg, (const xmlChar *) message);
2375     msg = xmlStrcat(msg, BAD_CAST ".\n");
2376
2377     /* URGENT TODO: Set the error code to something sane. */
2378     xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2379         (const char *) msg, str1, str2, str3, NULL);
2380
2381     FREE_AND_NULL(msg)
2382 }
2383
2384
2385
2386 static void LIBXML_ATTR_FORMAT(5,0)
2387 xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2388                    xmlParserErrors error,
2389                    xmlSchemaPSVIIDCNodePtr idcNode,
2390                    xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2391                    const char *message,
2392                    const xmlChar *str1,
2393                    const xmlChar *str2)
2394 {
2395     xmlChar *msg = NULL, *qname = NULL;
2396
2397     msg = xmlStrdup(BAD_CAST "Element '%s': ");
2398     msg = xmlStrcat(msg, (const xmlChar *) message);
2399     msg = xmlStrcat(msg, BAD_CAST ".\n");
2400     xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
2401         error, NULL, idcNode->nodeLine, (const char *) msg,
2402         xmlSchemaFormatQName(&qname,
2403             vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2404             vctxt->nodeQNames->items[idcNode->nodeQNameID]),
2405         str1, str2, NULL);
2406     FREE_AND_NULL(qname);
2407     FREE_AND_NULL(msg);
2408 }
2409
2410 static int
2411 xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2412                            xmlNodePtr node)
2413 {
2414     if (node != NULL)
2415         return (node->type);
2416     if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2417         (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2418         return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2419     return (-1);
2420 }
2421
2422 static int
2423 xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2424 {
2425     switch (item->type) {
2426         case XML_SCHEMA_TYPE_COMPLEX:
2427         case XML_SCHEMA_TYPE_SIMPLE:
2428             if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2429                 return(1);
2430             break;
2431         case XML_SCHEMA_TYPE_GROUP:
2432             return (1);
2433         case XML_SCHEMA_TYPE_ELEMENT:
2434             if ( ((xmlSchemaElementPtr) item)->flags &
2435                 XML_SCHEMAS_ELEM_GLOBAL)
2436                 return(1);
2437             break;
2438         case XML_SCHEMA_TYPE_ATTRIBUTE:
2439             if ( ((xmlSchemaAttributePtr) item)->flags &
2440                 XML_SCHEMAS_ATTR_GLOBAL)
2441                 return(1);
2442             break;
2443         /* Note that attribute groups are always global. */
2444         default:
2445             return(1);
2446     }
2447     return (0);
2448 }
2449
2450 static void
2451 xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2452                        xmlParserErrors error,
2453                        xmlNodePtr node,
2454                        const xmlChar *value,
2455                        xmlSchemaTypePtr type,
2456                        int displayValue)
2457 {
2458     xmlChar *msg = NULL;
2459
2460     xmlSchemaFormatNodeForError(&msg, actxt, node);
2461
2462     if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2463             XML_ATTRIBUTE_NODE))
2464         msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2465     else
2466         msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2467             "value of ");
2468
2469     if (! xmlSchemaIsGlobalItem(type))
2470         msg = xmlStrcat(msg, BAD_CAST "the local ");
2471     else
2472         msg = xmlStrcat(msg, BAD_CAST "the ");
2473
2474     if (WXS_IS_ATOMIC(type))
2475         msg = xmlStrcat(msg, BAD_CAST "atomic type");
2476     else if (WXS_IS_LIST(type))
2477         msg = xmlStrcat(msg, BAD_CAST "list type");
2478     else if (WXS_IS_UNION(type))
2479         msg = xmlStrcat(msg, BAD_CAST "union type");
2480
2481     if (xmlSchemaIsGlobalItem(type)) {
2482         xmlChar *str = NULL;
2483         msg = xmlStrcat(msg, BAD_CAST " '");
2484         if (type->builtInType != 0) {
2485             msg = xmlStrcat(msg, BAD_CAST "xs:");
2486             str = xmlStrdup(type->name);
2487         } else {
2488             const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
2489             if (!str)
2490                 str = xmlStrdup(qName);
2491         }
2492         msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
2493         msg = xmlStrcat(msg, BAD_CAST "'");
2494         FREE_AND_NULL(str);
2495     }
2496     msg = xmlStrcat(msg, BAD_CAST ".\n");
2497     if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2498             XML_ATTRIBUTE_NODE))
2499         xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2500     else
2501         xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2502     FREE_AND_NULL(msg)
2503 }
2504
2505 static const xmlChar *
2506 xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2507                               xmlSchemaNodeInfoPtr ni,
2508                               xmlNodePtr node)
2509 {
2510     if (node != NULL) {
2511         if (node->ns != NULL)
2512             return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2513         else
2514             return (xmlSchemaFormatQName(str, NULL, node->name));
2515     } else if (ni != NULL)
2516         return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2517     return (NULL);
2518 }
2519
2520 static void
2521 xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2522                         xmlParserErrors error,
2523                         xmlSchemaAttrInfoPtr ni,
2524                         xmlNodePtr node)
2525 {
2526     xmlChar *msg = NULL, *str = NULL;
2527
2528     xmlSchemaFormatNodeForError(&msg, actxt, node);
2529     msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2530     xmlSchemaErr(actxt, error, node, (const char *) msg,
2531         xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2532         NULL);
2533     FREE_AND_NULL(str)
2534     FREE_AND_NULL(msg)
2535 }
2536
2537 static void LIBXML_ATTR_FORMAT(5,0)
2538 xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2539                         xmlParserErrors error,
2540                         xmlNodePtr node,
2541                         xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2542                         const char *message,
2543                         int nbval,
2544                         int nbneg,
2545                         xmlChar **values)
2546 {
2547     xmlChar *str = NULL, *msg = NULL;
2548     xmlChar *localName, *nsName;
2549     const xmlChar *cur, *end;
2550     int i;
2551
2552     xmlSchemaFormatNodeForError(&msg, actxt, node);
2553     msg = xmlStrcat(msg, (const xmlChar *) message);
2554     msg = xmlStrcat(msg, BAD_CAST ".");
2555     /*
2556     * Note that is does not make sense to report that we have a
2557     * wildcard here, since the wildcard might be unfolded into
2558     * multiple transitions.
2559     */
2560     if (nbval + nbneg > 0) {
2561         if (nbval + nbneg > 1) {
2562             str = xmlStrdup(BAD_CAST " Expected is one of ( ");
2563         } else
2564             str = xmlStrdup(BAD_CAST " Expected is ( ");
2565         nsName = NULL;
2566
2567         for (i = 0; i < nbval + nbneg; i++) {
2568             cur = values[i];
2569             if (cur == NULL)
2570                 continue;
2571             if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2572                 (cur[3] == ' ')) {
2573                 cur += 4;
2574                 str = xmlStrcat(str, BAD_CAST "##other");
2575             }
2576             /*
2577             * Get the local name.
2578             */
2579             localName = NULL;
2580
2581             end = cur;
2582             if (*end == '*') {
2583                 localName = xmlStrdup(BAD_CAST "*");
2584                 end++;
2585             } else {
2586                 while ((*end != 0) && (*end != '|'))
2587                     end++;
2588                 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
2589             }
2590             if (*end != 0) {
2591                 end++;
2592                 /*
2593                 * Skip "*|*" if they come with negated expressions, since
2594                 * they represent the same negated wildcard.
2595                 */
2596                 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2597                     /*
2598                     * Get the namespace name.
2599                     */
2600                     cur = end;
2601                     if (*end == '*') {
2602                         nsName = xmlStrdup(BAD_CAST "{*}");
2603                     } else {
2604                         while (*end != 0)
2605                             end++;
2606
2607                         if (i >= nbval)
2608                             nsName = xmlStrdup(BAD_CAST "{##other:");
2609                         else
2610                             nsName = xmlStrdup(BAD_CAST "{");
2611
2612                         nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2613                         nsName = xmlStrcat(nsName, BAD_CAST "}");
2614                     }
2615                     str = xmlStrcat(str, BAD_CAST nsName);
2616                     FREE_AND_NULL(nsName)
2617                 } else {
2618                     FREE_AND_NULL(localName);
2619                     continue;
2620                 }
2621             }
2622             str = xmlStrcat(str, BAD_CAST localName);
2623             FREE_AND_NULL(localName);
2624
2625             if (i < nbval + nbneg -1)
2626                 str = xmlStrcat(str, BAD_CAST ", ");
2627         }
2628         str = xmlStrcat(str, BAD_CAST " ).\n");
2629         msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
2630         FREE_AND_NULL(str)
2631     } else
2632       msg = xmlStrcat(msg, BAD_CAST "\n");
2633     xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2634     xmlFree(msg);
2635 }
2636
2637 static void LIBXML_ATTR_FORMAT(8,0)
2638 xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2639                   xmlParserErrors error,
2640                   xmlNodePtr node,
2641                   const xmlChar *value,
2642                   unsigned long length,
2643                   xmlSchemaTypePtr type,
2644                   xmlSchemaFacetPtr facet,
2645                   const char *message,
2646                   const xmlChar *str1,
2647                   const xmlChar *str2)
2648 {
2649     xmlChar *str = NULL, *msg = NULL;
2650     xmlSchemaTypeType facetType;
2651     int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2652
2653     xmlSchemaFormatNodeForError(&msg, actxt, node);
2654     if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2655         facetType = XML_SCHEMA_FACET_ENUMERATION;
2656         /*
2657         * If enumerations are validated, one must not expect the
2658         * facet to be given.
2659         */
2660     } else
2661         facetType = facet->type;
2662     msg = xmlStrcat(msg, BAD_CAST "[");
2663     msg = xmlStrcat(msg, BAD_CAST "facet '");
2664     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2665     msg = xmlStrcat(msg, BAD_CAST "'] ");
2666     if (message == NULL) {
2667         /*
2668         * Use a default message.
2669         */
2670         if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2671             (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2672             (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2673
2674             char len[25], actLen[25];
2675
2676             /* FIXME, TODO: What is the max expected string length of the
2677             * this value?
2678             */
2679             if (nodeType == XML_ATTRIBUTE_NODE)
2680                 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2681             else
2682                 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2683
2684             snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2685             snprintf(actLen, 24, "%lu", length);
2686
2687             if (facetType == XML_SCHEMA_FACET_LENGTH)
2688                 msg = xmlStrcat(msg,
2689                 BAD_CAST "this differs from the allowed length of '%s'.\n");
2690             else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2691                 msg = xmlStrcat(msg,
2692                 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2693             else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2694                 msg = xmlStrcat(msg,
2695                 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2696
2697             if (nodeType == XML_ATTRIBUTE_NODE)
2698                 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2699                     value, (const xmlChar *) actLen, (const xmlChar *) len);
2700             else
2701                 xmlSchemaErr(actxt, error, node, (const char *) msg,
2702                     (const xmlChar *) actLen, (const xmlChar *) len);
2703
2704         } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2705             msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2706                 "of the set {%s}.\n");
2707             xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2708                 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2709         } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2710             msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2711                 "by the pattern '%s'.\n");
2712             xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2713                 facet->value);
2714         } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2715             msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2716                 "minimum value allowed ('%s').\n");
2717             xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2718                 facet->value);
2719         } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2720             msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2721                 "maximum value allowed ('%s').\n");
2722             xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2723                 facet->value);
2724         } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2725             msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
2726                 "'%s'.\n");
2727             xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2728                 facet->value);
2729         } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2730             msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2731                 "'%s'.\n");
2732             xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2733                 facet->value);
2734         } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2735             msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2736                 "digits than are allowed ('%s').\n");
2737             xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2738                 facet->value);
2739         } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2740             msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2741                 "digits than are allowed ('%s').\n");
2742             xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2743                 facet->value);
2744         } else if (nodeType == XML_ATTRIBUTE_NODE) {
2745             msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2746             xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2747         } else {
2748             msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2749             xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2750         }
2751     } else {
2752         msg = xmlStrcat(msg, (const xmlChar *) message);
2753         msg = xmlStrcat(msg, BAD_CAST ".\n");
2754         xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2755     }
2756     FREE_AND_NULL(str)
2757     xmlFree(msg);
2758 }
2759
2760 #define VERROR(err, type, msg) \
2761     xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
2762
2763 #define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
2764
2765 #define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2766 #define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
2767
2768 #define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2769
2770
2771 /**
2772  * xmlSchemaPMissingAttrErr:
2773  * @ctxt: the schema validation context
2774  * @ownerDes: the designation of  the owner
2775  * @ownerName: the name of the owner
2776  * @ownerItem: the owner as a schema object
2777  * @ownerElem: the owner as an element node
2778  * @node: the parent element node of the missing attribute node
2779  * @type: the corresponding type of the attribute node
2780  *
2781  * Reports an illegal attribute.
2782  */
2783 static void
2784 xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
2785                          xmlParserErrors error,
2786                          xmlSchemaBasicItemPtr ownerItem,
2787                          xmlNodePtr ownerElem,
2788                          const char *name,
2789                          const char *message)
2790 {
2791     xmlChar *des = NULL;
2792
2793     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2794
2795     if (message != NULL)
2796         xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
2797     else
2798         xmlSchemaPErr(ctxt, ownerElem, error,
2799             "%s: The attribute '%s' is required but missing.\n",
2800             BAD_CAST des, BAD_CAST name);
2801     FREE_AND_NULL(des);
2802 }
2803
2804
2805 /**
2806  * xmlSchemaPResCompAttrErr:
2807  * @ctxt: the schema validation context
2808  * @error: the error code
2809  * @ownerDes: the designation of  the owner
2810  * @ownerItem: the owner as a schema object
2811  * @ownerElem: the owner as an element node
2812  * @name: the name of the attribute holding the QName
2813  * @refName: the referenced local name
2814  * @refURI: the referenced namespace URI
2815  * @message: optional message
2816  *
2817  * Used to report QName attribute values that failed to resolve
2818  * to schema components.
2819  */
2820 static void
2821 xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
2822                          xmlParserErrors error,
2823                          xmlSchemaBasicItemPtr ownerItem,
2824                          xmlNodePtr ownerElem,
2825                          const char *name,
2826                          const xmlChar *refName,
2827                          const xmlChar *refURI,
2828                          xmlSchemaTypeType refType,
2829                          const char *refTypeStr)
2830 {
2831     xmlChar *des = NULL, *strA = NULL;
2832
2833     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2834     if (refTypeStr == NULL)
2835         refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
2836         xmlSchemaPErrExt(ctxt, ownerElem, error,
2837             NULL, NULL, NULL,
2838             "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2839             "%s.\n", BAD_CAST des, BAD_CAST name,
2840             xmlSchemaFormatQName(&strA, refURI, refName),
2841             BAD_CAST refTypeStr, NULL);
2842     FREE_AND_NULL(des)
2843     FREE_AND_NULL(strA)
2844 }
2845
2846 /**
2847  * xmlSchemaPCustomAttrErr:
2848  * @ctxt: the schema parser context
2849  * @error: the error code
2850  * @ownerDes: the designation of the owner
2851  * @ownerItem: the owner as a schema object
2852  * @attr: the illegal attribute node
2853  *
2854  * Reports an illegal attribute during the parse.
2855  */
2856 static void
2857 xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
2858                         xmlParserErrors error,
2859                         xmlChar **ownerDes,
2860                         xmlSchemaBasicItemPtr ownerItem,
2861                         xmlAttrPtr attr,
2862                         const char *msg)
2863 {
2864     xmlChar *des = NULL;
2865
2866     if (ownerDes == NULL)
2867         xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
2868     else if (*ownerDes == NULL) {
2869         xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
2870         des = *ownerDes;
2871     } else
2872         des = *ownerDes;
2873     if (attr == NULL) {
2874         xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL,
2875             "%s, attribute '%s': %s.\n",
2876             BAD_CAST des, (const xmlChar *) "Unknown",
2877             (const xmlChar *) msg, NULL, NULL);
2878     } else {
2879         xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2880             "%s, attribute '%s': %s.\n",
2881             BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2882     }
2883     if (ownerDes == NULL)
2884         FREE_AND_NULL(des);
2885 }
2886
2887 /**
2888  * xmlSchemaPIllegalAttrErr:
2889  * @ctxt: the schema parser context
2890  * @error: the error code
2891  * @ownerDes: the designation of the attribute's owner
2892  * @ownerItem: the attribute's owner item
2893  * @attr: the illegal attribute node
2894  *
2895  * Reports an illegal attribute during the parse.
2896  */
2897 static void
2898 xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
2899                          xmlParserErrors error,
2900                          xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
2901                          xmlAttrPtr attr)
2902 {
2903     xmlChar *strA = NULL, *strB = NULL;
2904
2905     xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2906     xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2907         "%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2908         xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2909         NULL, NULL);
2910     FREE_AND_NULL(strA);
2911     FREE_AND_NULL(strB);
2912 }
2913
2914 /**
2915  * xmlSchemaPCustomErr:
2916  * @ctxt: the schema parser context
2917  * @error: the error code
2918  * @itemDes: the designation of the schema item
2919  * @item: the schema item
2920  * @itemElem: the node of the schema item
2921  * @message: the error message
2922  * @str1: an optional param for the error message
2923  * @str2: an optional param for the error message
2924  * @str3: an optional param for the error message
2925  *
2926  * Reports an error during parsing.
2927  */
2928 static void LIBXML_ATTR_FORMAT(5,0)
2929 xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
2930                     xmlParserErrors error,
2931                     xmlSchemaBasicItemPtr item,
2932                     xmlNodePtr itemElem,
2933                     const char *message,
2934                     const xmlChar *str1,
2935                     const xmlChar *str2,
2936                     const xmlChar *str3)
2937 {
2938     xmlChar *des = NULL, *msg = NULL;
2939
2940     xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
2941     msg = xmlStrdup(BAD_CAST "%s: ");
2942     msg = xmlStrcat(msg, (const xmlChar *) message);
2943     msg = xmlStrcat(msg, BAD_CAST ".\n");
2944     if ((itemElem == NULL) && (item != NULL))
2945         itemElem = WXS_ITEM_NODE(item);
2946     xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
2947         (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2948     FREE_AND_NULL(des);
2949     FREE_AND_NULL(msg);
2950 }
2951
2952 /**
2953  * xmlSchemaPCustomErr:
2954  * @ctxt: the schema parser context
2955  * @error: the error code
2956  * @itemDes: the designation of the schema item
2957  * @item: the schema item
2958  * @itemElem: the node of the schema item
2959  * @message: the error message
2960  * @str1: the optional param for the error message
2961  *
2962  * Reports an error during parsing.
2963  */
2964 static void LIBXML_ATTR_FORMAT(5,0)
2965 xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
2966                     xmlParserErrors error,
2967                     xmlSchemaBasicItemPtr item,
2968                     xmlNodePtr itemElem,
2969                     const char *message,
2970                     const xmlChar *str1)
2971 {
2972     xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
2973         str1, NULL, NULL);
2974 }
2975
2976 /**
2977  * xmlSchemaPAttrUseErr:
2978  * @ctxt: the schema parser context
2979  * @error: the error code
2980  * @itemDes: the designation of the schema type
2981  * @item: the schema type
2982  * @itemElem: the node of the schema type
2983  * @attr: the invalid schema attribute
2984  * @message: the error message
2985  * @str1: the optional param for the error message
2986  *
2987  * Reports an attribute use error during parsing.
2988  */
2989 static void LIBXML_ATTR_FORMAT(6,0)
2990 xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
2991                     xmlParserErrors error,
2992                     xmlNodePtr node,
2993                     xmlSchemaBasicItemPtr ownerItem,
2994                     const xmlSchemaAttributeUsePtr attruse,
2995                     const char *message,
2996                     const xmlChar *str1, const xmlChar *str2,
2997                     const xmlChar *str3,const xmlChar *str4)
2998 {
2999     xmlChar *str = NULL, *msg = NULL;
3000
3001     xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
3002     msg = xmlStrcat(msg, BAD_CAST ", ");
3003     msg = xmlStrcat(msg,
3004         BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
3005         WXS_BASIC_CAST attruse, NULL));
3006     FREE_AND_NULL(str);
3007     msg = xmlStrcat(msg, BAD_CAST ": ");
3008     msg = xmlStrcat(msg, (const xmlChar *) message);
3009     msg = xmlStrcat(msg, BAD_CAST ".\n");
3010     xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
3011         (const char *) msg, str1, str2, str3, str4);
3012     xmlFree(msg);
3013 }
3014
3015 /**
3016  * xmlSchemaPIllegalFacetAtomicErr:
3017  * @ctxt: the schema parser context
3018  * @error: the error code
3019  * @type: the schema type
3020  * @baseType: the base type of type
3021  * @facet: the illegal facet
3022  *
3023  * Reports an illegal facet for atomic simple types.
3024  */
3025 static void
3026 xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
3027                           xmlParserErrors error,
3028                           xmlSchemaTypePtr type,
3029                           xmlSchemaTypePtr baseType,
3030                           xmlSchemaFacetPtr facet)
3031 {
3032     xmlChar *des = NULL, *strT = NULL;
3033
3034     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
3035     xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
3036         "%s: The facet '%s' is not allowed on types derived from the "
3037         "type %s.\n",
3038         BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
3039         xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
3040         NULL, NULL);
3041     FREE_AND_NULL(des);
3042     FREE_AND_NULL(strT);
3043 }
3044
3045 /**
3046  * xmlSchemaPIllegalFacetListUnionErr:
3047  * @ctxt: the schema parser context
3048  * @error: the error code
3049  * @itemDes: the designation of the schema item involved
3050  * @item: the schema item involved
3051  * @facet: the illegal facet
3052  *
3053  * Reports an illegal facet for <list> and <union>.
3054  */
3055 static void
3056 xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
3057                           xmlParserErrors error,
3058                           xmlSchemaTypePtr type,
3059                           xmlSchemaFacetPtr facet)
3060 {
3061     xmlChar *des = NULL;
3062
3063     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3064         type->node);
3065     xmlSchemaPErr(ctxt, type->node, error,
3066         "%s: The facet '%s' is not allowed.\n",
3067         BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
3068     FREE_AND_NULL(des);
3069 }
3070
3071 /**
3072  * xmlSchemaPMutualExclAttrErr:
3073  * @ctxt: the schema validation context
3074  * @error: the error code
3075  * @elemDes: the designation of the parent element node
3076  * @attr: the bad attribute node
3077  * @type: the corresponding type of the attribute node
3078  *
3079  * Reports an illegal attribute.
3080  */
3081 static void
3082 xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3083                          xmlParserErrors error,
3084                          xmlSchemaBasicItemPtr ownerItem,
3085                          xmlAttrPtr attr,
3086                          const char *name1,
3087                          const char *name2)
3088 {
3089     xmlChar *des = NULL;
3090
3091     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
3092     xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
3093         "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
3094         BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
3095     FREE_AND_NULL(des);
3096 }
3097
3098 /**
3099  * xmlSchemaPSimpleTypeErr:
3100  * @ctxt:  the schema validation context
3101  * @error: the error code
3102  * @type: the type specifier
3103  * @ownerDes: the designation of the owner
3104  * @ownerItem: the schema object if existent
3105  * @node: the validated node
3106  * @value: the validated value
3107  *
3108  * Reports a simple type validation error.
3109  * TODO: Should this report the value of an element as well?
3110  */
3111 static void LIBXML_ATTR_FORMAT(8,0)
3112 xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3113                         xmlParserErrors error,
3114                         xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
3115                         xmlNodePtr node,
3116                         xmlSchemaTypePtr type,
3117                         const char *expected,
3118                         const xmlChar *value,
3119                         const char *message,
3120                         const xmlChar *str1,
3121                         const xmlChar *str2)
3122 {
3123     xmlChar *msg = NULL;
3124
3125     xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
3126     if (message == NULL) {
3127         /*
3128         * Use default messages.
3129         */
3130         if (type != NULL) {
3131             if (node->type == XML_ATTRIBUTE_NODE)
3132                 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3133             else
3134                 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3135                 "valid value of ");
3136             if (! xmlSchemaIsGlobalItem(type))
3137                 msg = xmlStrcat(msg, BAD_CAST "the local ");
3138             else
3139                 msg = xmlStrcat(msg, BAD_CAST "the ");
3140
3141             if (WXS_IS_ATOMIC(type))
3142                 msg = xmlStrcat(msg, BAD_CAST "atomic type");
3143             else if (WXS_IS_LIST(type))
3144                 msg = xmlStrcat(msg, BAD_CAST "list type");
3145             else if (WXS_IS_UNION(type))
3146                 msg = xmlStrcat(msg, BAD_CAST "union type");
3147
3148             if (xmlSchemaIsGlobalItem(type)) {
3149                 xmlChar *str = NULL;
3150                 msg = xmlStrcat(msg, BAD_CAST " '");
3151                 if (type->builtInType != 0) {
3152                     msg = xmlStrcat(msg, BAD_CAST "xs:");
3153                     str = xmlStrdup(type->name);
3154                 } else {
3155                     const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
3156                     if (!str)
3157                         str = xmlStrdup(qName);
3158                 }
3159                 msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
3160                 msg = xmlStrcat(msg, BAD_CAST "'.");
3161                 FREE_AND_NULL(str);
3162             }
3163         } else {
3164             if (node->type == XML_ATTRIBUTE_NODE)
3165                 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3166             else
3167                 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3168                 "valid.");
3169         }
3170         if (expected) {
3171             msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3172             xmlChar *expectedEscaped = xmlCharStrdup(expected);
3173             msg = xmlStrcat(msg, xmlEscapeFormatString(&expectedEscaped));
3174             FREE_AND_NULL(expectedEscaped);
3175             msg = xmlStrcat(msg, BAD_CAST "'.\n");
3176         } else
3177             msg = xmlStrcat(msg, BAD_CAST "\n");
3178         if (node->type == XML_ATTRIBUTE_NODE)
3179             xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3180         else
3181             xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3182     } else {
3183         msg = xmlStrcat(msg, BAD_CAST message);
3184         msg = xmlStrcat(msg, BAD_CAST ".\n");
3185         xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
3186              (const char*) msg, str1, str2, NULL, NULL, NULL);
3187     }
3188     /* Cleanup. */
3189     FREE_AND_NULL(msg)
3190 }
3191
3192 /**
3193  * xmlSchemaPContentErr:
3194  * @ctxt: the schema parser context
3195  * @error: the error code
3196  * @onwerDes: the designation of the holder of the content
3197  * @ownerItem: the owner item of the holder of the content
3198  * @ownerElem: the node of the holder of the content
3199  * @child: the invalid child node
3200  * @message: the optional error message
3201  * @content: the optional string describing the correct content
3202  *
3203  * Reports an error concerning the content of a schema element.
3204  */
3205 static void
3206 xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
3207                      xmlParserErrors error,
3208                      xmlSchemaBasicItemPtr ownerItem,
3209                      xmlNodePtr ownerElem,
3210                      xmlNodePtr child,
3211                      const char *message,
3212                      const char *content)
3213 {
3214     xmlChar *des = NULL;
3215
3216     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
3217     if (message != NULL)
3218         xmlSchemaPErr2(ctxt, ownerElem, child, error,
3219             "%s: %s.\n",
3220             BAD_CAST des, BAD_CAST message);
3221     else {
3222         if (content != NULL) {
3223             xmlSchemaPErr2(ctxt, ownerElem, child, error,
3224                 "%s: The content is not valid. Expected is %s.\n",
3225                 BAD_CAST des, BAD_CAST content);
3226         } else {
3227             xmlSchemaPErr2(ctxt, ownerElem, child, error,
3228                 "%s: The content is not valid.\n",
3229                 BAD_CAST des, NULL);
3230         }
3231     }
3232     FREE_AND_NULL(des)
3233 }
3234
3235 /************************************************************************
3236  *                                                                      *
3237  *                      Streamable error functions                      *
3238  *                                                                      *
3239  ************************************************************************/
3240
3241
3242
3243
3244 /************************************************************************
3245  *                                                                      *
3246  *                      Validation helper functions                     *
3247  *                                                                      *
3248  ************************************************************************/
3249
3250
3251 /************************************************************************
3252  *                                                                      *
3253  *                      Allocation functions                            *
3254  *                                                                      *
3255  ************************************************************************/
3256
3257 /**
3258  * xmlSchemaNewSchemaForParserCtxt:
3259  * @ctxt:  a schema validation context
3260  *
3261  * Allocate a new Schema structure.
3262  *
3263  * Returns the newly allocated structure or NULL in case or error
3264  */
3265 static xmlSchemaPtr
3266 xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3267 {
3268     xmlSchemaPtr ret;
3269
3270     ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3271     if (ret == NULL) {
3272         xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
3273         return (NULL);
3274     }
3275     memset(ret, 0, sizeof(xmlSchema));
3276     ret->dict = ctxt->dict;
3277     xmlDictReference(ret->dict);
3278
3279     return (ret);
3280 }
3281
3282 /**
3283  * xmlSchemaNewFacet:
3284  *
3285  * Allocate a new Facet structure.
3286  *
3287  * Returns the newly allocated structure or NULL in case or error
3288  */
3289 xmlSchemaFacetPtr
3290 xmlSchemaNewFacet(void)
3291 {
3292     xmlSchemaFacetPtr ret;
3293
3294     ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3295     if (ret == NULL) {
3296         return (NULL);
3297     }
3298     memset(ret, 0, sizeof(xmlSchemaFacet));
3299
3300     return (ret);
3301 }
3302
3303 /**
3304  * xmlSchemaNewAnnot:
3305  * @ctxt:  a schema validation context
3306  * @node:  a node
3307  *
3308  * Allocate a new annotation structure.
3309  *
3310  * Returns the newly allocated structure or NULL in case or error
3311  */
3312 static xmlSchemaAnnotPtr
3313 xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3314 {
3315     xmlSchemaAnnotPtr ret;
3316
3317     ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3318     if (ret == NULL) {
3319         xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
3320         return (NULL);
3321     }
3322     memset(ret, 0, sizeof(xmlSchemaAnnot));
3323     ret->content = node;
3324     return (ret);
3325 }
3326
3327 static xmlSchemaItemListPtr
3328 xmlSchemaItemListCreate(void)
3329 {
3330     xmlSchemaItemListPtr ret;
3331
3332     ret = xmlMalloc(sizeof(xmlSchemaItemList));
3333     if (ret == NULL) {
3334         xmlSchemaPErrMemory(NULL,
3335             "allocating an item list structure", NULL);
3336         return (NULL);
3337     }
3338     memset(ret, 0, sizeof(xmlSchemaItemList));
3339     return (ret);
3340 }
3341
3342 static void
3343 xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3344 {
3345     if (list->items != NULL) {
3346         xmlFree(list->items);
3347         list->items = NULL;
3348     }
3349     list->nbItems = 0;
3350     list->sizeItems = 0;
3351 }
3352
3353 static int
3354 xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3355 {
3356     if (list->items == NULL) {
3357         list->items = (void **) xmlMalloc(
3358             20 * sizeof(void *));
3359         if (list->items == NULL) {
3360             xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3361             return(-1);
3362         }
3363         list->sizeItems = 20;
3364     } else if (list->sizeItems <= list->nbItems) {
3365         list->sizeItems *= 2;
3366         list->items = (void **) xmlRealloc(list->items,
3367             list->sizeItems * sizeof(void *));
3368         if (list->items == NULL) {
3369             xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3370             list->sizeItems = 0;
3371             return(-1);
3372         }
3373     }
3374     list->items[list->nbItems++] = item;
3375     return(0);
3376 }
3377
3378 static int
3379 xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3380                          int initialSize,
3381                          void *item)
3382 {
3383     if (list->items == NULL) {
3384         if (initialSize <= 0)
3385             initialSize = 1;
3386         list->items = (void **) xmlMalloc(
3387             initialSize * sizeof(void *));
3388         if (list->items == NULL) {
3389             xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3390             return(-1);
3391         }
3392         list->sizeItems = initialSize;
3393     } else if (list->sizeItems <= list->nbItems) {
3394         list->sizeItems *= 2;
3395         list->items = (void **) xmlRealloc(list->items,
3396             list->sizeItems * sizeof(void *));
3397         if (list->items == NULL) {
3398             xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3399             list->sizeItems = 0;
3400             return(-1);
3401         }
3402     }
3403     list->items[list->nbItems++] = item;
3404     return(0);
3405 }
3406
3407 static int
3408 xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3409 {
3410     if (list->items == NULL) {
3411         list->items = (void **) xmlMalloc(
3412             20 * sizeof(void *));
3413         if (list->items == NULL) {
3414             xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3415             return(-1);
3416         }
3417         list->sizeItems = 20;
3418     } else if (list->sizeItems <= list->nbItems) {
3419         list->sizeItems *= 2;
3420         list->items = (void **) xmlRealloc(list->items,
3421             list->sizeItems * sizeof(void *));
3422         if (list->items == NULL) {
3423             xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3424             list->sizeItems = 0;
3425             return(-1);
3426         }
3427     }
3428     /*
3429     * Just append if the index is greater/equal than the item count.
3430     */
3431     if (idx >= list->nbItems) {
3432         list->items[list->nbItems++] = item;
3433     } else {
3434         int i;
3435         for (i = list->nbItems; i > idx; i--)
3436             list->items[i] = list->items[i-1];
3437         list->items[idx] = item;
3438         list->nbItems++;
3439     }
3440     return(0);
3441 }
3442
3443 #if 0 /* enable if ever needed */
3444 static int
3445 xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3446                             int initialSize,
3447                             void *item,
3448                             int idx)
3449 {
3450     if (list->items == NULL) {
3451         if (initialSize <= 0)
3452             initialSize = 1;
3453         list->items = (void **) xmlMalloc(
3454             initialSize * sizeof(void *));
3455         if (list->items == NULL) {
3456             xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3457             return(-1);
3458         }
3459         list->sizeItems = initialSize;
3460     } else if (list->sizeItems <= list->nbItems) {
3461         list->sizeItems *= 2;
3462         list->items = (void **) xmlRealloc(list->items,
3463             list->sizeItems * sizeof(void *));
3464         if (list->items == NULL) {
3465             xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3466             list->sizeItems = 0;
3467             return(-1);
3468         }
3469     }
3470     /*
3471     * Just append if the index is greater/equal than the item count.
3472     */
3473     if (idx >= list->nbItems) {
3474         list->items[list->nbItems++] = item;
3475     } else {
3476         int i;
3477         for (i = list->nbItems; i > idx; i--)
3478             list->items[i] = list->items[i-1];
3479         list->items[idx] = item;
3480         list->nbItems++;
3481     }
3482     return(0);
3483 }
3484 #endif
3485
3486 static int
3487 xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3488 {
3489     int i;
3490     if ((list->items == NULL) || (idx >= list->nbItems)) {
3491         xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3492             "index error.\n");
3493         return(-1);
3494     }
3495
3496     if (list->nbItems == 1) {
3497         /* TODO: Really free the list? */
3498         xmlFree(list->items);
3499         list->items = NULL;
3500         list->nbItems = 0;
3501         list->sizeItems = 0;
3502     } else if (list->nbItems -1 == idx) {
3503         list->nbItems--;
3504     } else {
3505         for (i = idx; i < list->nbItems -1; i++)
3506             list->items[i] = list->items[i+1];
3507         list->nbItems--;
3508     }
3509     return(0);
3510 }
3511
3512 /**
3513  * xmlSchemaItemListFree:
3514  * @annot:  a schema type structure
3515  *
3516  * Deallocate a annotation structure
3517  */
3518 static void
3519 xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3520 {
3521     if (list == NULL)
3522         return;
3523     if (list->items != NULL)
3524         xmlFree(list->items);
3525     xmlFree(list);
3526 }
3527
3528 static void
3529 xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
3530 {
3531     if (bucket == NULL)
3532         return;
3533     if (bucket->globals != NULL) {
3534         xmlSchemaComponentListFree(bucket->globals);
3535         xmlSchemaItemListFree(bucket->globals);
3536     }
3537     if (bucket->locals != NULL) {
3538         xmlSchemaComponentListFree(bucket->locals);
3539         xmlSchemaItemListFree(bucket->locals);
3540     }
3541     if (bucket->relations != NULL) {
3542         xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3543         do {
3544             prev = cur;
3545             cur = cur->next;
3546             xmlFree(prev);
3547         } while (cur != NULL);
3548     }
3549     if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3550         xmlFreeDoc(bucket->doc);
3551     }
3552     if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
3553         if (WXS_IMPBUCKET(bucket)->schema != NULL)
3554             xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
3555     }
3556     xmlFree(bucket);
3557 }
3558
3559 static xmlSchemaBucketPtr
3560 xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
3561                          int type, const xmlChar *targetNamespace)
3562 {
3563     xmlSchemaBucketPtr ret;
3564     int size;
3565     xmlSchemaPtr mainSchema;
3566
3567     if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
3568         PERROR_INT("xmlSchemaBucketCreate",
3569             "no main schema on constructor");
3570         return(NULL);
3571     }
3572     mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
3573     /* Create the schema bucket. */
3574     if (WXS_IS_BUCKET_INCREDEF(type))
3575         size = sizeof(xmlSchemaInclude);
3576     else
3577         size = sizeof(xmlSchemaImport);
3578     ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3579     if (ret == NULL) {
3580         xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3581         return(NULL);
3582     }
3583     memset(ret, 0, size);
3584     ret->targetNamespace = targetNamespace;
3585     ret->type = type;
3586     ret->globals = xmlSchemaItemListCreate();
3587     if (ret->globals == NULL) {
3588         xmlFree(ret);
3589         return(NULL);
3590     }
3591     ret->locals = xmlSchemaItemListCreate();
3592     if (ret->locals == NULL) {
3593         xmlFree(ret);
3594         return(NULL);
3595     }
3596     /*
3597     * The following will assure that only the first bucket is marked as
3598     * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3599     * For each following import buckets an xmlSchema will be created.
3600     * An xmlSchema will be created for every distinct targetNamespace.
3601     * We assign the targetNamespace to the schemata here.
3602     */
3603     if (! WXS_HAS_BUCKETS(pctxt)) {
3604         if (WXS_IS_BUCKET_INCREDEF(type)) {
3605             PERROR_INT("xmlSchemaBucketCreate",
3606                 "first bucket but it's an include or redefine");
3607             xmlSchemaBucketFree(ret);
3608             return(NULL);
3609         }
3610         /* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3611         ret->type = XML_SCHEMA_SCHEMA_MAIN;
3612         /* Point to the *main* schema. */
3613         WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3614         WXS_IMPBUCKET(ret)->schema = mainSchema;
3615         /*
3616         * Ensure that the main schema gets a targetNamespace.
3617         */
3618         mainSchema->targetNamespace = targetNamespace;
3619     } else {
3620         if (type == XML_SCHEMA_SCHEMA_MAIN) {
3621             PERROR_INT("xmlSchemaBucketCreate",
3622                 "main bucket but it's not the first one");
3623             xmlSchemaBucketFree(ret);
3624             return(NULL);
3625         } else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3626             /*
3627             * Create a schema for imports and assign the
3628             * targetNamespace.
3629             */
3630             WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3631             if (WXS_IMPBUCKET(ret)->schema == NULL) {
3632                 xmlSchemaBucketFree(ret);
3633                 return(NULL);
3634             }
3635             WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
3636         }
3637     }
3638     if (WXS_IS_BUCKET_IMPMAIN(type)) {
3639         int res;
3640         /*
3641         * Imports go into the "schemasImports" slot of the main *schema*.
3642         * Note that we create an import entry for the main schema as well; i.e.,
3643         * even if there's only one schema, we'll get an import.
3644         */
3645         if (mainSchema->schemasImports == NULL) {
3646             mainSchema->schemasImports = xmlHashCreateDict(5,
3647                 WXS_CONSTRUCTOR(pctxt)->dict);
3648             if (mainSchema->schemasImports == NULL) {
3649                 xmlSchemaBucketFree(ret);
3650                 return(NULL);
3651             }
3652         }
3653         if (targetNamespace == NULL)
3654             res = xmlHashAddEntry(mainSchema->schemasImports,
3655                 XML_SCHEMAS_NO_NAMESPACE, ret);
3656         else
3657             res = xmlHashAddEntry(mainSchema->schemasImports,
3658                 targetNamespace, ret);
3659         if (res != 0) {
3660             PERROR_INT("xmlSchemaBucketCreate",
3661                 "failed to add the schema bucket to the hash");
3662             xmlSchemaBucketFree(ret);
3663             return(NULL);
3664         }
3665     } else {
3666         /* Set the @ownerImport of an include bucket. */
3667         if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3668             WXS_INCBUCKET(ret)->ownerImport =
3669                 WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
3670         else
3671             WXS_INCBUCKET(ret)->ownerImport =
3672                 WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
3673
3674         /* Includes got into the "includes" slot of the *main* schema. */
3675         if (mainSchema->includes == NULL) {
3676             mainSchema->includes = xmlSchemaItemListCreate();
3677             if (mainSchema->includes == NULL) {
3678                 xmlSchemaBucketFree(ret);
3679                 return(NULL);
3680             }
3681         }
3682         xmlSchemaItemListAdd(mainSchema->includes, ret);
3683     }
3684     /*
3685     * Add to list of all buckets; this is used for lookup
3686     * during schema construction time only.
3687     */
3688     if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
3689         return(NULL);
3690     return(ret);
3691 }
3692
3693 static int
3694 xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
3695 {
3696     if (*list == NULL) {
3697         *list = xmlSchemaItemListCreate();
3698         if (*list == NULL)
3699             return(-1);
3700     }
3701     xmlSchemaItemListAddSize(*list, initialSize, item);
3702     return(0);
3703 }
3704
3705 /**
3706  * xmlSchemaFreeAnnot:
3707  * @annot:  a schema type structure
3708  *
3709  * Deallocate a annotation structure
3710  */
3711 static void
3712 xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3713 {
3714     if (annot == NULL)
3715         return;
3716     if (annot->next == NULL) {
3717         xmlFree(annot);
3718     } else {
3719         xmlSchemaAnnotPtr prev;
3720
3721         do {
3722             prev = annot;
3723             annot = annot->next;
3724             xmlFree(prev);
3725         } while (annot != NULL);
3726     }
3727 }
3728
3729 /**
3730  * xmlSchemaFreeNotation:
3731  * @schema:  a schema notation structure
3732  *
3733  * Deallocate a Schema Notation structure.
3734  */
3735 static void
3736 xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3737 {
3738     if (nota == NULL)
3739         return;
3740     xmlFree(nota);
3741 }
3742
3743 /**
3744  * xmlSchemaFreeAttribute:
3745  * @attr:  an attribute declaration
3746  *
3747  * Deallocates an attribute declaration structure.
3748  */
3749 static void
3750 xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3751 {
3752     if (attr == NULL)
3753         return;
3754     if (attr->annot != NULL)
3755         xmlSchemaFreeAnnot(attr->annot);
3756     if (attr->defVal != NULL)
3757         xmlSchemaFreeValue(attr->defVal);
3758     xmlFree(attr);
3759 }
3760
3761 /**
3762  * xmlSchemaFreeAttributeUse:
3763  * @use:  an attribute use
3764  *
3765  * Deallocates an attribute use structure.
3766  */
3767 static void
3768 xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3769 {
3770     if (use == NULL)
3771         return;
3772     if (use->annot != NULL)
3773         xmlSchemaFreeAnnot(use->annot);
3774     if (use->defVal != NULL)
3775         xmlSchemaFreeValue(use->defVal);
3776     xmlFree(use);
3777 }
3778
3779 /**
3780  * xmlSchemaFreeAttributeUseProhib:
3781  * @prohib:  an attribute use prohibition
3782  *
3783  * Deallocates an attribute use structure.
3784  */
3785 static void
3786 xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3787 {
3788     if (prohib == NULL)
3789         return;
3790     xmlFree(prohib);
3791 }
3792
3793 /**
3794  * xmlSchemaFreeWildcardNsSet:
3795  * set:  a schema wildcard namespace
3796  *
3797  * Deallocates a list of wildcard constraint structures.
3798  */
3799 static void
3800 xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3801 {
3802     xmlSchemaWildcardNsPtr next;
3803
3804     while (set != NULL) {
3805         next = set->next;
3806         xmlFree(set);
3807         set = next;
3808     }
3809 }
3810
3811 /**
3812  * xmlSchemaFreeWildcard:
3813  * @wildcard:  a wildcard structure
3814  *
3815  * Deallocates a wildcard structure.
3816  */
3817 void
3818 xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3819 {
3820     if (wildcard == NULL)
3821         return;
3822     if (wildcard->annot != NULL)
3823         xmlSchemaFreeAnnot(wildcard->annot);
3824     if (wildcard->nsSet != NULL)
3825         xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3826     if (wildcard->negNsSet != NULL)
3827         xmlFree(wildcard->negNsSet);
3828     xmlFree(wildcard);
3829 }
3830
3831 /**
3832  * xmlSchemaFreeAttributeGroup:
3833  * @schema:  a schema attribute group structure
3834  *
3835  * Deallocate a Schema Attribute Group structure.
3836  */
3837 static void
3838 xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
3839 {
3840     if (attrGr == NULL)
3841         return;
3842     if (attrGr->annot != NULL)
3843         xmlSchemaFreeAnnot(attrGr->annot);
3844     if (attrGr->attrUses != NULL)
3845         xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3846     xmlFree(attrGr);
3847 }
3848
3849 /**
3850  * xmlSchemaFreeQNameRef:
3851  * @item: a QName reference structure
3852  *
3853  * Deallocatea a QName reference structure.
3854  */
3855 static void
3856 xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3857 {
3858     xmlFree(item);
3859 }
3860
3861 /**
3862  * xmlSchemaFreeTypeLinkList:
3863  * @alink: a type link
3864  *
3865  * Deallocate a list of types.
3866  */
3867 static void
3868 xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3869 {
3870     xmlSchemaTypeLinkPtr next;
3871
3872     while (link != NULL) {
3873         next = link->next;
3874         xmlFree(link);
3875         link = next;
3876     }
3877 }
3878
3879 static void
3880 xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3881 {
3882     xmlSchemaIDCStateObjPtr next;
3883     while (sto != NULL) {
3884         next = sto->next;
3885         if (sto->history != NULL)
3886             xmlFree(sto->history);
3887         if (sto->xpathCtxt != NULL)
3888             xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3889         xmlFree(sto);
3890         sto = next;
3891     }
3892 }
3893
3894 /**
3895  * xmlSchemaFreeIDC:
3896  * @idc: a identity-constraint definition
3897  *
3898  * Deallocates an identity-constraint definition.
3899  */
3900 static void
3901 xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3902 {
3903     xmlSchemaIDCSelectPtr cur, prev;
3904
3905     if (idcDef == NULL)
3906         return;
3907     if (idcDef->annot != NULL)
3908         xmlSchemaFreeAnnot(idcDef->annot);
3909     /* Selector */
3910     if (idcDef->selector != NULL) {
3911         if (idcDef->selector->xpathComp != NULL)
3912             xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3913         xmlFree(idcDef->selector);
3914     }
3915     /* Fields */
3916     if (idcDef->fields != NULL) {
3917         cur = idcDef->fields;
3918         do {
3919             prev = cur;
3920             cur = cur->next;
3921             if (prev->xpathComp != NULL)
3922                 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
3923             xmlFree(prev);
3924         } while (cur != NULL);
3925     }
3926     xmlFree(idcDef);
3927 }
3928
3929 /**
3930  * xmlSchemaFreeElement:
3931  * @schema:  a schema element structure
3932  *
3933  * Deallocate a Schema Element structure.
3934  */
3935 static void
3936 xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3937 {
3938     if (elem == NULL)
3939         return;
3940     if (elem->annot != NULL)
3941         xmlSchemaFreeAnnot(elem->annot);
3942     if (elem->contModel != NULL)
3943         xmlRegFreeRegexp(elem->contModel);
3944     if (elem->defVal != NULL)
3945         xmlSchemaFreeValue(elem->defVal);
3946     xmlFree(elem);
3947 }
3948
3949 /**
3950  * xmlSchemaFreeFacet:
3951  * @facet:  a schema facet structure
3952  *
3953  * Deallocate a Schema Facet structure.
3954  */
3955 void
3956 xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3957 {
3958     if (facet == NULL)
3959         return;
3960     if (facet->val != NULL)
3961         xmlSchemaFreeValue(facet->val);
3962     if (facet->regexp != NULL)
3963         xmlRegFreeRegexp(facet->regexp);
3964     if (facet->annot != NULL)
3965         xmlSchemaFreeAnnot(facet->annot);
3966     xmlFree(facet);
3967 }
3968
3969 /**
3970  * xmlSchemaFreeType:
3971  * @type:  a schema type structure
3972  *
3973  * Deallocate a Schema Type structure.
3974  */
3975 void
3976 xmlSchemaFreeType(xmlSchemaTypePtr type)
3977 {
3978     if (type == NULL)
3979         return;
3980     if (type->annot != NULL)
3981         xmlSchemaFreeAnnot(type->annot);
3982     if (type->facets != NULL) {
3983         xmlSchemaFacetPtr facet, next;
3984
3985         facet = type->facets;
3986         while (facet != NULL) {
3987             next = facet->next;
3988             xmlSchemaFreeFacet(facet);
3989             facet = next;
3990         }
3991     }
3992     if (type->attrUses != NULL)
3993         xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
3994     if (type->memberTypes != NULL)
3995         xmlSchemaFreeTypeLinkList(type->memberTypes);
3996     if (type->facetSet != NULL) {
3997         xmlSchemaFacetLinkPtr next, link;
3998
3999         link = type->facetSet;
4000         do {
4001             next = link->next;
4002             xmlFree(link);
4003             link = next;
4004         } while (link != NULL);
4005     }
4006     if (type->contModel != NULL)
4007         xmlRegFreeRegexp(type->contModel);
4008     xmlFree(type);
4009 }
4010
4011 /**
4012  * xmlSchemaFreeModelGroupDef:
4013  * @item:  a schema model group definition
4014  *
4015  * Deallocates a schema model group definition.
4016  */
4017 static void
4018 xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
4019 {
4020     if (item->annot != NULL)
4021         xmlSchemaFreeAnnot(item->annot);
4022     xmlFree(item);
4023 }
4024
4025 /**
4026  * xmlSchemaFreeModelGroup:
4027  * @item:  a schema model group
4028  *
4029  * Deallocates a schema model group structure.
4030  */
4031 static void
4032 xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
4033 {
4034     if (item->annot != NULL)
4035         xmlSchemaFreeAnnot(item->annot);
4036     xmlFree(item);
4037 }
4038
4039 static void
4040 xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
4041 {
4042     if ((list == NULL) || (list->nbItems == 0))
4043         return;
4044     {
4045         xmlSchemaTreeItemPtr item;
4046         xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
4047         int i;
4048
4049         for (i = 0; i < list->nbItems; i++) {
4050             item = items[i];
4051             if (item == NULL)
4052                 continue;
4053             switch (item->type) {
4054                 case XML_SCHEMA_TYPE_SIMPLE:
4055                 case XML_SCHEMA_TYPE_COMPLEX:
4056                     xmlSchemaFreeType((xmlSchemaTypePtr) item);
4057                     break;
4058                 case XML_SCHEMA_TYPE_ATTRIBUTE:
4059                     xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
4060                     break;
4061                 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
4062                     xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
4063                     break;
4064                 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
4065                     xmlSchemaFreeAttributeUseProhib(
4066                         (xmlSchemaAttributeUseProhibPtr) item);
4067                     break;
4068                 case XML_SCHEMA_TYPE_ELEMENT:
4069                     xmlSchemaFreeElement((xmlSchemaElementPtr) item);
4070                     break;
4071                 case XML_SCHEMA_TYPE_PARTICLE:
4072                     if (item->annot != NULL)
4073                         xmlSchemaFreeAnnot(item->annot);
4074                     xmlFree(item);
4075                     break;
4076                 case XML_SCHEMA_TYPE_SEQUENCE:
4077                 case XML_SCHEMA_TYPE_CHOICE:
4078                 case XML_SCHEMA_TYPE_ALL:
4079                     xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4080                     break;
4081                 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4082                     xmlSchemaFreeAttributeGroup(
4083                         (xmlSchemaAttributeGroupPtr) item);
4084                     break;
4085                 case XML_SCHEMA_TYPE_GROUP:
4086                     xmlSchemaFreeModelGroupDef(
4087                         (xmlSchemaModelGroupDefPtr) item);
4088                     break;
4089                 case XML_SCHEMA_TYPE_ANY:
4090                 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4091                     xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4092                     break;
4093                 case XML_SCHEMA_TYPE_IDC_KEY:
4094                 case XML_SCHEMA_TYPE_IDC_UNIQUE:
4095                 case XML_SCHEMA_TYPE_IDC_KEYREF:
4096                     xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4097                     break;
4098                 case XML_SCHEMA_TYPE_NOTATION:
4099                     xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4100                     break;
4101                 case XML_SCHEMA_EXTRA_QNAMEREF:
4102                     xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4103                     break;
4104                 default: {
4105                     /* TODO: This should never be hit. */
4106                     xmlSchemaPSimpleInternalErr(NULL,
4107                         "Internal error: xmlSchemaComponentListFree, "
4108                         "unexpected component type '%s'\n",
4109                         (const xmlChar *) WXS_ITEM_TYPE_NAME(item));
4110                          }
4111                     break;
4112             }
4113         }
4114         list->nbItems = 0;
4115     }
4116 }
4117
4118 /**
4119  * xmlSchemaFree:
4120  * @schema:  a schema structure
4121  *
4122  * Deallocate a Schema structure.
4123  */
4124 void
4125 xmlSchemaFree(xmlSchemaPtr schema)
4126 {
4127     if (schema == NULL)
4128         return;
4129     /* @volatiles is not used anymore :-/ */
4130     if (schema->volatiles != NULL)
4131         TODO
4132     /*
4133     * Note that those slots are not responsible for freeing
4134     * schema components anymore; this will now be done by
4135     * the schema buckets.
4136     */
4137     if (schema->notaDecl != NULL)
4138         xmlHashFree(schema->notaDecl, NULL);
4139     if (schema->attrDecl != NULL)
4140         xmlHashFree(schema->attrDecl, NULL);
4141     if (schema->attrgrpDecl != NULL)
4142         xmlHashFree(schema->attrgrpDecl, NULL);
4143     if (schema->elemDecl != NULL)
4144         xmlHashFree(schema->elemDecl, NULL);
4145     if (schema->typeDecl != NULL)
4146         xmlHashFree(schema->typeDecl, NULL);
4147     if (schema->groupDecl != NULL)
4148         xmlHashFree(schema->groupDecl, NULL);
4149     if (schema->idcDef != NULL)
4150         xmlHashFree(schema->idcDef, NULL);
4151
4152     if (schema->schemasImports != NULL)
4153         xmlHashFree(schema->schemasImports,
4154                     (xmlHashDeallocator) xmlSchemaBucketFree);
4155     if (schema->includes != NULL) {
4156         xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4157         int i;
4158         for (i = 0; i < list->nbItems; i++) {
4159             xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4160         }
4161         xmlSchemaItemListFree(list);
4162     }
4163     if (schema->annot != NULL)
4164         xmlSchemaFreeAnnot(schema->annot);
4165     /* Never free the doc here, since this will be done by the buckets. */
4166
4167     xmlDictFree(schema->dict);
4168     xmlFree(schema);
4169 }
4170
4171 /************************************************************************
4172  *                                                                      *
4173  *                      Debug functions                                 *
4174  *                                                                      *
4175  ************************************************************************/
4176
4177 #ifdef LIBXML_OUTPUT_ENABLED
4178
4179 static void
4180 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4181
4182 /**
4183  * xmlSchemaElementDump:
4184  * @elem:  an element
4185  * @output:  the file output
4186  *
4187  * Dump the element
4188  */
4189 static void
4190 xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
4191                      const xmlChar * name ATTRIBUTE_UNUSED,
4192                      const xmlChar * namespace ATTRIBUTE_UNUSED,
4193                      const xmlChar * context ATTRIBUTE_UNUSED)
4194 {
4195     if (elem == NULL)
4196         return;
4197
4198
4199     fprintf(output, "Element");
4200     if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4201         fprintf(output, " (global)");
4202     fprintf(output, ": '%s' ", elem->name);
4203     if (namespace != NULL)
4204         fprintf(output, "ns '%s'", namespace);
4205     fprintf(output, "\n");
4206 #if 0
4207     if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
4208         fprintf(output, "  min %d ", elem->minOccurs);
4209         if (elem->maxOccurs >= UNBOUNDED)
4210             fprintf(output, "max: unbounded\n");
4211         else if (elem->maxOccurs != 1)
4212             fprintf(output, "max: %d\n", elem->maxOccurs);
4213         else
4214             fprintf(output, "\n");
4215     }
4216 #endif
4217     /*
4218     * Misc other properties.
4219     */
4220     if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4221         (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4222         (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
4223         (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
4224         fprintf(output, "  props: ");
4225         if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4226             fprintf(output, "[fixed] ");
4227         if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4228             fprintf(output, "[default] ");
4229         if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4230             fprintf(output, "[abstract] ");
4231         if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4232             fprintf(output, "[nillable] ");
4233         fprintf(output, "\n");
4234     }
4235     /*
4236     * Default/fixed value.
4237     */
4238     if (elem->value != NULL)
4239         fprintf(output, "  value: '%s'\n", elem->value);
4240     /*
4241     * Type.
4242     */
4243     if (elem->namedType != NULL) {
4244         fprintf(output, "  type: '%s' ", elem->namedType);
4245         if (elem->namedTypeNs != NULL)
4246             fprintf(output, "ns '%s'\n", elem->namedTypeNs);
4247         else
4248             fprintf(output, "\n");
4249     } else if (elem->subtypes != NULL) {
4250         /*
4251         * Dump local types.
4252         */
4253         xmlSchemaTypeDump(elem->subtypes, output);
4254     }
4255     /*
4256     * Substitution group.
4257     */
4258     if (elem->substGroup != NULL) {
4259         fprintf(output, "  substitutionGroup: '%s' ", elem->substGroup);
4260         if (elem->substGroupNs != NULL)
4261             fprintf(output, "ns '%s'\n", elem->substGroupNs);
4262         else
4263             fprintf(output, "\n");
4264     }
4265 }
4266
4267 /**
4268  * xmlSchemaAnnotDump:
4269  * @output:  the file output
4270  * @annot:  a annotation
4271  *
4272  * Dump the annotation
4273  */
4274 static void
4275 xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4276 {
4277     xmlChar *content;
4278
4279     if (annot == NULL)
4280         return;
4281
4282     content = xmlNodeGetContent(annot->content);
4283     if (content != NULL) {
4284         fprintf(output, "  Annot: %s\n", content);
4285         xmlFree(content);
4286     } else
4287         fprintf(output, "  Annot: empty\n");
4288 }
4289
4290 /**
4291  * xmlSchemaContentModelDump:
4292  * @particle: the schema particle
4293  * @output: the file output
4294  * @depth: the depth used for intentation
4295  *
4296  * Dump a SchemaType structure
4297  */
4298 static void
4299 xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4300 {
4301     xmlChar *str = NULL;
4302     xmlSchemaTreeItemPtr term;
4303     char shift[100];
4304     int i;
4305
4306     if (particle == NULL)
4307         return;
4308     for (i = 0;((i < depth) && (i < 25));i++)
4309         shift[2 * i] = shift[2 * i + 1] = ' ';
4310     shift[2 * i] = shift[2 * i + 1] = 0;
4311     fprintf(output, "%s", shift);
4312     if (particle->children == NULL) {
4313         fprintf(output, "MISSING particle term\n");
4314         return;
4315     }
4316     term = particle->children;
4317     if (term == NULL) {
4318         fprintf(output, "(NULL)");
4319     } else {
4320         switch (term->type) {
4321             case XML_SCHEMA_TYPE_ELEMENT:
4322                 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4323                     ((xmlSchemaElementPtr)term)->targetNamespace,
4324                     ((xmlSchemaElementPtr)term)->name));
4325                 FREE_AND_NULL(str);
4326                 break;
4327             case XML_SCHEMA_TYPE_SEQUENCE:
4328                 fprintf(output, "SEQUENCE");
4329                 break;
4330             case XML_SCHEMA_TYPE_CHOICE:
4331                 fprintf(output, "CHOICE");
4332                 break;
4333             case XML_SCHEMA_TYPE_ALL:
4334                 fprintf(output, "ALL");
4335                 break;
4336             case XML_SCHEMA_TYPE_ANY:
4337                 fprintf(output, "ANY");
4338                 break;
4339             default:
4340                 fprintf(output, "UNKNOWN\n");
4341                 return;
4342         }
4343     }
4344     if (particle->minOccurs != 1)
4345         fprintf(output, " min: %d", particle->minOccurs);
4346     if (particle->maxOccurs >= UNBOUNDED)
4347         fprintf(output, " max: unbounded");
4348     else if (particle->maxOccurs != 1)
4349         fprintf(output, " max: %d", particle->maxOccurs);
4350     fprintf(output, "\n");
4351     if (term &&
4352         ((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4353          (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4354          (term->type == XML_SCHEMA_TYPE_ALL)) &&
4355          (term->children != NULL)) {
4356         xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4357             output, depth +1);
4358     }
4359     if (particle->next != NULL)
4360         xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4361                 output, depth);
4362 }
4363
4364 /**
4365  * xmlSchemaAttrUsesDump:
4366  * @uses:  attribute uses list
4367  * @output:  the file output
4368  *
4369  * Dumps a list of attribute use components.
4370  */
4371 static void
4372 xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4373 {
4374     xmlSchemaAttributeUsePtr use;
4375     xmlSchemaAttributeUseProhibPtr prohib;
4376     xmlSchemaQNameRefPtr ref;
4377     const xmlChar *name, *tns;
4378     xmlChar *str = NULL;
4379     int i;
4380
4381     if ((uses == NULL) || (uses->nbItems == 0))
4382         return;
4383
4384     fprintf(output, "  attributes:\n");
4385     for (i = 0; i < uses->nbItems; i++) {
4386         use = uses->items[i];
4387         if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4388             fprintf(output, "  [prohibition] ");
4389             prohib = (xmlSchemaAttributeUseProhibPtr) use;
4390             name = prohib->name;
4391             tns = prohib->targetNamespace;
4392         } else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4393             fprintf(output, "  [reference] ");
4394             ref = (xmlSchemaQNameRefPtr) use;
4395             name = ref->name;
4396             tns = ref->targetNamespace;
4397         } else {
4398             fprintf(output, "  [use] ");
4399             name = WXS_ATTRUSE_DECL_NAME(use);
4400             tns = WXS_ATTRUSE_DECL_TNS(use);
4401         }
4402         fprintf(output, "'%s'\n",
4403             (const char *) xmlSchemaFormatQName(&str, tns, name));
4404         FREE_AND_NULL(str);
4405     }
4406 }
4407
4408 /**
4409  * xmlSchemaTypeDump:
4410  * @output:  the file output
4411  * @type:  a type structure
4412  *
4413  * Dump a SchemaType structure
4414  */
4415 static void
4416 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4417 {
4418     if (type == NULL) {
4419         fprintf(output, "Type: NULL\n");
4420         return;
4421     }
4422     fprintf(output, "Type: ");
4423     if (type->name != NULL)
4424         fprintf(output, "'%s' ", type->name);
4425     else
4426         fprintf(output, "(no name) ");
4427     if (type->targetNamespace != NULL)
4428         fprintf(output, "ns '%s' ", type->targetNamespace);
4429     switch (type->type) {
4430         case XML_SCHEMA_TYPE_BASIC:
4431             fprintf(output, "[basic] ");
4432             break;
4433         case XML_SCHEMA_TYPE_SIMPLE:
4434             fprintf(output, "[simple] ");
4435             break;
4436         case XML_SCHEMA_TYPE_COMPLEX:
4437             fprintf(output, "[complex] ");
4438             break;
4439         case XML_SCHEMA_TYPE_SEQUENCE:
4440             fprintf(output, "[sequence] ");
4441             break;
4442         case XML_SCHEMA_TYPE_CHOICE:
4443             fprintf(output, "[choice] ");
4444             break;
4445         case XML_SCHEMA_TYPE_ALL:
4446             fprintf(output, "[all] ");
4447             break;
4448         case XML_SCHEMA_TYPE_UR:
4449             fprintf(output, "[ur] ");
4450             break;
4451         case XML_SCHEMA_TYPE_RESTRICTION:
4452             fprintf(output, "[restriction] ");
4453             break;
4454         case XML_SCHEMA_TYPE_EXTENSION:
4455             fprintf(output, "[extension] ");
4456             break;
4457         default:
4458             fprintf(output, "[unknown type %d] ", type->type);
4459             break;
4460     }
4461     fprintf(output, "content: ");
4462     switch (type->contentType) {
4463         case XML_SCHEMA_CONTENT_UNKNOWN:
4464             fprintf(output, "[unknown] ");
4465             break;
4466         case XML_SCHEMA_CONTENT_EMPTY:
4467             fprintf(output, "[empty] ");
4468             break;
4469         case XML_SCHEMA_CONTENT_ELEMENTS:
4470             fprintf(output, "[element] ");
4471             break;
4472         case XML_SCHEMA_CONTENT_MIXED:
4473             fprintf(output, "[mixed] ");
4474             break;
4475         case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
4476         /* not used. */
4477             break;
4478         case XML_SCHEMA_CONTENT_BASIC:
4479             fprintf(output, "[basic] ");
4480             break;
4481         case XML_SCHEMA_CONTENT_SIMPLE:
4482             fprintf(output, "[simple] ");
4483             break;
4484         case XML_SCHEMA_CONTENT_ANY:
4485             fprintf(output, "[any] ");
4486             break;
4487     }
4488     fprintf(output, "\n");
4489     if (type->base != NULL) {
4490         fprintf(output, "  base type: '%s'", type->base);
4491         if (type->baseNs != NULL)
4492             fprintf(output, " ns '%s'\n", type->baseNs);
4493         else
4494             fprintf(output, "\n");
4495     }
4496     if (type->attrUses != NULL)
4497         xmlSchemaAttrUsesDump(type->attrUses, output);
4498     if (type->annot != NULL)
4499         xmlSchemaAnnotDump(output, type->annot);
4500 #ifdef DUMP_CONTENT_MODEL
4501     if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4502         (type->subtypes != NULL)) {
4503         xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4504             output, 1);
4505     }
4506 #endif
4507 }
4508
4509 /**
4510  * xmlSchemaDump:
4511  * @output:  the file output
4512  * @schema:  a schema structure
4513  *
4514  * Dump a Schema structure.
4515  */
4516 void
4517 xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4518 {
4519     if (output == NULL)
4520         return;
4521     if (schema == NULL) {
4522         fprintf(output, "Schemas: NULL\n");
4523         return;
4524     }
4525     fprintf(output, "Schemas: ");
4526     if (schema->name != NULL)
4527         fprintf(output, "%s, ", schema->name);
4528     else
4529         fprintf(output, "no name, ");
4530     if (schema->targetNamespace != NULL)
4531         fprintf(output, "%s", (const char *) schema->targetNamespace);
4532     else
4533         fprintf(output, "no target namespace");
4534     fprintf(output, "\n");
4535     if (schema->annot != NULL)
4536         xmlSchemaAnnotDump(output, schema->annot);
4537     xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
4538                 output);
4539     xmlHashScanFull(schema->elemDecl,
4540                     (xmlHashScannerFull) xmlSchemaElementDump, output);
4541 }
4542
4543 #ifdef DEBUG_IDC_NODE_TABLE
4544 /**
4545  * xmlSchemaDebugDumpIDCTable:
4546  * @vctxt: the WXS validation context
4547  *
4548  * Displays the current IDC table for debug purposes.
4549  */
4550 static void
4551 xmlSchemaDebugDumpIDCTable(FILE * output,
4552                            const xmlChar *namespaceName,
4553                            const xmlChar *localName,
4554                            xmlSchemaPSVIIDCBindingPtr bind)
4555 {
4556     xmlChar *str = NULL;
4557     const xmlChar *value;
4558     xmlSchemaPSVIIDCNodePtr tab;
4559     xmlSchemaPSVIIDCKeyPtr key;
4560     int i, j, res;
4561
4562     fprintf(output, "IDC: TABLES on '%s'\n",
4563         xmlSchemaFormatQName(&str, namespaceName, localName));
4564     FREE_AND_NULL(str)
4565
4566     if (bind == NULL)
4567         return;
4568     do {
4569         fprintf(output, "IDC:   BINDING '%s' (%d)\n",
4570             xmlSchemaGetComponentQName(&str,
4571                 bind->definition), bind->nbNodes);
4572         FREE_AND_NULL(str)
4573         for (i = 0; i < bind->nbNodes; i++) {
4574             tab = bind->nodeTable[i];
4575             fprintf(output, "         ( ");
4576             for (j = 0; j < bind->definition->nbFields; j++) {
4577                 key = tab->keys[j];
4578                 if ((key != NULL) && (key->val != NULL)) {
4579                     res = xmlSchemaGetCanonValue(key->val, &value);
4580                     if (res >= 0)
4581                         fprintf(output, "'%s' ", value);
4582                     else
4583                         fprintf(output, "CANON-VALUE-FAILED ");
4584                     if (res == 0)
4585                         FREE_AND_NULL(value)
4586                 } else if (key != NULL)
4587                     fprintf(output, "(no val), ");
4588                 else
4589                     fprintf(output, "(key missing), ");
4590             }
4591             fprintf(output, ")\n");
4592         }
4593         if (bind->dupls && bind->dupls->nbItems) {
4594             fprintf(output, "IDC:     dupls (%d):\n", bind->dupls->nbItems);
4595             for (i = 0; i < bind->dupls->nbItems; i++) {
4596                 tab = bind->dupls->items[i];
4597                 fprintf(output, "         ( ");
4598                 for (j = 0; j < bind->definition->nbFields; j++) {
4599                     key = tab->keys[j];
4600                     if ((key != NULL) && (key->val != NULL)) {
4601                         res = xmlSchemaGetCanonValue(key->val, &value);
4602                         if (res >= 0)
4603                             fprintf(output, "'%s' ", value);
4604                         else
4605                             fprintf(output, "CANON-VALUE-FAILED ");
4606                         if (res == 0)
4607                             FREE_AND_NULL(value)
4608                     } else if (key != NULL)
4609                     fprintf(output, "(no val), ");
4610                         else
4611                             fprintf(output, "(key missing), ");
4612                 }
4613                 fprintf(output, ")\n");
4614             }
4615         }
4616         bind = bind->next;
4617     } while (bind != NULL);
4618 }
4619 #endif /* DEBUG_IDC */
4620 #endif /* LIBXML_OUTPUT_ENABLED */
4621
4622 /************************************************************************
4623  *                                                                      *
4624  *                      Utilities                                       *
4625  *                                                                      *
4626  ************************************************************************/
4627
4628 /**
4629  * xmlSchemaGetPropNode:
4630  * @node: the element node
4631  * @name: the name of the attribute
4632  *
4633  * Seeks an attribute with a name of @name in
4634  * no namespace.
4635  *
4636  * Returns the attribute or NULL if not present.
4637  */
4638 static xmlAttrPtr
4639 xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
4640 {
4641     xmlAttrPtr prop;
4642
4643     if ((node == NULL) || (name == NULL))
4644         return(NULL);
4645     prop = node->properties;
4646     while (prop != NULL) {
4647         if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
4648             return(prop);
4649         prop = prop->next;
4650     }
4651     return (NULL);
4652 }
4653
4654 /**
4655  * xmlSchemaGetPropNodeNs:
4656  * @node: the element node
4657  * @uri: the uri
4658  * @name: the name of the attribute
4659  *
4660  * Seeks an attribute with a local name of @name and
4661  * a namespace URI of @uri.
4662  *
4663  * Returns the attribute or NULL if not present.
4664  */
4665 static xmlAttrPtr
4666 xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
4667 {
4668     xmlAttrPtr prop;
4669
4670     if ((node == NULL) || (name == NULL))
4671         return(NULL);
4672     prop = node->properties;
4673     while (prop != NULL) {
4674         if ((prop->ns != NULL) &&
4675             xmlStrEqual(prop->name, BAD_CAST name) &&
4676             xmlStrEqual(prop->ns->href, BAD_CAST uri))
4677             return(prop);
4678         prop = prop->next;
4679     }
4680     return (NULL);
4681 }
4682
4683 static const xmlChar *
4684 xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4685 {
4686     xmlChar *val;
4687     const xmlChar *ret;
4688
4689     val = xmlNodeGetContent(node);
4690     if (val == NULL)
4691         val = xmlStrdup((xmlChar *)"");
4692     ret = xmlDictLookup(ctxt->dict, val, -1);
4693     xmlFree(val);
4694     return(ret);
4695 }
4696
4697 static const xmlChar *
4698 xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4699 {
4700     return((const xmlChar*) xmlNodeGetContent(node));
4701 }
4702
4703 /**
4704  * xmlSchemaGetProp:
4705  * @ctxt: the parser context
4706  * @node: the node
4707  * @name: the property name
4708  *
4709  * Read a attribute value and internalize the string
4710  *
4711  * Returns the string or NULL if not present.
4712  */
4713 static const xmlChar *
4714 xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4715                  const char *name)
4716 {
4717     xmlChar *val;
4718     const xmlChar *ret;
4719
4720     val = xmlGetNoNsProp(node, BAD_CAST name);
4721     if (val == NULL)
4722         return(NULL);
4723     ret = xmlDictLookup(ctxt->dict, val, -1);
4724     xmlFree(val);
4725     return(ret);
4726 }
4727
4728 /************************************************************************
4729  *                                                                      *
4730  *                      Parsing functions                               *
4731  *                                                                      *
4732  ************************************************************************/
4733
4734 #define WXS_FIND_GLOBAL_ITEM(slot)                      \
4735     if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4736         ret = xmlHashLookup(schema->slot, name); \
4737         if (ret != NULL) goto exit; \
4738     } \
4739     if (xmlHashSize(schema->schemasImports) > 1) { \
4740         xmlSchemaImportPtr import; \
4741         if (nsName == NULL) \
4742             import = xmlHashLookup(schema->schemasImports, \
4743                 XML_SCHEMAS_NO_NAMESPACE); \
4744         else \
4745             import = xmlHashLookup(schema->schemasImports, nsName); \
4746         if (import == NULL) \
4747             goto exit; \
4748         ret = xmlHashLookup(import->schema->slot, name); \
4749     }
4750
4751 /**
4752  * xmlSchemaGetElem:
4753  * @schema:  the schema context
4754  * @name:  the element name
4755  * @ns:  the element namespace
4756  *
4757  * Lookup a global element declaration in the schema.
4758  *
4759  * Returns the element declaration or NULL if not found.
4760  */
4761 static xmlSchemaElementPtr
4762 xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
4763                  const xmlChar * nsName)
4764 {
4765     xmlSchemaElementPtr ret = NULL;
4766
4767     if ((name == NULL) || (schema == NULL))
4768         return(NULL);
4769     if (schema != NULL) {
4770         WXS_FIND_GLOBAL_ITEM(elemDecl)
4771     }
4772 exit:
4773 #ifdef DEBUG
4774     if (ret == NULL) {
4775         if (nsName == NULL)
4776             fprintf(stderr, "Unable to lookup element decl. %s", name);
4777         else
4778             fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
4779                     nsName);
4780     }
4781 #endif
4782     return (ret);
4783 }
4784
4785 /**
4786  * xmlSchemaGetType:
4787  * @schema:  the main schema
4788  * @name:  the type's name
4789  * nsName:  the type's namespace
4790  *
4791  * Lookup a type in the schemas or the predefined types
4792  *
4793  * Returns the group definition or NULL if not found.
4794  */
4795 static xmlSchemaTypePtr
4796 xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
4797                  const xmlChar * nsName)
4798 {
4799     xmlSchemaTypePtr ret = NULL;
4800
4801     if (name == NULL)
4802         return (NULL);
4803     /* First try the built-in types. */
4804     if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4805         ret = xmlSchemaGetPredefinedType(name, nsName);
4806         if (ret != NULL)
4807             goto exit;
4808         /*
4809         * Note that we try the parsed schemas as well here
4810         * since one might have parsed the S4S, which contain more
4811         * than the built-in types.
4812         * TODO: Can we optimize this?
4813         */
4814     }
4815     if (schema != NULL) {
4816         WXS_FIND_GLOBAL_ITEM(typeDecl)
4817     }
4818 exit:
4819
4820 #ifdef DEBUG
4821     if (ret == NULL) {
4822         if (nsName == NULL)
4823             fprintf(stderr, "Unable to lookup type %s", name);
4824         else
4825             fprintf(stderr, "Unable to lookup type %s:%s", name,
4826                     nsName);
4827     }
4828 #endif
4829     return (ret);
4830 }
4831
4832 /**
4833  * xmlSchemaGetAttributeDecl:
4834  * @schema:  the context of the schema
4835  * @name:  the name of the attribute
4836  * @ns:  the target namespace of the attribute
4837  *
4838  * Lookup a an attribute in the schema or imported schemas
4839  *
4840  * Returns the attribute declaration or NULL if not found.
4841  */
4842 static xmlSchemaAttributePtr
4843 xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
4844                  const xmlChar * nsName)
4845 {
4846     xmlSchemaAttributePtr ret = NULL;
4847
4848     if ((name == NULL) || (schema == NULL))
4849         return (NULL);
4850     if (schema != NULL) {
4851         WXS_FIND_GLOBAL_ITEM(attrDecl)
4852     }
4853 exit:
4854 #ifdef DEBUG
4855     if (ret == NULL) {
4856         if (nsName == NULL)
4857             fprintf(stderr, "Unable to lookup attribute %s", name);
4858         else
4859             fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4860                     nsName);
4861     }
4862 #endif
4863     return (ret);
4864 }
4865
4866 /**
4867  * xmlSchemaGetAttributeGroup:
4868  * @schema:  the context of the schema
4869  * @name:  the name of the attribute group
4870  * @ns:  the target namespace of the attribute group
4871  *
4872  * Lookup a an attribute group in the schema or imported schemas
4873  *
4874  * Returns the attribute group definition or NULL if not found.
4875  */
4876 static xmlSchemaAttributeGroupPtr
4877 xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4878                  const xmlChar * nsName)
4879 {
4880     xmlSchemaAttributeGroupPtr ret = NULL;
4881
4882     if ((name == NULL) || (schema == NULL))
4883         return (NULL);
4884     if (schema != NULL) {
4885         WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4886     }
4887 exit:
4888     /* TODO:
4889     if ((ret != NULL) && (ret->redef != NULL)) {
4890         * Return the last redefinition. *
4891         ret = ret->redef;
4892     }
4893     */
4894 #ifdef DEBUG
4895     if (ret == NULL) {
4896         if (nsName == NULL)
4897             fprintf(stderr, "Unable to lookup attribute group %s", name);
4898         else
4899             fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4900                     nsName);
4901     }
4902 #endif
4903     return (ret);
4904 }
4905
4906 /**
4907  * xmlSchemaGetGroup:
4908  * @schema:  the context of the schema
4909  * @name:  the name of the group
4910  * @ns:  the target namespace of the group
4911  *
4912  * Lookup a group in the schema or imported schemas
4913  *
4914  * Returns the group definition or NULL if not found.
4915  */
4916 static xmlSchemaModelGroupDefPtr
4917 xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4918                  const xmlChar * nsName)
4919 {
4920     xmlSchemaModelGroupDefPtr ret = NULL;
4921
4922     if ((name == NULL) || (schema == NULL))
4923         return (NULL);
4924     if (schema != NULL) {
4925         WXS_FIND_GLOBAL_ITEM(groupDecl)
4926     }
4927 exit:
4928
4929 #ifdef DEBUG
4930     if (ret == NULL) {
4931         if (nsName == NULL)
4932             fprintf(stderr, "Unable to lookup group %s", name);
4933         else
4934             fprintf(stderr, "Unable to lookup group %s:%s", name,
4935                     nsName);
4936     }
4937 #endif
4938     return (ret);
4939 }
4940
4941 static xmlSchemaNotationPtr
4942 xmlSchemaGetNotation(xmlSchemaPtr schema,
4943                      const xmlChar *name,
4944                      const xmlChar *nsName)
4945 {
4946     xmlSchemaNotationPtr ret = NULL;
4947
4948     if ((name == NULL) || (schema == NULL))
4949         return (NULL);
4950     if (schema != NULL) {
4951         WXS_FIND_GLOBAL_ITEM(notaDecl)
4952     }
4953 exit:
4954     return (ret);
4955 }
4956
4957 static xmlSchemaIDCPtr
4958 xmlSchemaGetIDC(xmlSchemaPtr schema,
4959                 const xmlChar *name,
4960                 const xmlChar *nsName)
4961 {
4962     xmlSchemaIDCPtr ret = NULL;
4963
4964     if ((name == NULL) || (schema == NULL))
4965         return (NULL);
4966     if (schema != NULL) {
4967         WXS_FIND_GLOBAL_ITEM(idcDef)
4968     }
4969 exit:
4970     return (ret);
4971 }
4972
4973 /**
4974  * xmlSchemaGetNamedComponent:
4975  * @schema:  the schema
4976  * @name:  the name of the group
4977  * @ns:  the target namespace of the group
4978  *
4979  * Lookup a group in the schema or imported schemas
4980  *
4981  * Returns the group definition or NULL if not found.
4982  */
4983 static xmlSchemaBasicItemPtr
4984 xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4985                            xmlSchemaTypeType itemType,
4986                            const xmlChar *name,
4987                            const xmlChar *targetNs)
4988 {
4989     switch (itemType) {
4990         case XML_SCHEMA_TYPE_GROUP:
4991             return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
4992                 name, targetNs));
4993         case XML_SCHEMA_TYPE_ELEMENT:
4994             return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
4995                 name, targetNs));
4996         default:
4997             TODO
4998             return (NULL);
4999     }
5000 }
5001
5002 /************************************************************************
5003  *                                                                      *
5004  *                      Parsing functions                               *
5005  *                                                                      *
5006  ************************************************************************/
5007
5008 #define IS_BLANK_NODE(n)                                                \
5009     (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
5010
5011 /**
5012  * xmlSchemaIsBlank:
5013  * @str:  a string
5014  * @len: the length of the string or -1
5015  *
5016  * Check if a string is ignorable
5017  *
5018  * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
5019  */
5020 static int
5021 xmlSchemaIsBlank(xmlChar * str, int len)
5022 {
5023     if (str == NULL)
5024         return (1);
5025     if (len < 0) {
5026         while (*str != 0) {
5027             if (!(IS_BLANK_CH(*str)))
5028                 return (0);
5029             str++;
5030         }
5031     } else while ((*str != 0) && (len != 0)) {
5032         if (!(IS_BLANK_CH(*str)))
5033             return (0);
5034         str++;
5035         len--;
5036     }
5037
5038     return (1);
5039 }
5040
5041 #define WXS_COMP_NAME(c, t) ((t) (c))->name
5042 #define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
5043 /*
5044 * xmlSchemaFindRedefCompInGraph:
5045 * ATTENTION TODO: This uses pointer comp. for strings.
5046 */
5047 static xmlSchemaBasicItemPtr
5048 xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
5049                               xmlSchemaTypeType type,
5050                               const xmlChar *name,
5051                               const xmlChar *nsName)
5052 {
5053     xmlSchemaBasicItemPtr ret;
5054     int i;
5055
5056     if ((bucket == NULL) || (name == NULL))
5057         return(NULL);
5058     if ((bucket->globals == NULL) ||
5059         (bucket->globals->nbItems == 0))
5060         goto subschemas;
5061     /*
5062     * Search in global components.
5063     */
5064     for (i = 0; i < bucket->globals->nbItems; i++) {
5065         ret = bucket->globals->items[i];
5066         if (ret->type == type) {
5067             switch (type) {
5068                 case XML_SCHEMA_TYPE_COMPLEX:
5069                 case XML_SCHEMA_TYPE_SIMPLE:
5070                     if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
5071                         (WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5072                         nsName))
5073                     {
5074                         return(ret);
5075                     }
5076                     break;
5077                 case XML_SCHEMA_TYPE_GROUP:
5078                     if ((WXS_COMP_NAME(ret,
5079                             xmlSchemaModelGroupDefPtr) == name) &&
5080                         (WXS_COMP_TNS(ret,
5081                             xmlSchemaModelGroupDefPtr) == nsName))
5082                     {
5083                         return(ret);
5084                     }
5085                     break;
5086                 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5087                     if ((WXS_COMP_NAME(ret,
5088                             xmlSchemaAttributeGroupPtr) == name) &&
5089                         (WXS_COMP_TNS(ret,
5090                             xmlSchemaAttributeGroupPtr) == nsName))
5091                     {
5092                         return(ret);
5093                     }
5094                     break;
5095                 default:
5096                     /* Should not be hit. */
5097                     return(NULL);
5098             }
5099         }
5100     }
5101 subschemas:
5102     /*
5103     * Process imported/included schemas.
5104     */
5105     if (bucket->relations != NULL) {
5106         xmlSchemaSchemaRelationPtr rel = bucket->relations;
5107
5108         /*
5109         * TODO: Marking the bucket will not avoid multiple searches
5110         * in the same schema, but avoids at least circularity.
5111         */
5112         bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5113         do {
5114             if ((rel->bucket != NULL) &&
5115                 ((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5116                 ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5117                     type, name, nsName);
5118                 if (ret != NULL)
5119                     return(ret);
5120             }
5121             rel = rel->next;
5122         } while (rel != NULL);
5123          bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5124     }
5125     return(NULL);
5126 }
5127
5128 /**
5129  * xmlSchemaAddNotation:
5130  * @ctxt:  a schema parser context
5131  * @schema:  the schema being built
5132  * @name:  the item name
5133  *
5134  * Add an XML schema annotation declaration
5135  * *WARNING* this interface is highly subject to change
5136  *
5137  * Returns the new struture or NULL in case of error
5138  */
5139 static xmlSchemaNotationPtr
5140 xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5141                      const xmlChar *name, const xmlChar *nsName,
5142                      xmlNodePtr node ATTRIBUTE_UNUSED)
5143 {
5144     xmlSchemaNotationPtr ret = NULL;
5145
5146     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5147         return (NULL);
5148
5149     ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5150     if (ret == NULL) {
5151         xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
5152         return (NULL);
5153     }
5154     memset(ret, 0, sizeof(xmlSchemaNotation));
5155     ret->type = XML_SCHEMA_TYPE_NOTATION;
5156     ret->name = name;
5157     ret->targetNamespace = nsName;
5158     /* TODO: do we need the node to be set?
5159     * ret->node = node;*/
5160     WXS_ADD_GLOBAL(ctxt, ret);
5161     return (ret);
5162 }
5163
5164 /**
5165  * xmlSchemaAddAttribute:
5166  * @ctxt:  a schema parser context
5167  * @schema:  the schema being built
5168  * @name:  the item name
5169  * @namespace:  the namespace
5170  *
5171  * Add an XML schema Attrribute declaration
5172  * *WARNING* this interface is highly subject to change
5173  *
5174  * Returns the new struture or NULL in case of error
5175  */
5176 static xmlSchemaAttributePtr
5177 xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5178                       const xmlChar * name, const xmlChar * nsName,
5179                       xmlNodePtr node, int topLevel)
5180 {
5181     xmlSchemaAttributePtr ret = NULL;
5182
5183     if ((ctxt == NULL) || (schema == NULL))
5184         return (NULL);
5185
5186     ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5187     if (ret == NULL) {
5188         xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
5189         return (NULL);
5190     }
5191     memset(ret, 0, sizeof(xmlSchemaAttribute));
5192     ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5193     ret->node = node;
5194     ret->name = name;
5195     ret->targetNamespace = nsName;
5196
5197     if (topLevel)
5198         WXS_ADD_GLOBAL(ctxt, ret);
5199     else
5200         WXS_ADD_LOCAL(ctxt, ret);
5201     WXS_ADD_PENDING(ctxt, ret);
5202     return (ret);
5203 }
5204
5205 /**
5206  * xmlSchemaAddAttributeUse:
5207  * @ctxt:  a schema parser context
5208  * @schema:  the schema being built
5209  * @name:  the item name
5210  * @namespace:  the namespace
5211  *
5212  * Add an XML schema Attrribute declaration
5213  * *WARNING* this interface is highly subject to change
5214  *
5215  * Returns the new struture or NULL in case of error
5216  */
5217 static xmlSchemaAttributeUsePtr
5218 xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5219                          xmlNodePtr node)
5220 {
5221     xmlSchemaAttributeUsePtr ret = NULL;
5222
5223     if (pctxt == NULL)
5224         return (NULL);
5225
5226     ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5227     if (ret == NULL) {
5228         xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5229         return (NULL);
5230     }
5231     memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5232     ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5233     ret->node = node;
5234
5235     WXS_ADD_LOCAL(pctxt, ret);
5236     return (ret);
5237 }
5238
5239 /*
5240 * xmlSchemaAddRedef:
5241 *
5242 * Adds a redefinition information. This is used at a later stage to:
5243 * resolve references to the redefined components and to check constraints.
5244 */
5245 static xmlSchemaRedefPtr
5246 xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5247                   xmlSchemaBucketPtr targetBucket,
5248                   void *item,
5249                   const xmlChar *refName,
5250                   const xmlChar *refTargetNs)
5251 {
5252     xmlSchemaRedefPtr ret;
5253
5254     ret = (xmlSchemaRedefPtr)
5255         xmlMalloc(sizeof(xmlSchemaRedef));
5256     if (ret == NULL) {
5257         xmlSchemaPErrMemory(pctxt,
5258             "allocating redefinition info", NULL);
5259         return (NULL);
5260     }
5261     memset(ret, 0, sizeof(xmlSchemaRedef));
5262     ret->item = item;
5263     ret->targetBucket = targetBucket;
5264     ret->refName = refName;
5265     ret->refTargetNs = refTargetNs;
5266     if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5267         WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5268     else
5269         WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5270     WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5271
5272     return (ret);
5273 }
5274
5275 /**
5276  * xmlSchemaAddAttributeGroupDefinition:
5277  * @ctxt:  a schema parser context
5278  * @schema:  the schema being built
5279  * @name:  the item name
5280  * @nsName:  the target namespace
5281  * @node: the corresponding node
5282  *
5283  * Add an XML schema Attrribute Group definition.
5284  *
5285  * Returns the new struture or NULL in case of error
5286  */
5287 static xmlSchemaAttributeGroupPtr
5288 xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5289                            xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5290                            const xmlChar *name,
5291                            const xmlChar *nsName,
5292                            xmlNodePtr node)
5293 {
5294     xmlSchemaAttributeGroupPtr ret = NULL;
5295
5296     if ((pctxt == NULL) || (name == NULL))
5297         return (NULL);
5298
5299     ret = (xmlSchemaAttributeGroupPtr)
5300         xmlMalloc(sizeof(xmlSchemaAttributeGroup));
5301     if (ret == NULL) {
5302         xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
5303         return (NULL);
5304     }
5305     memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
5306     ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5307     ret->name = name;
5308     ret->targetNamespace = nsName;
5309     ret->node = node;
5310
5311     /* TODO: Remove the flag. */
5312     ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5313     if (pctxt->isRedefine) {
5314         pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5315             ret, name, nsName);
5316         if (pctxt->redef == NULL) {
5317             xmlFree(ret);
5318             return(NULL);
5319         }
5320         pctxt->redefCounter = 0;
5321     }
5322     WXS_ADD_GLOBAL(pctxt, ret);
5323     WXS_ADD_PENDING(pctxt, ret);
5324     return (ret);
5325 }
5326
5327 /**
5328  * xmlSchemaAddElement:
5329  * @ctxt:  a schema parser context
5330  * @schema:  the schema being built
5331  * @name:  the type name
5332  * @namespace:  the type namespace
5333  *
5334  * Add an XML schema Element declaration
5335  * *WARNING* this interface is highly subject to change
5336  *
5337  * Returns the new struture or NULL in case of error
5338  */
5339 static xmlSchemaElementPtr
5340 xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
5341                     const xmlChar * name, const xmlChar * nsName,
5342                     xmlNodePtr node, int topLevel)
5343 {
5344     xmlSchemaElementPtr ret = NULL;
5345
5346     if ((ctxt == NULL) || (name == NULL))
5347         return (NULL);
5348
5349     ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5350     if (ret == NULL) {
5351         xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
5352         return (NULL);
5353     }
5354     memset(ret, 0, sizeof(xmlSchemaElement));
5355     ret->type = XML_SCHEMA_TYPE_ELEMENT;
5356     ret->name = name;
5357     ret->targetNamespace = nsName;
5358     ret->node = node;
5359
5360     if (topLevel)
5361         WXS_ADD_GLOBAL(ctxt, ret);
5362     else
5363         WXS_ADD_LOCAL(ctxt, ret);
5364     WXS_ADD_PENDING(ctxt, ret);
5365     return (ret);
5366 }
5367
5368 /**
5369  * xmlSchemaAddType:
5370  * @ctxt:  a schema parser context
5371  * @schema:  the schema being built
5372  * @name:  the item name
5373  * @namespace:  the namespace
5374  *
5375  * Add an XML schema item
5376  * *WARNING* this interface is highly subject to change
5377  *
5378  * Returns the new struture or NULL in case of error
5379  */
5380 static xmlSchemaTypePtr
5381 xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5382                  xmlSchemaTypeType type,
5383                  const xmlChar * name, const xmlChar * nsName,
5384                  xmlNodePtr node, int topLevel)
5385 {
5386     xmlSchemaTypePtr ret = NULL;
5387
5388     if ((ctxt == NULL) || (schema == NULL))
5389         return (NULL);
5390
5391     ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5392     if (ret == NULL) {
5393         xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
5394         return (NULL);
5395     }
5396     memset(ret, 0, sizeof(xmlSchemaType));
5397     ret->type = type;
5398     ret->name = name;
5399     ret->targetNamespace = nsName;
5400     ret->node = node;
5401     if (topLevel) {
5402         if (ctxt->isRedefine) {
5403             ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5404                 ret, name, nsName);
5405             if (ctxt->redef == NULL) {
5406                 xmlFree(ret);
5407                 return(NULL);
5408             }
5409             ctxt->redefCounter = 0;
5410         }
5411         WXS_ADD_GLOBAL(ctxt, ret);
5412     } else
5413         WXS_ADD_LOCAL(ctxt, ret);
5414     WXS_ADD_PENDING(ctxt, ret);
5415     return (ret);
5416 }
5417
5418 static xmlSchemaQNameRefPtr
5419 xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
5420                      xmlSchemaTypeType refType,
5421                      const xmlChar *refName,
5422                      const xmlChar *refNs)
5423 {
5424     xmlSchemaQNameRefPtr ret;
5425
5426     ret = (xmlSchemaQNameRefPtr)
5427         xmlMalloc(sizeof(xmlSchemaQNameRef));
5428     if (ret == NULL) {
5429         xmlSchemaPErrMemory(pctxt,
5430             "allocating QName reference item", NULL);
5431         return (NULL);
5432     }
5433     ret->node = NULL;
5434     ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5435     ret->name = refName;
5436     ret->targetNamespace = refNs;
5437     ret->item = NULL;
5438     ret->itemType = refType;
5439     /*
5440     * Store the reference item in the schema.
5441     */
5442     WXS_ADD_LOCAL(pctxt, ret);
5443     return (ret);
5444 }
5445
5446 static xmlSchemaAttributeUseProhibPtr
5447 xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5448 {
5449     xmlSchemaAttributeUseProhibPtr ret;
5450
5451     ret = (xmlSchemaAttributeUseProhibPtr)
5452         xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5453     if (ret == NULL) {
5454         xmlSchemaPErrMemory(pctxt,
5455             "allocating attribute use prohibition", NULL);
5456         return (NULL);
5457     }
5458     memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5459     ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5460     WXS_ADD_LOCAL(pctxt, ret);
5461     return (ret);
5462 }
5463
5464
5465 /**
5466  * xmlSchemaAddModelGroup:
5467  * @ctxt:  a schema parser context
5468  * @schema:  the schema being built
5469  * @type: the "compositor" type of the model group
5470  * @node: the node in the schema doc
5471  *
5472  * Adds a schema model group
5473  * *WARNING* this interface is highly subject to change
5474  *
5475  * Returns the new struture or NULL in case of error
5476  */
5477 static xmlSchemaModelGroupPtr
5478 xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5479                        xmlSchemaPtr schema,
5480                        xmlSchemaTypeType type,
5481                        xmlNodePtr node)
5482 {
5483     xmlSchemaModelGroupPtr ret = NULL;
5484
5485     if ((ctxt == NULL) || (schema == NULL))
5486         return (NULL);
5487
5488     ret = (xmlSchemaModelGroupPtr)
5489         xmlMalloc(sizeof(xmlSchemaModelGroup));
5490     if (ret == NULL) {
5491         xmlSchemaPErrMemory(ctxt, "allocating model group component",
5492             NULL);
5493         return (NULL);
5494     }
5495     memset(ret, 0, sizeof(xmlSchemaModelGroup));
5496     ret->type = type;
5497     ret->node = node;
5498     WXS_ADD_LOCAL(ctxt, ret);
5499     if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5500         (type == XML_SCHEMA_TYPE_CHOICE))
5501         WXS_ADD_PENDING(ctxt, ret);
5502     return (ret);
5503 }
5504
5505
5506 /**
5507  * xmlSchemaAddParticle:
5508  * @ctxt:  a schema parser context
5509  * @schema:  the schema being built
5510  * @node: the corresponding node in the schema doc
5511  * @min: the minOccurs
5512  * @max: the maxOccurs
5513  *
5514  * Adds an XML schema particle component.
5515  * *WARNING* this interface is highly subject to change
5516  *
5517  * Returns the new struture or NULL in case of error
5518  */
5519 static xmlSchemaParticlePtr
5520 xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
5521                      xmlNodePtr node, int min, int max)
5522 {
5523     xmlSchemaParticlePtr ret = NULL;
5524     if (ctxt == NULL)
5525         return (NULL);
5526
5527 #ifdef DEBUG
5528     fprintf(stderr, "Adding particle component\n");
5529 #endif
5530     ret = (xmlSchemaParticlePtr)
5531         xmlMalloc(sizeof(xmlSchemaParticle));
5532     if (ret == NULL) {
5533         xmlSchemaPErrMemory(ctxt, "allocating particle component",
5534             NULL);
5535         return (NULL);
5536     }
5537     ret->type = XML_SCHEMA_TYPE_PARTICLE;
5538     ret->annot = NULL;
5539     ret->node = node;
5540     ret->minOccurs = min;
5541     ret->maxOccurs = max;
5542     ret->next = NULL;
5543     ret->children = NULL;
5544
5545     WXS_ADD_LOCAL(ctxt, ret);
5546     /*
5547     * Note that addition to pending components will be done locally
5548     * to the specific parsing function, since the most particles
5549     * need not to be fixed up (i.e. the reference to be resolved).
5550     * REMOVED: WXS_ADD_PENDING(ctxt, ret);
5551     */
5552     return (ret);
5553 }
5554
5555 /**
5556  * xmlSchemaAddModelGroupDefinition:
5557  * @ctxt:  a schema validation context
5558  * @schema:  the schema being built
5559  * @name:  the group name
5560  *
5561  * Add an XML schema Group definition
5562  *
5563  * Returns the new struture or NULL in case of error
5564  */
5565 static xmlSchemaModelGroupDefPtr
5566 xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5567                                  xmlSchemaPtr schema,
5568                                  const xmlChar *name,
5569                                  const xmlChar *nsName,
5570                                  xmlNodePtr node)
5571 {
5572     xmlSchemaModelGroupDefPtr ret = NULL;
5573
5574     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5575         return (NULL);
5576
5577     ret = (xmlSchemaModelGroupDefPtr)
5578         xmlMalloc(sizeof(xmlSchemaModelGroupDef));
5579     if (ret == NULL) {
5580         xmlSchemaPErrMemory(ctxt, "adding group", NULL);
5581         return (NULL);
5582     }
5583     memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
5584     ret->name = name;
5585     ret->type = XML_SCHEMA_TYPE_GROUP;
5586     ret->node = node;
5587     ret->targetNamespace = nsName;
5588
5589     if (ctxt->isRedefine) {
5590         ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5591             ret, name, nsName);
5592         if (ctxt->redef == NULL) {
5593             xmlFree(ret);
5594             return(NULL);
5595         }
5596         ctxt->redefCounter = 0;
5597     }
5598     WXS_ADD_GLOBAL(ctxt, ret);
5599     WXS_ADD_PENDING(ctxt, ret);
5600     return (ret);
5601 }
5602
5603 /**
5604  * xmlSchemaNewWildcardNs:
5605  * @ctxt:  a schema validation context
5606  *
5607  * Creates a new wildcard namespace constraint.
5608  *
5609  * Returns the new struture or NULL in case of error
5610  */
5611 static xmlSchemaWildcardNsPtr
5612 xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5613 {
5614     xmlSchemaWildcardNsPtr ret;
5615
5616     ret = (xmlSchemaWildcardNsPtr)
5617         xmlMalloc(sizeof(xmlSchemaWildcardNs));
5618     if (ret == NULL) {
5619         xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
5620         return (NULL);
5621     }
5622     ret->value = NULL;
5623     ret->next = NULL;
5624     return (ret);
5625 }
5626
5627 static xmlSchemaIDCPtr
5628 xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5629                   const xmlChar *name, const xmlChar *nsName,
5630                   int category, xmlNodePtr node)
5631 {
5632     xmlSchemaIDCPtr ret = NULL;
5633
5634     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5635         return (NULL);
5636
5637     ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5638     if (ret == NULL) {
5639         xmlSchemaPErrMemory(ctxt,
5640             "allocating an identity-constraint definition", NULL);
5641         return (NULL);
5642     }
5643     memset(ret, 0, sizeof(xmlSchemaIDC));
5644     /* The target namespace of the parent element declaration. */
5645     ret->targetNamespace = nsName;
5646     ret->name = name;
5647     ret->type = category;
5648     ret->node = node;
5649
5650     WXS_ADD_GLOBAL(ctxt, ret);
5651     /*
5652     * Only keyrefs need to be fixup up.
5653     */
5654     if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
5655         WXS_ADD_PENDING(ctxt, ret);
5656     return (ret);
5657 }
5658
5659 /**
5660  * xmlSchemaAddWildcard:
5661  * @ctxt:  a schema validation context
5662  * @schema: a schema
5663  *
5664  * Adds a wildcard.
5665  * It corresponds to a xsd:anyAttribute and xsd:any.
5666  *
5667  * Returns the new struture or NULL in case of error
5668  */
5669 static xmlSchemaWildcardPtr
5670 xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5671                      xmlSchemaTypeType type, xmlNodePtr node)
5672 {
5673     xmlSchemaWildcardPtr ret = NULL;
5674
5675     if ((ctxt == NULL) || (schema == NULL))
5676         return (NULL);
5677
5678     ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5679     if (ret == NULL) {
5680         xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5681         return (NULL);
5682     }
5683     memset(ret, 0, sizeof(xmlSchemaWildcard));
5684     ret->type = type;
5685     ret->node = node;
5686     WXS_ADD_LOCAL(ctxt, ret);
5687     return (ret);
5688 }
5689
5690 static void
5691 xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5692 {
5693     if (group == NULL)
5694         return;
5695     if (group->members != NULL)
5696         xmlSchemaItemListFree(group->members);
5697     xmlFree(group);
5698 }
5699
5700 static xmlSchemaSubstGroupPtr
5701 xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5702                        xmlSchemaElementPtr head)
5703 {
5704     xmlSchemaSubstGroupPtr ret;
5705
5706     /* Init subst group hash. */
5707     if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5708         WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5709         if (WXS_SUBST_GROUPS(pctxt) == NULL)
5710             return(NULL);
5711     }
5712     /* Create a new substitution group. */
5713     ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5714     if (ret == NULL) {
5715         xmlSchemaPErrMemory(NULL,
5716             "allocating a substitution group container", NULL);
5717         return(NULL);
5718     }
5719     memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5720     ret->head = head;
5721     /* Create list of members. */
5722     ret->members = xmlSchemaItemListCreate();
5723     if (ret->members == NULL) {
5724         xmlSchemaSubstGroupFree(ret);
5725         return(NULL);
5726     }
5727     /* Add subst group to hash. */
5728     if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5729         head->name, head->targetNamespace, ret) != 0) {
5730         PERROR_INT("xmlSchemaSubstGroupAdd",
5731             "failed to add a new substitution container");
5732         xmlSchemaSubstGroupFree(ret);
5733         return(NULL);
5734     }
5735     return(ret);
5736 }
5737
5738 static xmlSchemaSubstGroupPtr
5739 xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5740                        xmlSchemaElementPtr head)
5741 {
5742     if (WXS_SUBST_GROUPS(pctxt) == NULL)
5743         return(NULL);
5744     return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5745         head->name, head->targetNamespace));
5746
5747 }
5748
5749 /**
5750  * xmlSchemaAddElementSubstitutionMember:
5751  * @pctxt:  a schema parser context
5752  * @head:  the head of the substitution group
5753  * @member: the new member of the substitution group
5754  *
5755  * Allocate a new annotation structure.
5756  *
5757  * Returns the newly allocated structure or NULL in case or error
5758  */
5759 static int
5760 xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5761                                       xmlSchemaElementPtr head,
5762                                       xmlSchemaElementPtr member)
5763 {
5764     xmlSchemaSubstGroupPtr substGroup = NULL;
5765
5766     if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5767         return (-1);
5768
5769     substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5770     if (substGroup == NULL)
5771         substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5772     if (substGroup == NULL)
5773         return(-1);
5774     if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5775         return(-1);
5776     return(0);
5777 }
5778
5779 /************************************************************************
5780  *                                                                      *
5781  *              Utilities for parsing                                   *
5782  *                                                                      *
5783  ************************************************************************/
5784
5785 /**
5786  * xmlSchemaPValAttrNodeQNameValue:
5787  * @ctxt:  a schema parser context
5788  * @schema: the schema context
5789  * @ownerDes: the designation of the parent element
5790  * @ownerItem: the parent as a schema object
5791  * @value:  the QName value
5792  * @local: the resulting local part if found, the attribute value otherwise
5793  * @uri:  the resulting namespace URI if found
5794  *
5795  * Extracts the local name and the URI of a QName value and validates it.
5796  * This one is intended to be used on attribute values that
5797  * should resolve to schema components.
5798  *
5799  * Returns 0, in case the QName is valid, a positive error code
5800  * if not valid and -1 if an internal error occurs.
5801  */
5802 static int
5803 xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
5804                                        xmlSchemaPtr schema,
5805                                        xmlSchemaBasicItemPtr ownerItem,
5806                                        xmlAttrPtr attr,
5807                                        const xmlChar *value,
5808                                        const xmlChar **uri,
5809                                        const xmlChar **local)
5810 {
5811     const xmlChar *pref;
5812     xmlNsPtr ns;
5813     int len, ret;
5814
5815     *uri = NULL;
5816     *local = NULL;
5817     ret = xmlValidateQName(value, 1);
5818     if (ret > 0) {
5819         xmlSchemaPSimpleTypeErr(ctxt,
5820             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5821             ownerItem, (xmlNodePtr) attr,
5822             xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5823             NULL, value, NULL, NULL, NULL);
5824         *local = value;
5825         return (ctxt->err);
5826     } else if (ret < 0)
5827         return (-1);
5828
5829     if (!strchr((char *) value, ':')) {
5830         ns = xmlSearchNs(attr->doc, attr->parent, NULL);
5831         if (ns)
5832             *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5833         else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5834             /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5835             * parser context. */
5836             /*
5837             * This one takes care of included schemas with no
5838             * target namespace.
5839             */
5840             *uri = ctxt->targetNamespace;
5841         }
5842         *local = xmlDictLookup(ctxt->dict, value, -1);
5843         return (0);
5844     }
5845     /*
5846     * At this point xmlSplitQName3 has to return a local name.
5847     */
5848     *local = xmlSplitQName3(value, &len);
5849     *local = xmlDictLookup(ctxt->dict, *local, -1);
5850     pref = xmlDictLookup(ctxt->dict, value, len);
5851     ns = xmlSearchNs(attr->doc, attr->parent, pref);
5852     if (ns == NULL) {
5853         xmlSchemaPSimpleTypeErr(ctxt,
5854             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5855             ownerItem, (xmlNodePtr) attr,
5856             xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5857             "The value '%s' of simple type 'xs:QName' has no "
5858             "corresponding namespace declaration in scope", value, NULL);
5859         return (ctxt->err);
5860     } else {
5861         *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5862     }
5863     return (0);
5864 }
5865
5866 /**
5867  * xmlSchemaPValAttrNodeQName:
5868  * @ctxt:  a schema parser context
5869  * @schema: the schema context
5870  * @ownerDes: the designation of the owner element
5871  * @ownerItem: the owner as a schema object
5872  * @attr:  the attribute node
5873  * @local: the resulting local part if found, the attribute value otherwise
5874  * @uri:  the resulting namespace URI if found
5875  *
5876  * Extracts and validates the QName of an attribute value.
5877  * This one is intended to be used on attribute values that
5878  * should resolve to schema components.
5879  *
5880  * Returns 0, in case the QName is valid, a positive error code
5881  * if not valid and -1 if an internal error occurs.
5882  */
5883 static int
5884 xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
5885                                        xmlSchemaPtr schema,
5886                                        xmlSchemaBasicItemPtr ownerItem,
5887                                        xmlAttrPtr attr,
5888                                        const xmlChar **uri,
5889                                        const xmlChar **local)
5890 {
5891     const xmlChar *value;
5892
5893     value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5894     return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5895         ownerItem, attr, value, uri, local));
5896 }
5897
5898 /**
5899  * xmlSchemaPValAttrQName:
5900  * @ctxt:  a schema parser context
5901  * @schema: the schema context
5902  * @ownerDes: the designation of the parent element
5903  * @ownerItem: the owner as a schema object
5904  * @ownerElem:  the parent node of the attribute
5905  * @name:  the name of the attribute
5906  * @local: the resulting local part if found, the attribute value otherwise
5907  * @uri:  the resulting namespace URI if found
5908  *
5909  * Extracts and validates the QName of an attribute value.
5910  *
5911  * Returns 0, in case the QName is valid, a positive error code
5912  * if not valid and -1 if an internal error occurs.
5913  */
5914 static int
5915 xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5916                                    xmlSchemaPtr schema,
5917                                    xmlSchemaBasicItemPtr ownerItem,
5918                                    xmlNodePtr ownerElem,
5919                                    const char *name,
5920                                    const xmlChar **uri,
5921                                    const xmlChar **local)
5922 {
5923     xmlAttrPtr attr;
5924
5925     attr = xmlSchemaGetPropNode(ownerElem, name);
5926     if (attr == NULL) {
5927         *local = NULL;
5928         *uri = NULL;
5929         return (0);
5930     }
5931     return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5932         ownerItem, attr, uri, local));
5933 }
5934
5935 /**
5936  * xmlSchemaPValAttrID:
5937  * @ctxt:  a schema parser context
5938  * @schema: the schema context
5939  * @ownerDes: the designation of the parent element
5940  * @ownerItem: the owner as a schema object
5941  * @ownerElem:  the parent node of the attribute
5942  * @name:  the name of the attribute
5943  *
5944  * Extracts and validates the ID of an attribute value.
5945  *
5946  * Returns 0, in case the ID is valid, a positive error code
5947  * if not valid and -1 if an internal error occurs.
5948  */
5949 static int
5950 xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
5951 {
5952     int ret;
5953     const xmlChar *value;
5954
5955     if (attr == NULL)
5956         return(0);
5957     value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
5958     ret = xmlValidateNCName(value, 1);
5959     if (ret == 0) {
5960         /*
5961         * NOTE: the IDness might have already be declared in the DTD
5962         */
5963         if (attr->atype != XML_ATTRIBUTE_ID) {
5964             xmlIDPtr res;
5965             xmlChar *strip;
5966
5967             /*
5968             * TODO: Use xmlSchemaStrip here; it's not exported at this
5969             * moment.
5970             */
5971             strip = xmlSchemaCollapseString(value);
5972             if (strip != NULL) {
5973                 xmlFree((xmlChar *) value);
5974                 value = strip;
5975             }
5976             res = xmlAddID(NULL, attr->doc, value, attr);
5977             if (res == NULL) {
5978                 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5979                 xmlSchemaPSimpleTypeErr(ctxt,
5980                     XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5981                     NULL, (xmlNodePtr) attr,
5982                     xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5983                     NULL, NULL, "Duplicate value '%s' of simple "
5984                     "type 'xs:ID'", value, NULL);
5985             } else
5986                 attr->atype = XML_ATTRIBUTE_ID;
5987         }
5988     } else if (ret > 0) {
5989         ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5990         xmlSchemaPSimpleTypeErr(ctxt,
5991             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5992             NULL, (xmlNodePtr) attr,
5993             xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5994             NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5995             "not a valid 'xs:NCName'",
5996             value, NULL);
5997     }
5998     if (value != NULL)
5999         xmlFree((xmlChar *)value);
6000
6001     return (ret);
6002 }
6003
6004 static int
6005 xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
6006                     xmlNodePtr ownerElem,
6007                     const xmlChar *name)
6008 {
6009     xmlAttrPtr attr;
6010
6011     attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
6012     if (attr == NULL)
6013         return(0);
6014     return(xmlSchemaPValAttrNodeID(ctxt, attr));
6015
6016 }
6017
6018 /**
6019  * xmlGetMaxOccurs:
6020  * @ctxt:  a schema validation context
6021  * @node:  a subtree containing XML Schema informations
6022  *
6023  * Get the maxOccurs property
6024  *
6025  * Returns the default if not found, or the value
6026  */
6027 static int
6028 xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6029                 int min, int max, int def, const char *expected)
6030 {
6031     const xmlChar *val, *cur;
6032     int ret = 0;
6033     xmlAttrPtr attr;
6034
6035     attr = xmlSchemaGetPropNode(node, "maxOccurs");
6036     if (attr == NULL)
6037         return (def);
6038     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6039
6040     if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
6041         if (max != UNBOUNDED) {
6042             xmlSchemaPSimpleTypeErr(ctxt,
6043                 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6044                 /* XML_SCHEMAP_INVALID_MINOCCURS, */
6045                 NULL, (xmlNodePtr) attr, NULL, expected,
6046                 val, NULL, NULL, NULL);
6047             return (def);
6048         } else
6049             return (UNBOUNDED);  /* encoding it with -1 might be another option */
6050     }
6051
6052     cur = val;
6053     while (IS_BLANK_CH(*cur))
6054         cur++;
6055     if (*cur == 0) {
6056         xmlSchemaPSimpleTypeErr(ctxt,
6057             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6058             /* XML_SCHEMAP_INVALID_MINOCCURS, */
6059             NULL, (xmlNodePtr) attr, NULL, expected,
6060             val, NULL, NULL, NULL);
6061         return (def);
6062     }
6063     while ((*cur >= '0') && (*cur <= '9')) {
6064         ret = ret * 10 + (*cur - '0');
6065         cur++;
6066     }
6067     while (IS_BLANK_CH(*cur))
6068         cur++;
6069     /*
6070     * TODO: Restrict the maximal value to Integer.
6071     */
6072     if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6073         xmlSchemaPSimpleTypeErr(ctxt,
6074             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6075             /* XML_SCHEMAP_INVALID_MINOCCURS, */
6076             NULL, (xmlNodePtr) attr, NULL, expected,
6077             val, NULL, NULL, NULL);
6078         return (def);
6079     }
6080     return (ret);
6081 }
6082
6083 /**
6084  * xmlGetMinOccurs:
6085  * @ctxt:  a schema validation context
6086  * @node:  a subtree containing XML Schema informations
6087  *
6088  * Get the minOccurs property
6089  *
6090  * Returns the default if not found, or the value
6091  */
6092 static int
6093 xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6094                 int min, int max, int def, const char *expected)
6095 {
6096     const xmlChar *val, *cur;
6097     int ret = 0;
6098     xmlAttrPtr attr;
6099
6100     attr = xmlSchemaGetPropNode(node, "minOccurs");
6101     if (attr == NULL)
6102         return (def);
6103     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6104     cur = val;
6105     while (IS_BLANK_CH(*cur))
6106         cur++;
6107     if (*cur == 0) {
6108         xmlSchemaPSimpleTypeErr(ctxt,
6109             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6110             /* XML_SCHEMAP_INVALID_MINOCCURS, */
6111             NULL, (xmlNodePtr) attr, NULL, expected,
6112             val, NULL, NULL, NULL);
6113         return (def);
6114     }
6115     while ((*cur >= '0') && (*cur <= '9')) {
6116         ret = ret * 10 + (*cur - '0');
6117         cur++;
6118     }
6119     while (IS_BLANK_CH(*cur))
6120         cur++;
6121     /*
6122     * TODO: Restrict the maximal value to Integer.
6123     */
6124     if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6125         xmlSchemaPSimpleTypeErr(ctxt,
6126             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6127             /* XML_SCHEMAP_INVALID_MINOCCURS, */
6128             NULL, (xmlNodePtr) attr, NULL, expected,
6129             val, NULL, NULL, NULL);
6130         return (def);
6131     }
6132     return (ret);
6133 }
6134
6135 /**
6136  * xmlSchemaPGetBoolNodeValue:
6137  * @ctxt:  a schema validation context
6138  * @ownerDes:  owner designation
6139  * @ownerItem:  the owner as a schema item
6140  * @node: the node holding the value
6141  *
6142  * Converts a boolean string value into 1 or 0.
6143  *
6144  * Returns 0 or 1.
6145  */
6146 static int
6147 xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
6148                            xmlSchemaBasicItemPtr ownerItem,
6149                            xmlNodePtr node)
6150 {
6151     xmlChar *value = NULL;
6152     int res = 0;
6153
6154     value = xmlNodeGetContent(node);
6155     /*
6156     * 3.2.2.1 Lexical representation
6157     * An instance of a datatype that is defined as `boolean`
6158     * can have the following legal literals {true, false, 1, 0}.
6159     */
6160     if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6161         res = 1;
6162     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6163         res = 0;
6164     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6165         res = 1;
6166     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
6167         res = 0;
6168     else {
6169         xmlSchemaPSimpleTypeErr(ctxt,
6170             XML_SCHEMAP_INVALID_BOOLEAN,
6171             ownerItem, node,
6172             xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6173             NULL, BAD_CAST value,
6174             NULL, NULL, NULL);
6175     }
6176     if (value != NULL)
6177         xmlFree(value);
6178     return (res);
6179 }
6180
6181 /**
6182  * xmlGetBooleanProp:
6183  * @ctxt:  a schema validation context
6184  * @node:  a subtree containing XML Schema informations
6185  * @name:  the attribute name
6186  * @def:  the default value
6187  *
6188  * Evaluate if a boolean property is set
6189  *
6190  * Returns the default if not found, 0 if found to be false,
6191  * 1 if found to be true
6192  */
6193 static int
6194 xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
6195                   xmlNodePtr node,
6196                   const char *name, int def)
6197 {
6198     const xmlChar *val;
6199
6200     val = xmlSchemaGetProp(ctxt, node, name);
6201     if (val == NULL)
6202         return (def);
6203     /*
6204     * 3.2.2.1 Lexical representation
6205     * An instance of a datatype that is defined as `boolean`
6206     * can have the following legal literals {true, false, 1, 0}.
6207     */
6208     if (xmlStrEqual(val, BAD_CAST "true"))
6209         def = 1;
6210     else if (xmlStrEqual(val, BAD_CAST "false"))
6211         def = 0;
6212     else if (xmlStrEqual(val, BAD_CAST "1"))
6213         def = 1;
6214     else if (xmlStrEqual(val, BAD_CAST "0"))
6215         def = 0;
6216     else {
6217         xmlSchemaPSimpleTypeErr(ctxt,
6218             XML_SCHEMAP_INVALID_BOOLEAN,
6219             NULL,
6220             (xmlNodePtr) xmlSchemaGetPropNode(node, name),
6221             xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6222             NULL, val, NULL, NULL, NULL);
6223     }
6224     return (def);
6225 }
6226
6227 /************************************************************************
6228  *                                                                      *
6229  *              Shema extraction from an Infoset                        *
6230  *                                                                      *
6231  ************************************************************************/
6232 static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6233                                                  ctxt, xmlSchemaPtr schema,
6234                                                  xmlNodePtr node,
6235                                                  int topLevel);
6236 static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6237                                                   ctxt,
6238                                                   xmlSchemaPtr schema,
6239                                                   xmlNodePtr node,
6240                                                   int topLevel);
6241 static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6242                                                   ctxt,
6243                                                   xmlSchemaPtr schema,
6244                                                   xmlNodePtr node,
6245                                                   xmlSchemaTypeType parentType);
6246 static xmlSchemaBasicItemPtr
6247 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6248                              xmlSchemaPtr schema,
6249                              xmlNodePtr node,
6250                              xmlSchemaItemListPtr uses,
6251                              int parentType);
6252 static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6253                                            xmlSchemaPtr schema,
6254                                            xmlNodePtr node);
6255 static xmlSchemaWildcardPtr
6256 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6257                            xmlSchemaPtr schema, xmlNodePtr node);
6258
6259 /**
6260  * xmlSchemaPValAttrNodeValue:
6261  *
6262  * @ctxt:  a schema parser context
6263  * @ownerDes: the designation of the parent element
6264  * @ownerItem: the schema object owner if existent
6265  * @attr:  the schema attribute node being validated
6266  * @value: the value
6267  * @type: the built-in type to be validated against
6268  *
6269  * Validates a value against the given built-in type.
6270  * This one is intended to be used internally for validation
6271  * of schema attribute values during parsing of the schema.
6272  *
6273  * Returns 0 if the value is valid, a positive error code
6274  * number otherwise and -1 in case of an internal or API error.
6275  */
6276 static int
6277 xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
6278                            xmlSchemaBasicItemPtr ownerItem,
6279                            xmlAttrPtr attr,
6280                            const xmlChar *value,
6281                            xmlSchemaTypePtr type)
6282 {
6283
6284     int ret = 0;
6285
6286     /*
6287     * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6288     * one is really meant to be used internally, so better not.
6289     */
6290     if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
6291         return (-1);
6292     if (type->type != XML_SCHEMA_TYPE_BASIC) {
6293         PERROR_INT("xmlSchemaPValAttrNodeValue",
6294             "the given type is not a built-in type");
6295         return (-1);
6296     }
6297     switch (type->builtInType) {
6298         case XML_SCHEMAS_NCNAME:
6299         case XML_SCHEMAS_QNAME:
6300         case XML_SCHEMAS_ANYURI:
6301         case XML_SCHEMAS_TOKEN:
6302         case XML_SCHEMAS_LANGUAGE:
6303             ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6304                 (xmlNodePtr) attr);
6305             break;
6306         default: {
6307             PERROR_INT("xmlSchemaPValAttrNodeValue",
6308                 "validation using the given type is not supported while "
6309                 "parsing a schema");
6310             return (-1);
6311         }
6312     }
6313     /*
6314     * TODO: Should we use the S4S error codes instead?
6315     */
6316     if (ret < 0) {
6317         PERROR_INT("xmlSchemaPValAttrNodeValue",
6318             "failed to validate a schema attribute value");
6319         return (-1);
6320     } else if (ret > 0) {
6321         if (WXS_IS_LIST(type))
6322             ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6323         else
6324             ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6325         xmlSchemaPSimpleTypeErr(pctxt,
6326             ret, ownerItem, (xmlNodePtr) attr,
6327             type, NULL, value, NULL, NULL, NULL);
6328     }
6329     return (ret);
6330 }
6331
6332 /**
6333  * xmlSchemaPValAttrNode:
6334  *
6335  * @ctxt:  a schema parser context
6336  * @ownerDes: the designation of the parent element
6337  * @ownerItem: the schema object owner if existent
6338  * @attr:  the schema attribute node being validated
6339  * @type: the built-in type to be validated against
6340  * @value: the resulting value if any
6341  *
6342  * Extracts and validates a value against the given built-in type.
6343  * This one is intended to be used internally for validation
6344  * of schema attribute values during parsing of the schema.
6345  *
6346  * Returns 0 if the value is valid, a positive error code
6347  * number otherwise and -1 in case of an internal or API error.
6348  */
6349 static int
6350 xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
6351                            xmlSchemaBasicItemPtr ownerItem,
6352                            xmlAttrPtr attr,
6353                            xmlSchemaTypePtr type,
6354                            const xmlChar **value)
6355 {
6356     const xmlChar *val;
6357
6358     if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
6359         return (-1);
6360
6361     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6362     if (value != NULL)
6363         *value = val;
6364
6365     return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
6366         val, type));
6367 }
6368
6369 /**
6370  * xmlSchemaPValAttr:
6371  *
6372  * @ctxt:  a schema parser context
6373  * @node: the element node of the attribute
6374  * @ownerDes: the designation of the parent element
6375  * @ownerItem: the schema object owner if existent
6376  * @ownerElem: the owner element node
6377  * @name:  the name of the schema attribute node
6378  * @type: the built-in type to be validated against
6379  * @value: the resulting value if any
6380  *
6381  * Extracts and validates a value against the given built-in type.
6382  * This one is intended to be used internally for validation
6383  * of schema attribute values during parsing of the schema.
6384  *
6385  * Returns 0 if the value is valid, a positive error code
6386  * number otherwise and -1 in case of an internal or API error.
6387  */
6388 static int
6389 xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6390                        xmlSchemaBasicItemPtr ownerItem,
6391                        xmlNodePtr ownerElem,
6392                        const char *name,
6393                        xmlSchemaTypePtr type,
6394                        const xmlChar **value)
6395 {
6396     xmlAttrPtr attr;
6397
6398     if ((ctxt == NULL) || (type == NULL)) {
6399         if (value != NULL)
6400             *value = NULL;
6401         return (-1);
6402     }
6403     if (type->type != XML_SCHEMA_TYPE_BASIC) {
6404         if (value != NULL)
6405             *value = NULL;
6406         xmlSchemaPErr(ctxt, ownerElem,
6407             XML_SCHEMAP_INTERNAL,
6408             "Internal error: xmlSchemaPValAttr, the given "
6409             "type '%s' is not a built-in type.\n",
6410             type->name, NULL);
6411         return (-1);
6412     }
6413     attr = xmlSchemaGetPropNode(ownerElem, name);
6414     if (attr == NULL) {
6415         if (value != NULL)
6416             *value = NULL;
6417         return (0);
6418     }
6419     return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
6420         type, value));
6421 }
6422
6423 static int
6424 xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
6425                   xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6426                   xmlNodePtr node,
6427                   xmlAttrPtr attr,
6428                   const xmlChar *namespaceName)
6429 {
6430     /* TODO: Pointer comparison instead? */
6431     if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
6432         return (0);
6433     if (xmlStrEqual(xmlSchemaNs, namespaceName))
6434         return (0);
6435     /*
6436     * Check if the referenced namespace was <import>ed.
6437     */
6438     if (WXS_BUCKET(pctxt)->relations != NULL) {
6439         xmlSchemaSchemaRelationPtr rel;
6440
6441         rel = WXS_BUCKET(pctxt)->relations;
6442         do {
6443             if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
6444                 xmlStrEqual(namespaceName, rel->importNamespace))
6445                 return (0);
6446             rel = rel->next;
6447         } while (rel != NULL);
6448     }
6449     /*
6450     * No matching <import>ed namespace found.
6451     */
6452     {
6453         xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6454
6455         if (namespaceName == NULL)
6456             xmlSchemaCustomErr(ACTXT_CAST pctxt,
6457                 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6458                 "References from this schema to components in no "
6459                 "namespace are not allowed, since not indicated by an "
6460                 "import statement", NULL, NULL);
6461         else
6462             xmlSchemaCustomErr(ACTXT_CAST pctxt,
6463                 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6464                 "References from this schema to components in the "
6465                 "namespace '%s' are not allowed, since not indicated by an "
6466                 "import statement", namespaceName, NULL);
6467     }
6468     return (XML_SCHEMAP_SRC_RESOLVE);
6469 }
6470
6471 /**
6472  * xmlSchemaParseLocalAttributes:
6473  * @ctxt:  a schema validation context
6474  * @schema:  the schema being built
6475  * @node:  a subtree containing XML Schema informations
6476  * @type:  the hosting type where the attributes will be anchored
6477  *
6478  * Parses attribute uses and attribute declarations and
6479  * attribute group references.
6480  */
6481 static int
6482 xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6483                         xmlNodePtr *child, xmlSchemaItemListPtr *list,
6484                         int parentType, int *hasRefs)
6485 {
6486     void *item;
6487
6488     while ((IS_SCHEMA((*child), "attribute")) ||
6489            (IS_SCHEMA((*child), "attributeGroup"))) {
6490         if (IS_SCHEMA((*child), "attribute")) {
6491             item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6492                 *list, parentType);
6493         } else {
6494             item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6495             if ((item != NULL) && (hasRefs != NULL))
6496                 *hasRefs = 1;
6497         }
6498         if (item != NULL) {
6499             if (*list == NULL) {
6500                 /* TODO: Customize grow factor. */
6501                 *list = xmlSchemaItemListCreate();
6502                 if (*list == NULL)
6503                     return(-1);
6504             }
6505             if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6506                 return(-1);
6507         }
6508         *child = (*child)->next;
6509     }
6510     return (0);
6511 }
6512
6513 /**
6514  * xmlSchemaParseAnnotation:
6515  * @ctxt:  a schema validation context
6516  * @schema:  the schema being built
6517  * @node:  a subtree containing XML Schema informations
6518  *
6519  * parse a XML schema Attrribute declaration
6520  * *WARNING* this interface is highly subject to change
6521  *
6522  * Returns -1 in case of error, 0 if the declaration is improper and
6523  *         1 in case of success.
6524  */
6525 static xmlSchemaAnnotPtr
6526 xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed)
6527 {
6528     xmlSchemaAnnotPtr ret;
6529     xmlNodePtr child = NULL;
6530     xmlAttrPtr attr;
6531     int barked = 0;
6532
6533     /*
6534     * INFO: S4S completed.
6535     */
6536     /*
6537     * id = ID
6538     * {any attributes with non-schema namespace . . .}>
6539     * Content: (appinfo | documentation)*
6540     */
6541     if ((ctxt == NULL) || (node == NULL))
6542         return (NULL);
6543     if (needed)
6544         ret = xmlSchemaNewAnnot(ctxt, node);
6545     else
6546         ret = NULL;
6547     attr = node->properties;
6548     while (attr != NULL) {
6549         if (((attr->ns == NULL) &&
6550             (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
6551             ((attr->ns != NULL) &&
6552             xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6553
6554             xmlSchemaPIllegalAttrErr(ctxt,
6555                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6556         }
6557         attr = attr->next;
6558     }
6559     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6560     /*
6561     * And now for the children...
6562     */
6563     child = node->children;
6564     while (child != NULL) {
6565         if (IS_SCHEMA(child, "appinfo")) {
6566             /* TODO: make available the content of "appinfo". */
6567             /*
6568             * source = anyURI
6569             * {any attributes with non-schema namespace . . .}>
6570             * Content: ({any})*
6571             */
6572             attr = child->properties;
6573             while (attr != NULL) {
6574                 if (((attr->ns == NULL) &&
6575                      (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
6576                      ((attr->ns != NULL) &&
6577                       xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6578
6579                     xmlSchemaPIllegalAttrErr(ctxt,
6580                         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6581                 }
6582                 attr = attr->next;
6583             }
6584             xmlSchemaPValAttr(ctxt, NULL, child, "source",
6585                 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
6586             child = child->next;
6587         } else if (IS_SCHEMA(child, "documentation")) {
6588             /* TODO: make available the content of "documentation". */
6589             /*
6590             * source = anyURI
6591             * {any attributes with non-schema namespace . . .}>
6592             * Content: ({any})*
6593             */
6594             attr = child->properties;
6595             while (attr != NULL) {
6596                 if (attr->ns == NULL) {
6597                     if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
6598                         xmlSchemaPIllegalAttrErr(ctxt,
6599                             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6600                     }
6601                 } else {
6602                     if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6603                         (xmlStrEqual(attr->name, BAD_CAST "lang") &&
6604                         (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
6605
6606                         xmlSchemaPIllegalAttrErr(ctxt,
6607                             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6608                     }
6609                 }
6610                 attr = attr->next;
6611             }
6612             /*
6613             * Attribute "xml:lang".
6614             */
6615             attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6616             if (attr != NULL)
6617                 xmlSchemaPValAttrNode(ctxt, NULL, attr,
6618                 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
6619             child = child->next;
6620         } else {
6621             if (!barked)
6622                 xmlSchemaPContentErr(ctxt,
6623                     XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6624                     NULL, node, child, NULL, "(appinfo | documentation)*");
6625             barked = 1;
6626             child = child->next;
6627         }
6628     }
6629
6630     return (ret);
6631 }
6632
6633 /**
6634  * xmlSchemaParseFacet:
6635  * @ctxt:  a schema validation context
6636  * @schema:  the schema being built
6637  * @node:  a subtree containing XML Schema informations
6638  *
6639  * parse a XML schema Facet declaration
6640  * *WARNING* this interface is highly subject to change
6641  *
6642  * Returns the new type structure or NULL in case of error
6643  */
6644 static xmlSchemaFacetPtr
6645 xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6646                     xmlNodePtr node)
6647 {
6648     xmlSchemaFacetPtr facet;
6649     xmlNodePtr child = NULL;
6650     const xmlChar *value;
6651
6652     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6653         return (NULL);
6654
6655     facet = xmlSchemaNewFacet();
6656     if (facet == NULL) {
6657         xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6658         return (NULL);
6659     }
6660     facet->node = node;
6661     value = xmlSchemaGetProp(ctxt, node, "value");
6662     if (value == NULL) {
6663         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6664                        "Facet %s has no value\n", node->name, NULL);
6665         xmlSchemaFreeFacet(facet);
6666         return (NULL);
6667     }
6668     if (IS_SCHEMA(node, "minInclusive")) {
6669         facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
6670     } else if (IS_SCHEMA(node, "minExclusive")) {
6671         facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
6672     } else if (IS_SCHEMA(node, "maxInclusive")) {
6673         facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
6674     } else if (IS_SCHEMA(node, "maxExclusive")) {
6675         facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
6676     } else if (IS_SCHEMA(node, "totalDigits")) {
6677         facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
6678     } else if (IS_SCHEMA(node, "fractionDigits")) {
6679         facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
6680     } else if (IS_SCHEMA(node, "pattern")) {
6681         facet->type = XML_SCHEMA_FACET_PATTERN;
6682     } else if (IS_SCHEMA(node, "enumeration")) {
6683         facet->type = XML_SCHEMA_FACET_ENUMERATION;
6684     } else if (IS_SCHEMA(node, "whiteSpace")) {
6685         facet->type = XML_SCHEMA_FACET_WHITESPACE;
6686     } else if (IS_SCHEMA(node, "length")) {
6687         facet->type = XML_SCHEMA_FACET_LENGTH;
6688     } else if (IS_SCHEMA(node, "maxLength")) {
6689         facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6690     } else if (IS_SCHEMA(node, "minLength")) {
6691         facet->type = XML_SCHEMA_FACET_MINLENGTH;
6692     } else {
6693         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6694                        "Unknown facet type %s\n", node->name, NULL);
6695         xmlSchemaFreeFacet(facet);
6696         return (NULL);
6697     }
6698     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6699     facet->value = value;
6700     if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6701         (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6702         const xmlChar *fixed;
6703
6704         fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6705         if (fixed != NULL) {
6706             if (xmlStrEqual(fixed, BAD_CAST "true"))
6707                 facet->fixed = 1;
6708         }
6709     }
6710     child = node->children;
6711
6712     if (IS_SCHEMA(child, "annotation")) {
6713         facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6714         child = child->next;
6715     }
6716     if (child != NULL) {
6717         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6718                        "Facet %s has unexpected child content\n",
6719                        node->name, NULL);
6720     }
6721     return (facet);
6722 }
6723
6724 /**
6725  * xmlSchemaParseWildcardNs:
6726  * @ctxt:  a schema parser context
6727  * @wildc:  the wildcard, already created
6728  * @node:  a subtree containing XML Schema informations
6729  *
6730  * Parses the attribute "processContents" and "namespace"
6731  * of a xsd:anyAttribute and xsd:any.
6732  * *WARNING* this interface is highly subject to change
6733  *
6734  * Returns 0 if everything goes fine, a positive error code
6735  * if something is not valid and -1 if an internal error occurs.
6736  */
6737 static int
6738 xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
6739                          xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6740                          xmlSchemaWildcardPtr wildc,
6741                          xmlNodePtr node)
6742 {
6743     const xmlChar *pc, *ns, *dictnsItem;
6744     int ret = 0;
6745     xmlChar *nsItem;
6746     xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6747     xmlAttrPtr attr;
6748
6749     pc = xmlSchemaGetProp(ctxt, node, "processContents");
6750     if ((pc == NULL)
6751         || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6752         wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6753     } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6754         wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6755     } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6756         wildc->processContents = XML_SCHEMAS_ANY_LAX;
6757     } else {
6758         xmlSchemaPSimpleTypeErr(ctxt,
6759             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6760             NULL, node,
6761             NULL, "(strict | skip | lax)", pc,
6762             NULL, NULL, NULL);
6763         wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6764         ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6765     }
6766     /*
6767      * Build the namespace constraints.
6768      */
6769     attr = xmlSchemaGetPropNode(node, "namespace");
6770     ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6771     if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
6772         wildc->any = 1;
6773     else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6774         wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6775         if (wildc->negNsSet == NULL) {
6776             return (-1);
6777         }
6778         wildc->negNsSet->value = ctxt->targetNamespace;
6779     } else {
6780         const xmlChar *end, *cur;
6781
6782         cur = ns;
6783         do {
6784             while (IS_BLANK_CH(*cur))
6785                 cur++;
6786             end = cur;
6787             while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6788                 end++;
6789             if (end == cur)
6790                 break;
6791             nsItem = xmlStrndup(cur, end - cur);
6792             if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6793                     (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
6794                 xmlSchemaPSimpleTypeErr(ctxt,
6795                     XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
6796                     NULL, (xmlNodePtr) attr,
6797                     NULL,
6798                     "((##any | ##other) | List of (xs:anyURI | "
6799                     "(##targetNamespace | ##local)))",
6800                     nsItem, NULL, NULL, NULL);
6801                 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6802             } else {
6803                 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
6804                     dictnsItem = ctxt->targetNamespace;
6805                 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6806                     dictnsItem = NULL;
6807                 } else {
6808                     /*
6809                     * Validate the item (anyURI).
6810                     */
6811                     xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
6812                         nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6813                     dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6814                 }
6815                 /*
6816                 * Avoid dublicate namespaces.
6817                 */
6818                 tmp = wildc->nsSet;
6819                 while (tmp != NULL) {
6820                     if (dictnsItem == tmp->value)
6821                         break;
6822                     tmp = tmp->next;
6823                 }
6824                 if (tmp == NULL) {
6825                     tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6826                     if (tmp == NULL) {
6827                         xmlFree(nsItem);
6828                         return (-1);
6829                     }
6830                     tmp->value = dictnsItem;
6831                     tmp->next = NULL;
6832                     if (wildc->nsSet == NULL)
6833                         wildc->nsSet = tmp;
6834                     else if (lastNs != NULL)
6835                         lastNs->next = tmp;
6836                     lastNs = tmp;
6837                 }
6838
6839             }
6840             xmlFree(nsItem);
6841             cur = end;
6842         } while (*cur != 0);
6843     }
6844     return (ret);
6845 }
6846
6847 static int
6848 xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6849                                  xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
6850                                  xmlNodePtr node,
6851                                  int minOccurs,
6852                                  int maxOccurs) {
6853
6854     if ((maxOccurs == 0) && ( minOccurs == 0))
6855         return (0);
6856     if (maxOccurs != UNBOUNDED) {
6857         /*
6858         * TODO: Maybe we should better not create the particle,
6859         * if min/max is invalid, since it could confuse the build of the
6860         * content model.
6861         */
6862         /*
6863         * 3.9.6 Schema Component Constraint: Particle Correct
6864         *
6865         */
6866         if (maxOccurs < 1) {
6867             /*
6868             * 2.2 {max occurs} must be greater than or equal to 1.
6869             */
6870             xmlSchemaPCustomAttrErr(ctxt,
6871                 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
6872                 NULL, NULL,
6873                 xmlSchemaGetPropNode(node, "maxOccurs"),
6874                 "The value must be greater than or equal to 1");
6875             return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6876         } else if (minOccurs > maxOccurs) {
6877             /*
6878             * 2.1 {min occurs} must not be greater than {max occurs}.
6879             */
6880             xmlSchemaPCustomAttrErr(ctxt,
6881                 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
6882                 NULL, NULL,
6883                 xmlSchemaGetPropNode(node, "minOccurs"),
6884                 "The value must not be greater than the value of 'maxOccurs'");
6885             return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6886         }
6887     }
6888     return (0);
6889 }
6890
6891 /**
6892  * xmlSchemaParseAny:
6893  * @ctxt:  a schema validation context
6894  * @schema:  the schema being built
6895  * @node:  a subtree containing XML Schema informations
6896  *
6897  * Parsea a XML schema <any> element. A particle and wildcard
6898  * will be created (except if minOccurs==maxOccurs==0, in this case
6899  * nothing will be created).
6900  * *WARNING* this interface is highly subject to change
6901  *
6902  * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
6903  */
6904 static xmlSchemaParticlePtr
6905 xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6906                   xmlNodePtr node)
6907 {
6908     xmlSchemaParticlePtr particle;
6909     xmlNodePtr child = NULL;
6910     xmlSchemaWildcardPtr wild;
6911     int min, max;
6912     xmlAttrPtr attr;
6913     xmlSchemaAnnotPtr annot = NULL;
6914
6915     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6916         return (NULL);
6917     /*
6918     * Check for illegal attributes.
6919     */
6920     attr = node->properties;
6921     while (attr != NULL) {
6922         if (attr->ns == NULL) {
6923             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6924                 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6925                 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6926                 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6927                 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
6928                 xmlSchemaPIllegalAttrErr(ctxt,
6929                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6930             }
6931         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6932             xmlSchemaPIllegalAttrErr(ctxt,
6933                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6934         }
6935         attr = attr->next;
6936     }
6937     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6938     /*
6939     * minOccurs/maxOccurs.
6940     */
6941     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6942         "(xs:nonNegativeInteger | unbounded)");
6943     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6944         "xs:nonNegativeInteger");
6945     xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6946     /*
6947     * Create & parse the wildcard.
6948     */
6949     wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6950     if (wild == NULL)
6951         return (NULL);
6952     xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
6953     /*
6954     * And now for the children...
6955     */
6956     child = node->children;
6957     if (IS_SCHEMA(child, "annotation")) {
6958         annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6959         child = child->next;
6960     }
6961     if (child != NULL) {
6962         xmlSchemaPContentErr(ctxt,
6963             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6964             NULL, node, child,
6965             NULL, "(annotation?)");
6966     }
6967     /*
6968     * No component if minOccurs==maxOccurs==0.
6969     */
6970     if ((min == 0) && (max == 0)) {
6971         /* Don't free the wildcard, since it's already on the list. */
6972         return (NULL);
6973     }
6974     /*
6975     * Create the particle.
6976     */
6977     particle = xmlSchemaAddParticle(ctxt, node, min, max);
6978     if (particle == NULL)
6979         return (NULL);
6980     particle->annot = annot;
6981     particle->children = (xmlSchemaTreeItemPtr) wild;
6982
6983     return (particle);
6984 }
6985
6986 /**
6987  * xmlSchemaParseNotation:
6988  * @ctxt:  a schema validation context
6989  * @schema:  the schema being built
6990  * @node:  a subtree containing XML Schema informations
6991  *
6992  * parse a XML schema Notation declaration
6993  *
6994  * Returns the new structure or NULL in case of error
6995  */
6996 static xmlSchemaNotationPtr
6997 xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6998                        xmlNodePtr node)
6999 {
7000     const xmlChar *name;
7001     xmlSchemaNotationPtr ret;
7002     xmlNodePtr child = NULL;
7003
7004     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7005         return (NULL);
7006     name = xmlSchemaGetProp(ctxt, node, "name");
7007     if (name == NULL) {
7008         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
7009                        "Notation has no name\n", NULL, NULL);
7010         return (NULL);
7011     }
7012     ret = xmlSchemaAddNotation(ctxt, schema, name,
7013         ctxt->targetNamespace, node);
7014     if (ret == NULL)
7015         return (NULL);
7016     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7017
7018     child = node->children;
7019     if (IS_SCHEMA(child, "annotation")) {
7020         ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7021         child = child->next;
7022     }
7023     if (child != NULL) {
7024         xmlSchemaPContentErr(ctxt,
7025             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7026             NULL, node, child,
7027             NULL, "(annotation?)");
7028     }
7029
7030     return (ret);
7031 }
7032
7033 /**
7034  * xmlSchemaParseAnyAttribute:
7035  * @ctxt:  a schema validation context
7036  * @schema:  the schema being built
7037  * @node:  a subtree containing XML Schema informations
7038  *
7039  * parse a XML schema AnyAttrribute declaration
7040  * *WARNING* this interface is highly subject to change
7041  *
7042  * Returns a wildcard or NULL.
7043  */
7044 static xmlSchemaWildcardPtr
7045 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
7046                            xmlSchemaPtr schema, xmlNodePtr node)
7047 {
7048     xmlSchemaWildcardPtr ret;
7049     xmlNodePtr child = NULL;
7050     xmlAttrPtr attr;
7051
7052     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7053         return (NULL);
7054
7055     ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
7056         node);
7057     if (ret == NULL) {
7058         return (NULL);
7059     }
7060     /*
7061     * Check for illegal attributes.
7062     */
7063     attr = node->properties;
7064     while (attr != NULL) {
7065         if (attr->ns == NULL) {
7066             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7067                 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7068                 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
7069                 xmlSchemaPIllegalAttrErr(ctxt,
7070                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7071             }
7072         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7073             xmlSchemaPIllegalAttrErr(ctxt,
7074                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7075         }
7076         attr = attr->next;
7077     }
7078     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7079     /*
7080     * Parse the namespace list.
7081     */
7082     if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
7083         return (NULL);
7084     /*
7085     * And now for the children...
7086     */
7087     child = node->children;
7088     if (IS_SCHEMA(child, "annotation")) {
7089         ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7090         child = child->next;
7091     }
7092     if (child != NULL) {
7093         xmlSchemaPContentErr(ctxt,
7094             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7095             NULL, node, child,
7096             NULL, "(annotation?)");
7097     }
7098
7099     return (ret);
7100 }
7101
7102
7103 /**
7104  * xmlSchemaParseAttribute:
7105  * @ctxt:  a schema validation context
7106  * @schema:  the schema being built
7107  * @node:  a subtree containing XML Schema informations
7108  *
7109  * parse a XML schema Attrribute declaration
7110  * *WARNING* this interface is highly subject to change
7111  *
7112  * Returns the attribute declaration.
7113  */
7114 static xmlSchemaBasicItemPtr
7115 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7116                              xmlSchemaPtr schema,
7117                              xmlNodePtr node,
7118                              xmlSchemaItemListPtr uses,
7119                              int parentType)
7120 {
7121     const xmlChar *attrValue, *name = NULL, *ns = NULL;
7122     xmlSchemaAttributeUsePtr use = NULL;
7123     xmlNodePtr child = NULL;
7124     xmlAttrPtr attr;
7125     const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7126     int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7127     int nberrors, hasForm = 0, defValueType = 0;
7128
7129 #define WXS_ATTR_DEF_VAL_DEFAULT 1
7130 #define WXS_ATTR_DEF_VAL_FIXED 2
7131
7132     /*
7133      * 3.2.3 Constraints on XML Representations of Attribute Declarations
7134      */
7135
7136     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7137         return (NULL);
7138     attr = xmlSchemaGetPropNode(node, "ref");
7139     if (attr != NULL) {
7140         if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7141             NULL, attr, &tmpNs, &tmpName) != 0) {
7142             return (NULL);
7143         }
7144         if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7145             return(NULL);
7146         isRef = 1;
7147     }
7148     nberrors = pctxt->nberrors;
7149     /*
7150     * Check for illegal attributes.
7151     */
7152     attr = node->properties;
7153     while (attr != NULL) {
7154         if (attr->ns == NULL) {
7155             if (isRef) {
7156                 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7157                     xmlSchemaPValAttrNodeID(pctxt, attr);
7158                     goto attr_next;
7159                 } else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7160                     goto attr_next;
7161                 }
7162             } else {
7163                 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7164                     goto attr_next;
7165                 } else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7166                     xmlSchemaPValAttrNodeID(pctxt, attr);
7167                     goto attr_next;
7168                 } else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7169                     xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7170                         attr, &tmpNs, &tmpName);
7171                     goto attr_next;
7172                 } else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7173                     /*
7174                     * Evaluate the target namespace
7175                     */
7176                     hasForm = 1;
7177                     attrValue = xmlSchemaGetNodeContent(pctxt,
7178                         (xmlNodePtr) attr);
7179                     if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7180                         ns = pctxt->targetNamespace;
7181                     } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7182                     {
7183                         xmlSchemaPSimpleTypeErr(pctxt,
7184                             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7185                             NULL, (xmlNodePtr) attr,
7186                             NULL, "(qualified | unqualified)",
7187                             attrValue, NULL, NULL, NULL);
7188                     }
7189                     goto attr_next;
7190                 }
7191             }
7192             if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7193
7194                 attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7195                 /* TODO: Maybe we need to normalize the value beforehand. */
7196                 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7197                     occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7198                 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7199                     occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7200                 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7201                     occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7202                 else {
7203                     xmlSchemaPSimpleTypeErr(pctxt,
7204                         XML_SCHEMAP_INVALID_ATTR_USE,
7205                         NULL, (xmlNodePtr) attr,
7206                         NULL, "(optional | prohibited | required)",
7207                         attrValue, NULL, NULL, NULL);
7208                 }
7209                 goto attr_next;
7210             } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7211                 /*
7212                 * 3.2.3 : 1
7213                 * default and fixed must not both be present.
7214                 */
7215                 if (defValue) {
7216                     xmlSchemaPMutualExclAttrErr(pctxt,
7217                         XML_SCHEMAP_SRC_ATTRIBUTE_1,
7218                         NULL, attr, "default", "fixed");
7219                 } else {
7220                     defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7221                     defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7222                 }
7223                 goto attr_next;
7224             } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7225                 /*
7226                 * 3.2.3 : 1
7227                 * default and fixed must not both be present.
7228                 */
7229                 if (defValue) {
7230                     xmlSchemaPMutualExclAttrErr(pctxt,
7231                         XML_SCHEMAP_SRC_ATTRIBUTE_1,
7232                         NULL, attr, "default", "fixed");
7233                 } else {
7234                     defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7235                     defValueType = WXS_ATTR_DEF_VAL_FIXED;
7236                 }
7237                 goto attr_next;
7238             }
7239         } else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7240             goto attr_next;
7241
7242         xmlSchemaPIllegalAttrErr(pctxt,
7243             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7244
7245 attr_next:
7246         attr = attr->next;
7247     }
7248     /*
7249     * 3.2.3 : 2
7250     * If default and use are both present, use must have
7251     * the actual value optional.
7252     */
7253     if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7254         (occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7255         xmlSchemaPSimpleTypeErr(pctxt,
7256             XML_SCHEMAP_SRC_ATTRIBUTE_2,
7257             NULL, node, NULL,
7258             "(optional | prohibited | required)", NULL,
7259             "The value of the attribute 'use' must be 'optional' "
7260             "if the attribute 'default' is present",
7261             NULL, NULL);
7262     }
7263     /*
7264     * We want correct attributes.
7265     */
7266     if (nberrors != pctxt->nberrors)
7267         return(NULL);
7268     if (! isRef) {
7269         xmlSchemaAttributePtr attrDecl;
7270
7271         /* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7272         if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7273             ns = pctxt->targetNamespace;
7274         /*
7275         * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7276         * TODO: Move this to the component layer.
7277         */
7278         if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7279             xmlSchemaCustomErr(ACTXT_CAST pctxt,
7280                 XML_SCHEMAP_NO_XSI,
7281                 node, NULL,
7282                 "The target namespace must not match '%s'",
7283                 xmlSchemaInstanceNs, NULL);
7284         }
7285         attr = xmlSchemaGetPropNode(node, "name");
7286         if (attr == NULL) {
7287             xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7288                 NULL, node, "name", NULL);
7289             return (NULL);
7290         }
7291         if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7292             xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7293             return (NULL);
7294         }
7295         /*
7296         * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7297         * TODO: Move this to the component layer.
7298         */
7299         if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7300             xmlSchemaPSimpleTypeErr(pctxt,
7301                 XML_SCHEMAP_NO_XMLNS,
7302                 NULL, (xmlNodePtr) attr,
7303                 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7304                 "The value of the attribute must not match 'xmlns'",
7305                 NULL, NULL);
7306             return (NULL);
7307         }
7308         if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7309             goto check_children;
7310         /*
7311         * Create the attribute use component.
7312         */
7313         use = xmlSchemaAddAttributeUse(pctxt, node);
7314         if (use == NULL)
7315             return(NULL);
7316         use->occurs = occurs;
7317         /*
7318         * Create the attribute declaration.
7319         */
7320         attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7321         if (attrDecl == NULL)
7322             return (NULL);
7323         if (tmpName != NULL) {
7324             attrDecl->typeName = tmpName;
7325             attrDecl->typeNs = tmpNs;
7326         }
7327         use->attrDecl = attrDecl;
7328         /*
7329         * Value constraint.
7330         */
7331         if (defValue != NULL) {
7332             attrDecl->defValue = defValue;
7333             if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7334                 attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7335         }
7336     } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7337         xmlSchemaQNameRefPtr ref;
7338
7339         /*
7340         * Create the attribute use component.
7341         */
7342         use = xmlSchemaAddAttributeUse(pctxt, node);
7343         if (use == NULL)
7344             return(NULL);
7345         /*
7346         * We need to resolve the reference at later stage.
7347         */
7348         WXS_ADD_PENDING(pctxt, use);
7349         use->occurs = occurs;
7350         /*
7351         * Create a QName reference to the attribute declaration.
7352         */
7353         ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7354             tmpName, tmpNs);
7355         if (ref == NULL)
7356             return(NULL);
7357         /*
7358         * Assign the reference. This will be substituted for the
7359         * referenced attribute declaration when the QName is resolved.
7360         */
7361         use->attrDecl = WXS_ATTR_CAST ref;
7362         /*
7363         * Value constraint.
7364         */
7365         if (defValue != NULL)
7366             use->defValue = defValue;
7367             if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7368                 use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7369     }
7370
7371 check_children:
7372     /*
7373     * And now for the children...
7374     */
7375     child = node->children;
7376     if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7377         xmlSchemaAttributeUseProhibPtr prohib;
7378
7379         if (IS_SCHEMA(child, "annotation")) {
7380             xmlSchemaParseAnnotation(pctxt, child, 0);
7381             child = child->next;
7382         }
7383         if (child != NULL) {
7384             xmlSchemaPContentErr(pctxt,
7385                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7386                 NULL, node, child, NULL,
7387                 "(annotation?)");
7388         }
7389         /*
7390         * Check for pointlessness of attribute prohibitions.
7391         */
7392         if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7393             xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7394                 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7395                 node, NULL,
7396                 "Skipping attribute use prohibition, since it is "
7397                 "pointless inside an <attributeGroup>",
7398                 NULL, NULL, NULL);
7399             return(NULL);
7400         } else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7401             xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7402                 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7403                 node, NULL,
7404                 "Skipping attribute use prohibition, since it is "
7405                 "pointless when extending a type",
7406                 NULL, NULL, NULL);
7407             return(NULL);
7408         }
7409         if (! isRef) {
7410             tmpName = name;
7411             tmpNs = ns;
7412         }
7413         /*
7414         * Check for duplicate attribute prohibitions.
7415         */
7416         if (uses) {
7417             int i;
7418
7419             for (i = 0; i < uses->nbItems; i++) {
7420                 use = uses->items[i];
7421                 if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7422                     (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7423                     (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7424                 {
7425                     xmlChar *str = NULL;
7426
7427                     xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7428                         XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7429                         node, NULL,
7430                         "Skipping duplicate attribute use prohibition '%s'",
7431                         xmlSchemaFormatQName(&str, tmpNs, tmpName),
7432                         NULL, NULL);
7433                     FREE_AND_NULL(str)
7434                     return(NULL);
7435                 }
7436             }
7437         }
7438         /*
7439         * Create the attribute prohibition helper component.
7440         */
7441         prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7442         if (prohib == NULL)
7443             return(NULL);
7444         prohib->node = node;
7445         prohib->name = tmpName;
7446         prohib->targetNamespace = tmpNs;
7447         if (isRef) {
7448             /*
7449             * We need at least to resolve to the attribute declaration.
7450             */
7451             WXS_ADD_PENDING(pctxt, prohib);
7452         }
7453         return(WXS_BASIC_CAST prohib);
7454     } else {
7455         if (IS_SCHEMA(child, "annotation")) {
7456             /*
7457             * TODO: Should this go into the attr decl?
7458             */
7459             use->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7460             child = child->next;
7461         }
7462         if (isRef) {
7463             if (child != NULL) {
7464                 if (IS_SCHEMA(child, "simpleType"))
7465                     /*
7466                     * 3.2.3 : 3.2
7467                     * If ref is present, then all of <simpleType>,
7468                     * form and type must be absent.
7469                     */
7470                     xmlSchemaPContentErr(pctxt,
7471                         XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7472                         NULL, node, child, NULL,
7473                         "(annotation?)");
7474                 else
7475                     xmlSchemaPContentErr(pctxt,
7476                         XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7477                         NULL, node, child, NULL,
7478                         "(annotation?)");
7479             }
7480         } else {
7481             if (IS_SCHEMA(child, "simpleType")) {
7482                 if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7483                     /*
7484                     * 3.2.3 : 4
7485                     * type and <simpleType> must not both be present.
7486                     */
7487                     xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7488                         NULL, node, child,
7489                         "The attribute 'type' and the <simpleType> child "
7490                         "are mutually exclusive", NULL);
7491                 } else
7492                     WXS_ATTRUSE_TYPEDEF(use) =
7493                         xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7494                 child = child->next;
7495             }
7496             if (child != NULL)
7497                 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7498                 NULL, node, child, NULL,
7499                 "(annotation?, simpleType?)");
7500         }
7501     }
7502     return (WXS_BASIC_CAST use);
7503 }
7504
7505
7506 static xmlSchemaAttributePtr
7507 xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7508                               xmlSchemaPtr schema,
7509                               xmlNodePtr node)
7510 {
7511     const xmlChar *attrValue;
7512     xmlSchemaAttributePtr ret;
7513     xmlNodePtr child = NULL;
7514     xmlAttrPtr attr;
7515
7516     /*
7517      * Note that the w3c spec assumes the schema to be validated with schema
7518      * for schemas beforehand.
7519      *
7520      * 3.2.3 Constraints on XML Representations of Attribute Declarations
7521      */
7522     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7523         return (NULL);
7524     /*
7525     * 3.2.3 : 3.1
7526     * One of ref or name must be present, but not both
7527     */
7528     attr = xmlSchemaGetPropNode(node, "name");
7529     if (attr == NULL) {
7530         xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7531             NULL, node, "name", NULL);
7532         return (NULL);
7533     }
7534     if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7535         xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7536         return (NULL);
7537     }
7538     /*
7539     * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7540     * TODO: Move this to the component layer.
7541     */
7542     if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7543         xmlSchemaPSimpleTypeErr(pctxt,
7544             XML_SCHEMAP_NO_XMLNS,
7545             NULL, (xmlNodePtr) attr,
7546             xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7547             "The value of the attribute must not match 'xmlns'",
7548             NULL, NULL);
7549         return (NULL);
7550     }
7551     /*
7552     * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7553     * TODO: Move this to the component layer.
7554     *       Or better leave it here and add it to the component layer
7555     *       if we have a schema construction API.
7556     */
7557     if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7558         xmlSchemaCustomErr(ACTXT_CAST pctxt,
7559             XML_SCHEMAP_NO_XSI, node, NULL,
7560             "The target namespace must not match '%s'",
7561             xmlSchemaInstanceNs, NULL);
7562     }
7563
7564     ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7565         pctxt->targetNamespace, node, 1);
7566     if (ret == NULL)
7567         return (NULL);
7568     ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7569
7570     /*
7571     * Check for illegal attributes.
7572     */
7573     attr = node->properties;
7574     while (attr != NULL) {
7575         if (attr->ns == NULL) {
7576             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7577                 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7578                 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7579                 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7580                 (!xmlStrEqual(attr->name, BAD_CAST "type")))
7581             {
7582                 xmlSchemaPIllegalAttrErr(pctxt,
7583                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7584             }
7585         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7586             xmlSchemaPIllegalAttrErr(pctxt,
7587                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7588         }
7589         attr = attr->next;
7590     }
7591     xmlSchemaPValAttrQName(pctxt, schema, NULL,
7592         node, "type", &ret->typeNs, &ret->typeName);
7593
7594     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7595     /*
7596     * Attribute "fixed".
7597     */
7598     ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
7599     if (ret->defValue != NULL)
7600         ret->flags |= XML_SCHEMAS_ATTR_FIXED;
7601     /*
7602     * Attribute "default".
7603     */
7604     attr = xmlSchemaGetPropNode(node, "default");
7605     if (attr != NULL) {
7606         /*
7607         * 3.2.3 : 1
7608         * default and fixed must not both be present.
7609         */
7610         if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
7611             xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7612                 WXS_BASIC_CAST ret, attr, "default", "fixed");
7613         } else
7614             ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7615     }
7616     /*
7617     * And now for the children...
7618     */
7619     child = node->children;
7620     if (IS_SCHEMA(child, "annotation")) {
7621         ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7622         child = child->next;
7623     }
7624     if (IS_SCHEMA(child, "simpleType")) {
7625         if (ret->typeName != NULL) {
7626             /*
7627             * 3.2.3 : 4
7628             * type and <simpleType> must not both be present.
7629             */
7630             xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7631                 NULL, node, child,
7632                 "The attribute 'type' and the <simpleType> child "
7633                 "are mutually exclusive", NULL);
7634         } else
7635             ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7636         child = child->next;
7637     }
7638     if (child != NULL)
7639         xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7640             NULL, node, child, NULL,
7641             "(annotation?, simpleType?)");
7642
7643     return (ret);
7644 }
7645
7646 /**
7647  * xmlSchemaParseAttributeGroupRef:
7648  * @ctxt:  a schema validation context
7649  * @schema:  the schema being built
7650  * @node:  a subtree containing XML Schema informations
7651  *
7652  * Parse an attribute group definition reference.
7653  * Note that a reference to an attribute group does not
7654  * correspond to any component at all.
7655  * *WARNING* this interface is highly subject to change
7656  *
7657  * Returns the attribute group or NULL in case of error.
7658  */
7659 static xmlSchemaQNameRefPtr
7660 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7661                                 xmlSchemaPtr schema,
7662                                 xmlNodePtr node)
7663 {
7664     xmlSchemaQNameRefPtr ret;
7665     xmlNodePtr child = NULL;
7666     xmlAttrPtr attr;
7667     const xmlChar *refNs = NULL, *ref = NULL;
7668
7669     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7670         return (NULL);
7671
7672     attr = xmlSchemaGetPropNode(node, "ref");
7673     if (attr == NULL) {
7674         xmlSchemaPMissingAttrErr(pctxt,
7675             XML_SCHEMAP_S4S_ATTR_MISSING,
7676             NULL, node, "ref", NULL);
7677         return (NULL);
7678     }
7679     xmlSchemaPValAttrNodeQName(pctxt, schema,
7680         NULL, attr, &refNs, &ref);
7681     if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7682         return(NULL);
7683
7684     /*
7685     * Check for illegal attributes.
7686     */
7687     attr = node->properties;
7688     while (attr != NULL) {
7689         if (attr->ns == NULL) {
7690             if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
7691                 (!xmlStrEqual(attr->name, BAD_CAST "id")))
7692             {
7693                 xmlSchemaPIllegalAttrErr(pctxt,
7694                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7695             }
7696         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7697             xmlSchemaPIllegalAttrErr(pctxt,
7698                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7699         }
7700         attr = attr->next;
7701     }
7702     /* Attribute ID */
7703     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7704
7705     /*
7706     * And now for the children...
7707     */
7708     child = node->children;
7709     if (IS_SCHEMA(child, "annotation")) {
7710         /*
7711         * TODO: We do not have a place to store the annotation, do we?
7712         */
7713         xmlSchemaParseAnnotation(pctxt, child, 0);
7714         child = child->next;
7715     }
7716     if (child != NULL) {
7717         xmlSchemaPContentErr(pctxt,
7718             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7719             NULL, node, child, NULL,
7720             "(annotation?)");
7721     }
7722
7723     /*
7724     * Handle attribute group redefinitions.
7725     */
7726     if (pctxt->isRedefine && pctxt->redef &&
7727         (pctxt->redef->item->type ==
7728             XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7729         (ref == pctxt->redef->refName) &&
7730         (refNs == pctxt->redef->refTargetNs))
7731     {
7732         /*
7733         * SPEC src-redefine:
7734         * (7.1) "If it has an <attributeGroup> among its contents
7735         * the `actual value` of whose ref [attribute] is the same
7736         * as the `actual value` of its own name attribute plus
7737         * target namespace, then it must have exactly one such group."
7738         */
7739         if (pctxt->redefCounter != 0) {
7740             xmlChar *str = NULL;
7741
7742             xmlSchemaCustomErr(ACTXT_CAST pctxt,
7743                 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7744                 "The redefining attribute group definition "
7745                 "'%s' must not contain more than one "
7746                 "reference to the redefined definition",
7747                 xmlSchemaFormatQName(&str, refNs, ref), NULL);
7748             FREE_AND_NULL(str);
7749             return(NULL);
7750         }
7751         pctxt->redefCounter++;
7752         /*
7753         * URGENT TODO: How to ensure that the reference will not be
7754         * handled by the normal component resolution mechanism?
7755         */
7756         ret = xmlSchemaNewQNameRef(pctxt,
7757             XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7758         if (ret == NULL)
7759             return(NULL);
7760         ret->node = node;
7761         pctxt->redef->reference = WXS_BASIC_CAST ret;
7762     } else {
7763         /*
7764         * Create a QName-reference helper component. We will substitute this
7765         * component for the attribute uses of the referenced attribute group
7766         * definition.
7767         */
7768         ret = xmlSchemaNewQNameRef(pctxt,
7769             XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7770         if (ret == NULL)
7771             return(NULL);
7772         ret->node = node;
7773         /* Add to pending items, to be able to resolve the reference. */
7774         WXS_ADD_PENDING(pctxt, ret);
7775     }
7776     return (ret);
7777 }
7778
7779 /**
7780  * xmlSchemaParseAttributeGroupDefinition:
7781  * @pctxt:  a schema validation context
7782  * @schema:  the schema being built
7783  * @node:  a subtree containing XML Schema informations
7784  *
7785  * parse a XML schema Attribute Group declaration
7786  * *WARNING* this interface is highly subject to change
7787  *
7788  * Returns the attribute group definition or NULL in case of error.
7789  */
7790 static xmlSchemaAttributeGroupPtr
7791 xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7792                                        xmlSchemaPtr schema,
7793                                        xmlNodePtr node)
7794 {
7795     const xmlChar *name;
7796     xmlSchemaAttributeGroupPtr ret;
7797     xmlNodePtr child = NULL;
7798     xmlAttrPtr attr;
7799     int hasRefs = 0;
7800
7801     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7802         return (NULL);
7803
7804     attr = xmlSchemaGetPropNode(node, "name");
7805     if (attr == NULL) {
7806         xmlSchemaPMissingAttrErr(pctxt,
7807             XML_SCHEMAP_S4S_ATTR_MISSING,
7808             NULL, node, "name", NULL);
7809         return (NULL);
7810     }
7811     /*
7812     * The name is crucial, exit if invalid.
7813     */
7814     if (xmlSchemaPValAttrNode(pctxt,
7815         NULL, attr,
7816         xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7817         return (NULL);
7818     }
7819     ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7820         name, pctxt->targetNamespace, node);
7821     if (ret == NULL)
7822         return (NULL);
7823     /*
7824     * Check for illegal attributes.
7825     */
7826     attr = node->properties;
7827     while (attr != NULL) {
7828         if (attr->ns == NULL) {
7829             if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7830                 (!xmlStrEqual(attr->name, BAD_CAST "id")))
7831             {
7832                 xmlSchemaPIllegalAttrErr(pctxt,
7833                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7834             }
7835         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7836             xmlSchemaPIllegalAttrErr(pctxt,
7837                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7838         }
7839         attr = attr->next;
7840     }
7841     /* Attribute ID */
7842     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7843     /*
7844     * And now for the children...
7845     */
7846     child = node->children;
7847     if (IS_SCHEMA(child, "annotation")) {
7848         ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7849         child = child->next;
7850     }
7851     /*
7852     * Parse contained attribute decls/refs.
7853     */
7854     if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7855         (xmlSchemaItemListPtr *) &(ret->attrUses),
7856         XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7857         return(NULL);
7858     if (hasRefs)
7859         ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7860     /*
7861     * Parse the attribute wildcard.
7862     */
7863     if (IS_SCHEMA(child, "anyAttribute")) {
7864         ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7865             schema, child);
7866         child = child->next;
7867     }
7868     if (child != NULL) {
7869         xmlSchemaPContentErr(pctxt,
7870             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7871             NULL, node, child, NULL,
7872             "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
7873     }
7874     return (ret);
7875 }
7876
7877 /**
7878  * xmlSchemaPValAttrFormDefault:
7879  * @value:  the value
7880  * @flags: the flags to be modified
7881  * @flagQualified: the specific flag for "qualified"
7882  *
7883  * Returns 0 if the value is valid, 1 otherwise.
7884  */
7885 static int
7886 xmlSchemaPValAttrFormDefault(const xmlChar *value,
7887                              int *flags,
7888                              int flagQualified)
7889 {
7890     if (xmlStrEqual(value, BAD_CAST "qualified")) {
7891         if  ((*flags & flagQualified) == 0)
7892             *flags |= flagQualified;
7893     } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
7894         return (1);
7895
7896     return (0);
7897 }
7898
7899 /**
7900  * xmlSchemaPValAttrBlockFinal:
7901  * @value:  the value
7902  * @flags: the flags to be modified
7903  * @flagAll: the specific flag for "#all"
7904  * @flagExtension: the specific flag for "extension"
7905  * @flagRestriction: the specific flag for "restriction"
7906  * @flagSubstitution: the specific flag for "substitution"
7907  * @flagList: the specific flag for "list"
7908  * @flagUnion: the specific flag for "union"
7909  *
7910  * Validates the value of the attribute "final" and "block". The value
7911  * is converted into the specified flag values and returned in @flags.
7912  *
7913  * Returns 0 if the value is valid, 1 otherwise.
7914  */
7915
7916 static int
7917 xmlSchemaPValAttrBlockFinal(const xmlChar *value,
7918                             int *flags,
7919                             int flagAll,
7920                             int flagExtension,
7921                             int flagRestriction,
7922                             int flagSubstitution,
7923                             int flagList,
7924                             int flagUnion)
7925 {
7926     int ret = 0;
7927
7928     /*
7929     * TODO: This does not check for dublicate entries.
7930     */
7931     if ((flags == NULL) || (value == NULL))
7932         return (-1);
7933     if (value[0] == 0)
7934         return (0);
7935     if (xmlStrEqual(value, BAD_CAST "#all")) {
7936         if (flagAll != -1)
7937             *flags |= flagAll;
7938         else {
7939             if (flagExtension != -1)
7940                 *flags |= flagExtension;
7941             if (flagRestriction != -1)
7942                 *flags |= flagRestriction;
7943             if (flagSubstitution != -1)
7944                 *flags |= flagSubstitution;
7945             if (flagList != -1)
7946                 *flags |= flagList;
7947             if (flagUnion != -1)
7948                 *flags |= flagUnion;
7949         }
7950     } else {
7951         const xmlChar *end, *cur = value;
7952         xmlChar *item;
7953
7954         do {
7955             while (IS_BLANK_CH(*cur))
7956                 cur++;
7957             end = cur;
7958             while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7959                 end++;
7960             if (end == cur)
7961                 break;
7962             item = xmlStrndup(cur, end - cur);
7963             if (xmlStrEqual(item, BAD_CAST "extension")) {
7964                 if (flagExtension != -1) {
7965                     if ((*flags & flagExtension) == 0)
7966                         *flags |= flagExtension;
7967                 } else
7968                     ret = 1;
7969             } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
7970                 if (flagRestriction != -1) {
7971                     if ((*flags & flagRestriction) == 0)
7972                         *flags |= flagRestriction;
7973                 } else
7974                     ret = 1;
7975             } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
7976                 if (flagSubstitution != -1) {
7977                     if ((*flags & flagSubstitution) == 0)
7978                         *flags |= flagSubstitution;
7979                 } else
7980                     ret = 1;
7981             } else if (xmlStrEqual(item, BAD_CAST "list")) {
7982                 if (flagList != -1) {
7983                     if ((*flags & flagList) == 0)
7984                         *flags |= flagList;
7985                 } else
7986                     ret = 1;
7987             } else if (xmlStrEqual(item, BAD_CAST "union")) {
7988                 if (flagUnion != -1) {
7989                     if ((*flags & flagUnion) == 0)
7990                         *flags |= flagUnion;
7991                 } else
7992                     ret = 1;
7993             } else
7994                 ret = 1;
7995             if (item != NULL)
7996                 xmlFree(item);
7997             cur = end;
7998         } while ((ret == 0) && (*cur != 0));
7999     }
8000
8001     return (ret);
8002 }
8003
8004 static int
8005 xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
8006                              xmlSchemaIDCPtr idc,
8007                              xmlSchemaIDCSelectPtr selector,
8008                              xmlAttrPtr attr,
8009                              int isField)
8010 {
8011     xmlNodePtr node;
8012
8013     /*
8014     * c-selector-xpath:
8015     * Schema Component Constraint: Selector Value OK
8016     *
8017     * TODO: 1 The {selector} must be a valid XPath expression, as defined
8018     * in [XPath].
8019     */
8020     if (selector == NULL) {
8021         xmlSchemaPErr(ctxt, idc->node,
8022             XML_SCHEMAP_INTERNAL,
8023             "Internal error: xmlSchemaCheckCSelectorXPath, "
8024             "the selector is not specified.\n", NULL, NULL);
8025         return (-1);
8026     }
8027     if (attr == NULL)
8028         node = idc->node;
8029     else
8030         node = (xmlNodePtr) attr;
8031     if (selector->xpath == NULL) {
8032         xmlSchemaPCustomErr(ctxt,
8033             /* TODO: Adjust error code. */
8034             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8035             NULL, node,
8036             "The XPath expression of the selector is not valid", NULL);
8037         return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8038     } else {
8039         const xmlChar **nsArray = NULL;
8040         xmlNsPtr *nsList = NULL;
8041         /*
8042         * Compile the XPath expression.
8043         */
8044         /*
8045         * TODO: We need the array of in-scope namespaces for compilation.
8046         * TODO: Call xmlPatterncompile with different options for selector/
8047         * field.
8048         */
8049         if (attr == NULL)
8050             nsList = NULL;
8051         else
8052             nsList = xmlGetNsList(attr->doc, attr->parent);
8053         /*
8054         * Build an array of prefixes and namespaces.
8055         */
8056         if (nsList != NULL) {
8057             int i, count = 0;
8058
8059             for (i = 0; nsList[i] != NULL; i++)
8060                 count++;
8061
8062             nsArray = (const xmlChar **) xmlMalloc(
8063                 (count * 2 + 1) * sizeof(const xmlChar *));
8064             if (nsArray == NULL) {
8065                 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
8066                     NULL);
8067                 xmlFree(nsList);
8068                 return (-1);
8069             }
8070             for (i = 0; i < count; i++) {
8071                 nsArray[2 * i] = nsList[i]->href;
8072                 nsArray[2 * i + 1] = nsList[i]->prefix;
8073             }
8074             nsArray[count * 2] = NULL;
8075             xmlFree(nsList);
8076         }
8077         /*
8078         * TODO: Differentiate between "selector" and "field".
8079         */
8080         if (isField)
8081             selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8082                 NULL, XML_PATTERN_XSFIELD, nsArray);
8083         else
8084             selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8085                 NULL, XML_PATTERN_XSSEL, nsArray);
8086         if (nsArray != NULL)
8087             xmlFree((xmlChar **) nsArray);
8088
8089         if (selector->xpathComp == NULL) {
8090             xmlSchemaPCustomErr(ctxt,
8091                 /* TODO: Adjust error code? */
8092                 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8093                 NULL, node,
8094                 "The XPath expression '%s' could not be "
8095                 "compiled", selector->xpath);
8096             return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8097         }
8098     }
8099     return (0);
8100 }
8101
8102 #define ADD_ANNOTATION(annot)   \
8103     xmlSchemaAnnotPtr cur = item->annot; \
8104     if (item->annot == NULL) {  \
8105         item->annot = annot;    \
8106         return (annot);         \
8107     }                           \
8108     cur = item->annot;          \
8109     if (cur->next != NULL) {    \
8110         cur = cur->next;        \
8111     }                           \
8112     cur->next = annot;
8113
8114 /**
8115  * xmlSchemaAssignAnnotation:
8116  * @item: the schema component
8117  * @annot: the annotation
8118  *
8119  * Adds the annotation to the given schema component.
8120  *
8121  * Returns the given annotaion.
8122  */
8123 static xmlSchemaAnnotPtr
8124 xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8125                        xmlSchemaAnnotPtr annot)
8126 {
8127     if ((annItem == NULL) || (annot == NULL))
8128         return (NULL);
8129     switch (annItem->type) {
8130         case XML_SCHEMA_TYPE_ELEMENT: {
8131                 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8132                 ADD_ANNOTATION(annot)
8133             }
8134             break;
8135         case XML_SCHEMA_TYPE_ATTRIBUTE: {
8136                 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8137                 ADD_ANNOTATION(annot)
8138             }
8139             break;
8140         case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8141         case XML_SCHEMA_TYPE_ANY: {
8142                 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8143                 ADD_ANNOTATION(annot)
8144             }
8145             break;
8146         case XML_SCHEMA_TYPE_PARTICLE:
8147         case XML_SCHEMA_TYPE_IDC_KEY:
8148         case XML_SCHEMA_TYPE_IDC_KEYREF:
8149         case XML_SCHEMA_TYPE_IDC_UNIQUE: {
8150                 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8151                 ADD_ANNOTATION(annot)
8152             }
8153             break;
8154         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8155                 xmlSchemaAttributeGroupPtr item =
8156                     (xmlSchemaAttributeGroupPtr) annItem;
8157                 ADD_ANNOTATION(annot)
8158             }
8159             break;
8160         case XML_SCHEMA_TYPE_NOTATION: {
8161                 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8162                 ADD_ANNOTATION(annot)
8163             }
8164             break;
8165         case XML_SCHEMA_FACET_MININCLUSIVE:
8166         case XML_SCHEMA_FACET_MINEXCLUSIVE:
8167         case XML_SCHEMA_FACET_MAXINCLUSIVE:
8168         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8169         case XML_SCHEMA_FACET_TOTALDIGITS:
8170         case XML_SCHEMA_FACET_FRACTIONDIGITS:
8171         case XML_SCHEMA_FACET_PATTERN:
8172         case XML_SCHEMA_FACET_ENUMERATION:
8173         case XML_SCHEMA_FACET_WHITESPACE:
8174         case XML_SCHEMA_FACET_LENGTH:
8175         case XML_SCHEMA_FACET_MAXLENGTH:
8176         case XML_SCHEMA_FACET_MINLENGTH: {
8177                 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8178                 ADD_ANNOTATION(annot)
8179             }
8180             break;
8181         case XML_SCHEMA_TYPE_SIMPLE:
8182         case XML_SCHEMA_TYPE_COMPLEX: {
8183                 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8184                 ADD_ANNOTATION(annot)
8185             }
8186             break;
8187         case XML_SCHEMA_TYPE_GROUP: {
8188                 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8189                 ADD_ANNOTATION(annot)
8190             }
8191             break;
8192         case XML_SCHEMA_TYPE_SEQUENCE:
8193         case XML_SCHEMA_TYPE_CHOICE:
8194         case XML_SCHEMA_TYPE_ALL: {
8195                 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8196                 ADD_ANNOTATION(annot)
8197             }
8198             break;
8199         default:
8200              xmlSchemaPCustomErr(NULL,
8201                 XML_SCHEMAP_INTERNAL,
8202                 NULL, NULL,
8203                 "Internal error: xmlSchemaAddAnnotation, "
8204                 "The item is not a annotated schema component", NULL);
8205              break;
8206     }
8207     return (annot);
8208 }
8209
8210 /**
8211  * xmlSchemaParseIDCSelectorAndField:
8212  * @ctxt:  a schema validation context
8213  * @schema:  the schema being built
8214  * @node:  a subtree containing XML Schema informations
8215  *
8216  * Parses a XML Schema identity-contraint definition's
8217  * <selector> and <field> elements.
8218  *
8219  * Returns the parsed identity-constraint definition.
8220  */
8221 static xmlSchemaIDCSelectPtr
8222 xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
8223                           xmlSchemaIDCPtr idc,
8224                           xmlNodePtr node,
8225                           int isField)
8226 {
8227     xmlSchemaIDCSelectPtr item;
8228     xmlNodePtr child = NULL;
8229     xmlAttrPtr attr;
8230
8231     /*
8232     * Check for illegal attributes.
8233     */
8234     attr = node->properties;
8235     while (attr != NULL) {
8236         if (attr->ns == NULL) {
8237             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8238                 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
8239                 xmlSchemaPIllegalAttrErr(ctxt,
8240                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8241             }
8242         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8243             xmlSchemaPIllegalAttrErr(ctxt,
8244                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8245         }
8246         attr = attr->next;
8247     }
8248     /*
8249     * Create the item.
8250     */
8251     item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8252     if (item == NULL) {
8253         xmlSchemaPErrMemory(ctxt,
8254             "allocating a 'selector' of an identity-constraint definition",
8255             NULL);
8256         return (NULL);
8257     }
8258     memset(item, 0, sizeof(xmlSchemaIDCSelect));
8259     /*
8260     * Attribute "xpath" (mandatory).
8261     */
8262     attr = xmlSchemaGetPropNode(node, "xpath");
8263     if (attr == NULL) {
8264         xmlSchemaPMissingAttrErr(ctxt,
8265             XML_SCHEMAP_S4S_ATTR_MISSING,
8266             NULL, node,
8267             "name", NULL);
8268     } else {
8269         item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8270         /*
8271         * URGENT TODO: "field"s have an other syntax than "selector"s.
8272         */
8273
8274         if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8275             isField) == -1) {
8276             xmlSchemaPErr(ctxt,
8277                 (xmlNodePtr) attr,
8278                 XML_SCHEMAP_INTERNAL,
8279                 "Internal error: xmlSchemaParseIDCSelectorAndField, "
8280                 "validating the XPath expression of a IDC selector.\n",
8281                 NULL, NULL);
8282         }
8283
8284     }
8285     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8286     /*
8287     * And now for the children...
8288     */
8289     child = node->children;
8290     if (IS_SCHEMA(child, "annotation")) {
8291         /*
8292         * Add the annotation to the parent IDC.
8293         */
8294         xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
8295             xmlSchemaParseAnnotation(ctxt, child, 1));
8296         child = child->next;
8297     }
8298     if (child != NULL) {
8299         xmlSchemaPContentErr(ctxt,
8300             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8301             NULL, node, child,
8302             NULL, "(annotation?)");
8303     }
8304
8305     return (item);
8306 }
8307
8308 /**
8309  * xmlSchemaParseIDC:
8310  * @ctxt:  a schema validation context
8311  * @schema:  the schema being built
8312  * @node:  a subtree containing XML Schema informations
8313  *
8314  * Parses a XML Schema identity-contraint definition.
8315  *
8316  * Returns the parsed identity-constraint definition.
8317  */
8318 static xmlSchemaIDCPtr
8319 xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
8320                   xmlSchemaPtr schema,
8321                   xmlNodePtr node,
8322                   xmlSchemaTypeType idcCategory,
8323                   const xmlChar *targetNamespace)
8324 {
8325     xmlSchemaIDCPtr item = NULL;
8326     xmlNodePtr child = NULL;
8327     xmlAttrPtr attr;
8328     const xmlChar *name = NULL;
8329     xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
8330
8331     /*
8332     * Check for illegal attributes.
8333     */
8334     attr = node->properties;
8335     while (attr != NULL) {
8336         if (attr->ns == NULL) {
8337             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8338                 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8339                 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8340                  (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
8341                 xmlSchemaPIllegalAttrErr(ctxt,
8342                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8343             }
8344         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8345             xmlSchemaPIllegalAttrErr(ctxt,
8346                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8347         }
8348         attr = attr->next;
8349     }
8350     /*
8351     * Attribute "name" (mandatory).
8352     */
8353     attr = xmlSchemaGetPropNode(node, "name");
8354     if (attr == NULL) {
8355         xmlSchemaPMissingAttrErr(ctxt,
8356             XML_SCHEMAP_S4S_ATTR_MISSING,
8357             NULL, node,
8358             "name", NULL);
8359         return (NULL);
8360     } else if (xmlSchemaPValAttrNode(ctxt,
8361         NULL, attr,
8362         xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8363         return (NULL);
8364     }
8365     /* Create the component. */
8366     item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8367         idcCategory, node);
8368     if (item == NULL)
8369         return(NULL);
8370
8371     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8372     if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8373         /*
8374         * Attribute "refer" (mandatory).
8375         */
8376         attr = xmlSchemaGetPropNode(node, "refer");
8377         if (attr == NULL) {
8378             xmlSchemaPMissingAttrErr(ctxt,
8379                 XML_SCHEMAP_S4S_ATTR_MISSING,
8380                 NULL, node,
8381                 "refer", NULL);
8382         } else {
8383             /*
8384             * Create a reference item.
8385             */
8386             item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
8387                 NULL, NULL);
8388             if (item->ref == NULL)
8389                 return (NULL);
8390             xmlSchemaPValAttrNodeQName(ctxt, schema,
8391                 NULL, attr,
8392                 &(item->ref->targetNamespace),
8393                 &(item->ref->name));
8394             xmlSchemaCheckReference(ctxt, schema, node, attr,
8395                 item->ref->targetNamespace);
8396         }
8397     }
8398     /*
8399     * And now for the children...
8400     */
8401     child = node->children;
8402     if (IS_SCHEMA(child, "annotation")) {
8403         item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8404         child = child->next;
8405     }
8406     if (child == NULL) {
8407         xmlSchemaPContentErr(ctxt,
8408                 XML_SCHEMAP_S4S_ELEM_MISSING,
8409                 NULL, node, child,
8410                 "A child element is missing",
8411                 "(annotation?, (selector, field+))");
8412     }
8413     /*
8414     * Child element <selector>.
8415     */
8416     if (IS_SCHEMA(child, "selector")) {
8417         item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
8418             item, child, 0);
8419         child = child->next;
8420         /*
8421         * Child elements <field>.
8422         */
8423         if (IS_SCHEMA(child, "field")) {
8424             do {
8425                 field = xmlSchemaParseIDCSelectorAndField(ctxt,
8426                     item, child, 1);
8427                 if (field != NULL) {
8428                     field->index = item->nbFields;
8429                     item->nbFields++;
8430                     if (lastField != NULL)
8431                         lastField->next = field;
8432                     else
8433                         item->fields = field;
8434                     lastField = field;
8435                 }
8436                 child = child->next;
8437             } while (IS_SCHEMA(child, "field"));
8438         } else {
8439             xmlSchemaPContentErr(ctxt,
8440                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8441                 NULL, node, child,
8442                 NULL, "(annotation?, (selector, field+))");
8443         }
8444     }
8445     if (child != NULL) {
8446         xmlSchemaPContentErr(ctxt,
8447             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8448             NULL, node, child,
8449             NULL, "(annotation?, (selector, field+))");
8450     }
8451
8452     return (item);
8453 }
8454
8455 /**
8456  * xmlSchemaParseElement:
8457  * @ctxt:  a schema validation context
8458  * @schema:  the schema being built
8459  * @node:  a subtree containing XML Schema informations
8460  * @topLevel: indicates if this is global declaration
8461  *
8462  * Parses a XML schema element declaration.
8463  * *WARNING* this interface is highly subject to change
8464  *
8465  * Returns the element declaration or a particle; NULL in case
8466  * of an error or if the particle has minOccurs==maxOccurs==0.
8467  */
8468 static xmlSchemaBasicItemPtr
8469 xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8470                       xmlNodePtr node, int *isElemRef, int topLevel)
8471 {
8472     xmlSchemaElementPtr decl = NULL;
8473     xmlSchemaParticlePtr particle = NULL;
8474     xmlSchemaAnnotPtr annot = NULL;
8475     xmlNodePtr child = NULL;
8476     xmlAttrPtr attr, nameAttr;
8477     int min, max, isRef = 0;
8478     xmlChar *des = NULL;
8479
8480     /* 3.3.3 Constraints on XML Representations of Element Declarations */
8481     /* TODO: Complete implementation of 3.3.6 */
8482
8483     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8484         return (NULL);
8485
8486     if (isElemRef != NULL)
8487         *isElemRef = 0;
8488     /*
8489     * If we get a "ref" attribute on a local <element> we will assume it's
8490     * a reference - even if there's a "name" attribute; this seems to be more
8491     * robust.
8492     */
8493     nameAttr = xmlSchemaGetPropNode(node, "name");
8494     attr = xmlSchemaGetPropNode(node, "ref");
8495     if ((topLevel) || (attr == NULL)) {
8496         if (nameAttr == NULL) {
8497             xmlSchemaPMissingAttrErr(ctxt,
8498                 XML_SCHEMAP_S4S_ATTR_MISSING,
8499                 NULL, node, "name", NULL);
8500             return (NULL);
8501         }
8502     } else
8503         isRef = 1;
8504
8505     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8506     child = node->children;
8507     if (IS_SCHEMA(child, "annotation")) {
8508         annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8509         child = child->next;
8510     }
8511     /*
8512     * Skip particle part if a global declaration.
8513     */
8514     if (topLevel)
8515         goto declaration_part;
8516     /*
8517     * The particle part ==================================================
8518     */
8519     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8520     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8521     xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
8522     particle = xmlSchemaAddParticle(ctxt, node, min, max);
8523     if (particle == NULL)
8524         goto return_null;
8525
8526     /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8527
8528     if (isRef) {
8529         const xmlChar *refNs = NULL, *ref = NULL;
8530         xmlSchemaQNameRefPtr refer = NULL;
8531         /*
8532         * The reference part =============================================
8533         */
8534         if (isElemRef != NULL)
8535             *isElemRef = 1;
8536
8537         xmlSchemaPValAttrNodeQName(ctxt, schema,
8538             NULL, attr, &refNs, &ref);
8539         xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
8540         /*
8541         * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
8542         */
8543         if (nameAttr != NULL) {
8544             xmlSchemaPMutualExclAttrErr(ctxt,
8545                 XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
8546         }
8547         /*
8548         * Check for illegal attributes.
8549         */
8550         attr = node->properties;
8551         while (attr != NULL) {
8552             if (attr->ns == NULL) {
8553                 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8554                     xmlStrEqual(attr->name, BAD_CAST "name") ||
8555                     xmlStrEqual(attr->name, BAD_CAST "id") ||
8556                     xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8557                     xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8558                 {
8559                     attr = attr->next;
8560                     continue;
8561                 } else {
8562                     /* SPEC (3.3.3 : 2.2) */
8563                     xmlSchemaPCustomAttrErr(ctxt,
8564                         XML_SCHEMAP_SRC_ELEMENT_2_2,
8565                         NULL, NULL, attr,
8566                         "Only the attributes 'minOccurs', 'maxOccurs' and "
8567                         "'id' are allowed in addition to 'ref'");
8568                     break;
8569                 }
8570             } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8571                 xmlSchemaPIllegalAttrErr(ctxt,
8572                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8573             }
8574             attr = attr->next;
8575         }
8576         /*
8577         * No children except <annotation> expected.
8578         */
8579         if (child != NULL) {
8580             xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8581                 NULL, node, child, NULL, "(annotation?)");
8582         }
8583         if ((min == 0) && (max == 0))
8584             goto return_null;
8585         /*
8586         * Create the reference item and attach it to the particle.
8587         */
8588         refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
8589             ref, refNs);
8590         if (refer == NULL)
8591             goto return_null;
8592         particle->children = (xmlSchemaTreeItemPtr) refer;
8593         particle->annot = annot;
8594         /*
8595         * Add the particle to pending components, since the reference
8596         * need to be resolved.
8597         */
8598         WXS_ADD_PENDING(ctxt, particle);
8599         return ((xmlSchemaBasicItemPtr) particle);
8600     }
8601     /*
8602     * The declaration part ===============================================
8603     */
8604 declaration_part:
8605     {
8606         const xmlChar *ns = NULL, *fixed, *name, *attrValue;
8607         xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8608
8609         if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
8610             xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
8611             goto return_null;
8612         /*
8613         * Evaluate the target namespace.
8614         */
8615         if (topLevel) {
8616             ns = ctxt->targetNamespace;
8617         } else {
8618             attr = xmlSchemaGetPropNode(node, "form");
8619             if (attr != NULL) {
8620                 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8621                 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
8622                     ns = ctxt->targetNamespace;
8623                 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
8624                     xmlSchemaPSimpleTypeErr(ctxt,
8625                         XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8626                         NULL, (xmlNodePtr) attr,
8627                         NULL, "(qualified | unqualified)",
8628                         attrValue, NULL, NULL, NULL);
8629                 }
8630             } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8631                 ns = ctxt->targetNamespace;
8632         }
8633         decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
8634         if (decl == NULL) {
8635             goto return_null;
8636         }
8637         /*
8638         * Check for illegal attributes.
8639         */
8640         attr = node->properties;
8641         while (attr != NULL) {
8642             if (attr->ns == NULL) {
8643                 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8644                     (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
8645                     (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8646                     (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
8647                     (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
8648                     (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
8649                     (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8650                 {
8651                     if (topLevel == 0) {
8652                         if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8653                             (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8654                             (!xmlStrEqual(attr->name, BAD_CAST "form")))
8655                         {
8656                             xmlSchemaPIllegalAttrErr(ctxt,
8657                                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8658                         }
8659                     } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8660                         (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
8661                         (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8662
8663                         xmlSchemaPIllegalAttrErr(ctxt,
8664                             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8665                     }
8666                 }
8667             } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8668
8669                 xmlSchemaPIllegalAttrErr(ctxt,
8670                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8671             }
8672             attr = attr->next;
8673         }
8674         /*
8675         * Extract/validate attributes.
8676         */
8677         if (topLevel) {
8678             /*
8679             * Process top attributes of global element declarations here.
8680             */
8681             decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8682             decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
8683             xmlSchemaPValAttrQName(ctxt, schema,
8684                 NULL, node, "substitutionGroup",
8685                 &(decl->substGroupNs), &(decl->substGroup));
8686             if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
8687                 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
8688             /*
8689             * Attribute "final".
8690             */
8691             attr = xmlSchemaGetPropNode(node, "final");
8692             if (attr == NULL) {
8693                 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8694                     decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8695                 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8696                     decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
8697             } else {
8698                 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8699                 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8700                     -1,
8701                     XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8702                     XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
8703                     xmlSchemaPSimpleTypeErr(ctxt,
8704                         XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8705                         NULL, (xmlNodePtr) attr,
8706                         NULL, "(#all | List of (extension | restriction))",
8707                         attrValue, NULL, NULL, NULL);
8708                 }
8709             }
8710         }
8711         /*
8712         * Attribute "block".
8713         */
8714         attr = xmlSchemaGetPropNode(node, "block");
8715         if (attr == NULL) {
8716             /*
8717             * Apply default "block" values.
8718             */
8719             if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8720                 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8721             if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8722                 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8723             if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8724                 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
8725         } else {
8726             attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8727             if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8728                 -1,
8729                 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
8730                 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
8731                 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8732                 xmlSchemaPSimpleTypeErr(ctxt,
8733                     XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8734                     NULL, (xmlNodePtr) attr,
8735                     NULL, "(#all | List of (extension | "
8736                     "restriction | substitution))", attrValue,
8737                     NULL, NULL, NULL);
8738             }
8739         }
8740         if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
8741             decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
8742
8743         attr = xmlSchemaGetPropNode(node, "type");
8744         if (attr != NULL) {
8745             xmlSchemaPValAttrNodeQName(ctxt, schema,
8746                 NULL, attr,
8747                 &(decl->namedTypeNs), &(decl->namedType));
8748             xmlSchemaCheckReference(ctxt, schema, node,
8749                 attr, decl->namedTypeNs);
8750         }
8751         decl->value = xmlSchemaGetProp(ctxt, node, "default");
8752         attr = xmlSchemaGetPropNode(node, "fixed");
8753         if (attr != NULL) {
8754             fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8755             if (decl->value != NULL) {
8756                 /*
8757                 * 3.3.3 : 1
8758                 * default and fixed must not both be present.
8759                 */
8760                 xmlSchemaPMutualExclAttrErr(ctxt,
8761                     XML_SCHEMAP_SRC_ELEMENT_1,
8762                     NULL, attr, "default", "fixed");
8763             } else {
8764                 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8765                 decl->value = fixed;
8766             }
8767         }
8768         /*
8769         * And now for the children...
8770         */
8771         if (IS_SCHEMA(child, "complexType")) {
8772             /*
8773             * 3.3.3 : 3
8774             * "type" and either <simpleType> or <complexType> are mutually
8775             * exclusive
8776             */
8777             if (decl->namedType != NULL) {
8778                 xmlSchemaPContentErr(ctxt,
8779                     XML_SCHEMAP_SRC_ELEMENT_3,
8780                     NULL, node, child,
8781                     "The attribute 'type' and the <complexType> child are "
8782                     "mutually exclusive", NULL);
8783             } else
8784                 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
8785             child = child->next;
8786         } else if (IS_SCHEMA(child, "simpleType")) {
8787             /*
8788             * 3.3.3 : 3
8789             * "type" and either <simpleType> or <complexType> are
8790             * mutually exclusive
8791             */
8792             if (decl->namedType != NULL) {
8793                 xmlSchemaPContentErr(ctxt,
8794                     XML_SCHEMAP_SRC_ELEMENT_3,
8795                     NULL, node, child,
8796                     "The attribute 'type' and the <simpleType> child are "
8797                     "mutually exclusive", NULL);
8798             } else
8799                 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8800             child = child->next;
8801         }
8802         while ((IS_SCHEMA(child, "unique")) ||
8803             (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
8804             if (IS_SCHEMA(child, "unique")) {
8805                 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8806                     XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
8807             } else if (IS_SCHEMA(child, "key")) {
8808                 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8809                     XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
8810             } else if (IS_SCHEMA(child, "keyref")) {
8811                 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8812                     XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
8813             }
8814             if (lastIDC != NULL)
8815                 lastIDC->next = curIDC;
8816             else
8817                 decl->idcs = (void *) curIDC;
8818             lastIDC = curIDC;
8819             child = child->next;
8820         }
8821         if (child != NULL) {
8822             xmlSchemaPContentErr(ctxt,
8823                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8824                 NULL, node, child,
8825                 NULL, "(annotation?, ((simpleType | complexType)?, "
8826                 "(unique | key | keyref)*))");
8827         }
8828         decl->annot = annot;
8829     }
8830     /*
8831     * NOTE: Element Declaration Representation OK 4. will be checked at a
8832     * different layer.
8833     */
8834     FREE_AND_NULL(des)
8835     if (topLevel)
8836         return ((xmlSchemaBasicItemPtr) decl);
8837     else {
8838         particle->children = (xmlSchemaTreeItemPtr) decl;
8839         return ((xmlSchemaBasicItemPtr) particle);
8840     }
8841
8842 return_null:
8843     FREE_AND_NULL(des);
8844     if (annot != NULL) {
8845         if (particle != NULL)
8846             particle->annot = NULL;
8847         if (decl != NULL)
8848             decl->annot = NULL;
8849         xmlSchemaFreeAnnot(annot);
8850     }
8851     return (NULL);
8852 }
8853
8854 /**
8855  * xmlSchemaParseUnion:
8856  * @ctxt:  a schema validation context
8857  * @schema:  the schema being built
8858  * @node:  a subtree containing XML Schema informations
8859  *
8860  * parse a XML schema Union definition
8861  * *WARNING* this interface is highly subject to change
8862  *
8863  * Returns -1 in case of internal error, 0 in case of success and a positive
8864  * error code otherwise.
8865  */
8866 static int
8867 xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8868                     xmlNodePtr node)
8869 {
8870     xmlSchemaTypePtr type;
8871     xmlNodePtr child = NULL;
8872     xmlAttrPtr attr;
8873     const xmlChar *cur = NULL;
8874
8875     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8876         return (-1);
8877     /* Not a component, don't create it. */
8878     type = ctxt->ctxtType;
8879     /*
8880     * Mark the simple type as being of variety "union".
8881     */
8882     type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
8883     /*
8884     * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8885     * then the `simple ur-type definition`."
8886     */
8887     type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8888     /*
8889     * Check for illegal attributes.
8890     */
8891     attr = node->properties;
8892     while (attr != NULL) {
8893         if (attr->ns == NULL) {
8894             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8895                 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
8896                 xmlSchemaPIllegalAttrErr(ctxt,
8897                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8898             }
8899         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8900             xmlSchemaPIllegalAttrErr(ctxt,
8901                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8902         }
8903         attr = attr->next;
8904     }
8905     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8906     /*
8907     * Attribute "memberTypes". This is a list of QNames.
8908     * TODO: Check the value to contain anything.
8909     */
8910     attr = xmlSchemaGetPropNode(node, "memberTypes");
8911     if (attr != NULL) {
8912         const xmlChar *end;
8913         xmlChar *tmp;
8914         const xmlChar *localName, *nsName;
8915         xmlSchemaTypeLinkPtr link, lastLink = NULL;
8916         xmlSchemaQNameRefPtr ref;
8917
8918         cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8919         type->base = cur;
8920         do {
8921             while (IS_BLANK_CH(*cur))
8922                 cur++;
8923             end = cur;
8924             while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8925                 end++;
8926             if (end == cur)
8927                 break;
8928             tmp = xmlStrndup(cur, end - cur);
8929             if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
8930                 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
8931                 /*
8932                 * Create the member type link.
8933                 */
8934                 link = (xmlSchemaTypeLinkPtr)
8935                     xmlMalloc(sizeof(xmlSchemaTypeLink));
8936                 if (link == NULL) {
8937                     xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8938                         "allocating a type link", NULL);
8939                     return (-1);
8940                 }
8941                 link->type = NULL;
8942                 link->next = NULL;
8943                 if (lastLink == NULL)
8944                     type->memberTypes = link;
8945                 else
8946                     lastLink->next = link;
8947                 lastLink = link;
8948                 /*
8949                 * Create a reference item.
8950                 */
8951                 ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
8952                     localName, nsName);
8953                 if (ref == NULL) {
8954                     FREE_AND_NULL(tmp)
8955                     return (-1);
8956                 }
8957                 /*
8958                 * Assign the reference to the link, it will be resolved
8959                 * later during fixup of the union simple type.
8960                 */
8961                 link->type = (xmlSchemaTypePtr) ref;
8962             }
8963             FREE_AND_NULL(tmp)
8964             cur = end;
8965         } while (*cur != 0);
8966
8967     }
8968     /*
8969     * And now for the children...
8970     */
8971     child = node->children;
8972     if (IS_SCHEMA(child, "annotation")) {
8973         /*
8974         * Add the annotation to the simple type ancestor.
8975         */
8976         xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8977             xmlSchemaParseAnnotation(ctxt, child, 1));
8978         child = child->next;
8979     }
8980     if (IS_SCHEMA(child, "simpleType")) {
8981         xmlSchemaTypePtr subtype, last = NULL;
8982
8983         /*
8984         * Anchor the member types in the "subtypes" field of the
8985         * simple type.
8986         */
8987         while (IS_SCHEMA(child, "simpleType")) {
8988             subtype = (xmlSchemaTypePtr)
8989                 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8990             if (subtype != NULL) {
8991                 if (last == NULL) {
8992                     type->subtypes = subtype;
8993                     last = subtype;
8994                 } else {
8995                     last->next = subtype;
8996                     last = subtype;
8997                 }
8998                 last->next = NULL;
8999             }
9000             child = child->next;
9001         }
9002     }
9003     if (child != NULL) {
9004         xmlSchemaPContentErr(ctxt,
9005             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9006             NULL, node, child, NULL, "(annotation?, simpleType*)");
9007     }
9008     if ((attr == NULL) && (type->subtypes == NULL)) {
9009          /*
9010         * src-union-memberTypes-or-simpleTypes
9011         * Either the memberTypes [attribute] of the <union> element must
9012         * be non-empty or there must be at least one simpleType [child].
9013         */
9014         xmlSchemaPCustomErr(ctxt,
9015             XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
9016             NULL, node,
9017             "Either the attribute 'memberTypes' or "
9018             "at least one <simpleType> child must be present", NULL);
9019     }
9020     return (0);
9021 }
9022
9023 /**
9024  * xmlSchemaParseList:
9025  * @ctxt:  a schema validation context
9026  * @schema:  the schema being built
9027  * @node:  a subtree containing XML Schema informations
9028  *
9029  * parse a XML schema List definition
9030  * *WARNING* this interface is highly subject to change
9031  *
9032  * Returns -1 in case of error, 0 if the declaration is improper and
9033  *         1 in case of success.
9034  */
9035 static xmlSchemaTypePtr
9036 xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9037                    xmlNodePtr node)
9038 {
9039     xmlSchemaTypePtr type;
9040     xmlNodePtr child = NULL;
9041     xmlAttrPtr attr;
9042
9043     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9044         return (NULL);
9045     /* Not a component, don't create it. */
9046     type = ctxt->ctxtType;
9047     /*
9048     * Mark the type as being of variety "list".
9049     */
9050     type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
9051     /*
9052     * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
9053     * then the `simple ur-type definition`."
9054     */
9055     type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
9056     /*
9057     * Check for illegal attributes.
9058     */
9059     attr = node->properties;
9060     while (attr != NULL) {
9061         if (attr->ns == NULL) {
9062             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9063                 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
9064                 xmlSchemaPIllegalAttrErr(ctxt,
9065                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9066             }
9067         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9068             xmlSchemaPIllegalAttrErr(ctxt,
9069                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9070         }
9071         attr = attr->next;
9072     }
9073
9074     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9075
9076     /*
9077     * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9078     * fields for holding the reference to the itemType.
9079     *
9080     * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9081     * the "ref" fields.
9082     */
9083     xmlSchemaPValAttrQName(ctxt, schema, NULL,
9084         node, "itemType", &(type->baseNs), &(type->base));
9085     /*
9086     * And now for the children...
9087     */
9088     child = node->children;
9089     if (IS_SCHEMA(child, "annotation")) {
9090         xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9091             xmlSchemaParseAnnotation(ctxt, child, 1));
9092         child = child->next;
9093     }
9094     if (IS_SCHEMA(child, "simpleType")) {
9095         /*
9096         * src-list-itemType-or-simpleType
9097         * Either the itemType [attribute] or the <simpleType> [child] of
9098         * the <list> element must be present, but not both.
9099         */
9100         if (type->base != NULL) {
9101             xmlSchemaPCustomErr(ctxt,
9102                 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9103                 NULL, node,
9104                 "The attribute 'itemType' and the <simpleType> child "
9105                 "are mutually exclusive", NULL);
9106         } else {
9107             type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9108         }
9109         child = child->next;
9110     } else if (type->base == NULL) {
9111         xmlSchemaPCustomErr(ctxt,
9112             XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9113             NULL, node,
9114             "Either the attribute 'itemType' or the <simpleType> child "
9115             "must be present", NULL);
9116     }
9117     if (child != NULL) {
9118         xmlSchemaPContentErr(ctxt,
9119             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9120             NULL, node, child, NULL, "(annotation?, simpleType?)");
9121     }
9122     if ((type->base == NULL) &&
9123         (type->subtypes == NULL) &&
9124         (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
9125         xmlSchemaPCustomErr(ctxt,
9126             XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9127             NULL, node,
9128             "Either the attribute 'itemType' or the <simpleType> child "
9129             "must be present", NULL);
9130     }
9131     return (NULL);
9132 }
9133
9134 /**
9135  * xmlSchemaParseSimpleType:
9136  * @ctxt:  a schema validation context
9137  * @schema:  the schema being built
9138  * @node:  a subtree containing XML Schema informations
9139  *
9140  * parse a XML schema Simple Type definition
9141  * *WARNING* this interface is highly subject to change
9142  *
9143  * Returns -1 in case of error, 0 if the declaration is improper and
9144  * 1 in case of success.
9145  */
9146 static xmlSchemaTypePtr
9147 xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9148                          xmlNodePtr node, int topLevel)
9149 {
9150     xmlSchemaTypePtr type, oldCtxtType;
9151     xmlNodePtr child = NULL;
9152     const xmlChar *attrValue = NULL;
9153     xmlAttrPtr attr;
9154     int hasRestriction = 0;
9155
9156     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9157         return (NULL);
9158
9159     if (topLevel) {
9160         attr = xmlSchemaGetPropNode(node, "name");
9161         if (attr == NULL) {
9162             xmlSchemaPMissingAttrErr(ctxt,
9163                 XML_SCHEMAP_S4S_ATTR_MISSING,
9164                 NULL, node,
9165                 "name", NULL);
9166             return (NULL);
9167         } else {
9168             if (xmlSchemaPValAttrNode(ctxt,
9169                 NULL, attr,
9170                 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9171                 return (NULL);
9172             /*
9173             * Skip built-in types.
9174             */
9175             if (ctxt->isS4S) {
9176                 xmlSchemaTypePtr biType;
9177
9178                 if (ctxt->isRedefine) {
9179                     /*
9180                     * REDEFINE: Disallow redefinition of built-in-types.
9181                     * TODO: It seems that the spec does not say anything
9182                     * about this case.
9183                     */
9184                     xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9185                         NULL, node,
9186                         "Redefinition of built-in simple types is not "
9187                         "supported", NULL);
9188                     return(NULL);
9189                 }
9190                 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9191                 if (biType != NULL)
9192                     return (biType);
9193             }
9194         }
9195     }
9196     /*
9197     * TargetNamespace:
9198     * SPEC "The `actual value` of the targetNamespace [attribute]
9199     * of the <schema> ancestor element information item if present,
9200     * otherwise `absent`.
9201     */
9202     if (topLevel == 0) {
9203 #ifdef ENABLE_NAMED_LOCALS
9204         char buf[40];
9205 #endif
9206         /*
9207         * Parse as local simple type definition.
9208         */
9209 #ifdef ENABLE_NAMED_LOCALS
9210         snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
9211         type = xmlSchemaAddType(ctxt, schema,
9212             XML_SCHEMA_TYPE_SIMPLE,
9213             xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
9214             ctxt->targetNamespace, node, 0);
9215 #else
9216         type = xmlSchemaAddType(ctxt, schema,
9217             XML_SCHEMA_TYPE_SIMPLE,
9218             NULL, ctxt->targetNamespace, node, 0);
9219 #endif
9220         if (type == NULL)
9221             return (NULL);
9222         type->type = XML_SCHEMA_TYPE_SIMPLE;
9223         type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9224         /*
9225         * Check for illegal attributes.
9226         */
9227         attr = node->properties;
9228         while (attr != NULL) {
9229             if (attr->ns == NULL) {
9230                 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
9231                     xmlSchemaPIllegalAttrErr(ctxt,
9232                         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9233                 }
9234             } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9235                     xmlSchemaPIllegalAttrErr(ctxt,
9236                         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9237             }
9238             attr = attr->next;
9239         }
9240     } else {
9241         /*
9242         * Parse as global simple type definition.
9243         *
9244         * Note that attrValue is the value of the attribute "name" here.
9245         */
9246         type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9247             attrValue, ctxt->targetNamespace, node, 1);
9248         if (type == NULL)
9249             return (NULL);
9250         type->type = XML_SCHEMA_TYPE_SIMPLE;
9251         type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9252         type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9253         /*
9254         * Check for illegal attributes.
9255         */
9256         attr = node->properties;
9257         while (attr != NULL) {
9258             if (attr->ns == NULL) {
9259                 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9260                     (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9261                     (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
9262                     xmlSchemaPIllegalAttrErr(ctxt,
9263                         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9264                 }
9265             } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9266                 xmlSchemaPIllegalAttrErr(ctxt,
9267                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9268             }
9269             attr = attr->next;
9270         }
9271         /*
9272         * Attribute "final".
9273         */
9274         attr = xmlSchemaGetPropNode(node, "final");
9275         if (attr == NULL) {
9276             if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9277                 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9278             if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9279                 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9280             if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9281                 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
9282         } else {
9283             attrValue = xmlSchemaGetProp(ctxt, node, "final");
9284             if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9285                 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
9286                 XML_SCHEMAS_TYPE_FINAL_LIST,
9287                 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9288
9289                 xmlSchemaPSimpleTypeErr(ctxt,
9290                     XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9291                     WXS_BASIC_CAST type, (xmlNodePtr) attr,
9292                     NULL, "(#all | List of (list | union | restriction)",
9293                     attrValue, NULL, NULL, NULL);
9294             }
9295         }
9296     }
9297     type->targetNamespace = ctxt->targetNamespace;
9298     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9299     /*
9300     * And now for the children...
9301     */
9302     oldCtxtType = ctxt->ctxtType;
9303
9304     ctxt->ctxtType = type;
9305
9306     child = node->children;
9307     if (IS_SCHEMA(child, "annotation")) {
9308         type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9309         child = child->next;
9310     }
9311     if (child == NULL) {
9312         xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
9313             NULL, node, child, NULL,
9314             "(annotation?, (restriction | list | union))");
9315     } else if (IS_SCHEMA(child, "restriction")) {
9316         xmlSchemaParseRestriction(ctxt, schema, child,
9317             XML_SCHEMA_TYPE_SIMPLE);
9318         hasRestriction = 1;
9319         child = child->next;
9320     } else if (IS_SCHEMA(child, "list")) {
9321         xmlSchemaParseList(ctxt, schema, child);
9322         child = child->next;
9323     } else if (IS_SCHEMA(child, "union")) {
9324         xmlSchemaParseUnion(ctxt, schema, child);
9325         child = child->next;
9326     }
9327     if (child != NULL) {
9328         xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9329             NULL, node, child, NULL,
9330             "(annotation?, (restriction | list | union))");
9331     }
9332     /*
9333     * REDEFINE: SPEC src-redefine (5)
9334     * "Within the [children], each <simpleType> must have a
9335     * <restriction> among its [children] ... the `actual value` of whose
9336     * base [attribute] must be the same as the `actual value` of its own
9337     * name attribute plus target namespace;"
9338     */
9339     if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9340         xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9341             NULL, node, "This is a redefinition, thus the "
9342             "<simpleType> must have a <restriction> child", NULL);
9343     }
9344
9345     ctxt->ctxtType = oldCtxtType;
9346     return (type);
9347 }
9348
9349 /**
9350  * xmlSchemaParseModelGroupDefRef:
9351  * @ctxt:  the parser context
9352  * @schema: the schema being built
9353  * @node:  the node
9354  *
9355  * Parses a reference to a model group definition.
9356  *
9357  * We will return a particle component with a qname-component or
9358  * NULL in case of an error.
9359  */
9360 static xmlSchemaTreeItemPtr
9361 xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9362                                xmlSchemaPtr schema,
9363                                xmlNodePtr node)
9364 {
9365     xmlSchemaParticlePtr item;
9366     xmlNodePtr child = NULL;
9367     xmlAttrPtr attr;
9368     const xmlChar *ref = NULL, *refNs = NULL;
9369     int min, max;
9370
9371     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9372         return (NULL);
9373
9374     attr = xmlSchemaGetPropNode(node, "ref");
9375     if (attr == NULL) {
9376         xmlSchemaPMissingAttrErr(ctxt,
9377             XML_SCHEMAP_S4S_ATTR_MISSING,
9378             NULL, node, "ref", NULL);
9379         return (NULL);
9380     } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
9381         attr, &refNs, &ref) != 0) {
9382         return (NULL);
9383     }
9384     xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
9385     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9386     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9387         "(xs:nonNegativeInteger | unbounded)");
9388     /*
9389     * Check for illegal attributes.
9390     */
9391     attr = node->properties;
9392     while (attr != NULL) {
9393         if (attr->ns == NULL) {
9394             if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
9395                 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9396                 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9397                 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
9398                 xmlSchemaPIllegalAttrErr(ctxt,
9399                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9400             }
9401         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9402             xmlSchemaPIllegalAttrErr(ctxt,
9403                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9404         }
9405         attr = attr->next;
9406     }
9407     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9408     item = xmlSchemaAddParticle(ctxt, node, min, max);
9409     if (item == NULL)
9410         return (NULL);
9411     /*
9412     * Create a qname-reference and set as the term; it will be substituted
9413     * for the model group after the reference has been resolved.
9414     */
9415     item->children = (xmlSchemaTreeItemPtr)
9416         xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
9417     xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9418     /*
9419     * And now for the children...
9420     */
9421     child = node->children;
9422     /* TODO: Is annotation even allowed for a model group reference? */
9423     if (IS_SCHEMA(child, "annotation")) {
9424         /*
9425         * TODO: What to do exactly with the annotation?
9426         */
9427         item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9428         child = child->next;
9429     }
9430     if (child != NULL) {
9431         xmlSchemaPContentErr(ctxt,
9432             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9433             NULL, node, child, NULL,
9434             "(annotation?)");
9435     }
9436     /*
9437     * Corresponds to no component at all if minOccurs==maxOccurs==0.
9438     */
9439     if ((min == 0) && (max == 0))
9440         return (NULL);
9441
9442     return ((xmlSchemaTreeItemPtr) item);
9443 }
9444
9445 /**
9446  * xmlSchemaParseModelGroupDefinition:
9447  * @ctxt:  a schema validation context
9448  * @schema:  the schema being built
9449  * @node:  a subtree containing XML Schema informations
9450  *
9451  * Parses a XML schema model group definition.
9452  *
9453  * Note that the contraint src-redefine (6.2) can't be applied until
9454  * references have been resolved. So we will do this at the
9455  * component fixup level.
9456  *
9457  * *WARNING* this interface is highly subject to change
9458  *
9459  * Returns -1 in case of error, 0 if the declaration is improper and
9460  *         1 in case of success.
9461  */
9462 static xmlSchemaModelGroupDefPtr
9463 xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9464                                    xmlSchemaPtr schema,
9465                                    xmlNodePtr node)
9466 {
9467     xmlSchemaModelGroupDefPtr item;
9468     xmlNodePtr child = NULL;
9469     xmlAttrPtr attr;
9470     const xmlChar *name;
9471
9472     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9473         return (NULL);
9474
9475     attr = xmlSchemaGetPropNode(node, "name");
9476     if (attr == NULL) {
9477         xmlSchemaPMissingAttrErr(ctxt,
9478             XML_SCHEMAP_S4S_ATTR_MISSING,
9479             NULL, node,
9480             "name", NULL);
9481         return (NULL);
9482     } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
9483         xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9484         return (NULL);
9485     }
9486     item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9487         ctxt->targetNamespace, node);
9488     if (item == NULL)
9489         return (NULL);
9490     /*
9491     * Check for illegal attributes.
9492     */
9493     attr = node->properties;
9494     while (attr != NULL) {
9495         if (attr->ns == NULL) {
9496             if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9497                 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
9498                 xmlSchemaPIllegalAttrErr(ctxt,
9499                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9500             }
9501         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9502             xmlSchemaPIllegalAttrErr(ctxt,
9503                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9504         }
9505         attr = attr->next;
9506     }
9507     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9508     /*
9509     * And now for the children...
9510     */
9511     child = node->children;
9512     if (IS_SCHEMA(child, "annotation")) {
9513         item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9514         child = child->next;
9515     }
9516     if (IS_SCHEMA(child, "all")) {
9517         item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9518             XML_SCHEMA_TYPE_ALL, 0);
9519         child = child->next;
9520     } else if (IS_SCHEMA(child, "choice")) {
9521         item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9522             XML_SCHEMA_TYPE_CHOICE, 0);
9523         child = child->next;
9524     } else if (IS_SCHEMA(child, "sequence")) {
9525         item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9526             XML_SCHEMA_TYPE_SEQUENCE, 0);
9527         child = child->next;
9528     }
9529
9530
9531
9532     if (child != NULL) {
9533         xmlSchemaPContentErr(ctxt,
9534             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9535             NULL, node, child, NULL,
9536             "(annotation?, (all | choice | sequence)?)");
9537     }
9538     return (item);
9539 }
9540
9541 /**
9542  * xmlSchemaCleanupDoc:
9543  * @ctxt:  a schema validation context
9544  * @node:  the root of the document.
9545  *
9546  * removes unwanted nodes in a schemas document tree
9547  */
9548 static void
9549 xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9550 {
9551     xmlNodePtr delete, cur;
9552
9553     if ((ctxt == NULL) || (root == NULL)) return;
9554
9555     /*
9556      * Remove all the blank text nodes
9557      */
9558     delete = NULL;
9559     cur = root;
9560     while (cur != NULL) {
9561         if (delete != NULL) {
9562             xmlUnlinkNode(delete);
9563             xmlFreeNode(delete);
9564             delete = NULL;
9565         }
9566         if (cur->type == XML_TEXT_NODE) {
9567             if (IS_BLANK_NODE(cur)) {
9568                 if (xmlNodeGetSpacePreserve(cur) != 1) {
9569                     delete = cur;
9570                 }
9571             }
9572         } else if ((cur->type != XML_ELEMENT_NODE) &&
9573                    (cur->type != XML_CDATA_SECTION_NODE)) {
9574             delete = cur;
9575             goto skip_children;
9576         }
9577
9578         /*
9579          * Skip to next node
9580          */
9581         if (cur->children != NULL) {
9582             if ((cur->children->type != XML_ENTITY_DECL) &&
9583                 (cur->children->type != XML_ENTITY_REF_NODE) &&
9584                 (cur->children->type != XML_ENTITY_NODE)) {
9585                 cur = cur->children;
9586                 continue;
9587             }
9588         }
9589       skip_children:
9590         if (cur->next != NULL) {
9591             cur = cur->next;
9592             continue;
9593         }
9594
9595         do {
9596             cur = cur->parent;
9597             if (cur == NULL)
9598                 break;
9599             if (cur == root) {
9600                 cur = NULL;
9601                 break;
9602             }
9603             if (cur->next != NULL) {
9604                 cur = cur->next;
9605                 break;
9606             }
9607         } while (cur != NULL);
9608     }
9609     if (delete != NULL) {
9610         xmlUnlinkNode(delete);
9611         xmlFreeNode(delete);
9612         delete = NULL;
9613     }
9614 }
9615
9616
9617 static void
9618 xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9619 {
9620     if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9621         schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9622
9623     if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9624         schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9625
9626     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9627         schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9628     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9629         schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9630     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9631         schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9632     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9633         schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9634
9635     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9636         schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9637     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9638         schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9639     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9640         schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9641 }
9642
9643 static int
9644 xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
9645                              xmlSchemaPtr schema,
9646                              xmlNodePtr node)
9647 {
9648     xmlAttrPtr attr;
9649     const xmlChar *val;
9650     int res = 0, oldErrs = ctxt->nberrors;
9651
9652     /*
9653     * Those flags should be moved to the parser context flags,
9654     * since they are not visible at the component level. I.e.
9655     * they are used if processing schema *documents* only.
9656     */
9657     res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9658     HFAILURE;
9659
9660     /*
9661     * Since the version is of type xs:token, we won't bother to
9662     * check it.
9663     */
9664     /* REMOVED:
9665     attr = xmlSchemaGetPropNode(node, "version");
9666     if (attr != NULL) {
9667         res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9668             xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9669         HFAILURE;
9670     }
9671     */
9672     attr = xmlSchemaGetPropNode(node, "targetNamespace");
9673     if (attr != NULL) {
9674         res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
9675             xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9676         HFAILURE;
9677         if (res != 0) {
9678             ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9679             goto exit;
9680         }
9681     }
9682     attr = xmlSchemaGetPropNode(node, "elementFormDefault");
9683     if (attr != NULL) {
9684         val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9685         res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9686             XML_SCHEMAS_QUALIF_ELEM);
9687         HFAILURE;
9688         if (res != 0) {
9689             xmlSchemaPSimpleTypeErr(ctxt,
9690                 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
9691                 NULL, (xmlNodePtr) attr, NULL,
9692                 "(qualified | unqualified)", val, NULL, NULL, NULL);
9693         }
9694     }
9695     attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
9696     if (attr != NULL) {
9697         val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9698         res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9699             XML_SCHEMAS_QUALIF_ATTR);
9700         HFAILURE;
9701         if (res != 0) {
9702             xmlSchemaPSimpleTypeErr(ctxt,
9703                 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
9704                 NULL, (xmlNodePtr) attr, NULL,
9705                 "(qualified | unqualified)", val, NULL, NULL, NULL);
9706         }
9707     }
9708     attr = xmlSchemaGetPropNode(node, "finalDefault");
9709     if (attr != NULL) {
9710         val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9711         res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9712             XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9713             XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9714             -1,
9715             XML_SCHEMAS_FINAL_DEFAULT_LIST,
9716             XML_SCHEMAS_FINAL_DEFAULT_UNION);
9717         HFAILURE;
9718         if (res != 0) {
9719             xmlSchemaPSimpleTypeErr(ctxt,
9720                 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9721                 NULL, (xmlNodePtr) attr, NULL,
9722                 "(#all | List of (extension | restriction | list | union))",
9723                 val, NULL, NULL, NULL);
9724         }
9725     }
9726     attr = xmlSchemaGetPropNode(node, "blockDefault");
9727     if (attr != NULL) {
9728         val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9729         res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9730             XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9731             XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
9732             XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9733         HFAILURE;
9734         if (res != 0) {
9735             xmlSchemaPSimpleTypeErr(ctxt,
9736                 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9737                 NULL, (xmlNodePtr) attr, NULL,
9738                 "(#all | List of (extension | restriction | substitution))",
9739                 val, NULL, NULL, NULL);
9740         }
9741     }
9742
9743 exit:
9744     if (oldErrs != ctxt->nberrors)
9745         res = ctxt->err;
9746     return(res);
9747 exit_failure:
9748     return(-1);
9749 }
9750
9751 /**
9752  * xmlSchemaParseSchemaTopLevel:
9753  * @ctxt:  a schema validation context
9754  * @schema:  the schemas
9755  * @nodes:  the list of top level nodes
9756  *
9757  * Returns the internal XML Schema structure built from the resource or
9758  *         NULL in case of error
9759  */
9760 static int
9761 xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9762                              xmlSchemaPtr schema, xmlNodePtr nodes)
9763 {
9764     xmlNodePtr child;
9765     xmlSchemaAnnotPtr annot;
9766     int res = 0, oldErrs, tmpOldErrs;
9767
9768     if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
9769         return(-1);
9770
9771     oldErrs = ctxt->nberrors;
9772     child = nodes;
9773     while ((IS_SCHEMA(child, "include")) ||
9774            (IS_SCHEMA(child, "import")) ||
9775            (IS_SCHEMA(child, "redefine")) ||
9776            (IS_SCHEMA(child, "annotation"))) {
9777         if (IS_SCHEMA(child, "annotation")) {
9778             annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9779             if (schema->annot == NULL)
9780                 schema->annot = annot;
9781             else
9782                 xmlSchemaFreeAnnot(annot);
9783         } else if (IS_SCHEMA(child, "import")) {
9784             tmpOldErrs = ctxt->nberrors;
9785             res = xmlSchemaParseImport(ctxt, schema, child);
9786             HFAILURE;
9787             HSTOP(ctxt);
9788             if (tmpOldErrs != ctxt->nberrors)
9789                 goto exit;
9790         } else if (IS_SCHEMA(child, "include")) {
9791             tmpOldErrs = ctxt->nberrors;
9792             res = xmlSchemaParseInclude(ctxt, schema, child);
9793             HFAILURE;
9794             HSTOP(ctxt);
9795             if (tmpOldErrs != ctxt->nberrors)
9796                 goto exit;
9797         } else if (IS_SCHEMA(child, "redefine")) {
9798             tmpOldErrs = ctxt->nberrors;
9799             res = xmlSchemaParseRedefine(ctxt, schema, child);
9800             HFAILURE;
9801             HSTOP(ctxt);
9802             if (tmpOldErrs != ctxt->nberrors)
9803                 goto exit;
9804         }
9805         child = child->next;
9806     }
9807     /*
9808     * URGENT TODO: Change the functions to return int results.
9809     * We need especially to catch internal errors.
9810     */
9811     while (child != NULL) {
9812         if (IS_SCHEMA(child, "complexType")) {
9813             xmlSchemaParseComplexType(ctxt, schema, child, 1);
9814             child = child->next;
9815         } else if (IS_SCHEMA(child, "simpleType")) {
9816             xmlSchemaParseSimpleType(ctxt, schema, child, 1);
9817             child = child->next;
9818         } else if (IS_SCHEMA(child, "element")) {
9819             xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
9820             child = child->next;
9821         } else if (IS_SCHEMA(child, "attribute")) {
9822             xmlSchemaParseGlobalAttribute(ctxt, schema, child);
9823             child = child->next;
9824         } else if (IS_SCHEMA(child, "attributeGroup")) {
9825             xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
9826             child = child->next;
9827         } else if (IS_SCHEMA(child, "group")) {
9828             xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
9829             child = child->next;
9830         } else if (IS_SCHEMA(child, "notation")) {
9831             xmlSchemaParseNotation(ctxt, schema, child);
9832             child = child->next;
9833         } else {
9834             xmlSchemaPContentErr(ctxt,
9835                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9836                 NULL, child->parent, child,
9837                 NULL, "((include | import | redefine | annotation)*, "
9838                 "(((simpleType | complexType | group | attributeGroup) "
9839                 "| element | attribute | notation), annotation*)*)");
9840             child = child->next;
9841         }
9842         while (IS_SCHEMA(child, "annotation")) {
9843             /*
9844             * TODO: We should add all annotations.
9845             */
9846             annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9847             if (schema->annot == NULL)
9848                 schema->annot = annot;
9849             else
9850                 xmlSchemaFreeAnnot(annot);
9851             child = child->next;
9852         }
9853     }
9854 exit:
9855     ctxt->ctxtType = NULL;
9856     if (oldErrs != ctxt->nberrors)
9857         res = ctxt->err;
9858     return(res);
9859 exit_failure:
9860     return(-1);
9861 }
9862
9863 static xmlSchemaSchemaRelationPtr
9864 xmlSchemaSchemaRelationCreate(void)
9865 {
9866     xmlSchemaSchemaRelationPtr ret;
9867
9868     ret = (xmlSchemaSchemaRelationPtr)
9869         xmlMalloc(sizeof(xmlSchemaSchemaRelation));
9870     if (ret == NULL) {
9871         xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
9872         return(NULL);
9873     }
9874     memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
9875     return(ret);
9876 }
9877
9878 #if 0
9879 static void
9880 xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
9881 {
9882     xmlFree(rel);
9883 }
9884 #endif
9885
9886 static void
9887 xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9888 {
9889     xmlSchemaRedefPtr prev;
9890
9891     while (redef != NULL) {
9892         prev = redef;
9893         redef = redef->next;
9894         xmlFree(prev);
9895     }
9896 }
9897
9898 static void
9899 xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9900 {
9901     /*
9902     * After the construction context has been freed, there will be
9903     * no schema graph available any more. Only the schema buckets
9904     * will stay alive, which are put into the "schemasImports" and
9905     * "includes" slots of the xmlSchema.
9906     */
9907     if (con->buckets != NULL)
9908         xmlSchemaItemListFree(con->buckets);
9909     if (con->pending != NULL)
9910         xmlSchemaItemListFree(con->pending);
9911     if (con->substGroups != NULL)
9912         xmlHashFree(con->substGroups,
9913             (xmlHashDeallocator) xmlSchemaSubstGroupFree);
9914     if (con->redefs != NULL)
9915         xmlSchemaRedefListFree(con->redefs);
9916     if (con->dict != NULL)
9917         xmlDictFree(con->dict);
9918     xmlFree(con);
9919 }
9920
9921 static xmlSchemaConstructionCtxtPtr
9922 xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9923 {
9924     xmlSchemaConstructionCtxtPtr ret;
9925
9926     ret = (xmlSchemaConstructionCtxtPtr)
9927         xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9928     if (ret == NULL) {
9929         xmlSchemaPErrMemory(NULL,
9930             "allocating schema construction context", NULL);
9931         return (NULL);
9932     }
9933     memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
9934
9935     ret->buckets = xmlSchemaItemListCreate();
9936     if (ret->buckets == NULL) {
9937         xmlSchemaPErrMemory(NULL,
9938             "allocating list of schema buckets", NULL);
9939         xmlFree(ret);
9940         return (NULL);
9941     }
9942     ret->pending = xmlSchemaItemListCreate();
9943     if (ret->pending == NULL) {
9944         xmlSchemaPErrMemory(NULL,
9945             "allocating list of pending global components", NULL);
9946         xmlSchemaConstructionCtxtFree(ret);
9947         return (NULL);
9948     }
9949     ret->dict = dict;
9950     xmlDictReference(dict);
9951     return(ret);
9952 }
9953
9954 static xmlSchemaParserCtxtPtr
9955 xmlSchemaParserCtxtCreate(void)
9956 {
9957     xmlSchemaParserCtxtPtr ret;
9958
9959     ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9960     if (ret == NULL) {
9961         xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9962                             NULL);
9963         return (NULL);
9964     }
9965     memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9966     ret->type = XML_SCHEMA_CTXT_PARSER;
9967     ret->attrProhibs = xmlSchemaItemListCreate();
9968     if (ret->attrProhibs == NULL) {
9969         xmlFree(ret);
9970         return(NULL);
9971     }
9972     return(ret);
9973 }
9974
9975 /**
9976  * xmlSchemaNewParserCtxtUseDict:
9977  * @URL:  the location of the schema
9978  * @dict: the dictionary to be used
9979  *
9980  * Create an XML Schemas parse context for that file/resource expected
9981  * to contain an XML Schemas file.
9982  *
9983  * Returns the parser context or NULL in case of error
9984  */
9985 static xmlSchemaParserCtxtPtr
9986 xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9987 {
9988     xmlSchemaParserCtxtPtr ret;
9989
9990     ret = xmlSchemaParserCtxtCreate();
9991     if (ret == NULL)
9992         return (NULL);
9993     ret->dict = dict;
9994     xmlDictReference(dict);
9995     if (URL != NULL)
9996         ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
9997     return (ret);
9998 }
9999
10000 static int
10001 xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
10002 {
10003     if (vctxt->pctxt == NULL) {
10004         if (vctxt->schema != NULL)
10005             vctxt->pctxt =
10006                 xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
10007         else
10008             vctxt->pctxt = xmlSchemaNewParserCtxt("*");
10009         if (vctxt->pctxt == NULL) {
10010             VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
10011                 "failed to create a temp. parser context");
10012             return (-1);
10013         }
10014         /* TODO: Pass user data. */
10015         xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
10016             vctxt->warning, vctxt->errCtxt);
10017         xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
10018             vctxt->errCtxt);
10019     }
10020     return (0);
10021 }
10022
10023 /**
10024  * xmlSchemaGetSchemaBucket:
10025  * @pctxt: the schema parser context
10026  * @schemaLocation: the URI of the schema document
10027  *
10028  * Returns a schema bucket if it was already parsed.
10029  *
10030  * Returns a schema bucket if it was already parsed from
10031  *         @schemaLocation, NULL otherwise.
10032  */
10033 static xmlSchemaBucketPtr
10034 xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10035                             const xmlChar *schemaLocation)
10036 {
10037     xmlSchemaBucketPtr cur;
10038     xmlSchemaItemListPtr list;
10039
10040     list = pctxt->constructor->buckets;
10041     if (list->nbItems == 0)
10042         return(NULL);
10043     else {
10044         int i;
10045         for (i = 0; i < list->nbItems; i++) {
10046             cur = (xmlSchemaBucketPtr) list->items[i];
10047             /* Pointer comparison! */
10048             if (cur->schemaLocation == schemaLocation)
10049                 return(cur);
10050         }
10051     }
10052     return(NULL);
10053 }
10054
10055 static xmlSchemaBucketPtr
10056 xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10057                                      const xmlChar *schemaLocation,
10058                                      const xmlChar *targetNamespace)
10059 {
10060     xmlSchemaBucketPtr cur;
10061     xmlSchemaItemListPtr list;
10062
10063     list = pctxt->constructor->buckets;
10064     if (list->nbItems == 0)
10065         return(NULL);
10066     else {
10067         int i;
10068         for (i = 0; i < list->nbItems; i++) {
10069             cur = (xmlSchemaBucketPtr) list->items[i];
10070             /* Pointer comparison! */
10071             if ((cur->origTargetNamespace == NULL) &&
10072                 (cur->schemaLocation == schemaLocation) &&
10073                 (cur->targetNamespace == targetNamespace))
10074                 return(cur);
10075         }
10076     }
10077     return(NULL);
10078 }
10079
10080
10081 #define IS_BAD_SCHEMA_DOC(b) \
10082     (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10083
10084 static xmlSchemaBucketPtr
10085 xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10086                                  const xmlChar *targetNamespace,
10087                                  int imported)
10088 {
10089     xmlSchemaBucketPtr cur;
10090     xmlSchemaItemListPtr list;
10091
10092     list = pctxt->constructor->buckets;
10093     if (list->nbItems == 0)
10094         return(NULL);
10095     else {
10096         int i;
10097         for (i = 0; i < list->nbItems; i++) {
10098             cur = (xmlSchemaBucketPtr) list->items[i];
10099             if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10100                 (cur->origTargetNamespace == targetNamespace) &&
10101                 ((imported && cur->imported) ||
10102                  ((!imported) && (!cur->imported))))
10103                 return(cur);
10104         }
10105     }
10106     return(NULL);
10107 }
10108
10109 static int
10110 xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10111                      xmlSchemaPtr schema,
10112                      xmlSchemaBucketPtr bucket)
10113 {
10114     int oldFlags;
10115     xmlDocPtr oldDoc;
10116     xmlNodePtr node;
10117     int ret, oldErrs;
10118     xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10119
10120     /*
10121     * Save old values; reset the *main* schema.
10122     * URGENT TODO: This is not good; move the per-document information
10123     * to the parser. Get rid of passing the main schema to the
10124     * parsing functions.
10125     */
10126     oldFlags = schema->flags;
10127     oldDoc = schema->doc;
10128     if (schema->flags != 0)
10129         xmlSchemaClearSchemaDefaults(schema);
10130     schema->doc = bucket->doc;
10131     pctxt->schema = schema;
10132     /*
10133     * Keep the current target namespace on the parser *not* on the
10134     * main schema.
10135     */
10136     pctxt->targetNamespace = bucket->targetNamespace;
10137     WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
10138
10139     if ((bucket->targetNamespace != NULL) &&
10140         xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
10141         /*
10142         * We are parsing the schema for schemas!
10143         */
10144         pctxt->isS4S = 1;
10145     }
10146     /* Mark it as parsed, even if parsing fails. */
10147     bucket->parsed++;
10148     /* Compile the schema doc. */
10149     node = xmlDocGetRootElement(bucket->doc);
10150     ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10151     if (ret != 0)
10152         goto exit;
10153     /* An empty schema; just get out. */
10154     if (node->children == NULL)
10155         goto exit;
10156     oldErrs = pctxt->nberrors;
10157     ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10158     if (ret != 0)
10159         goto exit;
10160     /*
10161     * TODO: Not nice, but I'm not 100% sure we will get always an error
10162     * as a result of the obove functions; so better rely on pctxt->err
10163     * as well.
10164     */
10165     if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10166         ret = pctxt->err;
10167         goto exit;
10168     }
10169
10170 exit:
10171     WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10172     /* Restore schema values. */
10173     schema->doc = oldDoc;
10174     schema->flags = oldFlags;
10175     return(ret);
10176 }
10177
10178 static int
10179 xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10180                      xmlSchemaPtr schema,
10181                      xmlSchemaBucketPtr bucket)
10182 {
10183     xmlSchemaParserCtxtPtr newpctxt;
10184     int res = 0;
10185
10186     if (bucket == NULL)
10187         return(0);
10188     if (bucket->parsed) {
10189         PERROR_INT("xmlSchemaParseNewDoc",
10190             "reparsing a schema doc");
10191         return(-1);
10192     }
10193     if (bucket->doc == NULL) {
10194         PERROR_INT("xmlSchemaParseNewDoc",
10195             "parsing a schema doc, but there's no doc");
10196         return(-1);
10197     }
10198     if (pctxt->constructor == NULL) {
10199         PERROR_INT("xmlSchemaParseNewDoc",
10200             "no constructor");
10201         return(-1);
10202     }
10203     /* Create and init the temporary parser context. */
10204     newpctxt = xmlSchemaNewParserCtxtUseDict(
10205         (const char *) bucket->schemaLocation, pctxt->dict);
10206     if (newpctxt == NULL)
10207         return(-1);
10208     newpctxt->constructor = pctxt->constructor;
10209     /*
10210     * TODO: Can we avoid that the parser knows about the main schema?
10211     * It would be better if he knows about the current schema bucket
10212     * only.
10213     */
10214     newpctxt->schema = schema;
10215     xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
10216         pctxt->errCtxt);
10217     xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10218         pctxt->errCtxt);
10219     newpctxt->counter = pctxt->counter;
10220
10221
10222     res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10223
10224     /* Channel back errors and cleanup the temporary parser context. */
10225     if (res != 0)
10226         pctxt->err = res;
10227     pctxt->nberrors += newpctxt->nberrors;
10228     pctxt->counter = newpctxt->counter;
10229     newpctxt->constructor = NULL;
10230     /* Free the parser context. */
10231     xmlSchemaFreeParserCtxt(newpctxt);
10232     return(res);
10233 }
10234
10235 static void
10236 xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10237                                 xmlSchemaSchemaRelationPtr rel)
10238 {
10239     xmlSchemaSchemaRelationPtr cur = bucket->relations;
10240
10241     if (cur == NULL) {
10242         bucket->relations = rel;
10243         return;
10244     }
10245     while (cur->next != NULL)
10246         cur = cur->next;
10247     cur->next = rel;
10248 }
10249
10250
10251 static const xmlChar *
10252 xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10253                           xmlNodePtr ctxtNode)
10254 {
10255     /*
10256     * Build an absolue location URI.
10257     */
10258     if (location != NULL) {
10259         if (ctxtNode == NULL)
10260             return(location);
10261         else {
10262             xmlChar *base, *URI;
10263             const xmlChar *ret = NULL;
10264
10265             base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10266             if (base == NULL) {
10267                 URI = xmlBuildURI(location, ctxtNode->doc->URL);
10268             } else {
10269                 URI = xmlBuildURI(location, base);
10270                 xmlFree(base);
10271             }
10272             if (URI != NULL) {
10273                 ret = xmlDictLookup(dict, URI, -1);
10274                 xmlFree(URI);
10275                 return(ret);
10276             }
10277         }
10278     }
10279     return(NULL);
10280 }
10281
10282
10283
10284 /**
10285  * xmlSchemaAddSchemaDoc:
10286  * @pctxt:  a schema validation context
10287  * @schema:  the schema being built
10288  * @node:  a subtree containing XML Schema informations
10289  *
10290  * Parse an included (and to-be-redefined) XML schema document.
10291  *
10292  * Returns 0 on success, a positive error code on errors and
10293  *         -1 in case of an internal or API error.
10294  */
10295
10296 static int
10297 xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10298                 int type, /* import or include or redefine */
10299                 const xmlChar *schemaLocation,
10300                 xmlDocPtr schemaDoc,
10301                 const char *schemaBuffer,
10302                 int schemaBufferLen,
10303                 xmlNodePtr invokingNode,
10304                 const xmlChar *sourceTargetNamespace,
10305                 const xmlChar *importNamespace,
10306                 xmlSchemaBucketPtr *bucket)
10307 {
10308     const xmlChar *targetNamespace = NULL;
10309     xmlSchemaSchemaRelationPtr relation = NULL;
10310     xmlDocPtr doc = NULL;
10311     int res = 0, err = 0, located = 0, preserveDoc = 0;
10312     xmlSchemaBucketPtr bkt = NULL;
10313
10314     if (bucket != NULL)
10315         *bucket = NULL;
10316
10317     switch (type) {
10318         case XML_SCHEMA_SCHEMA_IMPORT:
10319         case XML_SCHEMA_SCHEMA_MAIN:
10320             err = XML_SCHEMAP_SRC_IMPORT;
10321             break;
10322         case XML_SCHEMA_SCHEMA_INCLUDE:
10323             err = XML_SCHEMAP_SRC_INCLUDE;
10324             break;
10325         case XML_SCHEMA_SCHEMA_REDEFINE:
10326             err = XML_SCHEMAP_SRC_REDEFINE;
10327             break;
10328     }
10329
10330
10331     /* Special handling for the main schema:
10332     * skip the location and relation logic and just parse the doc.
10333     * We need just a bucket to be returned in this case.
10334     */
10335     if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10336         goto doc_load;
10337
10338     /* Note that we expect the location to be an absulute URI. */
10339     if (schemaLocation != NULL) {
10340         bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10341         if ((bkt != NULL) &&
10342             (pctxt->constructor->bucket == bkt)) {
10343             /* Report self-imports/inclusions/redefinitions. */
10344
10345             xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10346                 invokingNode, NULL,
10347                 "The schema must not import/include/redefine itself",
10348                 NULL, NULL);
10349             goto exit;
10350         }
10351     }
10352     /*
10353     * Create a relation for the graph of schemas.
10354     */
10355     relation = xmlSchemaSchemaRelationCreate();
10356     if (relation == NULL)
10357         return(-1);
10358     xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10359         relation);
10360     relation->type = type;
10361
10362     /*
10363     * Save the namespace import information.
10364     */
10365     if (WXS_IS_BUCKET_IMPMAIN(type)) {
10366         relation->importNamespace = importNamespace;
10367         if (schemaLocation == NULL) {
10368             /*
10369             * No location; this is just an import of the namespace.
10370             * Note that we don't assign a bucket to the relation
10371             * in this case.
10372             */
10373             goto exit;
10374         }
10375         targetNamespace = importNamespace;
10376     }
10377
10378     /* Did we already fetch the doc? */
10379     if (bkt != NULL) {
10380         if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
10381             /*
10382             * We included/redefined and then try to import a schema,
10383             * but the new location provided for import was different.
10384             */
10385             if (schemaLocation == NULL)
10386                 schemaLocation = BAD_CAST "in_memory_buffer";
10387             if (!xmlStrEqual(schemaLocation,
10388                 bkt->schemaLocation)) {
10389                 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10390                     invokingNode, NULL,
10391                     "The schema document '%s' cannot be imported, since "
10392                     "it was already included or redefined",
10393                     schemaLocation, NULL);
10394                 goto exit;
10395             }
10396         } else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
10397             /*
10398             * We imported and then try to include/redefine a schema,
10399             * but the new location provided for the include/redefine
10400             * was different.
10401             */
10402             if (schemaLocation == NULL)
10403                 schemaLocation = BAD_CAST "in_memory_buffer";
10404             if (!xmlStrEqual(schemaLocation,
10405                 bkt->schemaLocation)) {
10406                 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10407                     invokingNode, NULL,
10408                     "The schema document '%s' cannot be included or "
10409                     "redefined, since it was already imported",
10410                     schemaLocation, NULL);
10411                 goto exit;
10412             }
10413         }
10414     }
10415
10416     if (WXS_IS_BUCKET_IMPMAIN(type)) {
10417         /*
10418         * Given that the schemaLocation [attribute] is only a hint, it is open
10419         * to applications to ignore all but the first <import> for a given
10420         * namespace, regardless of the `actual value` of schemaLocation, but
10421         * such a strategy risks missing useful information when new
10422         * schemaLocations are offered.
10423         *
10424         * We will use the first <import> that comes with a location.
10425         * Further <import>s *with* a location, will result in an error.
10426         * TODO: Better would be to just report a warning here, but
10427         * we'll try it this way until someone complains.
10428         *
10429         * Schema Document Location Strategy:
10430         * 3 Based on the namespace name, identify an existing schema document,
10431         * either as a resource which is an XML document or a <schema> element
10432         * information item, in some local schema repository;
10433         * 5 Attempt to resolve the namespace name to locate such a resource.
10434         *
10435         * NOTE: (3) and (5) are not supported.
10436         */
10437         if (bkt != NULL) {
10438             relation->bucket = bkt;
10439             goto exit;
10440         }
10441         bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10442             importNamespace, 1);
10443
10444         if (bkt != NULL) {
10445             relation->bucket = bkt;
10446             if (bkt->schemaLocation == NULL) {
10447                 /* First given location of the schema; load the doc. */
10448                 bkt->schemaLocation = schemaLocation;
10449             } else {
10450                 if (!xmlStrEqual(schemaLocation,
10451                     bkt->schemaLocation)) {
10452                     /*
10453                     * Additional location given; just skip it.
10454                     * URGENT TODO: We should report a warning here.
10455                     * res = XML_SCHEMAP_SRC_IMPORT;
10456                     */
10457                     if (schemaLocation == NULL)
10458                         schemaLocation = BAD_CAST "in_memory_buffer";
10459
10460                     xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10461                         XML_SCHEMAP_WARN_SKIP_SCHEMA,
10462                         invokingNode, NULL,
10463                         "Skipping import of schema located at '%s' for the "
10464                         "namespace '%s', since this namespace was already "
10465                         "imported with the schema located at '%s'",
10466                         schemaLocation, importNamespace, bkt->schemaLocation);
10467                 }
10468                 goto exit;
10469             }
10470         }
10471         /*
10472         * No bucket + first location: load the doc and create a
10473         * bucket.
10474         */
10475     } else {
10476         /* <include> and <redefine> */
10477         if (bkt != NULL) {
10478
10479             if ((bkt->origTargetNamespace == NULL) &&
10480                 (bkt->targetNamespace != sourceTargetNamespace)) {
10481                 xmlSchemaBucketPtr chamel;
10482
10483                 /*
10484                 * Chameleon include/redefine: skip loading only if it was
10485                 * aleady build for the targetNamespace of the including
10486                 * schema.
10487                 */
10488                 /*
10489                 * URGENT TODO: If the schema is a chameleon-include then copy
10490                 * the components into the including schema and modify the
10491                 * targetNamespace of those components, do nothing otherwise.
10492                 * NOTE: This is currently worked-around by compiling the
10493                 * chameleon for every destinct including targetNamespace; thus
10494                 * not performant at the moment.
10495                 * TODO: Check when the namespace in wildcards for chameleons
10496                 * needs to be converted: before we built wildcard intersections
10497                 * or after.
10498                 *   Answer: after!
10499                 */
10500                 chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10501                     schemaLocation, sourceTargetNamespace);
10502                 if (chamel != NULL) {
10503                     /* A fitting chameleon was already parsed; NOP. */
10504                     relation->bucket = chamel;
10505                     goto exit;
10506                 }
10507                 /*
10508                 * We need to parse the chameleon again for a different
10509                 * targetNamespace.
10510                 * CHAMELEON TODO: Optimize this by only parsing the
10511                 * chameleon once, and then copying the components to
10512                 * the new targetNamespace.
10513                 */
10514                 bkt = NULL;
10515             } else {
10516                 relation->bucket = bkt;
10517                 goto exit;
10518             }
10519         }
10520     }
10521     if ((bkt != NULL) && (bkt->doc != NULL)) {
10522         PERROR_INT("xmlSchemaAddSchemaDoc",
10523             "trying to load a schema doc, but a doc is already "
10524             "assigned to the schema bucket");
10525         goto exit_failure;
10526     }
10527
10528 doc_load:
10529     /*
10530     * Load the document.
10531     */
10532     if (schemaDoc != NULL) {
10533         doc = schemaDoc;
10534         /* Don' free this one, since it was provided by the caller. */
10535         preserveDoc = 1;
10536         /* TODO: Does the context or the doc hold the location? */
10537         if (schemaDoc->URL != NULL)
10538             schemaLocation = xmlDictLookup(pctxt->dict,
10539                 schemaDoc->URL, -1);
10540         else
10541             schemaLocation = BAD_CAST "in_memory_buffer";
10542     } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10543         xmlParserCtxtPtr parserCtxt;
10544
10545         parserCtxt = xmlNewParserCtxt();
10546         if (parserCtxt == NULL) {
10547             xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10548                 "allocating a parser context", NULL);
10549             goto exit_failure;
10550         }
10551         if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10552             /*
10553             * TODO: Do we have to burden the schema parser dict with all
10554             * the content of the schema doc?
10555             */
10556             xmlDictFree(parserCtxt->dict);
10557             parserCtxt->dict = pctxt->dict;
10558             xmlDictReference(parserCtxt->dict);
10559         }
10560         if (schemaLocation != NULL) {
10561             /* Parse from file. */
10562             doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10563                 NULL, SCHEMAS_PARSE_OPTIONS);
10564         } else if (schemaBuffer != NULL) {
10565             /* Parse from memory buffer. */
10566             doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10567                 NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10568             schemaLocation = BAD_CAST "in_memory_buffer";
10569             if (doc != NULL)
10570                 doc->URL = xmlStrdup(schemaLocation);
10571         }
10572         /*
10573         * For <import>:
10574         * 2.1 The referent is (a fragment of) a resource which is an
10575         * XML document (see clause 1.1), which in turn corresponds to
10576         * a <schema> element information item in a well-formed information
10577         * set, which in turn corresponds to a valid schema.
10578         * TODO: (2.1) fragments of XML documents are not supported.
10579         *
10580         * 2.2 The referent is a <schema> element information item in
10581         * a well-formed information set, which in turn corresponds
10582         * to a valid schema.
10583         * TODO: (2.2) is not supported.
10584         */
10585         if (doc == NULL) {
10586             xmlErrorPtr lerr;
10587             lerr = xmlGetLastError();
10588             /*
10589             * Check if this a parser error, or if the document could
10590             * just not be located.
10591             * TODO: Try to find specific error codes to react only on
10592             * localisation failures.
10593             */
10594             if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10595                 /*
10596                 * We assume a parser error here.
10597                 */
10598                 located = 1;
10599                 /* TODO: Error code ?? */
10600                 res = XML_SCHEMAP_SRC_IMPORT_2_1;
10601                 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10602                     invokingNode, NULL,
10603                     "Failed to parse the XML resource '%s'",
10604                     schemaLocation, NULL);
10605             }
10606         }
10607         xmlFreeParserCtxt(parserCtxt);
10608         if ((doc == NULL) && located)
10609             goto exit_error;
10610     } else {
10611         xmlSchemaPErr(pctxt, NULL,
10612             XML_SCHEMAP_NOTHING_TO_PARSE,
10613             "No information for parsing was provided with the "
10614             "given schema parser context.\n",
10615             NULL, NULL);
10616         goto exit_failure;
10617     }
10618     /*
10619     * Preprocess the document.
10620     */
10621     if (doc != NULL) {
10622         xmlNodePtr docElem = NULL;
10623
10624         located = 1;
10625         docElem = xmlDocGetRootElement(doc);
10626         if (docElem == NULL) {
10627             xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10628                 invokingNode, NULL,
10629                 "The document '%s' has no document element",
10630                 schemaLocation, NULL);
10631             goto exit_error;
10632         }
10633         /*
10634         * Remove all the blank text nodes.
10635         */
10636         xmlSchemaCleanupDoc(pctxt, docElem);
10637         /*
10638         * Check the schema's top level element.
10639         */
10640         if (!IS_SCHEMA(docElem, "schema")) {
10641             xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10642                 invokingNode, NULL,
10643                 "The XML document '%s' is not a schema document",
10644                 schemaLocation, NULL);
10645             goto exit_error;
10646         }
10647         /*
10648         * Note that we don't apply a type check for the
10649         * targetNamespace value here.
10650         */
10651         targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10652             "targetNamespace");
10653     }
10654
10655 /* after_doc_loading: */
10656     if ((bkt == NULL) && located) {
10657         /* Only create a bucket if the schema was located. */
10658         bkt = xmlSchemaBucketCreate(pctxt, type,
10659             targetNamespace);
10660         if (bkt == NULL)
10661             goto exit_failure;
10662     }
10663     if (bkt != NULL) {
10664         bkt->schemaLocation = schemaLocation;
10665         bkt->located = located;
10666         if (doc != NULL) {
10667             bkt->doc = doc;
10668             bkt->targetNamespace = targetNamespace;
10669             bkt->origTargetNamespace = targetNamespace;
10670             if (preserveDoc)
10671                 bkt->preserveDoc = 1;
10672         }
10673         if (WXS_IS_BUCKET_IMPMAIN(type))
10674             bkt->imported++;
10675             /*
10676             * Add it to the graph of schemas.
10677             */
10678         if (relation != NULL)
10679             relation->bucket = bkt;
10680     }
10681
10682 exit:
10683     /*
10684     * Return the bucket explicitely; this is needed for the
10685     * main schema.
10686     */
10687     if (bucket != NULL)
10688         *bucket = bkt;
10689     return (0);
10690
10691 exit_error:
10692     if ((doc != NULL) && (! preserveDoc)) {
10693         xmlFreeDoc(doc);
10694         if (bkt != NULL)
10695             bkt->doc = NULL;
10696     }
10697     return(pctxt->err);
10698
10699 exit_failure:
10700     if ((doc != NULL) && (! preserveDoc)) {
10701         xmlFreeDoc(doc);
10702         if (bkt != NULL)
10703             bkt->doc = NULL;
10704     }
10705     return (-1);
10706 }
10707
10708 /**
10709  * xmlSchemaParseImport:
10710  * @ctxt:  a schema validation context
10711  * @schema:  the schema being built
10712  * @node:  a subtree containing XML Schema informations
10713  *
10714  * parse a XML schema Import definition
10715  * *WARNING* this interface is highly subject to change
10716  *
10717  * Returns 0 in case of success, a positive error code if
10718  * not valid and -1 in case of an internal error.
10719  */
10720 static int
10721 xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
10722                      xmlNodePtr node)
10723 {
10724     xmlNodePtr child;
10725     const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10726     const xmlChar *thisTargetNamespace;
10727     xmlAttrPtr attr;
10728     int ret = 0;
10729     xmlSchemaBucketPtr bucket = NULL;
10730
10731     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10732         return (-1);
10733
10734     /*
10735     * Check for illegal attributes.
10736     */
10737     attr = node->properties;
10738     while (attr != NULL) {
10739         if (attr->ns == NULL) {
10740             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10741                 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10742                 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10743                 xmlSchemaPIllegalAttrErr(pctxt,
10744                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10745             }
10746         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10747             xmlSchemaPIllegalAttrErr(pctxt,
10748                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10749         }
10750         attr = attr->next;
10751     }
10752     /*
10753     * Extract and validate attributes.
10754     */
10755     if (xmlSchemaPValAttr(pctxt, NULL, node,
10756         "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10757         &namespaceName) != 0) {
10758         xmlSchemaPSimpleTypeErr(pctxt,
10759             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10760             NULL, node,
10761             xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10762             NULL, namespaceName, NULL, NULL, NULL);
10763         return (pctxt->err);
10764     }
10765
10766     if (xmlSchemaPValAttr(pctxt, NULL, node,
10767         "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10768         &schemaLocation) != 0) {
10769         xmlSchemaPSimpleTypeErr(pctxt,
10770             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10771             NULL, node,
10772             xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10773             NULL, schemaLocation, NULL, NULL, NULL);
10774         return (pctxt->err);
10775     }
10776     /*
10777     * And now for the children...
10778     */
10779     child = node->children;
10780     if (IS_SCHEMA(child, "annotation")) {
10781         /*
10782          * the annotation here is simply discarded ...
10783          * TODO: really?
10784          */
10785         child = child->next;
10786     }
10787     if (child != NULL) {
10788         xmlSchemaPContentErr(pctxt,
10789             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10790             NULL, node, child, NULL,
10791             "(annotation?)");
10792     }
10793     /*
10794     * Apply additional constraints.
10795     *
10796     * Note that it is important to use the original @targetNamespace
10797     * (or none at all), to rule out imports of schemas _with_ a
10798     * @targetNamespace if the importing schema is a chameleon schema
10799     * (with no @targetNamespace).
10800     */
10801     thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
10802     if (namespaceName != NULL) {
10803         /*
10804         * 1.1 If the namespace [attribute] is present, then its `actual value`
10805         * must not match the `actual value` of the enclosing <schema>'s
10806         * targetNamespace [attribute].
10807         */
10808         if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
10809             xmlSchemaPCustomErr(pctxt,
10810                 XML_SCHEMAP_SRC_IMPORT_1_1,
10811                 NULL, node,
10812                 "The value of the attribute 'namespace' must not match "
10813                 "the target namespace '%s' of the importing schema",
10814                 thisTargetNamespace);
10815             return (pctxt->err);
10816         }
10817     } else {
10818         /*
10819         * 1.2 If the namespace [attribute] is not present, then the enclosing
10820         * <schema> must have a targetNamespace [attribute].
10821         */
10822         if (thisTargetNamespace == NULL) {
10823             xmlSchemaPCustomErr(pctxt,
10824                 XML_SCHEMAP_SRC_IMPORT_1_2,
10825                 NULL, node,
10826                 "The attribute 'namespace' must be existent if "
10827                 "the importing schema has no target namespace",
10828                 NULL);
10829             return (pctxt->err);
10830         }
10831     }
10832     /*
10833     * Locate and acquire the schema document.
10834     */
10835     if (schemaLocation != NULL)
10836         schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10837             schemaLocation, node);
10838     ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
10839         schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
10840         namespaceName, &bucket);
10841
10842     if (ret != 0)
10843         return(ret);
10844
10845     /*
10846     * For <import>: "It is *not* an error for the application
10847     * schema reference strategy to fail."
10848     * So just don't parse if no schema document was found.
10849     * Note that we will get no bucket if the schema could not be
10850     * located or if there was no schemaLocation.
10851     */
10852     if ((bucket == NULL) && (schemaLocation != NULL)) {
10853         xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10854             XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10855             node, NULL,
10856             "Failed to locate a schema at location '%s'. "
10857             "Skipping the import", schemaLocation, NULL, NULL);
10858     }
10859
10860     if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10861         ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10862     }
10863
10864     return (ret);
10865 }
10866
10867 static int
10868 xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10869                                      xmlSchemaPtr schema,
10870                                      xmlNodePtr node,
10871                                      xmlChar **schemaLocation,
10872                                      int type)
10873 {
10874     xmlAttrPtr attr;
10875
10876     if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10877         (schemaLocation == NULL))
10878         return (-1);
10879
10880     *schemaLocation = NULL;
10881     /*
10882     * Check for illegal attributes.
10883     * Applies for both <include> and <redefine>.
10884     */
10885     attr = node->properties;
10886     while (attr != NULL) {
10887         if (attr->ns == NULL) {
10888             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10889                 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10890                 xmlSchemaPIllegalAttrErr(pctxt,
10891                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10892             }
10893         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10894             xmlSchemaPIllegalAttrErr(pctxt,
10895                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10896         }
10897         attr = attr->next;
10898     }
10899     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
10900     /*
10901     * Preliminary step, extract the URI-Reference and make an URI
10902     * from the base.
10903     */
10904     /*
10905     * Attribute "schemaLocation" is mandatory.
10906     */
10907     attr = xmlSchemaGetPropNode(node, "schemaLocation");
10908     if (attr != NULL) {
10909         xmlChar *base = NULL;
10910         xmlChar *uri = NULL;
10911
10912         if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
10913             xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10914             (const xmlChar **) schemaLocation) != 0)
10915             goto exit_error;
10916         base = xmlNodeGetBase(node->doc, node);
10917         if (base == NULL) {
10918             uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10919         } else {
10920             uri = xmlBuildURI(*schemaLocation, base);
10921             xmlFree(base);
10922         }
10923         if (uri == NULL) {
10924             PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10925                 "could not build an URI from the schemaLocation")
10926             goto exit_failure;
10927         }
10928         (*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10929         xmlFree(uri);
10930     } else {
10931         xmlSchemaPMissingAttrErr(pctxt,
10932             XML_SCHEMAP_S4S_ATTR_MISSING,
10933             NULL, node, "schemaLocation", NULL);
10934         goto exit_error;
10935     }
10936     /*
10937     * Report self-inclusion and self-redefinition.
10938     */
10939     if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
10940         if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
10941             xmlSchemaPCustomErr(pctxt,
10942                 XML_SCHEMAP_SRC_REDEFINE,
10943                 NULL, node,
10944                 "The schema document '%s' cannot redefine itself.",
10945                 *schemaLocation);
10946         } else {
10947             xmlSchemaPCustomErr(pctxt,
10948                 XML_SCHEMAP_SRC_INCLUDE,
10949                 NULL, node,
10950                 "The schema document '%s' cannot include itself.",
10951                 *schemaLocation);
10952         }
10953         goto exit_error;
10954     }
10955
10956     return(0);
10957 exit_error:
10958     return(pctxt->err);
10959 exit_failure:
10960     return(-1);
10961 }
10962
10963 static int
10964 xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
10965                                 xmlSchemaPtr schema,
10966                                 xmlNodePtr node,
10967                                 int type)
10968 {
10969     xmlNodePtr child = NULL;
10970     const xmlChar *schemaLocation = NULL;
10971     int res = 0; /* hasRedefinitions = 0 */
10972     int isChameleon = 0, wasChameleon = 0;
10973     xmlSchemaBucketPtr bucket = NULL;
10974
10975     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10976         return (-1);
10977
10978     /*
10979     * Parse attributes. Note that the returned schemaLocation will
10980     * be already converted to an absolute URI.
10981     */
10982     res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
10983         node, (xmlChar **) (&schemaLocation), type);
10984     if (res != 0)
10985         return(res);
10986     /*
10987     * Load and add the schema document.
10988     */
10989     res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
10990         NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
10991     if (res != 0)
10992         return(res);
10993     /*
10994     * If we get no schema bucket back, then this means that the schema
10995     * document could not be located or was broken XML or was not
10996     * a schema document.
10997     */
10998     if ((bucket == NULL) || (bucket->doc == NULL)) {
10999         if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
11000             /*
11001             * WARNING for <include>:
11002             * We will raise an error if the schema cannot be located
11003             * for inclusions, since the that was the feedback from the
11004             * schema people. I.e. the following spec piece will *not* be
11005             * satisfied:
11006             * SPEC src-include: "It is not an error for the `actual value` of the
11007             * schemaLocation [attribute] to fail to resolve it all, in which
11008             * case no corresponding inclusion is performed.
11009             * So do we need a warning report here?"
11010             */
11011             res = XML_SCHEMAP_SRC_INCLUDE;
11012             xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
11013                 node, NULL,
11014                 "Failed to load the document '%s' for inclusion",
11015                 schemaLocation, NULL);
11016         } else {
11017             /*
11018             * NOTE: This was changed to raise an error even if no redefinitions
11019             * are specified.
11020             *
11021             * SPEC src-redefine (1)
11022             * "If there are any element information items among the [children]
11023             * other than <annotation> then the `actual value` of the
11024             * schemaLocation [attribute] must successfully resolve."
11025             * TODO: Ask the WG if a the location has always to resolve
11026             * here as well!
11027             */
11028             res = XML_SCHEMAP_SRC_REDEFINE;
11029             xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
11030                 node, NULL,
11031                 "Failed to load the document '%s' for redefinition",
11032                 schemaLocation, NULL);
11033         }
11034     } else {
11035         /*
11036         * Check targetNamespace sanity before parsing the new schema.
11037         * TODO: Note that we won't check further content if the
11038         * targetNamespace was bad.
11039         */
11040         if (bucket->origTargetNamespace != NULL) {
11041             /*
11042             * SPEC src-include (2.1)
11043             * "SII has a targetNamespace [attribute], and its `actual
11044             * value` is identical to the `actual value` of the targetNamespace
11045             * [attribute] of SII' (which must have such an [attribute])."
11046             */
11047             if (pctxt->targetNamespace == NULL) {
11048                 xmlSchemaCustomErr(ACTXT_CAST pctxt,
11049                     XML_SCHEMAP_SRC_INCLUDE,
11050                     node, NULL,
11051                     "The target namespace of the included/redefined schema "
11052                     "'%s' has to be absent, since the including/redefining "
11053                     "schema has no target namespace",
11054                     schemaLocation, NULL);
11055                 goto exit_error;
11056             } else if (!xmlStrEqual(bucket->origTargetNamespace,
11057                 pctxt->targetNamespace)) {
11058                 /* TODO: Change error function. */
11059                 xmlSchemaPCustomErrExt(pctxt,
11060                     XML_SCHEMAP_SRC_INCLUDE,
11061                     NULL, node,
11062                     "The target namespace '%s' of the included/redefined "
11063                     "schema '%s' differs from '%s' of the "
11064                     "including/redefining schema",
11065                     bucket->origTargetNamespace, schemaLocation,
11066                     pctxt->targetNamespace);
11067                 goto exit_error;
11068             }
11069         } else if (pctxt->targetNamespace != NULL) {
11070             /*
11071             * Chameleons: the original target namespace will
11072             * differ from the resulting namespace.
11073             */
11074             isChameleon = 1;
11075             if (bucket->parsed &&
11076                 bucket->origTargetNamespace != NULL) {
11077                 xmlSchemaCustomErr(ACTXT_CAST pctxt,
11078                     XML_SCHEMAP_SRC_INCLUDE,
11079                     node, NULL,
11080                     "The target namespace of the included/redefined schema "
11081                     "'%s' has to be absent or the same as the "
11082                     "including/redefining schema's target namespace",
11083                     schemaLocation, NULL);
11084                 goto exit_error;
11085             }
11086             bucket->targetNamespace = pctxt->targetNamespace;
11087         }
11088     }
11089     /*
11090     * Parse the schema.
11091     */
11092     if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11093         if (isChameleon) {
11094             /* TODO: Get rid of this flag on the schema itself. */
11095             if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11096                 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11097             } else
11098                 wasChameleon = 1;
11099         }
11100         xmlSchemaParseNewDoc(pctxt, schema, bucket);
11101         /* Restore chameleon flag. */
11102         if (isChameleon && (!wasChameleon))
11103             schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11104     }
11105     /*
11106     * And now for the children...
11107     */
11108     child = node->children;
11109     if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11110         /*
11111         * Parse (simpleType | complexType | group | attributeGroup))*
11112         */
11113         pctxt->redefined = bucket;
11114         /*
11115         * How to proceed if the redefined schema was not located?
11116         */
11117         pctxt->isRedefine = 1;
11118         while (IS_SCHEMA(child, "annotation") ||
11119             IS_SCHEMA(child, "simpleType") ||
11120             IS_SCHEMA(child, "complexType") ||
11121             IS_SCHEMA(child, "group") ||
11122             IS_SCHEMA(child, "attributeGroup")) {
11123             if (IS_SCHEMA(child, "annotation")) {
11124                 /*
11125                 * TODO: discard or not?
11126                 */
11127             } else if (IS_SCHEMA(child, "simpleType")) {
11128                 xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11129             } else if (IS_SCHEMA(child, "complexType")) {
11130                 xmlSchemaParseComplexType(pctxt, schema, child, 1);
11131                 /* hasRedefinitions = 1; */
11132             } else if (IS_SCHEMA(child, "group")) {
11133                 /* hasRedefinitions = 1; */
11134                 xmlSchemaParseModelGroupDefinition(pctxt,
11135                     schema, child);
11136             } else if (IS_SCHEMA(child, "attributeGroup")) {
11137                 /* hasRedefinitions = 1; */
11138                 xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11139                     child);
11140             }
11141             child = child->next;
11142         }
11143         pctxt->redefined = NULL;
11144         pctxt->isRedefine = 0;
11145     } else {
11146         if (IS_SCHEMA(child, "annotation")) {
11147             /*
11148             * TODO: discard or not?
11149             */
11150             child = child->next;
11151         }
11152     }
11153     if (child != NULL) {
11154         res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
11155         if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11156             xmlSchemaPContentErr(pctxt, res,
11157                 NULL, node, child, NULL,
11158                 "(annotation | (simpleType | complexType | group | attributeGroup))*");
11159         } else {
11160              xmlSchemaPContentErr(pctxt, res,
11161                 NULL, node, child, NULL,
11162                 "(annotation?)");
11163         }
11164     }
11165     return(res);
11166
11167 exit_error:
11168     return(pctxt->err);
11169 }
11170
11171 static int
11172 xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11173                        xmlNodePtr node)
11174 {
11175     int res;
11176 #ifndef ENABLE_REDEFINE
11177     TODO
11178     return(0);
11179 #endif
11180     res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11181         XML_SCHEMA_SCHEMA_REDEFINE);
11182     if (res != 0)
11183         return(res);
11184     return(0);
11185 }
11186
11187 static int
11188 xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11189                        xmlNodePtr node)
11190 {
11191     int res;
11192
11193     res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11194         XML_SCHEMA_SCHEMA_INCLUDE);
11195     if (res != 0)
11196         return(res);
11197     return(0);
11198 }
11199
11200 /**
11201  * xmlSchemaParseModelGroup:
11202  * @ctxt:  a schema validation context
11203  * @schema:  the schema being built
11204  * @node:  a subtree containing XML Schema informations
11205  * @type: the "compositor" type
11206  * @particleNeeded: if a a model group with a particle
11207  *
11208  * parse a XML schema Sequence definition.
11209  * Applies parts of:
11210  *   Schema Representation Constraint:
11211  *     Redefinition Constraints and Semantics (src-redefine)
11212  *     (6.1), (6.1.1), (6.1.2)
11213  *
11214  *   Schema Component Constraint:
11215  *     All Group Limited (cos-all-limited) (2)
11216  *     TODO: Actually this should go to component-level checks,
11217  *     but is done here due to performance. Move it to an other layer
11218  *     is schema construction via an API is implemented.
11219  *
11220  * *WARNING* this interface is highly subject to change
11221  *
11222  * Returns -1 in case of error, 0 if the declaration is improper and
11223  *         1 in case of success.
11224  */
11225 static xmlSchemaTreeItemPtr
11226 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11227                          xmlNodePtr node, xmlSchemaTypeType type,
11228                          int withParticle)
11229 {
11230     xmlSchemaModelGroupPtr item;
11231     xmlSchemaParticlePtr particle = NULL;
11232     xmlNodePtr child = NULL;
11233     xmlAttrPtr attr;
11234     int min = 1, max = 1, isElemRef, hasRefs = 0;
11235
11236     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11237         return (NULL);
11238     /*
11239     * Create a model group with the given compositor.
11240     */
11241     item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
11242     if (item == NULL)
11243         return (NULL);
11244
11245     if (withParticle) {
11246         if (type == XML_SCHEMA_TYPE_ALL) {
11247             min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
11248             max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
11249         } else {
11250             /* choice + sequence */
11251             min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11252             max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11253                 "(xs:nonNegativeInteger | unbounded)");
11254         }
11255         xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11256         /*
11257         * Create a particle
11258         */
11259         particle = xmlSchemaAddParticle(ctxt, node, min, max);
11260         if (particle == NULL)
11261             return (NULL);
11262         particle->children = (xmlSchemaTreeItemPtr) item;
11263         /*
11264         * Check for illegal attributes.
11265         */
11266         attr = node->properties;
11267         while (attr != NULL) {
11268             if (attr->ns == NULL) {
11269                 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11270                     (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11271                     (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
11272                     xmlSchemaPIllegalAttrErr(ctxt,
11273                         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11274                 }
11275             } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11276                 xmlSchemaPIllegalAttrErr(ctxt,
11277                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11278             }
11279             attr = attr->next;
11280         }
11281     } else {
11282         /*
11283         * Check for illegal attributes.
11284         */
11285         attr = node->properties;
11286         while (attr != NULL) {
11287             if (attr->ns == NULL) {
11288                 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
11289                     xmlSchemaPIllegalAttrErr(ctxt,
11290                         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11291                 }
11292             } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11293                 xmlSchemaPIllegalAttrErr(ctxt,
11294                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11295             }
11296             attr = attr->next;
11297         }
11298     }
11299
11300     /*
11301     * Extract and validate attributes.
11302     */
11303     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11304     /*
11305     * And now for the children...
11306     */
11307     child = node->children;
11308     if (IS_SCHEMA(child, "annotation")) {
11309         item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
11310         child = child->next;
11311     }
11312     if (type == XML_SCHEMA_TYPE_ALL) {
11313         xmlSchemaParticlePtr part, last = NULL;
11314
11315         while (IS_SCHEMA(child, "element")) {
11316             part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
11317                 schema, child, &isElemRef, 0);
11318             /*
11319             * SPEC cos-all-limited (2)
11320             * "The {max occurs} of all the particles in the {particles}
11321             * of the ('all') group must be 0 or 1.
11322             */
11323             if (part != NULL) {
11324                 if (isElemRef)
11325                     hasRefs++;
11326                 if (part->minOccurs > 1) {
11327                     xmlSchemaPCustomErr(ctxt,
11328                         XML_SCHEMAP_COS_ALL_LIMITED,
11329                         NULL, child,
11330                         "Invalid value for minOccurs (must be 0 or 1)",
11331                         NULL);
11332                     /* Reset to 1. */
11333                     part->minOccurs = 1;
11334                 }
11335                 if (part->maxOccurs > 1) {
11336                     xmlSchemaPCustomErr(ctxt,
11337                         XML_SCHEMAP_COS_ALL_LIMITED,
11338                         NULL, child,
11339                         "Invalid value for maxOccurs (must be 0 or 1)",
11340                         NULL);
11341                     /* Reset to 1. */
11342                     part->maxOccurs = 1;
11343                 }
11344                 if (last == NULL)
11345                     item->children = (xmlSchemaTreeItemPtr) part;
11346                 else
11347                     last->next = (xmlSchemaTreeItemPtr) part;
11348                 last = part;
11349             }
11350             child = child->next;
11351         }
11352         if (child != NULL) {
11353             xmlSchemaPContentErr(ctxt,
11354                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11355                 NULL, node, child, NULL,
11356                 "(annotation?, (annotation?, element*)");
11357         }
11358     } else {
11359         /* choice + sequence */
11360         xmlSchemaTreeItemPtr part = NULL, last = NULL;
11361
11362         while ((IS_SCHEMA(child, "element")) ||
11363             (IS_SCHEMA(child, "group")) ||
11364             (IS_SCHEMA(child, "any")) ||
11365             (IS_SCHEMA(child, "choice")) ||
11366             (IS_SCHEMA(child, "sequence"))) {
11367
11368             if (IS_SCHEMA(child, "element")) {
11369                 part = (xmlSchemaTreeItemPtr)
11370                     xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11371                 if (part && isElemRef)
11372                     hasRefs++;
11373             } else if (IS_SCHEMA(child, "group")) {
11374                 part =
11375                     xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11376                 if (part != NULL)
11377                     hasRefs++;
11378                 /*
11379                 * Handle redefinitions.
11380                 */
11381                 if (ctxt->isRedefine && ctxt->redef &&
11382                     (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11383                     part && part->children)
11384                 {
11385                     if ((xmlSchemaGetQNameRefName(part->children) ==
11386                             ctxt->redef->refName) &&
11387                         (xmlSchemaGetQNameRefTargetNs(part->children) ==
11388                             ctxt->redef->refTargetNs))
11389                     {
11390                         /*
11391                         * SPEC src-redefine:
11392                         * (6.1) "If it has a <group> among its contents at
11393                         * some level the `actual value` of whose ref
11394                         * [attribute] is the same as the `actual value` of
11395                         * its own name attribute plus target namespace, then
11396                         * all of the following must be true:"
11397                         * (6.1.1) "It must have exactly one such group."
11398                         */
11399                         if (ctxt->redefCounter != 0) {
11400                             xmlChar *str = NULL;
11401
11402                             xmlSchemaCustomErr(ACTXT_CAST ctxt,
11403                                 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11404                                 "The redefining model group definition "
11405                                 "'%s' must not contain more than one "
11406                                 "reference to the redefined definition",
11407                                 xmlSchemaFormatQName(&str,
11408                                     ctxt->redef->refTargetNs,
11409                                     ctxt->redef->refName),
11410                                 NULL);
11411                             FREE_AND_NULL(str)
11412                             part = NULL;
11413                         } else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11414                             ((WXS_PARTICLE(part))->maxOccurs != 1))
11415                         {
11416                             xmlChar *str = NULL;
11417                             /*
11418                             * SPEC src-redefine:
11419                             * (6.1.2) "The `actual value` of both that
11420                             * group's minOccurs and maxOccurs [attribute]
11421                             * must be 1 (or `absent`).
11422                             */
11423                             xmlSchemaCustomErr(ACTXT_CAST ctxt,
11424                                 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11425                                 "The redefining model group definition "
11426                                 "'%s' must not contain a reference to the "
11427                                 "redefined definition with a "
11428                                 "maxOccurs/minOccurs other than 1",
11429                                 xmlSchemaFormatQName(&str,
11430                                     ctxt->redef->refTargetNs,
11431                                     ctxt->redef->refName),
11432                                 NULL);
11433                             FREE_AND_NULL(str)
11434                             part = NULL;
11435                         }
11436                         ctxt->redef->reference = WXS_BASIC_CAST part;
11437                         ctxt->redefCounter++;
11438                     }
11439                 }
11440             } else if (IS_SCHEMA(child, "any")) {
11441                 part = (xmlSchemaTreeItemPtr)
11442                     xmlSchemaParseAny(ctxt, schema, child);
11443             } else if (IS_SCHEMA(child, "choice")) {
11444                 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11445                     XML_SCHEMA_TYPE_CHOICE, 1);
11446             } else if (IS_SCHEMA(child, "sequence")) {
11447                 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11448                     XML_SCHEMA_TYPE_SEQUENCE, 1);
11449             }
11450             if (part != NULL) {
11451                 if (last == NULL)
11452                     item->children = part;
11453                 else
11454                     last->next = part;
11455                 last = part;
11456             }
11457             child = child->next;
11458         }
11459         if (child != NULL) {
11460             xmlSchemaPContentErr(ctxt,
11461                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11462                 NULL, node, child, NULL,
11463                 "(annotation?, (element | group | choice | sequence | any)*)");
11464         }
11465     }
11466     if ((max == 0) && (min == 0))
11467         return (NULL);
11468     if (hasRefs) {
11469         /*
11470         * We need to resolve references.
11471         */
11472         WXS_ADD_PENDING(ctxt, item);
11473     }
11474     if (withParticle)
11475         return ((xmlSchemaTreeItemPtr) particle);
11476     else
11477         return ((xmlSchemaTreeItemPtr) item);
11478 }
11479
11480 /**
11481  * xmlSchemaParseRestriction:
11482  * @ctxt:  a schema validation context
11483  * @schema:  the schema being built
11484  * @node:  a subtree containing XML Schema informations
11485  *
11486  * parse a XML schema Restriction definition
11487  * *WARNING* this interface is highly subject to change
11488  *
11489  * Returns the type definition or NULL in case of error
11490  */
11491 static xmlSchemaTypePtr
11492 xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11493                           xmlNodePtr node, xmlSchemaTypeType parentType)
11494 {
11495     xmlSchemaTypePtr type;
11496     xmlNodePtr child = NULL;
11497     xmlAttrPtr attr;
11498
11499     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11500         return (NULL);
11501     /* Not a component, don't create it. */
11502     type = ctxt->ctxtType;
11503     type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
11504
11505     /*
11506     * Check for illegal attributes.
11507     */
11508     attr = node->properties;
11509     while (attr != NULL) {
11510         if (attr->ns == NULL) {
11511             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11512                 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11513                 xmlSchemaPIllegalAttrErr(ctxt,
11514                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11515             }
11516         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11517             xmlSchemaPIllegalAttrErr(ctxt,
11518                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11519         }
11520         attr = attr->next;
11521     }
11522     /*
11523     * Extract and validate attributes.
11524     */
11525     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11526     /*
11527     * Attribute
11528     */
11529     /*
11530     * Extract the base type. The "base" attribute is mandatory if inside
11531     * a complex type or if redefining.
11532     *
11533     * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
11534     * among its [children]), the simple type definition which is
11535     * the {content type} of the type definition `resolved` to by
11536     * the `actual value` of the base [attribute]"
11537     */
11538     if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
11539         &(type->baseNs), &(type->base)) == 0)
11540     {
11541         if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11542             xmlSchemaPMissingAttrErr(ctxt,
11543                 XML_SCHEMAP_S4S_ATTR_MISSING,
11544                 NULL, node, "base", NULL);
11545         } else if ((ctxt->isRedefine) &&
11546             (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11547         {
11548             if (type->base == NULL) {
11549                 xmlSchemaPMissingAttrErr(ctxt,
11550                     XML_SCHEMAP_S4S_ATTR_MISSING,
11551                     NULL, node, "base", NULL);
11552             } else if ((! xmlStrEqual(type->base, type->name)) ||
11553                 (! xmlStrEqual(type->baseNs, type->targetNamespace)))
11554             {
11555                 xmlChar *str1 = NULL, *str2 = NULL;
11556                 /*
11557                 * REDEFINE: SPEC src-redefine (5)
11558                 * "Within the [children], each <simpleType> must have a
11559                 * <restriction> among its [children] ... the `actual value` of
11560                 * whose base [attribute] must be the same as the `actual value`
11561                 * of its own name attribute plus target namespace;"
11562                 */
11563                 xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
11564                     NULL, node, "This is a redefinition, but the QName "
11565                     "value '%s' of the 'base' attribute does not match the "
11566                     "type's designation '%s'",
11567                     xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11568                     xmlSchemaFormatQName(&str2, type->targetNamespace,
11569                         type->name), NULL);
11570                 FREE_AND_NULL(str1);
11571                 FREE_AND_NULL(str2);
11572                 /* Avoid confusion and erase the values. */
11573                 type->base = NULL;
11574                 type->baseNs = NULL;
11575             }
11576         }
11577     }
11578     /*
11579     * And now for the children...
11580     */
11581     child = node->children;
11582     if (IS_SCHEMA(child, "annotation")) {
11583         /*
11584         * Add the annotation to the simple type ancestor.
11585         */
11586         xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11587             xmlSchemaParseAnnotation(ctxt, child, 1));
11588         child = child->next;
11589     }
11590     if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11591         /*
11592         * Corresponds to <simpleType><restriction><simpleType>.
11593         */
11594         if (IS_SCHEMA(child, "simpleType")) {
11595             if (type->base != NULL) {
11596                 /*
11597                 * src-restriction-base-or-simpleType
11598                 * Either the base [attribute] or the simpleType [child] of the
11599                 * <restriction> element must be present, but not both.
11600                 */
11601                 xmlSchemaPContentErr(ctxt,
11602                     XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11603                     NULL, node, child,
11604                     "The attribute 'base' and the <simpleType> child are "
11605                     "mutually exclusive", NULL);
11606             } else {
11607                 type->baseType = (xmlSchemaTypePtr)
11608                     xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11609             }
11610             child = child->next;
11611         } else if (type->base == NULL) {
11612             xmlSchemaPContentErr(ctxt,
11613                 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11614                 NULL, node, child,
11615                 "Either the attribute 'base' or a <simpleType> child "
11616                 "must be present", NULL);
11617         }
11618     } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11619         /*
11620         * Corresponds to <complexType><complexContent><restriction>...
11621         * followed by:
11622         *
11623         * Model groups <all>, <choice> and <sequence>.
11624         */
11625         if (IS_SCHEMA(child, "all")) {
11626             type->subtypes = (xmlSchemaTypePtr)
11627                 xmlSchemaParseModelGroup(ctxt, schema, child,
11628                     XML_SCHEMA_TYPE_ALL, 1);
11629             child = child->next;
11630         } else if (IS_SCHEMA(child, "choice")) {
11631             type->subtypes = (xmlSchemaTypePtr)
11632                 xmlSchemaParseModelGroup(ctxt,
11633                     schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11634             child = child->next;
11635         } else if (IS_SCHEMA(child, "sequence")) {
11636             type->subtypes = (xmlSchemaTypePtr)
11637                 xmlSchemaParseModelGroup(ctxt, schema, child,
11638                     XML_SCHEMA_TYPE_SEQUENCE, 1);
11639             child = child->next;
11640         /*
11641         * Model group reference <group>.
11642         */
11643         } else if (IS_SCHEMA(child, "group")) {
11644             type->subtypes = (xmlSchemaTypePtr)
11645                 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11646             /*
11647             * Note that the reference will be resolved in
11648             * xmlSchemaResolveTypeReferences();
11649             */
11650             child = child->next;
11651         }
11652     } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11653         /*
11654         * Corresponds to <complexType><simpleContent><restriction>...
11655         *
11656         * "1.1 the simple type definition corresponding to the <simpleType>
11657         * among the [children] of <restriction> if there is one;"
11658         */
11659         if (IS_SCHEMA(child, "simpleType")) {
11660             /*
11661             * We will store the to-be-restricted simple type in
11662             * type->contentTypeDef *temporarily*.
11663             */
11664             type->contentTypeDef = (xmlSchemaTypePtr)
11665                 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11666             if ( type->contentTypeDef == NULL)
11667                 return (NULL);
11668             child = child->next;
11669         }
11670     }
11671
11672     if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
11673         (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
11674         xmlSchemaFacetPtr facet, lastfacet = NULL;
11675         /*
11676         * Corresponds to <complexType><simpleContent><restriction>...
11677         * <simpleType><restriction>...
11678         */
11679
11680         /*
11681         * Add the facets to the simple type ancestor.
11682         */
11683         /*
11684         * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11685         * Simple Type Definition Schema Representation Constraint:
11686         * *Single Facet Value*
11687         */
11688         while ((IS_SCHEMA(child, "minInclusive")) ||
11689             (IS_SCHEMA(child, "minExclusive")) ||
11690             (IS_SCHEMA(child, "maxInclusive")) ||
11691             (IS_SCHEMA(child, "maxExclusive")) ||
11692             (IS_SCHEMA(child, "totalDigits")) ||
11693             (IS_SCHEMA(child, "fractionDigits")) ||
11694             (IS_SCHEMA(child, "pattern")) ||
11695             (IS_SCHEMA(child, "enumeration")) ||
11696             (IS_SCHEMA(child, "whiteSpace")) ||
11697             (IS_SCHEMA(child, "length")) ||
11698             (IS_SCHEMA(child, "maxLength")) ||
11699             (IS_SCHEMA(child, "minLength"))) {
11700             facet = xmlSchemaParseFacet(ctxt, schema, child);
11701             if (facet != NULL) {
11702                 if (lastfacet == NULL)
11703                     type->facets = facet;
11704                 else
11705                     lastfacet->next = facet;
11706                 lastfacet = facet;
11707                 lastfacet->next = NULL;
11708             }
11709             child = child->next;
11710         }
11711         /*
11712         * Create links for derivation and validation.
11713         */
11714         if (type->facets != NULL) {
11715             xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11716
11717             facet = type->facets;
11718             do {
11719                 facetLink = (xmlSchemaFacetLinkPtr)
11720                     xmlMalloc(sizeof(xmlSchemaFacetLink));
11721                 if (facetLink == NULL) {
11722                     xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
11723                     xmlFree(facetLink);
11724                     return (NULL);
11725                 }
11726                 facetLink->facet = facet;
11727                 facetLink->next = NULL;
11728                 if (lastFacetLink == NULL)
11729                     type->facetSet = facetLink;
11730                 else
11731                     lastFacetLink->next = facetLink;
11732                 lastFacetLink = facetLink;
11733                 facet = facet->next;
11734             } while (facet != NULL);
11735         }
11736     }
11737     if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11738         /*
11739         * Attribute uses/declarations.
11740         */
11741         if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11742             (xmlSchemaItemListPtr *) &(type->attrUses),
11743             XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11744             return(NULL);
11745         /*
11746         * Attribute wildcard.
11747         */
11748         if (IS_SCHEMA(child, "anyAttribute")) {
11749             type->attributeWildcard =
11750                 xmlSchemaParseAnyAttribute(ctxt, schema, child);
11751             child = child->next;
11752         }
11753     }
11754     if (child != NULL) {
11755         if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11756             xmlSchemaPContentErr(ctxt,
11757                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11758                 NULL, node, child, NULL,
11759                 "annotation?, (group | all | choice | sequence)?, "
11760                 "((attribute | attributeGroup)*, anyAttribute?))");
11761         } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11762              xmlSchemaPContentErr(ctxt,
11763                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11764                 NULL, node, child, NULL,
11765                 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11766                 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11767                 "length | minLength | maxLength | enumeration | whiteSpace | "
11768                 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11769         } else {
11770             /* Simple type */
11771             xmlSchemaPContentErr(ctxt,
11772                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11773                 NULL, node, child, NULL,
11774                 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11775                 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11776                 "length | minLength | maxLength | enumeration | whiteSpace | "
11777                 "pattern)*))");
11778         }
11779     }
11780     return (NULL);
11781 }
11782
11783 /**
11784  * xmlSchemaParseExtension:
11785  * @ctxt:  a schema validation context
11786  * @schema:  the schema being built
11787  * @node:  a subtree containing XML Schema informations
11788  *
11789  * Parses an <extension>, which is found inside a
11790  * <simpleContent> or <complexContent>.
11791  * *WARNING* this interface is highly subject to change.
11792  *
11793  * TODO: Returns the type definition or NULL in case of error
11794  */
11795 static xmlSchemaTypePtr
11796 xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11797                         xmlNodePtr node, xmlSchemaTypeType parentType)
11798 {
11799     xmlSchemaTypePtr type;
11800     xmlNodePtr child = NULL;
11801     xmlAttrPtr attr;
11802
11803     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11804         return (NULL);
11805     /* Not a component, don't create it. */
11806     type = ctxt->ctxtType;
11807     type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
11808
11809     /*
11810     * Check for illegal attributes.
11811     */
11812     attr = node->properties;
11813     while (attr != NULL) {
11814         if (attr->ns == NULL) {
11815             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11816                 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11817                 xmlSchemaPIllegalAttrErr(ctxt,
11818                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11819             }
11820         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11821             xmlSchemaPIllegalAttrErr(ctxt,
11822                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11823         }
11824         attr = attr->next;
11825     }
11826
11827     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11828
11829     /*
11830     * Attribute "base" - mandatory.
11831     */
11832     if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11833         "base", &(type->baseNs), &(type->base)) == 0) &&
11834         (type->base == NULL)) {
11835         xmlSchemaPMissingAttrErr(ctxt,
11836             XML_SCHEMAP_S4S_ATTR_MISSING,
11837             NULL, node, "base", NULL);
11838     }
11839     /*
11840     * And now for the children...
11841     */
11842     child = node->children;
11843     if (IS_SCHEMA(child, "annotation")) {
11844         /*
11845         * Add the annotation to the type ancestor.
11846         */
11847         xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11848             xmlSchemaParseAnnotation(ctxt, child, 1));
11849         child = child->next;
11850     }
11851     if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11852         /*
11853         * Corresponds to <complexType><complexContent><extension>... and:
11854         *
11855         * Model groups <all>, <choice>, <sequence> and <group>.
11856         */
11857         if (IS_SCHEMA(child, "all")) {
11858             type->subtypes = (xmlSchemaTypePtr)
11859                 xmlSchemaParseModelGroup(ctxt, schema,
11860                     child, XML_SCHEMA_TYPE_ALL, 1);
11861             child = child->next;
11862         } else if (IS_SCHEMA(child, "choice")) {
11863             type->subtypes = (xmlSchemaTypePtr)
11864                 xmlSchemaParseModelGroup(ctxt, schema,
11865                     child, XML_SCHEMA_TYPE_CHOICE, 1);
11866             child = child->next;
11867         } else if (IS_SCHEMA(child, "sequence")) {
11868             type->subtypes = (xmlSchemaTypePtr)
11869                 xmlSchemaParseModelGroup(ctxt, schema,
11870                 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11871             child = child->next;
11872         } else if (IS_SCHEMA(child, "group")) {
11873             type->subtypes = (xmlSchemaTypePtr)
11874                 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11875             /*
11876             * Note that the reference will be resolved in
11877             * xmlSchemaResolveTypeReferences();
11878             */
11879             child = child->next;
11880         }
11881     }
11882     if (child != NULL) {
11883         /*
11884         * Attribute uses/declarations.
11885         */
11886         if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11887             (xmlSchemaItemListPtr *) &(type->attrUses),
11888             XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11889             return(NULL);
11890         /*
11891         * Attribute wildcard.
11892         */
11893         if (IS_SCHEMA(child, "anyAttribute")) {
11894             ctxt->ctxtType->attributeWildcard =
11895                 xmlSchemaParseAnyAttribute(ctxt, schema, child);
11896             child = child->next;
11897         }
11898     }
11899     if (child != NULL) {
11900         if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11901             /* Complex content extension. */
11902             xmlSchemaPContentErr(ctxt,
11903                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11904                 NULL, node, child, NULL,
11905                 "(annotation?, ((group | all | choice | sequence)?, "
11906                 "((attribute | attributeGroup)*, anyAttribute?)))");
11907         } else {
11908             /* Simple content extension. */
11909             xmlSchemaPContentErr(ctxt,
11910                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11911                 NULL, node, child, NULL,
11912                 "(annotation?, ((attribute | attributeGroup)*, "
11913                 "anyAttribute?))");
11914         }
11915     }
11916     return (NULL);
11917 }
11918
11919 /**
11920  * xmlSchemaParseSimpleContent:
11921  * @ctxt:  a schema validation context
11922  * @schema:  the schema being built
11923  * @node:  a subtree containing XML Schema informations
11924  *
11925  * parse a XML schema SimpleContent definition
11926  * *WARNING* this interface is highly subject to change
11927  *
11928  * Returns the type definition or NULL in case of error
11929  */
11930 static int
11931 xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
11932                             xmlSchemaPtr schema, xmlNodePtr node,
11933                             int *hasRestrictionOrExtension)
11934 {
11935     xmlSchemaTypePtr type;
11936     xmlNodePtr child = NULL;
11937     xmlAttrPtr attr;
11938
11939     if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11940         (hasRestrictionOrExtension == NULL))
11941         return (-1);
11942     *hasRestrictionOrExtension = 0;
11943     /* Not a component, don't create it. */
11944     type = ctxt->ctxtType;
11945     type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11946     /*
11947     * Check for illegal attributes.
11948     */
11949     attr = node->properties;
11950     while (attr != NULL) {
11951         if (attr->ns == NULL) {
11952             if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
11953                 xmlSchemaPIllegalAttrErr(ctxt,
11954                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11955             }
11956         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11957             xmlSchemaPIllegalAttrErr(ctxt,
11958                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11959         }
11960         attr = attr->next;
11961     }
11962
11963     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11964
11965     /*
11966     * And now for the children...
11967     */
11968     child = node->children;
11969     if (IS_SCHEMA(child, "annotation")) {
11970         /*
11971         * Add the annotation to the complex type ancestor.
11972         */
11973         xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11974             xmlSchemaParseAnnotation(ctxt, child, 1));
11975         child = child->next;
11976     }
11977     if (child == NULL) {
11978         xmlSchemaPContentErr(ctxt,
11979             XML_SCHEMAP_S4S_ELEM_MISSING,
11980             NULL, node, NULL, NULL,
11981             "(annotation?, (restriction | extension))");
11982     }
11983     if (child == NULL) {
11984         xmlSchemaPContentErr(ctxt,
11985             XML_SCHEMAP_S4S_ELEM_MISSING,
11986             NULL, node, NULL, NULL,
11987             "(annotation?, (restriction | extension))");
11988     }
11989     if (IS_SCHEMA(child, "restriction")) {
11990         xmlSchemaParseRestriction(ctxt, schema, child,
11991             XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11992         (*hasRestrictionOrExtension) = 1;
11993         child = child->next;
11994     } else if (IS_SCHEMA(child, "extension")) {
11995         xmlSchemaParseExtension(ctxt, schema, child,
11996             XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11997         (*hasRestrictionOrExtension) = 1;
11998         child = child->next;
11999     }
12000     if (child != NULL) {
12001         xmlSchemaPContentErr(ctxt,
12002             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12003             NULL, node, child, NULL,
12004             "(annotation?, (restriction | extension))");
12005     }
12006     return (0);
12007 }
12008
12009 /**
12010  * xmlSchemaParseComplexContent:
12011  * @ctxt:  a schema validation context
12012  * @schema:  the schema being built
12013  * @node:  a subtree containing XML Schema informations
12014  *
12015  * parse a XML schema ComplexContent definition
12016  * *WARNING* this interface is highly subject to change
12017  *
12018  * Returns the type definition or NULL in case of error
12019  */
12020 static int
12021 xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
12022                              xmlSchemaPtr schema, xmlNodePtr node,
12023                              int *hasRestrictionOrExtension)
12024 {
12025     xmlSchemaTypePtr type;
12026     xmlNodePtr child = NULL;
12027     xmlAttrPtr attr;
12028
12029     if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
12030         (hasRestrictionOrExtension == NULL))
12031         return (-1);
12032     *hasRestrictionOrExtension = 0;
12033     /* Not a component, don't create it. */
12034     type = ctxt->ctxtType;
12035     /*
12036     * Check for illegal attributes.
12037     */
12038     attr = node->properties;
12039     while (attr != NULL) {
12040         if (attr->ns == NULL) {
12041             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
12042                 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
12043             {
12044                 xmlSchemaPIllegalAttrErr(ctxt,
12045                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12046             }
12047         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12048             xmlSchemaPIllegalAttrErr(ctxt,
12049                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12050         }
12051         attr = attr->next;
12052     }
12053
12054     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12055
12056     /*
12057     * Set the 'mixed' on the complex type ancestor.
12058     */
12059     if (xmlGetBooleanProp(ctxt, node, "mixed", 0))  {
12060         if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
12061             type->flags |= XML_SCHEMAS_TYPE_MIXED;
12062     }
12063     child = node->children;
12064     if (IS_SCHEMA(child, "annotation")) {
12065         /*
12066         * Add the annotation to the complex type ancestor.
12067         */
12068         xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12069             xmlSchemaParseAnnotation(ctxt, child, 1));
12070         child = child->next;
12071     }
12072     if (child == NULL) {
12073         xmlSchemaPContentErr(ctxt,
12074             XML_SCHEMAP_S4S_ELEM_MISSING,
12075             NULL, node, NULL,
12076             NULL, "(annotation?, (restriction | extension))");
12077     }
12078     if (child == NULL) {
12079         xmlSchemaPContentErr(ctxt,
12080             XML_SCHEMAP_S4S_ELEM_MISSING,
12081             NULL, node, NULL,
12082             NULL, "(annotation?, (restriction | extension))");
12083     }
12084     if (IS_SCHEMA(child, "restriction")) {
12085         xmlSchemaParseRestriction(ctxt, schema, child,
12086             XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12087         (*hasRestrictionOrExtension) = 1;
12088         child = child->next;
12089     } else if (IS_SCHEMA(child, "extension")) {
12090         xmlSchemaParseExtension(ctxt, schema, child,
12091             XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12092         (*hasRestrictionOrExtension) = 1;
12093         child = child->next;
12094     }
12095     if (child != NULL) {
12096         xmlSchemaPContentErr(ctxt,
12097             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12098             NULL, node, child,
12099             NULL, "(annotation?, (restriction | extension))");
12100     }
12101     return (0);
12102 }
12103
12104 /**
12105  * xmlSchemaParseComplexType:
12106  * @ctxt:  a schema validation context
12107  * @schema:  the schema being built
12108  * @node:  a subtree containing XML Schema informations
12109  *
12110  * parse a XML schema Complex Type definition
12111  * *WARNING* this interface is highly subject to change
12112  *
12113  * Returns the type definition or NULL in case of error
12114  */
12115 static xmlSchemaTypePtr
12116 xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
12117                           xmlNodePtr node, int topLevel)
12118 {
12119     xmlSchemaTypePtr type, ctxtType;
12120     xmlNodePtr child = NULL;
12121     const xmlChar *name = NULL;
12122     xmlAttrPtr attr;
12123     const xmlChar *attrValue;
12124 #ifdef ENABLE_NAMED_LOCALS
12125     char buf[40];
12126 #endif
12127     int final = 0, block = 0, hasRestrictionOrExtension = 0;
12128
12129
12130     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12131         return (NULL);
12132
12133     ctxtType = ctxt->ctxtType;
12134
12135     if (topLevel) {
12136         attr = xmlSchemaGetPropNode(node, "name");
12137         if (attr == NULL) {
12138             xmlSchemaPMissingAttrErr(ctxt,
12139                 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
12140             return (NULL);
12141         } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
12142             xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12143             return (NULL);
12144         }
12145     }
12146
12147     if (topLevel == 0) {
12148         /*
12149         * Parse as local complex type definition.
12150         */
12151 #ifdef ENABLE_NAMED_LOCALS
12152         snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
12153         type = xmlSchemaAddType(ctxt, schema,
12154             XML_SCHEMA_TYPE_COMPLEX,
12155             xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
12156             ctxt->targetNamespace, node, 0);
12157 #else
12158         type = xmlSchemaAddType(ctxt, schema,
12159             XML_SCHEMA_TYPE_COMPLEX,
12160             NULL, ctxt->targetNamespace, node, 0);
12161 #endif
12162         if (type == NULL)
12163             return (NULL);
12164         name = type->name;
12165         type->node = node;
12166         type->type = XML_SCHEMA_TYPE_COMPLEX;
12167         /*
12168         * TODO: We need the target namespace.
12169         */
12170     } else {
12171         /*
12172         * Parse as global complex type definition.
12173         */
12174         type = xmlSchemaAddType(ctxt, schema,
12175             XML_SCHEMA_TYPE_COMPLEX,
12176             name, ctxt->targetNamespace, node, 1);
12177         if (type == NULL)
12178             return (NULL);
12179         type->node = node;
12180         type->type = XML_SCHEMA_TYPE_COMPLEX;
12181         type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
12182     }
12183     type->targetNamespace = ctxt->targetNamespace;
12184     /*
12185     * Handle attributes.
12186     */
12187     attr = node->properties;
12188     while (attr != NULL) {
12189         if (attr->ns == NULL) {
12190             if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12191                 /*
12192                 * Attribute "id".
12193                 */
12194                 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12195             } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12196                 /*
12197                 * Attribute "mixed".
12198                 */
12199                 if (xmlSchemaPGetBoolNodeValue(ctxt,
12200                         NULL, (xmlNodePtr) attr))
12201                     type->flags |= XML_SCHEMAS_TYPE_MIXED;
12202             } else if (topLevel) {
12203                 /*
12204                 * Attributes of global complex type definitions.
12205                 */
12206                 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12207                     /* Pass. */
12208                 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12209                     /*
12210                     * Attribute "abstract".
12211                     */
12212                     if (xmlSchemaPGetBoolNodeValue(ctxt,
12213                             NULL, (xmlNodePtr) attr))
12214                         type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12215                 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12216                     /*
12217                     * Attribute "final".
12218                     */
12219                     attrValue = xmlSchemaGetNodeContent(ctxt,
12220                         (xmlNodePtr) attr);
12221                     if (xmlSchemaPValAttrBlockFinal(attrValue,
12222                         &(type->flags),
12223                         -1,
12224                         XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12225                         XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12226                         -1, -1, -1) != 0)
12227                     {
12228                         xmlSchemaPSimpleTypeErr(ctxt,
12229                             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12230                             NULL, (xmlNodePtr) attr, NULL,
12231                             "(#all | List of (extension | restriction))",
12232                             attrValue, NULL, NULL, NULL);
12233                     } else
12234                         final = 1;
12235                 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12236                     /*
12237                     * Attribute "block".
12238                     */
12239                     attrValue = xmlSchemaGetNodeContent(ctxt,
12240                         (xmlNodePtr) attr);
12241                     if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
12242                         -1,
12243                         XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
12244                         XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
12245                         -1, -1, -1) != 0) {
12246                         xmlSchemaPSimpleTypeErr(ctxt,
12247                             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12248                             NULL, (xmlNodePtr) attr, NULL,
12249                             "(#all | List of (extension | restriction)) ",
12250                             attrValue, NULL, NULL, NULL);
12251                     } else
12252                         block = 1;
12253                 } else {
12254                         xmlSchemaPIllegalAttrErr(ctxt,
12255                             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12256                 }
12257             } else {
12258                 xmlSchemaPIllegalAttrErr(ctxt,
12259                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12260             }
12261         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12262             xmlSchemaPIllegalAttrErr(ctxt,
12263                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12264         }
12265         attr = attr->next;
12266     }
12267     if (! block) {
12268         /*
12269         * Apply default "block" values.
12270         */
12271         if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12272             type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12273         if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12274             type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12275     }
12276     if (! final) {
12277         /*
12278         * Apply default "block" values.
12279         */
12280         if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12281             type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12282         if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12283             type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12284     }
12285     /*
12286     * And now for the children...
12287     */
12288     child = node->children;
12289     if (IS_SCHEMA(child, "annotation")) {
12290         type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
12291         child = child->next;
12292     }
12293     ctxt->ctxtType = type;
12294     if (IS_SCHEMA(child, "simpleContent")) {
12295         /*
12296         * <complexType><simpleContent>...
12297         * 3.4.3 : 2.2
12298         * Specifying mixed='true' when the <simpleContent>
12299         * alternative is chosen has no effect
12300         */
12301         if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12302             type->flags ^= XML_SCHEMAS_TYPE_MIXED;
12303         xmlSchemaParseSimpleContent(ctxt, schema, child,
12304             &hasRestrictionOrExtension);
12305         child = child->next;
12306     } else if (IS_SCHEMA(child, "complexContent")) {
12307         /*
12308         * <complexType><complexContent>...
12309         */
12310         type->contentType = XML_SCHEMA_CONTENT_EMPTY;
12311         xmlSchemaParseComplexContent(ctxt, schema, child,
12312             &hasRestrictionOrExtension);
12313         child = child->next;
12314     } else {
12315         /*
12316         * E.g <complexType><sequence>... or <complexType><attribute>... etc.
12317         *
12318         * SPEC
12319         * "...the third alternative (neither <simpleContent> nor
12320         * <complexContent>) is chosen. This case is understood as shorthand
12321         * for complex content restricting the `ur-type definition`, and the
12322         * details of the mappings should be modified as necessary.
12323         */
12324         type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12325         type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
12326         /*
12327         * Parse model groups.
12328         */
12329         if (IS_SCHEMA(child, "all")) {
12330             type->subtypes = (xmlSchemaTypePtr)
12331                 xmlSchemaParseModelGroup(ctxt, schema, child,
12332                     XML_SCHEMA_TYPE_ALL, 1);
12333             child = child->next;
12334         } else if (IS_SCHEMA(child, "choice")) {
12335             type->subtypes = (xmlSchemaTypePtr)
12336                 xmlSchemaParseModelGroup(ctxt, schema, child,
12337                     XML_SCHEMA_TYPE_CHOICE, 1);
12338             child = child->next;
12339         } else if (IS_SCHEMA(child, "sequence")) {
12340             type->subtypes = (xmlSchemaTypePtr)
12341                 xmlSchemaParseModelGroup(ctxt, schema, child,
12342                     XML_SCHEMA_TYPE_SEQUENCE, 1);
12343             child = child->next;
12344         } else if (IS_SCHEMA(child, "group")) {
12345             type->subtypes = (xmlSchemaTypePtr)
12346                 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
12347             /*
12348             * Note that the reference will be resolved in
12349             * xmlSchemaResolveTypeReferences();
12350             */
12351             child = child->next;
12352         }
12353         /*
12354         * Parse attribute decls/refs.
12355         */
12356         if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12357             (xmlSchemaItemListPtr *) &(type->attrUses),
12358             XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12359             return(NULL);
12360         /*
12361         * Parse attribute wildcard.
12362         */
12363         if (IS_SCHEMA(child, "anyAttribute")) {
12364             type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12365             child = child->next;
12366         }
12367     }
12368     if (child != NULL) {
12369         xmlSchemaPContentErr(ctxt,
12370             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12371             NULL, node, child,
12372             NULL, "(annotation?, (simpleContent | complexContent | "
12373             "((group | all | choice | sequence)?, ((attribute | "
12374             "attributeGroup)*, anyAttribute?))))");
12375     }
12376     /*
12377     * REDEFINE: SPEC src-redefine (5)
12378     */
12379     if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12380         xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
12381             NULL, node, "This is a redefinition, thus the "
12382             "<complexType> must have a <restriction> or <extension> "
12383             "grand-child", NULL);
12384     }
12385     ctxt->ctxtType = ctxtType;
12386     return (type);
12387 }
12388
12389 /************************************************************************
12390  *                                                                      *
12391  *                      Validating using Schemas                        *
12392  *                                                                      *
12393  ************************************************************************/
12394
12395 /************************************************************************
12396  *                                                                      *
12397  *                      Reading/Writing Schemas                         *
12398  *                                                                      *
12399  ************************************************************************/
12400
12401 #if 0 /* Will be enabled if it is clear what options are needed. */
12402 /**
12403  * xmlSchemaParserCtxtSetOptions:
12404  * @ctxt:       a schema parser context
12405  * @options: a combination of xmlSchemaParserOption
12406  *
12407  * Sets the options to be used during the parse.
12408  *
12409  * Returns 0 in case of success, -1 in case of an
12410  * API error.
12411  */
12412 static int
12413 xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12414                               int options)
12415
12416 {
12417     int i;
12418
12419     if (ctxt == NULL)
12420         return (-1);
12421     /*
12422     * WARNING: Change the start value if adding to the
12423     * xmlSchemaParseOption.
12424     */
12425     for (i = 1; i < (int) sizeof(int) * 8; i++) {
12426         if (options & 1<<i) {
12427             return (-1);
12428         }
12429     }
12430     ctxt->options = options;
12431     return (0);
12432 }
12433
12434 /**
12435  * xmlSchemaValidCtxtGetOptions:
12436  * @ctxt: a schema parser context
12437  *
12438  * Returns the option combination of the parser context.
12439  */
12440 static int
12441 xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
12442
12443 {
12444     if (ctxt == NULL)
12445         return (-1);
12446     else
12447         return (ctxt->options);
12448 }
12449 #endif
12450
12451 /**
12452  * xmlSchemaNewParserCtxt:
12453  * @URL:  the location of the schema
12454  *
12455  * Create an XML Schemas parse context for that file/resource expected
12456  * to contain an XML Schemas file.
12457  *
12458  * Returns the parser context or NULL in case of error
12459  */
12460 xmlSchemaParserCtxtPtr
12461 xmlSchemaNewParserCtxt(const char *URL)
12462 {
12463     xmlSchemaParserCtxtPtr ret;
12464
12465     if (URL == NULL)
12466         return (NULL);
12467
12468     ret = xmlSchemaParserCtxtCreate();
12469     if (ret == NULL)
12470         return(NULL);
12471     ret->dict = xmlDictCreate();
12472     ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
12473     return (ret);
12474 }
12475
12476 /**
12477  * xmlSchemaNewMemParserCtxt:
12478  * @buffer:  a pointer to a char array containing the schemas
12479  * @size:  the size of the array
12480  *
12481  * Create an XML Schemas parse context for that memory buffer expected
12482  * to contain an XML Schemas file.
12483  *
12484  * Returns the parser context or NULL in case of error
12485  */
12486 xmlSchemaParserCtxtPtr
12487 xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12488 {
12489     xmlSchemaParserCtxtPtr ret;
12490
12491     if ((buffer == NULL) || (size <= 0))
12492         return (NULL);
12493     ret = xmlSchemaParserCtxtCreate();
12494     if (ret == NULL)
12495         return(NULL);
12496     ret->buffer = buffer;
12497     ret->size = size;
12498     ret->dict = xmlDictCreate();
12499     return (ret);
12500 }
12501
12502 /**
12503  * xmlSchemaNewDocParserCtxt:
12504  * @doc:  a preparsed document tree
12505  *
12506  * Create an XML Schemas parse context for that document.
12507  * NB. The document may be modified during the parsing process.
12508  *
12509  * Returns the parser context or NULL in case of error
12510  */
12511 xmlSchemaParserCtxtPtr
12512 xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12513 {
12514     xmlSchemaParserCtxtPtr ret;
12515
12516     if (doc == NULL)
12517       return (NULL);
12518     ret = xmlSchemaParserCtxtCreate();
12519     if (ret == NULL)
12520         return(NULL);
12521     ret->doc = doc;
12522     ret->dict = xmlDictCreate();
12523     /* The application has responsibility for the document */
12524     ret->preserve = 1;
12525
12526     return (ret);
12527 }
12528
12529 /**
12530  * xmlSchemaFreeParserCtxt:
12531  * @ctxt:  the schema parser context
12532  *
12533  * Free the resources associated to the schema parser context
12534  */
12535 void
12536 xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12537 {
12538     if (ctxt == NULL)
12539         return;
12540     if (ctxt->doc != NULL && !ctxt->preserve)
12541         xmlFreeDoc(ctxt->doc);
12542     if (ctxt->vctxt != NULL) {
12543         xmlSchemaFreeValidCtxt(ctxt->vctxt);
12544     }
12545     if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12546         xmlSchemaConstructionCtxtFree(ctxt->constructor);
12547         ctxt->constructor = NULL;
12548         ctxt->ownsConstructor = 0;
12549     }
12550     if (ctxt->attrProhibs != NULL)
12551         xmlSchemaItemListFree(ctxt->attrProhibs);
12552     xmlDictFree(ctxt->dict);
12553     xmlFree(ctxt);
12554 }
12555
12556 /************************************************************************
12557  *                                                                      *
12558  *                      Building the content models                     *
12559  *                                                                      *
12560  ************************************************************************/
12561
12562 /**
12563  * xmlSchemaBuildContentModelForSubstGroup:
12564  *
12565  * Returns 1 if nillable, 0 otherwise
12566  */
12567 static int
12568 xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
12569         xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
12570 {
12571     xmlAutomataStatePtr start, tmp;
12572     xmlSchemaElementPtr elemDecl, member;
12573     xmlSchemaSubstGroupPtr substGroup;
12574     int i;
12575     int ret = 0;
12576
12577     elemDecl = (xmlSchemaElementPtr) particle->children;
12578     /*
12579     * Wrap the substitution group with a CHOICE.
12580     */
12581     start = pctxt->state;
12582     if (end == NULL)
12583         end = xmlAutomataNewState(pctxt->am);
12584     substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
12585     if (substGroup == NULL) {
12586         xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
12587             XML_SCHEMAP_INTERNAL,
12588             "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12589             "declaration is marked having a subst. group but none "
12590             "available.\n", elemDecl->name, NULL);
12591         return(0);
12592     }
12593     if (counter >= 0) {
12594         /*
12595         * NOTE that we put the declaration in, even if it's abstract.
12596         * However, an error will be raised during *validation* if an element
12597         * information item shall be validated against an abstract element
12598         * declaration.
12599         */
12600         tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12601         xmlAutomataNewTransition2(pctxt->am, tmp, end,
12602                     elemDecl->name, elemDecl->targetNamespace, elemDecl);
12603         /*
12604         * Add subst. group members.
12605         */
12606         for (i = 0; i < substGroup->members->nbItems; i++) {
12607             member = (xmlSchemaElementPtr) substGroup->members->items[i];
12608             xmlAutomataNewTransition2(pctxt->am, tmp, end,
12609                                member->name, member->targetNamespace, member);
12610         }
12611     } else if (particle->maxOccurs == 1) {
12612         /*
12613         * NOTE that we put the declaration in, even if it's abstract,
12614         */
12615         xmlAutomataNewEpsilon(pctxt->am,
12616             xmlAutomataNewTransition2(pctxt->am,
12617             start, NULL,
12618             elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12619         /*
12620         * Add subst. group members.
12621         */
12622         for (i = 0; i < substGroup->members->nbItems; i++) {
12623             member = (xmlSchemaElementPtr) substGroup->members->items[i];
12624             /*
12625             * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2()
12626             *  was incorrectly used instead of xmlAutomataNewTransition2()
12627             *  (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL
12628             *  section in xmlSchemaBuildAContentModel() ).
12629             * TODO: Check if xmlAutomataNewOnceTrans2() was instead
12630             *  intended for the above "counter" section originally. I.e.,
12631             *  check xs:all with subst-groups.
12632             *
12633             * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12634             *                  member->name, member->targetNamespace,
12635             *                  1, 1, member);
12636             */
12637             tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL,
12638                 member->name, member->targetNamespace, member);
12639             xmlAutomataNewEpsilon(pctxt->am, tmp, end);
12640         }
12641     } else {
12642         xmlAutomataStatePtr hop;
12643         int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12644             UNBOUNDED : particle->maxOccurs - 1;
12645         int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12646
12647         counter =
12648             xmlAutomataNewCounter(pctxt->am, minOccurs,
12649             maxOccurs);
12650         hop = xmlAutomataNewState(pctxt->am);
12651
12652         xmlAutomataNewEpsilon(pctxt->am,
12653             xmlAutomataNewTransition2(pctxt->am,
12654             start, NULL,
12655             elemDecl->name, elemDecl->targetNamespace, elemDecl),
12656             hop);
12657         /*
12658          * Add subst. group members.
12659          */
12660         for (i = 0; i < substGroup->members->nbItems; i++) {
12661             member = (xmlSchemaElementPtr) substGroup->members->items[i];
12662             xmlAutomataNewEpsilon(pctxt->am,
12663                 xmlAutomataNewTransition2(pctxt->am,
12664                 start, NULL,
12665                 member->name, member->targetNamespace, member),
12666                 hop);
12667         }
12668         xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12669         xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12670     }
12671     if (particle->minOccurs == 0) {
12672         xmlAutomataNewEpsilon(pctxt->am, start, end);
12673         ret = 1;
12674     }
12675     pctxt->state = end;
12676     return(ret);
12677 }
12678
12679 /**
12680  * xmlSchemaBuildContentModelForElement:
12681  *
12682  * Returns 1 if nillable, 0 otherwise
12683  */
12684 static int
12685 xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12686                                      xmlSchemaParticlePtr particle)
12687 {
12688     int ret = 0;
12689
12690     if (((xmlSchemaElementPtr) particle->children)->flags &
12691         XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12692         /*
12693         * Substitution groups.
12694         */
12695         ret = xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
12696     } else {
12697         xmlSchemaElementPtr elemDecl;
12698         xmlAutomataStatePtr start;
12699
12700         elemDecl = (xmlSchemaElementPtr) particle->children;
12701
12702         if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
12703             return(0);
12704         if (particle->maxOccurs == 1) {
12705             start = ctxt->state;
12706             ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12707                     elemDecl->name, elemDecl->targetNamespace, elemDecl);
12708         } else if ((particle->maxOccurs >= UNBOUNDED) &&
12709                    (particle->minOccurs < 2)) {
12710             /* Special case. */
12711             start = ctxt->state;
12712             ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12713                 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12714             ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
12715                 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12716         } else {
12717             int counter;
12718             int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12719                             UNBOUNDED : particle->maxOccurs - 1;
12720             int minOccurs = particle->minOccurs < 1 ?
12721                             0 : particle->minOccurs - 1;
12722
12723             start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
12724             counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12725             ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12726                 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12727             xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12728             ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12729                 NULL, counter);
12730         }
12731         if (particle->minOccurs == 0) {
12732             xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12733             ret = 1;
12734         }
12735     }
12736     return(ret);
12737 }
12738
12739 /**
12740  * xmlSchemaBuildAContentModel:
12741  * @ctxt:  the schema parser context
12742  * @particle:  the particle component
12743  * @name:  the complex type's name whose content is being built
12744  *
12745  * Create the automaton for the {content type} of a complex type.
12746  *
12747  * Returns 1 if the content is nillable, 0 otherwise
12748  */
12749 static int
12750 xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
12751                             xmlSchemaParticlePtr particle)
12752 {
12753     int ret = 0, tmp2;
12754
12755     if (particle == NULL) {
12756         PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
12757         return(1);
12758     }
12759     if (particle->children == NULL) {
12760         /*
12761         * Just return in this case. A missing "term" of the particle
12762         * might arise due to an invalid "term" component.
12763         */
12764         return(1);
12765     }
12766
12767     switch (particle->children->type) {
12768         case XML_SCHEMA_TYPE_ANY: {
12769             xmlAutomataStatePtr start, end;
12770             xmlSchemaWildcardPtr wild;
12771             xmlSchemaWildcardNsPtr ns;
12772
12773             wild = (xmlSchemaWildcardPtr) particle->children;
12774
12775             start = pctxt->state;
12776             end = xmlAutomataNewState(pctxt->am);
12777
12778             if (particle->maxOccurs == 1) {
12779                 if (wild->any == 1) {
12780                     /*
12781                     * We need to add both transitions:
12782                     *
12783                     * 1. the {"*", "*"} for elements in a namespace.
12784                     */
12785                     pctxt->state =
12786                         xmlAutomataNewTransition2(pctxt->am,
12787                         start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12788                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12789                     /*
12790                     * 2. the {"*"} for elements in no namespace.
12791                     */
12792                     pctxt->state =
12793                         xmlAutomataNewTransition2(pctxt->am,
12794                         start, NULL, BAD_CAST "*", NULL, wild);
12795                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12796
12797                 } else if (wild->nsSet != NULL) {
12798                     ns = wild->nsSet;
12799                     do {
12800                         pctxt->state = start;
12801                         pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12802                             pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12803                         xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12804                         ns = ns->next;
12805                     } while (ns != NULL);
12806
12807                 } else if (wild->negNsSet != NULL) {
12808                     pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12809                         start, end, BAD_CAST "*", wild->negNsSet->value,
12810                         wild);
12811                 }
12812             } else {
12813                 int counter;
12814                 xmlAutomataStatePtr hop;
12815                 int maxOccurs =
12816                     particle->maxOccurs == UNBOUNDED ? UNBOUNDED :
12817                                            particle->maxOccurs - 1;
12818                 int minOccurs =
12819                     particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12820
12821                 counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12822                 hop = xmlAutomataNewState(pctxt->am);
12823                 if (wild->any == 1) {
12824                     pctxt->state =
12825                         xmlAutomataNewTransition2(pctxt->am,
12826                         start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12827                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12828                     pctxt->state =
12829                         xmlAutomataNewTransition2(pctxt->am,
12830                         start, NULL, BAD_CAST "*", NULL, wild);
12831                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12832                 } else if (wild->nsSet != NULL) {
12833                     ns = wild->nsSet;
12834                     do {
12835                         pctxt->state =
12836                             xmlAutomataNewTransition2(pctxt->am,
12837                                 start, NULL, BAD_CAST "*", ns->value, wild);
12838                         xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12839                         ns = ns->next;
12840                     } while (ns != NULL);
12841
12842                 } else if (wild->negNsSet != NULL) {
12843                     pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12844                         start, hop, BAD_CAST "*", wild->negNsSet->value,
12845                         wild);
12846                 }
12847                 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12848                 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12849             }
12850             if (particle->minOccurs == 0) {
12851                 xmlAutomataNewEpsilon(pctxt->am, start, end);
12852                 ret = 1;
12853             }
12854             pctxt->state = end;
12855             break;
12856         }
12857         case XML_SCHEMA_TYPE_ELEMENT:
12858             ret = xmlSchemaBuildContentModelForElement(pctxt, particle);
12859             break;
12860         case XML_SCHEMA_TYPE_SEQUENCE:{
12861             xmlSchemaTreeItemPtr sub;
12862
12863             ret = 1;
12864             /*
12865              * If max and min occurances are default (1) then
12866              * simply iterate over the particles of the <sequence>.
12867              */
12868             if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12869                 sub = particle->children->children;
12870
12871                 while (sub != NULL) {
12872                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
12873                                         (xmlSchemaParticlePtr) sub);
12874                     if (tmp2 != 1) ret = 0;
12875                     sub = sub->next;
12876                 }
12877             } else {
12878                 xmlAutomataStatePtr oldstate = pctxt->state;
12879
12880                 if (particle->maxOccurs >= UNBOUNDED) {
12881                     if (particle->minOccurs > 1) {
12882                         xmlAutomataStatePtr tmp;
12883                         int counter;
12884
12885                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12886                             oldstate, NULL);
12887                         oldstate = pctxt->state;
12888
12889                         counter = xmlAutomataNewCounter(pctxt->am,
12890                             particle->minOccurs - 1, UNBOUNDED);
12891
12892                         sub = particle->children->children;
12893                         while (sub != NULL) {
12894                             tmp2 = xmlSchemaBuildAContentModel(pctxt,
12895                                             (xmlSchemaParticlePtr) sub);
12896                             if (tmp2 != 1) ret = 0;
12897                             sub = sub->next;
12898                         }
12899                         tmp = pctxt->state;
12900                         xmlAutomataNewCountedTrans(pctxt->am, tmp,
12901                                                    oldstate, counter);
12902                         pctxt->state =
12903                             xmlAutomataNewCounterTrans(pctxt->am, tmp,
12904                                                        NULL, counter);
12905                         if (ret == 1)
12906                             xmlAutomataNewEpsilon(pctxt->am,
12907                                                 oldstate, pctxt->state);
12908
12909                     } else {
12910                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12911                             oldstate, NULL);
12912                         oldstate = pctxt->state;
12913
12914                         sub = particle->children->children;
12915                         while (sub != NULL) {
12916                             tmp2 = xmlSchemaBuildAContentModel(pctxt,
12917                                         (xmlSchemaParticlePtr) sub);
12918                             if (tmp2 != 1) ret = 0;
12919                             sub = sub->next;
12920                         }
12921                         xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
12922                                               oldstate);
12923                         /*
12924                          * epsilon needed to block previous trans from
12925                          * being allowed to enter back from another
12926                          * construct
12927                          */
12928                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12929                                             pctxt->state, NULL);
12930                         if (particle->minOccurs == 0) {
12931                             xmlAutomataNewEpsilon(pctxt->am,
12932                                 oldstate, pctxt->state);
12933                             ret = 1;
12934                         }
12935                     }
12936                 } else if ((particle->maxOccurs > 1)
12937                            || (particle->minOccurs > 1)) {
12938                     xmlAutomataStatePtr tmp;
12939                     int counter;
12940
12941                     pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12942                         oldstate, NULL);
12943                     oldstate = pctxt->state;
12944
12945                     counter = xmlAutomataNewCounter(pctxt->am,
12946                         particle->minOccurs - 1,
12947                         particle->maxOccurs - 1);
12948
12949                     sub = particle->children->children;
12950                     while (sub != NULL) {
12951                         tmp2 = xmlSchemaBuildAContentModel(pctxt,
12952                                         (xmlSchemaParticlePtr) sub);
12953                         if (tmp2 != 1) ret = 0;
12954                         sub = sub->next;
12955                     }
12956                     tmp = pctxt->state;
12957                     xmlAutomataNewCountedTrans(pctxt->am,
12958                         tmp, oldstate, counter);
12959                     pctxt->state =
12960                         xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
12961                                                    counter);
12962                     if ((particle->minOccurs == 0) || (ret == 1)) {
12963                         xmlAutomataNewEpsilon(pctxt->am,
12964                                             oldstate, pctxt->state);
12965                         ret = 1;
12966                     }
12967                 } else {
12968                     sub = particle->children->children;
12969                     while (sub != NULL) {
12970                         tmp2 = xmlSchemaBuildAContentModel(pctxt,
12971                                         (xmlSchemaParticlePtr) sub);
12972                         if (tmp2 != 1) ret = 0;
12973                         sub = sub->next;
12974                     }
12975
12976                     /*
12977                      * epsilon needed to block previous trans from
12978                      * being allowed to enter back from another
12979                      * construct
12980                      */
12981                     pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12982                                         pctxt->state, NULL);
12983
12984                     if (particle->minOccurs == 0) {
12985                         xmlAutomataNewEpsilon(pctxt->am, oldstate,
12986                                               pctxt->state);
12987                         ret = 1;
12988                     }
12989                 }
12990             }
12991             break;
12992         }
12993         case XML_SCHEMA_TYPE_CHOICE:{
12994             xmlSchemaTreeItemPtr sub;
12995             xmlAutomataStatePtr start, end;
12996
12997             ret = 0;
12998             start = pctxt->state;
12999             end = xmlAutomataNewState(pctxt->am);
13000
13001             /*
13002              * iterate over the subtypes and remerge the end with an
13003              * epsilon transition
13004              */
13005             if (particle->maxOccurs == 1) {
13006                 sub = particle->children->children;
13007                 while (sub != NULL) {
13008                     pctxt->state = start;
13009                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
13010                                         (xmlSchemaParticlePtr) sub);
13011                     if (tmp2 == 1) ret = 1;
13012                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
13013                     sub = sub->next;
13014                 }
13015             } else {
13016                 int counter;
13017                 xmlAutomataStatePtr hop, base;
13018                 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
13019                     UNBOUNDED : particle->maxOccurs - 1;
13020                 int minOccurs =
13021                     particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
13022
13023                 /*
13024                  * use a counter to keep track of the number of transtions
13025                  * which went through the choice.
13026                  */
13027                 counter =
13028                     xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
13029                 hop = xmlAutomataNewState(pctxt->am);
13030                 base = xmlAutomataNewState(pctxt->am);
13031
13032                 sub = particle->children->children;
13033                 while (sub != NULL) {
13034                     pctxt->state = base;
13035                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
13036                                         (xmlSchemaParticlePtr) sub);
13037                     if (tmp2 == 1) ret = 1;
13038                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
13039                     sub = sub->next;
13040                 }
13041                 xmlAutomataNewEpsilon(pctxt->am, start, base);
13042                 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
13043                 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
13044                 if (ret == 1)
13045                     xmlAutomataNewEpsilon(pctxt->am, base, end);
13046             }
13047             if (particle->minOccurs == 0) {
13048                 xmlAutomataNewEpsilon(pctxt->am, start, end);
13049                 ret = 1;
13050             }
13051             pctxt->state = end;
13052             break;
13053         }
13054         case XML_SCHEMA_TYPE_ALL:{
13055             xmlAutomataStatePtr start, tmp;
13056             xmlSchemaParticlePtr sub;
13057             xmlSchemaElementPtr elemDecl;
13058
13059             ret = 1;
13060
13061             sub = (xmlSchemaParticlePtr) particle->children->children;
13062             if (sub == NULL)
13063                 break;
13064
13065             ret = 0;
13066
13067             start = pctxt->state;
13068             tmp = xmlAutomataNewState(pctxt->am);
13069             xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp);
13070             pctxt->state = tmp;
13071             while (sub != NULL) {
13072                 pctxt->state = tmp;
13073
13074                 elemDecl = (xmlSchemaElementPtr) sub->children;
13075                 if (elemDecl == NULL) {
13076                     PERROR_INT("xmlSchemaBuildAContentModel",
13077                         "<element> particle has no term");
13078                     return(ret);
13079                 };
13080                 /*
13081                 * NOTE: The {max occurs} of all the particles in the
13082                 * {particles} of the group must be 0 or 1; this is
13083                 * already ensured during the parse of the content of
13084                 * <all>.
13085                 */
13086                 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
13087                     int counter;
13088
13089                     /*
13090                      * This is an abstract group, we need to share
13091                      * the same counter for all the element transitions
13092                      * derived from the group
13093                      */
13094                     counter = xmlAutomataNewCounter(pctxt->am,
13095                                        sub->minOccurs, sub->maxOccurs);
13096                     xmlSchemaBuildContentModelForSubstGroup(pctxt,
13097                                        sub, counter, pctxt->state);
13098                 } else {
13099                     if ((sub->minOccurs == 1) &&
13100                         (sub->maxOccurs == 1)) {
13101                         xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
13102                                                 pctxt->state,
13103                                                 elemDecl->name,
13104                                                 elemDecl->targetNamespace,
13105                                                 1, 1, elemDecl);
13106                     } else if ((sub->minOccurs == 0) &&
13107                         (sub->maxOccurs == 1)) {
13108
13109                         xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
13110                                                  pctxt->state,
13111                                                  elemDecl->name,
13112                                                  elemDecl->targetNamespace,
13113                                                  0,
13114                                                  1,
13115                                                  elemDecl);
13116                     }
13117                 }
13118                 sub = (xmlSchemaParticlePtr) sub->next;
13119             }
13120             pctxt->state =
13121                 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0);
13122             if (particle->minOccurs == 0) {
13123                 xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state);
13124                 ret = 1;
13125             }
13126             break;
13127         }
13128         case XML_SCHEMA_TYPE_GROUP:
13129             /*
13130             * If we hit a model group definition, then this means that
13131             * it was empty, thus was not substituted for the containing
13132             * model group. Just do nothing in this case.
13133             * TODO: But the group should be substituted and not occur at
13134             * all in the content model at this point. Fix this.
13135             */
13136             ret = 1;
13137             break;
13138         default:
13139             xmlSchemaInternalErr2(ACTXT_CAST pctxt,
13140                 "xmlSchemaBuildAContentModel",
13141                 "found unexpected term of type '%s' in content model",
13142                 WXS_ITEM_TYPE_NAME(particle->children), NULL);
13143             return(ret);
13144     }
13145     return(ret);
13146 }
13147
13148 /**
13149  * xmlSchemaBuildContentModel:
13150  * @ctxt:  the schema parser context
13151  * @type:  the complex type definition
13152  * @name:  the element name
13153  *
13154  * Builds the content model of the complex type.
13155  */
13156 static void
13157 xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
13158                            xmlSchemaParserCtxtPtr ctxt)
13159 {
13160     if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13161         (type->contModel != NULL) ||
13162         ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13163         (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
13164         return;
13165
13166 #ifdef DEBUG_CONTENT
13167     xmlGenericError(xmlGenericErrorContext,
13168                     "Building content model for %s\n", name);
13169 #endif
13170     ctxt->am = NULL;
13171     ctxt->am = xmlNewAutomata();
13172     if (ctxt->am == NULL) {
13173         xmlGenericError(xmlGenericErrorContext,
13174             "Cannot create automata for complex type %s\n", type->name);
13175         return;
13176     }
13177     ctxt->state = xmlAutomataGetInitState(ctxt->am);
13178     /*
13179     * Build the automaton.
13180     */
13181     xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
13182     xmlAutomataSetFinalState(ctxt->am, ctxt->state);
13183     type->contModel = xmlAutomataCompile(ctxt->am);
13184     if (type->contModel == NULL) {
13185         xmlSchemaPCustomErr(ctxt,
13186             XML_SCHEMAP_INTERNAL,
13187             WXS_BASIC_CAST type, type->node,
13188             "Failed to compile the content model", NULL);
13189     } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
13190         xmlSchemaPCustomErr(ctxt,
13191             XML_SCHEMAP_NOT_DETERMINISTIC,
13192             /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
13193             WXS_BASIC_CAST type, type->node,
13194             "The content model is not determinist", NULL);
13195     } else {
13196 #ifdef DEBUG_CONTENT_REGEXP
13197         xmlGenericError(xmlGenericErrorContext,
13198                         "Content model of %s:\n", type->name);
13199         xmlRegexpPrint(stderr, type->contModel);
13200 #endif
13201     }
13202     ctxt->state = NULL;
13203     xmlFreeAutomata(ctxt->am);
13204     ctxt->am = NULL;
13205 }
13206
13207 /**
13208  * xmlSchemaResolveElementReferences:
13209  * @elem:  the schema element context
13210  * @ctxt:  the schema parser context
13211  *
13212  * Resolves the references of an element declaration
13213  * or particle, which has an element declaration as it's
13214  * term.
13215  */
13216 static void
13217 xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13218                                   xmlSchemaParserCtxtPtr ctxt)
13219 {
13220     if ((ctxt == NULL) || (elemDecl == NULL) ||
13221         ((elemDecl != NULL) &&
13222         (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
13223         return;
13224     elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
13225
13226     if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
13227         xmlSchemaTypePtr type;
13228
13229         /* (type definition) ... otherwise the type definition `resolved`
13230         * to by the `actual value` of the type [attribute] ...
13231         */
13232         type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
13233             elemDecl->namedTypeNs);
13234         if (type == NULL) {
13235             xmlSchemaPResCompAttrErr(ctxt,
13236                 XML_SCHEMAP_SRC_RESOLVE,
13237                 WXS_BASIC_CAST elemDecl, elemDecl->node,
13238                 "type", elemDecl->namedType, elemDecl->namedTypeNs,
13239                 XML_SCHEMA_TYPE_BASIC, "type definition");
13240         } else
13241             elemDecl->subtypes = type;
13242     }
13243     if (elemDecl->substGroup != NULL) {
13244         xmlSchemaElementPtr substHead;
13245
13246         /*
13247         * FIXME TODO: Do we need a new field in _xmlSchemaElement for
13248         * substitutionGroup?
13249         */
13250         substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13251             elemDecl->substGroupNs);
13252         if (substHead == NULL) {
13253             xmlSchemaPResCompAttrErr(ctxt,
13254                 XML_SCHEMAP_SRC_RESOLVE,
13255                 WXS_BASIC_CAST elemDecl, NULL,
13256                 "substitutionGroup", elemDecl->substGroup,
13257                 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
13258         } else {
13259             xmlSchemaResolveElementReferences(substHead, ctxt);
13260             /*
13261             * Set the "substitution group affiliation".
13262             * NOTE that now we use the "refDecl" field for this.
13263             */
13264             WXS_SUBST_HEAD(elemDecl) = substHead;
13265             /*
13266             * The type definitions is set to:
13267             * SPEC "...the {type definition} of the element
13268             * declaration `resolved` to by the `actual value`
13269             * of the substitutionGroup [attribute], if present"
13270             */
13271             if (elemDecl->subtypes == NULL)
13272                 elemDecl->subtypes = substHead->subtypes;
13273         }
13274     }
13275     /*
13276     * SPEC "The definition of anyType serves as the default type definition
13277     * for element declarations whose XML representation does not specify one."
13278     */
13279     if ((elemDecl->subtypes == NULL) &&
13280         (elemDecl->namedType == NULL) &&
13281         (elemDecl->substGroup == NULL))
13282         elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13283 }
13284
13285 /**
13286  * xmlSchemaResolveUnionMemberTypes:
13287  * @ctxt:  the schema parser context
13288  * @type:  the schema simple type definition
13289  *
13290  * Checks and builds the "member type definitions" property of the union
13291  * simple type. This handles part (1), part (2) is done in
13292  * xmlSchemaFinishMemberTypeDefinitionsProperty()
13293  *
13294  * Returns -1 in case of an internal error, 0 otherwise.
13295  */
13296 static int
13297 xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13298                                  xmlSchemaTypePtr type)
13299 {
13300
13301     xmlSchemaTypeLinkPtr link, lastLink, newLink;
13302     xmlSchemaTypePtr memberType;
13303
13304     /*
13305     * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13306     * define the explicit members as the type definitions `resolved`
13307     * to by the items in the `actual value` of the memberTypes [attribute],
13308     * if any, followed by the type definitions corresponding to the
13309     * <simpleType>s among the [children] of <union>, if any."
13310     */
13311     /*
13312     * Resolve references.
13313     */
13314     link = type->memberTypes;
13315     lastLink = NULL;
13316     while (link != NULL) {
13317         const xmlChar *name, *nsName;
13318
13319         name = ((xmlSchemaQNameRefPtr) link->type)->name;
13320         nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13321
13322         memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
13323         if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
13324             xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
13325                 WXS_BASIC_CAST type, type->node, "memberTypes",
13326                 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13327             /*
13328             * Remove the member type link.
13329             */
13330             if (lastLink == NULL)
13331                 type->memberTypes = link->next;
13332             else
13333                 lastLink->next = link->next;
13334             newLink = link;
13335             link = link->next;
13336             xmlFree(newLink);
13337         } else {
13338             link->type = memberType;
13339             lastLink = link;
13340             link = link->next;
13341         }
13342     }
13343     /*
13344     * Add local simple types,
13345     */
13346     memberType = type->subtypes;
13347     while (memberType != NULL) {
13348         link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13349         if (link == NULL) {
13350             xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13351             return (-1);
13352         }
13353         link->type = memberType;
13354         link->next = NULL;
13355         if (lastLink == NULL)
13356             type->memberTypes = link;
13357         else
13358             lastLink->next = link;
13359         lastLink = link;
13360         memberType = memberType->next;
13361     }
13362     return (0);
13363 }
13364
13365 /**
13366  * xmlSchemaIsDerivedFromBuiltInType:
13367  * @ctxt:  the schema parser context
13368  * @type:  the type definition
13369  * @valType: the value type
13370  *
13371  *
13372  * Returns 1 if the type has the given value type, or
13373  * is derived from such a type.
13374  */
13375 static int
13376 xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13377 {
13378     if (type == NULL)
13379         return (0);
13380     if (WXS_IS_COMPLEX(type))
13381         return (0);
13382     if (type->type == XML_SCHEMA_TYPE_BASIC) {
13383         if (type->builtInType == valType)
13384             return(1);
13385         if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13386             (type->builtInType == XML_SCHEMAS_ANYTYPE))
13387             return (0);
13388         return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13389     }
13390     return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13391 }
13392
13393 #if 0
13394 /**
13395  * xmlSchemaIsDerivedFromBuiltInType:
13396  * @ctxt:  the schema parser context
13397  * @type:  the type definition
13398  * @valType: the value type
13399  *
13400  *
13401  * Returns 1 if the type has the given value type, or
13402  * is derived from such a type.
13403  */
13404 static int
13405 xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13406 {
13407     if (type == NULL)
13408         return (0);
13409     if (WXS_IS_COMPLEX(type))
13410         return (0);
13411     if (type->type == XML_SCHEMA_TYPE_BASIC) {
13412         if (type->builtInType == valType)
13413             return(1);
13414         return (0);
13415     } else
13416         return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13417
13418     return (0);
13419 }
13420
13421 static xmlSchemaTypePtr
13422 xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13423 {
13424     if (type == NULL)
13425         return (NULL);
13426     if (WXS_IS_COMPLEX(type))
13427         return (NULL);
13428     if (type->type == XML_SCHEMA_TYPE_BASIC)
13429         return(type);
13430     return(xmlSchemaQueryBuiltInType(type->subtypes));
13431 }
13432 #endif
13433
13434 /**
13435  * xmlSchemaGetPrimitiveType:
13436  * @type:  the simpleType definition
13437  *
13438  * Returns the primitive type of the given type or
13439  * NULL in case of error.
13440  */
13441 static xmlSchemaTypePtr
13442 xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13443 {
13444
13445     while (type != NULL) {
13446         /*
13447         * Note that anySimpleType is actually not a primitive type
13448         * but we need that here.
13449         */
13450         if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13451            (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
13452             return (type);
13453         type = type->baseType;
13454     }
13455
13456     return (NULL);
13457 }
13458
13459 #if 0
13460 /**
13461  * xmlSchemaGetBuiltInTypeAncestor:
13462  * @type:  the simpleType definition
13463  *
13464  * Returns the primitive type of the given type or
13465  * NULL in case of error.
13466  */
13467 static xmlSchemaTypePtr
13468 xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13469 {
13470     if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
13471         return (0);
13472     while (type != NULL) {
13473         if (type->type == XML_SCHEMA_TYPE_BASIC)
13474             return (type);
13475         type = type->baseType;
13476     }
13477
13478     return (NULL);
13479 }
13480 #endif
13481
13482 /**
13483  * xmlSchemaCloneWildcardNsConstraints:
13484  * @ctxt:  the schema parser context
13485  * @dest:  the destination wildcard
13486  * @source: the source wildcard
13487  *
13488  * Clones the namespace constraints of source
13489  * and assignes them to dest.
13490  * Returns -1 on internal error, 0 otherwise.
13491  */
13492 static int
13493 xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
13494                                     xmlSchemaWildcardPtr dest,
13495                                     xmlSchemaWildcardPtr source)
13496 {
13497     xmlSchemaWildcardNsPtr cur, tmp, last;
13498
13499     if ((source == NULL) || (dest == NULL))
13500         return(-1);
13501     dest->any = source->any;
13502     cur = source->nsSet;
13503     last = NULL;
13504     while (cur != NULL) {
13505         tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13506         if (tmp == NULL)
13507             return(-1);
13508         tmp->value = cur->value;
13509         if (last == NULL)
13510             dest->nsSet = tmp;
13511         else
13512             last->next = tmp;
13513         last = tmp;
13514         cur = cur->next;
13515     }
13516     if (dest->negNsSet != NULL)
13517         xmlSchemaFreeWildcardNsSet(dest->negNsSet);
13518     if (source->negNsSet != NULL) {
13519         dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13520         if (dest->negNsSet == NULL)
13521             return(-1);
13522         dest->negNsSet->value = source->negNsSet->value;
13523     } else
13524         dest->negNsSet = NULL;
13525     return(0);
13526 }
13527
13528 /**
13529  * xmlSchemaUnionWildcards:
13530  * @ctxt:  the schema parser context
13531  * @completeWild:  the first wildcard
13532  * @curWild: the second wildcard
13533  *
13534  * Unions the namespace constraints of the given wildcards.
13535  * @completeWild will hold the resulting union.
13536  * Returns a positive error code on failure, -1 in case of an
13537  * internal error, 0 otherwise.
13538  */
13539 static int
13540 xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
13541                             xmlSchemaWildcardPtr completeWild,
13542                             xmlSchemaWildcardPtr curWild)
13543 {
13544     xmlSchemaWildcardNsPtr cur, curB, tmp;
13545
13546     /*
13547     * 1 If O1 and O2 are the same value, then that value must be the
13548     * value.
13549     */
13550     if ((completeWild->any == curWild->any) &&
13551         ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13552         ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13553
13554         if ((completeWild->negNsSet == NULL) ||
13555             (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13556
13557             if (completeWild->nsSet != NULL) {
13558                 int found = 0;
13559
13560                 /*
13561                 * Check equality of sets.
13562                 */
13563                 cur = completeWild->nsSet;
13564                 while (cur != NULL) {
13565                     found = 0;
13566                     curB = curWild->nsSet;
13567                     while (curB != NULL) {
13568                         if (cur->value == curB->value) {
13569                             found = 1;
13570                             break;
13571                         }
13572                         curB = curB->next;
13573                     }
13574                     if (!found)
13575                         break;
13576                     cur = cur->next;
13577                 }
13578                 if (found)
13579                     return(0);
13580             } else
13581                 return(0);
13582         }
13583     }
13584     /*
13585     * 2 If either O1 or O2 is any, then any must be the value
13586     */
13587     if (completeWild->any != curWild->any) {
13588         if (completeWild->any == 0) {
13589             completeWild->any = 1;
13590             if (completeWild->nsSet != NULL) {
13591                 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13592                 completeWild->nsSet = NULL;
13593             }
13594             if (completeWild->negNsSet != NULL) {
13595                 xmlFree(completeWild->negNsSet);
13596                 completeWild->negNsSet = NULL;
13597             }
13598         }
13599         return (0);
13600     }
13601     /*
13602     * 3 If both O1 and O2 are sets of (namespace names or `absent`),
13603     * then the union of those sets must be the value.
13604     */
13605     if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13606         int found;
13607         xmlSchemaWildcardNsPtr start;
13608
13609         cur = curWild->nsSet;
13610         start = completeWild->nsSet;
13611         while (cur != NULL) {
13612             found = 0;
13613             curB = start;
13614             while (curB != NULL) {
13615                 if (cur->value == curB->value) {
13616                     found = 1;
13617                     break;
13618                 }
13619                 curB = curB->next;
13620             }
13621             if (!found) {
13622                 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13623                 if (tmp == NULL)
13624                     return (-1);
13625                 tmp->value = cur->value;
13626                 tmp->next = completeWild->nsSet;
13627                 completeWild->nsSet = tmp;
13628             }
13629             cur = cur->next;
13630         }
13631
13632         return(0);
13633     }
13634     /*
13635     * 4 If the two are negations of different values (namespace names
13636     * or `absent`), then a pair of not and `absent` must be the value.
13637     */
13638     if ((completeWild->negNsSet != NULL) &&
13639         (curWild->negNsSet != NULL) &&
13640         (completeWild->negNsSet->value != curWild->negNsSet->value)) {
13641         completeWild->negNsSet->value = NULL;
13642
13643         return(0);
13644     }
13645     /*
13646      * 5.
13647      */
13648     if (((completeWild->negNsSet != NULL) &&
13649         (completeWild->negNsSet->value != NULL) &&
13650         (curWild->nsSet != NULL)) ||
13651         ((curWild->negNsSet != NULL) &&
13652         (curWild->negNsSet->value != NULL) &&
13653         (completeWild->nsSet != NULL))) {
13654
13655         int nsFound, absentFound = 0;
13656
13657         if (completeWild->nsSet != NULL) {
13658             cur = completeWild->nsSet;
13659             curB = curWild->negNsSet;
13660         } else {
13661             cur = curWild->nsSet;
13662             curB = completeWild->negNsSet;
13663         }
13664         nsFound = 0;
13665         while (cur != NULL) {
13666             if (cur->value == NULL)
13667                 absentFound = 1;
13668             else if (cur->value == curB->value)
13669                 nsFound = 1;
13670             if (nsFound && absentFound)
13671                 break;
13672             cur = cur->next;
13673         }
13674
13675         if (nsFound && absentFound) {
13676             /*
13677             * 5.1 If the set S includes both the negated namespace
13678             * name and `absent`, then any must be the value.
13679             */
13680             completeWild->any = 1;
13681             if (completeWild->nsSet != NULL) {
13682                 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13683                 completeWild->nsSet = NULL;
13684             }
13685             if (completeWild->negNsSet != NULL) {
13686                 xmlFree(completeWild->negNsSet);
13687                 completeWild->negNsSet = NULL;
13688             }
13689         } else if (nsFound && (!absentFound)) {
13690             /*
13691             * 5.2 If the set S includes the negated namespace name
13692             * but not `absent`, then a pair of not and `absent` must
13693             * be the value.
13694             */
13695             if (completeWild->nsSet != NULL) {
13696                 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13697                 completeWild->nsSet = NULL;
13698             }
13699             if (completeWild->negNsSet == NULL) {
13700                 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13701                 if (completeWild->negNsSet == NULL)
13702                     return (-1);
13703             }
13704             completeWild->negNsSet->value = NULL;
13705         } else if ((!nsFound) && absentFound) {
13706             /*
13707             * 5.3 If the set S includes `absent` but not the negated
13708             * namespace name, then the union is not expressible.
13709             */
13710             xmlSchemaPErr(ctxt, completeWild->node,
13711                 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
13712                 "The union of the wilcard is not expressible.\n",
13713                 NULL, NULL);
13714             return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
13715         } else if ((!nsFound) && (!absentFound)) {
13716             /*
13717             * 5.4 If the set S does not include either the negated namespace
13718             * name or `absent`, then whichever of O1 or O2 is a pair of not
13719             * and a namespace name must be the value.
13720             */
13721             if (completeWild->negNsSet == NULL) {
13722                 if (completeWild->nsSet != NULL) {
13723                     xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13724                     completeWild->nsSet = NULL;
13725                 }
13726                 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13727                 if (completeWild->negNsSet == NULL)
13728                     return (-1);
13729                 completeWild->negNsSet->value = curWild->negNsSet->value;
13730             }
13731         }
13732         return (0);
13733     }
13734     /*
13735      * 6.
13736      */
13737     if (((completeWild->negNsSet != NULL) &&
13738         (completeWild->negNsSet->value == NULL) &&
13739         (curWild->nsSet != NULL)) ||
13740         ((curWild->negNsSet != NULL) &&
13741         (curWild->negNsSet->value == NULL) &&
13742         (completeWild->nsSet != NULL))) {
13743
13744         if (completeWild->nsSet != NULL) {
13745             cur = completeWild->nsSet;
13746         } else {
13747             cur = curWild->nsSet;
13748         }
13749         while (cur != NULL) {
13750             if (cur->value == NULL) {
13751                 /*
13752                 * 6.1 If the set S includes `absent`, then any must be the
13753                 * value.
13754                 */
13755                 completeWild->any = 1;
13756                 if (completeWild->nsSet != NULL) {
13757                     xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13758                     completeWild->nsSet = NULL;
13759                 }
13760                 if (completeWild->negNsSet != NULL) {
13761                     xmlFree(completeWild->negNsSet);
13762                     completeWild->negNsSet = NULL;
13763                 }
13764                 return (0);
13765             }
13766             cur = cur->next;
13767         }
13768         if (completeWild->negNsSet == NULL) {
13769             /*
13770             * 6.2 If the set S does not include `absent`, then a pair of not
13771             * and `absent` must be the value.
13772             */
13773             if (completeWild->nsSet != NULL) {
13774                 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13775                 completeWild->nsSet = NULL;
13776             }
13777             completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13778             if (completeWild->negNsSet == NULL)
13779                 return (-1);
13780             completeWild->negNsSet->value = NULL;
13781         }
13782         return (0);
13783     }
13784     return (0);
13785
13786 }
13787
13788 /**
13789  * xmlSchemaIntersectWildcards:
13790  * @ctxt:  the schema parser context
13791  * @completeWild:  the first wildcard
13792  * @curWild: the second wildcard
13793  *
13794  * Intersects the namespace constraints of the given wildcards.
13795  * @completeWild will hold the resulting intersection.
13796  * Returns a positive error code on failure, -1 in case of an
13797  * internal error, 0 otherwise.
13798  */
13799 static int
13800 xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
13801                             xmlSchemaWildcardPtr completeWild,
13802                             xmlSchemaWildcardPtr curWild)
13803 {
13804     xmlSchemaWildcardNsPtr cur, curB, prev,  tmp;
13805
13806     /*
13807     * 1 If O1 and O2 are the same value, then that value must be the
13808     * value.
13809     */
13810     if ((completeWild->any == curWild->any) &&
13811         ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13812         ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13813
13814         if ((completeWild->negNsSet == NULL) ||
13815             (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13816
13817             if (completeWild->nsSet != NULL) {
13818                 int found = 0;
13819
13820                 /*
13821                 * Check equality of sets.
13822                 */
13823                 cur = completeWild->nsSet;
13824                 while (cur != NULL) {
13825                     found = 0;
13826                     curB = curWild->nsSet;
13827                     while (curB != NULL) {
13828                         if (cur->value == curB->value) {
13829                             found = 1;
13830                             break;
13831                         }
13832                         curB = curB->next;
13833                     }
13834                     if (!found)
13835                         break;
13836                     cur = cur->next;
13837                 }
13838                 if (found)
13839                     return(0);
13840             } else
13841                 return(0);
13842         }
13843     }
13844     /*
13845     * 2 If either O1 or O2 is any, then the other must be the value.
13846     */
13847     if ((completeWild->any != curWild->any) && (completeWild->any)) {
13848         if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13849             return(-1);
13850         return(0);
13851     }
13852     /*
13853     * 3 If either O1 or O2 is a pair of not and a value (a namespace
13854     * name or `absent`) and the other is a set of (namespace names or
13855     * `absent`), then that set, minus the negated value if it was in
13856     * the set, minus `absent` if it was in the set, must be the value.
13857     */
13858     if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13859         ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13860         const xmlChar *neg;
13861
13862         if (completeWild->nsSet == NULL) {
13863             neg = completeWild->negNsSet->value;
13864             if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13865                 return(-1);
13866         } else
13867             neg = curWild->negNsSet->value;
13868         /*
13869         * Remove absent and negated.
13870         */
13871         prev = NULL;
13872         cur = completeWild->nsSet;
13873         while (cur != NULL) {
13874             if (cur->value == NULL) {
13875                 if (prev == NULL)
13876                     completeWild->nsSet = cur->next;
13877                 else
13878                     prev->next = cur->next;
13879                 xmlFree(cur);
13880                 break;
13881             }
13882             prev = cur;
13883             cur = cur->next;
13884         }
13885         if (neg != NULL) {
13886             prev = NULL;
13887             cur = completeWild->nsSet;
13888             while (cur != NULL) {
13889                 if (cur->value == neg) {
13890                     if (prev == NULL)
13891                         completeWild->nsSet = cur->next;
13892                     else
13893                         prev->next = cur->next;
13894                     xmlFree(cur);
13895                     break;
13896                 }
13897                 prev = cur;
13898                 cur = cur->next;
13899             }
13900         }
13901
13902         return(0);
13903     }
13904     /*
13905     * 4 If both O1 and O2 are sets of (namespace names or `absent`),
13906     * then the intersection of those sets must be the value.
13907     */
13908     if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13909         int found;
13910
13911         cur = completeWild->nsSet;
13912         prev = NULL;
13913         while (cur != NULL) {
13914             found = 0;
13915             curB = curWild->nsSet;
13916             while (curB != NULL) {
13917                 if (cur->value == curB->value) {
13918                     found = 1;
13919                     break;
13920                 }
13921                 curB = curB->next;
13922             }
13923             if (!found) {
13924                 if (prev == NULL)
13925                     completeWild->nsSet = cur->next;
13926                 else
13927                     prev->next = cur->next;
13928                 tmp = cur->next;
13929                 xmlFree(cur);
13930                 cur = tmp;
13931                 continue;
13932             }
13933             prev = cur;
13934             cur = cur->next;
13935         }
13936
13937         return(0);
13938     }
13939     /* 5 If the two are negations of different namespace names,
13940     * then the intersection is not expressible
13941     */
13942     if ((completeWild->negNsSet != NULL) &&
13943         (curWild->negNsSet != NULL) &&
13944         (completeWild->negNsSet->value != curWild->negNsSet->value) &&
13945         (completeWild->negNsSet->value != NULL) &&
13946         (curWild->negNsSet->value != NULL)) {
13947
13948         xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
13949             "The intersection of the wilcard is not expressible.\n",
13950             NULL, NULL);
13951         return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
13952     }
13953     /*
13954     * 6 If the one is a negation of a namespace name and the other
13955     * is a negation of `absent`, then the one which is the negation
13956     * of a namespace name must be the value.
13957     */
13958     if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
13959         (completeWild->negNsSet->value != curWild->negNsSet->value) &&
13960         (completeWild->negNsSet->value == NULL)) {
13961         completeWild->negNsSet->value =  curWild->negNsSet->value;
13962     }
13963     return(0);
13964 }
13965
13966 /**
13967  * xmlSchemaIsWildcardNsConstraintSubset:
13968  * @ctxt:  the schema parser context
13969  * @sub:  the first wildcard
13970  * @super: the second wildcard
13971  *
13972  * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
13973  *
13974  * Returns 0 if the namespace constraint of @sub is an intensional
13975  * subset of @super, 1 otherwise.
13976  */
13977 static int
13978 xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
13979                           xmlSchemaWildcardPtr super)
13980 {
13981     /*
13982     * 1 super must be any.
13983     */
13984     if (super->any)
13985         return (0);
13986     /*
13987     * 2.1 sub must be a pair of not and a namespace name or `absent`.
13988     * 2.2 super must be a pair of not and the same value.
13989     */
13990     if ((sub->negNsSet != NULL) &&
13991         (super->negNsSet != NULL) &&
13992         (sub->negNsSet->value == super->negNsSet->value))
13993         return (0);
13994     /*
13995     * 3.1 sub must be a set whose members are either namespace names or `absent`.
13996     */
13997     if (sub->nsSet != NULL) {
13998         /*
13999         * 3.2.1 super must be the same set or a superset thereof.
14000         */
14001         if (super->nsSet != NULL) {
14002             xmlSchemaWildcardNsPtr cur, curB;
14003             int found = 0;
14004
14005             cur = sub->nsSet;
14006             while (cur != NULL) {
14007                 found = 0;
14008                 curB = super->nsSet;
14009                 while (curB != NULL) {
14010                     if (cur->value == curB->value) {
14011                         found = 1;
14012                         break;
14013                     }
14014                     curB = curB->next;
14015                 }
14016                 if (!found)
14017                     return (1);
14018                 cur = cur->next;
14019             }
14020             if (found)
14021                 return (0);
14022         } else if (super->negNsSet != NULL) {
14023             xmlSchemaWildcardNsPtr cur;
14024             /*
14025             * 3.2.2 super must be a pair of not and a namespace name or
14026             * `absent` and that value must not be in sub's set.
14027             */
14028             cur = sub->nsSet;
14029             while (cur != NULL) {
14030                 if (cur->value == super->negNsSet->value)
14031                     return (1);
14032                 cur = cur->next;
14033             }
14034             return (0);
14035         }
14036     }
14037     return (1);
14038 }
14039
14040 static int
14041 xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
14042                                      int *fixed,
14043                                      const xmlChar **value,
14044                                      xmlSchemaValPtr *val)
14045 {
14046     *fixed = 0;
14047     *value = NULL;
14048     if (val != 0)
14049         *val = NULL;
14050
14051     if (attruse->defValue != NULL) {
14052         *value = attruse->defValue;
14053         if (val != NULL)
14054             *val = attruse->defVal;
14055         if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
14056             *fixed = 1;
14057         return(1);
14058     } else if ((attruse->attrDecl != NULL) &&
14059         (attruse->attrDecl->defValue != NULL)) {
14060         *value = attruse->attrDecl->defValue;
14061         if (val != NULL)
14062             *val = attruse->attrDecl->defVal;
14063         if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
14064             *fixed = 1;
14065         return(1);
14066     }
14067     return(0);
14068 }
14069 /**
14070  * xmlSchemaCheckCVCWildcardNamespace:
14071  * @wild:  the wildcard
14072  * @ns:  the namespace
14073  *
14074  * Validation Rule: Wildcard allows Namespace Name
14075  * (cvc-wildcard-namespace)
14076  *
14077  * Returns 0 if the given namespace matches the wildcard,
14078  * 1 otherwise and -1 on API errors.
14079  */
14080 static int
14081 xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
14082                                    const xmlChar* ns)
14083 {
14084     if (wild == NULL)
14085         return(-1);
14086
14087     if (wild->any)
14088         return(0);
14089     else if (wild->nsSet != NULL) {
14090         xmlSchemaWildcardNsPtr cur;
14091
14092         cur = wild->nsSet;
14093         while (cur != NULL) {
14094             if (xmlStrEqual(cur->value, ns))
14095                 return(0);
14096             cur = cur->next;
14097         }
14098     } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
14099         (!xmlStrEqual(wild->negNsSet->value, ns)))
14100         return(0);
14101
14102     return(1);
14103 }
14104
14105 #define XML_SCHEMA_ACTION_DERIVE 0
14106 #define XML_SCHEMA_ACTION_REDEFINE 1
14107
14108 #define WXS_ACTION_STR(a) \
14109 ((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
14110
14111 /*
14112 * Schema Component Constraint:
14113 *   Derivation Valid (Restriction, Complex)
14114 *   derivation-ok-restriction (2) - (4)
14115 *
14116 * ATTENTION:
14117 * In XML Schema 1.1 this will be:
14118 * Validation Rule:
14119 *     Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
14120 *
14121 */
14122 static int
14123 xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
14124                                        int action,
14125                                        xmlSchemaBasicItemPtr item,
14126                                        xmlSchemaBasicItemPtr baseItem,
14127                                        xmlSchemaItemListPtr uses,
14128                                        xmlSchemaItemListPtr baseUses,
14129                                        xmlSchemaWildcardPtr wild,
14130                                        xmlSchemaWildcardPtr baseWild)
14131 {
14132     xmlSchemaAttributeUsePtr cur = NULL, bcur;
14133     int i, j, found; /* err = 0; */
14134     const xmlChar *bEffValue;
14135     int effFixed;
14136
14137     if (uses != NULL) {
14138         for (i = 0; i < uses->nbItems; i++) {
14139             cur = uses->items[i];
14140             found = 0;
14141             if (baseUses == NULL)
14142                 goto not_found;
14143             for (j = 0; j < baseUses->nbItems; j++) {
14144                 bcur = baseUses->items[j];
14145                 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14146                         WXS_ATTRUSE_DECL_NAME(bcur)) &&
14147                     (WXS_ATTRUSE_DECL_TNS(cur) ==
14148                         WXS_ATTRUSE_DECL_TNS(bcur)))
14149                 {
14150                     /*
14151                     * (2.1) "If there is an attribute use in the {attribute
14152                     * uses} of the {base type definition} (call this B) whose
14153                     * {attribute declaration} has the same {name} and {target
14154                     * namespace}, then  all of the following must be true:"
14155                     */
14156                     found = 1;
14157
14158                     if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14159                         (bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14160                     {
14161                         xmlChar *str = NULL;
14162                         /*
14163                         * (2.1.1) "one of the following must be true:"
14164                         * (2.1.1.1) "B's {required} is false."
14165                         * (2.1.1.2) "R's {required} is true."
14166                         */
14167                         xmlSchemaPAttrUseErr4(pctxt,
14168                             XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14169                             WXS_ITEM_NODE(item), item, cur,
14170                             "The 'optional' attribute use is inconsistent "
14171                             "with the corresponding 'required' attribute use of "
14172                             "the %s %s",
14173                             WXS_ACTION_STR(action),
14174                             xmlSchemaGetComponentDesignation(&str, baseItem),
14175                             NULL, NULL);
14176                         FREE_AND_NULL(str);
14177                         /* err = pctxt->err; */
14178                     } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
14179                         WXS_ATTRUSE_TYPEDEF(cur),
14180                         WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14181                     {
14182                         xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14183
14184                         /*
14185                         * SPEC (2.1.2) "R's {attribute declaration}'s
14186                         * {type definition} must be validly derived from
14187                         * B's {type definition} given the empty set as
14188                         * defined in Type Derivation OK (Simple) ($3.14.6)."
14189                         */
14190                         xmlSchemaPAttrUseErr4(pctxt,
14191                             XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14192                             WXS_ITEM_NODE(item), item, cur,
14193                             "The attribute declaration's %s "
14194                             "is not validly derived from "
14195                             "the corresponding %s of the "
14196                             "attribute declaration in the %s %s",
14197                             xmlSchemaGetComponentDesignation(&strA,
14198                                 WXS_ATTRUSE_TYPEDEF(cur)),
14199                             xmlSchemaGetComponentDesignation(&strB,
14200                                 WXS_ATTRUSE_TYPEDEF(bcur)),
14201                             WXS_ACTION_STR(action),
14202                             xmlSchemaGetComponentDesignation(&strC, baseItem));
14203                             /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14204                         FREE_AND_NULL(strA);
14205                         FREE_AND_NULL(strB);
14206                         FREE_AND_NULL(strC);
14207                         /* err = pctxt->err; */
14208                     } else {
14209                         /*
14210                         * 2.1.3 [Definition:]  Let the effective value
14211                         * constraint of an attribute use be its {value
14212                         * constraint}, if present, otherwise its {attribute
14213                         * declaration}'s {value constraint} .
14214                         */
14215                         xmlSchemaGetEffectiveValueConstraint(bcur,
14216                             &effFixed, &bEffValue, NULL);
14217                         /*
14218                         * 2.1.3 ... one of the following must be true
14219                         *
14220                         * 2.1.3.1 B's `effective value constraint` is
14221                         * `absent` or default.
14222                         */
14223                         if ((bEffValue != NULL) &&
14224                             (effFixed == 1)) {
14225                             const xmlChar *rEffValue = NULL;
14226
14227                             xmlSchemaGetEffectiveValueConstraint(bcur,
14228                                 &effFixed, &rEffValue, NULL);
14229                             /*
14230                             * 2.1.3.2 R's `effective value constraint` is
14231                             * fixed with the same string as B's.
14232                             * MAYBE TODO: Compare the computed values.
14233                             *       Hmm, it says "same string" so
14234                             *       string-equality might really be sufficient.
14235                             */
14236                             if ((effFixed == 0) ||
14237                                 (! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14238                             {
14239                                 xmlChar *str = NULL;
14240
14241                                 xmlSchemaPAttrUseErr4(pctxt,
14242                                     XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14243                                     WXS_ITEM_NODE(item), item, cur,
14244                                     "The effective value constraint of the "
14245                                     "attribute use is inconsistent with "
14246                                     "its correspondent in the %s %s",
14247                                     WXS_ACTION_STR(action),
14248                                     xmlSchemaGetComponentDesignation(&str,
14249                                         baseItem),
14250                                     NULL, NULL);
14251                                 FREE_AND_NULL(str);
14252                                 /* err = pctxt->err; */
14253                             }
14254                         }
14255                     }
14256                     break;
14257                 }
14258             }
14259 not_found:
14260             if (!found) {
14261                 /*
14262                 * (2.2) "otherwise the {base type definition} must have an
14263                 * {attribute wildcard} and the {target namespace} of the
14264                 * R's {attribute declaration} must be `valid` with respect
14265                 * to that wildcard, as defined in Wildcard allows Namespace
14266                 * Name ($3.10.4)."
14267                 */
14268                 if ((baseWild == NULL) ||
14269                     (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14270                     (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14271                 {
14272                     xmlChar *str = NULL;
14273
14274                     xmlSchemaPAttrUseErr4(pctxt,
14275                         XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14276                         WXS_ITEM_NODE(item), item, cur,
14277                         "Neither a matching attribute use, "
14278                         "nor a matching wildcard exists in the %s %s",
14279                         WXS_ACTION_STR(action),
14280                         xmlSchemaGetComponentDesignation(&str, baseItem),
14281                         NULL, NULL);
14282                     FREE_AND_NULL(str);
14283                     /* err = pctxt->err; */
14284                 }
14285             }
14286         }
14287     }
14288     /*
14289     * SPEC derivation-ok-restriction (3):
14290     * (3) "For each attribute use in the {attribute uses} of the {base type
14291     * definition} whose {required} is true, there must be an attribute
14292     * use with an {attribute declaration} with the same {name} and
14293     * {target namespace} as its {attribute declaration} in the {attribute
14294     * uses} of the complex type definition itself whose {required} is true.
14295     */
14296     if (baseUses != NULL) {
14297         for (j = 0; j < baseUses->nbItems; j++) {
14298             bcur = baseUses->items[j];
14299             if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14300                 continue;
14301             found = 0;
14302             if (uses != NULL) {
14303                 for (i = 0; i < uses->nbItems; i++) {
14304                     cur = uses->items[i];
14305                     if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14306                         WXS_ATTRUSE_DECL_NAME(bcur)) &&
14307                         (WXS_ATTRUSE_DECL_TNS(cur) ==
14308                         WXS_ATTRUSE_DECL_TNS(bcur))) {
14309                         found = 1;
14310                         break;
14311                     }
14312                 }
14313             }
14314             if (!found) {
14315                 xmlChar *strA = NULL, *strB = NULL;
14316
14317                 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14318                     XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14319                     NULL, item,
14320                     "A matching attribute use for the "
14321                     "'required' %s of the %s %s is missing",
14322                     xmlSchemaGetComponentDesignation(&strA, bcur),
14323                     WXS_ACTION_STR(action),
14324                     xmlSchemaGetComponentDesignation(&strB, baseItem),
14325                     NULL);
14326                 FREE_AND_NULL(strA);
14327                 FREE_AND_NULL(strB);
14328             }
14329         }
14330     }
14331     /*
14332     * derivation-ok-restriction (4)
14333     */
14334     if (wild != NULL) {
14335         /*
14336         * (4) "If there is an {attribute wildcard}, all of the
14337         * following must be true:"
14338         */
14339         if (baseWild == NULL) {
14340             xmlChar *str = NULL;
14341
14342             /*
14343             * (4.1) "The {base type definition} must also have one."
14344             */
14345             xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14346                 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14347                 NULL, item,
14348                 "The %s has an attribute wildcard, "
14349                 "but the %s %s '%s' does not have one",
14350                 WXS_ITEM_TYPE_NAME(item),
14351                 WXS_ACTION_STR(action),
14352                 WXS_ITEM_TYPE_NAME(baseItem),
14353                 xmlSchemaGetComponentQName(&str, baseItem));
14354             FREE_AND_NULL(str);
14355             return(pctxt->err);
14356         } else if ((baseWild->any == 0) &&
14357                 xmlSchemaCheckCOSNSSubset(wild, baseWild))
14358         {
14359             xmlChar *str = NULL;
14360             /*
14361             * (4.2) "The complex type definition's {attribute wildcard}'s
14362             * {namespace constraint} must be a subset of the {base type
14363             * definition}'s {attribute wildcard}'s {namespace constraint},
14364             * as defined by Wildcard Subset ($3.10.6)."
14365             */
14366             xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14367                 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14368                 NULL, item,
14369                 "The attribute wildcard is not a valid "
14370                 "subset of the wildcard in the %s %s '%s'",
14371                 WXS_ACTION_STR(action),
14372                 WXS_ITEM_TYPE_NAME(baseItem),
14373                 xmlSchemaGetComponentQName(&str, baseItem),
14374                 NULL);
14375             FREE_AND_NULL(str);
14376             return(pctxt->err);
14377         }
14378         /* 4.3 Unless the {base type definition} is the `ur-type
14379         * definition`, the complex type definition's {attribute
14380         * wildcard}'s {process contents} must be identical to or
14381         * stronger than the {base type definition}'s {attribute
14382         * wildcard}'s {process contents}, where strict is stronger
14383         * than lax is stronger than skip.
14384         */
14385         if ((! WXS_IS_ANYTYPE(baseItem)) &&
14386             (wild->processContents < baseWild->processContents)) {
14387             xmlChar *str = NULL;
14388             xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14389                 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14390                 NULL, baseItem,
14391                 "The {process contents} of the attribute wildcard is "
14392                 "weaker than the one in the %s %s '%s'",
14393                 WXS_ACTION_STR(action),
14394                 WXS_ITEM_TYPE_NAME(baseItem),
14395                 xmlSchemaGetComponentQName(&str, baseItem),
14396                 NULL);
14397             FREE_AND_NULL(str)
14398                 return(pctxt->err);
14399         }
14400     }
14401     return(0);
14402 }
14403
14404
14405 static int
14406 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14407                                   xmlSchemaBasicItemPtr item,
14408                                   xmlSchemaWildcardPtr *completeWild,
14409                                   xmlSchemaItemListPtr list,
14410                                   xmlSchemaItemListPtr prohibs);
14411 /**
14412  * xmlSchemaFixupTypeAttributeUses:
14413  * @ctxt:  the schema parser context
14414  * @type:  the complex type definition
14415  *
14416  *
14417  * Builds the wildcard and the attribute uses on the given complex type.
14418  * Returns -1 if an internal error occurs, 0 otherwise.
14419  *
14420  * ATTENTION TODO: Experimantally this uses pointer comparisons for
14421  * strings, so recheck this if we start to hardcode some schemata, since
14422  * they might not be in the same dict.
14423  * NOTE: It is allowed to "extend" the xs:anyType type.
14424  */
14425 static int
14426 xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
14427                                   xmlSchemaTypePtr type)
14428 {
14429     xmlSchemaTypePtr baseType = NULL;
14430     xmlSchemaAttributeUsePtr use;
14431     xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
14432
14433     if (type->baseType == NULL) {
14434         PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14435             "no base type");
14436         return (-1);
14437     }
14438     baseType = type->baseType;
14439     if (WXS_IS_TYPE_NOT_FIXED(baseType))
14440         if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
14441             return(-1);
14442
14443     uses = type->attrUses;
14444     baseUses = baseType->attrUses;
14445     /*
14446     * Expand attribute group references. And build the 'complete'
14447     * wildcard, i.e. intersect multiple wildcards.
14448     * Move attribute prohibitions into a separate list.
14449     */
14450     if (uses != NULL) {
14451         if (WXS_IS_RESTRICTION(type)) {
14452             /*
14453             * This one will transfer all attr. prohibitions
14454             * into pctxt->attrProhibs.
14455             */
14456             if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14457                 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14458                 pctxt->attrProhibs) == -1)
14459             {
14460                 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14461                 "failed to expand attributes");
14462             }
14463             if (pctxt->attrProhibs->nbItems != 0)
14464                 prohibs = pctxt->attrProhibs;
14465         } else {
14466             if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14467                 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14468                 NULL) == -1)
14469             {
14470                 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14471                 "failed to expand attributes");
14472             }
14473         }
14474     }
14475     /*
14476     * Inherit the attribute uses of the base type.
14477     */
14478     if (baseUses != NULL) {
14479         int i, j;
14480         xmlSchemaAttributeUseProhibPtr pro;
14481
14482         if (WXS_IS_RESTRICTION(type)) {
14483             int usesCount;
14484             xmlSchemaAttributeUsePtr tmp;
14485
14486             if (uses != NULL)
14487                 usesCount = uses->nbItems;
14488             else
14489                 usesCount = 0;
14490
14491             /* Restriction. */
14492             for (i = 0; i < baseUses->nbItems; i++) {
14493                 use = baseUses->items[i];
14494                 if (prohibs) {
14495                     /*
14496                     * Filter out prohibited uses.
14497                     */
14498                     for (j = 0; j < prohibs->nbItems; j++) {
14499                         pro = prohibs->items[j];
14500                         if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14501                             (WXS_ATTRUSE_DECL_TNS(use) ==
14502                                 pro->targetNamespace))
14503                         {
14504                             goto inherit_next;
14505                         }
14506                     }
14507                 }
14508                 if (usesCount) {
14509                     /*
14510                     * Filter out existing uses.
14511                     */
14512                     for (j = 0; j < usesCount; j++) {
14513                         tmp = uses->items[j];
14514                         if ((WXS_ATTRUSE_DECL_NAME(use) ==
14515                                 WXS_ATTRUSE_DECL_NAME(tmp)) &&
14516                             (WXS_ATTRUSE_DECL_TNS(use) ==
14517                                 WXS_ATTRUSE_DECL_TNS(tmp)))
14518                         {
14519                             goto inherit_next;
14520                         }
14521                     }
14522                 }
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, 2, use);
14530 inherit_next: {}
14531             }
14532         } else {
14533             /* Extension. */
14534             for (i = 0; i < baseUses->nbItems; i++) {
14535                 use = baseUses->items[i];
14536                 if (uses == NULL) {
14537                     type->attrUses = xmlSchemaItemListCreate();
14538                     if (type->attrUses == NULL)
14539                         goto exit_failure;
14540                     uses = type->attrUses;
14541                 }
14542                 xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14543             }
14544         }
14545     }
14546     /*
14547     * Shrink attr. uses.
14548     */
14549     if (uses) {
14550         if (uses->nbItems == 0) {
14551             xmlSchemaItemListFree(uses);
14552             type->attrUses = NULL;
14553         }
14554         /*
14555         * TODO: We could shrink the size of the array
14556         * to fit the actual number of items.
14557         */
14558     }
14559     /*
14560     * Compute the complete wildcard.
14561     */
14562     if (WXS_IS_EXTENSION(type)) {
14563         if (baseType->attributeWildcard != NULL) {
14564             /*
14565             * (3.2.2.1) "If the `base wildcard` is non-`absent`, then
14566             * the appropriate case among the following:"
14567             */
14568             if (type->attributeWildcard != NULL) {
14569                 /*
14570                 * Union the complete wildcard with the base wildcard.
14571                 * SPEC {attribute wildcard}
14572                 * (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14573                 * and {annotation} are those of the `complete wildcard`,
14574                 * and whose {namespace constraint} is the intensional union
14575                 * of the {namespace constraint} of the `complete wildcard`
14576                 * and of the `base wildcard`, as defined in Attribute
14577                 * Wildcard Union ($3.10.6)."
14578                 */
14579                 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14580                     baseType->attributeWildcard) == -1)
14581                     goto exit_failure;
14582             } else {
14583                 /*
14584                 * (3.2.2.1.1) "If the `complete wildcard` is `absent`,
14585                 * then the `base wildcard`."
14586                 */
14587                 type->attributeWildcard = baseType->attributeWildcard;
14588             }
14589         } else {
14590             /*
14591             * (3.2.2.2) "otherwise (the `base wildcard` is `absent`) the
14592             * `complete wildcard`"
14593             * NOOP
14594             */
14595         }
14596     } else {
14597         /*
14598         * SPEC {attribute wildcard}
14599         * (3.1) "If the <restriction> alternative is chosen, then the
14600         * `complete wildcard`;"
14601         * NOOP
14602         */
14603     }
14604
14605     return (0);
14606
14607 exit_failure:
14608     return(-1);
14609 }
14610
14611 /**
14612  * xmlSchemaTypeFinalContains:
14613  * @schema:  the schema
14614  * @type:  the type definition
14615  * @final: the final
14616  *
14617  * Evaluates if a type definition contains the given "final".
14618  * This does take "finalDefault" into account as well.
14619  *
14620  * Returns 1 if the type does containt the given "final",
14621  * 0 otherwise.
14622  */
14623 static int
14624 xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
14625 {
14626     if (type == NULL)
14627         return (0);
14628     if (type->flags & final)
14629         return (1);
14630     else
14631         return (0);
14632 }
14633
14634 /**
14635  * xmlSchemaGetUnionSimpleTypeMemberTypes:
14636  * @type:  the Union Simple Type
14637  *
14638  * Returns a list of member types of @type if existing,
14639  * returns NULL otherwise.
14640  */
14641 static xmlSchemaTypeLinkPtr
14642 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14643 {
14644     while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
14645         if (type->memberTypes != NULL)
14646             return (type->memberTypes);
14647         else
14648             type = type->baseType;
14649     }
14650     return (NULL);
14651 }
14652
14653 /**
14654  * xmlSchemaGetParticleTotalRangeMin:
14655  * @particle: the particle
14656  *
14657  * Schema Component Constraint: Effective Total Range
14658  * (all and sequence) + (choice)
14659  *
14660  * Returns the minimun Effective Total Range.
14661  */
14662 static int
14663 xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
14664 {
14665     if ((particle->children == NULL) ||
14666         (particle->minOccurs == 0))
14667         return (0);
14668     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14669         int min = -1, cur;
14670         xmlSchemaParticlePtr part =
14671             (xmlSchemaParticlePtr) particle->children->children;
14672
14673         if (part == NULL)
14674             return (0);
14675         while (part != NULL) {
14676             if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14677                 (part->children->type == XML_SCHEMA_TYPE_ANY))
14678                 cur = part->minOccurs;
14679             else
14680                 cur = xmlSchemaGetParticleTotalRangeMin(part);
14681             if (cur == 0)
14682                 return (0);
14683             if ((min > cur) || (min == -1))
14684                 min = cur;
14685             part = (xmlSchemaParticlePtr) part->next;
14686         }
14687         return (particle->minOccurs * min);
14688     } else {
14689         /* <all> and <sequence> */
14690         int sum = 0;
14691         xmlSchemaParticlePtr part =
14692             (xmlSchemaParticlePtr) particle->children->children;
14693
14694         if (part == NULL)
14695             return (0);
14696         do {
14697             if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14698                 (part->children->type == XML_SCHEMA_TYPE_ANY))
14699                 sum += part->minOccurs;
14700             else
14701                 sum += xmlSchemaGetParticleTotalRangeMin(part);
14702             part = (xmlSchemaParticlePtr) part->next;
14703         } while (part != NULL);
14704         return (particle->minOccurs * sum);
14705     }
14706 }
14707
14708 #if 0
14709 /**
14710  * xmlSchemaGetParticleTotalRangeMax:
14711  * @particle: the particle
14712  *
14713  * Schema Component Constraint: Effective Total Range
14714  * (all and sequence) + (choice)
14715  *
14716  * Returns the maximum Effective Total Range.
14717  */
14718 static int
14719 xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14720 {
14721     if ((particle->children == NULL) ||
14722         (particle->children->children == NULL))
14723         return (0);
14724     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14725         int max = -1, cur;
14726         xmlSchemaParticlePtr part =
14727             (xmlSchemaParticlePtr) particle->children->children;
14728
14729         for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14730             if (part->children == NULL)
14731                 continue;
14732             if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14733                 (part->children->type == XML_SCHEMA_TYPE_ANY))
14734                 cur = part->maxOccurs;
14735             else
14736                 cur = xmlSchemaGetParticleTotalRangeMax(part);
14737             if (cur == UNBOUNDED)
14738                 return (UNBOUNDED);
14739             if ((max < cur) || (max == -1))
14740                 max = cur;
14741         }
14742         /* TODO: Handle overflows? */
14743         return (particle->maxOccurs * max);
14744     } else {
14745         /* <all> and <sequence> */
14746         int sum = 0, cur;
14747         xmlSchemaParticlePtr part =
14748             (xmlSchemaParticlePtr) particle->children->children;
14749
14750         for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14751             if (part->children == NULL)
14752                 continue;
14753             if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14754                 (part->children->type == XML_SCHEMA_TYPE_ANY))
14755                 cur = part->maxOccurs;
14756             else
14757                 cur = xmlSchemaGetParticleTotalRangeMax(part);
14758             if (cur == UNBOUNDED)
14759                 return (UNBOUNDED);
14760             if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14761                 return (UNBOUNDED);
14762             sum += cur;
14763         }
14764         /* TODO: Handle overflows? */
14765         return (particle->maxOccurs * sum);
14766     }
14767 }
14768 #endif
14769
14770 /**
14771  * xmlSchemaIsParticleEmptiable:
14772  * @particle: the particle
14773  *
14774  * Schema Component Constraint: Particle Emptiable
14775  * Checks whether the given particle is emptiable.
14776  *
14777  * Returns 1 if emptiable, 0 otherwise.
14778  */
14779 static int
14780 xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14781 {
14782     /*
14783     * SPEC (1) "Its {min occurs} is 0."
14784     */
14785     if ((particle == NULL) || (particle->minOccurs == 0) ||
14786         (particle->children == NULL))
14787         return (1);
14788     /*
14789     * SPEC (2) "Its {term} is a group and the minimum part of the
14790     * effective total range of that group, [...] is 0."
14791     */
14792     if (WXS_IS_MODEL_GROUP(particle->children)) {
14793         if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
14794             return (1);
14795     }
14796     return (0);
14797 }
14798
14799 /**
14800  * xmlSchemaCheckCOSSTDerivedOK:
14801  * @actxt: a context
14802  * @type:  the derived simple type definition
14803  * @baseType:  the base type definition
14804  * @subset: the subset of ('restriction', ect.)
14805  *
14806  * Schema Component Constraint:
14807  * Type Derivation OK (Simple) (cos-st-derived-OK)
14808  *
14809  * Checks wheter @type can be validly
14810  * derived from @baseType.
14811  *
14812  * Returns 0 on success, an positive error code otherwise.
14813  */
14814 static int
14815 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
14816                              xmlSchemaTypePtr type,
14817                              xmlSchemaTypePtr baseType,
14818                              int subset)
14819 {
14820     /*
14821     * 1 They are the same type definition.
14822     * TODO: The identy check might have to be more complex than this.
14823     */
14824     if (type == baseType)
14825         return (0);
14826     /*
14827     * 2.1 restriction is not in the subset, or in the {final}
14828     * of its own {base type definition};
14829     *
14830     * NOTE that this will be used also via "xsi:type".
14831     *
14832     * TODO: Revise this, it looks strange. How can the "type"
14833     * not be fixed or *in* fixing?
14834     */
14835     if (WXS_IS_TYPE_NOT_FIXED(type))
14836         if (xmlSchemaTypeFixup(type, actxt) == -1)
14837             return(-1);
14838     if (WXS_IS_TYPE_NOT_FIXED(baseType))
14839         if (xmlSchemaTypeFixup(baseType, actxt) == -1)
14840             return(-1);
14841     if ((subset & SUBSET_RESTRICTION) ||
14842         (xmlSchemaTypeFinalContains(type->baseType,
14843             XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14844         return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
14845     }
14846     /* 2.2 */
14847     if (type->baseType == baseType) {
14848         /*
14849         * 2.2.1 D's `base type definition` is B.
14850         */
14851         return (0);
14852     }
14853     /*
14854     * 2.2.2 D's `base type definition` is not the `ur-type definition`
14855     * and is validly derived from B given the subset, as defined by this
14856     * constraint.
14857     */
14858     if ((! WXS_IS_ANYTYPE(type->baseType)) &&
14859         (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
14860             baseType, subset) == 0)) {
14861         return (0);
14862     }
14863     /*
14864     * 2.2.3 D's {variety} is list or union and B is the `simple ur-type
14865     * definition`.
14866     */
14867     if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14868         (WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
14869         return (0);
14870     }
14871     /*
14872     * 2.2.4 B's {variety} is union and D is validly derived from a type
14873     * definition in B's {member type definitions} given the subset, as
14874     * defined by this constraint.
14875     *
14876     * NOTE: This seems not to involve built-in types, since there is no
14877     * built-in Union Simple Type.
14878     */
14879     if (WXS_IS_UNION(baseType)) {
14880         xmlSchemaTypeLinkPtr cur;
14881
14882         cur = baseType->memberTypes;
14883         while (cur != NULL) {
14884             if (WXS_IS_TYPE_NOT_FIXED(cur->type))
14885                 if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
14886                     return(-1);
14887             if (xmlSchemaCheckCOSSTDerivedOK(actxt,
14888                     type, cur->type, subset) == 0)
14889             {
14890                 /*
14891                 * It just has to be validly derived from at least one
14892                 * member-type.
14893                 */
14894                 return (0);
14895             }
14896             cur = cur->next;
14897         }
14898     }
14899     return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14900 }
14901
14902 /**
14903  * xmlSchemaCheckTypeDefCircularInternal:
14904  * @pctxt:  the schema parser context
14905  * @ctxtType:  the type definition
14906  * @ancestor: an ancestor of @ctxtType
14907  *
14908  * Checks st-props-correct (2) + ct-props-correct (3).
14909  * Circular type definitions are not allowed.
14910  *
14911  * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
14912  * circular, 0 otherwise.
14913  */
14914 static int
14915 xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14916                            xmlSchemaTypePtr ctxtType,
14917                            xmlSchemaTypePtr ancestor)
14918 {
14919     int ret;
14920
14921     if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14922         return (0);
14923
14924     if (ctxtType == ancestor) {
14925         xmlSchemaPCustomErr(pctxt,
14926             XML_SCHEMAP_ST_PROPS_CORRECT_2,
14927             WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
14928             "The definition is circular", NULL);
14929         return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14930     }
14931     if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14932         /*
14933         * Avoid inifinite recursion on circular types not yet checked.
14934         */
14935         return (0);
14936     }
14937     ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14938     ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14939         ancestor->baseType);
14940     ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14941     return (ret);
14942 }
14943
14944 /**
14945  * xmlSchemaCheckTypeDefCircular:
14946  * @item:  the complex/simple type definition
14947  * @ctxt:  the parser context
14948  * @name:  the name
14949  *
14950  * Checks for circular type definitions.
14951  */
14952 static void
14953 xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
14954                               xmlSchemaParserCtxtPtr ctxt)
14955 {
14956     if ((item == NULL) ||
14957         (item->type == XML_SCHEMA_TYPE_BASIC) ||
14958         (item->baseType == NULL))
14959         return;
14960     xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
14961         item->baseType);
14962 }
14963
14964 /*
14965 * Simple Type Definition Representation OK (src-simple-type) 4
14966 *
14967 * "4 Circular union type definition is disallowed. That is, if the
14968 * <union> alternative is chosen, there must not be any entries in the
14969 * memberTypes [attribute] at any depth which resolve to the component
14970 * corresponding to the <simpleType>."
14971 *
14972 * Note that this should work on the *representation* of a component,
14973 * thus assumes any union types in the member types not being yet
14974 * substituted. At this stage we need the variety of the types
14975 * to be already computed.
14976 */
14977 static int
14978 xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
14979                                         xmlSchemaTypePtr ctxType,
14980                                         xmlSchemaTypeLinkPtr members)
14981 {
14982     xmlSchemaTypeLinkPtr member;
14983     xmlSchemaTypePtr memberType;
14984
14985     member = members;
14986     while (member != NULL) {
14987         memberType = member->type;
14988         while ((memberType != NULL) &&
14989             (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
14990             if (memberType == ctxType) {
14991                 xmlSchemaPCustomErr(pctxt,
14992                     XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
14993                     WXS_BASIC_CAST ctxType, NULL,
14994                     "The union type definition is circular", NULL);
14995                 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
14996             }
14997             if ((WXS_IS_UNION(memberType)) &&
14998                 ((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
14999             {
15000                 int res;
15001                 memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
15002                 res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
15003                     ctxType,
15004                     xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
15005                 memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
15006                 if (res != 0)
15007                     return(res);
15008             }
15009             memberType = memberType->baseType;
15010         }
15011         member = member->next;
15012     }
15013     return(0);
15014 }
15015
15016 static int
15017 xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
15018                                    xmlSchemaTypePtr type)
15019 {
15020     if (! WXS_IS_UNION(type))
15021         return(0);
15022     return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
15023         type->memberTypes));
15024 }
15025
15026 /**
15027  * xmlSchemaResolveTypeReferences:
15028  * @item:  the complex/simple type definition
15029  * @ctxt:  the parser context
15030  * @name:  the name
15031  *
15032  * Resolvese type definition references
15033  */
15034 static void
15035 xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
15036                          xmlSchemaParserCtxtPtr ctxt)
15037 {
15038     if (typeDef == NULL)
15039         return;
15040
15041     /*
15042     * Resolve the base type.
15043     */
15044     if (typeDef->baseType == NULL) {
15045         typeDef->baseType = xmlSchemaGetType(ctxt->schema,
15046             typeDef->base, typeDef->baseNs);
15047         if (typeDef->baseType == NULL) {
15048             xmlSchemaPResCompAttrErr(ctxt,
15049                 XML_SCHEMAP_SRC_RESOLVE,
15050                 WXS_BASIC_CAST typeDef, typeDef->node,
15051                 "base", typeDef->base, typeDef->baseNs,
15052                 XML_SCHEMA_TYPE_SIMPLE, NULL);
15053             return;
15054         }
15055     }
15056     if (WXS_IS_SIMPLE(typeDef)) {
15057         if (WXS_IS_UNION(typeDef)) {
15058             /*
15059             * Resolve the memberTypes.
15060             */
15061             xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
15062             return;
15063         } else if (WXS_IS_LIST(typeDef)) {
15064             /*
15065             * Resolve the itemType.
15066             */
15067             if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
15068
15069                 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
15070                     typeDef->base, typeDef->baseNs);
15071
15072                 if ((typeDef->subtypes == NULL) ||
15073                     (! WXS_IS_SIMPLE(typeDef->subtypes)))
15074                 {
15075                     typeDef->subtypes = NULL;
15076                     xmlSchemaPResCompAttrErr(ctxt,
15077                         XML_SCHEMAP_SRC_RESOLVE,
15078                         WXS_BASIC_CAST typeDef, typeDef->node,
15079                         "itemType", typeDef->base, typeDef->baseNs,
15080                         XML_SCHEMA_TYPE_SIMPLE, NULL);
15081                 }
15082             }
15083             return;
15084         }
15085     }
15086     /*
15087     * The ball of letters below means, that if we have a particle
15088     * which has a QName-helper component as its {term}, we want
15089     * to resolve it...
15090     */
15091     else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
15092         ((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
15093             XML_SCHEMA_TYPE_PARTICLE) &&
15094         (WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
15095         ((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
15096             XML_SCHEMA_EXTRA_QNAMEREF))
15097     {
15098         xmlSchemaQNameRefPtr ref =
15099             WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
15100         xmlSchemaModelGroupDefPtr groupDef;
15101
15102         /*
15103         * URGENT TODO: Test this.
15104         */
15105         WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
15106         /*
15107         * Resolve the MG definition reference.
15108         */
15109         groupDef =
15110             WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
15111                 ref->itemType, ref->name, ref->targetNamespace);
15112         if (groupDef == NULL) {
15113             xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
15114                 NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
15115                 "ref", ref->name, ref->targetNamespace, ref->itemType,
15116                 NULL);
15117             /* Remove the particle. */
15118             WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15119         } else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
15120             /* Remove the particle. */
15121             WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15122         else {
15123             /*
15124             * Assign the MG definition's {model group} to the
15125             * particle's {term}.
15126             */
15127             WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
15128
15129             if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
15130                 /*
15131                 * SPEC cos-all-limited (1.2)
15132                 * "1.2 the {term} property of a particle with
15133                 * {max occurs}=1 which is part of a pair which constitutes
15134                 * the {content type} of a complex type definition."
15135                 */
15136                 if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
15137                     xmlSchemaCustomErr(ACTXT_CAST ctxt,
15138                         /* TODO: error code */
15139                         XML_SCHEMAP_COS_ALL_LIMITED,
15140                         WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
15141                         "The particle's {max occurs} must be 1, since the "
15142                         "reference resolves to an 'all' model group",
15143                         NULL, NULL);
15144                 }
15145             }
15146         }
15147     }
15148 }
15149
15150
15151
15152 /**
15153  * xmlSchemaCheckSTPropsCorrect:
15154  * @ctxt:  the schema parser context
15155  * @type:  the simple type definition
15156  *
15157  * Checks st-props-correct.
15158  *
15159  * Returns 0 if the properties are correct,
15160  * if not, a positive error code and -1 on internal
15161  * errors.
15162  */
15163 static int
15164 xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
15165                              xmlSchemaTypePtr type)
15166 {
15167     xmlSchemaTypePtr baseType = type->baseType;
15168     xmlChar *str = NULL;
15169
15170     /* STATE: error funcs converted. */
15171     /*
15172     * Schema Component Constraint: Simple Type Definition Properties Correct
15173     *
15174     * NOTE: This is somehow redundant, since we actually built a simple type
15175     * to have all the needed information; this acts as an self test.
15176     */
15177     /* Base type: If the datatype has been `derived` by `restriction`
15178     * then the Simple Type Definition component from which it is `derived`,
15179     * otherwise the Simple Type Definition for anySimpleType ($4.1.6).
15180     */
15181     if (baseType == NULL) {
15182         /*
15183         * TODO: Think about: "modulo the impact of Missing
15184         * Sub-components ($5.3)."
15185         */
15186         xmlSchemaPCustomErr(ctxt,
15187             XML_SCHEMAP_ST_PROPS_CORRECT_1,
15188             WXS_BASIC_CAST type, NULL,
15189             "No base type existent", NULL);
15190         return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15191
15192     }
15193     if (! WXS_IS_SIMPLE(baseType)) {
15194         xmlSchemaPCustomErr(ctxt,
15195             XML_SCHEMAP_ST_PROPS_CORRECT_1,
15196             WXS_BASIC_CAST type, NULL,
15197             "The base type '%s' is not a simple type",
15198             xmlSchemaGetComponentQName(&str, baseType));
15199         FREE_AND_NULL(str)
15200         return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15201     }
15202     if ((WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
15203         (WXS_IS_RESTRICTION(type) == 0) &&
15204         ((! WXS_IS_ANY_SIMPLE_TYPE(baseType)) &&
15205          (baseType->type != XML_SCHEMA_TYPE_SIMPLE))) {
15206         xmlSchemaPCustomErr(ctxt,
15207             XML_SCHEMAP_ST_PROPS_CORRECT_1,
15208             WXS_BASIC_CAST type, NULL,
15209             "A type, derived by list or union, must have "
15210             "the simple ur-type definition as base type, not '%s'",
15211             xmlSchemaGetComponentQName(&str, baseType));
15212         FREE_AND_NULL(str)
15213         return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15214     }
15215     /*
15216     * Variety: One of {atomic, list, union}.
15217     */
15218     if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15219         (! WXS_IS_LIST(type))) {
15220         xmlSchemaPCustomErr(ctxt,
15221             XML_SCHEMAP_ST_PROPS_CORRECT_1,
15222             WXS_BASIC_CAST type, NULL,
15223             "The variety is absent", NULL);
15224         return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15225     }
15226     /* TODO: Finish this. Hmm, is this finished? */
15227
15228     /*
15229     * 3 The {final} of the {base type definition} must not contain restriction.
15230     */
15231     if (xmlSchemaTypeFinalContains(baseType,
15232         XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15233         xmlSchemaPCustomErr(ctxt,
15234             XML_SCHEMAP_ST_PROPS_CORRECT_3,
15235             WXS_BASIC_CAST type, NULL,
15236             "The 'final' of its base type '%s' must not contain "
15237             "'restriction'",
15238             xmlSchemaGetComponentQName(&str, baseType));
15239         FREE_AND_NULL(str)
15240         return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
15241     }
15242
15243     /*
15244     * 2 All simple type definitions must be derived ultimately from the `simple
15245     * ur-type definition` (so circular definitions are disallowed). That is, it
15246     * must be possible to reach a built-in primitive datatype or the `simple
15247     * ur-type definition` by repeatedly following the {base type definition}.
15248     *
15249     * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
15250     */
15251     return (0);
15252 }
15253
15254 /**
15255  * xmlSchemaCheckCOSSTRestricts:
15256  * @ctxt:  the schema parser context
15257  * @type:  the simple type definition
15258  *
15259  * Schema Component Constraint:
15260  * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15261
15262  * Checks if the given @type (simpleType) is derived validly by restriction.
15263  * STATUS:
15264  *
15265  * Returns -1 on internal errors, 0 if the type is validly derived,
15266  * a positive error code otherwise.
15267  */
15268 static int
15269 xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
15270                              xmlSchemaTypePtr type)
15271 {
15272     xmlChar *str = NULL;
15273
15274     if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
15275         PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15276             "given type is not a user-derived simpleType");
15277         return (-1);
15278     }
15279
15280     if (WXS_IS_ATOMIC(type)) {
15281         xmlSchemaTypePtr primitive;
15282         /*
15283         * 1.1 The {base type definition} must be an atomic simple
15284         * type definition or a built-in primitive datatype.
15285         */
15286         if (! WXS_IS_ATOMIC(type->baseType)) {
15287             xmlSchemaPCustomErr(pctxt,
15288                 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
15289                 WXS_BASIC_CAST type, NULL,
15290                 "The base type '%s' is not an atomic simple type",
15291                 xmlSchemaGetComponentQName(&str, type->baseType));
15292             FREE_AND_NULL(str)
15293             return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15294         }
15295         /* 1.2 The {final} of the {base type definition} must not contain
15296         * restriction.
15297         */
15298         /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
15299         if (xmlSchemaTypeFinalContains(type->baseType,
15300             XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15301             xmlSchemaPCustomErr(pctxt,
15302                 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
15303                 WXS_BASIC_CAST type, NULL,
15304                 "The final of its base type '%s' must not contain 'restriction'",
15305                 xmlSchemaGetComponentQName(&str, type->baseType));
15306             FREE_AND_NULL(str)
15307             return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15308         }
15309
15310         /*
15311         * 1.3.1 DF must be an allowed constraining facet for the {primitive
15312         * type definition}, as specified in the appropriate subsection of 3.2
15313         * Primitive datatypes.
15314         */
15315         if (type->facets != NULL) {
15316             xmlSchemaFacetPtr facet;
15317             int ok = 1;
15318
15319             primitive = xmlSchemaGetPrimitiveType(type);
15320             if (primitive == NULL) {
15321                 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15322                     "failed to get primitive type");
15323                 return (-1);
15324             }
15325             facet = type->facets;
15326             do {
15327                 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
15328                     ok = 0;
15329                     xmlSchemaPIllegalFacetAtomicErr(pctxt,
15330                         XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
15331                         type, primitive, facet);
15332                 }
15333                 facet = facet->next;
15334             } while (facet != NULL);
15335             if (ok == 0)
15336                 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
15337         }
15338         /*
15339         * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15340         * of the {base type definition} (call this BF),then the DF's {value}
15341         * must be a valid restriction of BF's {value} as defined in
15342         * [XML Schemas: Datatypes]."
15343         *
15344         * NOTE (1.3.2) Facet derivation constraints are currently handled in
15345         * xmlSchemaDeriveAndValidateFacets()
15346         */
15347     } else if (WXS_IS_LIST(type)) {
15348         xmlSchemaTypePtr itemType = NULL;
15349
15350         itemType = type->subtypes;
15351         if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
15352             PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15353                 "failed to evaluate the item type");
15354             return (-1);
15355         }
15356         if (WXS_IS_TYPE_NOT_FIXED(itemType))
15357             xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
15358         /*
15359         * 2.1 The {item type definition} must have a {variety} of atomic or
15360         * union (in which case all the {member type definitions}
15361         * must be atomic).
15362         */
15363         if ((! WXS_IS_ATOMIC(itemType)) &&
15364             (! WXS_IS_UNION(itemType))) {
15365             xmlSchemaPCustomErr(pctxt,
15366                 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15367                 WXS_BASIC_CAST type, NULL,
15368                 "The item type '%s' does not have a variety of atomic or union",
15369                 xmlSchemaGetComponentQName(&str, itemType));
15370             FREE_AND_NULL(str)
15371             return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15372         } else if (WXS_IS_UNION(itemType)) {
15373             xmlSchemaTypeLinkPtr member;
15374
15375             member = itemType->memberTypes;
15376             while (member != NULL) {
15377                 if (! WXS_IS_ATOMIC(member->type)) {
15378                     xmlSchemaPCustomErr(pctxt,
15379                         XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15380                         WXS_BASIC_CAST type, NULL,
15381                         "The item type is a union type, but the "
15382                         "member type '%s' of this item type is not atomic",
15383                         xmlSchemaGetComponentQName(&str, member->type));
15384                     FREE_AND_NULL(str)
15385                     return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15386                 }
15387                 member = member->next;
15388             }
15389         }
15390
15391         if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
15392             xmlSchemaFacetPtr facet;
15393             /*
15394             * This is the case if we have: <simpleType><list ..
15395             */
15396             /*
15397             * 2.3.1
15398             * 2.3.1.1 The {final} of the {item type definition} must not
15399             * contain list.
15400             */
15401             if (xmlSchemaTypeFinalContains(itemType,
15402                 XML_SCHEMAS_TYPE_FINAL_LIST)) {
15403                 xmlSchemaPCustomErr(pctxt,
15404                     XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
15405                     WXS_BASIC_CAST type, NULL,
15406                     "The final of its item type '%s' must not contain 'list'",
15407                     xmlSchemaGetComponentQName(&str, itemType));
15408                 FREE_AND_NULL(str)
15409                 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15410             }
15411             /*
15412             * 2.3.1.2 The {facets} must only contain the whiteSpace
15413             * facet component.
15414             * OPTIMIZE TODO: the S4S already disallows any facet
15415             * to be specified.
15416             */
15417             if (type->facets != NULL) {
15418                 facet = type->facets;
15419                 do {
15420                     if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15421                         xmlSchemaPIllegalFacetListUnionErr(pctxt,
15422                             XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
15423                             type, facet);
15424                         return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15425                     }
15426                     facet = facet->next;
15427                 } while (facet != NULL);
15428             }
15429             /*
15430             * MAYBE TODO: (Hmm, not really) Datatypes states:
15431             * A `list` datatype can be `derived` from an `atomic` datatype
15432             * whose `lexical space` allows space (such as string or anyURI)or
15433             * a `union` datatype any of whose {member type definitions}'s
15434             * `lexical space` allows space.
15435             */
15436         } else {
15437             /*
15438             * This is the case if we have: <simpleType><restriction ...
15439             * I.e. the variety of "list" is inherited.
15440             */
15441             /*
15442             * 2.3.2
15443             * 2.3.2.1 The {base type definition} must have a {variety} of list.
15444             */
15445             if (! WXS_IS_LIST(type->baseType)) {
15446                 xmlSchemaPCustomErr(pctxt,
15447                     XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
15448                     WXS_BASIC_CAST type, NULL,
15449                     "The base type '%s' must be a list type",
15450                     xmlSchemaGetComponentQName(&str, type->baseType));
15451                 FREE_AND_NULL(str)
15452                 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15453             }
15454             /*
15455             * 2.3.2.2 The {final} of the {base type definition} must not
15456             * contain restriction.
15457             */
15458             if (xmlSchemaTypeFinalContains(type->baseType,
15459                 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15460                 xmlSchemaPCustomErr(pctxt,
15461                     XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
15462                     WXS_BASIC_CAST type, NULL,
15463                     "The 'final' of the base type '%s' must not contain 'restriction'",
15464                     xmlSchemaGetComponentQName(&str, type->baseType));
15465                 FREE_AND_NULL(str)
15466                 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15467             }
15468             /*
15469             * 2.3.2.3 The {item type definition} must be validly derived
15470             * from the {base type definition}'s {item type definition} given
15471             * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6).
15472             */
15473             {
15474                 xmlSchemaTypePtr baseItemType;
15475
15476                 baseItemType = type->baseType->subtypes;
15477                 if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
15478                     PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15479                         "failed to eval the item type of a base type");
15480                     return (-1);
15481                 }
15482                 if ((itemType != baseItemType) &&
15483                     (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
15484                         baseItemType, 0) != 0)) {
15485                     xmlChar *strBIT = NULL, *strBT = NULL;
15486                     xmlSchemaPCustomErrExt(pctxt,
15487                         XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
15488                         WXS_BASIC_CAST type, NULL,
15489                         "The item type '%s' is not validly derived from "
15490                         "the item type '%s' of the base type '%s'",
15491                         xmlSchemaGetComponentQName(&str, itemType),
15492                         xmlSchemaGetComponentQName(&strBIT, baseItemType),
15493                         xmlSchemaGetComponentQName(&strBT, type->baseType));
15494
15495                     FREE_AND_NULL(str)
15496                     FREE_AND_NULL(strBIT)
15497                     FREE_AND_NULL(strBT)
15498                     return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15499                 }
15500             }
15501
15502             if (type->facets != NULL) {
15503                 xmlSchemaFacetPtr facet;
15504                 int ok = 1;
15505                 /*
15506                 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
15507                 * and enumeration facet components are allowed among the {facets}.
15508                 */
15509                 facet = type->facets;
15510                 do {
15511                     switch (facet->type) {
15512                         case XML_SCHEMA_FACET_LENGTH:
15513                         case XML_SCHEMA_FACET_MINLENGTH:
15514                         case XML_SCHEMA_FACET_MAXLENGTH:
15515                         case XML_SCHEMA_FACET_WHITESPACE:
15516                             /*
15517                             * TODO: 2.5.1.2 List datatypes
15518                             * The value of `whiteSpace` is fixed to the value collapse.
15519                             */
15520                         case XML_SCHEMA_FACET_PATTERN:
15521                         case XML_SCHEMA_FACET_ENUMERATION:
15522                             break;
15523                         default: {
15524                             xmlSchemaPIllegalFacetListUnionErr(pctxt,
15525                                 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
15526                                 type, facet);
15527                             /*
15528                             * We could return, but it's nicer to report all
15529                             * invalid facets.
15530                             */
15531                             ok = 0;
15532                         }
15533                     }
15534                     facet = facet->next;
15535                 } while (facet != NULL);
15536                 if (ok == 0)
15537                     return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15538                 /*
15539                 * SPEC (2.3.2.5) (same as 1.3.2)
15540                 *
15541                 * NOTE (2.3.2.5) This is currently done in
15542                 * xmlSchemaDeriveAndValidateFacets()
15543                 */
15544             }
15545         }
15546     } else if (WXS_IS_UNION(type)) {
15547         /*
15548         * 3.1 The {member type definitions} must all have {variety} of
15549         * atomic or list.
15550         */
15551         xmlSchemaTypeLinkPtr member;
15552
15553         member = type->memberTypes;
15554         while (member != NULL) {
15555             if (WXS_IS_TYPE_NOT_FIXED(member->type))
15556                 xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
15557
15558             if ((! WXS_IS_ATOMIC(member->type)) &&
15559                 (! WXS_IS_LIST(member->type))) {
15560                 xmlSchemaPCustomErr(pctxt,
15561                     XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
15562                     WXS_BASIC_CAST type, NULL,
15563                     "The member type '%s' is neither an atomic, nor a list type",
15564                     xmlSchemaGetComponentQName(&str, member->type));
15565                 FREE_AND_NULL(str)
15566                 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15567             }
15568             member = member->next;
15569         }
15570         /*
15571         * 3.3.1 If the {base type definition} is the `simple ur-type
15572         * definition`
15573         */
15574         if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
15575             /*
15576             * 3.3.1.1 All of the {member type definitions} must have a
15577             * {final} which does not contain union.
15578             */
15579             member = type->memberTypes;
15580             while (member != NULL) {
15581                 if (xmlSchemaTypeFinalContains(member->type,
15582                     XML_SCHEMAS_TYPE_FINAL_UNION)) {
15583                     xmlSchemaPCustomErr(pctxt,
15584                         XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
15585                         WXS_BASIC_CAST type, NULL,
15586                         "The 'final' of member type '%s' contains 'union'",
15587                         xmlSchemaGetComponentQName(&str, member->type));
15588                     FREE_AND_NULL(str)
15589                     return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15590                 }
15591                 member = member->next;
15592             }
15593             /*
15594             * 3.3.1.2 The {facets} must be empty.
15595             */
15596             if (type->facetSet != NULL) {
15597                 xmlSchemaPCustomErr(pctxt,
15598                     XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
15599                     WXS_BASIC_CAST type, NULL,
15600                     "No facets allowed", NULL);
15601                 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15602             }
15603         } else {
15604             /*
15605             * 3.3.2.1 The {base type definition} must have a {variety} of union.
15606             * I.e. the variety of "list" is inherited.
15607             */
15608             if (! WXS_IS_UNION(type->baseType)) {
15609                 xmlSchemaPCustomErr(pctxt,
15610                     XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
15611                     WXS_BASIC_CAST type, NULL,
15612                     "The base type '%s' is not a union type",
15613                     xmlSchemaGetComponentQName(&str, type->baseType));
15614                 FREE_AND_NULL(str)
15615                 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15616             }
15617             /*
15618             * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15619             */
15620             if (xmlSchemaTypeFinalContains(type->baseType,
15621                 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15622                 xmlSchemaPCustomErr(pctxt,
15623                     XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
15624                     WXS_BASIC_CAST type, NULL,
15625                     "The 'final' of its base type '%s' must not contain 'restriction'",
15626                     xmlSchemaGetComponentQName(&str, type->baseType));
15627                 FREE_AND_NULL(str)
15628                 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15629             }
15630             /*
15631             * 3.3.2.3 The {member type definitions}, in order, must be validly
15632             * derived from the corresponding type definitions in the {base
15633             * type definition}'s {member type definitions} given the empty set,
15634             * as defined in Type Derivation OK (Simple) ($3.14.6).
15635             */
15636             {
15637                 xmlSchemaTypeLinkPtr baseMember;
15638
15639                 /*
15640                 * OPTIMIZE: if the type is restricting, it has no local defined
15641                 * member types and inherits the member types of the base type;
15642                 * thus a check for equality can be skipped.
15643                 */
15644                 /*
15645                 * Even worse: I cannot see a scenario where a restricting
15646                 * union simple type can have other member types as the member
15647                 * types of it's base type. This check seems not necessary with
15648                 * respect to the derivation process in libxml2.
15649                 * But necessary if constructing types with an API.
15650                 */
15651                 if (type->memberTypes != NULL) {
15652                     member = type->memberTypes;
15653                     baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
15654                     if ((member == NULL) && (baseMember != NULL)) {
15655                         PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15656                             "different number of member types in base");
15657                     }
15658                     while (member != NULL) {
15659                         if (baseMember == NULL) {
15660                             PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15661                             "different number of member types in base");
15662                         } else if ((member->type != baseMember->type) &&
15663                             (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
15664                                 member->type, baseMember->type, 0) != 0)) {
15665                             xmlChar *strBMT = NULL, *strBT = NULL;
15666
15667                             xmlSchemaPCustomErrExt(pctxt,
15668                                 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
15669                                 WXS_BASIC_CAST type, NULL,
15670                                 "The member type %s is not validly "
15671                                 "derived from its corresponding member "
15672                                 "type %s of the base type %s",
15673                                 xmlSchemaGetComponentQName(&str, member->type),
15674                                 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15675                                 xmlSchemaGetComponentQName(&strBT, type->baseType));
15676                             FREE_AND_NULL(str)
15677                             FREE_AND_NULL(strBMT)
15678                             FREE_AND_NULL(strBT)
15679                             return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
15680                         }
15681                         member = member->next;
15682                         if (baseMember != NULL)
15683                             baseMember = baseMember->next;
15684                     }
15685                 }
15686             }
15687             /*
15688             * 3.3.2.4 Only pattern and enumeration facet components are
15689             * allowed among the {facets}.
15690             */
15691             if (type->facets != NULL) {
15692                 xmlSchemaFacetPtr facet;
15693                 int ok = 1;
15694
15695                 facet = type->facets;
15696                 do {
15697                     if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15698                         (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
15699                         xmlSchemaPIllegalFacetListUnionErr(pctxt,
15700                                 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
15701                                 type, facet);
15702                         ok = 0;
15703                     }
15704                     facet = facet->next;
15705                 } while (facet != NULL);
15706                 if (ok == 0)
15707                     return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
15708
15709             }
15710             /*
15711             * SPEC (3.3.2.5) (same as 1.3.2)
15712             *
15713             * NOTE (3.3.2.5) This is currently done in
15714             * xmlSchemaDeriveAndValidateFacets()
15715             */
15716         }
15717     }
15718
15719     return (0);
15720 }
15721
15722 /**
15723  * xmlSchemaCheckSRCSimpleType:
15724  * @ctxt:  the schema parser context
15725  * @type:  the simple type definition
15726  *
15727  * Checks crc-simple-type constraints.
15728  *
15729  * Returns 0 if the constraints are satisfied,
15730  * if not a positive error code and -1 on internal
15731  * errors.
15732  */
15733 #if 0
15734 static int
15735 xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15736                             xmlSchemaTypePtr type)
15737 {
15738     /*
15739     * src-simple-type.1 The corresponding simple type definition, if any,
15740     * must satisfy the conditions set out in Constraints on Simple Type
15741     * Definition Schema Components ($3.14.6).
15742     */
15743     if (WXS_IS_RESTRICTION(type)) {
15744         /*
15745         * src-simple-type.2 "If the <restriction> alternative is chosen,
15746         * either it must have a base [attribute] or a <simpleType> among its
15747         * [children], but not both."
15748         * NOTE: This is checked in the parse function of <restriction>.
15749         */
15750         /*
15751         *
15752         */
15753     } else if (WXS_IS_LIST(type)) {
15754         /* src-simple-type.3 "If the <list> alternative is chosen, either it must have
15755         * an itemType [attribute] or a <simpleType> among its [children],
15756         * but not both."
15757         *
15758         * NOTE: This is checked in the parse function of <list>.
15759         */
15760     } else if (WXS_IS_UNION(type)) {
15761         /*
15762         * src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
15763         */
15764     }
15765     return (0);
15766 }
15767 #endif
15768
15769 static int
15770 xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15771 {
15772    if (ctxt->vctxt == NULL) {
15773         ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15774         if (ctxt->vctxt == NULL) {
15775             xmlSchemaPErr(ctxt, NULL,
15776                 XML_SCHEMAP_INTERNAL,
15777                 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
15778                 "failed to create a temp. validation context.\n",
15779                 NULL, NULL);
15780             return (-1);
15781         }
15782         /* TODO: Pass user data. */
15783         xmlSchemaSetValidErrors(ctxt->vctxt,
15784             ctxt->error, ctxt->warning, ctxt->errCtxt);
15785         xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15786             ctxt->serror, ctxt->errCtxt);
15787     }
15788     return (0);
15789 }
15790
15791 static int
15792 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15793                              xmlNodePtr node,
15794                              xmlSchemaTypePtr type,
15795                              const xmlChar *value,
15796                              xmlSchemaValPtr *retVal,
15797                              int fireErrors,
15798                              int normalize,
15799                              int isNormalized);
15800
15801 /**
15802  * xmlSchemaParseCheckCOSValidDefault:
15803  * @pctxt:  the schema parser context
15804  * @type:  the simple type definition
15805  * @value: the default value
15806  * @node: an optional node (the holder of the value)
15807  *
15808  * Schema Component Constraint: Element Default Valid (Immediate)
15809  * (cos-valid-default)
15810  * This will be used by the parser only. For the validator there's
15811  * an other version.
15812  *
15813  * Returns 0 if the constraints are satisfied,
15814  * if not, a positive error code and -1 on internal
15815  * errors.
15816  */
15817 static int
15818 xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15819                                    xmlNodePtr node,
15820                                    xmlSchemaTypePtr type,
15821                                    const xmlChar *value,
15822                                    xmlSchemaValPtr *val)
15823 {
15824     int ret = 0;
15825
15826     /*
15827     * cos-valid-default:
15828     * Schema Component Constraint: Element Default Valid (Immediate)
15829     * For a string to be a valid default with respect to a type
15830     * definition the appropriate case among the following must be true:
15831     */
15832     if WXS_IS_COMPLEX(type) {
15833         /*
15834         * Complex type.
15835         *
15836         * SPEC (2.1) "its {content type} must be a simple type definition
15837         * or mixed."
15838         * SPEC (2.2.2) "If the {content type} is mixed, then the {content
15839         * type}'s particle must be `emptiable` as defined by
15840         * Particle Emptiable ($3.9.6)."
15841         */
15842         if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15843             ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
15844             /* NOTE that this covers (2.2.2) as well. */
15845             xmlSchemaPCustomErr(pctxt,
15846                 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
15847                 WXS_BASIC_CAST type, type->node,
15848                 "For a string to be a valid default, the type definition "
15849                 "must be a simple type or a complex type with mixed content "
15850                 "and a particle emptiable", NULL);
15851             return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15852         }
15853     }
15854     /*
15855     * 1 If the type definition is a simple type definition, then the string
15856     * must be `valid` with respect to that definition as defined by String
15857     * Valid ($3.14.4).
15858     *
15859     * AND
15860     *
15861     * 2.2.1 If the {content type} is a simple type definition, then the
15862     * string must be `valid` with respect to that simple type definition
15863     * as defined by String Valid ($3.14.4).
15864     */
15865     if (WXS_IS_SIMPLE(type))
15866         ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15867             type, value, val, 1, 1, 0);
15868     else if (WXS_HAS_SIMPLE_CONTENT(type))
15869         ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15870             type->contentTypeDef, value, val, 1, 1, 0);
15871     else
15872         return (ret);
15873
15874     if (ret < 0) {
15875         PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15876             "calling xmlSchemaVCheckCVCSimpleType()");
15877     }
15878
15879     return (ret);
15880 }
15881
15882 /**
15883  * xmlSchemaCheckCTPropsCorrect:
15884  * @ctxt:  the schema parser context
15885  * @type:  the complex type definition
15886  *
15887  *.(4.6) Constraints on Complex Type Definition Schema Components
15888  * Schema Component Constraint:
15889  * Complex Type Definition Properties Correct (ct-props-correct)
15890  * STATUS: (seems) complete
15891  *
15892  * Returns 0 if the constraints are satisfied, a positive
15893  * error code if not and -1 if an internal error occured.
15894  */
15895 static int
15896 xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15897                              xmlSchemaTypePtr type)
15898 {
15899     /*
15900     * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15901     *
15902     * SPEC (1) "The values of the properties of a complex type definition must
15903     * be as described in the property tableau in The Complex Type Definition
15904     * Schema Component ($3.4.1), modulo the impact of Missing
15905     * Sub-components ($5.3)."
15906     */
15907     if ((type->baseType != NULL) &&
15908         (WXS_IS_SIMPLE(type->baseType)) &&
15909         (WXS_IS_EXTENSION(type) == 0)) {
15910         /*
15911         * SPEC (2) "If the {base type definition} is a simple type definition,
15912         * the {derivation method} must be extension."
15913         */
15914         xmlSchemaCustomErr(ACTXT_CAST pctxt,
15915             XML_SCHEMAP_SRC_CT_1,
15916             NULL, WXS_BASIC_CAST type,
15917             "If the base type is a simple type, the derivation method must be "
15918             "'extension'", NULL, NULL);
15919         return (XML_SCHEMAP_SRC_CT_1);
15920     }
15921     /*
15922     * SPEC (3) "Circular definitions are disallowed, except for the `ur-type
15923     * definition`. That is, it must be possible to reach the `ur-type
15924     * definition` by repeatedly following the {base type definition}."
15925     *
15926     * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
15927     */
15928     /*
15929     * NOTE that (4) and (5) need the following:
15930     *   - attribute uses need to be already inherited (apply attr. prohibitions)
15931     *   - attribute group references need to be expanded already
15932     *   - simple types need to be typefixed already
15933     */
15934     if (type->attrUses &&
15935         (((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15936     {
15937         xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15938         xmlSchemaAttributeUsePtr use, tmp;
15939         int i, j, hasId = 0;
15940
15941         for (i = uses->nbItems -1; i >= 0; i--) {
15942             use = uses->items[i];
15943
15944             /*
15945             * SPEC ct-props-correct
15946             * (4) "Two distinct attribute declarations in the
15947             * {attribute uses} must not have identical {name}s and
15948             * {target namespace}s."
15949             */
15950             if (i > 0) {
15951                 for (j = i -1; j >= 0; j--) {
15952                     tmp = uses->items[j];
15953                     if ((WXS_ATTRUSE_DECL_NAME(use) ==
15954                         WXS_ATTRUSE_DECL_NAME(tmp)) &&
15955                         (WXS_ATTRUSE_DECL_TNS(use) ==
15956                         WXS_ATTRUSE_DECL_TNS(tmp)))
15957                     {
15958                         xmlChar *str = NULL;
15959
15960                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
15961                             XML_SCHEMAP_AG_PROPS_CORRECT,
15962                             NULL, WXS_BASIC_CAST type,
15963                             "Duplicate %s",
15964                             xmlSchemaGetComponentDesignation(&str, use),
15965                             NULL);
15966                         FREE_AND_NULL(str);
15967                         /*
15968                         * Remove the duplicate.
15969                         */
15970                         if (xmlSchemaItemListRemove(uses, i) == -1)
15971                             goto exit_failure;
15972                         goto next_use;
15973                     }
15974                 }
15975             }
15976             /*
15977             * SPEC ct-props-correct
15978             * (5) "Two distinct attribute declarations in the
15979             * {attribute uses} must not have {type definition}s which
15980             * are or are derived from ID."
15981             */
15982             if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15983                 if (xmlSchemaIsDerivedFromBuiltInType(
15984                     WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
15985                 {
15986                     if (hasId) {
15987                         xmlChar *str = NULL;
15988
15989                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
15990                             XML_SCHEMAP_AG_PROPS_CORRECT,
15991                             NULL, WXS_BASIC_CAST type,
15992                             "There must not exist more than one attribute "
15993                             "declaration of type 'xs:ID' "
15994                             "(or derived from 'xs:ID'). The %s violates this "
15995                             "constraint",
15996                             xmlSchemaGetComponentDesignation(&str, use),
15997                             NULL);
15998                         FREE_AND_NULL(str);
15999                         if (xmlSchemaItemListRemove(uses, i) == -1)
16000                             goto exit_failure;
16001                     }
16002
16003                     hasId = 1;
16004                 }
16005             }
16006 next_use: {}
16007         }
16008     }
16009     return (0);
16010 exit_failure:
16011     return(-1);
16012 }
16013
16014 static int
16015 xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
16016                        xmlSchemaTypePtr typeB)
16017 {
16018     /*
16019     * TODO: This should implement component-identity
16020     * in the future.
16021     */
16022     if ((typeA == NULL) || (typeB == NULL))
16023         return (0);
16024     return (typeA == typeB);
16025 }
16026
16027 /**
16028  * xmlSchemaCheckCOSCTDerivedOK:
16029  * @ctxt:  the schema parser context
16030  * @type:  the to-be derived complex type definition
16031  * @baseType:  the base complex type definition
16032  * @set: the given set
16033  *
16034  * Schema Component Constraint:
16035  * Type Derivation OK (Complex) (cos-ct-derived-ok)
16036  *
16037  * STATUS: completed
16038  *
16039  * Returns 0 if the constraints are satisfied, or 1
16040  * if not.
16041  */
16042 static int
16043 xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16044                              xmlSchemaTypePtr type,
16045                              xmlSchemaTypePtr baseType,
16046                              int set)
16047 {
16048     int equal = xmlSchemaAreEqualTypes(type, baseType);
16049     /* TODO: Error codes. */
16050     /*
16051     * SPEC "For a complex type definition (call it D, for derived)
16052     * to be validly derived from a type definition (call this
16053     * B, for base) given a subset of {extension, restriction}
16054     * all of the following must be true:"
16055     */
16056     if (! equal) {
16057         /*
16058         * SPEC (1) "If B and D are not the same type definition, then the
16059         * {derivation method} of D must not be in the subset."
16060         */
16061         if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
16062             ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
16063             return (1);
16064     } else {
16065         /*
16066         * SPEC (2.1) "B and D must be the same type definition."
16067         */
16068         return (0);
16069     }
16070     /*
16071     * SPEC (2.2) "B must be D's {base type definition}."
16072     */
16073     if (type->baseType == baseType)
16074         return (0);
16075     /*
16076     * SPEC (2.3.1) "D's {base type definition} must not be the `ur-type
16077     * definition`."
16078     */
16079     if (WXS_IS_ANYTYPE(type->baseType))
16080         return (1);
16081
16082     if (WXS_IS_COMPLEX(type->baseType)) {
16083         /*
16084         * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
16085         * must be validly derived from B given the subset as defined by this
16086         * constraint."
16087         */
16088         return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
16089             baseType, set));
16090     } else {
16091         /*
16092         * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
16093         * must be validly derived from B given the subset as defined in Type
16094         * Derivation OK (Simple) ($3.14.6).
16095         */
16096         return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
16097             baseType, set));
16098     }
16099 }
16100
16101 /**
16102  * xmlSchemaCheckCOSDerivedOK:
16103  * @type:  the derived simple type definition
16104  * @baseType:  the base type definition
16105  *
16106  * Calls:
16107  * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
16108  *
16109  * Checks wheter @type can be validly derived from @baseType.
16110  *
16111  * Returns 0 on success, an positive error code otherwise.
16112  */
16113 static int
16114 xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16115                            xmlSchemaTypePtr type,
16116                            xmlSchemaTypePtr baseType,
16117                            int set)
16118 {
16119     if (WXS_IS_SIMPLE(type))
16120         return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
16121     else
16122         return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
16123 }
16124
16125 /**
16126  * xmlSchemaCheckCOSCTExtends:
16127  * @ctxt:  the schema parser context
16128  * @type:  the complex type definition
16129  *
16130  * (3.4.6) Constraints on Complex Type Definition Schema Components
16131  * Schema Component Constraint:
16132  * Derivation Valid (Extension) (cos-ct-extends)
16133  *
16134  * STATUS:
16135  *   missing:
16136  *     (1.5)
16137  *     (1.4.3.2.2.2) "Particle Valid (Extension)"
16138  *
16139  * Returns 0 if the constraints are satisfied, a positive
16140  * error code if not and -1 if an internal error occured.
16141  */
16142 static int
16143 xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16144                            xmlSchemaTypePtr type)
16145 {
16146     xmlSchemaTypePtr base = type->baseType;
16147     /*
16148     * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16149     * temporarily only.
16150     */
16151     /*
16152     * SPEC (1) "If the {base type definition} is a complex type definition,
16153     * then all of the following must be true:"
16154     */
16155     if (WXS_IS_COMPLEX(base)) {
16156         /*
16157         * SPEC (1.1) "The {final} of the {base type definition} must not
16158         * contain extension."
16159         */
16160         if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16161             xmlSchemaPCustomErr(ctxt,
16162                 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16163                 WXS_BASIC_CAST type, NULL,
16164                 "The 'final' of the base type definition "
16165                 "contains 'extension'", NULL);
16166             return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16167         }
16168
16169         /*
16170         * ATTENTION: The constrains (1.2) and (1.3) are not applied,
16171         * since they are automatically satisfied through the
16172         * inheriting mechanism.
16173         * Note that even if redefining components, the inheriting mechanism
16174         * is used.
16175         */
16176 #if 0
16177         /*
16178         * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
16179         * uses}
16180         * of the complex type definition itself, that is, for every attribute
16181         * use in the {attribute uses} of the {base type definition}, there
16182         * must be an attribute use in the {attribute uses} of the complex
16183         * type definition itself whose {attribute declaration} has the same
16184         * {name}, {target namespace} and {type definition} as its attribute
16185         * declaration"
16186         */
16187         if (base->attrUses != NULL) {
16188             int i, j, found;
16189             xmlSchemaAttributeUsePtr use, buse;
16190
16191             for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16192                 buse = (WXS_LIST_CAST base->attrUses)->items[i];
16193                 found = 0;
16194                 if (type->attrUses != NULL) {
16195                     use = (WXS_LIST_CAST type->attrUses)->items[j];
16196                     for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16197                     {
16198                         if ((WXS_ATTRUSE_DECL_NAME(use) ==
16199                                 WXS_ATTRUSE_DECL_NAME(buse)) &&
16200                             (WXS_ATTRUSE_DECL_TNS(use) ==
16201                                 WXS_ATTRUSE_DECL_TNS(buse)) &&
16202                             (WXS_ATTRUSE_TYPEDEF(use) ==
16203                                 WXS_ATTRUSE_TYPEDEF(buse))
16204                         {
16205                             found = 1;
16206                             break;
16207                         }
16208                     }
16209                 }
16210                 if (! found) {
16211                     xmlChar *str = NULL;
16212
16213                     xmlSchemaCustomErr(ACTXT_CAST ctxt,
16214                         XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16215                         NULL, WXS_BASIC_CAST type,
16216                         /*
16217                         * TODO: The report does not indicate that also the
16218                         * type needs to be the same.
16219                         */
16220                         "This type is missing a matching correspondent "
16221                         "for its {base type}'s %s in its {attribute uses}",
16222                         xmlSchemaGetComponentDesignation(&str,
16223                             buse->children),
16224                         NULL);
16225                     FREE_AND_NULL(str)
16226                 }
16227             }
16228         }
16229         /*
16230         * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16231         * definition must also have one, and the base type definition's
16232         * {attribute  wildcard}'s {namespace constraint} must be a subset
16233         * of the complex  type definition's {attribute wildcard}'s {namespace
16234         * constraint}, as defined by Wildcard Subset ($3.10.6)."
16235         */
16236
16237         /*
16238         * MAYBE TODO: Enable if ever needed. But this will be needed only
16239         * if created the type via a schema construction API.
16240         */
16241         if (base->attributeWildcard != NULL) {
16242             if (type->attributeWilcard == NULL) {
16243                 xmlChar *str = NULL;
16244
16245                 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16246                     XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16247                     NULL, type,
16248                     "The base %s has an attribute wildcard, "
16249                     "but this type is missing an attribute wildcard",
16250                     xmlSchemaGetComponentDesignation(&str, base));
16251                 FREE_AND_NULL(str)
16252
16253             } else if (xmlSchemaCheckCOSNSSubset(
16254                 base->attributeWildcard, type->attributeWildcard))
16255             {
16256                 xmlChar *str = NULL;
16257
16258                 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16259                     XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16260                     NULL, type,
16261                     "The attribute wildcard is not a valid "
16262                     "superset of the one in the base %s",
16263                     xmlSchemaGetComponentDesignation(&str, base));
16264                 FREE_AND_NULL(str)
16265             }
16266         }
16267 #endif
16268         /*
16269         * SPEC (1.4) "One of the following must be true:"
16270         */
16271         if ((type->contentTypeDef != NULL) &&
16272             (type->contentTypeDef == base->contentTypeDef)) {
16273             /*
16274             * SPEC (1.4.1) "The {content type} of the {base type definition}
16275             * and the {content type} of the complex type definition itself
16276             * must be the same simple type definition"
16277             * PASS
16278             */
16279         } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16280             (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16281             /*
16282             * SPEC (1.4.2) "The {content type} of both the {base type
16283             * definition} and the complex type definition itself must
16284             * be empty."
16285             * PASS
16286             */
16287         } else {
16288             /*
16289             * SPEC (1.4.3) "All of the following must be true:"
16290             */
16291             if (type->subtypes == NULL) {
16292                 /*
16293                 * SPEC 1.4.3.1 The {content type} of the complex type
16294                 * definition itself must specify a particle.
16295                 */
16296                 xmlSchemaPCustomErr(ctxt,
16297                     XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16298                     WXS_BASIC_CAST type, NULL,
16299                     "The content type must specify a particle", NULL);
16300                 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16301             }
16302             /*
16303             * SPEC (1.4.3.2) "One of the following must be true:"
16304             */
16305             if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16306                 /*
16307                 * SPEC (1.4.3.2.1) "The {content type} of the {base type
16308                 * definition} must be empty.
16309                 * PASS
16310                 */
16311             } else {
16312                 /*
16313                 * SPEC (1.4.3.2.2) "All of the following must be true:"
16314                 */
16315                 if ((type->contentType != base->contentType) ||
16316                     ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16317                     (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16318                     /*
16319                     * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16320                     * or both must be element-only."
16321                     */
16322                     xmlSchemaPCustomErr(ctxt,
16323                         XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16324                         WXS_BASIC_CAST type, NULL,
16325                         "The content type of both, the type and its base "
16326                         "type, must either 'mixed' or 'element-only'", NULL);
16327                     return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16328                 }
16329                 /*
16330                 * URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
16331                 * complex type definition must be a `valid extension`
16332                 * of the {base type definition}'s particle, as defined
16333                 * in Particle Valid (Extension) ($3.9.6)."
16334                 *
16335                 * NOTE that we won't check "Particle Valid (Extension)",
16336                 * since it is ensured by the derivation process in
16337                 * xmlSchemaTypeFixup(). We need to implement this when heading
16338                 * for a construction API
16339                 * TODO: !! This is needed to be checked if redefining a type !!
16340                 */
16341             }
16342             /*
16343             * URGENT TODO (1.5)
16344             */
16345         }
16346     } else {
16347         /*
16348         * SPEC (2) "If the {base type definition} is a simple type definition,
16349         * then all of the following must be true:"
16350         */
16351         if (type->contentTypeDef != base) {
16352             /*
16353             * SPEC (2.1) "The {content type} must be the same simple type
16354             * definition."
16355             */
16356             xmlSchemaPCustomErr(ctxt,
16357                 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16358                 WXS_BASIC_CAST type, NULL,
16359                 "The content type must be the simple base type", NULL);
16360             return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16361         }
16362         if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16363             /*
16364             * SPEC (2.2) "The {final} of the {base type definition} must not
16365             * contain extension"
16366             * NOTE that this is the same as (1.1).
16367             */
16368             xmlSchemaPCustomErr(ctxt,
16369                 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16370                 WXS_BASIC_CAST type, NULL,
16371                 "The 'final' of the base type definition "
16372                 "contains 'extension'", NULL);
16373             return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16374         }
16375     }
16376     return (0);
16377 }
16378
16379 /**
16380  * xmlSchemaCheckDerivationOKRestriction:
16381  * @ctxt:  the schema parser context
16382  * @type:  the complex type definition
16383  *
16384  * (3.4.6) Constraints on Complex Type Definition Schema Components
16385  * Schema Component Constraint:
16386  * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16387  *
16388  * STATUS:
16389  *   missing:
16390  *     (5.4.2) ???
16391  *
16392  * ATTENTION:
16393  * In XML Schema 1.1 this will be:
16394  * Validation Rule: Checking complex type subsumption
16395  *
16396  * Returns 0 if the constraints are satisfied, a positive
16397  * error code if not and -1 if an internal error occured.
16398  */
16399 static int
16400 xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16401                                       xmlSchemaTypePtr type)
16402 {
16403     xmlSchemaTypePtr base;
16404
16405     /*
16406     * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
16407     * temporarily only.
16408     */
16409     base = type->baseType;
16410     if (! WXS_IS_COMPLEX(base)) {
16411         xmlSchemaCustomErr(ACTXT_CAST ctxt,
16412             XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16413             type->node, WXS_BASIC_CAST type,
16414             "The base type must be a complex type", NULL, NULL);
16415         return(ctxt->err);
16416     }
16417     if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16418         /*
16419         * SPEC (1) "The {base type definition} must be a complex type
16420         * definition whose {final} does not contain restriction."
16421         */
16422         xmlSchemaCustomErr(ACTXT_CAST ctxt,
16423             XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16424             type->node, WXS_BASIC_CAST type,
16425             "The 'final' of the base type definition "
16426             "contains 'restriction'", NULL, NULL);
16427         return (ctxt->err);
16428     }
16429     /*
16430     * SPEC (2), (3) and (4)
16431     * Those are handled in a separate function, since the
16432     * same constraints are needed for redefinition of
16433     * attribute groups as well.
16434     */
16435     if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16436         XML_SCHEMA_ACTION_DERIVE,
16437         WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16438         type->attrUses, base->attrUses,
16439         type->attributeWildcard,
16440         base->attributeWildcard) == -1)
16441     {
16442         return(-1);
16443     }
16444     /*
16445     * SPEC (5) "One of the following must be true:"
16446     */
16447     if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16448         /*
16449         * SPEC (5.1) "The {base type definition} must be the
16450         * `ur-type definition`."
16451         * PASS
16452         */
16453     } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16454             (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16455         /*
16456         * SPEC (5.2.1) "The {content type} of the complex type definition
16457         * must be a simple type definition"
16458         *
16459         * SPEC (5.2.2) "One of the following must be true:"
16460         */
16461         if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16462             (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16463         {
16464             int err;
16465             /*
16466             * SPEC (5.2.2.1) "The {content type} of the {base type
16467             * definition} must be a simple type definition from which
16468             * the {content type} is validly derived given the empty
16469             * set as defined in Type Derivation OK (Simple) ($3.14.6)."
16470             *
16471             * ATTENTION TODO: This seems not needed if the type implicitely
16472             * derived from the base type.
16473             *
16474             */
16475             err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16476                 type->contentTypeDef, base->contentTypeDef, 0);
16477             if (err != 0) {
16478                 xmlChar *strA = NULL, *strB = NULL;
16479
16480                 if (err == -1)
16481                     return(-1);
16482                 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16483                     XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16484                     NULL, WXS_BASIC_CAST type,
16485                     "The {content type} %s is not validly derived from the "
16486                     "base type's {content type} %s",
16487                     xmlSchemaGetComponentDesignation(&strA,
16488                         type->contentTypeDef),
16489                     xmlSchemaGetComponentDesignation(&strB,
16490                         base->contentTypeDef));
16491                 FREE_AND_NULL(strA);
16492                 FREE_AND_NULL(strB);
16493                 return(ctxt->err);
16494             }
16495         } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16496             (xmlSchemaIsParticleEmptiable(
16497                 (xmlSchemaParticlePtr) base->subtypes))) {
16498             /*
16499             * SPEC (5.2.2.2) "The {base type definition} must be mixed
16500             * and have a particle which is `emptiable` as defined in
16501             * Particle Emptiable ($3.9.6)."
16502             * PASS
16503             */
16504         } else {
16505             xmlSchemaPCustomErr(ctxt,
16506                 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16507                 WXS_BASIC_CAST type, NULL,
16508                 "The content type of the base type must be either "
16509                 "a simple type or 'mixed' and an emptiable particle", NULL);
16510             return (ctxt->err);
16511         }
16512     } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16513         /*
16514         * SPEC (5.3.1) "The {content type} of the complex type itself must
16515         * be empty"
16516         */
16517         if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16518             /*
16519             * SPEC (5.3.2.1) "The {content type} of the {base type
16520             * definition} must also be empty."
16521             * PASS
16522             */
16523         } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16524             (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16525             xmlSchemaIsParticleEmptiable(
16526                 (xmlSchemaParticlePtr) base->subtypes)) {
16527             /*
16528             * SPEC (5.3.2.2) "The {content type} of the {base type
16529             * definition} must be elementOnly or mixed and have a particle
16530             * which is `emptiable` as defined in Particle Emptiable ($3.9.6)."
16531             * PASS
16532             */
16533         } else {
16534             xmlSchemaPCustomErr(ctxt,
16535                 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16536                 WXS_BASIC_CAST type, NULL,
16537                 "The content type of the base type must be either "
16538                 "empty or 'mixed' (or 'elements-only') and an emptiable "
16539                 "particle", NULL);
16540             return (ctxt->err);
16541         }
16542     } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16543         WXS_HAS_MIXED_CONTENT(type)) {
16544         /*
16545         * SPEC (5.4.1.1) "The {content type} of the complex type definition
16546         * itself must be element-only"
16547         */
16548         if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
16549             /*
16550             * SPEC (5.4.1.2) "The {content type} of the complex type
16551             * definition itself and of the {base type definition} must be
16552             * mixed"
16553             */
16554             xmlSchemaPCustomErr(ctxt,
16555                 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16556                 WXS_BASIC_CAST type, NULL,
16557                 "If the content type is 'mixed', then the content type of the "
16558                 "base type must also be 'mixed'", NULL);
16559             return (ctxt->err);
16560         }
16561         /*
16562         * SPEC (5.4.2) "The particle of the complex type definition itself
16563         * must be a `valid restriction` of the particle of the {content
16564         * type} of the {base type definition} as defined in Particle Valid
16565         * (Restriction) ($3.9.6).
16566         *
16567         * URGENT TODO: (5.4.2)
16568         */
16569     } else {
16570         xmlSchemaPCustomErr(ctxt,
16571             XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16572             WXS_BASIC_CAST type, NULL,
16573             "The type is not a valid restriction of its base type", NULL);
16574         return (ctxt->err);
16575     }
16576     return (0);
16577 }
16578
16579 /**
16580  * xmlSchemaCheckCTComponent:
16581  * @ctxt:  the schema parser context
16582  * @type:  the complex type definition
16583  *
16584  * (3.4.6) Constraints on Complex Type Definition Schema Components
16585  *
16586  * Returns 0 if the constraints are satisfied, a positive
16587  * error code if not and -1 if an internal error occured.
16588  */
16589 static int
16590 xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16591                           xmlSchemaTypePtr type)
16592 {
16593     int ret;
16594     /*
16595     * Complex Type Definition Properties Correct
16596     */
16597     ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16598     if (ret != 0)
16599         return (ret);
16600     if (WXS_IS_EXTENSION(type))
16601         ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16602     else
16603         ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16604     return (ret);
16605 }
16606
16607 /**
16608  * xmlSchemaCheckSRCCT:
16609  * @ctxt:  the schema parser context
16610  * @type:  the complex type definition
16611  *
16612  * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
16613  * Schema Representation Constraint:
16614  * Complex Type Definition Representation OK (src-ct)
16615  *
16616  * Returns 0 if the constraints are satisfied, a positive
16617  * error code if not and -1 if an internal error occured.
16618  */
16619 static int
16620 xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
16621                     xmlSchemaTypePtr type)
16622 {
16623     xmlSchemaTypePtr base;
16624     int ret = 0;
16625
16626     /*
16627     * TODO: Adjust the error codes here, as I used
16628     * XML_SCHEMAP_SRC_CT_1 only yet.
16629     */
16630     base = type->baseType;
16631     if (! WXS_HAS_SIMPLE_CONTENT(type)) {
16632         /*
16633         * 1 If the <complexContent> alternative is chosen, the type definition
16634         * `resolved` to by the `actual value` of the base [attribute]
16635         * must be a complex type definition;
16636         */
16637         if (! WXS_IS_COMPLEX(base)) {
16638             xmlChar *str = NULL;
16639             xmlSchemaPCustomErr(ctxt,
16640                 XML_SCHEMAP_SRC_CT_1,
16641                 WXS_BASIC_CAST type, type->node,
16642                 "If using <complexContent>, the base type is expected to be "
16643                 "a complex type. The base type '%s' is a simple type",
16644                 xmlSchemaFormatQName(&str, base->targetNamespace,
16645                 base->name));
16646             FREE_AND_NULL(str)
16647             return (XML_SCHEMAP_SRC_CT_1);
16648         }
16649     } else {
16650         /*
16651         * SPEC
16652         * 2 If the <simpleContent> alternative is chosen, all of the
16653         * following must be true:
16654         * 2.1 The type definition `resolved` to by the `actual value` of the
16655         * base [attribute] must be one of the following:
16656         */
16657         if (WXS_IS_SIMPLE(base)) {
16658             if (WXS_IS_EXTENSION(type) == 0) {
16659                 xmlChar *str = NULL;
16660                 /*
16661                 * 2.1.3 only if the <extension> alternative is also
16662                 * chosen, a simple type definition.
16663                 */
16664                 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
16665                 xmlSchemaPCustomErr(ctxt,
16666                     XML_SCHEMAP_SRC_CT_1,
16667                     WXS_BASIC_CAST type, NULL,
16668                     "If using <simpleContent> and <restriction>, the base "
16669                     "type must be a complex type. The base type '%s' is "
16670                     "a simple type",
16671                     xmlSchemaFormatQName(&str, base->targetNamespace,
16672                         base->name));
16673                 FREE_AND_NULL(str)
16674                 return (XML_SCHEMAP_SRC_CT_1);
16675             }
16676         } else {
16677             /* Base type is a complex type. */
16678             if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16679                 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16680                 /*
16681                 * 2.1.1 a complex type definition whose {content type} is a
16682                 * simple type definition;
16683                 * PASS
16684                 */
16685                 if (base->contentTypeDef == NULL) {
16686                     xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16687                         WXS_BASIC_CAST type, NULL,
16688                         "Internal error: xmlSchemaCheckSRCCT, "
16689                         "'%s', base type has no content type",
16690                         type->name);
16691                     return (-1);
16692                 }
16693             } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16694                 (WXS_IS_RESTRICTION(type))) {
16695
16696                 /*
16697                 * 2.1.2 only if the <restriction> alternative is also
16698                 * chosen, a complex type definition whose {content type}
16699                 * is mixed and a particle emptiable.
16700                 */
16701                 if (! xmlSchemaIsParticleEmptiable(
16702                     (xmlSchemaParticlePtr) base->subtypes)) {
16703                     ret = XML_SCHEMAP_SRC_CT_1;
16704                 } else
16705                     /*
16706                     * Attention: at this point the <simpleType> child is in
16707                     * ->contentTypeDef (put there during parsing).
16708                     */
16709                     if (type->contentTypeDef == NULL) {
16710                     xmlChar *str = NULL;
16711                     /*
16712                     * 2.2 If clause 2.1.2 above is satisfied, then there
16713                     * must be a <simpleType> among the [children] of
16714                     * <restriction>.
16715                     */
16716                     /* TODO: Change error code to ..._SRC_CT_2_2. */
16717                     xmlSchemaPCustomErr(ctxt,
16718                         XML_SCHEMAP_SRC_CT_1,
16719                         WXS_BASIC_CAST type, NULL,
16720                         "A <simpleType> is expected among the children "
16721                         "of <restriction>, if <simpleContent> is used and "
16722                         "the base type '%s' is a complex type",
16723                         xmlSchemaFormatQName(&str, base->targetNamespace,
16724                         base->name));
16725                     FREE_AND_NULL(str)
16726                     return (XML_SCHEMAP_SRC_CT_1);
16727                 }
16728             } else {
16729                 ret = XML_SCHEMAP_SRC_CT_1;
16730             }
16731         }
16732         if (ret > 0) {
16733             xmlChar *str = NULL;
16734             if (WXS_IS_RESTRICTION(type)) {
16735                 xmlSchemaPCustomErr(ctxt,
16736                     XML_SCHEMAP_SRC_CT_1,
16737                     WXS_BASIC_CAST type, NULL,
16738                     "If <simpleContent> and <restriction> is used, the "
16739                     "base type must be a simple type or a complex type with "
16740                     "mixed content and particle emptiable. The base type "
16741                     "'%s' is none of those",
16742                     xmlSchemaFormatQName(&str, base->targetNamespace,
16743                     base->name));
16744             } else {
16745                 xmlSchemaPCustomErr(ctxt,
16746                     XML_SCHEMAP_SRC_CT_1,
16747                     WXS_BASIC_CAST type, NULL,
16748                     "If <simpleContent> and <extension> is used, the "
16749                     "base type must be a simple type. The base type '%s' "
16750                     "is a complex type",
16751                     xmlSchemaFormatQName(&str, base->targetNamespace,
16752                     base->name));
16753             }
16754             FREE_AND_NULL(str)
16755         }
16756     }
16757     /*
16758     * SPEC (3) "The corresponding complex type definition component must
16759     * satisfy the conditions set out in Constraints on Complex Type
16760     * Definition Schema Components ($3.4.6);"
16761     * NOTE (3) will be done in xmlSchemaTypeFixup().
16762     */
16763     /*
16764     * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
16765     * above for {attribute wildcard} is satisfied, the intensional
16766     * intersection must be expressible, as defined in Attribute Wildcard
16767     * Intersection ($3.10.6).
16768     * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
16769     */
16770     return (ret);
16771 }
16772
16773 #ifdef ENABLE_PARTICLE_RESTRICTION
16774 /**
16775  * xmlSchemaCheckParticleRangeOK:
16776  * @ctxt:  the schema parser context
16777  * @type:  the complex type definition
16778  *
16779  * (3.9.6) Constraints on Particle Schema Components
16780  * Schema Component Constraint:
16781  * Occurrence Range OK (range-ok)
16782  *
16783  * STATUS: complete
16784  *
16785  * Returns 0 if the constraints are satisfied, a positive
16786  * error code if not and -1 if an internal error occured.
16787  */
16788 static int
16789 xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16790                               int bmin, int bmax)
16791 {
16792     if (rmin < bmin)
16793         return (1);
16794     if ((bmax != UNBOUNDED) &&
16795         (rmax > bmax))
16796         return (1);
16797     return (0);
16798 }
16799
16800 /**
16801  * xmlSchemaCheckRCaseNameAndTypeOK:
16802  * @ctxt:  the schema parser context
16803  * @r: the restricting element declaration particle
16804  * @b: the base element declaration particle
16805  *
16806  * (3.9.6) Constraints on Particle Schema Components
16807  * Schema Component Constraint:
16808  * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16809  * (rcase-NameAndTypeOK)
16810  *
16811  * STATUS:
16812  *   MISSING (3.2.3)
16813  *   CLARIFY: (3.2.2)
16814  *
16815  * Returns 0 if the constraints are satisfied, a positive
16816  * error code if not and -1 if an internal error occured.
16817  */
16818 static int
16819 xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16820                                  xmlSchemaParticlePtr r,
16821                                  xmlSchemaParticlePtr b)
16822 {
16823     xmlSchemaElementPtr elemR, elemB;
16824
16825     /* TODO: Error codes (rcase-NameAndTypeOK). */
16826     elemR = (xmlSchemaElementPtr) r->children;
16827     elemB = (xmlSchemaElementPtr) b->children;
16828     /*
16829     * SPEC (1) "The declarations' {name}s and {target namespace}s are
16830     * the same."
16831     */
16832     if ((elemR != elemB) &&
16833         ((! xmlStrEqual(elemR->name, elemB->name)) ||
16834         (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16835         return (1);
16836     /*
16837     * SPEC (2) "R's occurrence range is a valid restriction of B's
16838     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
16839     */
16840     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16841             b->minOccurs, b->maxOccurs) != 0)
16842         return (1);
16843     /*
16844     * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16845     * {scope} are global."
16846     */
16847     if (elemR == elemB)
16848         return (0);
16849     /*
16850     * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16851     */
16852     if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16853         (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16854          return (1);
16855     /*
16856     * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16857     * or is not fixed, or R's declaration's {value constraint} is fixed
16858     * with the same value."
16859     */
16860     if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16861         ((elemR->value == NULL) ||
16862          ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16863          /* TODO: Equality of the initial value or normalized or canonical? */
16864          (! xmlStrEqual(elemR->value, elemB->value))))
16865          return (1);
16866     /*
16867     * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16868     * definitions} is a subset of B's declaration's {identity-constraint
16869     * definitions}, if any."
16870     */
16871     if (elemB->idcs != NULL) {
16872         /* TODO */
16873     }
16874     /*
16875     * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16876     * superset of B's declaration's {disallowed substitutions}."
16877     */
16878     if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16879          ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16880         ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16881          ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16882         ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16883          ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16884          return (1);
16885     /*
16886     * SPEC (3.2.5) "R's {type definition} is validly derived given
16887     * {extension, list, union} from B's {type definition}"
16888     *
16889     * BADSPEC TODO: What's the point of adding "list" and "union" to the
16890     * set, if the corresponding constraints handle "restriction" and
16891     * "extension" only?
16892     *
16893     */
16894     {
16895         int set = 0;
16896
16897         set |= SUBSET_EXTENSION;
16898         set |= SUBSET_LIST;
16899         set |= SUBSET_UNION;
16900         if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
16901             elemB->subtypes, set) != 0)
16902             return (1);
16903     }
16904     return (0);
16905 }
16906
16907 /**
16908  * xmlSchemaCheckRCaseNSCompat:
16909  * @ctxt:  the schema parser context
16910  * @r: the restricting element declaration particle
16911  * @b: the base wildcard particle
16912  *
16913  * (3.9.6) Constraints on Particle Schema Components
16914  * Schema Component Constraint:
16915  * Particle Derivation OK (Elt:Any -- NSCompat)
16916  * (rcase-NSCompat)
16917  *
16918  * STATUS: complete
16919  *
16920  * Returns 0 if the constraints are satisfied, a positive
16921  * error code if not and -1 if an internal error occured.
16922  */
16923 static int
16924 xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16925                             xmlSchemaParticlePtr r,
16926                             xmlSchemaParticlePtr b)
16927 {
16928     /* TODO:Error codes (rcase-NSCompat). */
16929     /*
16930     * SPEC "For an element declaration particle to be a `valid restriction`
16931     * of a wildcard particle all of the following must be true:"
16932     *
16933     * SPEC (1) "The element declaration's {target namespace} is `valid`
16934     * with respect to the wildcard's {namespace constraint} as defined by
16935     * Wildcard allows Namespace Name ($3.10.4)."
16936     */
16937     if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
16938         ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16939         return (1);
16940     /*
16941     * SPEC (2) "R's occurrence range is a valid restriction of B's
16942     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
16943     */
16944     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16945             b->minOccurs, b->maxOccurs) != 0)
16946         return (1);
16947
16948     return (0);
16949 }
16950
16951 /**
16952  * xmlSchemaCheckRCaseRecurseAsIfGroup:
16953  * @ctxt:  the schema parser context
16954  * @r: the restricting element declaration particle
16955  * @b: the base model group particle
16956  *
16957  * (3.9.6) Constraints on Particle Schema Components
16958  * Schema Component Constraint:
16959  * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
16960  * (rcase-RecurseAsIfGroup)
16961  *
16962  * STATUS: TODO
16963  *
16964  * Returns 0 if the constraints are satisfied, a positive
16965  * error code if not and -1 if an internal error occured.
16966  */
16967 static int
16968 xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16969                                     xmlSchemaParticlePtr r,
16970                                     xmlSchemaParticlePtr b)
16971 {
16972     /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16973     TODO
16974     return (0);
16975 }
16976
16977 /**
16978  * xmlSchemaCheckRCaseNSSubset:
16979  * @ctxt:  the schema parser context
16980  * @r: the restricting wildcard particle
16981  * @b: the base wildcard particle
16982  *
16983  * (3.9.6) Constraints on Particle Schema Components
16984  * Schema Component Constraint:
16985  * Particle Derivation OK (Any:Any -- NSSubset)
16986  * (rcase-NSSubset)
16987  *
16988  * STATUS: complete
16989  *
16990  * Returns 0 if the constraints are satisfied, a positive
16991  * error code if not and -1 if an internal error occured.
16992  */
16993 static int
16994 xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
16995                                     xmlSchemaParticlePtr r,
16996                                     xmlSchemaParticlePtr b,
16997                                     int isAnyTypeBase)
16998 {
16999     /* TODO: Error codes (rcase-NSSubset). */
17000     /*
17001     * SPEC (1) "R's occurrence range is a valid restriction of B's
17002     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17003     */
17004     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17005             b->minOccurs, b->maxOccurs))
17006         return (1);
17007     /*
17008     * SPEC (2) "R's {namespace constraint} must be an intensional subset
17009     * of B's {namespace constraint} as defined by Wildcard Subset ($3.10.6)."
17010     */
17011     if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
17012         (xmlSchemaWildcardPtr) b->children))
17013         return (1);
17014     /*
17015     * SPEC (3) "Unless B is the content model wildcard of the `ur-type
17016     * definition`, R's {process contents} must be identical to or stronger
17017     * than B's {process contents}, where strict is stronger than lax is
17018     * stronger than skip."
17019     */
17020     if (! isAnyTypeBase) {
17021         if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
17022             ((xmlSchemaWildcardPtr) b->children)->processContents)
17023             return (1);
17024     }
17025
17026     return (0);
17027 }
17028
17029 /**
17030  * xmlSchemaCheckCOSParticleRestrict:
17031  * @ctxt:  the schema parser context
17032  * @type:  the complex type definition
17033  *
17034  * (3.9.6) Constraints on Particle Schema Components
17035  * Schema Component Constraint:
17036  * Particle Valid (Restriction) (cos-particle-restrict)
17037  *
17038  * STATUS: TODO
17039  *
17040  * Returns 0 if the constraints are satisfied, a positive
17041  * error code if not and -1 if an internal error occured.
17042  */
17043 static int
17044 xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
17045                                   xmlSchemaParticlePtr r,
17046                                   xmlSchemaParticlePtr b)
17047 {
17048     int ret = 0;
17049
17050     /*part = WXS_TYPE_PARTICLE(type);
17051     basePart = WXS_TYPE_PARTICLE(base);
17052     */
17053
17054     TODO
17055
17056     /*
17057     * SPEC (1) "They are the same particle."
17058     */
17059     if (r == b)
17060         return (0);
17061
17062
17063     return (0);
17064 }
17065
17066 #if 0
17067 /**
17068  * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
17069  * @ctxt:  the schema parser context
17070  * @r: the model group particle
17071  * @b: the base wildcard particle
17072  *
17073  * (3.9.6) Constraints on Particle Schema Components
17074  * Schema Component Constraint:
17075  * Particle Derivation OK (All/Choice/Sequence:Any --
17076  *                         NSRecurseCheckCardinality)
17077  * (rcase-NSRecurseCheckCardinality)
17078  *
17079  * STATUS: TODO: subst-groups
17080  *
17081  * Returns 0 if the constraints are satisfied, a positive
17082  * error code if not and -1 if an internal error occured.
17083  */
17084 static int
17085 xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
17086                                              xmlSchemaParticlePtr r,
17087                                              xmlSchemaParticlePtr b)
17088 {
17089     xmlSchemaParticlePtr part;
17090     /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
17091     if ((r->children == NULL) || (r->children->children == NULL))
17092         return (-1);
17093     /*
17094     * SPEC "For a group particle to be a `valid restriction` of a
17095     * wildcard particle..."
17096     *
17097     * SPEC (1) "Every member of the {particles} of the group is a `valid
17098     * restriction` of the wildcard as defined by
17099     * Particle Valid (Restriction) ($3.9.6)."
17100     */
17101     part = (xmlSchemaParticlePtr) r->children->children;
17102     do {
17103         if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
17104             return (1);
17105         part = (xmlSchemaParticlePtr) part->next;
17106     } while (part != NULL);
17107     /*
17108     * SPEC (2) "The effective total range of the group [...] is a
17109     * valid restriction of B's occurrence range as defined by
17110     * Occurrence Range OK ($3.9.6)."
17111     */
17112     if (xmlSchemaCheckParticleRangeOK(
17113             xmlSchemaGetParticleTotalRangeMin(r),
17114             xmlSchemaGetParticleTotalRangeMax(r),
17115             b->minOccurs, b->maxOccurs) != 0)
17116         return (1);
17117     return (0);
17118 }
17119 #endif
17120
17121 /**
17122  * xmlSchemaCheckRCaseRecurse:
17123  * @ctxt:  the schema parser context
17124  * @r: the <all> or <sequence> model group particle
17125  * @b: the base <all> or <sequence> model group particle
17126  *
17127  * (3.9.6) Constraints on Particle Schema Components
17128  * Schema Component Constraint:
17129  * Particle Derivation OK (All:All,Sequence:Sequence --
17130                            Recurse)
17131  * (rcase-Recurse)
17132  *
17133  * STATUS:  ?
17134  * TODO: subst-groups
17135  *
17136  * Returns 0 if the constraints are satisfied, a positive
17137  * error code if not and -1 if an internal error occured.
17138  */
17139 static int
17140 xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17141                            xmlSchemaParticlePtr r,
17142                            xmlSchemaParticlePtr b)
17143 {
17144     /* xmlSchemaParticlePtr part; */
17145     /* TODO: Error codes (rcase-Recurse). */
17146     if ((r->children == NULL) || (b->children == NULL) ||
17147         (r->children->type != b->children->type))
17148         return (-1);
17149     /*
17150     * SPEC "For an all or sequence group particle to be a `valid
17151     * restriction` of another group particle with the same {compositor}..."
17152     *
17153     * SPEC (1) "R's occurrence range is a valid restriction of B's
17154     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17155     */
17156     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17157             b->minOccurs, b->maxOccurs))
17158         return (1);
17159
17160
17161     return (0);
17162 }
17163
17164 #endif
17165
17166 #define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17167     xmlSchemaPCustomErrExt(pctxt,      \
17168         XML_SCHEMAP_INVALID_FACET_VALUE, \
17169         WXS_BASIC_CAST fac1, fac1->node, \
17170         "It is an error for both '%s' and '%s' to be specified on the "\
17171         "same type definition", \
17172         BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17173         BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17174
17175 #define FACET_RESTR_ERR(fac1, msg) \
17176     xmlSchemaPCustomErr(pctxt,      \
17177         XML_SCHEMAP_INVALID_FACET_VALUE, \
17178         WXS_BASIC_CAST fac1, fac1->node, \
17179         msg, NULL);
17180
17181 #define FACET_RESTR_FIXED_ERR(fac) \
17182     xmlSchemaPCustomErr(pctxt, \
17183         XML_SCHEMAP_INVALID_FACET_VALUE, \
17184         WXS_BASIC_CAST fac, fac->node, \
17185         "The base type's facet is 'fixed', thus the value must not " \
17186         "differ", NULL);
17187
17188 static void
17189 xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17190                         xmlSchemaFacetPtr facet1,
17191                         xmlSchemaFacetPtr facet2,
17192                         int lessGreater,
17193                         int orEqual,
17194                         int ofBase)
17195 {
17196     xmlChar *msg = NULL;
17197
17198     msg = xmlStrdup(BAD_CAST "'");
17199     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17200     msg = xmlStrcat(msg, BAD_CAST "' has to be");
17201     if (lessGreater == 0)
17202         msg = xmlStrcat(msg, BAD_CAST " equal to");
17203     if (lessGreater == 1)
17204         msg = xmlStrcat(msg, BAD_CAST " greater than");
17205     else
17206         msg = xmlStrcat(msg, BAD_CAST " less than");
17207
17208     if (orEqual)
17209         msg = xmlStrcat(msg, BAD_CAST " or equal to");
17210     msg = xmlStrcat(msg, BAD_CAST " '");
17211     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17212     if (ofBase)
17213         msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17214     else
17215         msg = xmlStrcat(msg, BAD_CAST "'");
17216
17217     xmlSchemaPCustomErr(pctxt,
17218         XML_SCHEMAP_INVALID_FACET_VALUE,
17219         WXS_BASIC_CAST facet1, NULL,
17220         (const char *) msg, NULL);
17221
17222     if (msg != NULL)
17223         xmlFree(msg);
17224 }
17225
17226 /*
17227 * xmlSchemaDeriveAndValidateFacets:
17228 *
17229 * Schema Component Constraint: Simple Type Restriction (Facets)
17230 * (st-restrict-facets)
17231 */
17232 static int
17233 xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17234                                  xmlSchemaTypePtr type)
17235 {
17236     xmlSchemaTypePtr base = type->baseType;
17237     xmlSchemaFacetLinkPtr link, cur, last = NULL;
17238     xmlSchemaFacetPtr facet, bfacet,
17239         flength = NULL, ftotdig = NULL, ffracdig = NULL,
17240         fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17241         fmininc = NULL, fmaxinc = NULL,
17242         fminexc = NULL, fmaxexc = NULL,
17243         bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17244         bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17245         bfmininc = NULL, bfmaxinc = NULL,
17246         bfminexc = NULL, bfmaxexc = NULL;
17247     int res; /* err = 0, fixedErr; */
17248
17249     /*
17250     * SPEC st-restrict-facets 1:
17251     * "The {variety} of R is the same as that of B."
17252     */
17253     /*
17254     * SPEC st-restrict-facets 2:
17255     * "If {variety} is atomic, the {primitive type definition}
17256     * of R is the same as that of B."
17257     *
17258     * NOTE: we leave 1 & 2 out for now, since this will be
17259     * satisfied by the derivation process.
17260     * CONSTRUCTION TODO: Maybe needed if using a construction API.
17261     */
17262     /*
17263     * SPEC st-restrict-facets 3:
17264     * "The {facets} of R are the union of S and the {facets}
17265     * of B, eliminating duplicates. To eliminate duplicates,
17266     * when a facet of the same kind occurs in both S and the
17267     * {facets} of B, the one in the {facets} of B is not
17268     * included, with the exception of enumeration and pattern
17269     * facets, for which multiple occurrences with distinct values
17270     * are allowed."
17271     */
17272
17273     if ((type->facetSet == NULL) && (base->facetSet == NULL))
17274         return (0);
17275
17276     last = type->facetSet;
17277     if (last != NULL)
17278         while (last->next != NULL)
17279             last = last->next;
17280
17281     for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17282         facet = cur->facet;
17283         switch (facet->type) {
17284             case XML_SCHEMA_FACET_LENGTH:
17285                 flength = facet; break;
17286             case XML_SCHEMA_FACET_MINLENGTH:
17287                 fminlen = facet; break;
17288             case XML_SCHEMA_FACET_MININCLUSIVE:
17289                 fmininc = facet; break;
17290             case XML_SCHEMA_FACET_MINEXCLUSIVE:
17291                 fminexc = facet; break;
17292             case XML_SCHEMA_FACET_MAXLENGTH:
17293                 fmaxlen = facet; break;
17294             case XML_SCHEMA_FACET_MAXINCLUSIVE:
17295                 fmaxinc = facet; break;
17296             case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17297                 fmaxexc = facet; break;
17298             case XML_SCHEMA_FACET_TOTALDIGITS:
17299                 ftotdig = facet; break;
17300             case XML_SCHEMA_FACET_FRACTIONDIGITS:
17301                 ffracdig = facet; break;
17302             default:
17303                 break;
17304         }
17305     }
17306     for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17307         facet = cur->facet;
17308         switch (facet->type) {
17309             case XML_SCHEMA_FACET_LENGTH:
17310                 bflength = facet; break;
17311             case XML_SCHEMA_FACET_MINLENGTH:
17312                 bfminlen = facet; break;
17313             case XML_SCHEMA_FACET_MININCLUSIVE:
17314                 bfmininc = facet; break;
17315             case XML_SCHEMA_FACET_MINEXCLUSIVE:
17316                 bfminexc = facet; break;
17317             case XML_SCHEMA_FACET_MAXLENGTH:
17318                 bfmaxlen = facet; break;
17319             case XML_SCHEMA_FACET_MAXINCLUSIVE:
17320                 bfmaxinc = facet; break;
17321             case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17322                 bfmaxexc = facet; break;
17323             case XML_SCHEMA_FACET_TOTALDIGITS:
17324                 bftotdig = facet; break;
17325             case XML_SCHEMA_FACET_FRACTIONDIGITS:
17326                 bffracdig = facet; break;
17327             default:
17328                 break;
17329         }
17330     }
17331     /*
17332     * length and minLength or maxLength (2.2) + (3.2)
17333     */
17334     if (flength && (fminlen || fmaxlen)) {
17335         FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17336             "either of 'minLength' or 'maxLength' to be specified on "
17337             "the same type definition")
17338     }
17339     /*
17340     * Mutual exclusions in the same derivation step.
17341     */
17342     if ((fmaxinc) && (fmaxexc)) {
17343         /*
17344         * SCC "maxInclusive and maxExclusive"
17345         */
17346         FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17347     }
17348     if ((fmininc) && (fminexc)) {
17349         /*
17350         * SCC "minInclusive and minExclusive"
17351         */
17352         FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
17353     }
17354
17355     if (flength && bflength) {
17356         /*
17357         * SCC "length valid restriction"
17358         * The values have to be equal.
17359         */
17360         res = xmlSchemaCompareValues(flength->val, bflength->val);
17361         if (res == -2)
17362             goto internal_error;
17363         if (res != 0)
17364             xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17365         if ((res != 0) && (bflength->fixed)) {
17366             FACET_RESTR_FIXED_ERR(flength)
17367         }
17368
17369     }
17370     if (fminlen && bfminlen) {
17371         /*
17372         * SCC "minLength valid restriction"
17373         * minLength >= BASE minLength
17374         */
17375         res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17376         if (res == -2)
17377             goto internal_error;
17378         if (res == -1)
17379             xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17380         if ((res != 0) && (bfminlen->fixed)) {
17381             FACET_RESTR_FIXED_ERR(fminlen)
17382         }
17383     }
17384     if (fmaxlen && bfmaxlen) {
17385         /*
17386         * SCC "maxLength valid restriction"
17387         * maxLength <= BASE minLength
17388         */
17389         res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17390         if (res == -2)
17391             goto internal_error;
17392         if (res == 1)
17393             xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17394         if ((res != 0) && (bfmaxlen->fixed)) {
17395             FACET_RESTR_FIXED_ERR(fmaxlen)
17396         }
17397     }
17398     /*
17399     * SCC "length and minLength or maxLength"
17400     */
17401     if (! flength)
17402         flength = bflength;
17403     if (flength) {
17404         if (! fminlen)
17405             fminlen = bfminlen;
17406         if (fminlen) {
17407             /* (1.1) length >= minLength */
17408             res = xmlSchemaCompareValues(flength->val, fminlen->val);
17409             if (res == -2)
17410                 goto internal_error;
17411             if (res == -1)
17412                 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17413         }
17414         if (! fmaxlen)
17415             fmaxlen = bfmaxlen;
17416         if (fmaxlen) {
17417             /* (2.1) length <= maxLength */
17418             res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17419             if (res == -2)
17420                 goto internal_error;
17421             if (res == 1)
17422                 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17423         }
17424     }
17425     if (fmaxinc) {
17426         /*
17427         * "maxInclusive"
17428         */
17429         if (fmininc) {
17430             /* SCC "maxInclusive >= minInclusive" */
17431             res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17432             if (res == -2)
17433                 goto internal_error;
17434             if (res == -1) {
17435                 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17436             }
17437         }
17438         /*
17439         * SCC "maxInclusive valid restriction"
17440         */
17441         if (bfmaxinc) {
17442             /* maxInclusive <= BASE maxInclusive */
17443             res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17444             if (res == -2)
17445                 goto internal_error;
17446             if (res == 1)
17447                 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17448             if ((res != 0) && (bfmaxinc->fixed)) {
17449                 FACET_RESTR_FIXED_ERR(fmaxinc)
17450             }
17451         }
17452         if (bfmaxexc) {
17453             /* maxInclusive < BASE maxExclusive */
17454             res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17455             if (res == -2)
17456                 goto internal_error;
17457             if (res != -1) {
17458                 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17459             }
17460         }
17461         if (bfmininc) {
17462             /* maxInclusive >= BASE minInclusive */
17463             res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17464             if (res == -2)
17465                 goto internal_error;
17466             if (res == -1) {
17467                 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17468             }
17469         }
17470         if (bfminexc) {
17471             /* maxInclusive > BASE minExclusive */
17472             res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17473             if (res == -2)
17474                 goto internal_error;
17475             if (res != 1) {
17476                 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17477             }
17478         }
17479     }
17480     if (fmaxexc) {
17481         /*
17482         * "maxExclusive >= minExclusive"
17483         */
17484         if (fminexc) {
17485             res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17486             if (res == -2)
17487                 goto internal_error;
17488             if (res == -1) {
17489                 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17490             }
17491         }
17492         /*
17493         * "maxExclusive valid restriction"
17494         */
17495         if (bfmaxexc) {
17496             /* maxExclusive <= BASE maxExclusive */
17497             res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17498             if (res == -2)
17499                 goto internal_error;
17500             if (res == 1) {
17501                 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17502             }
17503             if ((res != 0) && (bfmaxexc->fixed)) {
17504                 FACET_RESTR_FIXED_ERR(fmaxexc)
17505             }
17506         }
17507         if (bfmaxinc) {
17508             /* maxExclusive <= BASE maxInclusive */
17509             res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17510             if (res == -2)
17511                 goto internal_error;
17512             if (res == 1) {
17513                 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17514             }
17515         }
17516         if (bfmininc) {
17517             /* maxExclusive > BASE minInclusive */
17518             res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17519             if (res == -2)
17520                 goto internal_error;
17521             if (res != 1) {
17522                 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17523             }
17524         }
17525         if (bfminexc) {
17526             /* maxExclusive > BASE minExclusive */
17527             res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17528             if (res == -2)
17529                 goto internal_error;
17530             if (res != 1) {
17531                 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17532             }
17533         }
17534     }
17535     if (fminexc) {
17536         /*
17537         * "minExclusive < maxInclusive"
17538         */
17539         if (fmaxinc) {
17540             res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17541             if (res == -2)
17542                 goto internal_error;
17543             if (res != -1) {
17544                 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17545             }
17546         }
17547         /*
17548         * "minExclusive valid restriction"
17549         */
17550         if (bfminexc) {
17551             /* minExclusive >= BASE minExclusive */
17552             res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17553             if (res == -2)
17554                 goto internal_error;
17555             if (res == -1) {
17556                 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17557             }
17558             if ((res != 0) && (bfminexc->fixed)) {
17559                 FACET_RESTR_FIXED_ERR(fminexc)
17560             }
17561         }
17562         if (bfmaxinc) {
17563             /* minExclusive <= BASE maxInclusive */
17564             res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17565             if (res == -2)
17566                 goto internal_error;
17567             if (res == 1) {
17568                 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17569             }
17570         }
17571         if (bfmininc) {
17572             /* minExclusive >= BASE minInclusive */
17573             res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17574             if (res == -2)
17575                 goto internal_error;
17576             if (res == -1) {
17577                 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17578             }
17579         }
17580         if (bfmaxexc) {
17581             /* minExclusive < BASE maxExclusive */
17582             res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17583             if (res == -2)
17584                 goto internal_error;
17585             if (res != -1) {
17586                 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17587             }
17588         }
17589     }
17590     if (fmininc) {
17591         /*
17592         * "minInclusive < maxExclusive"
17593         */
17594         if (fmaxexc) {
17595             res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17596             if (res == -2)
17597                 goto internal_error;
17598             if (res != -1) {
17599                 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17600             }
17601         }
17602         /*
17603         * "minExclusive valid restriction"
17604         */
17605         if (bfmininc) {
17606             /* minInclusive >= BASE minInclusive */
17607             res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17608             if (res == -2)
17609                 goto internal_error;
17610             if (res == -1) {
17611                 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17612             }
17613             if ((res != 0) && (bfmininc->fixed)) {
17614                 FACET_RESTR_FIXED_ERR(fmininc)
17615             }
17616         }
17617         if (bfmaxinc) {
17618             /* minInclusive <= BASE maxInclusive */
17619             res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17620             if (res == -2)
17621                 goto internal_error;
17622             if (res == 1) {
17623                 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17624             }
17625         }
17626         if (bfminexc) {
17627             /* minInclusive > BASE minExclusive */
17628             res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17629             if (res == -2)
17630                 goto internal_error;
17631             if (res != 1)
17632                 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17633         }
17634         if (bfmaxexc) {
17635             /* minInclusive < BASE maxExclusive */
17636             res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17637             if (res == -2)
17638                 goto internal_error;
17639             if (res != -1)
17640                 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17641         }
17642     }
17643     if (ftotdig && bftotdig) {
17644         /*
17645         * SCC " totalDigits valid restriction"
17646         * totalDigits <= BASE totalDigits
17647         */
17648         res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17649         if (res == -2)
17650             goto internal_error;
17651         if (res == 1)
17652             xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17653             -1, 1, 1);
17654         if ((res != 0) && (bftotdig->fixed)) {
17655             FACET_RESTR_FIXED_ERR(ftotdig)
17656         }
17657     }
17658     if (ffracdig && bffracdig) {
17659         /*
17660         * SCC  "fractionDigits valid restriction"
17661         * fractionDigits <= BASE fractionDigits
17662         */
17663         res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17664         if (res == -2)
17665             goto internal_error;
17666         if (res == 1)
17667             xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17668             -1, 1, 1);
17669         if ((res != 0) && (bffracdig->fixed)) {
17670             FACET_RESTR_FIXED_ERR(ffracdig)
17671         }
17672     }
17673     /*
17674     * SCC "fractionDigits less than or equal to totalDigits"
17675     */
17676     if (! ftotdig)
17677         ftotdig = bftotdig;
17678     if (! ffracdig)
17679         ffracdig = bffracdig;
17680     if (ftotdig && ffracdig) {
17681         res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17682         if (res == -2)
17683             goto internal_error;
17684         if (res == 1)
17685             xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17686                 -1, 1, 0);
17687     }
17688     /*
17689     * *Enumerations* won' be added here, since only the first set
17690     * of enumerations in the ancestor-or-self axis is used
17691     * for validation, plus we need to use the base type of those
17692     * enumerations for whitespace.
17693     *
17694     * *Patterns*: won't be add here, since they are ORed at
17695     * type level and ANDed at ancestor level. This will
17696     * happed during validation by walking the base axis
17697     * of the type.
17698     */
17699     for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17700         bfacet = cur->facet;
17701         /*
17702         * Special handling of enumerations and patterns.
17703         * TODO: hmm, they should not appear in the set, so remove this.
17704         */
17705         if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
17706             (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
17707             continue;
17708         /*
17709         * Search for a duplicate facet in the current type.
17710         */
17711         link = type->facetSet;
17712         /* err = 0; */
17713         /* fixedErr = 0; */
17714         while (link != NULL) {
17715             facet = link->facet;
17716             if (facet->type == bfacet->type) {
17717                 switch (facet->type) {
17718                     case XML_SCHEMA_FACET_WHITESPACE:
17719                         /*
17720                         * The whitespace must be stronger.
17721                         */
17722                         if (facet->whitespace < bfacet->whitespace) {
17723                             FACET_RESTR_ERR(facet,
17724                                 "The 'whitespace' value has to be equal to "
17725                                 "or stronger than the 'whitespace' value of "
17726                                 "the base type")
17727                         }
17728                         if ((bfacet->fixed) &&
17729                             (facet->whitespace != bfacet->whitespace)) {
17730                             FACET_RESTR_FIXED_ERR(facet)
17731                         }
17732                         break;
17733                     default:
17734                         break;
17735                 }
17736                 /* Duplicate found. */
17737                 break;
17738             }
17739             link = link->next;
17740         }
17741         /*
17742         * If no duplicate was found: add the base types's facet
17743         * to the set.
17744         */
17745         if (link == NULL) {
17746             link = (xmlSchemaFacetLinkPtr)
17747                 xmlMalloc(sizeof(xmlSchemaFacetLink));
17748             if (link == NULL) {
17749                 xmlSchemaPErrMemory(pctxt,
17750                     "deriving facets, creating a facet link", NULL);
17751                 return (-1);
17752             }
17753             link->facet = cur->facet;
17754             link->next = NULL;
17755             if (last == NULL)
17756                 type->facetSet = link;
17757             else
17758                 last->next = link;
17759             last = link;
17760         }
17761
17762     }
17763
17764     return (0);
17765 internal_error:
17766     PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17767         "an error occured");
17768     return (-1);
17769 }
17770
17771 static int
17772 xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17773                                              xmlSchemaTypePtr type)
17774 {
17775     xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17776     /*
17777     * The actual value is then formed by replacing any union type
17778     * definition in the `explicit members` with the members of their
17779     * {member type definitions}, in order.
17780     *
17781     * TODO: There's a bug entry at
17782     * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17783     * which indicates that we'll keep the union types the future.
17784     */
17785     link = type->memberTypes;
17786     while (link != NULL) {
17787
17788         if (WXS_IS_TYPE_NOT_FIXED(link->type))
17789             xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
17790
17791         if (WXS_IS_UNION(link->type)) {
17792             subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
17793             if (subLink != NULL) {
17794                 link->type = subLink->type;
17795                 if (subLink->next != NULL) {
17796                     lastLink = link->next;
17797                     subLink = subLink->next;
17798                     prevLink = link;
17799                     while (subLink != NULL) {
17800                         newLink = (xmlSchemaTypeLinkPtr)
17801                             xmlMalloc(sizeof(xmlSchemaTypeLink));
17802                         if (newLink == NULL) {
17803                             xmlSchemaPErrMemory(pctxt, "allocating a type link",
17804                                 NULL);
17805                             return (-1);
17806                         }
17807                         newLink->type = subLink->type;
17808                         prevLink->next = newLink;
17809                         prevLink = newLink;
17810                         newLink->next = lastLink;
17811
17812                         subLink = subLink->next;
17813                     }
17814                 }
17815             }
17816         }
17817         link = link->next;
17818     }
17819     return (0);
17820 }
17821
17822 static void
17823 xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17824 {
17825     int has = 0, needVal = 0, normVal = 0;
17826
17827     has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17828     if (has) {
17829         needVal = (type->baseType->flags &
17830             XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17831         normVal = (type->baseType->flags &
17832             XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17833     }
17834     if (type->facets != NULL) {
17835         xmlSchemaFacetPtr fac;
17836
17837         for (fac = type->facets; fac != NULL; fac = fac->next) {
17838             switch (fac->type) {
17839                 case XML_SCHEMA_FACET_WHITESPACE:
17840                     break;
17841                 case XML_SCHEMA_FACET_PATTERN:
17842                     normVal = 1;
17843                     has = 1;
17844                     break;
17845                 case XML_SCHEMA_FACET_ENUMERATION:
17846                     needVal = 1;
17847                     normVal = 1;
17848                     has = 1;
17849                     break;
17850                 default:
17851                     has = 1;
17852                     break;
17853             }
17854         }
17855     }
17856     if (normVal)
17857         type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17858     if (needVal)
17859         type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17860     if (has)
17861         type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17862
17863     if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
17864         xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17865         /*
17866         * OPTIMIZE VAL TODO: Some facets need a computed value.
17867         */
17868         if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17869             (prim->builtInType != XML_SCHEMAS_STRING)) {
17870             type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17871         }
17872     }
17873 }
17874
17875 static int
17876 xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17877 {
17878
17879
17880     /*
17881     * Evaluate the whitespace-facet value.
17882     */
17883     if (WXS_IS_LIST(type)) {
17884         type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17885         return (0);
17886     } else if (WXS_IS_UNION(type))
17887         return (0);
17888
17889     if (type->facetSet != NULL) {
17890         xmlSchemaFacetLinkPtr lin;
17891
17892         for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17893             if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17894                 switch (lin->facet->whitespace) {
17895                 case XML_SCHEMAS_FACET_PRESERVE:
17896                     type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17897                     break;
17898                 case XML_SCHEMAS_FACET_REPLACE:
17899                     type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17900                     break;
17901                 case XML_SCHEMAS_FACET_COLLAPSE:
17902                     type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17903                     break;
17904                 default:
17905                     return (-1);
17906                 }
17907                 return (0);
17908             }
17909         }
17910     }
17911     /*
17912     * For all `atomic` datatypes other than string (and types `derived`
17913     * by `restriction` from it) the value of whiteSpace is fixed to
17914     * collapse
17915     */
17916     {
17917         xmlSchemaTypePtr anc;
17918
17919         for (anc = type->baseType; anc != NULL &&
17920                 anc->builtInType != XML_SCHEMAS_ANYTYPE;
17921                 anc = anc->baseType) {
17922
17923             if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17924                 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17925                     type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17926
17927                 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17928                     (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17929                     type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17930
17931                 } else
17932                     type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17933                 break;
17934             }
17935         }
17936     }
17937     return (0);
17938 }
17939
17940 static int
17941 xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17942                           xmlSchemaTypePtr type)
17943 {
17944     if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17945         return(0);
17946     if (! WXS_IS_TYPE_NOT_FIXED_1(type))
17947         return(0);
17948     type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
17949
17950     if (WXS_IS_LIST(type)) {
17951         /*
17952         * Corresponds to <simpleType><list>...
17953         */
17954         if (type->subtypes == NULL) {
17955             /*
17956             * This one is really needed, so get out.
17957             */
17958             PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17959                 "list type has no item-type assigned");
17960             return(-1);
17961         }
17962     } else if (WXS_IS_UNION(type)) {
17963         /*
17964         * Corresponds to <simpleType><union>...
17965         */
17966         if (type->memberTypes == NULL) {
17967             /*
17968             * This one is really needed, so get out.
17969             */
17970             PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17971                 "union type has no member-types assigned");
17972             return(-1);
17973         }
17974     } else {
17975         /*
17976         * Corresponds to <simpleType><restriction>...
17977         */
17978         if (type->baseType == NULL) {
17979             PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17980                 "type has no base-type assigned");
17981             return(-1);
17982         }
17983         if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
17984             if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17985                 return(-1);
17986         /*
17987         * Variety
17988         * If the <restriction> alternative is chosen, then the
17989         * {variety} of the {base type definition}.
17990         */
17991         if (WXS_IS_ATOMIC(type->baseType))
17992             type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
17993         else if (WXS_IS_LIST(type->baseType)) {
17994             type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
17995             /*
17996             * Inherit the itemType.
17997             */
17998             type->subtypes = type->baseType->subtypes;
17999         } else if (WXS_IS_UNION(type->baseType)) {
18000             type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
18001             /*
18002             * NOTE that we won't assign the memberTypes of the base,
18003             * since this will make trouble when freeing them; we will
18004             * use a lookup function to access them instead.
18005             */
18006         }
18007     }
18008     return(0);
18009 }
18010
18011 #ifdef DEBUG_TYPE
18012 static void
18013 xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
18014                        xmlSchemaTypePtr type)
18015 {
18016     if (type->node != NULL) {
18017         xmlGenericError(xmlGenericErrorContext,
18018                         "Type of %s : %s:%d :", name,
18019                         type->node->doc->URL,
18020                         xmlGetLineNo(type->node));
18021     } else {
18022         xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
18023     }
18024     if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
18025         switch (type->contentType) {
18026             case XML_SCHEMA_CONTENT_SIMPLE:
18027                 xmlGenericError(xmlGenericErrorContext, "simple\n");
18028                 break;
18029             case XML_SCHEMA_CONTENT_ELEMENTS:
18030                 xmlGenericError(xmlGenericErrorContext, "elements\n");
18031                 break;
18032             case XML_SCHEMA_CONTENT_UNKNOWN:
18033                 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
18034                 break;
18035             case XML_SCHEMA_CONTENT_EMPTY:
18036                 xmlGenericError(xmlGenericErrorContext, "empty\n");
18037                 break;
18038             case XML_SCHEMA_CONTENT_MIXED:
18039                 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
18040                     type->subtypes))
18041                     xmlGenericError(xmlGenericErrorContext,
18042                         "mixed as emptiable particle\n");
18043                 else
18044                     xmlGenericError(xmlGenericErrorContext, "mixed\n");
18045                 break;
18046                 /* Removed, since not used. */
18047                 /*
18048                 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
18049                 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
18050                 break;
18051                 */
18052             case XML_SCHEMA_CONTENT_BASIC:
18053                 xmlGenericError(xmlGenericErrorContext, "basic\n");
18054                 break;
18055             default:
18056                 xmlGenericError(xmlGenericErrorContext,
18057                     "not registered !!!\n");
18058                 break;
18059         }
18060     }
18061 }
18062 #endif
18063
18064 /*
18065 * 3.14.6 Constraints on Simple Type Definition Schema Components
18066 */
18067 static int
18068 xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
18069                                  xmlSchemaTypePtr type)
18070 {
18071     int res, olderrs = pctxt->nberrors;
18072
18073     if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18074         return(-1);
18075
18076     if (! WXS_IS_TYPE_NOT_FIXED(type))
18077         return(0);
18078
18079     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18080     type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
18081
18082     if (type->baseType == NULL) {
18083         PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
18084             "missing baseType");
18085         goto exit_failure;
18086     }
18087     if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
18088         xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
18089     /*
18090     * If a member type of a union is a union itself, we need to substitute
18091     * that member type for its member types.
18092     * NOTE that this might change in WXS 1.1; i.e. we will keep the union
18093     * types in WXS 1.1.
18094     */
18095     if ((type->memberTypes != NULL) &&
18096         (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
18097         return(-1);
18098     /*
18099     * SPEC src-simple-type 1
18100     * "The corresponding simple type definition, if any, must satisfy
18101     * the conditions set out in Constraints on Simple Type Definition
18102     * Schema Components ($3.14.6)."
18103     */
18104     /*
18105     * Schema Component Constraint: Simple Type Definition Properties Correct
18106     * (st-props-correct)
18107     */
18108     res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
18109     HFAILURE HERROR
18110     /*
18111     * Schema Component Constraint: Derivation Valid (Restriction, Simple)
18112     * (cos-st-restricts)
18113     */
18114     res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
18115     HFAILURE HERROR
18116     /*
18117     * TODO: Removed the error report, since it got annoying to get an
18118     * extra error report, if anything failed until now.
18119     * Enable this if needed.
18120     *
18121     * xmlSchemaPErr(ctxt, type->node,
18122     *    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
18123     *    "Simple type '%s' does not satisfy the constraints "
18124     *    "on simple type definitions.\n",
18125     *    type->name, NULL);
18126     */
18127     /*
18128     * Schema Component Constraint: Simple Type Restriction (Facets)
18129     * (st-restrict-facets)
18130     */
18131     res = xmlSchemaCheckFacetValues(type, pctxt);
18132     HFAILURE HERROR
18133     if ((type->facetSet != NULL) ||
18134         (type->baseType->facetSet != NULL)) {
18135         res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18136         HFAILURE HERROR
18137     }
18138     /*
18139     * Whitespace value.
18140     */
18141     res = xmlSchemaTypeFixupWhitespace(type);
18142     HFAILURE HERROR
18143     xmlSchemaTypeFixupOptimFacets(type);
18144
18145 exit_error:
18146 #ifdef DEBUG_TYPE
18147     xmlSchemaDebugFixedType(pctxt, type);
18148 #endif
18149     if (olderrs != pctxt->nberrors)
18150         return(pctxt->err);
18151     return(0);
18152
18153 exit_failure:
18154 #ifdef DEBUG_TYPE
18155     xmlSchemaDebugFixedType(pctxt, type);
18156 #endif
18157     return(-1);
18158 }
18159
18160 static int
18161 xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18162                           xmlSchemaTypePtr type)
18163 {
18164     int res = 0, olderrs = pctxt->nberrors;
18165     xmlSchemaTypePtr baseType = type->baseType;
18166
18167     if (! WXS_IS_TYPE_NOT_FIXED(type))
18168         return(0);
18169     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18170     if (baseType == NULL) {
18171         PERROR_INT("xmlSchemaFixupComplexType",
18172             "missing baseType");
18173         goto exit_failure;
18174     }
18175     /*
18176     * Fixup the base type.
18177     */
18178     if (WXS_IS_TYPE_NOT_FIXED(baseType))
18179         xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
18180     if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18181         /*
18182         * Skip fixup if the base type is invalid.
18183         * TODO: Generate a warning!
18184         */
18185         return(0);
18186     }
18187     /*
18188     * This basically checks if the base type can be derived.
18189     */
18190     res = xmlSchemaCheckSRCCT(pctxt, type);
18191     HFAILURE HERROR
18192     /*
18193     * Fixup the content type.
18194     */
18195     if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18196         /*
18197         * Corresponds to <complexType><simpleContent>...
18198         */
18199         if ((WXS_IS_COMPLEX(baseType)) &&
18200             (baseType->contentTypeDef != NULL) &&
18201             (WXS_IS_RESTRICTION(type))) {
18202             xmlSchemaTypePtr contentBase, content;
18203 #ifdef ENABLE_NAMED_LOCALS
18204             char buf[30];
18205             const xmlChar *tmpname;
18206 #endif
18207             /*
18208             * SPEC (1) If <restriction> + base type is <complexType>,
18209             * "whose own {content type} is a simple type..."
18210             */
18211             if (type->contentTypeDef != NULL) {
18212                 /*
18213                 * SPEC (1.1) "the simple type definition corresponding to the
18214                 * <simpleType> among the [children] of <restriction> if there
18215                 * is one;"
18216                 * Note that this "<simpleType> among the [children]" was put
18217                 * into ->contentTypeDef during parsing.
18218                 */
18219                 contentBase = type->contentTypeDef;
18220                 type->contentTypeDef = NULL;
18221             } else {
18222                 /*
18223                 * (1.2) "...otherwise (<restriction> has no <simpleType>
18224                 * among its [children]), the simple type definition which
18225                 * is the {content type} of the ... base type."
18226                 */
18227                 contentBase = baseType->contentTypeDef;
18228             }
18229             /*
18230             * SPEC
18231             * "... a simple type definition which restricts the simple
18232             * type definition identified in clause 1.1 or clause 1.2
18233             * with a set of facet components"
18234             *
18235             * Create the anonymous simple type, which will be the content
18236             * type of the complex type.
18237             */
18238 #ifdef ENABLE_NAMED_LOCALS
18239             snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18240             tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
18241             content = xmlSchemaAddType(pctxt, pctxt->schema,
18242                 XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
18243                 type->node, 0);
18244 #else
18245             content = xmlSchemaAddType(pctxt, pctxt->schema,
18246                 XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
18247                 type->node, 0);
18248 #endif
18249             if (content == NULL)
18250                 goto exit_failure;
18251             /*
18252             * We will use the same node as for the <complexType>
18253             * to have it somehow anchored in the schema doc.
18254             */
18255             content->type = XML_SCHEMA_TYPE_SIMPLE;
18256             content->baseType = contentBase;
18257             /*
18258             * Move the facets, previously anchored on the
18259             * complexType during parsing.
18260             */
18261             content->facets = type->facets;
18262             type->facets = NULL;
18263             content->facetSet = type->facetSet;
18264             type->facetSet = NULL;
18265
18266             type->contentTypeDef = content;
18267             if (WXS_IS_TYPE_NOT_FIXED(contentBase))
18268                 xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
18269             /*
18270             * Fixup the newly created type. We don't need to check
18271             * for circularity here.
18272             */
18273             res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18274             HFAILURE HERROR
18275             res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18276             HFAILURE HERROR
18277
18278         } else if ((WXS_IS_COMPLEX(baseType)) &&
18279             (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18280             (WXS_IS_RESTRICTION(type))) {
18281             /*
18282             * SPEC (2) If <restriction> + base is a mixed <complexType> with
18283             * an emptiable particle, then a simple type definition which
18284             * restricts the <restriction>'s <simpleType> child.
18285             */
18286             if ((type->contentTypeDef == NULL) ||
18287                 (type->contentTypeDef->baseType == NULL)) {
18288                 /*
18289                 * TODO: Check if this ever happens.
18290                 */
18291                 xmlSchemaPCustomErr(pctxt,
18292                     XML_SCHEMAP_INTERNAL,
18293                     WXS_BASIC_CAST type, NULL,
18294                     "Internal error: xmlSchemaTypeFixup, "
18295                     "complex type '%s': the <simpleContent><restriction> "
18296                     "is missing a <simpleType> child, but was not catched "
18297                     "by xmlSchemaCheckSRCCT()", type->name);
18298                 goto exit_failure;
18299             }
18300         } else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
18301             /*
18302             * SPEC (3) If <extension> + base is <complexType> with
18303             * <simpleType> content, "...then the {content type} of that
18304             * complex type definition"
18305             */
18306             if (baseType->contentTypeDef == NULL) {
18307                 /*
18308                 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18309                 * should have catched this already.
18310                 */
18311                 xmlSchemaPCustomErr(pctxt,
18312                     XML_SCHEMAP_INTERNAL,
18313                     WXS_BASIC_CAST type, NULL,
18314                     "Internal error: xmlSchemaTypeFixup, "
18315                     "complex type '%s': the <extension>ed base type is "
18316                     "a complex type with no simple content type",
18317                     type->name);
18318                 goto exit_failure;
18319             }
18320             type->contentTypeDef = baseType->contentTypeDef;
18321         } else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
18322             /*
18323             * SPEC (4) <extension> + base is <simpleType>
18324             * "... then that simple type definition"
18325             */
18326             type->contentTypeDef = baseType;
18327         } else {
18328             /*
18329             * TODO: Check if this ever happens.
18330             */
18331             xmlSchemaPCustomErr(pctxt,
18332                 XML_SCHEMAP_INTERNAL,
18333                 WXS_BASIC_CAST type, NULL,
18334                 "Internal error: xmlSchemaTypeFixup, "
18335                 "complex type '%s' with <simpleContent>: unhandled "
18336                 "derivation case", type->name);
18337             goto exit_failure;
18338         }
18339     } else {
18340         int dummySequence = 0;
18341         xmlSchemaParticlePtr particle =
18342             (xmlSchemaParticlePtr) type->subtypes;
18343         /*
18344         * Corresponds to <complexType><complexContent>...
18345         *
18346         * NOTE that the effective mixed was already set during parsing of
18347         * <complexType> and <complexContent>; its flag value is
18348         * XML_SCHEMAS_TYPE_MIXED.
18349         *
18350         * Compute the "effective content":
18351         * (2.1.1) + (2.1.2) + (2.1.3)
18352         */
18353         if ((particle == NULL) ||
18354             ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18355             ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18356             (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18357             ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18358             (particle->minOccurs == 0))) &&
18359             ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18360             if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18361                 /*
18362                 * SPEC (2.1.4) "If the `effective mixed` is true, then
18363                 * a particle whose properties are as follows:..."
18364                 *
18365                 * Empty sequence model group with
18366                 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18367                 * NOTE that we sill assign it the <complexType> node to
18368                 * somehow anchor it in the doc.
18369                 */
18370                 if ((particle == NULL) ||
18371                     (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18372                     /*
18373                     * Create the particle.
18374                     */
18375                     particle = xmlSchemaAddParticle(pctxt,
18376                         type->node, 1, 1);
18377                     if (particle == NULL)
18378                         goto exit_failure;
18379                     /*
18380                     * Create the model group.
18381                     */ /* URGENT TODO: avoid adding to pending items. */
18382                     particle->children = (xmlSchemaTreeItemPtr)
18383                         xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18384                         XML_SCHEMA_TYPE_SEQUENCE, type->node);
18385                     if (particle->children == NULL)
18386                         goto exit_failure;
18387
18388                     type->subtypes = (xmlSchemaTypePtr) particle;
18389                 }
18390                 dummySequence = 1;
18391                 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18392             } else {
18393                 /*
18394                 * SPEC (2.1.5) "otherwise empty"
18395                 */
18396                 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18397             }
18398         } else {
18399             /*
18400             * SPEC (2.2) "otherwise the particle corresponding to the
18401             * <all>, <choice>, <group> or <sequence> among the
18402             * [children]."
18403             */
18404             type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18405         }
18406         /*
18407         * Compute the "content type".
18408         */
18409         if (WXS_IS_RESTRICTION(type)) {
18410             /*
18411             * SPEC (3.1) "If <restriction>..."
18412             * (3.1.1) + (3.1.2) */
18413             if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18414                 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18415                     type->contentType = XML_SCHEMA_CONTENT_MIXED;
18416             }
18417         } else {
18418             /*
18419             * SPEC (3.2) "If <extension>..."
18420             */
18421             if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18422                 /*
18423                 * SPEC (3.2.1)
18424                 * "If the `effective content` is empty, then the
18425                 *  {content type} of the [...] base ..."
18426                 */
18427                 type->contentType = baseType->contentType;
18428                 type->subtypes = baseType->subtypes;
18429                 /*
18430                 * Fixes bug #347316:
18431                 * This is the case when the base type has a simple
18432                 * type definition as content.
18433                 */
18434                 type->contentTypeDef = baseType->contentTypeDef;
18435                 /*
18436                 * NOTE that the effective mixed is ignored here.
18437                 */
18438             } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18439                 /*
18440                 * SPEC (3.2.2)
18441                 */
18442                 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18443                     type->contentType = XML_SCHEMA_CONTENT_MIXED;
18444             } else {
18445                 /*
18446                 * SPEC (3.2.3)
18447                 */
18448                 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18449                     type->contentType = XML_SCHEMA_CONTENT_MIXED;
18450                     /*
18451                     * "A model group whose {compositor} is sequence and whose
18452                     * {particles} are..."
18453                     */
18454                 if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18455                     (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18456                     ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18457                         XML_SCHEMA_TYPE_ALL))
18458                 {
18459                     /*
18460                     * SPEC cos-all-limited (1)
18461                     */
18462                     xmlSchemaCustomErr(ACTXT_CAST pctxt,
18463                         /* TODO: error code */
18464                         XML_SCHEMAP_COS_ALL_LIMITED,
18465                         WXS_ITEM_NODE(type), NULL,
18466                         "The type has an 'all' model group in its "
18467                         "{content type} and thus cannot be derived from "
18468                         "a non-empty type, since this would produce a "
18469                         "'sequence' model group containing the 'all' "
18470                         "model group; 'all' model groups are not "
18471                         "allowed to appear inside other model groups",
18472                         NULL, NULL);
18473
18474                 } else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18475                     (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18476                     ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18477                         XML_SCHEMA_TYPE_ALL))
18478                 {
18479                     /*
18480                     * SPEC cos-all-limited (1)
18481                     */
18482                     xmlSchemaCustomErr(ACTXT_CAST pctxt,
18483                         /* TODO: error code */
18484                         XML_SCHEMAP_COS_ALL_LIMITED,
18485                         WXS_ITEM_NODE(type), NULL,
18486                         "A type cannot be derived by extension from a type "
18487                         "which has an 'all' model group in its "
18488                         "{content type}, since this would produce a "
18489                         "'sequence' model group containing the 'all' "
18490                         "model group; 'all' model groups are not "
18491                         "allowed to appear inside other model groups",
18492                         NULL, NULL);
18493
18494                 } else if (! dummySequence) {
18495                     xmlSchemaTreeItemPtr effectiveContent =
18496                         (xmlSchemaTreeItemPtr) type->subtypes;
18497                     /*
18498                     * Create the particle.
18499                     */
18500                     particle = xmlSchemaAddParticle(pctxt,
18501                         type->node, 1, 1);
18502                     if (particle == NULL)
18503                         goto exit_failure;
18504                     /*
18505                     * Create the "sequence" model group.
18506                     */
18507                     particle->children = (xmlSchemaTreeItemPtr)
18508                         xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18509                         XML_SCHEMA_TYPE_SEQUENCE, type->node);
18510                     if (particle->children == NULL)
18511                         goto exit_failure;
18512                     WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
18513                     /*
18514                     * SPEC "the particle of the {content type} of
18515                     * the ... base ..."
18516                     * Create a duplicate of the base type's particle
18517                     * and assign its "term" to it.
18518                     */
18519                     particle->children->children =
18520                         (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18521                         type->node,
18522                         ((xmlSchemaParticlePtr) baseType->subtypes)->minOccurs,
18523                         ((xmlSchemaParticlePtr) baseType->subtypes)->maxOccurs);
18524                     if (particle->children->children == NULL)
18525                         goto exit_failure;
18526                     particle = (xmlSchemaParticlePtr)
18527                         particle->children->children;
18528                     particle->children =
18529                         ((xmlSchemaParticlePtr) baseType->subtypes)->children;
18530                     /*
18531                     * SPEC "followed by the `effective content`."
18532                     */
18533                     particle->next = effectiveContent;
18534                     /*
18535                     * This all will result in:
18536                     * new-particle
18537                     *   --> new-sequence(
18538                     *         new-particle
18539                     *           --> base-model,
18540                     *         this-particle
18541                     *           --> this-model
18542                     *       )
18543                     */
18544                 } else {
18545                     /*
18546                     * This is the case when there is already an empty
18547                     * <sequence> with minOccurs==maxOccurs==1.
18548                     * Just add the base types's content type.
18549                     * NOTE that, although we miss to add an intermediate
18550                     * <sequence>, this should produce no difference to
18551                     * neither the regex compilation of the content model,
18552                     * nor to the complex type contraints.
18553                     */
18554                     particle->children->children =
18555                         (xmlSchemaTreeItemPtr) baseType->subtypes;
18556                 }
18557             }
18558         }
18559     }
18560     /*
18561     * Now fixup attribute uses:
18562     *   - expand attr. group references
18563     *     - intersect attribute wildcards
18564     *   - inherit attribute uses of the base type
18565     *   - inherit or union attr. wildcards if extending
18566     *   - apply attr. use prohibitions if restricting
18567     */
18568     res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
18569     HFAILURE HERROR
18570     /*
18571     * Apply the complex type component constraints; this will not
18572     * check attributes, since this is done in
18573     * xmlSchemaFixupTypeAttributeUses().
18574     */
18575     res = xmlSchemaCheckCTComponent(pctxt, type);
18576     HFAILURE HERROR
18577
18578 #ifdef DEBUG_TYPE
18579     xmlSchemaDebugFixedType(pctxt, type);
18580 #endif
18581     if (olderrs != pctxt->nberrors)
18582         return(pctxt->err);
18583     else
18584         return(0);
18585
18586 exit_error:
18587     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18588 #ifdef DEBUG_TYPE
18589     xmlSchemaDebugFixedType(pctxt, type);
18590 #endif
18591     return(pctxt->err);
18592
18593 exit_failure:
18594     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18595 #ifdef DEBUG_TYPE
18596     xmlSchemaDebugFixedType(pctxt, type);
18597 #endif
18598     return(-1);
18599 }
18600
18601
18602 /**
18603  * xmlSchemaTypeFixup:
18604  * @typeDecl:  the schema type definition
18605  * @ctxt:  the schema parser context
18606  *
18607  * Fixes the content model of the type.
18608  * URGENT TODO: We need an int result!
18609  */
18610 static int
18611 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
18612                    xmlSchemaAbstractCtxtPtr actxt)
18613 {
18614     if (type == NULL)
18615         return(0);
18616     if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18617         AERROR_INT("xmlSchemaTypeFixup",
18618             "this function needs a parser context");
18619         return(-1);
18620     }
18621     if (! WXS_IS_TYPE_NOT_FIXED(type))
18622         return(0);
18623     if (type->type == XML_SCHEMA_TYPE_COMPLEX)
18624         return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
18625     else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
18626         return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
18627     return(0);
18628 }
18629
18630 /**
18631  * xmlSchemaCheckFacet:
18632  * @facet:  the facet
18633  * @typeDecl:  the schema type definition
18634  * @pctxt:  the schema parser context or NULL
18635  * @name: the optional name of the type
18636  *
18637  * Checks and computes the values of facets.
18638  *
18639  * Returns 0 if valid, a positive error code if not valid and
18640  *         -1 in case of an internal or API error.
18641  */
18642 int
18643 xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
18644                     xmlSchemaTypePtr typeDecl,
18645                     xmlSchemaParserCtxtPtr pctxt,
18646                     const xmlChar * name ATTRIBUTE_UNUSED)
18647 {
18648     int ret = 0, ctxtGiven;
18649
18650     if ((facet == NULL) || (typeDecl == NULL))
18651         return(-1);
18652     /*
18653     * TODO: will the parser context be given if used from
18654     * the relaxNG module?
18655     */
18656     if (pctxt == NULL)
18657         ctxtGiven = 0;
18658     else
18659         ctxtGiven = 1;
18660
18661     switch (facet->type) {
18662         case XML_SCHEMA_FACET_MININCLUSIVE:
18663         case XML_SCHEMA_FACET_MINEXCLUSIVE:
18664         case XML_SCHEMA_FACET_MAXINCLUSIVE:
18665         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18666         case XML_SCHEMA_FACET_ENUMERATION: {
18667                 /*
18668                  * Okay we need to validate the value
18669                  * at that point.
18670                  */
18671                 xmlSchemaTypePtr base;
18672
18673                 /* 4.3.5.5 Constraints on enumeration Schema Components
18674                 * Schema Component Constraint: enumeration valid restriction
18675                 * It is an `error` if any member of {value} is not in the
18676                 * `value space` of {base type definition}.
18677                 *
18678                 * minInclusive, maxInclusive, minExclusive, maxExclusive:
18679                 * The value `must` be in the
18680                 * `value space` of the `base type`.
18681                 */
18682                 /*
18683                 * This function is intended to deliver a compiled value
18684                 * on the facet. In this implementation of XML Schemata the
18685                 * type holding a facet, won't be a built-in type.
18686                 * Thus to ensure that other API
18687                 * calls (relaxng) do work, if the given type is a built-in
18688                 * type, we will assume that the given built-in type *is
18689                 * already* the base type.
18690                 */
18691                 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18692                     base = typeDecl->baseType;
18693                     if (base == NULL) {
18694                         PERROR_INT("xmlSchemaCheckFacet",
18695                             "a type user derived type has no base type");
18696                         return (-1);
18697                     }
18698                 } else
18699                     base = typeDecl;
18700
18701                 if (! ctxtGiven) {
18702                     /*
18703                     * A context is needed if called from RelaxNG.
18704                     */
18705                     pctxt = xmlSchemaNewParserCtxt("*");
18706                     if (pctxt == NULL)
18707                         return (-1);
18708                 }
18709                 /*
18710                 * NOTE: This call does not check the content nodes,
18711                 * since they are not available:
18712                 * facet->node is just the node holding the facet
18713                 * definition, *not* the attribute holding the *value*
18714                 * of the facet.
18715                 */
18716                 ret = xmlSchemaVCheckCVCSimpleType(
18717                     ACTXT_CAST pctxt, facet->node, base,
18718                     facet->value, &(facet->val), 1, 1, 0);
18719                 if (ret != 0) {
18720                     if (ret < 0) {
18721                         /* No error message for RelaxNG. */
18722                         if (ctxtGiven) {
18723                             xmlSchemaCustomErr(ACTXT_CAST pctxt,
18724                                 XML_SCHEMAP_INTERNAL, facet->node, NULL,
18725                                 "Internal error: xmlSchemaCheckFacet, "
18726                                 "failed to validate the value '%s' of the "
18727                                 "facet '%s' against the base type",
18728                                 facet->value, xmlSchemaFacetTypeToString(facet->type));
18729                         }
18730                         goto internal_error;
18731                     }
18732                     ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18733                     /* No error message for RelaxNG. */
18734                     if (ctxtGiven) {
18735                         xmlChar *str = NULL;
18736
18737                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
18738                             ret, facet->node, WXS_BASIC_CAST facet,
18739                             "The value '%s' of the facet does not validate "
18740                             "against the base type '%s'",
18741                             facet->value,
18742                             xmlSchemaFormatQName(&str,
18743                                 base->targetNamespace, base->name));
18744                         FREE_AND_NULL(str);
18745                     }
18746                     goto exit;
18747                 } else if (facet->val == NULL) {
18748                     if (ctxtGiven) {
18749                         PERROR_INT("xmlSchemaCheckFacet",
18750                             "value was not computed");
18751                     }
18752                     TODO
18753                 }
18754                 break;
18755             }
18756         case XML_SCHEMA_FACET_PATTERN:
18757             facet->regexp = xmlRegexpCompile(facet->value);
18758             if (facet->regexp == NULL) {
18759                 ret = XML_SCHEMAP_REGEXP_INVALID;
18760                 /* No error message for RelaxNG. */
18761                 if (ctxtGiven) {
18762                     xmlSchemaCustomErr(ACTXT_CAST pctxt,
18763                         ret, facet->node, WXS_BASIC_CAST typeDecl,
18764                         "The value '%s' of the facet 'pattern' is not a "
18765                         "valid regular expression",
18766                         facet->value, NULL);
18767                 }
18768             }
18769             break;
18770         case XML_SCHEMA_FACET_TOTALDIGITS:
18771         case XML_SCHEMA_FACET_FRACTIONDIGITS:
18772         case XML_SCHEMA_FACET_LENGTH:
18773         case XML_SCHEMA_FACET_MAXLENGTH:
18774         case XML_SCHEMA_FACET_MINLENGTH:
18775
18776             if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18777                 ret = xmlSchemaValidatePredefinedType(
18778                     xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18779                     facet->value, &(facet->val));
18780             } else {
18781                 ret = xmlSchemaValidatePredefinedType(
18782                     xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18783                     facet->value, &(facet->val));
18784             }
18785             if (ret != 0) {
18786                 if (ret < 0) {
18787                     /* No error message for RelaxNG. */
18788                     if (ctxtGiven) {
18789                         PERROR_INT("xmlSchemaCheckFacet",
18790                             "validating facet value");
18791                     }
18792                     goto internal_error;
18793                 }
18794                 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18795                 /* No error message for RelaxNG. */
18796                 if (ctxtGiven) {
18797                     /* error code */
18798                     xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18799                         ret, facet->node, WXS_BASIC_CAST typeDecl,
18800                         "The value '%s' of the facet '%s' is not a valid '%s'",
18801                         facet->value,
18802                         xmlSchemaFacetTypeToString(facet->type),
18803                         (facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18804                             BAD_CAST "nonNegativeInteger" :
18805                             BAD_CAST "positiveInteger",
18806                         NULL);
18807                 }
18808             }
18809             break;
18810
18811         case XML_SCHEMA_FACET_WHITESPACE:{
18812                 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18813                     facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18814                 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18815                     facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18816                 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18817                     facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18818                 } else {
18819                     ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18820                     /* No error message for RelaxNG. */
18821                     if (ctxtGiven) {
18822                         /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
18823                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
18824                             ret, facet->node, WXS_BASIC_CAST typeDecl,
18825                             "The value '%s' of the facet 'whitespace' is not "
18826                             "valid", facet->value, NULL);
18827                     }
18828                 }
18829             }
18830         default:
18831             break;
18832     }
18833 exit:
18834     if ((! ctxtGiven) && (pctxt != NULL))
18835         xmlSchemaFreeParserCtxt(pctxt);
18836     return (ret);
18837 internal_error:
18838     if ((! ctxtGiven) && (pctxt != NULL))
18839         xmlSchemaFreeParserCtxt(pctxt);
18840     return (-1);
18841 }
18842
18843 /**
18844  * xmlSchemaCheckFacetValues:
18845  * @typeDecl:  the schema type definition
18846  * @ctxt:  the schema parser context
18847  *
18848  * Checks the default values types, especially for facets
18849  */
18850 static int
18851 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
18852                           xmlSchemaParserCtxtPtr pctxt)
18853 {
18854     int res, olderrs = pctxt->nberrors;
18855     const xmlChar *name = typeDecl->name;
18856     /*
18857     * NOTE: It is intended to use the facets list, instead
18858     * of facetSet.
18859     */
18860     if (typeDecl->facets != NULL) {
18861         xmlSchemaFacetPtr facet = typeDecl->facets;
18862
18863         /*
18864         * Temporarily assign the "schema" to the validation context
18865         * of the parser context. This is needed for NOTATION validation.
18866         */
18867         if (pctxt->vctxt == NULL) {
18868             if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18869                 return(-1);
18870         }
18871         pctxt->vctxt->schema = pctxt->schema;
18872         while (facet != NULL) {
18873             res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18874             HFAILURE
18875             facet = facet->next;
18876         }
18877         pctxt->vctxt->schema = NULL;
18878     }
18879     if (olderrs != pctxt->nberrors)
18880         return(pctxt->err);
18881     return(0);
18882 exit_failure:
18883     return(-1);
18884 }
18885
18886 /**
18887  * xmlSchemaGetCircModelGrDefRef:
18888  * @ctxtMGroup: the searched model group
18889  * @selfMGroup: the second searched model group
18890  * @particle: the first particle
18891  *
18892  * This one is intended to be used by
18893  * xmlSchemaCheckGroupDefCircular only.
18894  *
18895  * Returns the particle with the circular model group definition reference,
18896  * otherwise NULL.
18897  */
18898 static xmlSchemaTreeItemPtr
18899 xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
18900                               xmlSchemaTreeItemPtr particle)
18901 {
18902     xmlSchemaTreeItemPtr circ = NULL;
18903     xmlSchemaTreeItemPtr term;
18904     xmlSchemaModelGroupDefPtr gdef;
18905
18906     for (; particle != NULL; particle = particle->next) {
18907         term = particle->children;
18908         if (term == NULL)
18909             continue;
18910         switch (term->type) {
18911             case XML_SCHEMA_TYPE_GROUP:
18912                 gdef = (xmlSchemaModelGroupDefPtr) term;
18913                 if (gdef == groupDef)
18914                     return (particle);
18915                 /*
18916                 * Mark this model group definition to avoid infinite
18917                 * recursion on circular references not yet examined.
18918                 */
18919                 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18920                     continue;
18921                 if (gdef->children != NULL) {
18922                     gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18923                     circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18924                         gdef->children->children);
18925                     gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18926                     if (circ != NULL)
18927                         return (circ);
18928                 }
18929                 break;
18930             case XML_SCHEMA_TYPE_SEQUENCE:
18931             case XML_SCHEMA_TYPE_CHOICE:
18932             case XML_SCHEMA_TYPE_ALL:
18933                 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18934                 if (circ != NULL)
18935                     return (circ);
18936                 break;
18937             default:
18938                 break;
18939         }
18940     }
18941     return (NULL);
18942 }
18943
18944 /**
18945  * xmlSchemaCheckGroupDefCircular:
18946  * @item:  the model group definition
18947  * @ctxt:  the parser context
18948  * @name:  the name
18949  *
18950  * Checks for circular references to model group definitions.
18951  */
18952 static void
18953 xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
18954                                xmlSchemaParserCtxtPtr ctxt)
18955 {
18956     /*
18957     * Schema Component Constraint: Model Group Correct
18958     * 2 Circular groups are disallowed. That is, within the {particles}
18959     * of a group there must not be at any depth a particle whose {term}
18960     * is the group itself.
18961     */
18962     if ((item == NULL) ||
18963         (item->type != XML_SCHEMA_TYPE_GROUP) ||
18964         (item->children == NULL))
18965         return;
18966     {
18967         xmlSchemaTreeItemPtr circ;
18968
18969         circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
18970         if (circ != NULL) {
18971             xmlChar *str = NULL;
18972             /*
18973             * TODO: The error report is not adequate: this constraint
18974             * is defined for model groups but not definitions, but since
18975             * there cannot be any circular model groups without a model group
18976             * definition (if not using a construction API), we check those
18977             * defintions only.
18978             */
18979             xmlSchemaPCustomErr(ctxt,
18980                 XML_SCHEMAP_MG_PROPS_CORRECT_2,
18981                 NULL, WXS_ITEM_NODE(circ),
18982                 "Circular reference to the model group definition '%s' "
18983                 "defined", xmlSchemaFormatQName(&str,
18984                     item->targetNamespace, item->name));
18985             FREE_AND_NULL(str)
18986             /*
18987             * NOTE: We will cut the reference to avoid further
18988             * confusion of the processor. This is a fatal error.
18989             */
18990             circ->children = NULL;
18991         }
18992     }
18993 }
18994
18995 /**
18996  * xmlSchemaModelGroupToModelGroupDefFixup:
18997  * @ctxt:  the parser context
18998  * @mg:  the model group
18999  *
19000  * Assigns the model group of model group definitions to the "term"
19001  * of the referencing particle.
19002  * In xmlSchemaResolveModelGroupParticleReferences the model group
19003  * definitions were assigned to the "term", since needed for the
19004  * circularity check.
19005  *
19006  * Schema Component Constraint:
19007  *     All Group Limited (cos-all-limited) (1.2)
19008  */
19009 static void
19010 xmlSchemaModelGroupToModelGroupDefFixup(
19011     xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
19012     xmlSchemaModelGroupPtr mg)
19013 {
19014     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19015
19016     while (particle != NULL) {
19017         if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19018             ((WXS_PARTICLE_TERM(particle))->type !=
19019                 XML_SCHEMA_TYPE_GROUP))
19020         {
19021             particle = WXS_PTC_CAST particle->next;
19022             continue;
19023         }
19024         if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
19025             /*
19026             * TODO: Remove the particle.
19027             */
19028             WXS_PARTICLE_TERM(particle) = NULL;
19029             particle = WXS_PTC_CAST particle->next;
19030             continue;
19031         }
19032         /*
19033         * Assign the model group to the {term} of the particle.
19034         */
19035         WXS_PARTICLE_TERM(particle) =
19036             WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
19037
19038         particle = WXS_PTC_CAST particle->next;
19039     }
19040 }
19041
19042 /**
19043  * xmlSchemaCheckAttrGroupCircularRecur:
19044  * @ctxtGr: the searched attribute group
19045  * @attr: the current attribute list to be processed
19046  *
19047  * This one is intended to be used by
19048  * xmlSchemaCheckAttrGroupCircular only.
19049  *
19050  * Returns the circular attribute grou reference, otherwise NULL.
19051  */
19052 static xmlSchemaQNameRefPtr
19053 xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
19054                                      xmlSchemaItemListPtr list)
19055 {
19056     xmlSchemaAttributeGroupPtr gr;
19057     xmlSchemaQNameRefPtr ref, circ;
19058     int i;
19059     /*
19060     * We will search for an attribute group reference which
19061     * references the context attribute group.
19062     */
19063     for (i = 0; i < list->nbItems; i++) {
19064         ref = list->items[i];
19065         if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19066             (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
19067             (ref->item != NULL))
19068         {
19069             gr = WXS_ATTR_GROUP_CAST ref->item;
19070             if (gr == ctxtGr)
19071                 return(ref);
19072             if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
19073                 continue;
19074             /*
19075             * Mark as visited to avoid infinite recursion on
19076             * circular references not yet examined.
19077             */
19078             if ((gr->attrUses) &&
19079                 (gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
19080             {
19081                 gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
19082                 circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
19083                     (xmlSchemaItemListPtr) gr->attrUses);
19084                 gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
19085                 if (circ != NULL)
19086                     return (circ);
19087             }
19088
19089         }
19090     }
19091     return (NULL);
19092 }
19093
19094 /**
19095  * xmlSchemaCheckAttrGroupCircular:
19096  * attrGr:  the attribute group definition
19097  * @ctxt:  the parser context
19098  * @name:  the name
19099  *
19100  * Checks for circular references of attribute groups.
19101  */
19102 static int
19103 xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
19104                                 xmlSchemaParserCtxtPtr ctxt)
19105 {
19106     /*
19107     * Schema Representation Constraint:
19108     * Attribute Group Definition Representation OK
19109     * 3 Circular group reference is disallowed outside <redefine>.
19110     * That is, unless this element information item's parent is
19111     * <redefine>, then among the [children], if any, there must
19112     * not be an <attributeGroup> with ref [attribute] which resolves
19113     * to the component corresponding to this <attributeGroup>. Indirect
19114     * circularity is also ruled out. That is, when QName resolution
19115     * (Schema Document) ($3.15.3) is applied to a `QName` arising from
19116     * any <attributeGroup>s with a ref [attribute] among the [children],
19117     * it must not be the case that a `QName` is encountered at any depth
19118     * which resolves to the component corresponding to this <attributeGroup>.
19119     */
19120     if (attrGr->attrUses == NULL)
19121         return(0);
19122     else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
19123         return(0);
19124     else {
19125         xmlSchemaQNameRefPtr circ;
19126
19127         circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
19128             (xmlSchemaItemListPtr) attrGr->attrUses);
19129         if (circ != NULL) {
19130             xmlChar *str = NULL;
19131             /*
19132             * TODO: Report the referenced attr group as QName.
19133             */
19134             xmlSchemaPCustomErr(ctxt,
19135                 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
19136                 NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
19137                 "Circular reference to the attribute group '%s' "
19138                 "defined", xmlSchemaGetComponentQName(&str, attrGr));
19139             FREE_AND_NULL(str);
19140             /*
19141             * NOTE: We will cut the reference to avoid further
19142             * confusion of the processor.
19143             * BADSPEC TODO: The spec should define how to process in this case.
19144             */
19145             circ->item = NULL;
19146             return(ctxt->err);
19147         }
19148     }
19149     return(0);
19150 }
19151
19152 static int
19153 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19154                                   xmlSchemaAttributeGroupPtr attrGr);
19155
19156 /**
19157  * xmlSchemaExpandAttributeGroupRefs:
19158  * @pctxt: the parser context
19159  * @node: the node of the component holding the attribute uses
19160  * @completeWild: the intersected wildcard to be returned
19161  * @list: the attribute uses
19162  *
19163  * Substitutes contained attribute group references
19164  * for their attribute uses. Wilcards are intersected.
19165  * Attribute use prohibitions are removed from the list
19166  * and returned via the @prohibs list.
19167  * Pointlessness of attr. prohibs, if a matching attr. decl
19168  * is existent a well, are checked.
19169  */
19170 static int
19171 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19172                                   xmlSchemaBasicItemPtr item,
19173                                   xmlSchemaWildcardPtr *completeWild,
19174                                   xmlSchemaItemListPtr list,
19175                                   xmlSchemaItemListPtr prohibs)
19176 {
19177     xmlSchemaAttributeGroupPtr gr;
19178     xmlSchemaAttributeUsePtr use;
19179     xmlSchemaItemListPtr sublist;
19180     int i, j;
19181     int created = (*completeWild == NULL) ? 0 : 1;
19182
19183     if (prohibs)
19184         prohibs->nbItems = 0;
19185
19186     for (i = 0; i < list->nbItems; i++) {
19187         use = list->items[i];
19188
19189         if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19190             if (prohibs == NULL) {
19191                 PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19192                     "unexpected attr prohibition found");
19193                 return(-1);
19194             }
19195             /*
19196             * Remove from attribute uses.
19197             */
19198             if (xmlSchemaItemListRemove(list, i) == -1)
19199                 return(-1);
19200             i--;
19201             /*
19202             * Note that duplicate prohibitions were already
19203             * handled at parsing time.
19204             */
19205             /*
19206             * Add to list of prohibitions.
19207             */
19208             xmlSchemaItemListAddSize(prohibs, 2, use);
19209             continue;
19210         }
19211         if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19212             ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19213         {
19214             if ((WXS_QNAME_CAST use)->item == NULL)
19215                 return(-1);
19216             gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19217             /*
19218             * Expand the referenced attr. group.
19219             * TODO: remove this, this is done in a previous step, so
19220             * already done here.
19221             */
19222             if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19223                 if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19224                     return(-1);
19225             }
19226             /*
19227             * Build the 'complete' wildcard; i.e. intersect multiple
19228             * wildcards.
19229             */
19230             if (gr->attributeWildcard != NULL) {
19231                 if (*completeWild == NULL) {
19232                     *completeWild = gr->attributeWildcard;
19233                 } else {
19234                     if (! created) {
19235                         xmlSchemaWildcardPtr tmpWild;
19236
19237                          /*
19238                         * Copy the first encountered wildcard as context,
19239                         * except for the annotation.
19240                         *
19241                         * Although the complete wildcard might not correspond
19242                         * to any node in the schema, we will anchor it on
19243                         * the node of the owner component.
19244                         */
19245                         tmpWild =  xmlSchemaAddWildcard(pctxt, pctxt->schema,
19246                             XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19247                             WXS_ITEM_NODE(item));
19248                         if (tmpWild == NULL)
19249                             return(-1);
19250                         if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19251                             tmpWild, *completeWild) == -1)
19252                             return (-1);
19253                         tmpWild->processContents = (*completeWild)->processContents;
19254                         *completeWild = tmpWild;
19255                         created = 1;
19256                     }
19257
19258                     if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19259                         gr->attributeWildcard) == -1)
19260                         return(-1);
19261                 }
19262             }
19263             /*
19264             * Just remove the reference if the referenced group does not
19265             * contain any attribute uses.
19266             */
19267             sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19268             if ((sublist == NULL) || sublist->nbItems == 0) {
19269                 if (xmlSchemaItemListRemove(list, i) == -1)
19270                     return(-1);
19271                 i--;
19272                 continue;
19273             }
19274             /*
19275             * Add the attribute uses.
19276             */
19277             list->items[i] = sublist->items[0];
19278             if (sublist->nbItems != 1) {
19279                 for (j = 1; j < sublist->nbItems; j++) {
19280                     i++;
19281                     if (xmlSchemaItemListInsert(list,
19282                             sublist->items[j], i) == -1)
19283                         return(-1);
19284                 }
19285             }
19286         }
19287
19288     }
19289     /*
19290     * Handle pointless prohibitions of declared attributes.
19291     */
19292     if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19293         xmlSchemaAttributeUseProhibPtr prohib;
19294
19295         for (i = prohibs->nbItems -1; i >= 0; i--) {
19296             prohib = prohibs->items[i];
19297             for (j = 0; j < list->nbItems; j++) {
19298                 use = list->items[j];
19299
19300                 if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19301                     (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19302                 {
19303                     xmlChar *str = NULL;
19304
19305                     xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19306                         XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19307                         prohib->node, NULL,
19308                         "Skipping pointless attribute use prohibition "
19309                         "'%s', since a corresponding attribute use "
19310                         "exists already in the type definition",
19311                         xmlSchemaFormatQName(&str,
19312                             prohib->targetNamespace, prohib->name),
19313                         NULL, NULL);
19314                     FREE_AND_NULL(str);
19315                     /*
19316                     * Remove the prohibition.
19317                     */
19318                     if (xmlSchemaItemListRemove(prohibs, i) == -1)
19319                         return(-1);
19320                     break;
19321                 }
19322             }
19323         }
19324     }
19325     return(0);
19326 }
19327
19328 /**
19329  * xmlSchemaAttributeGroupExpandRefs:
19330  * @pctxt:  the parser context
19331  * @attrGr:  the attribute group definition
19332  *
19333  * Computation of:
19334  * {attribute uses} property
19335  * {attribute wildcard} property
19336  *
19337  * Substitutes contained attribute group references
19338  * for their attribute uses. Wilcards are intersected.
19339  */
19340 static int
19341 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19342                                   xmlSchemaAttributeGroupPtr attrGr)
19343 {
19344     if ((attrGr->attrUses == NULL) ||
19345         (attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19346         return(0);
19347
19348     attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19349     if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19350         &(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19351         return(-1);
19352     return(0);
19353 }
19354
19355 /**
19356  * xmlSchemaAttributeGroupExpandRefs:
19357  * @pctxt:  the parser context
19358  * @attrGr:  the attribute group definition
19359  *
19360  * Substitutes contained attribute group references
19361  * for their attribute uses. Wilcards are intersected.
19362  *
19363  * Schema Component Constraint:
19364  *    Attribute Group Definition Properties Correct (ag-props-correct)
19365  */
19366 static int
19367 xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19368                                   xmlSchemaAttributeGroupPtr attrGr)
19369 {
19370     /*
19371     * SPEC ag-props-correct
19372     * (1) "The values of the properties of an attribute group definition
19373     * must be as described in the property tableau in The Attribute
19374     * Group Definition Schema Component ($3.6.1), modulo the impact of
19375     * Missing Sub-components ($5.3);"
19376     */
19377
19378     if ((attrGr->attrUses != NULL) &&
19379         (WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19380     {
19381         xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19382         xmlSchemaAttributeUsePtr use, tmp;
19383         int i, j, hasId = 0;
19384
19385         for (i = uses->nbItems -1; i >= 0; i--) {
19386             use = uses->items[i];
19387             /*
19388             * SPEC ag-props-correct
19389             * (2) "Two distinct members of the {attribute uses} must not have
19390             * {attribute declaration}s both of whose {name}s match and whose
19391             * {target namespace}s are identical."
19392             */
19393             if (i > 0) {
19394                 for (j = i -1; j >= 0; j--) {
19395                     tmp = uses->items[j];
19396                     if ((WXS_ATTRUSE_DECL_NAME(use) ==
19397                         WXS_ATTRUSE_DECL_NAME(tmp)) &&
19398                         (WXS_ATTRUSE_DECL_TNS(use) ==
19399                         WXS_ATTRUSE_DECL_TNS(tmp)))
19400                     {
19401                         xmlChar *str = NULL;
19402
19403                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
19404                             XML_SCHEMAP_AG_PROPS_CORRECT,
19405                             attrGr->node, WXS_BASIC_CAST attrGr,
19406                             "Duplicate %s",
19407                             xmlSchemaGetComponentDesignation(&str, use),
19408                             NULL);
19409                         FREE_AND_NULL(str);
19410                         /*
19411                         * Remove the duplicate.
19412                         */
19413                         if (xmlSchemaItemListRemove(uses, i) == -1)
19414                             return(-1);
19415                         goto next_use;
19416                     }
19417                 }
19418             }
19419             /*
19420             * SPEC ag-props-correct
19421             * (3) "Two distinct members of the {attribute uses} must not have
19422             * {attribute declaration}s both of whose {type definition}s are or
19423             * are derived from ID."
19424             * TODO: Does 'derived' include member-types of unions?
19425             */
19426             if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19427                 if (xmlSchemaIsDerivedFromBuiltInType(
19428                     WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19429                 {
19430                     if (hasId) {
19431                         xmlChar *str = NULL;
19432
19433                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
19434                             XML_SCHEMAP_AG_PROPS_CORRECT,
19435                             attrGr->node, WXS_BASIC_CAST attrGr,
19436                             "There must not exist more than one attribute "
19437                             "declaration of type 'xs:ID' "
19438                             "(or derived from 'xs:ID'). The %s violates this "
19439                             "constraint",
19440                             xmlSchemaGetComponentDesignation(&str, use),
19441                             NULL);
19442                         FREE_AND_NULL(str);
19443                         if (xmlSchemaItemListRemove(uses, i) == -1)
19444                             return(-1);
19445                     }
19446                     hasId = 1;
19447                 }
19448             }
19449 next_use: {}
19450         }
19451     }
19452     return(0);
19453 }
19454
19455 /**
19456  * xmlSchemaResolveAttrGroupReferences:
19457  * @attrgrpDecl:  the schema attribute definition
19458  * @ctxt:  the schema parser context
19459  * @name:  the attribute name
19460  *
19461  * Resolves references to attribute group definitions.
19462  */
19463 static int
19464 xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19465                                     xmlSchemaParserCtxtPtr ctxt)
19466 {
19467     xmlSchemaAttributeGroupPtr group;
19468
19469     if (ref->item != NULL)
19470         return(0);
19471     group = xmlSchemaGetAttributeGroup(ctxt->schema,
19472         ref->name,
19473         ref->targetNamespace);
19474     if (group == NULL) {
19475         xmlSchemaPResCompAttrErr(ctxt,
19476             XML_SCHEMAP_SRC_RESOLVE,
19477             NULL, ref->node,
19478             "ref", ref->name, ref->targetNamespace,
19479             ref->itemType, NULL);
19480         return(ctxt->err);
19481     }
19482     ref->item = WXS_BASIC_CAST group;
19483     return(0);
19484 }
19485
19486 /**
19487  * xmlSchemaCheckAttrPropsCorrect:
19488  * @item:  an schema attribute declaration/use
19489  * @ctxt:  a schema parser context
19490  * @name:  the name of the attribute
19491  *
19492  *
19493  * Schema Component Constraint:
19494  *    Attribute Declaration Properties Correct (a-props-correct)
19495  *
19496  * Validates the value constraints of an attribute declaration/use.
19497  * NOTE that this needs the simle type definitions to be already
19498  *   builded and checked.
19499  */
19500 static int
19501 xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19502                                xmlSchemaAttributePtr attr)
19503 {
19504
19505     /*
19506     * SPEC a-props-correct (1)
19507     * "The values of the properties of an attribute declaration must
19508     * be as described in the property tableau in The Attribute
19509     * Declaration Schema Component ($3.2.1), modulo the impact of
19510     * Missing Sub-components ($5.3)."
19511     */
19512
19513     if (WXS_ATTR_TYPEDEF(attr) == NULL)
19514         return(0);
19515
19516     if (attr->defValue != NULL) {
19517         int ret;
19518
19519         /*
19520         * SPEC a-props-correct (3)
19521         * "If the {type definition} is or is derived from ID then there
19522         * must not be a {value constraint}."
19523         */
19524         if (xmlSchemaIsDerivedFromBuiltInType(
19525             WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19526         {
19527             xmlSchemaCustomErr(ACTXT_CAST pctxt,
19528                 XML_SCHEMAP_A_PROPS_CORRECT_3,
19529                 NULL, WXS_BASIC_CAST attr,
19530                 "Value constraints are not allowed if the type definition "
19531                 "is or is derived from xs:ID",
19532                 NULL, NULL);
19533             return(pctxt->err);
19534         }
19535         /*
19536         * SPEC a-props-correct (2)
19537         * "if there is a {value constraint}, the canonical lexical
19538         * representation of its value must be `valid` with respect
19539         * to the {type definition} as defined in String Valid ($3.14.4)."
19540         * TODO: Don't care about the *canonical* stuff here, this requirement
19541         * will be removed in WXS 1.1 anyway.
19542         */
19543         ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
19544             attr->node, WXS_ATTR_TYPEDEF(attr),
19545             attr->defValue, &(attr->defVal),
19546             1, 1, 0);
19547         if (ret != 0) {
19548             if (ret < 0) {
19549                 PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
19550                     "calling xmlSchemaVCheckCVCSimpleType()");
19551                 return(-1);
19552             }
19553             xmlSchemaCustomErr(ACTXT_CAST pctxt,
19554                 XML_SCHEMAP_A_PROPS_CORRECT_2,
19555                 NULL, WXS_BASIC_CAST attr,
19556                 "The value of the value constraint is not valid",
19557                 NULL, NULL);
19558             return(pctxt->err);
19559         }
19560     }
19561
19562     return(0);
19563 }
19564
19565 static xmlSchemaElementPtr
19566 xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19567                                  xmlSchemaElementPtr ancestor)
19568 {
19569     xmlSchemaElementPtr ret;
19570
19571     if (WXS_SUBST_HEAD(ancestor) == NULL)
19572         return (NULL);
19573     if (WXS_SUBST_HEAD(ancestor) == elemDecl)
19574         return (ancestor);
19575
19576     if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
19577         return (NULL);
19578     WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
19579     ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
19580         WXS_SUBST_HEAD(ancestor));
19581     WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
19582
19583     return (ret);
19584 }
19585
19586 /**
19587  * xmlSchemaCheckElemPropsCorrect:
19588  * @ctxt:  a schema parser context
19589  * @decl: the element declaration
19590  * @name:  the name of the attribute
19591  *
19592  * Schema Component Constraint:
19593  * Element Declaration Properties Correct (e-props-correct)
19594  *
19595  * STATUS:
19596  *   missing: (6)
19597  */
19598 static int
19599 xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19600                                xmlSchemaElementPtr elemDecl)
19601 {
19602     int ret = 0;
19603     xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
19604     /*
19605     * SPEC (1) "The values of the properties of an element declaration
19606     * must be as described in the property tableau in The Element
19607     * Declaration Schema Component ($3.3.1), modulo the impact of Missing
19608     * Sub-components ($5.3)."
19609     */
19610     if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19611         xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
19612
19613         xmlSchemaCheckElementDeclComponent(head, pctxt);
19614         /*
19615         * SPEC (3) "If there is a non-`absent` {substitution group
19616         * affiliation}, then {scope} must be global."
19617         */
19618         if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19619             xmlSchemaPCustomErr(pctxt,
19620                 XML_SCHEMAP_E_PROPS_CORRECT_3,
19621                 WXS_BASIC_CAST elemDecl, NULL,
19622                 "Only global element declarations can have a "
19623                 "substitution group affiliation", NULL);
19624             ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
19625         }
19626         /*
19627         * TODO: SPEC (6) "Circular substitution groups are disallowed.
19628         * That is, it must not be possible to return to an element declaration
19629         * by repeatedly following the {substitution group affiliation}
19630         * property."
19631         */
19632         if (head == elemDecl)
19633             circ = head;
19634         else if (WXS_SUBST_HEAD(head) != NULL)
19635             circ = xmlSchemaCheckSubstGroupCircular(head, head);
19636         else
19637             circ = NULL;
19638         if (circ != NULL) {
19639             xmlChar *strA = NULL, *strB = NULL;
19640
19641             xmlSchemaPCustomErrExt(pctxt,
19642                 XML_SCHEMAP_E_PROPS_CORRECT_6,
19643                 WXS_BASIC_CAST circ, NULL,
19644                 "The element declaration '%s' defines a circular "
19645                 "substitution group to element declaration '%s'",
19646                 xmlSchemaGetComponentQName(&strA, circ),
19647                 xmlSchemaGetComponentQName(&strB, head),
19648                 NULL);
19649             FREE_AND_NULL(strA)
19650             FREE_AND_NULL(strB)
19651             ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19652         }
19653         /*
19654         * SPEC (4) "If there is a {substitution group affiliation},
19655         * the {type definition}
19656         * of the element declaration must be validly derived from the {type
19657         * definition} of the {substitution group affiliation}, given the value
19658         * of the {substitution group exclusions} of the {substitution group
19659         * affiliation}, as defined in Type Derivation OK (Complex) ($3.4.6)
19660         * (if the {type definition} is complex) or as defined in
19661         * Type Derivation OK (Simple) ($3.14.6) (if the {type definition} is
19662         * simple)."
19663         *
19664         * NOTE: {substitution group exclusions} means the values of the
19665         * attribute "final".
19666         */
19667
19668         if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
19669             int set = 0;
19670
19671             if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19672                 set |= SUBSET_EXTENSION;
19673             if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19674                 set |= SUBSET_RESTRICTION;
19675
19676             if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
19677                 WXS_ELEM_TYPEDEF(head), set) != 0) {
19678                 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19679
19680                 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
19681                 xmlSchemaPCustomErrExt(pctxt,
19682                     XML_SCHEMAP_E_PROPS_CORRECT_4,
19683                     WXS_BASIC_CAST elemDecl, NULL,
19684                     "The type definition '%s' was "
19685                     "either rejected by the substitution group "
19686                     "affiliation '%s', or not validly derived from its type "
19687                     "definition '%s'",
19688                     xmlSchemaGetComponentQName(&strA, typeDef),
19689                     xmlSchemaGetComponentQName(&strB, head),
19690                     xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
19691                 FREE_AND_NULL(strA)
19692                 FREE_AND_NULL(strB)
19693                 FREE_AND_NULL(strC)
19694             }
19695         }
19696     }
19697     /*
19698     * SPEC (5) "If the {type definition} or {type definition}'s
19699     * {content type}
19700     * is or is derived from ID then there must not be a {value constraint}.
19701     * Note: The use of ID as a type definition for elements goes beyond
19702     * XML 1.0, and should be avoided if backwards compatibility is desired"
19703     */
19704     if ((elemDecl->value != NULL) &&
19705         ((WXS_IS_SIMPLE(typeDef) &&
19706           xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
19707          (WXS_IS_COMPLEX(typeDef) &&
19708           WXS_HAS_SIMPLE_CONTENT(typeDef) &&
19709           xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19710             XML_SCHEMAS_ID)))) {
19711
19712         ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19713         xmlSchemaPCustomErr(pctxt,
19714             XML_SCHEMAP_E_PROPS_CORRECT_5,
19715             WXS_BASIC_CAST elemDecl, NULL,
19716             "The type definition (or type definition's content type) is or "
19717             "is derived from ID; value constraints are not allowed in "
19718             "conjunction with such a type definition", NULL);
19719     } else if (elemDecl->value != NULL) {
19720         int vcret;
19721         xmlNodePtr node = NULL;
19722
19723         /*
19724         * SPEC (2) "If there is a {value constraint}, the canonical lexical
19725         * representation of its value must be `valid` with respect to the
19726         * {type definition} as defined in Element Default Valid (Immediate)
19727         * ($3.3.6)."
19728         */
19729         if (typeDef == NULL) {
19730             xmlSchemaPErr(pctxt, elemDecl->node,
19731                 XML_SCHEMAP_INTERNAL,
19732                 "Internal error: xmlSchemaCheckElemPropsCorrect, "
19733                 "type is missing... skipping validation of "
19734                 "the value constraint", NULL, NULL);
19735             return (-1);
19736         }
19737         if (elemDecl->node != NULL) {
19738             if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19739                 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19740                     BAD_CAST "fixed");
19741             else
19742                 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19743                     BAD_CAST "default");
19744         }
19745         vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19746             typeDef, elemDecl->value, &(elemDecl->defVal));
19747         if (vcret != 0) {
19748             if (vcret < 0) {
19749                 PERROR_INT("xmlSchemaElemCheckValConstr",
19750                     "failed to validate the value constraint of an "
19751                     "element declaration");
19752                 return (-1);
19753             }
19754             return (vcret);
19755         }
19756     }
19757
19758     return (ret);
19759 }
19760
19761 /**
19762  * xmlSchemaCheckElemSubstGroup:
19763  * @ctxt:  a schema parser context
19764  * @decl: the element declaration
19765  * @name:  the name of the attribute
19766  *
19767  * Schema Component Constraint:
19768  * Substitution Group (cos-equiv-class)
19769  *
19770  * In Libxml2 the subst. groups will be precomputed, in terms of that
19771  * a list will be built for each subst. group head, holding all direct
19772  * referents to this head.
19773  * NOTE that this function needs:
19774  *   1. circular subst. groups to be checked beforehand
19775  *   2. the declaration's type to be derived from the head's type
19776  *
19777  * STATUS:
19778  *
19779  */
19780 static void
19781 xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19782                              xmlSchemaElementPtr elemDecl)
19783 {
19784     if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
19785         /* SPEC (1) "Its {abstract} is false." */
19786         (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19787         return;
19788     {
19789         xmlSchemaElementPtr head;
19790         xmlSchemaTypePtr headType, type;
19791         int set, methSet;
19792         /*
19793         * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19794         * {disallowed substitutions} as the blocking constraint, as defined in
19795         * Substitution Group OK (Transitive) ($3.3.6)."
19796         */
19797         for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19798             head = WXS_SUBST_HEAD(head)) {
19799             set = 0;
19800             methSet = 0;
19801             /*
19802             * The blocking constraints.
19803             */
19804             if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19805                 continue;
19806             headType = head->subtypes;
19807             type = elemDecl->subtypes;
19808             if (headType == type)
19809                 goto add_member;
19810             if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19811                 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19812             if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19813                 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19814             /*
19815             * SPEC: Substitution Group OK (Transitive) (2.3)
19816             * "The set of all {derivation method}s involved in the
19817             * derivation of D's {type definition} from C's {type definition}
19818             * does not intersect with the union of the blocking constraint,
19819             * C's {prohibited substitutions} (if C is complex, otherwise the
19820             * empty set) and the {prohibited substitutions} (respectively the
19821             * empty set) of any intermediate {type definition}s in the
19822             * derivation of D's {type definition} from C's {type definition}."
19823             */
19824             /*
19825             * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19826             * subst.head axis, the methSet does not need to be computed for
19827             * the full depth over and over.
19828             */
19829             /*
19830             * The set of all {derivation method}s involved in the derivation
19831             */
19832             while ((type != NULL) && (type != headType)) {
19833                 if ((WXS_IS_EXTENSION(type)) &&
19834                     ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19835                     methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19836
19837                 if (WXS_IS_RESTRICTION(type) &&
19838                     ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19839                     methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19840
19841                 type = type->baseType;
19842             }
19843             /*
19844             * The {prohibited substitutions} of all intermediate types +
19845             * the head's type.
19846             */
19847             type = elemDecl->subtypes->baseType;
19848             while (type != NULL) {
19849                 if (WXS_IS_COMPLEX(type)) {
19850                     if ((type->flags &
19851                             XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19852                         ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19853                     set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19854                     if ((type->flags &
19855                             XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19856                         ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19857                     set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19858                 } else
19859                     break;
19860                 if (type == headType)
19861                     break;
19862                 type = type->baseType;
19863             }
19864             if ((set != 0) &&
19865                 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19866                 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19867                 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19868                 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19869                 continue;
19870             }
19871 add_member:
19872             xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19873             if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19874                 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19875         }
19876     }
19877 }
19878
19879 #ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */
19880 /**
19881  * xmlSchemaCheckElementDeclComponent
19882  * @pctxt: the schema parser context
19883  * @ctxtComponent: the context component (an element declaration)
19884  * @ctxtParticle: the first particle of the context component
19885  * @searchParticle: the element declaration particle to be analysed
19886  *
19887  * Schema Component Constraint: Element Declarations Consistent
19888  */
19889 static int
19890 xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,
19891                                     xmlSchemaBasicItemPtr ctxtComponent,
19892                                     xmlSchemaParticlePtr ctxtParticle,
19893                                     xmlSchemaParticlePtr searchParticle,
19894                                     xmlSchemaParticlePtr curParticle,
19895                                     int search)
19896 {
19897     return(0);
19898
19899     int ret = 0;
19900     xmlSchemaParticlePtr cur = curParticle;
19901     if (curParticle == NULL) {
19902         return(0);
19903     }
19904     if (WXS_PARTICLE_TERM(curParticle) == NULL) {
19905         /*
19906         * Just return in this case. A missing "term" of the particle
19907         * might arise due to an invalid "term" component.
19908         */
19909         return(0);
19910     }
19911     while (cur != NULL) {
19912         switch (WXS_PARTICLE_TERM(cur)->type) {
19913             case XML_SCHEMA_TYPE_ANY:
19914                 break;
19915             case XML_SCHEMA_TYPE_ELEMENT:
19916                 if (search == 0) {
19917                     ret = xmlSchemaCheckElementDeclConsistent(pctxt,
19918                         ctxtComponent, ctxtParticle, cur, ctxtParticle, 1);
19919                     if (ret != 0)
19920                         return(ret);
19921                 } else {
19922                     xmlSchemaElementPtr elem =
19923                         WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur));
19924                     /*
19925                     * SPEC Element Declarations Consistent:
19926                     * "If the {particles} contains, either directly,
19927                     * indirectly (that is, within the {particles} of a
19928                     * contained model group, recursively) or `implicitly`
19929                     * two or more element declaration particles with
19930                     * the same {name} and {target namespace}, then
19931                     * all their type definitions must be the same
19932                     * top-level definition [...]"
19933                     */
19934                     if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name,
19935                             WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) &&
19936                         xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19937                             WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace))
19938                     {
19939                         xmlChar *strA = NULL, *strB = NULL;
19940
19941                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
19942                             /* TODO: error code */
19943                             XML_SCHEMAP_COS_NONAMBIG,
19944                             WXS_ITEM_NODE(cur), NULL,
19945                             "In the content model of %s, there are multiple "
19946                             "element declarations for '%s' with different "
19947                             "type definitions",
19948                             xmlSchemaGetComponentDesignation(&strA,
19949                                 ctxtComponent),
19950                             xmlSchemaFormatQName(&strB,
19951                                 WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19952                                 WXS_PARTICLE_TERM_AS_ELEM(cur)->name));
19953                         FREE_AND_NULL(strA);
19954                         FREE_AND_NULL(strB);
19955                         return(XML_SCHEMAP_COS_NONAMBIG);
19956                     }
19957                 }
19958                 break;
19959             case XML_SCHEMA_TYPE_SEQUENCE: {
19960                 break;
19961                 }
19962             case XML_SCHEMA_TYPE_CHOICE:{
19963                 /*
19964                 xmlSchemaTreeItemPtr sub;
19965
19966                 sub = WXS_PARTICLE_TERM(particle)->children;  (xmlSchemaParticlePtr)
19967                 while (sub != NULL) {
19968                     ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent,
19969                         ctxtParticle, ctxtElem);
19970                     if (ret != 0)
19971                         return(ret);
19972                     sub = sub->next;
19973                 }
19974                 */
19975                 break;
19976                 }
19977             case XML_SCHEMA_TYPE_ALL:
19978                 break;
19979             case XML_SCHEMA_TYPE_GROUP:
19980                 break;
19981             default:
19982                 xmlSchemaInternalErr2(ACTXT_CAST pctxt,
19983                     "xmlSchemaCheckElementDeclConsistent",
19984                     "found unexpected term of type '%s' in content model",
19985                     WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL);
19986                 return(-1);
19987         }
19988         cur = (xmlSchemaParticlePtr) cur->next;
19989     }
19990
19991 exit:
19992     return(ret);
19993 }
19994 #endif
19995
19996 /**
19997  * xmlSchemaCheckElementDeclComponent
19998  * @item:  an schema element declaration/particle
19999  * @ctxt:  a schema parser context
20000  * @name:  the name of the attribute
20001  *
20002  * Validates the value constraints of an element declaration.
20003  * Adds substitution group members.
20004  */
20005 static void
20006 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
20007                                    xmlSchemaParserCtxtPtr ctxt)
20008 {
20009     if (elemDecl == NULL)
20010         return;
20011     if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
20012         return;
20013     elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
20014     if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) {
20015         /*
20016         * Adds substitution group members.
20017         */
20018         xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
20019     }
20020 }
20021
20022 /**
20023  * xmlSchemaResolveModelGroupParticleReferences:
20024  * @particle:  a particle component
20025  * @ctxt:  a parser context
20026  *
20027  * Resolves references of a model group's {particles} to
20028  * model group definitions and to element declarations.
20029  */
20030 static void
20031 xmlSchemaResolveModelGroupParticleReferences(
20032     xmlSchemaParserCtxtPtr ctxt,
20033     xmlSchemaModelGroupPtr mg)
20034 {
20035     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
20036     xmlSchemaQNameRefPtr ref;
20037     xmlSchemaBasicItemPtr refItem;
20038
20039     /*
20040     * URGENT TODO: Test this.
20041     */
20042     while (particle != NULL) {
20043         if ((WXS_PARTICLE_TERM(particle) == NULL) ||
20044             ((WXS_PARTICLE_TERM(particle))->type !=
20045                 XML_SCHEMA_EXTRA_QNAMEREF))
20046         {
20047             goto next_particle;
20048         }
20049         ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
20050         /*
20051         * Resolve the reference.
20052         * NULL the {term} by default.
20053         */
20054         particle->children = NULL;
20055
20056         refItem = xmlSchemaGetNamedComponent(ctxt->schema,
20057             ref->itemType, ref->name, ref->targetNamespace);
20058         if (refItem == NULL) {
20059             xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
20060                 NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
20061                 ref->targetNamespace, ref->itemType, NULL);
20062             /* TODO: remove the particle. */
20063             goto next_particle;
20064         }
20065         if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
20066             if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
20067                 /* TODO: remove the particle. */
20068                 goto next_particle;
20069             /*
20070             * NOTE that we will assign the model group definition
20071             * itself to the "term" of the particle. This will ease
20072             * the check for circular model group definitions. After
20073             * that the "term" will be assigned the model group of the
20074             * model group definition.
20075             */
20076             if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
20077                     XML_SCHEMA_TYPE_ALL) {
20078                 /*
20079                 * SPEC cos-all-limited (1)
20080                 * SPEC cos-all-limited (1.2)
20081                 * "It appears only as the value of one or both of the
20082                 * following properties:"
20083                 * (1.1) "the {model group} property of a model group
20084                 *        definition."
20085                 * (1.2) "the {term} property of a particle [... of] the "
20086                 * {content type} of a complex type definition."
20087                 */
20088                 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20089                     /* TODO: error code */
20090                     XML_SCHEMAP_COS_ALL_LIMITED,
20091                     WXS_ITEM_NODE(particle), NULL,
20092                     "A model group definition is referenced, but "
20093                     "it contains an 'all' model group, which "
20094                     "cannot be contained by model groups",
20095                     NULL, NULL);
20096                 /* TODO: remove the particle. */
20097                 goto next_particle;
20098             }
20099             particle->children = (xmlSchemaTreeItemPtr) refItem;
20100         } else {
20101             /*
20102             * TODO: Are referenced element declarations the only
20103             * other components we expect here?
20104             */
20105             particle->children = (xmlSchemaTreeItemPtr) refItem;
20106         }
20107 next_particle:
20108         particle = WXS_PTC_CAST particle->next;
20109     }
20110 }
20111
20112 static int
20113 xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
20114                        xmlSchemaValPtr y)
20115 {
20116     xmlSchemaTypePtr tx, ty, ptx, pty;
20117     int ret;
20118
20119     while (x != NULL) {
20120         /* Same types. */
20121         tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
20122         ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
20123         ptx = xmlSchemaGetPrimitiveType(tx);
20124         pty = xmlSchemaGetPrimitiveType(ty);
20125         /*
20126         * (1) if a datatype T' is `derived` by `restriction` from an
20127         * atomic datatype T then the `value space` of T' is a subset of
20128         * the `value space` of T. */
20129         /*
20130         * (2) if datatypes T' and T'' are `derived` by `restriction`
20131         * from a common atomic ancestor T then the `value space`s of T'
20132         * and T'' may overlap.
20133         */
20134         if (ptx != pty)
20135             return(0);
20136         /*
20137         * We assume computed values to be normalized, so do a fast
20138         * string comparison for string based types.
20139         */
20140         if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
20141             WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
20142             if (! xmlStrEqual(
20143                 xmlSchemaValueGetAsString(x),
20144                 xmlSchemaValueGetAsString(y)))
20145                 return (0);
20146         } else {
20147             ret = xmlSchemaCompareValuesWhtsp(
20148                 x, XML_SCHEMA_WHITESPACE_PRESERVE,
20149                 y, XML_SCHEMA_WHITESPACE_PRESERVE);
20150             if (ret == -2)
20151                 return(-1);
20152             if (ret != 0)
20153                 return(0);
20154         }
20155         /*
20156         * Lists.
20157         */
20158         x = xmlSchemaValueGetNext(x);
20159         if (x != NULL) {
20160             y = xmlSchemaValueGetNext(y);
20161             if (y == NULL)
20162                 return (0);
20163         } else if (xmlSchemaValueGetNext(y) != NULL)
20164             return (0);
20165         else
20166             return (1);
20167     }
20168     return (0);
20169 }
20170
20171 /**
20172  * xmlSchemaResolveAttrUseReferences:
20173  * @item:  an attribute use
20174  * @ctxt:  a parser context
20175  *
20176  * Resolves the referenced attribute declaration.
20177  */
20178 static int
20179 xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
20180                                   xmlSchemaParserCtxtPtr ctxt)
20181 {
20182     if ((ctxt == NULL) || (ause == NULL))
20183         return(-1);
20184     if ((ause->attrDecl == NULL) ||
20185         (ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
20186         return(0);
20187
20188     {
20189         xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
20190
20191         /*
20192         * TODO: Evaluate, what errors could occur if the declaration is not
20193         * found.
20194         */
20195         ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
20196             ref->name, ref->targetNamespace);
20197         if (ause->attrDecl == NULL) {
20198             xmlSchemaPResCompAttrErr(ctxt,
20199                 XML_SCHEMAP_SRC_RESOLVE,
20200                 WXS_BASIC_CAST ause, ause->node,
20201                 "ref", ref->name, ref->targetNamespace,
20202                 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20203             return(ctxt->err);;
20204         }
20205     }
20206     return(0);
20207 }
20208
20209 /**
20210  * xmlSchemaCheckAttrUsePropsCorrect:
20211  * @ctxt:  a parser context
20212  * @use:  an attribute use
20213  *
20214  * Schema Component Constraint:
20215  * Attribute Use Correct (au-props-correct)
20216  *
20217  */
20218 static int
20219 xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
20220                              xmlSchemaAttributeUsePtr use)
20221 {
20222     if ((ctxt == NULL) || (use == NULL))
20223         return(-1);
20224     if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
20225         ((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
20226         return(0);
20227
20228     /*
20229     * SPEC au-props-correct (1)
20230     * "The values of the properties of an attribute use must be as
20231     * described in the property tableau in The Attribute Use Schema
20232     * Component ($3.5.1), modulo the impact of Missing
20233     * Sub-components ($5.3)."
20234     */
20235
20236     if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
20237         ((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
20238         ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20239     {
20240         xmlSchemaPCustomErr(ctxt,
20241             XML_SCHEMAP_AU_PROPS_CORRECT_2,
20242             WXS_BASIC_CAST use, NULL,
20243             "The attribute declaration has a 'fixed' value constraint "
20244             ", thus the attribute use must also have a 'fixed' value "
20245             "constraint",
20246             NULL);
20247         return(ctxt->err);
20248     }
20249     /*
20250     * Compute and check the value constraint's value.
20251     */
20252     if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
20253         int ret;
20254         /*
20255         * TODO: The spec seems to be missing a check of the
20256         * value constraint of the attribute use. We will do it here.
20257         */
20258         /*
20259         * SPEC a-props-correct (3)
20260         */
20261         if (xmlSchemaIsDerivedFromBuiltInType(
20262             WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20263         {
20264             xmlSchemaCustomErr(ACTXT_CAST ctxt,
20265                 XML_SCHEMAP_AU_PROPS_CORRECT,
20266                 NULL, WXS_BASIC_CAST use,
20267                 "Value constraints are not allowed if the type definition "
20268                 "is or is derived from xs:ID",
20269                 NULL, NULL);
20270             return(ctxt->err);
20271         }
20272
20273         ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20274             use->node, WXS_ATTRUSE_TYPEDEF(use),
20275             use->defValue, &(use->defVal),
20276             1, 1, 0);
20277         if (ret != 0) {
20278             if (ret < 0) {
20279                 PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20280                     "calling xmlSchemaVCheckCVCSimpleType()");
20281                 return(-1);
20282             }
20283             xmlSchemaCustomErr(ACTXT_CAST ctxt,
20284                 XML_SCHEMAP_AU_PROPS_CORRECT,
20285                 NULL, WXS_BASIC_CAST use,
20286                 "The value of the value constraint is not valid",
20287                 NULL, NULL);
20288             return(ctxt->err);
20289         }
20290     }
20291     /*
20292     * SPEC au-props-correct (2)
20293     * "If the {attribute declaration} has a fixed
20294     * {value constraint}, then if the attribute use itself has a
20295     * {value constraint}, it must also be fixed and its value must match
20296     * that of the {attribute declaration}'s {value constraint}."
20297     */
20298     if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20299         (((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20300     {
20301         if (! xmlSchemaAreValuesEqual(use->defVal,
20302                 (WXS_ATTRUSE_DECL(use))->defVal))
20303         {
20304             xmlSchemaPCustomErr(ctxt,
20305                 XML_SCHEMAP_AU_PROPS_CORRECT_2,
20306                 WXS_BASIC_CAST use, NULL,
20307                 "The 'fixed' value constraint of the attribute use "
20308                 "must match the attribute declaration's value "
20309                 "constraint '%s'",
20310                 (WXS_ATTRUSE_DECL(use))->defValue);
20311         }
20312         return(ctxt->err);
20313     }
20314     return(0);
20315 }
20316
20317
20318
20319
20320 /**
20321  * xmlSchemaResolveAttrTypeReferences:
20322  * @item:  an attribute declaration
20323  * @ctxt:  a parser context
20324  *
20325  * Resolves the referenced type definition component.
20326  */
20327 static int
20328 xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20329                                    xmlSchemaParserCtxtPtr ctxt)
20330 {
20331     /*
20332     * The simple type definition corresponding to the <simpleType> element
20333     * information item in the [children], if present, otherwise the simple
20334     * type definition `resolved` to by the `actual value` of the type
20335     * [attribute], if present, otherwise the `simple ur-type definition`.
20336     */
20337     if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
20338         return(0);
20339     item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20340     if (item->subtypes != NULL)
20341         return(0);
20342     if (item->typeName != NULL) {
20343         xmlSchemaTypePtr type;
20344
20345         type = xmlSchemaGetType(ctxt->schema, item->typeName,
20346             item->typeNs);
20347         if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
20348             xmlSchemaPResCompAttrErr(ctxt,
20349                 XML_SCHEMAP_SRC_RESOLVE,
20350                 WXS_BASIC_CAST item, item->node,
20351                 "type", item->typeName, item->typeNs,
20352                 XML_SCHEMA_TYPE_SIMPLE, NULL);
20353             return(ctxt->err);
20354         } else
20355             item->subtypes = type;
20356
20357     } else {
20358         /*
20359         * The type defaults to the xs:anySimpleType.
20360         */
20361         item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20362     }
20363     return(0);
20364 }
20365
20366 /**
20367  * xmlSchemaResolveIDCKeyReferences:
20368  * @idc:  the identity-constraint definition
20369  * @ctxt:  the schema parser context
20370  * @name:  the attribute name
20371  *
20372  * Resolve keyRef references to key/unique IDCs.
20373  * Schema Component Constraint:
20374  *   Identity-constraint Definition Properties Correct (c-props-correct)
20375  */
20376 static int
20377 xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
20378                           xmlSchemaParserCtxtPtr pctxt)
20379 {
20380     if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
20381         return(0);
20382     if (idc->ref->name != NULL) {
20383         idc->ref->item = (xmlSchemaBasicItemPtr)
20384             xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20385                 idc->ref->targetNamespace);
20386         if (idc->ref->item == NULL) {
20387             /*
20388             * TODO: It is actually not an error to fail to resolve
20389             * at this stage. BUT we need to be that strict!
20390             */
20391             xmlSchemaPResCompAttrErr(pctxt,
20392                 XML_SCHEMAP_SRC_RESOLVE,
20393                 WXS_BASIC_CAST idc, idc->node,
20394                 "refer", idc->ref->name,
20395                 idc->ref->targetNamespace,
20396                 XML_SCHEMA_TYPE_IDC_KEY, NULL);
20397             return(pctxt->err);
20398         } else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20399             /*
20400             * SPEC c-props-correct (1)
20401             */
20402             xmlSchemaCustomErr(ACTXT_CAST pctxt,
20403                 XML_SCHEMAP_C_PROPS_CORRECT,
20404                 NULL, WXS_BASIC_CAST idc,
20405                 "The keyref references a keyref",
20406                 NULL, NULL);
20407             idc->ref->item = NULL;
20408             return(pctxt->err);
20409         } else {
20410             if (idc->nbFields !=
20411                 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20412                 xmlChar *str = NULL;
20413                 xmlSchemaIDCPtr refer;
20414
20415                 refer = (xmlSchemaIDCPtr) idc->ref->item;
20416                 /*
20417                 * SPEC c-props-correct(2)
20418                 * "If the {identity-constraint category} is keyref,
20419                 * the cardinality of the {fields} must equal that of
20420                 * the {fields} of the {referenced key}.
20421                 */
20422                 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20423                     XML_SCHEMAP_C_PROPS_CORRECT,
20424                     NULL, WXS_BASIC_CAST idc,
20425                     "The cardinality of the keyref differs from the "
20426                     "cardinality of the referenced key/unique '%s'",
20427                     xmlSchemaFormatQName(&str, refer->targetNamespace,
20428                         refer->name),
20429                     NULL);
20430                 FREE_AND_NULL(str)
20431                 return(pctxt->err);
20432             }
20433         }
20434     }
20435     return(0);
20436 }
20437
20438 static int
20439 xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20440                                        xmlSchemaParserCtxtPtr pctxt)
20441 {
20442     if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20443         prohib->targetNamespace) == NULL) {
20444
20445         xmlSchemaPResCompAttrErr(pctxt,
20446             XML_SCHEMAP_SRC_RESOLVE,
20447             NULL, prohib->node,
20448             "ref", prohib->name, prohib->targetNamespace,
20449             XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20450         return(XML_SCHEMAP_SRC_RESOLVE);
20451     }
20452     return(0);
20453 }
20454
20455 #define WXS_REDEFINED_TYPE(c) \
20456 (((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20457
20458 #define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20459 (((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20460
20461 #define WXS_REDEFINED_ATTR_GROUP(c) \
20462 (((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20463
20464 static int
20465 xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20466 {
20467     int err = 0;
20468     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20469     xmlSchemaBasicItemPtr prev, item;
20470     int wasRedefined;
20471
20472     if (redef == NULL)
20473         return(0);
20474
20475     do {
20476         item = redef->item;
20477         /*
20478         * First try to locate the redefined component in the
20479         * schema graph starting with the redefined schema.
20480         * NOTE: According to this schema bug entry:
20481         *   http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20482         *   it's not clear if the referenced component needs to originate
20483         *   from the <redefine>d schema _document_ or the schema; the latter
20484         *   would include all imported and included sub-schemas of the
20485         *   <redefine>d schema. Currenlty we latter approach is used.
20486         *   SUPPLEMENT: It seems that the WG moves towards the latter
20487         *   approach, so we are doing it right.
20488         *
20489         */
20490         prev = xmlSchemaFindRedefCompInGraph(
20491             redef->targetBucket, item->type,
20492             redef->refName, redef->refTargetNs);
20493         if (prev == NULL) {
20494             xmlChar *str = NULL;
20495             xmlNodePtr node;
20496
20497             /*
20498             * SPEC src-redefine:
20499             * (6.2.1) "The `actual value` of its own name attribute plus
20500             * target namespace must successfully `resolve` to a model
20501             * group definition in I."
20502             * (7.2.1) "The `actual value` of its own name attribute plus
20503             * target namespace must successfully `resolve` to an attribute
20504             * group definition in I."
20505
20506             *
20507             * Note that, if we are redefining with the use of references
20508             * to components, the spec assumes the src-resolve to be used;
20509             * but this won't assure that we search only *inside* the
20510             * redefined schema.
20511             */
20512             if (redef->reference)
20513                 node = WXS_ITEM_NODE(redef->reference);
20514             else
20515                 node = WXS_ITEM_NODE(item);
20516             xmlSchemaCustomErr(ACTXT_CAST pctxt,
20517                 /*
20518                 * TODO: error code.
20519                 * Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20520                 * reference kind.
20521                 */
20522                 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
20523                 "The %s '%s' to be redefined could not be found in "
20524                 "the redefined schema",
20525                 WXS_ITEM_TYPE_NAME(item),
20526                 xmlSchemaFormatQName(&str, redef->refTargetNs,
20527                     redef->refName));
20528             FREE_AND_NULL(str);
20529             err = pctxt->err;
20530             redef = redef->next;
20531             continue;
20532         }
20533         /*
20534         * TODO: Obtaining and setting the redefinition state is really
20535         * clumsy.
20536         */
20537         wasRedefined = 0;
20538         switch (item->type) {
20539             case XML_SCHEMA_TYPE_COMPLEX:
20540             case XML_SCHEMA_TYPE_SIMPLE:
20541                 if ((WXS_TYPE_CAST prev)->flags &
20542                     XML_SCHEMAS_TYPE_REDEFINED)
20543                 {
20544                     wasRedefined = 1;
20545                     break;
20546                 }
20547                 /* Mark it as redefined. */
20548                 (WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20549                 /*
20550                 * Assign the redefined type to the
20551                 * base type of the redefining type.
20552                 * TODO: How
20553                 */
20554                 ((xmlSchemaTypePtr) item)->baseType =
20555                     (xmlSchemaTypePtr) prev;
20556                 break;
20557             case XML_SCHEMA_TYPE_GROUP:
20558                 if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20559                     XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20560                 {
20561                     wasRedefined = 1;
20562                     break;
20563                 }
20564                 /* Mark it as redefined. */
20565                 (WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20566                     XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20567                 if (redef->reference != NULL) {
20568                     /*
20569                     * Overwrite the QName-reference with the
20570                     * referenced model group def.
20571                     */
20572                     (WXS_PTC_CAST redef->reference)->children =
20573                         WXS_TREE_CAST prev;
20574                 }
20575                 redef->target = prev;
20576                 break;
20577             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20578                 if ((WXS_ATTR_GROUP_CAST prev)->flags &
20579                     XML_SCHEMAS_ATTRGROUP_REDEFINED)
20580                 {
20581                     wasRedefined = 1;
20582                     break;
20583                 }
20584                 (WXS_ATTR_GROUP_CAST prev)->flags |=
20585                     XML_SCHEMAS_ATTRGROUP_REDEFINED;
20586                 if (redef->reference != NULL) {
20587                     /*
20588                     * Assign the redefined attribute group to the
20589                     * QName-reference component.
20590                     * This is the easy case, since we will just
20591                     * expand the redefined group.
20592                     */
20593                     (WXS_QNAME_CAST redef->reference)->item = prev;
20594                     redef->target = NULL;
20595                 } else {
20596                     /*
20597                     * This is the complicated case: we need
20598                     * to apply src-redefine (7.2.2) at a later
20599                     * stage, i.e. when attribute group references
20600                     * have beed expanded and simple types have
20601                     * beed fixed.
20602                     */
20603                     redef->target = prev;
20604                 }
20605                 break;
20606             default:
20607                 PERROR_INT("xmlSchemaResolveRedefReferences",
20608                     "Unexpected redefined component type");
20609                 return(-1);
20610         }
20611         if (wasRedefined) {
20612             xmlChar *str = NULL;
20613             xmlNodePtr node;
20614
20615             if (redef->reference)
20616                 node = WXS_ITEM_NODE(redef->reference);
20617             else
20618                 node = WXS_ITEM_NODE(redef->item);
20619
20620             xmlSchemaCustomErr(ACTXT_CAST pctxt,
20621                 /* TODO: error code. */
20622                 XML_SCHEMAP_SRC_REDEFINE,
20623                 node, NULL,
20624                 "The referenced %s was already redefined. Multiple "
20625                 "redefinition of the same component is not supported",
20626                 xmlSchemaGetComponentDesignation(&str, prev),
20627                 NULL);
20628             FREE_AND_NULL(str)
20629             err = pctxt->err;
20630             redef = redef->next;
20631             continue;
20632         }
20633         redef = redef->next;
20634     } while (redef != NULL);
20635
20636     return(err);
20637 }
20638
20639 static int
20640 xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20641 {
20642     int err = 0;
20643     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20644     xmlSchemaBasicItemPtr item;
20645
20646     if (redef == NULL)
20647         return(0);
20648
20649     do {
20650         if (redef->target == NULL) {
20651             redef = redef->next;
20652             continue;
20653         }
20654         item = redef->item;
20655
20656         switch (item->type) {
20657             case XML_SCHEMA_TYPE_SIMPLE:
20658             case XML_SCHEMA_TYPE_COMPLEX:
20659                 /*
20660                 * Since the spec wants the {name} of the redefined
20661                 * type to be 'absent', we'll NULL it.
20662                 */
20663                 (WXS_TYPE_CAST redef->target)->name = NULL;
20664
20665                 /*
20666                 * TODO: Seems like there's nothing more to do. The normal
20667                 * inheritance mechanism is used. But not 100% sure.
20668                 */
20669                 break;
20670             case XML_SCHEMA_TYPE_GROUP:
20671                 /*
20672                 * URGENT TODO:
20673                 * SPEC src-redefine:
20674                 * (6.2.2) "The {model group} of the model group definition
20675                 * which corresponds to it per XML Representation of Model
20676                 * Group Definition Schema Components ($3.7.2) must be a
20677                 * `valid restriction` of the {model group} of that model
20678                 * group definition in I, as defined in Particle Valid
20679                 * (Restriction) ($3.9.6)."
20680                 */
20681                 break;
20682             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20683                 /*
20684                 * SPEC src-redefine:
20685                 * (7.2.2) "The {attribute uses} and {attribute wildcard} of
20686                 * the attribute group definition which corresponds to it
20687                 * per XML Representation of Attribute Group Definition Schema
20688                 * Components ($3.6.2) must be `valid restrictions` of the
20689                 * {attribute uses} and {attribute wildcard} of that attribute
20690                 * group definition in I, as defined in clause 2, clause 3 and
20691                 * clause 4 of Derivation Valid (Restriction, Complex)
20692                 * ($3.4.6) (where references to the base type definition are
20693                 * understood as references to the attribute group definition
20694                 * in I)."
20695                 */
20696                 err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20697                     XML_SCHEMA_ACTION_REDEFINE,
20698                     item, redef->target,
20699                     (WXS_ATTR_GROUP_CAST item)->attrUses,
20700                     (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20701                     (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20702                     (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20703                 if (err == -1)
20704                     return(-1);
20705                 break;
20706             default:
20707                 break;
20708         }
20709         redef = redef->next;
20710     } while (redef != NULL);
20711     return(0);
20712 }
20713
20714
20715 static int
20716 xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20717                        xmlSchemaBucketPtr bucket)
20718 {
20719     xmlSchemaBasicItemPtr item;
20720     int err;
20721     xmlHashTablePtr *table;
20722     const xmlChar *name;
20723     int i;
20724
20725 #define WXS_GET_GLOBAL_HASH(c, slot) { \
20726     if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20727         table = &(WXS_IMPBUCKET((c))->schema->slot); \
20728     else \
20729         table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20730
20731     /*
20732     * Add global components to the schema's hash tables.
20733     * This is the place where duplicate components will be
20734     * detected.
20735     * TODO: I think normally we should support imports of the
20736     *   same namespace from multiple locations. We don't do currently,
20737     *   but if we do then according to:
20738     *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20739     *   we would need, if imported directly, to import redefined
20740     *   components as well to be able to catch clashing components.
20741     *   (I hope I'll still know what this means after some months :-()
20742     */
20743     if (bucket == NULL)
20744         return(-1);
20745     if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20746         return(0);
20747     bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20748
20749     for (i = 0; i < bucket->globals->nbItems; i++) {
20750         item = bucket->globals->items[i];
20751         table = NULL;
20752         switch (item->type) {
20753             case XML_SCHEMA_TYPE_COMPLEX:
20754             case XML_SCHEMA_TYPE_SIMPLE:
20755                 if (WXS_REDEFINED_TYPE(item))
20756                     continue;
20757                 name = (WXS_TYPE_CAST item)->name;
20758                 WXS_GET_GLOBAL_HASH(bucket, typeDecl)
20759                 break;
20760             case XML_SCHEMA_TYPE_ELEMENT:
20761                 name = (WXS_ELEM_CAST item)->name;
20762                 WXS_GET_GLOBAL_HASH(bucket, elemDecl)
20763                 break;
20764             case XML_SCHEMA_TYPE_ATTRIBUTE:
20765                 name = (WXS_ATTR_CAST item)->name;
20766                 WXS_GET_GLOBAL_HASH(bucket, attrDecl)
20767                 break;
20768             case XML_SCHEMA_TYPE_GROUP:
20769                 if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20770                     continue;
20771                 name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20772                 WXS_GET_GLOBAL_HASH(bucket, groupDecl)
20773                 break;
20774             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20775                 if (WXS_REDEFINED_ATTR_GROUP(item))
20776                     continue;
20777                 name = (WXS_ATTR_GROUP_CAST item)->name;
20778                 WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
20779                 break;
20780             case XML_SCHEMA_TYPE_IDC_KEY:
20781             case XML_SCHEMA_TYPE_IDC_UNIQUE:
20782             case XML_SCHEMA_TYPE_IDC_KEYREF:
20783                 name = (WXS_IDC_CAST item)->name;
20784                 WXS_GET_GLOBAL_HASH(bucket, idcDef)
20785                 break;
20786             case XML_SCHEMA_TYPE_NOTATION:
20787                 name = ((xmlSchemaNotationPtr) item)->name;
20788                 WXS_GET_GLOBAL_HASH(bucket, notaDecl)
20789                 break;
20790             default:
20791                 PERROR_INT("xmlSchemaAddComponents",
20792                     "Unexpected global component type");
20793                 continue;
20794         }
20795         if (*table == NULL) {
20796             *table = xmlHashCreateDict(10, pctxt->dict);
20797             if (*table == NULL) {
20798                 PERROR_INT("xmlSchemaAddComponents",
20799                     "failed to create a component hash table");
20800                 return(-1);
20801             }
20802         }
20803         err = xmlHashAddEntry(*table, name, item);
20804         if (err != 0) {
20805             xmlChar *str = NULL;
20806
20807             xmlSchemaCustomErr(ACTXT_CAST pctxt,
20808                 XML_SCHEMAP_REDEFINED_TYPE,
20809                 WXS_ITEM_NODE(item),
20810                 WXS_BASIC_CAST item,
20811                 "A global %s '%s' does already exist",
20812                 WXS_ITEM_TYPE_NAME(item),
20813                 xmlSchemaGetComponentQName(&str, item));
20814             FREE_AND_NULL(str);
20815         }
20816     }
20817     /*
20818     * Process imported/included schemas.
20819     */
20820     if (bucket->relations != NULL) {
20821         xmlSchemaSchemaRelationPtr rel = bucket->relations;
20822         do {
20823             if ((rel->bucket != NULL) &&
20824                 ((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20825                 if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20826                     return(-1);
20827             }
20828             rel = rel->next;
20829         } while (rel != NULL);
20830     }
20831     return(0);
20832 }
20833
20834 static int
20835 xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20836                          xmlSchemaBucketPtr rootBucket)
20837 {
20838     xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20839     xmlSchemaTreeItemPtr item, *items;
20840     int nbItems, i, ret = 0;
20841     xmlSchemaBucketPtr oldbucket = con->bucket;
20842     xmlSchemaElementPtr elemDecl;
20843
20844 #define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20845
20846     if ((con->pending == NULL) ||
20847         (con->pending->nbItems == 0))
20848         return(0);
20849
20850     /*
20851     * Since xmlSchemaFixupComplexType() will create new particles
20852     * (local components), and those particle components need a bucket
20853     * on the constructor, we'll assure here that the constructor has
20854     * a bucket.
20855     * TODO: Think about storing locals _only_ on the main bucket.
20856     */
20857     if (con->bucket == NULL)
20858         con->bucket = rootBucket;
20859
20860     /* TODO:
20861     * SPEC (src-redefine):
20862     * (6.2) "If it has no such self-reference, then all of the
20863     * following must be true:"
20864
20865     * (6.2.2) The {model group} of the model group definition which
20866     * corresponds to it per XML Representation of Model Group
20867     * Definition Schema Components ($3.7.2) must be a `valid
20868     * restriction` of the {model group} of that model group definition
20869     * in I, as defined in Particle Valid (Restriction) ($3.9.6)."
20870     */
20871     xmlSchemaCheckSRCRedefineFirst(pctxt);
20872
20873     /*
20874     * Add global components to the schemata's hash tables.
20875     */
20876     xmlSchemaAddComponents(pctxt, rootBucket);
20877
20878     pctxt->ctxtType = NULL;
20879     items = (xmlSchemaTreeItemPtr *) con->pending->items;
20880     nbItems = con->pending->nbItems;
20881     /*
20882     * Now that we have parsed *all* the schema document(s) and converted
20883     * them to schema components, we can resolve references, apply component
20884     * constraints, create the FSA from the content model, etc.
20885     */
20886     /*
20887     * Resolve references of..
20888     *
20889     * 1. element declarations:
20890     *   - the type definition
20891     *   - the substitution group affiliation
20892     * 2. simple/complex types:
20893     *   - the base type definition
20894     *   - the memberTypes of union types
20895     *   - the itemType of list types
20896     * 3. attributes declarations and attribute uses:
20897     *   - the type definition
20898     *   - if an attribute use, then the attribute declaration
20899     * 4. attribute group references:
20900     *   - the attribute group definition
20901     * 5. particles:
20902     *   - the term of the particle (e.g. a model group)
20903     * 6. IDC key-references:
20904     *   - the referenced IDC 'key' or 'unique' definition
20905     * 7. Attribute prohibitions which had a "ref" attribute.
20906     */
20907     for (i = 0; i < nbItems; i++) {
20908         item = items[i];
20909         switch (item->type) {
20910             case XML_SCHEMA_TYPE_ELEMENT:
20911                 xmlSchemaResolveElementReferences(
20912                     (xmlSchemaElementPtr) item, pctxt);
20913                 FIXHFAILURE;
20914                 break;
20915             case XML_SCHEMA_TYPE_COMPLEX:
20916             case XML_SCHEMA_TYPE_SIMPLE:
20917                 xmlSchemaResolveTypeReferences(
20918                     (xmlSchemaTypePtr) item, pctxt);
20919                 FIXHFAILURE;
20920                 break;
20921             case XML_SCHEMA_TYPE_ATTRIBUTE:
20922                 xmlSchemaResolveAttrTypeReferences(
20923                     (xmlSchemaAttributePtr) item, pctxt);
20924                 FIXHFAILURE;
20925                 break;
20926             case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20927                 xmlSchemaResolveAttrUseReferences(
20928                     (xmlSchemaAttributeUsePtr) item, pctxt);
20929                 FIXHFAILURE;
20930                 break;
20931             case XML_SCHEMA_EXTRA_QNAMEREF:
20932                 if ((WXS_QNAME_CAST item)->itemType ==
20933                     XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20934                 {
20935                     xmlSchemaResolveAttrGroupReferences(
20936                         WXS_QNAME_CAST item, pctxt);
20937                 }
20938                 FIXHFAILURE;
20939                 break;
20940             case XML_SCHEMA_TYPE_SEQUENCE:
20941             case XML_SCHEMA_TYPE_CHOICE:
20942             case XML_SCHEMA_TYPE_ALL:
20943                 xmlSchemaResolveModelGroupParticleReferences(pctxt,
20944                     WXS_MODEL_GROUP_CAST item);
20945                 FIXHFAILURE;
20946                 break;
20947             case XML_SCHEMA_TYPE_IDC_KEY:
20948             case XML_SCHEMA_TYPE_IDC_UNIQUE:
20949             case XML_SCHEMA_TYPE_IDC_KEYREF:
20950                 xmlSchemaResolveIDCKeyReferences(
20951                     (xmlSchemaIDCPtr) item, pctxt);
20952                 FIXHFAILURE;
20953                 break;
20954             case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20955                 /*
20956                 * Handle attribue prohibition which had a
20957                 * "ref" attribute.
20958                 */
20959                 xmlSchemaResolveAttrUseProhibReferences(
20960                     WXS_ATTR_PROHIB_CAST item, pctxt);
20961                 FIXHFAILURE;
20962                 break;
20963             default:
20964                 break;
20965         }
20966     }
20967     if (pctxt->nberrors != 0)
20968         goto exit_error;
20969
20970     /*
20971     * Now that all references are resolved we
20972     * can check for circularity of...
20973     * 1. the base axis of type definitions
20974     * 2. nested model group definitions
20975     * 3. nested attribute group definitions
20976     * TODO: check for circual substitution groups.
20977     */
20978     for (i = 0; i < nbItems; i++) {
20979         item = items[i];
20980         /*
20981         * Let's better stop on the first error here.
20982         */
20983         switch (item->type) {
20984             case XML_SCHEMA_TYPE_COMPLEX:
20985             case XML_SCHEMA_TYPE_SIMPLE:
20986                 xmlSchemaCheckTypeDefCircular(
20987                     (xmlSchemaTypePtr) item, pctxt);
20988                 FIXHFAILURE;
20989                 if (pctxt->nberrors != 0)
20990                     goto exit_error;
20991                 break;
20992             case XML_SCHEMA_TYPE_GROUP:
20993                 xmlSchemaCheckGroupDefCircular(
20994                     (xmlSchemaModelGroupDefPtr) item, pctxt);
20995                 FIXHFAILURE;
20996                 if (pctxt->nberrors != 0)
20997                     goto exit_error;
20998                 break;
20999             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21000                 xmlSchemaCheckAttrGroupCircular(
21001                     (xmlSchemaAttributeGroupPtr) item, pctxt);
21002                 FIXHFAILURE;
21003                 if (pctxt->nberrors != 0)
21004                     goto exit_error;
21005                 break;
21006             default:
21007                 break;
21008         }
21009     }
21010     if (pctxt->nberrors != 0)
21011         goto exit_error;
21012     /*
21013     * Model group definition references:
21014     * Such a reference is reflected by a particle at the component
21015     * level. Until now the 'term' of such particles pointed
21016     * to the model group definition; this was done, in order to
21017     * ease circularity checks. Now we need to set the 'term' of
21018     * such particles to the model group of the model group definition.
21019     */
21020     for (i = 0; i < nbItems; i++) {
21021         item = items[i];
21022         switch (item->type) {
21023             case XML_SCHEMA_TYPE_SEQUENCE:
21024             case XML_SCHEMA_TYPE_CHOICE:
21025                 xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
21026                     WXS_MODEL_GROUP_CAST item);
21027                 break;
21028             default:
21029                 break;
21030         }
21031     }
21032     if (pctxt->nberrors != 0)
21033         goto exit_error;
21034     /*
21035     * Expand attribute group references of attribute group definitions.
21036     */
21037     for (i = 0; i < nbItems; i++) {
21038         item = items[i];
21039         switch (item->type) {
21040             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21041                 if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
21042                     WXS_ATTR_GROUP_HAS_REFS(item))
21043                 {
21044                     xmlSchemaAttributeGroupExpandRefs(pctxt,
21045                         WXS_ATTR_GROUP_CAST item);
21046                     FIXHFAILURE;
21047                 }
21048                 break;
21049             default:
21050                 break;
21051         }
21052     }
21053     if (pctxt->nberrors != 0)
21054         goto exit_error;
21055     /*
21056     * First compute the variety of simple types. This is needed as
21057     * a seperate step, since otherwise we won't be able to detect
21058     * circular union types in all cases.
21059     */
21060     for (i = 0; i < nbItems; i++) {
21061         item = items[i];
21062         switch (item->type) {
21063             case XML_SCHEMA_TYPE_SIMPLE:
21064                 if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
21065                     xmlSchemaFixupSimpleTypeStageOne(pctxt,
21066                         (xmlSchemaTypePtr) item);
21067                     FIXHFAILURE;
21068                 }
21069                 break;
21070             default:
21071                 break;
21072         }
21073     }
21074     if (pctxt->nberrors != 0)
21075         goto exit_error;
21076     /*
21077     * Detect circular union types. Note that this needs the variety to
21078     * be already computed.
21079     */
21080     for (i = 0; i < nbItems; i++) {
21081         item = items[i];
21082         switch (item->type) {
21083             case XML_SCHEMA_TYPE_SIMPLE:
21084                 if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
21085                     xmlSchemaCheckUnionTypeDefCircular(pctxt,
21086                         (xmlSchemaTypePtr) item);
21087                     FIXHFAILURE;
21088                 }
21089                 break;
21090             default:
21091                 break;
21092         }
21093     }
21094     if (pctxt->nberrors != 0)
21095         goto exit_error;
21096
21097     /*
21098     * Do the complete type fixup for simple types.
21099     */
21100     for (i = 0; i < nbItems; i++) {
21101         item = items[i];
21102         switch (item->type) {
21103             case XML_SCHEMA_TYPE_SIMPLE:
21104                 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21105                     xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
21106                     FIXHFAILURE;
21107                 }
21108                 break;
21109             default:
21110                 break;
21111         }
21112     }
21113     if (pctxt->nberrors != 0)
21114         goto exit_error;
21115     /*
21116     * At this point we need build and check all simple types.
21117     */
21118     /*
21119     * Apply contraints for attribute declarations.
21120     */
21121     for (i = 0; i < nbItems; i++) {
21122         item = items[i];
21123         switch (item->type) {
21124             case XML_SCHEMA_TYPE_ATTRIBUTE:
21125                 xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
21126                 FIXHFAILURE;
21127                 break;
21128             default:
21129                 break;
21130         }
21131     }
21132     if (pctxt->nberrors != 0)
21133         goto exit_error;
21134     /*
21135     * Apply constraints for attribute uses.
21136     */
21137     for (i = 0; i < nbItems; i++) {
21138         item = items[i];
21139         switch (item->type) {
21140             case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21141                 if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
21142                     xmlSchemaCheckAttrUsePropsCorrect(pctxt,
21143                         WXS_ATTR_USE_CAST item);
21144                     FIXHFAILURE;
21145                 }
21146                 break;
21147             default:
21148                 break;
21149         }
21150     }
21151     if (pctxt->nberrors != 0)
21152         goto exit_error;
21153
21154     /*
21155     * Apply constraints for attribute group definitions.
21156     */
21157     for (i = 0; i < nbItems; i++) {
21158         item = items[i];
21159         switch (item->type) {
21160         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21161             if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
21162                 ( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
21163             {
21164                 xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
21165                 FIXHFAILURE;
21166             }
21167             break;
21168         default:
21169             break;
21170         }
21171     }
21172     if (pctxt->nberrors != 0)
21173         goto exit_error;
21174
21175     /*
21176     * Apply constraints for redefinitions.
21177     */
21178     if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
21179         xmlSchemaCheckSRCRedefineSecond(pctxt);
21180     if (pctxt->nberrors != 0)
21181         goto exit_error;
21182
21183     /*
21184     * Complex types are builded and checked.
21185     */
21186     for (i = 0; i < nbItems; i++) {
21187         item = con->pending->items[i];
21188         switch (item->type) {
21189             case XML_SCHEMA_TYPE_COMPLEX:
21190                 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21191                     xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
21192                     FIXHFAILURE;
21193                 }
21194                 break;
21195             default:
21196                 break;
21197         }
21198     }
21199     if (pctxt->nberrors != 0)
21200         goto exit_error;
21201
21202     /*
21203     * The list could have changed, since xmlSchemaFixupComplexType()
21204     * will create particles and model groups in some cases.
21205     */
21206     items = (xmlSchemaTreeItemPtr *) con->pending->items;
21207     nbItems = con->pending->nbItems;
21208
21209     /*
21210     * Apply some constraints for element declarations.
21211     */
21212     for (i = 0; i < nbItems; i++) {
21213         item = items[i];
21214         switch (item->type) {
21215             case XML_SCHEMA_TYPE_ELEMENT:
21216                 elemDecl = (xmlSchemaElementPtr) item;
21217
21218                 if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
21219                 {
21220                     xmlSchemaCheckElementDeclComponent(
21221                         (xmlSchemaElementPtr) elemDecl, pctxt);
21222                     FIXHFAILURE;
21223                 }
21224
21225 #ifdef WXS_ELEM_DECL_CONS_ENABLED
21226                 /*
21227                 * Schema Component Constraint: Element Declarations Consistent
21228                 * Apply this constraint to local types of element declarations.
21229                 */
21230                 if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
21231                     (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
21232                     (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
21233                 {
21234                     xmlSchemaCheckElementDeclConsistent(pctxt,
21235                         WXS_BASIC_CAST elemDecl,
21236                         WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
21237                         NULL, NULL, 0);
21238                 }
21239 #endif
21240                 break;
21241             default:
21242                 break;
21243         }
21244     }
21245     if (pctxt->nberrors != 0)
21246         goto exit_error;
21247
21248     /*
21249     * Finally we can build the automaton from the content model of
21250     * complex types.
21251     */
21252
21253     for (i = 0; i < nbItems; i++) {
21254         item = items[i];
21255         switch (item->type) {
21256             case XML_SCHEMA_TYPE_COMPLEX:
21257                 xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
21258                 /* FIXHFAILURE; */
21259                 break;
21260             default:
21261                 break;
21262         }
21263     }
21264     if (pctxt->nberrors != 0)
21265         goto exit_error;
21266     /*
21267     * URGENT TODO: cos-element-consistent
21268     */
21269     goto exit;
21270
21271 exit_error:
21272     ret = pctxt->err;
21273     goto exit;
21274
21275 exit_failure:
21276     ret = -1;
21277
21278 exit:
21279     /*
21280     * Reset the constructor. This is needed for XSI acquisition, since
21281     * those items will be processed over and over again for every XSI
21282     * if not cleared here.
21283     */
21284     con->bucket = oldbucket;
21285     con->pending->nbItems = 0;
21286     if (con->substGroups != NULL) {
21287         xmlHashFree(con->substGroups,
21288             (xmlHashDeallocator) xmlSchemaSubstGroupFree);
21289         con->substGroups = NULL;
21290     }
21291     if (con->redefs != NULL) {
21292         xmlSchemaRedefListFree(con->redefs);
21293         con->redefs = NULL;
21294     }
21295     return(ret);
21296 }
21297 /**
21298  * xmlSchemaParse:
21299  * @ctxt:  a schema validation context
21300  *
21301  * parse a schema definition resource and build an internal
21302  * XML Shema struture which can be used to validate instances.
21303  *
21304  * Returns the internal XML Schema structure built from the resource or
21305  *         NULL in case of error
21306  */
21307 xmlSchemaPtr
21308 xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21309 {
21310     xmlSchemaPtr mainSchema = NULL;
21311     xmlSchemaBucketPtr bucket = NULL;
21312     int res;
21313
21314     /*
21315     * This one is used if the schema to be parsed was specified via
21316     * the API; i.e. not automatically by the validated instance document.
21317     */
21318
21319     xmlSchemaInitTypes();
21320
21321     if (ctxt == NULL)
21322         return (NULL);
21323
21324     /* TODO: Init the context. Is this all we need?*/
21325     ctxt->nberrors = 0;
21326     ctxt->err = 0;
21327     ctxt->counter = 0;
21328
21329     /* Create the *main* schema. */
21330     mainSchema = xmlSchemaNewSchema(ctxt);
21331     if (mainSchema == NULL)
21332         goto exit_failure;
21333     /*
21334     * Create the schema constructor.
21335     */
21336     if (ctxt->constructor == NULL) {
21337         ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21338         if (ctxt->constructor == NULL)
21339             return(NULL);
21340         /* Take ownership of the constructor to be able to free it. */
21341         ctxt->ownsConstructor = 1;
21342     }
21343     ctxt->constructor->mainSchema = mainSchema;
21344     /*
21345     * Locate and add the schema document.
21346     */
21347     res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21348         ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21349         NULL, NULL, &bucket);
21350     if (res == -1)
21351         goto exit_failure;
21352     if (res != 0)
21353         goto exit;
21354
21355     if (bucket == NULL) {
21356         /* TODO: Error code, actually we failed to *locate* the schema. */
21357         if (ctxt->URL)
21358             xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21359                 NULL, NULL,
21360                 "Failed to locate the main schema resource at '%s'",
21361                 ctxt->URL, NULL);
21362         else
21363             xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21364                 NULL, NULL,
21365                 "Failed to locate the main schema resource",
21366                     NULL, NULL);
21367         goto exit;
21368     }
21369     /* Then do the parsing for good. */
21370     if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
21371         goto exit_failure;
21372     if (ctxt->nberrors != 0)
21373         goto exit;
21374
21375     mainSchema->doc = bucket->doc;
21376     mainSchema->preserve = ctxt->preserve;
21377
21378     ctxt->schema = mainSchema;
21379
21380     if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
21381         goto exit_failure;
21382
21383     /*
21384     * TODO: This is not nice, since we cannot distinguish from the
21385     * result if there was an internal error or not.
21386     */
21387 exit:
21388     if (ctxt->nberrors != 0) {
21389         if (mainSchema) {
21390             xmlSchemaFree(mainSchema);
21391             mainSchema = NULL;
21392         }
21393         if (ctxt->constructor) {
21394             xmlSchemaConstructionCtxtFree(ctxt->constructor);
21395             ctxt->constructor = NULL;
21396             ctxt->ownsConstructor = 0;
21397         }
21398     }
21399     ctxt->schema = NULL;
21400     return(mainSchema);
21401 exit_failure:
21402     /*
21403     * Quite verbose, but should catch internal errors, which were
21404     * not communitated.
21405     */
21406     if (mainSchema) {
21407         xmlSchemaFree(mainSchema);
21408         mainSchema = NULL;
21409     }
21410     if (ctxt->constructor) {
21411         xmlSchemaConstructionCtxtFree(ctxt->constructor);
21412         ctxt->constructor = NULL;
21413         ctxt->ownsConstructor = 0;
21414     }
21415     PERROR_INT2("xmlSchemaParse",
21416         "An internal error occured");
21417     ctxt->schema = NULL;
21418     return(NULL);
21419 }
21420
21421 /**
21422  * xmlSchemaSetParserErrors:
21423  * @ctxt:  a schema validation context
21424  * @err:  the error callback
21425  * @warn:  the warning callback
21426  * @ctx:  contextual data for the callbacks
21427  *
21428  * Set the callback functions used to handle errors for a validation context
21429  */
21430 void
21431 xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21432                          xmlSchemaValidityErrorFunc err,
21433                          xmlSchemaValidityWarningFunc warn, void *ctx)
21434 {
21435     if (ctxt == NULL)
21436         return;
21437     ctxt->error = err;
21438     ctxt->warning = warn;
21439     ctxt->errCtxt = ctx;
21440     if (ctxt->vctxt != NULL)
21441         xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21442 }
21443
21444 /**
21445  * xmlSchemaSetParserStructuredErrors:
21446  * @ctxt:  a schema parser context
21447  * @serror:  the structured error function
21448  * @ctx: the functions context
21449  *
21450  * Set the structured error callback
21451  */
21452 void
21453 xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21454                                    xmlStructuredErrorFunc serror,
21455                                    void *ctx)
21456 {
21457     if (ctxt == NULL)
21458         return;
21459     ctxt->serror = serror;
21460     ctxt->errCtxt = ctx;
21461     if (ctxt->vctxt != NULL)
21462         xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
21463 }
21464
21465 /**
21466  * xmlSchemaGetParserErrors:
21467  * @ctxt:  a XMl-Schema parser context
21468  * @err: the error callback result
21469  * @warn: the warning callback result
21470  * @ctx: contextual data for the callbacks result
21471  *
21472  * Get the callback information used to handle errors for a parser context
21473  *
21474  * Returns -1 in case of failure, 0 otherwise
21475  */
21476 int
21477 xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21478                          xmlSchemaValidityErrorFunc * err,
21479                          xmlSchemaValidityWarningFunc * warn, void **ctx)
21480 {
21481         if (ctxt == NULL)
21482                 return(-1);
21483         if (err != NULL)
21484                 *err = ctxt->error;
21485         if (warn != NULL)
21486                 *warn = ctxt->warning;
21487         if (ctx != NULL)
21488                 *ctx = ctxt->errCtxt;
21489         return(0);
21490 }
21491
21492 /**
21493  * xmlSchemaFacetTypeToString:
21494  * @type:  the facet type
21495  *
21496  * Convert the xmlSchemaTypeType to a char string.
21497  *
21498  * Returns the char string representation of the facet type if the
21499  *     type is a facet and an "Internal Error" string otherwise.
21500  */
21501 static const xmlChar *
21502 xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21503 {
21504     switch (type) {
21505         case XML_SCHEMA_FACET_PATTERN:
21506             return (BAD_CAST "pattern");
21507         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
21508             return (BAD_CAST "maxExclusive");
21509         case XML_SCHEMA_FACET_MAXINCLUSIVE:
21510             return (BAD_CAST "maxInclusive");
21511         case XML_SCHEMA_FACET_MINEXCLUSIVE:
21512             return (BAD_CAST "minExclusive");
21513         case XML_SCHEMA_FACET_MININCLUSIVE:
21514             return (BAD_CAST "minInclusive");
21515         case XML_SCHEMA_FACET_WHITESPACE:
21516             return (BAD_CAST "whiteSpace");
21517         case XML_SCHEMA_FACET_ENUMERATION:
21518             return (BAD_CAST "enumeration");
21519         case XML_SCHEMA_FACET_LENGTH:
21520             return (BAD_CAST "length");
21521         case XML_SCHEMA_FACET_MAXLENGTH:
21522             return (BAD_CAST "maxLength");
21523         case XML_SCHEMA_FACET_MINLENGTH:
21524             return (BAD_CAST "minLength");
21525         case XML_SCHEMA_FACET_TOTALDIGITS:
21526             return (BAD_CAST "totalDigits");
21527         case XML_SCHEMA_FACET_FRACTIONDIGITS:
21528             return (BAD_CAST "fractionDigits");
21529         default:
21530             break;
21531     }
21532     return (BAD_CAST "Internal Error");
21533 }
21534
21535 static xmlSchemaWhitespaceValueType
21536 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21537 {
21538     /*
21539     * The normalization type can be changed only for types which are derived
21540     * from xsd:string.
21541     */
21542     if (type->type == XML_SCHEMA_TYPE_BASIC) {
21543         /*
21544         * Note that we assume a whitespace of preserve for anySimpleType.
21545         */
21546         if ((type->builtInType == XML_SCHEMAS_STRING) ||
21547             (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21548             return(XML_SCHEMA_WHITESPACE_PRESERVE);
21549         else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
21550             return(XML_SCHEMA_WHITESPACE_REPLACE);
21551         else {
21552             /*
21553             * For all `atomic` datatypes other than string (and types `derived`
21554             * by `restriction` from it) the value of whiteSpace is fixed to
21555             * collapse
21556             * Note that this includes built-in list datatypes.
21557             */
21558             return(XML_SCHEMA_WHITESPACE_COLLAPSE);
21559         }
21560     } else if (WXS_IS_LIST(type)) {
21561         /*
21562         * For list types the facet "whiteSpace" is fixed to "collapse".
21563         */
21564         return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21565     } else if (WXS_IS_UNION(type)) {
21566         return (XML_SCHEMA_WHITESPACE_UNKNOWN);
21567     } else if (WXS_IS_ATOMIC(type)) {
21568         if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21569             return (XML_SCHEMA_WHITESPACE_PRESERVE);
21570         else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21571             return (XML_SCHEMA_WHITESPACE_REPLACE);
21572         else
21573             return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21574     }
21575     return (-1);
21576 }
21577
21578 /************************************************************************
21579  *                                                                      *
21580  *                      Simple type validation                          *
21581  *                                                                      *
21582  ************************************************************************/
21583
21584
21585 /************************************************************************
21586  *                                                                      *
21587  *                      DOM Validation code                             *
21588  *                                                                      *
21589  ************************************************************************/
21590
21591 /**
21592  * xmlSchemaAssembleByLocation:
21593  * @pctxt:  a schema parser context
21594  * @vctxt:  a schema validation context
21595  * @schema: the existing schema
21596  * @node: the node that fired the assembling
21597  * @nsName: the namespace name of the new schema
21598  * @location: the location of the schema
21599  *
21600  * Expands an existing schema by an additional schema.
21601  *
21602  * Returns 0 if the new schema is correct, a positive error code
21603  * number otherwise and -1 in case of an internal or API error.
21604  */
21605 static int
21606 xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
21607                             xmlSchemaPtr schema,
21608                             xmlNodePtr node,
21609                             const xmlChar *nsName,
21610                             const xmlChar *location)
21611 {
21612     int ret = 0;
21613     xmlSchemaParserCtxtPtr pctxt;
21614     xmlSchemaBucketPtr bucket = NULL;
21615
21616     if ((vctxt == NULL) || (schema == NULL))
21617         return (-1);
21618
21619     if (vctxt->pctxt == NULL) {
21620         VERROR_INT("xmlSchemaAssembleByLocation",
21621             "no parser context available");
21622         return(-1);
21623     }
21624     pctxt = vctxt->pctxt;
21625     if (pctxt->constructor == NULL) {
21626         PERROR_INT("xmlSchemaAssembleByLocation",
21627             "no constructor");
21628         return(-1);
21629     }
21630     /*
21631     * Acquire the schema document.
21632     */
21633     location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21634         location, node);
21635     /*
21636     * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21637     * the process will automatically change this to
21638     * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21639     */
21640     ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21641         location, NULL, NULL, 0, node, NULL, nsName,
21642         &bucket);
21643     if (ret != 0)
21644         return(ret);
21645     if (bucket == NULL) {
21646         /*
21647         * Generate a warning that the document could not be located.
21648         */
21649         xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21650             node, NULL,
21651             "The document at location '%s' could not be acquired",
21652             location, NULL, NULL);
21653         return(ret);
21654     }
21655     /*
21656     * The first located schema will be handled as if all other
21657     * schemas imported by XSI were imported by this first schema.
21658     */
21659     if ((bucket != NULL) &&
21660         (WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21661         WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21662     /*
21663     * TODO: Is this handled like an import? I.e. is it not an error
21664     * if the schema cannot be located?
21665     */
21666     if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21667         return(0);
21668     /*
21669     * We will reuse the parser context for every schema imported
21670     * directly via XSI. So reset the context.
21671     */
21672     pctxt->nberrors = 0;
21673     pctxt->err = 0;
21674     pctxt->doc = bucket->doc;
21675
21676     ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21677     if (ret == -1) {
21678         pctxt->doc = NULL;
21679         goto exit_failure;
21680     }
21681     /* Paranoid error channelling. */
21682     if ((ret == 0) && (pctxt->nberrors != 0))
21683         ret = pctxt->err;
21684     if (pctxt->nberrors == 0) {
21685         /*
21686         * Only bother to fixup pending components, if there was
21687         * no error yet.
21688         * For every XSI acquired schema (and its sub-schemata) we will
21689         * fixup the components.
21690         */
21691         xmlSchemaFixupComponents(pctxt, bucket);
21692         ret = pctxt->err;
21693         /*
21694         * Not nice, but we need somehow to channel the schema parser
21695         * error to the validation context.
21696         */
21697         if ((ret != 0) && (vctxt->err == 0))
21698             vctxt->err = ret;
21699         vctxt->nberrors += pctxt->nberrors;
21700     } else {
21701         /* Add to validation error sum. */
21702         vctxt->nberrors += pctxt->nberrors;
21703     }
21704     pctxt->doc = NULL;
21705     return(ret);
21706 exit_failure:
21707     pctxt->doc = NULL;
21708     return (-1);
21709 }
21710
21711 static xmlSchemaAttrInfoPtr
21712 xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21713                          int metaType)
21714 {
21715     if (vctxt->nbAttrInfos == 0)
21716         return (NULL);
21717     {
21718         int i;
21719         xmlSchemaAttrInfoPtr iattr;
21720
21721         for (i = 0; i < vctxt->nbAttrInfos; i++) {
21722             iattr = vctxt->attrInfos[i];
21723             if (iattr->metaType == metaType)
21724                 return (iattr);
21725         }
21726
21727     }
21728     return (NULL);
21729 }
21730
21731 /**
21732  * xmlSchemaAssembleByXSI:
21733  * @vctxt:  a schema validation context
21734  *
21735  * Expands an existing schema by an additional schema using
21736  * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21737  * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21738  * must be set to 1.
21739  *
21740  * Returns 0 if the new schema is correct, a positive error code
21741  * number otherwise and -1 in case of an internal or API error.
21742  */
21743 static int
21744 xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
21745 {
21746     const xmlChar *cur, *end;
21747     const xmlChar *nsname = NULL, *location;
21748     int count = 0;
21749     int ret = 0;
21750     xmlSchemaAttrInfoPtr iattr;
21751
21752     /*
21753     * Parse the value; we will assume an even number of values
21754     * to be given (this is how Xerces and XSV work).
21755     *
21756     * URGENT TODO: !! This needs to work for both
21757     * @noNamespaceSchemaLocation AND @schemaLocation on the same
21758     * element !!
21759     */
21760     iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21761         XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21762     if (iattr == NULL)
21763         iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21764         XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21765     if (iattr == NULL)
21766         return (0);
21767     cur = iattr->value;
21768     do {
21769         /*
21770         * TODO: Move the string parsing mechanism away from here.
21771         */
21772         if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
21773             /*
21774             * Get the namespace name.
21775             */
21776             while (IS_BLANK_CH(*cur))
21777                 cur++;
21778             end = cur;
21779             while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21780                 end++;
21781             if (end == cur)
21782                 break;
21783             count++; /* TODO: Don't use the schema's dict. */
21784             nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21785             cur = end;
21786         }
21787         /*
21788         * Get the URI.
21789         */
21790         while (IS_BLANK_CH(*cur))
21791             cur++;
21792         end = cur;
21793         while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21794             end++;
21795         if (end == cur) {
21796             if (iattr->metaType ==
21797                 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21798             {
21799                 /*
21800                 * If using @schemaLocation then tuples are expected.
21801                 * I.e. the namespace name *and* the document's URI.
21802                 */
21803                 xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21804                     iattr->node, NULL,
21805                     "The value must consist of tuples: the target namespace "
21806                     "name and the document's URI", NULL, NULL, NULL);
21807             }
21808             break;
21809         }
21810         count++; /* TODO: Don't use the schema's dict. */
21811         location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21812         cur = end;
21813         ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21814             iattr->node, nsname, location);
21815         if (ret == -1) {
21816             VERROR_INT("xmlSchemaAssembleByXSI",
21817                 "assembling schemata");
21818             return (-1);
21819         }
21820     } while (*cur != 0);
21821     return (ret);
21822 }
21823
21824 static const xmlChar *
21825 xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21826                          const xmlChar *prefix)
21827 {
21828     if (vctxt->sax != NULL) {
21829         int i, j;
21830         xmlSchemaNodeInfoPtr inode;
21831
21832         for (i = vctxt->depth; i >= 0; i--) {
21833             if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21834                 inode = vctxt->elemInfos[i];
21835                 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21836                     if (((prefix == NULL) &&
21837                             (inode->nsBindings[j] == NULL)) ||
21838                         ((prefix != NULL) && xmlStrEqual(prefix,
21839                             inode->nsBindings[j]))) {
21840
21841                         /*
21842                         * Note that the namespace bindings are already
21843                         * in a string dict.
21844                         */
21845                         return (inode->nsBindings[j+1]);
21846                     }
21847                 }
21848             }
21849         }
21850         return (NULL);
21851 #ifdef LIBXML_READER_ENABLED
21852     } else if (vctxt->reader != NULL) {
21853         xmlChar *nsName;
21854
21855         nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21856         if (nsName != NULL) {
21857             const xmlChar *ret;
21858
21859             ret = xmlDictLookup(vctxt->dict, nsName, -1);
21860             xmlFree(nsName);
21861             return (ret);
21862         } else
21863             return (NULL);
21864 #endif
21865     } else {
21866         xmlNsPtr ns;
21867
21868         if ((vctxt->inode->node == NULL) ||
21869             (vctxt->inode->node->doc == NULL)) {
21870             VERROR_INT("xmlSchemaLookupNamespace",
21871                 "no node or node's doc avaliable");
21872             return (NULL);
21873         }
21874         ns = xmlSearchNs(vctxt->inode->node->doc,
21875             vctxt->inode->node, prefix);
21876         if (ns != NULL)
21877             return (ns->href);
21878         return (NULL);
21879     }
21880 }
21881
21882 /*
21883 * This one works on the schema of the validation context.
21884 */
21885 static int
21886 xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21887                           xmlSchemaPtr schema,
21888                           xmlNodePtr node,
21889                           const xmlChar *value,
21890                           xmlSchemaValPtr *val,
21891                           int valNeeded)
21892 {
21893     int ret;
21894
21895     if (vctxt && (vctxt->schema == NULL)) {
21896         VERROR_INT("xmlSchemaValidateNotation",
21897             "a schema is needed on the validation context");
21898         return (-1);
21899     }
21900     ret = xmlValidateQName(value, 1);
21901     if (ret != 0)
21902         return (ret);
21903     {
21904         xmlChar *localName = NULL;
21905         xmlChar *prefix = NULL;
21906
21907         localName = xmlSplitQName2(value, &prefix);
21908         if (prefix != NULL) {
21909             const xmlChar *nsName = NULL;
21910
21911             if (vctxt != NULL)
21912                 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21913             else if (node != NULL) {
21914                 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21915                 if (ns != NULL)
21916                     nsName = ns->href;
21917             } else {
21918                 xmlFree(prefix);
21919                 xmlFree(localName);
21920                 return (1);
21921             }
21922             if (nsName == NULL) {
21923                 xmlFree(prefix);
21924                 xmlFree(localName);
21925                 return (1);
21926             }
21927             if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
21928                 if ((valNeeded) && (val != NULL)) {
21929                     (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName),
21930                                                        xmlStrdup(nsName));
21931                     if (*val == NULL)
21932                         ret = -1;
21933                 }
21934             } else
21935                 ret = 1;
21936             xmlFree(prefix);
21937             xmlFree(localName);
21938         } else {
21939             if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
21940                 if (valNeeded && (val != NULL)) {
21941                     (*val) = xmlSchemaNewNOTATIONValue(
21942                         BAD_CAST xmlStrdup(value), NULL);
21943                     if (*val == NULL)
21944                         ret = -1;
21945                 }
21946             } else
21947                 return (1);
21948         }
21949     }
21950     return (ret);
21951 }
21952
21953 static int
21954 xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21955                        const xmlChar* lname,
21956                        const xmlChar* nsname)
21957 {
21958     int i;
21959
21960     lname = xmlDictLookup(vctxt->dict, lname, -1);
21961     if (lname == NULL)
21962         return(-1);
21963     if (nsname != NULL) {
21964         nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21965         if (nsname == NULL)
21966             return(-1);
21967     }
21968     for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21969         if ((vctxt->nodeQNames->items [i] == lname) &&
21970             (vctxt->nodeQNames->items[i +1] == nsname))
21971             /* Already there */
21972             return(i);
21973     }
21974     /* Add new entry. */
21975     i = vctxt->nodeQNames->nbItems;
21976     xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21977     xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21978     return(i);
21979 }
21980
21981 /************************************************************************
21982  *                                                                      *
21983  *  Validation of identity-constraints (IDC)                            *
21984  *                                                                      *
21985  ************************************************************************/
21986
21987 /**
21988  * xmlSchemaAugmentIDC:
21989  * @idcDef: the IDC definition
21990  *
21991  * Creates an augmented IDC definition item.
21992  *
21993  * Returns the item, or NULL on internal errors.
21994  */
21995 static void
21996 xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
21997                     xmlSchemaValidCtxtPtr vctxt)
21998 {
21999     xmlSchemaIDCAugPtr aidc;
22000
22001     aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
22002     if (aidc == NULL) {
22003         xmlSchemaVErrMemory(vctxt,
22004             "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
22005             NULL);
22006         return;
22007     }
22008     aidc->keyrefDepth = -1;
22009     aidc->def = idcDef;
22010     aidc->next = NULL;
22011     if (vctxt->aidcs == NULL)
22012         vctxt->aidcs = aidc;
22013     else {
22014         aidc->next = vctxt->aidcs;
22015         vctxt->aidcs = aidc;
22016     }
22017     /*
22018     * Save if we have keyrefs at all.
22019     */
22020     if ((vctxt->hasKeyrefs == 0) &&
22021         (idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
22022         vctxt->hasKeyrefs = 1;
22023 }
22024
22025 /**
22026  * xmlSchemaAugmentImportedIDC:
22027  * @imported: the imported schema
22028  *
22029  * Creates an augmented IDC definition for the imported schema.
22030  */
22031 static void
22032 xmlSchemaAugmentImportedIDC(xmlSchemaImportPtr imported, xmlSchemaValidCtxtPtr vctxt) {
22033     if (imported->schema->idcDef != NULL) {
22034             xmlHashScan(imported->schema->idcDef ,
22035             (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
22036     }
22037 }
22038
22039 /**
22040  * xmlSchemaIDCNewBinding:
22041  * @idcDef: the IDC definition of this binding
22042  *
22043  * Creates a new IDC binding.
22044  *
22045  * Returns the new IDC binding, NULL on internal errors.
22046  */
22047 static xmlSchemaPSVIIDCBindingPtr
22048 xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
22049 {
22050     xmlSchemaPSVIIDCBindingPtr ret;
22051
22052     ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
22053             sizeof(xmlSchemaPSVIIDCBinding));
22054     if (ret == NULL) {
22055         xmlSchemaVErrMemory(NULL,
22056             "allocating a PSVI IDC binding item", NULL);
22057         return (NULL);
22058     }
22059     memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
22060     ret->definition = idcDef;
22061     return (ret);
22062 }
22063
22064 /**
22065  * xmlSchemaIDCStoreNodeTableItem:
22066  * @vctxt: the WXS validation context
22067  * @item: the IDC node table item
22068  *
22069  * The validation context is used to store IDC node table items.
22070  * They are stored to avoid copying them if IDC node-tables are merged
22071  * with corresponding parent IDC node-tables (bubbling).
22072  *
22073  * Returns 0 if succeeded, -1 on internal errors.
22074  */
22075 static int
22076 xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
22077                                xmlSchemaPSVIIDCNodePtr item)
22078 {
22079     /*
22080     * Add to gobal list.
22081     */
22082     if (vctxt->idcNodes == NULL) {
22083         vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22084             xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
22085         if (vctxt->idcNodes == NULL) {
22086             xmlSchemaVErrMemory(vctxt,
22087                 "allocating the IDC node table item list", NULL);
22088             return (-1);
22089         }
22090         vctxt->sizeIdcNodes = 20;
22091     } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
22092         vctxt->sizeIdcNodes *= 2;
22093         vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22094             xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
22095             sizeof(xmlSchemaPSVIIDCNodePtr));
22096         if (vctxt->idcNodes == NULL) {
22097             xmlSchemaVErrMemory(vctxt,
22098                 "re-allocating the IDC node table item list", NULL);
22099             return (-1);
22100         }
22101     }
22102     vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
22103
22104     return (0);
22105 }
22106
22107 /**
22108  * xmlSchemaIDCStoreKey:
22109  * @vctxt: the WXS validation context
22110  * @item: the IDC key
22111  *
22112  * The validation context is used to store an IDC key.
22113  *
22114  * Returns 0 if succeeded, -1 on internal errors.
22115  */
22116 static int
22117 xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
22118                      xmlSchemaPSVIIDCKeyPtr key)
22119 {
22120     /*
22121     * Add to gobal list.
22122     */
22123     if (vctxt->idcKeys == NULL) {
22124         vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22125             xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
22126         if (vctxt->idcKeys == NULL) {
22127             xmlSchemaVErrMemory(vctxt,
22128                 "allocating the IDC key storage list", NULL);
22129             return (-1);
22130         }
22131         vctxt->sizeIdcKeys = 40;
22132     } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
22133         vctxt->sizeIdcKeys *= 2;
22134         vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22135             xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
22136             sizeof(xmlSchemaPSVIIDCKeyPtr));
22137         if (vctxt->idcKeys == NULL) {
22138             xmlSchemaVErrMemory(vctxt,
22139                 "re-allocating the IDC key storage list", NULL);
22140             return (-1);
22141         }
22142     }
22143     vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
22144
22145     return (0);
22146 }
22147
22148 /**
22149  * xmlSchemaIDCAppendNodeTableItem:
22150  * @bind: the IDC binding
22151  * @ntItem: the node-table item
22152  *
22153  * Appends the IDC node-table item to the binding.
22154  *
22155  * Returns 0 on success and -1 on internal errors.
22156  */
22157 static int
22158 xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
22159                                 xmlSchemaPSVIIDCNodePtr ntItem)
22160 {
22161     if (bind->nodeTable == NULL) {
22162         bind->sizeNodes = 10;
22163         bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22164             xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
22165         if (bind->nodeTable == NULL) {
22166             xmlSchemaVErrMemory(NULL,
22167                 "allocating an array of IDC node-table items", NULL);
22168             return(-1);
22169         }
22170     } else if (bind->sizeNodes <= bind->nbNodes) {
22171         bind->sizeNodes *= 2;
22172         bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22173             xmlRealloc(bind->nodeTable, bind->sizeNodes *
22174                 sizeof(xmlSchemaPSVIIDCNodePtr));
22175         if (bind->nodeTable == NULL) {
22176             xmlSchemaVErrMemory(NULL,
22177                 "re-allocating an array of IDC node-table items", NULL);
22178             return(-1);
22179         }
22180     }
22181     bind->nodeTable[bind->nbNodes++] = ntItem;
22182     return(0);
22183 }
22184
22185 /**
22186  * xmlSchemaIDCAcquireBinding:
22187  * @vctxt: the WXS validation context
22188  * @matcher: the IDC matcher
22189  *
22190  * Looks up an PSVI IDC binding, for the IDC definition and
22191  * of the given matcher. If none found, a new one is created
22192  * and added to the IDC table.
22193  *
22194  * Returns an IDC binding or NULL on internal errors.
22195  */
22196 static xmlSchemaPSVIIDCBindingPtr
22197 xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
22198                           xmlSchemaIDCMatcherPtr matcher)
22199 {
22200     xmlSchemaNodeInfoPtr ielem;
22201
22202     ielem = vctxt->elemInfos[matcher->depth];
22203
22204     if (ielem->idcTable == NULL) {
22205         ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
22206         if (ielem->idcTable == NULL)
22207             return (NULL);
22208         return(ielem->idcTable);
22209     } else {
22210         xmlSchemaPSVIIDCBindingPtr bind = NULL;
22211
22212         bind = ielem->idcTable;
22213         do {
22214             if (bind->definition == matcher->aidc->def)
22215                 return(bind);
22216             if (bind->next == NULL) {
22217                 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
22218                 if (bind->next == NULL)
22219                     return (NULL);
22220                 return(bind->next);
22221             }
22222             bind = bind->next;
22223         } while (bind != NULL);
22224     }
22225     return (NULL);
22226 }
22227
22228 static xmlSchemaItemListPtr
22229 xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22230                              xmlSchemaIDCMatcherPtr matcher)
22231 {
22232     if (matcher->targets == NULL)
22233         matcher->targets = xmlSchemaItemListCreate();
22234     return(matcher->targets);
22235 }
22236
22237 /**
22238  * xmlSchemaIDCFreeKey:
22239  * @key: the IDC key
22240  *
22241  * Frees an IDC key together with its compiled value.
22242  */
22243 static void
22244 xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
22245 {
22246     if (key->val != NULL)
22247         xmlSchemaFreeValue(key->val);
22248     xmlFree(key);
22249 }
22250
22251 /**
22252  * xmlSchemaIDCFreeBinding:
22253  *
22254  * Frees an IDC binding. Note that the node table-items
22255  * are not freed.
22256  */
22257 static void
22258 xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
22259 {
22260     if (bind->nodeTable != NULL)
22261         xmlFree(bind->nodeTable);
22262     if (bind->dupls != NULL)
22263         xmlSchemaItemListFree(bind->dupls);
22264     xmlFree(bind);
22265 }
22266
22267 /**
22268  * xmlSchemaIDCFreeIDCTable:
22269  * @bind: the first IDC binding in the list
22270  *
22271  * Frees an IDC table, i.e. all the IDC bindings in the list.
22272  */
22273 static void
22274 xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
22275 {
22276     xmlSchemaPSVIIDCBindingPtr prev;
22277
22278     while (bind != NULL) {
22279         prev = bind;
22280         bind = bind->next;
22281         xmlSchemaIDCFreeBinding(prev);
22282     }
22283 }
22284
22285 /**
22286  * xmlSchemaIDCFreeMatcherList:
22287  * @matcher: the first IDC matcher in the list
22288  *
22289  * Frees a list of IDC matchers.
22290  */
22291 static void
22292 xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22293 {
22294     xmlSchemaIDCMatcherPtr next;
22295
22296     while (matcher != NULL) {
22297         next = matcher->next;
22298         if (matcher->keySeqs != NULL) {
22299             int i;
22300             for (i = 0; i < matcher->sizeKeySeqs; i++)
22301                 if (matcher->keySeqs[i] != NULL)
22302                     xmlFree(matcher->keySeqs[i]);
22303             xmlFree(matcher->keySeqs);
22304         }
22305         if (matcher->targets != NULL) {
22306             if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22307                 int i;
22308                 xmlSchemaPSVIIDCNodePtr idcNode;
22309                 /*
22310                 * Node-table items for keyrefs are not stored globally
22311                 * to the validation context, since they are not bubbled.
22312                 * We need to free them here.
22313                 */
22314                 for (i = 0; i < matcher->targets->nbItems; i++) {
22315                     idcNode =
22316                         (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22317                     xmlFree(idcNode->keys);
22318                     xmlFree(idcNode);
22319                 }
22320             }
22321             xmlSchemaItemListFree(matcher->targets);
22322         }
22323         xmlFree(matcher);
22324         matcher = next;
22325     }
22326 }
22327
22328 /**
22329  * xmlSchemaIDCReleaseMatcherList:
22330  * @vctxt: the WXS validation context
22331  * @matcher: the first IDC matcher in the list
22332  *
22333  * Caches a list of IDC matchers for reuse.
22334  */
22335 static void
22336 xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
22337                                xmlSchemaIDCMatcherPtr matcher)
22338 {
22339     xmlSchemaIDCMatcherPtr next;
22340
22341     while (matcher != NULL) {
22342         next = matcher->next;
22343         if (matcher->keySeqs != NULL) {
22344             int i;
22345             /*
22346             * Don't free the array, but only the content.
22347             */
22348             for (i = 0; i < matcher->sizeKeySeqs; i++)
22349                 if (matcher->keySeqs[i] != NULL) {
22350                     xmlFree(matcher->keySeqs[i]);
22351                     matcher->keySeqs[i] = NULL;
22352                 }
22353         }
22354         if (matcher->targets) {
22355             if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22356                 int i;
22357                 xmlSchemaPSVIIDCNodePtr idcNode;
22358                 /*
22359                 * Node-table items for keyrefs are not stored globally
22360                 * to the validation context, since they are not bubbled.
22361                 * We need to free them here.
22362                 */
22363                 for (i = 0; i < matcher->targets->nbItems; i++) {
22364                     idcNode =
22365                         (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22366                     xmlFree(idcNode->keys);
22367                     xmlFree(idcNode);
22368                 }
22369             }
22370             xmlSchemaItemListFree(matcher->targets);
22371             matcher->targets = NULL;
22372         }
22373         matcher->next = NULL;
22374         /*
22375         * Cache the matcher.
22376         */
22377         if (vctxt->idcMatcherCache != NULL)
22378             matcher->nextCached = vctxt->idcMatcherCache;
22379         vctxt->idcMatcherCache = matcher;
22380
22381         matcher = next;
22382     }
22383 }
22384
22385 /**
22386  * xmlSchemaIDCAddStateObject:
22387  * @vctxt: the WXS validation context
22388  * @matcher: the IDC matcher
22389  * @sel: the XPath information
22390  * @parent: the parent "selector" state object if any
22391  * @type: "selector" or "field"
22392  *
22393  * Creates/reuses and activates state objects for the given
22394  * XPath information; if the XPath expression consists of unions,
22395  * multiple state objects are created for every unioned expression.
22396  *
22397  * Returns 0 on success and -1 on internal errors.
22398  */
22399 static int
22400 xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22401                         xmlSchemaIDCMatcherPtr matcher,
22402                         xmlSchemaIDCSelectPtr sel,
22403                         int type)
22404 {
22405     xmlSchemaIDCStateObjPtr sto;
22406
22407     /*
22408     * Reuse the state objects from the pool.
22409     */
22410     if (vctxt->xpathStatePool != NULL) {
22411         sto = vctxt->xpathStatePool;
22412         vctxt->xpathStatePool = sto->next;
22413         sto->next = NULL;
22414     } else {
22415         /*
22416         * Create a new state object.
22417         */
22418         sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22419         if (sto == NULL) {
22420             xmlSchemaVErrMemory(NULL,
22421                 "allocating an IDC state object", NULL);
22422             return (-1);
22423         }
22424         memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22425     }
22426     /*
22427     * Add to global list.
22428     */
22429     if (vctxt->xpathStates != NULL)
22430         sto->next = vctxt->xpathStates;
22431     vctxt->xpathStates = sto;
22432
22433     /*
22434     * Free the old xpath validation context.
22435     */
22436     if (sto->xpathCtxt != NULL)
22437         xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22438
22439     /*
22440     * Create a new XPath (pattern) validation context.
22441     */
22442     sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22443         (xmlPatternPtr) sel->xpathComp);
22444     if (sto->xpathCtxt == NULL) {
22445         VERROR_INT("xmlSchemaIDCAddStateObject",
22446             "failed to create an XPath validation context");
22447         return (-1);
22448     }
22449     sto->type = type;
22450     sto->depth = vctxt->depth;
22451     sto->matcher = matcher;
22452     sto->sel = sel;
22453     sto->nbHistory = 0;
22454
22455 #ifdef DEBUG_IDC
22456     xmlGenericError(xmlGenericErrorContext, "IDC:   STO push '%s'\n",
22457         sto->sel->xpath);
22458 #endif
22459     return (0);
22460 }
22461
22462 /**
22463  * xmlSchemaXPathEvaluate:
22464  * @vctxt: the WXS validation context
22465  * @nodeType: the nodeType of the current node
22466  *
22467  * Evaluates all active XPath state objects.
22468  *
22469  * Returns the number of IC "field" state objects which resolved to
22470  * this node, 0 if none resolved and -1 on internal errors.
22471  */
22472 static int
22473 xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
22474                        xmlElementType nodeType)
22475 {
22476     xmlSchemaIDCStateObjPtr sto, head = NULL, first;
22477     int res, resolved = 0, depth = vctxt->depth;
22478
22479     if (vctxt->xpathStates == NULL)
22480         return (0);
22481
22482     if (nodeType == XML_ATTRIBUTE_NODE)
22483         depth++;
22484 #ifdef DEBUG_IDC
22485     {
22486         xmlChar *str = NULL;
22487         xmlGenericError(xmlGenericErrorContext,
22488             "IDC: EVAL on %s, depth %d, type %d\n",
22489             xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22490                 vctxt->inode->localName), depth, nodeType);
22491         FREE_AND_NULL(str)
22492     }
22493 #endif
22494     /*
22495     * Process all active XPath state objects.
22496     */
22497     first = vctxt->xpathStates;
22498     sto = first;
22499     while (sto != head) {
22500 #ifdef DEBUG_IDC
22501         if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
22502             xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] selector '%s'\n",
22503                 sto->matcher->aidc->def->name, sto->sel->xpath);
22504         else
22505             xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] field '%s'\n",
22506                 sto->matcher->aidc->def->name, sto->sel->xpath);
22507 #endif
22508         if (nodeType == XML_ELEMENT_NODE)
22509             res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
22510                 vctxt->inode->localName, vctxt->inode->nsName);
22511         else
22512             res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
22513                 vctxt->inode->localName, vctxt->inode->nsName);
22514
22515         if (res == -1) {
22516             VERROR_INT("xmlSchemaXPathEvaluate",
22517                 "calling xmlStreamPush()");
22518             return (-1);
22519         }
22520         if (res == 0)
22521             goto next_sto;
22522         /*
22523         * Full match.
22524         */
22525 #ifdef DEBUG_IDC
22526         xmlGenericError(xmlGenericErrorContext, "IDC:     "
22527             "MATCH\n");
22528 #endif
22529         /*
22530         * Register a match in the state object history.
22531         */
22532         if (sto->history == NULL) {
22533             sto->history = (int *) xmlMalloc(5 * sizeof(int));
22534             if (sto->history == NULL) {
22535                 xmlSchemaVErrMemory(NULL,
22536                     "allocating the state object history", NULL);
22537                 return(-1);
22538             }
22539             sto->sizeHistory = 5;
22540         } else if (sto->sizeHistory <= sto->nbHistory) {
22541             sto->sizeHistory *= 2;
22542             sto->history = (int *) xmlRealloc(sto->history,
22543                 sto->sizeHistory * sizeof(int));
22544             if (sto->history == NULL) {
22545                 xmlSchemaVErrMemory(NULL,
22546                     "re-allocating the state object history", NULL);
22547                 return(-1);
22548             }
22549         }
22550         sto->history[sto->nbHistory++] = depth;
22551
22552 #ifdef DEBUG_IDC
22553         xmlGenericError(xmlGenericErrorContext, "IDC:       push match '%d'\n",
22554             vctxt->depth);
22555 #endif
22556
22557         if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22558             xmlSchemaIDCSelectPtr sel;
22559             /*
22560             * Activate state objects for the IDC fields of
22561             * the IDC selector.
22562             */
22563 #ifdef DEBUG_IDC
22564             xmlGenericError(xmlGenericErrorContext, "IDC:     "
22565                 "activating field states\n");
22566 #endif
22567             sel = sto->matcher->aidc->def->fields;
22568             while (sel != NULL) {
22569                 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22570                     sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22571                     return (-1);
22572                 sel = sel->next;
22573             }
22574         } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22575             /*
22576             * An IDC key node was found by the IDC field.
22577             */
22578 #ifdef DEBUG_IDC
22579             xmlGenericError(xmlGenericErrorContext,
22580                 "IDC:     key found\n");
22581 #endif
22582             /*
22583             * Notify that the character value of this node is
22584             * needed.
22585             */
22586             if (resolved == 0) {
22587                 if ((vctxt->inode->flags &
22588                     XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22589                 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22590             }
22591             resolved++;
22592         }
22593 next_sto:
22594         if (sto->next == NULL) {
22595             /*
22596             * Evaluate field state objects created on this node as well.
22597             */
22598             head = first;
22599             sto = vctxt->xpathStates;
22600         } else
22601             sto = sto->next;
22602     }
22603     return (resolved);
22604 }
22605
22606 static const xmlChar *
22607 xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
22608                               xmlChar **buf,
22609                               xmlSchemaPSVIIDCKeyPtr *seq,
22610                               int count)
22611 {
22612     int i, res;
22613     xmlChar *value = NULL;
22614
22615     *buf = xmlStrdup(BAD_CAST "[");
22616     for (i = 0; i < count; i++) {
22617         *buf = xmlStrcat(*buf, BAD_CAST "'");
22618         res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22619             xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22620             &value);
22621         if (res == 0)
22622             *buf = xmlStrcat(*buf, BAD_CAST value);
22623         else {
22624             VERROR_INT("xmlSchemaFormatIDCKeySequence",
22625                 "failed to compute a canonical value");
22626             *buf = xmlStrcat(*buf, BAD_CAST "???");
22627         }
22628         if (i < count -1)
22629             *buf = xmlStrcat(*buf, BAD_CAST "', ");
22630         else
22631             *buf = xmlStrcat(*buf, BAD_CAST "'");
22632         if (value != NULL) {
22633             xmlFree(value);
22634             value = NULL;
22635         }
22636     }
22637     *buf = xmlStrcat(*buf, BAD_CAST "]");
22638
22639     return (BAD_CAST *buf);
22640 }
22641
22642 /**
22643  * xmlSchemaXPathPop:
22644  * @vctxt: the WXS validation context
22645  *
22646  * Pops all XPath states.
22647  *
22648  * Returns 0 on success and -1 on internal errors.
22649  */
22650 static int
22651 xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22652 {
22653     xmlSchemaIDCStateObjPtr sto;
22654     int res;
22655
22656     if (vctxt->xpathStates == NULL)
22657         return(0);
22658     sto = vctxt->xpathStates;
22659     do {
22660         res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22661         if (res == -1)
22662             return (-1);
22663         sto = sto->next;
22664     } while (sto != NULL);
22665     return(0);
22666 }
22667
22668 /**
22669  * xmlSchemaXPathProcessHistory:
22670  * @vctxt: the WXS validation context
22671  * @type: the simple/complex type of the current node if any at all
22672  * @val: the precompiled value
22673  *
22674  * Processes and pops the history items of the IDC state objects.
22675  * IDC key-sequences are validated/created on IDC bindings.
22676  *
22677  * Returns 0 on success and -1 on internal errors.
22678  */
22679 static int
22680 xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
22681                              int depth)
22682 {
22683     xmlSchemaIDCStateObjPtr sto, nextsto;
22684     int res, matchDepth;
22685     xmlSchemaPSVIIDCKeyPtr key = NULL;
22686     xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
22687
22688     if (vctxt->xpathStates == NULL)
22689         return (0);
22690     sto = vctxt->xpathStates;
22691
22692 #ifdef DEBUG_IDC
22693     {
22694         xmlChar *str = NULL;
22695         xmlGenericError(xmlGenericErrorContext,
22696             "IDC: BACK on %s, depth %d\n",
22697             xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22698                 vctxt->inode->localName), vctxt->depth);
22699         FREE_AND_NULL(str)
22700     }
22701 #endif
22702     /*
22703     * Evaluate the state objects.
22704     */
22705     while (sto != NULL) {
22706         res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22707         if (res == -1) {
22708             VERROR_INT("xmlSchemaXPathProcessHistory",
22709                 "calling xmlStreamPop()");
22710             return (-1);
22711         }
22712 #ifdef DEBUG_IDC
22713         xmlGenericError(xmlGenericErrorContext, "IDC:   stream pop '%s'\n",
22714             sto->sel->xpath);
22715 #endif
22716         if (sto->nbHistory == 0)
22717             goto deregister_check;
22718
22719         matchDepth = sto->history[sto->nbHistory -1];
22720
22721         /*
22722         * Only matches at the current depth are of interest.
22723         */
22724         if (matchDepth != depth) {
22725             sto = sto->next;
22726             continue;
22727         }
22728         if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22729             /*
22730             * NOTE: According to
22731             *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22732             *   ... the simple-content of complex types is also allowed.
22733             */
22734
22735             if (WXS_IS_COMPLEX(type)) {
22736                 if (WXS_HAS_SIMPLE_CONTENT(type)) {
22737                     /*
22738                     * Sanity check for complex types with simple content.
22739                     */
22740                     simpleType = type->contentTypeDef;
22741                     if (simpleType == NULL) {
22742                         VERROR_INT("xmlSchemaXPathProcessHistory",
22743                             "field resolves to a CT with simple content "
22744                             "but the CT is missing the ST definition");
22745                         return (-1);
22746                     }
22747                 } else
22748                     simpleType = NULL;
22749             } else
22750                 simpleType = type;
22751             if (simpleType == NULL) {
22752                 xmlChar *str = NULL;
22753
22754                 /*
22755                 * Not qualified if the field resolves to a node of non
22756                 * simple type.
22757                 */
22758                 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22759                     XML_SCHEMAV_CVC_IDC, NULL,
22760                     WXS_BASIC_CAST sto->matcher->aidc->def,
22761                     "The XPath '%s' of a field of %s does evaluate to a node of "
22762                     "non-simple type",
22763                     sto->sel->xpath,
22764                     xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22765                 FREE_AND_NULL(str);
22766                 sto->nbHistory--;
22767                 goto deregister_check;
22768             }
22769
22770             if ((key == NULL) && (vctxt->inode->val == NULL)) {
22771                 /*
22772                 * Failed to provide the normalized value; maybe
22773                 * the value was invalid.
22774                 */
22775                 VERROR(XML_SCHEMAV_CVC_IDC,
22776                     WXS_BASIC_CAST sto->matcher->aidc->def,
22777                     "Warning: No precomputed value available, the value "
22778                     "was either invalid or something strange happend");
22779                 sto->nbHistory--;
22780                 goto deregister_check;
22781             } else {
22782                 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22783                 xmlSchemaPSVIIDCKeyPtr *keySeq;
22784                 int pos, idx;
22785
22786                 /*
22787                 * The key will be anchored on the matcher's list of
22788                 * key-sequences. The position in this list is determined
22789                 * by the target node's depth relative to the matcher's
22790                 * depth of creation (i.e. the depth of the scope element).
22791                 *
22792                 * Element        Depth    Pos   List-entries
22793                 * <scope>          0              NULL
22794                 *   <bar>          1              NULL
22795                 *     <target/>    2       2      target
22796                 *   <bar>
22797                 * </scope>
22798                 *
22799                 * The size of the list is only dependant on the depth of
22800                 * the tree.
22801                 * An entry will be NULLed in selector_leave, i.e. when
22802                 * we hit the target's
22803                 */
22804                 pos = sto->depth - matcher->depth;
22805                 idx = sto->sel->index;
22806
22807                 /*
22808                 * Create/grow the array of key-sequences.
22809                 */
22810                 if (matcher->keySeqs == NULL) {
22811                     if (pos > 9)
22812                         matcher->sizeKeySeqs = pos * 2;
22813                     else
22814                         matcher->sizeKeySeqs = 10;
22815                     matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22816                         xmlMalloc(matcher->sizeKeySeqs *
22817                         sizeof(xmlSchemaPSVIIDCKeyPtr *));
22818                     if (matcher->keySeqs == NULL) {
22819                         xmlSchemaVErrMemory(NULL,
22820                             "allocating an array of key-sequences",
22821                             NULL);
22822                         return(-1);
22823                     }
22824                     memset(matcher->keySeqs, 0,
22825                         matcher->sizeKeySeqs *
22826                         sizeof(xmlSchemaPSVIIDCKeyPtr *));
22827                 } else if (pos >= matcher->sizeKeySeqs) {
22828                     int i = matcher->sizeKeySeqs;
22829
22830                     matcher->sizeKeySeqs *= 2;
22831                     matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22832                         xmlRealloc(matcher->keySeqs,
22833                         matcher->sizeKeySeqs *
22834                         sizeof(xmlSchemaPSVIIDCKeyPtr *));
22835                     if (matcher->keySeqs == NULL) {
22836                         xmlSchemaVErrMemory(NULL,
22837                             "reallocating an array of key-sequences",
22838                             NULL);
22839                         return (-1);
22840                     }
22841                     /*
22842                     * The array needs to be NULLed.
22843                     * TODO: Use memset?
22844                     */
22845                     for (; i < matcher->sizeKeySeqs; i++)
22846                         matcher->keySeqs[i] = NULL;
22847                 }
22848
22849                 /*
22850                 * Get/create the key-sequence.
22851                 */
22852                 keySeq = matcher->keySeqs[pos];
22853                 if (keySeq == NULL) {
22854                     goto create_sequence;
22855                 } else if (keySeq[idx] != NULL) {
22856                     xmlChar *str = NULL;
22857                     /*
22858                     * cvc-identity-constraint:
22859                     * 3 For each node in the `target node set` all
22860                     * of the {fields}, with that node as the context
22861                     * node, evaluate to either an empty node-set or
22862                     * a node-set with exactly one member, which must
22863                     * have a simple type.
22864                     *
22865                     * The key was already set; report an error.
22866                     */
22867                     xmlSchemaCustomErr(ACTXT_CAST vctxt,
22868                         XML_SCHEMAV_CVC_IDC, NULL,
22869                         WXS_BASIC_CAST matcher->aidc->def,
22870                         "The XPath '%s' of a field of %s evaluates to a "
22871                         "node-set with more than one member",
22872                         sto->sel->xpath,
22873                         xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22874                     FREE_AND_NULL(str);
22875                     sto->nbHistory--;
22876                     goto deregister_check;
22877                 } else
22878                     goto create_key;
22879
22880 create_sequence:
22881                 /*
22882                 * Create a key-sequence.
22883                 */
22884                 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22885                     matcher->aidc->def->nbFields *
22886                     sizeof(xmlSchemaPSVIIDCKeyPtr));
22887                 if (keySeq == NULL) {
22888                     xmlSchemaVErrMemory(NULL,
22889                         "allocating an IDC key-sequence", NULL);
22890                     return(-1);
22891                 }
22892                 memset(keySeq, 0, matcher->aidc->def->nbFields *
22893                     sizeof(xmlSchemaPSVIIDCKeyPtr));
22894                 matcher->keySeqs[pos] = keySeq;
22895 create_key:
22896                 /*
22897                 * Create a key once per node only.
22898                 */
22899                 if (key == NULL) {
22900                     key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22901                         sizeof(xmlSchemaPSVIIDCKey));
22902                     if (key == NULL) {
22903                         xmlSchemaVErrMemory(NULL,
22904                             "allocating a IDC key", NULL);
22905                         xmlFree(keySeq);
22906                         matcher->keySeqs[pos] = NULL;
22907                         return(-1);
22908                     }
22909                     /*
22910                     * Consume the compiled value.
22911                     */
22912                     key->type = simpleType;
22913                     key->val = vctxt->inode->val;
22914                     vctxt->inode->val = NULL;
22915                     /*
22916                     * Store the key in a global list.
22917                     */
22918                     if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22919                         xmlSchemaIDCFreeKey(key);
22920                         return (-1);
22921                     }
22922                 }
22923                 keySeq[idx] = key;
22924             }
22925         } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22926
22927             xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
22928             /* xmlSchemaPSVIIDCBindingPtr bind; */
22929             xmlSchemaPSVIIDCNodePtr ntItem;
22930             xmlSchemaIDCMatcherPtr matcher;
22931             xmlSchemaIDCPtr idc;
22932             xmlSchemaItemListPtr targets;
22933             int pos, i, j, nbKeys;
22934             /*
22935             * Here we have the following scenario:
22936             * An IDC 'selector' state object resolved to a target node,
22937             * during the time this target node was in the
22938             * ancestor-or-self axis, the 'field' state object(s) looked
22939             * out for matching nodes to create a key-sequence for this
22940             * target node. Now we are back to this target node and need
22941             * to put the key-sequence, together with the target node
22942             * itself, into the node-table of the corresponding IDC
22943             * binding.
22944             */
22945             matcher = sto->matcher;
22946             idc = matcher->aidc->def;
22947             nbKeys = idc->nbFields;
22948             pos = depth - matcher->depth;
22949             /*
22950             * Check if the matcher has any key-sequences at all, plus
22951             * if it has a key-sequence for the current target node.
22952             */
22953             if ((matcher->keySeqs == NULL) ||
22954                 (matcher->sizeKeySeqs <= pos)) {
22955                 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22956                     goto selector_key_error;
22957                 else
22958                     goto selector_leave;
22959             }
22960
22961             keySeq = &(matcher->keySeqs[pos]);
22962             if (*keySeq == NULL) {
22963                 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22964                     goto selector_key_error;
22965                 else
22966                     goto selector_leave;
22967             }
22968
22969             for (i = 0; i < nbKeys; i++) {
22970                 if ((*keySeq)[i] == NULL) {
22971                     /*
22972                     * Not qualified, if not all fields did resolve.
22973                     */
22974                     if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22975                         /*
22976                         * All fields of a "key" IDC must resolve.
22977                         */
22978                         goto selector_key_error;
22979                     }
22980                     goto selector_leave;
22981                 }
22982             }
22983             /*
22984             * All fields did resolve.
22985             */
22986
22987             /*
22988             * 4.1 If the {identity-constraint category} is unique(/key),
22989             * then no two members of the `qualified node set` have
22990             * `key-sequences` whose members are pairwise equal, as
22991             * defined by Equal in [XML Schemas: Datatypes].
22992             *
22993             * Get the IDC binding from the matcher and check for
22994             * duplicate key-sequences.
22995             */
22996 #if 0
22997             bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22998 #endif
22999             targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
23000             if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
23001                 (targets->nbItems != 0)) {
23002                 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
23003
23004                 i = 0;
23005                 res = 0;
23006                 /*
23007                 * Compare the key-sequences, key by key.
23008                 */
23009                 do {
23010                     bkeySeq =
23011                         ((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys;
23012                     for (j = 0; j < nbKeys; j++) {
23013                         ckey = (*keySeq)[j];
23014                         bkey = bkeySeq[j];
23015                         res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
23016                         if (res == -1) {
23017                             return (-1);
23018                         } else if (res == 0) {
23019                             /*
23020                             * One of the keys differs, so the key-sequence
23021                             * won't be equal; get out.
23022                             */
23023                             break;
23024                         }
23025                     }
23026                     if (res == 1) {
23027                         /*
23028                         * Duplicate key-sequence found.
23029                         */
23030                         break;
23031                     }
23032                     i++;
23033                 } while (i < targets->nbItems);
23034                 if (i != targets->nbItems) {
23035                     xmlChar *str = NULL, *strB = NULL;
23036                     /*
23037                     * TODO: Try to report the key-sequence.
23038                     */
23039                     xmlSchemaCustomErr(ACTXT_CAST vctxt,
23040                         XML_SCHEMAV_CVC_IDC, NULL,
23041                         WXS_BASIC_CAST idc,
23042                         "Duplicate key-sequence %s in %s",
23043                         xmlSchemaFormatIDCKeySequence(vctxt, &str,
23044                             (*keySeq), nbKeys),
23045                         xmlSchemaGetIDCDesignation(&strB, idc));
23046                     FREE_AND_NULL(str);
23047                     FREE_AND_NULL(strB);
23048                     goto selector_leave;
23049                 }
23050             }
23051             /*
23052             * Add a node-table item to the IDC binding.
23053             */
23054             ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
23055                 sizeof(xmlSchemaPSVIIDCNode));
23056             if (ntItem == NULL) {
23057                 xmlSchemaVErrMemory(NULL,
23058                     "allocating an IDC node-table item", NULL);
23059                 xmlFree(*keySeq);
23060                 *keySeq = NULL;
23061                 return(-1);
23062             }
23063             memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
23064
23065             /*
23066             * Store the node-table item in a global list.
23067             */
23068             if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23069                 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
23070                     xmlFree(ntItem);
23071                     xmlFree(*keySeq);
23072                     *keySeq = NULL;
23073                     return (-1);
23074                 }
23075                 ntItem->nodeQNameID = -1;
23076             } else {
23077                 /*
23078                 * Save a cached QName for this node on the IDC node, to be
23079                 * able to report it, even if the node is not saved.
23080                 */
23081                 ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
23082                     vctxt->inode->localName, vctxt->inode->nsName);
23083                 if (ntItem->nodeQNameID == -1) {
23084                     xmlFree(ntItem);
23085                     xmlFree(*keySeq);
23086                     *keySeq = NULL;
23087                     return (-1);
23088                 }
23089             }
23090             /*
23091             * Init the node-table item: Save the node, position and
23092             * consume the key-sequence.
23093             */
23094             ntItem->node = vctxt->node;
23095             ntItem->nodeLine = vctxt->inode->nodeLine;
23096             ntItem->keys = *keySeq;
23097             *keySeq = NULL;
23098 #if 0
23099             if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1)
23100 #endif
23101             if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
23102                 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23103                     /*
23104                     * Free the item, since keyref items won't be
23105                     * put on a global list.
23106                     */
23107                     xmlFree(ntItem->keys);
23108                     xmlFree(ntItem);
23109                 }
23110                 return (-1);
23111             }
23112
23113             goto selector_leave;
23114 selector_key_error:
23115             {
23116                 xmlChar *str = NULL;
23117                 /*
23118                 * 4.2.1 (KEY) The `target node set` and the
23119                 * `qualified node set` are equal, that is, every
23120                 * member of the `target node set` is also a member
23121                 * of the `qualified node set` and vice versa.
23122                 */
23123                 xmlSchemaCustomErr(ACTXT_CAST vctxt,
23124                     XML_SCHEMAV_CVC_IDC, NULL,
23125                     WXS_BASIC_CAST idc,
23126                     "Not all fields of %s evaluate to a node",
23127                     xmlSchemaGetIDCDesignation(&str, idc), NULL);
23128                 FREE_AND_NULL(str);
23129             }
23130 selector_leave:
23131             /*
23132             * Free the key-sequence if not added to the IDC table.
23133             */
23134             if ((keySeq != NULL) && (*keySeq != NULL)) {
23135                 xmlFree(*keySeq);
23136                 *keySeq = NULL;
23137             }
23138         } /* if selector */
23139
23140         sto->nbHistory--;
23141
23142 deregister_check:
23143         /*
23144         * Deregister state objects if they reach the depth of creation.
23145         */
23146         if ((sto->nbHistory == 0) && (sto->depth == depth)) {
23147 #ifdef DEBUG_IDC
23148             xmlGenericError(xmlGenericErrorContext, "IDC:   STO pop '%s'\n",
23149                 sto->sel->xpath);
23150 #endif
23151             if (vctxt->xpathStates != sto) {
23152                 VERROR_INT("xmlSchemaXPathProcessHistory",
23153                     "The state object to be removed is not the first "
23154                     "in the list");
23155             }
23156             nextsto = sto->next;
23157             /*
23158             * Unlink from the list of active XPath state objects.
23159             */
23160             vctxt->xpathStates = sto->next;
23161             sto->next = vctxt->xpathStatePool;
23162             /*
23163             * Link it to the pool of reusable state objects.
23164             */
23165             vctxt->xpathStatePool = sto;
23166             sto = nextsto;
23167         } else
23168             sto = sto->next;
23169     } /* while (sto != NULL) */
23170     return (0);
23171 }
23172
23173 /**
23174  * xmlSchemaIDCRegisterMatchers:
23175  * @vctxt: the WXS validation context
23176  * @elemDecl: the element declaration
23177  *
23178  * Creates helper objects to evaluate IDC selectors/fields
23179  * successively.
23180  *
23181  * Returns 0 if OK and -1 on internal errors.
23182  */
23183 static int
23184 xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
23185                              xmlSchemaElementPtr elemDecl)
23186 {
23187     xmlSchemaIDCMatcherPtr matcher, last = NULL;
23188     xmlSchemaIDCPtr idc, refIdc;
23189     xmlSchemaIDCAugPtr aidc;
23190
23191     idc = (xmlSchemaIDCPtr) elemDecl->idcs;
23192     if (idc == NULL)
23193         return (0);
23194
23195 #ifdef DEBUG_IDC
23196     {
23197         xmlChar *str = NULL;
23198         xmlGenericError(xmlGenericErrorContext,
23199             "IDC: REGISTER on %s, depth %d\n",
23200             (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
23201                 vctxt->inode->localName), vctxt->depth);
23202         FREE_AND_NULL(str)
23203     }
23204 #endif
23205     if (vctxt->inode->idcMatchers != NULL) {
23206         VERROR_INT("xmlSchemaIDCRegisterMatchers",
23207             "The chain of IDC matchers is expected to be empty");
23208         return (-1);
23209     }
23210     do {
23211         if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23212             /*
23213             * Since IDCs bubbles are expensive we need to know the
23214             * depth at which the bubbles should stop; this will be
23215             * the depth of the top-most keyref IDC. If no keyref
23216             * references a key/unique IDC, the keyrefDepth will
23217             * be -1, indicating that no bubbles are needed.
23218             */
23219             refIdc = (xmlSchemaIDCPtr) idc->ref->item;
23220             if (refIdc != NULL) {
23221                 /*
23222                 * Remember that we have keyrefs on this node.
23223                 */
23224                 vctxt->inode->hasKeyrefs = 1;
23225                 /*
23226                 * Lookup the referenced augmented IDC info.
23227                 */
23228                 aidc = vctxt->aidcs;
23229                 while (aidc != NULL) {
23230                     if (aidc->def == refIdc)
23231                         break;
23232                     aidc = aidc->next;
23233                 }
23234                 if (aidc == NULL) {
23235                     VERROR_INT("xmlSchemaIDCRegisterMatchers",
23236                         "Could not find an augmented IDC item for an IDC "
23237                         "definition");
23238                     return (-1);
23239                 }
23240                 if ((aidc->keyrefDepth == -1) ||
23241                     (vctxt->depth < aidc->keyrefDepth))
23242                     aidc->keyrefDepth = vctxt->depth;
23243             }
23244         }
23245         /*
23246         * Lookup the augmented IDC item for the IDC definition.
23247         */
23248         aidc = vctxt->aidcs;
23249         while (aidc != NULL) {
23250             if (aidc->def == idc)
23251                 break;
23252             aidc = aidc->next;
23253         }
23254         if (aidc == NULL) {
23255             VERROR_INT("xmlSchemaIDCRegisterMatchers",
23256                 "Could not find an augmented IDC item for an IDC definition");
23257             return (-1);
23258         }
23259         /*
23260         * Create an IDC matcher for every IDC definition.
23261         */
23262         if (vctxt->idcMatcherCache != NULL) {
23263             /*
23264             * Reuse a cached matcher.
23265             */
23266             matcher = vctxt->idcMatcherCache;
23267             vctxt->idcMatcherCache = matcher->nextCached;
23268             matcher->nextCached = NULL;
23269         } else {
23270             matcher = (xmlSchemaIDCMatcherPtr)
23271                 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
23272             if (matcher == NULL) {
23273                 xmlSchemaVErrMemory(vctxt,
23274                     "allocating an IDC matcher", NULL);
23275                 return (-1);
23276             }
23277             memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
23278         }
23279         if (last == NULL)
23280             vctxt->inode->idcMatchers = matcher;
23281         else
23282             last->next = matcher;
23283         last = matcher;
23284
23285         matcher->type = IDC_MATCHER;
23286         matcher->depth = vctxt->depth;
23287         matcher->aidc = aidc;
23288         matcher->idcType = aidc->def->type;
23289 #ifdef DEBUG_IDC
23290         xmlGenericError(xmlGenericErrorContext, "IDC:   register matcher\n");
23291 #endif
23292         /*
23293         * Init the automaton state object.
23294         */
23295         if (xmlSchemaIDCAddStateObject(vctxt, matcher,
23296             idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
23297             return (-1);
23298
23299         idc = idc->next;
23300     } while (idc != NULL);
23301     return (0);
23302 }
23303
23304 static int
23305 xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
23306                            xmlSchemaNodeInfoPtr ielem)
23307 {
23308     xmlSchemaPSVIIDCBindingPtr bind;
23309     int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
23310     xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
23311     xmlSchemaPSVIIDCNodePtr *targets, *dupls;
23312
23313     xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
23314     /* vctxt->createIDCNodeTables */
23315     while (matcher != NULL) {
23316         /*
23317         * Skip keyref IDCs and empty IDC target-lists.
23318         */
23319         if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
23320             WXS_ILIST_IS_EMPTY(matcher->targets))
23321         {
23322             matcher = matcher->next;
23323             continue;
23324         }
23325         /*
23326         * If we _want_ the IDC node-table to be created in any case
23327         * then do so. Otherwise create them only if keyrefs need them.
23328         */
23329         if ((! vctxt->createIDCNodeTables) &&
23330             ((matcher->aidc->keyrefDepth == -1) ||
23331              (matcher->aidc->keyrefDepth > vctxt->depth)))
23332         {
23333             matcher = matcher->next;
23334             continue;
23335         }
23336         /*
23337         * Get/create the IDC binding on this element for the IDC definition.
23338         */
23339         bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23340
23341         if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
23342             dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23343             nbDupls = bind->dupls->nbItems;
23344         } else {
23345             dupls = NULL;
23346             nbDupls = 0;
23347         }
23348         if (bind->nodeTable != NULL) {
23349             nbNodeTable = bind->nbNodes;
23350         } else {
23351             nbNodeTable = 0;
23352         }
23353
23354         if ((nbNodeTable == 0) && (nbDupls == 0)) {
23355             /*
23356             * Transfer all IDC target-nodes to the IDC node-table.
23357             */
23358             bind->nodeTable =
23359                 (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23360             bind->sizeNodes = matcher->targets->sizeItems;
23361             bind->nbNodes = matcher->targets->nbItems;
23362
23363             matcher->targets->items = NULL;
23364             matcher->targets->sizeItems = 0;
23365             matcher->targets->nbItems = 0;
23366         } else {
23367             /*
23368             * Compare the key-sequences and add to the IDC node-table.
23369             */
23370             nbTargets = matcher->targets->nbItems;
23371             targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23372             nbFields = matcher->aidc->def->nbFields;
23373             i = 0;
23374             do {
23375                 keys = targets[i]->keys;
23376                 if (nbDupls) {
23377                     /*
23378                     * Search in already found duplicates first.
23379                     */
23380                     j = 0;
23381                     do {
23382                         if (nbFields == 1) {
23383                             res = xmlSchemaAreValuesEqual(keys[0]->val,
23384                                 dupls[j]->keys[0]->val);
23385                             if (res == -1)
23386                                 goto internal_error;
23387                             if (res == 1) {
23388                                 /*
23389                                 * Equal key-sequence.
23390                                 */
23391                                 goto next_target;
23392                             }
23393                         } else {
23394                             res = 0;
23395                             ntkeys = dupls[j]->keys;
23396                             for (k = 0; k < nbFields; k++) {
23397                                 res = xmlSchemaAreValuesEqual(keys[k]->val,
23398                                     ntkeys[k]->val);
23399                                 if (res == -1)
23400                                     goto internal_error;
23401                                 if (res == 0) {
23402                                     /*
23403                                     * One of the keys differs.
23404                                     */
23405                                     break;
23406                                 }
23407                             }
23408                             if (res == 1) {
23409                                 /*
23410                                 * Equal key-sequence found.
23411                                 */
23412                                 goto next_target;
23413                             }
23414                         }
23415                         j++;
23416                     } while (j < nbDupls);
23417                 }
23418                 if (nbNodeTable) {
23419                     j = 0;
23420                     do {
23421                         if (nbFields == 1) {
23422                             res = xmlSchemaAreValuesEqual(keys[0]->val,
23423                                 bind->nodeTable[j]->keys[0]->val);
23424                             if (res == -1)
23425                                 goto internal_error;
23426                             if (res == 0) {
23427                                 /*
23428                                 * The key-sequence differs.
23429                                 */
23430                                 goto next_node_table_entry;
23431                             }
23432                         } else {
23433                             res = 0;
23434                             ntkeys = bind->nodeTable[j]->keys;
23435                             for (k = 0; k < nbFields; k++) {
23436                                 res = xmlSchemaAreValuesEqual(keys[k]->val,
23437                                     ntkeys[k]->val);
23438                                 if (res == -1)
23439                                     goto internal_error;
23440                                 if (res == 0) {
23441                                     /*
23442                                     * One of the keys differs.
23443                                     */
23444                                     goto next_node_table_entry;
23445                                 }
23446                             }
23447                         }
23448                         /*
23449                         * Add the duplicate to the list of duplicates.
23450                         */
23451                         if (bind->dupls == NULL) {
23452                             bind->dupls = xmlSchemaItemListCreate();
23453                             if (bind->dupls == NULL)
23454                                 goto internal_error;
23455                         }
23456                         if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23457                             goto internal_error;
23458                         /*
23459                         * Remove the duplicate entry from the IDC node-table.
23460                         */
23461                         bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23462                         bind->nbNodes--;
23463
23464                         goto next_target;
23465
23466 next_node_table_entry:
23467                         j++;
23468                     } while (j < nbNodeTable);
23469                 }
23470                 /*
23471                 * If everything is fine, then add the IDC target-node to
23472                 * the IDC node-table.
23473                 */
23474                 if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23475                     goto internal_error;
23476
23477 next_target:
23478                 i++;
23479             } while (i < nbTargets);
23480         }
23481         matcher = matcher->next;
23482     }
23483     return(0);
23484
23485 internal_error:
23486     return(-1);
23487 }
23488
23489 /**
23490  * xmlSchemaBubbleIDCNodeTables:
23491  * @depth: the current tree depth
23492  *
23493  * Merges IDC bindings of an element at @depth into the corresponding IDC
23494  * bindings of its parent element. If a duplicate note-table entry is found,
23495  * both, the parent node-table entry and child entry are discarded from the
23496  * node-table of the parent.
23497  *
23498  * Returns 0 if OK and -1 on internal errors.
23499  */
23500 static int
23501 xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23502 {
23503     xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
23504     xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23505     xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
23506     xmlSchemaIDCAugPtr aidc;
23507     int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
23508
23509     bind = vctxt->inode->idcTable;
23510     if (bind == NULL) {
23511         /* Fine, no table, no bubbles. */
23512         return (0);
23513     }
23514
23515     parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23516     /*
23517     * Walk all bindings; create new or add to existing bindings.
23518     * Remove duplicate key-sequences.
23519     */
23520     while (bind != NULL) {
23521
23522         if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23523             goto next_binding;
23524         /*
23525         * Check if the key/unique IDC table needs to be bubbled.
23526         */
23527         if (! vctxt->createIDCNodeTables) {
23528             aidc = vctxt->aidcs;
23529             do {
23530                 if (aidc->def == bind->definition) {
23531                     if ((aidc->keyrefDepth == -1) ||
23532                         (aidc->keyrefDepth >= vctxt->depth)) {
23533                         goto next_binding;
23534                     }
23535                     break;
23536                 }
23537                 aidc = aidc->next;
23538             } while (aidc != NULL);
23539         }
23540
23541         if (parTable != NULL)
23542             parBind = *parTable;
23543         /*
23544         * Search a matching parent binding for the
23545         * IDC definition.
23546         */
23547         while (parBind != NULL) {
23548             if (parBind->definition == bind->definition)
23549                 break;
23550             parBind = parBind->next;
23551         }
23552
23553         if (parBind != NULL) {
23554             /*
23555             * Compare every node-table entry of the child node,
23556             * i.e. the key-sequence within, ...
23557             */
23558             oldNum = parBind->nbNodes; /* Skip newly added items. */
23559
23560             if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23561                 oldDupls = parBind->dupls->nbItems;
23562                 dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23563             } else {
23564                 dupls = NULL;
23565                 oldDupls = 0;
23566             }
23567
23568             parNodes = parBind->nodeTable;
23569             nbFields = bind->definition->nbFields;
23570
23571             for (i = 0; i < bind->nbNodes; i++) {
23572                 node = bind->nodeTable[i];
23573                 if (node == NULL)
23574                     continue;
23575                 /*
23576                 * ...with every key-sequence of the parent node, already
23577                 * evaluated to be a duplicate key-sequence.
23578                 */
23579                 if (oldDupls) {
23580                     j = 0;
23581                     while (j < oldDupls) {
23582                         if (nbFields == 1) {
23583                             ret = xmlSchemaAreValuesEqual(
23584                                 node->keys[0]->val,
23585                                 dupls[j]->keys[0]->val);
23586                             if (ret == -1)
23587                                 goto internal_error;
23588                             if (ret == 0) {
23589                                 j++;
23590                                 continue;
23591                             }
23592                         } else {
23593                             parNode = dupls[j];
23594                             for (k = 0; k < nbFields; k++) {
23595                                 ret = xmlSchemaAreValuesEqual(
23596                                     node->keys[k]->val,
23597                                     parNode->keys[k]->val);
23598                                 if (ret == -1)
23599                                     goto internal_error;
23600                                 if (ret == 0)
23601                                     break;
23602                             }
23603                         }
23604                         if (ret == 1)
23605                             /* Duplicate found. */
23606                             break;
23607                         j++;
23608                     }
23609                     if (j != oldDupls) {
23610                         /* Duplicate found. Skip this entry. */
23611                         continue;
23612                     }
23613                 }
23614                 /*
23615                 * ... and with every key-sequence of the parent node.
23616                 */
23617                 if (oldNum) {
23618                     j = 0;
23619                     while (j < oldNum) {
23620                         parNode = parNodes[j];
23621                         if (nbFields == 1) {
23622                             ret = xmlSchemaAreValuesEqual(
23623                                 node->keys[0]->val,
23624                                 parNode->keys[0]->val);
23625                             if (ret == -1)
23626                                 goto internal_error;
23627                             if (ret == 0) {
23628                                 j++;
23629                                 continue;
23630                             }
23631                         } else {
23632                             for (k = 0; k < nbFields; k++) {
23633                                 ret = xmlSchemaAreValuesEqual(
23634                                     node->keys[k]->val,
23635                                     parNode->keys[k]->val);
23636                                 if (ret == -1)
23637                                     goto internal_error;
23638                                 if (ret == 0)
23639                                     break;
23640                             }
23641                         }
23642                         if (ret == 1)
23643                             /* Duplicate found. */
23644                             break;
23645                         j++;
23646                     }
23647                     if (j != oldNum) {
23648                         /*
23649                         * Handle duplicates. Move the duplicate in
23650                         * the parent's node-table to the list of
23651                         * duplicates.
23652                         */
23653                         oldNum--;
23654                         parBind->nbNodes--;
23655                         /*
23656                         * Move last old item to pos of duplicate.
23657                         */
23658                         parNodes[j] = parNodes[oldNum];
23659
23660                         if (parBind->nbNodes != oldNum) {
23661                             /*
23662                             * If new items exist, move last new item to
23663                             * last of old items.
23664                             */
23665                             parNodes[oldNum] =
23666                                 parNodes[parBind->nbNodes];
23667                         }
23668                         if (parBind->dupls == NULL) {
23669                             parBind->dupls = xmlSchemaItemListCreate();
23670                             if (parBind->dupls == NULL)
23671                                 goto internal_error;
23672                         }
23673                         xmlSchemaItemListAdd(parBind->dupls, parNode);
23674                     } else {
23675                         /*
23676                         * Add the node-table entry (node and key-sequence) of
23677                         * the child node to the node table of the parent node.
23678                         */
23679                         if (parBind->nodeTable == NULL) {
23680                             parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23681                                 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
23682                             if (parBind->nodeTable == NULL) {
23683                                 xmlSchemaVErrMemory(NULL,
23684                                     "allocating IDC list of node-table items", NULL);
23685                                 goto internal_error;
23686                             }
23687                             parBind->sizeNodes = 1;
23688                         } else if (parBind->nbNodes >= parBind->sizeNodes) {
23689                             parBind->sizeNodes *= 2;
23690                             parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23691                                 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23692                                 sizeof(xmlSchemaPSVIIDCNodePtr));
23693                             if (parBind->nodeTable == NULL) {
23694                                 xmlSchemaVErrMemory(NULL,
23695                                     "re-allocating IDC list of node-table items", NULL);
23696                                 goto internal_error;
23697                             }
23698                         }
23699                         parNodes = parBind->nodeTable;
23700                         /*
23701                         * Append the new node-table entry to the 'new node-table
23702                         * entries' section.
23703                         */
23704                         parNodes[parBind->nbNodes++] = node;
23705                     }
23706
23707                 }
23708
23709             }
23710         } else {
23711             /*
23712             * No binding for the IDC was found: create a new one and
23713             * copy all node-tables.
23714             */
23715             parBind = xmlSchemaIDCNewBinding(bind->definition);
23716             if (parBind == NULL)
23717                 goto internal_error;
23718
23719             /*
23720             * TODO: Hmm, how to optimize the initial number of
23721             * allocated entries?
23722             */
23723             if (bind->nbNodes != 0) {
23724                 /*
23725                 * Add all IDC node-table entries.
23726                 */
23727                 if (! vctxt->psviExposeIDCNodeTables) {
23728                     /*
23729                     * Just move the entries.
23730                     * NOTE: this is quite save here, since
23731                     * all the keyref lookups have already been
23732                     * performed.
23733                     */
23734                     parBind->nodeTable = bind->nodeTable;
23735                     bind->nodeTable = NULL;
23736                     parBind->sizeNodes = bind->sizeNodes;
23737                     bind->sizeNodes = 0;
23738                     parBind->nbNodes = bind->nbNodes;
23739                     bind->nbNodes = 0;
23740                 } else {
23741                     /*
23742                     * Copy the entries.
23743                     */
23744                     parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23745                         xmlMalloc(bind->nbNodes *
23746                         sizeof(xmlSchemaPSVIIDCNodePtr));
23747                     if (parBind->nodeTable == NULL) {
23748                         xmlSchemaVErrMemory(NULL,
23749                             "allocating an array of IDC node-table "
23750                             "items", NULL);
23751                         xmlSchemaIDCFreeBinding(parBind);
23752                         goto internal_error;
23753                     }
23754                     parBind->sizeNodes = bind->nbNodes;
23755                     parBind->nbNodes = bind->nbNodes;
23756                     memcpy(parBind->nodeTable, bind->nodeTable,
23757                         bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23758                 }
23759             }
23760             if (bind->dupls) {
23761                 /*
23762                 * Move the duplicates.
23763                 */
23764                 if (parBind->dupls != NULL)
23765                     xmlSchemaItemListFree(parBind->dupls);
23766                 parBind->dupls = bind->dupls;
23767                 bind->dupls = NULL;
23768             }
23769             if (parTable != NULL) {
23770                 if (*parTable == NULL)
23771                     *parTable = parBind;
23772                 else {
23773                     parBind->next = *parTable;
23774                     *parTable = parBind;
23775                 }
23776             }
23777         }
23778
23779 next_binding:
23780         bind = bind->next;
23781     }
23782     return (0);
23783
23784 internal_error:
23785     return(-1);
23786 }
23787
23788 /**
23789  * xmlSchemaCheckCVCIDCKeyRef:
23790  * @vctxt: the WXS validation context
23791  * @elemDecl: the element declaration
23792  *
23793  * Check the cvc-idc-keyref constraints.
23794  */
23795 static int
23796 xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23797 {
23798     xmlSchemaIDCMatcherPtr matcher;
23799     xmlSchemaPSVIIDCBindingPtr bind;
23800
23801     matcher = vctxt->inode->idcMatchers;
23802     /*
23803     * Find a keyref.
23804     */
23805     while (matcher != NULL) {
23806         if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23807             matcher->targets &&
23808             matcher->targets->nbItems)
23809         {
23810             int i, j, k, res, nbFields, hasDupls;
23811             xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
23812             xmlSchemaPSVIIDCNodePtr refNode = NULL;
23813
23814             nbFields = matcher->aidc->def->nbFields;
23815
23816             /*
23817             * Find the IDC node-table for the referenced IDC key/unique.
23818             */
23819             bind = vctxt->inode->idcTable;
23820             while (bind != NULL) {
23821                 if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
23822                     bind->definition)
23823                     break;
23824                 bind = bind->next;
23825             }
23826             hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
23827             /*
23828             * Search for a matching key-sequences.
23829             */
23830             for (i = 0; i < matcher->targets->nbItems; i++) {
23831                 res = 0;
23832                 refNode = matcher->targets->items[i];
23833                 if (bind != NULL) {
23834                     refKeys = refNode->keys;
23835                     for (j = 0; j < bind->nbNodes; j++) {
23836                         keys = bind->nodeTable[j]->keys;
23837                         for (k = 0; k < nbFields; k++) {
23838                             res = xmlSchemaAreValuesEqual(keys[k]->val,
23839                                 refKeys[k]->val);
23840                             if (res == 0)
23841                                 break;
23842                             else if (res == -1) {
23843                                 return (-1);
23844                             }
23845                         }
23846                         if (res == 1) {
23847                             /*
23848                             * Match found.
23849                             */
23850                             break;
23851                         }
23852                     }
23853                     if ((res == 0) && hasDupls) {
23854                         /*
23855                         * Search in duplicates
23856                         */
23857                         for (j = 0; j < bind->dupls->nbItems; j++) {
23858                             keys = ((xmlSchemaPSVIIDCNodePtr)
23859                                 bind->dupls->items[j])->keys;
23860                             for (k = 0; k < nbFields; k++) {
23861                                 res = xmlSchemaAreValuesEqual(keys[k]->val,
23862                                     refKeys[k]->val);
23863                                 if (res == 0)
23864                                     break;
23865                                 else if (res == -1) {
23866                                     return (-1);
23867                                 }
23868                             }
23869                             if (res == 1) {
23870                                 /*
23871                                 * Match in duplicates found.
23872                                 */
23873                                 xmlChar *str = NULL, *strB = NULL;
23874                                 xmlSchemaKeyrefErr(vctxt,
23875                                     XML_SCHEMAV_CVC_IDC, refNode,
23876                                     (xmlSchemaTypePtr) matcher->aidc->def,
23877                                     "More than one match found for "
23878                                     "key-sequence %s of keyref '%s'",
23879                                     xmlSchemaFormatIDCKeySequence(vctxt, &str,
23880                                         refNode->keys, nbFields),
23881                                     xmlSchemaGetComponentQName(&strB,
23882                                         matcher->aidc->def));
23883                                 FREE_AND_NULL(str);
23884                                 FREE_AND_NULL(strB);
23885                                 break;
23886                             }
23887                         }
23888                     }
23889                 }
23890
23891                 if (res == 0) {
23892                     xmlChar *str = NULL, *strB = NULL;
23893                     xmlSchemaKeyrefErr(vctxt,
23894                         XML_SCHEMAV_CVC_IDC, refNode,
23895                         (xmlSchemaTypePtr) matcher->aidc->def,
23896                         "No match found for key-sequence %s of keyref '%s'",
23897                         xmlSchemaFormatIDCKeySequence(vctxt, &str,
23898                             refNode->keys, nbFields),
23899                         xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
23900                     FREE_AND_NULL(str);
23901                     FREE_AND_NULL(strB);
23902                 }
23903             }
23904         }
23905         matcher = matcher->next;
23906     }
23907     /* TODO: Return an error if any error encountered. */
23908     return (0);
23909 }
23910
23911 /************************************************************************
23912  *                                                                      *
23913  *                      XML Reader validation code                      *
23914  *                                                                      *
23915  ************************************************************************/
23916
23917 static xmlSchemaAttrInfoPtr
23918 xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
23919 {
23920     xmlSchemaAttrInfoPtr iattr;
23921     /*
23922     * Grow/create list of attribute infos.
23923     */
23924     if (vctxt->attrInfos == NULL) {
23925         vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23926             xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23927         vctxt->sizeAttrInfos = 1;
23928         if (vctxt->attrInfos == NULL) {
23929             xmlSchemaVErrMemory(vctxt,
23930                 "allocating attribute info list", NULL);
23931             return (NULL);
23932         }
23933     } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23934         vctxt->sizeAttrInfos++;
23935         vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23936             xmlRealloc(vctxt->attrInfos,
23937                 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23938         if (vctxt->attrInfos == NULL) {
23939             xmlSchemaVErrMemory(vctxt,
23940                 "re-allocating attribute info list", NULL);
23941             return (NULL);
23942         }
23943     } else {
23944         iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23945         if (iattr->localName != NULL) {
23946             VERROR_INT("xmlSchemaGetFreshAttrInfo",
23947                 "attr info not cleared");
23948             return (NULL);
23949         }
23950         iattr->nodeType = XML_ATTRIBUTE_NODE;
23951         return (iattr);
23952     }
23953     /*
23954     * Create an attribute info.
23955     */
23956     iattr = (xmlSchemaAttrInfoPtr)
23957         xmlMalloc(sizeof(xmlSchemaAttrInfo));
23958     if (iattr == NULL) {
23959         xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
23960         return (NULL);
23961     }
23962     memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23963     iattr->nodeType = XML_ATTRIBUTE_NODE;
23964     vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23965
23966     return (iattr);
23967 }
23968
23969 static int
23970 xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23971                         xmlNodePtr attrNode,
23972                         int nodeLine,
23973                         const xmlChar *localName,
23974                         const xmlChar *nsName,
23975                         int ownedNames,
23976                         xmlChar *value,
23977                         int ownedValue)
23978 {
23979     xmlSchemaAttrInfoPtr attr;
23980
23981     attr = xmlSchemaGetFreshAttrInfo(vctxt);
23982     if (attr == NULL) {
23983         VERROR_INT("xmlSchemaPushAttribute",
23984             "calling xmlSchemaGetFreshAttrInfo()");
23985         return (-1);
23986     }
23987     attr->node = attrNode;
23988     attr->nodeLine = nodeLine;
23989     attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23990     attr->localName = localName;
23991     attr->nsName = nsName;
23992     if (ownedNames)
23993         attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23994     /*
23995     * Evaluate if it's an XSI attribute.
23996     */
23997     if (nsName != NULL) {
23998         if (xmlStrEqual(localName, BAD_CAST "nil")) {
23999             if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24000                 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
24001             }
24002         } else if (xmlStrEqual(localName, BAD_CAST "type")) {
24003             if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24004                 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
24005             }
24006         } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
24007             if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24008                 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
24009             }
24010         } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
24011             if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24012                 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
24013             }
24014         } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
24015             attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
24016         }
24017     }
24018     attr->value = value;
24019     if (ownedValue)
24020         attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
24021     if (attr->metaType != 0)
24022         attr->state = XML_SCHEMAS_ATTR_META;
24023     return (0);
24024 }
24025
24026 /**
24027  * xmlSchemaClearElemInfo:
24028  * @vctxt: the WXS validation context
24029  * @ielem: the element information item
24030  */
24031 static void
24032 xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,
24033                        xmlSchemaNodeInfoPtr ielem)
24034 {
24035     ielem->hasKeyrefs = 0;
24036     ielem->appliedXPath = 0;
24037     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
24038         FREE_AND_NULL(ielem->localName);
24039         FREE_AND_NULL(ielem->nsName);
24040     } else {
24041         ielem->localName = NULL;
24042         ielem->nsName = NULL;
24043     }
24044     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24045         FREE_AND_NULL(ielem->value);
24046     } else {
24047         ielem->value = NULL;
24048     }
24049     if (ielem->val != NULL) {
24050         /*
24051         * PSVI TODO: Be careful not to free it when the value is
24052         * exposed via PSVI.
24053         */
24054         xmlSchemaFreeValue(ielem->val);
24055         ielem->val = NULL;
24056     }
24057     if (ielem->idcMatchers != NULL) {
24058         /*
24059         * REVISIT OPTIMIZE TODO: Use a pool of IDC matchers.
24060         *   Does it work?
24061         */
24062         xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers);
24063 #if 0
24064         xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
24065 #endif
24066         ielem->idcMatchers = NULL;
24067     }
24068     if (ielem->idcTable != NULL) {
24069         /*
24070         * OPTIMIZE TODO: Use a pool of IDC tables??.
24071         */
24072         xmlSchemaIDCFreeIDCTable(ielem->idcTable);
24073         ielem->idcTable = NULL;
24074     }
24075     if (ielem->regexCtxt != NULL) {
24076         xmlRegFreeExecCtxt(ielem->regexCtxt);
24077         ielem->regexCtxt = NULL;
24078     }
24079     if (ielem->nsBindings != NULL) {
24080         xmlFree((xmlChar **)ielem->nsBindings);
24081         ielem->nsBindings = NULL;
24082         ielem->nbNsBindings = 0;
24083         ielem->sizeNsBindings = 0;
24084     }
24085 }
24086
24087 /**
24088  * xmlSchemaGetFreshElemInfo:
24089  * @vctxt: the schema validation context
24090  *
24091  * Creates/reuses and initializes the element info item for
24092  * the currect tree depth.
24093  *
24094  * Returns the element info item or NULL on API or internal errors.
24095  */
24096 static xmlSchemaNodeInfoPtr
24097 xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
24098 {
24099     xmlSchemaNodeInfoPtr info = NULL;
24100
24101     if (vctxt->depth > vctxt->sizeElemInfos) {
24102         VERROR_INT("xmlSchemaGetFreshElemInfo",
24103             "inconsistent depth encountered");
24104         return (NULL);
24105     }
24106     if (vctxt->elemInfos == NULL) {
24107         vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24108             xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
24109         if (vctxt->elemInfos == NULL) {
24110             xmlSchemaVErrMemory(vctxt,
24111                 "allocating the element info array", NULL);
24112             return (NULL);
24113         }
24114         memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
24115         vctxt->sizeElemInfos = 10;
24116     } else if (vctxt->sizeElemInfos <= vctxt->depth) {
24117         int i = vctxt->sizeElemInfos;
24118
24119         vctxt->sizeElemInfos *= 2;
24120         vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24121             xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
24122             sizeof(xmlSchemaNodeInfoPtr));
24123         if (vctxt->elemInfos == NULL) {
24124             xmlSchemaVErrMemory(vctxt,
24125                 "re-allocating the element info array", NULL);
24126             return (NULL);
24127         }
24128         /*
24129         * We need the new memory to be NULLed.
24130         * TODO: Use memset instead?
24131         */
24132         for (; i < vctxt->sizeElemInfos; i++)
24133             vctxt->elemInfos[i] = NULL;
24134     } else
24135         info = vctxt->elemInfos[vctxt->depth];
24136
24137     if (info == NULL) {
24138         info = (xmlSchemaNodeInfoPtr)
24139             xmlMalloc(sizeof(xmlSchemaNodeInfo));
24140         if (info == NULL) {
24141             xmlSchemaVErrMemory(vctxt,
24142                 "allocating an element info", NULL);
24143             return (NULL);
24144         }
24145         vctxt->elemInfos[vctxt->depth] = info;
24146     } else {
24147         if (info->localName != NULL) {
24148             VERROR_INT("xmlSchemaGetFreshElemInfo",
24149                 "elem info has not been cleared");
24150             return (NULL);
24151         }
24152     }
24153     memset(info, 0, sizeof(xmlSchemaNodeInfo));
24154     info->nodeType = XML_ELEMENT_NODE;
24155     info->depth = vctxt->depth;
24156
24157     return (info);
24158 }
24159
24160 #define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
24161 #define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
24162 #define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
24163
24164 static int
24165 xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
24166                         xmlNodePtr node,
24167                         xmlSchemaTypePtr type,
24168                         xmlSchemaValType valType,
24169                         const xmlChar * value,
24170                         xmlSchemaValPtr val,
24171                         unsigned long length,
24172                         int fireErrors)
24173 {
24174     int ret, error = 0;
24175
24176     xmlSchemaTypePtr tmpType;
24177     xmlSchemaFacetLinkPtr facetLink;
24178     xmlSchemaFacetPtr facet;
24179     unsigned long len = 0;
24180     xmlSchemaWhitespaceValueType ws;
24181
24182     /*
24183     * In Libxml2, derived built-in types have currently no explicit facets.
24184     */
24185     if (type->type == XML_SCHEMA_TYPE_BASIC)
24186         return (0);
24187
24188     /*
24189     * NOTE: Do not jump away, if the facetSet of the given type is
24190     * empty: until now, "pattern" and "enumeration" facets of the
24191     * *base types* need to be checked as well.
24192     */
24193     if (type->facetSet == NULL)
24194         goto pattern_and_enum;
24195
24196     if (! WXS_IS_ATOMIC(type)) {
24197         if (WXS_IS_LIST(type))
24198             goto WXS_IS_LIST;
24199         else
24200             goto pattern_and_enum;
24201     }
24202
24203     /*
24204     * Whitespace handling is only of importance for string-based
24205     * types.
24206     */
24207     tmpType = xmlSchemaGetPrimitiveType(type);
24208     if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
24209         WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
24210         ws = xmlSchemaGetWhiteSpaceFacetValue(type);
24211     } else
24212         ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
24213
24214     /*
24215     * If the value was not computed (for string or
24216     * anySimpleType based types), then use the provided
24217     * type.
24218     */
24219     if (val != NULL)
24220         valType = xmlSchemaGetValType(val);
24221
24222     ret = 0;
24223     for (facetLink = type->facetSet; facetLink != NULL;
24224         facetLink = facetLink->next) {
24225         /*
24226         * Skip the pattern "whiteSpace": it is used to
24227         * format the character content beforehand.
24228         */
24229         switch (facetLink->facet->type) {
24230             case XML_SCHEMA_FACET_WHITESPACE:
24231             case XML_SCHEMA_FACET_PATTERN:
24232             case XML_SCHEMA_FACET_ENUMERATION:
24233                 continue;
24234             case XML_SCHEMA_FACET_LENGTH:
24235             case XML_SCHEMA_FACET_MINLENGTH:
24236             case XML_SCHEMA_FACET_MAXLENGTH:
24237                 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
24238                     valType, value, val, &len, ws);
24239                 break;
24240             default:
24241                 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
24242                     valType, value, val, ws);
24243                 break;
24244         }
24245         if (ret < 0) {
24246             AERROR_INT("xmlSchemaValidateFacets",
24247                 "validating against a atomic type facet");
24248             return (-1);
24249         } else if (ret > 0) {
24250             if (fireErrors)
24251                 xmlSchemaFacetErr(actxt, ret, node,
24252                 value, len, type, facetLink->facet, NULL, NULL, NULL);
24253             else
24254                 return (ret);
24255             if (error == 0)
24256                 error = ret;
24257         }
24258         ret = 0;
24259     }
24260
24261 WXS_IS_LIST:
24262     if (! WXS_IS_LIST(type))
24263         goto pattern_and_enum;
24264     /*
24265     * "length", "minLength" and "maxLength" of list types.
24266     */
24267     ret = 0;
24268     for (facetLink = type->facetSet; facetLink != NULL;
24269         facetLink = facetLink->next) {
24270
24271         switch (facetLink->facet->type) {
24272             case XML_SCHEMA_FACET_LENGTH:
24273             case XML_SCHEMA_FACET_MINLENGTH:
24274             case XML_SCHEMA_FACET_MAXLENGTH:
24275                 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
24276                     value, length, NULL);
24277                 break;
24278             default:
24279                 continue;
24280         }
24281         if (ret < 0) {
24282             AERROR_INT("xmlSchemaValidateFacets",
24283                 "validating against a list type facet");
24284             return (-1);
24285         } else if (ret > 0) {
24286             if (fireErrors)
24287                 xmlSchemaFacetErr(actxt, ret, node,
24288                 value, length, type, facetLink->facet, NULL, NULL, NULL);
24289             else
24290                 return (ret);
24291             if (error == 0)
24292                 error = ret;
24293         }
24294         ret = 0;
24295     }
24296
24297 pattern_and_enum:
24298     if (error >= 0) {
24299         int found = 0;
24300         /*
24301         * Process enumerations. Facet values are in the value space
24302         * of the defining type's base type. This seems to be a bug in the
24303         * XML Schema 1.0 spec. Use the whitespace type of the base type.
24304         * Only the first set of enumerations in the ancestor-or-self axis
24305         * is used for validation.
24306         */
24307         ret = 0;
24308         tmpType = type;
24309         do {
24310             for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
24311                 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
24312                     continue;
24313                 found = 1;
24314                 ret = xmlSchemaAreValuesEqual(facet->val, val);
24315                 if (ret == 1)
24316                     break;
24317                 else if (ret < 0) {
24318                     AERROR_INT("xmlSchemaValidateFacets",
24319                         "validating against an enumeration facet");
24320                     return (-1);
24321                 }
24322             }
24323             if (ret != 0)
24324                 break;
24325             /*
24326             * Break on the first set of enumerations. Any additional
24327             *  enumerations which might be existent on the ancestors
24328             *  of the current type are restricted by this set; thus
24329             *  *must* *not* be taken into account.
24330             */
24331             if (found)
24332                 break;
24333             tmpType = tmpType->baseType;
24334         } while ((tmpType != NULL) &&
24335             (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24336         if (found && (ret == 0)) {
24337             ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
24338             if (fireErrors) {
24339                 xmlSchemaFacetErr(actxt, ret, node,
24340                     value, 0, type, NULL, NULL, NULL, NULL);
24341             } else
24342                 return (ret);
24343             if (error == 0)
24344                 error = ret;
24345         }
24346     }
24347
24348     if (error >= 0) {
24349         int found;
24350         /*
24351         * Process patters. Pattern facets are ORed at type level
24352         * and ANDed if derived. Walk the base type axis.
24353         */
24354         tmpType = type;
24355         facet = NULL;
24356         do {
24357             found = 0;
24358             for (facetLink = tmpType->facetSet; facetLink != NULL;
24359                 facetLink = facetLink->next) {
24360                 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
24361                     continue;
24362                 found = 1;
24363                 /*
24364                 * NOTE that for patterns, @value needs to be the
24365                 * normalized vaule.
24366                 */
24367                 ret = xmlRegexpExec(facetLink->facet->regexp, value);
24368                 if (ret == 1)
24369                     break;
24370                 else if (ret < 0) {
24371                     AERROR_INT("xmlSchemaValidateFacets",
24372                         "validating against a pattern facet");
24373                     return (-1);
24374                 } else {
24375                     /*
24376                     * Save the last non-validating facet.
24377                     */
24378                     facet = facetLink->facet;
24379                 }
24380             }
24381             if (found && (ret != 1)) {
24382                 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
24383                 if (fireErrors) {
24384                     xmlSchemaFacetErr(actxt, ret, node,
24385                         value, 0, type, facet, NULL, NULL, NULL);
24386                 } else
24387                     return (ret);
24388                 if (error == 0)
24389                     error = ret;
24390                 break;
24391             }
24392             tmpType = tmpType->baseType;
24393         } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24394     }
24395
24396     return (error);
24397 }
24398
24399 static xmlChar *
24400 xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24401                         const xmlChar *value)
24402 {
24403     switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
24404         case XML_SCHEMA_WHITESPACE_COLLAPSE:
24405             return (xmlSchemaCollapseString(value));
24406         case XML_SCHEMA_WHITESPACE_REPLACE:
24407             return (xmlSchemaWhiteSpaceReplace(value));
24408         default:
24409             return (NULL);
24410     }
24411 }
24412
24413 static int
24414 xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24415                        const xmlChar *value,
24416                        xmlSchemaValPtr *val,
24417                        int valNeeded)
24418 {
24419     int ret;
24420     const xmlChar *nsName;
24421     xmlChar *local, *prefix = NULL;
24422
24423     ret = xmlValidateQName(value, 1);
24424     if (ret != 0) {
24425         if (ret == -1) {
24426             VERROR_INT("xmlSchemaValidateQName",
24427                 "calling xmlValidateQName()");
24428             return (-1);
24429         }
24430         return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24431     }
24432     /*
24433     * NOTE: xmlSplitQName2 will always return a duplicated
24434     * strings.
24435     */
24436     local = xmlSplitQName2(value, &prefix);
24437     if (local == NULL)
24438         local = xmlStrdup(value);
24439     /*
24440     * OPTIMIZE TODO: Use flags for:
24441     *  - is there any namespace binding?
24442     *  - is there a default namespace?
24443     */
24444     nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24445
24446     if (prefix != NULL) {
24447         xmlFree(prefix);
24448         /*
24449         * A namespace must be found if the prefix is
24450         * NOT NULL.
24451         */
24452         if (nsName == NULL) {
24453             ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24454             xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
24455                 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24456                 "The QName value '%s' has no "
24457                 "corresponding namespace declaration in "
24458                 "scope", value, NULL);
24459             if (local != NULL)
24460                 xmlFree(local);
24461             return (ret);
24462         }
24463     }
24464     if (valNeeded && val) {
24465         if (nsName != NULL)
24466             *val = xmlSchemaNewQNameValue(
24467                 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24468         else
24469             *val = xmlSchemaNewQNameValue(NULL,
24470                 BAD_CAST local);
24471     } else
24472         xmlFree(local);
24473     return (0);
24474 }
24475
24476 /*
24477 * cvc-simple-type
24478 */
24479 static int
24480 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24481                              xmlNodePtr node,
24482                              xmlSchemaTypePtr type,
24483                              const xmlChar *value,
24484                              xmlSchemaValPtr *retVal,
24485                              int fireErrors,
24486                              int normalize,
24487                              int isNormalized)
24488 {
24489     int ret = 0, valNeeded = (retVal) ? 1 : 0;
24490     xmlSchemaValPtr val = NULL;
24491     /* xmlSchemaWhitespaceValueType ws; */
24492     xmlChar *normValue = NULL;
24493
24494 #define NORMALIZE(atype) \
24495     if ((! isNormalized) && \
24496     (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24497         normValue = xmlSchemaNormalizeValue(atype, value); \
24498         if (normValue != NULL) \
24499             value = normValue; \
24500         isNormalized = 1; \
24501     }
24502
24503     if ((retVal != NULL) && (*retVal != NULL)) {
24504         xmlSchemaFreeValue(*retVal);
24505         *retVal = NULL;
24506     }
24507     /*
24508     * 3.14.4 Simple Type Definition Validation Rules
24509     * Validation Rule: String Valid
24510     */
24511     /*
24512     * 1 It is schema-valid with respect to that definition as defined
24513     * by Datatype Valid in [XML Schemas: Datatypes].
24514     */
24515     /*
24516     * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24517     * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6), then
24518     * the string must be a `declared entity name`.
24519     */
24520     /*
24521     * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24522     * given the empty set, as defined in Type Derivation OK (Simple) ($3.14.6),
24523     * then every whitespace-delimited substring of the string must be a `declared
24524     * entity name`.
24525     */
24526     /*
24527     * 2.3 otherwise no further condition applies.
24528     */
24529     if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24530         valNeeded = 1;
24531     if (value == NULL)
24532         value = BAD_CAST "";
24533     if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
24534         xmlSchemaTypePtr biType; /* The built-in type. */
24535         /*
24536         * SPEC (1.2.1) "if {variety} is `atomic` then the string must `match`
24537         * a literal in the `lexical space` of {base type definition}"
24538         */
24539         /*
24540         * Whitespace-normalize.
24541         */
24542         NORMALIZE(type);
24543         if (type->type != XML_SCHEMA_TYPE_BASIC) {
24544             /*
24545             * Get the built-in type.
24546             */
24547             biType = type->baseType;
24548             while ((biType != NULL) &&
24549                 (biType->type != XML_SCHEMA_TYPE_BASIC))
24550                 biType = biType->baseType;
24551
24552             if (biType == NULL) {
24553                 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24554                     "could not get the built-in type");
24555                 goto internal_error;
24556             }
24557         } else
24558             biType = type;
24559         /*
24560         * NOTATIONs need to be processed here, since they need
24561         * to lookup in the hashtable of NOTATION declarations of the schema.
24562         */
24563         if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24564             switch (biType->builtInType) {
24565                 case XML_SCHEMAS_NOTATION:
24566                     ret = xmlSchemaValidateNotation(
24567                         (xmlSchemaValidCtxtPtr) actxt,
24568                         ((xmlSchemaValidCtxtPtr) actxt)->schema,
24569                         NULL, value, &val, valNeeded);
24570                     break;
24571                 case XML_SCHEMAS_QNAME:
24572                     ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24573                         value, &val, valNeeded);
24574                     break;
24575                 default:
24576                     /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24577                     if (valNeeded)
24578                         ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24579                             value, &val, node);
24580                     else
24581                         ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24582                             value, NULL, node);
24583                     break;
24584             }
24585         } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24586             switch (biType->builtInType) {
24587                 case XML_SCHEMAS_NOTATION:
24588                     ret = xmlSchemaValidateNotation(NULL,
24589                         ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24590                         value, &val, valNeeded);
24591                     break;
24592                 default:
24593                     /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24594                     if (valNeeded)
24595                         ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24596                             value, &val, node);
24597                     else
24598                         ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24599                             value, NULL, node);
24600                     break;
24601             }
24602         } else {
24603             /*
24604             * Validation via a public API is not implemented yet.
24605             */
24606             TODO
24607             goto internal_error;
24608         }
24609         if (ret != 0) {
24610             if (ret < 0) {
24611                 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24612                     "validating against a built-in type");
24613                 goto internal_error;
24614             }
24615             if (WXS_IS_LIST(type))
24616                 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24617             else
24618                 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24619         }
24620         if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24621             /*
24622             * Check facets.
24623             */
24624             ret = xmlSchemaValidateFacets(actxt, node, type,
24625                 (xmlSchemaValType) biType->builtInType, value, val,
24626                 0, fireErrors);
24627             if (ret != 0) {
24628                 if (ret < 0) {
24629                     AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24630                         "validating facets of atomic simple type");
24631                     goto internal_error;
24632                 }
24633                 if (WXS_IS_LIST(type))
24634                     ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24635                 else
24636                     ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24637             }
24638         }
24639         if (fireErrors && (ret > 0))
24640             xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24641     } else if (WXS_IS_LIST(type)) {
24642
24643         xmlSchemaTypePtr itemType;
24644         const xmlChar *cur, *end;
24645         xmlChar *tmpValue = NULL;
24646         unsigned long len = 0;
24647         xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24648         /* 1.2.2 if {variety} is `list` then the string must be a sequence
24649         * of white space separated tokens, each of which `match`es a literal
24650         * in the `lexical space` of {item type definition}
24651         */
24652         /*
24653         * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24654         * the list type has an enum or pattern facet.
24655         */
24656         NORMALIZE(type);
24657         /*
24658         * VAL TODO: Optimize validation of empty values.
24659         * VAL TODO: We do not have computed values for lists.
24660         */
24661         itemType = WXS_LIST_ITEMTYPE(type);
24662         cur = value;
24663         do {
24664             while (IS_BLANK_CH(*cur))
24665                 cur++;
24666             end = cur;
24667             while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24668                 end++;
24669             if (end == cur)
24670                 break;
24671             tmpValue = xmlStrndup(cur, end - cur);
24672             len++;
24673
24674             if (valNeeded)
24675                 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24676                     tmpValue, &curVal, fireErrors, 0, 1);
24677             else
24678                 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24679                     tmpValue, NULL, fireErrors, 0, 1);
24680             FREE_AND_NULL(tmpValue);
24681             if (curVal != NULL) {
24682                 /*
24683                 * Add to list of computed values.
24684                 */
24685                 if (val == NULL)
24686                     val = curVal;
24687                 else
24688                     xmlSchemaValueAppend(prevVal, curVal);
24689                 prevVal = curVal;
24690                 curVal = NULL;
24691             }
24692             if (ret != 0) {
24693                 if (ret < 0) {
24694                     AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24695                         "validating an item of list simple type");
24696                     goto internal_error;
24697                 }
24698                 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24699                 break;
24700             }
24701             cur = end;
24702         } while (*cur != 0);
24703         FREE_AND_NULL(tmpValue);
24704         if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24705             /*
24706             * Apply facets (pattern, enumeration).
24707             */
24708             ret = xmlSchemaValidateFacets(actxt, node, type,
24709                 XML_SCHEMAS_UNKNOWN, value, val,
24710                 len, fireErrors);
24711             if (ret != 0) {
24712                 if (ret < 0) {
24713                     AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24714                         "validating facets of list simple type");
24715                     goto internal_error;
24716                 }
24717                 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24718             }
24719         }
24720         if (fireErrors && (ret > 0)) {
24721             /*
24722             * Report the normalized value.
24723             */
24724             normalize = 1;
24725             NORMALIZE(type);
24726             xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24727         }
24728     } else if (WXS_IS_UNION(type)) {
24729         xmlSchemaTypeLinkPtr memberLink;
24730         /*
24731         * TODO: For all datatypes `derived` by `union`  whiteSpace does
24732         * not apply directly; however, the normalization behavior of `union`
24733         * types is controlled by the value of whiteSpace on that one of the
24734         * `memberTypes` against which the `union` is successfully validated.
24735         *
24736         * This means that the value is normalized by the first validating
24737         * member type, then the facets of the union type are applied. This
24738         * needs changing of the value!
24739         */
24740
24741         /*
24742         * 1.2.3 if {variety} is `union` then the string must `match` a
24743         * literal in the `lexical space` of at least one member of
24744         * {member type definitions}
24745         */
24746         memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24747         if (memberLink == NULL) {
24748             AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24749                 "union simple type has no member types");
24750             goto internal_error;
24751         }
24752         /*
24753         * Always normalize union type values, since we currently
24754         * cannot store the whitespace information with the value
24755         * itself; otherwise a later value-comparison would be
24756         * not possible.
24757         */
24758         while (memberLink != NULL) {
24759             if (valNeeded)
24760                 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24761                     memberLink->type, value, &val, 0, 1, 0);
24762             else
24763                 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24764                     memberLink->type, value, NULL, 0, 1, 0);
24765             if (ret <= 0)
24766                 break;
24767             memberLink = memberLink->next;
24768         }
24769         if (ret != 0) {
24770             if (ret < 0) {
24771                 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24772                     "validating members of union simple type");
24773                 goto internal_error;
24774             }
24775             ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24776         }
24777         /*
24778         * Apply facets (pattern, enumeration).
24779         */
24780         if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24781             /*
24782             * The normalization behavior of `union` types is controlled by
24783             * the value of whiteSpace on that one of the `memberTypes`
24784             * against which the `union` is successfully validated.
24785             */
24786             NORMALIZE(memberLink->type);
24787             ret = xmlSchemaValidateFacets(actxt, node, type,
24788                 XML_SCHEMAS_UNKNOWN, value, val,
24789                 0, fireErrors);
24790             if (ret != 0) {
24791                 if (ret < 0) {
24792                     AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24793                         "validating facets of union simple type");
24794                     goto internal_error;
24795                 }
24796                 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24797             }
24798         }
24799         if (fireErrors && (ret > 0))
24800             xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24801     }
24802
24803     if (normValue != NULL)
24804         xmlFree(normValue);
24805     if (ret == 0) {
24806         if (retVal != NULL)
24807             *retVal = val;
24808         else if (val != NULL)
24809             xmlSchemaFreeValue(val);
24810     } else if (val != NULL)
24811         xmlSchemaFreeValue(val);
24812     return (ret);
24813 internal_error:
24814     if (normValue != NULL)
24815         xmlFree(normValue);
24816     if (val != NULL)
24817         xmlSchemaFreeValue(val);
24818     return (-1);
24819 }
24820
24821 static int
24822 xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24823                            const xmlChar *value,
24824                            const xmlChar **nsName,
24825                            const xmlChar **localName)
24826 {
24827     int ret = 0;
24828
24829     if ((nsName == NULL) || (localName == NULL))
24830         return (-1);
24831     *nsName = NULL;
24832     *localName = NULL;
24833
24834     ret = xmlValidateQName(value, 1);
24835     if (ret == -1)
24836         return (-1);
24837     if (ret > 0) {
24838         xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
24839             XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24840             value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24841         return (1);
24842     }
24843     {
24844         xmlChar *local = NULL;
24845         xmlChar *prefix;
24846
24847         /*
24848         * NOTE: xmlSplitQName2 will return a duplicated
24849         * string.
24850         */
24851         local = xmlSplitQName2(value, &prefix);
24852         if (local == NULL)
24853             *localName = xmlDictLookup(vctxt->dict, value, -1);
24854         else {
24855             *localName = xmlDictLookup(vctxt->dict, local, -1);
24856             xmlFree(local);
24857         }
24858
24859         *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24860
24861         if (prefix != NULL) {
24862             xmlFree(prefix);
24863             /*
24864             * A namespace must be found if the prefix is NOT NULL.
24865             */
24866             if (*nsName == NULL) {
24867                 xmlSchemaCustomErr(ACTXT_CAST vctxt,
24868                     XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24869                     WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24870                     "The QName value '%s' has no "
24871                     "corresponding namespace declaration in scope",
24872                     value, NULL);
24873                 return (2);
24874             }
24875         }
24876     }
24877     return (0);
24878 }
24879
24880 static int
24881 xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24882                         xmlSchemaAttrInfoPtr iattr,
24883                         xmlSchemaTypePtr *localType,
24884                         xmlSchemaElementPtr elemDecl)
24885 {
24886     int ret = 0;
24887     /*
24888     * cvc-elt (3.3.4) : (4)
24889     * AND
24890     * Schema-Validity Assessment (Element) (cvc-assess-elt)
24891     *   (1.2.1.2.1) - (1.2.1.2.4)
24892     * Handle 'xsi:type'.
24893     */
24894     if (localType == NULL)
24895         return (-1);
24896     *localType = NULL;
24897     if (iattr == NULL)
24898         return (0);
24899     else {
24900         const xmlChar *nsName = NULL, *local = NULL;
24901         /*
24902         * TODO: We should report a *warning* that the type was overriden
24903         * by the instance.
24904         */
24905         ACTIVATE_ATTRIBUTE(iattr);
24906         /*
24907         * (cvc-elt) (3.3.4) : (4.1)
24908         * (cvc-assess-elt) (1.2.1.2.2)
24909         */
24910         ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24911             &nsName, &local);
24912         if (ret != 0) {
24913             if (ret < 0) {
24914                 VERROR_INT("xmlSchemaValidateElementByDeclaration",
24915                     "calling xmlSchemaQNameExpand() to validate the "
24916                     "attribute 'xsi:type'");
24917                 goto internal_error;
24918             }
24919             goto exit;
24920         }
24921         /*
24922         * (cvc-elt) (3.3.4) : (4.2)
24923         * (cvc-assess-elt) (1.2.1.2.3)
24924         */
24925         *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24926         if (*localType == NULL) {
24927             xmlChar *str = NULL;
24928
24929             xmlSchemaCustomErr(ACTXT_CAST vctxt,
24930                 XML_SCHEMAV_CVC_ELT_4_2, NULL,
24931                 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24932                 "The QName value '%s' of the xsi:type attribute does not "
24933                 "resolve to a type definition",
24934                 xmlSchemaFormatQName(&str, nsName, local), NULL);
24935             FREE_AND_NULL(str);
24936             ret = vctxt->err;
24937             goto exit;
24938         }
24939         if (elemDecl != NULL) {
24940             int set = 0;
24941
24942             /*
24943             * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
24944             * "The `local type definition` must be validly
24945             * derived from the {type definition} given the union of
24946             * the {disallowed substitutions} and the {type definition}'s
24947             * {prohibited substitutions}, as defined in
24948             * Type Derivation OK (Complex) ($3.4.6)
24949             * (if it is a complex type definition),
24950             * or given {disallowed substitutions} as defined in Type
24951             * Derivation OK (Simple) ($3.14.6) (if it is a simple type
24952             * definition)."
24953             *
24954             * {disallowed substitutions}: the "block" on the element decl.
24955             * {prohibited substitutions}: the "block" on the type def.
24956             */
24957             /*
24958             * OPTIMIZE TODO: We could map types already evaluated
24959             * to be validly derived from other types to avoid checking
24960             * this over and over for the same types.
24961             */
24962             if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24963                 (elemDecl->subtypes->flags &
24964                     XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24965                 set |= SUBSET_EXTENSION;
24966
24967             if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24968                 (elemDecl->subtypes->flags &
24969                     XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24970                 set |= SUBSET_RESTRICTION;
24971
24972             /*
24973             * REMOVED and CHANGED since this produced a parser context
24974             * which adds to the string dict of the schema. So this would
24975             * change the schema and we don't want this. We don't need
24976             * the parser context anymore.
24977             *
24978             * if ((vctxt->pctxt == NULL) &&
24979             *   (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24980             *       return (-1);
24981             */
24982
24983             if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
24984                 elemDecl->subtypes, set) != 0) {
24985                 xmlChar *str = NULL;
24986
24987                 xmlSchemaCustomErr(ACTXT_CAST vctxt,
24988                     XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24989                     "The type definition '%s', specified by xsi:type, is "
24990                     "blocked or not validly derived from the type definition "
24991                     "of the element declaration",
24992                     xmlSchemaFormatQName(&str,
24993                         (*localType)->targetNamespace,
24994                         (*localType)->name),
24995                     NULL);
24996                 FREE_AND_NULL(str);
24997                 ret = vctxt->err;
24998                 *localType = NULL;
24999             }
25000         }
25001     }
25002 exit:
25003     ACTIVATE_ELEM;
25004     return (ret);
25005 internal_error:
25006     ACTIVATE_ELEM;
25007     return (-1);
25008 }
25009
25010 static int
25011 xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
25012 {
25013     xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
25014     xmlSchemaTypePtr actualType;
25015
25016     /*
25017     * cvc-elt (3.3.4) : 1
25018     */
25019     if (elemDecl == NULL) {
25020         VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
25021             "No matching declaration available");
25022         return (vctxt->err);
25023     }
25024     actualType = WXS_ELEM_TYPEDEF(elemDecl);
25025     /*
25026     * cvc-elt (3.3.4) : 2
25027     */
25028     if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
25029         VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
25030             "The element declaration is abstract");
25031         return (vctxt->err);
25032     }
25033     if (actualType == NULL) {
25034         VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25035             "The type definition is absent");
25036         return (XML_SCHEMAV_CVC_TYPE_1);
25037     }
25038     if (vctxt->nbAttrInfos != 0) {
25039         int ret;
25040         xmlSchemaAttrInfoPtr iattr;
25041         /*
25042         * cvc-elt (3.3.4) : 3
25043         * Handle 'xsi:nil'.
25044         */
25045         iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25046             XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
25047         if (iattr) {
25048             ACTIVATE_ATTRIBUTE(iattr);
25049             /*
25050             * Validate the value.
25051             */
25052             ret = xmlSchemaVCheckCVCSimpleType(
25053                 ACTXT_CAST vctxt, NULL,
25054                 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
25055                 iattr->value, &(iattr->val), 1, 0, 0);
25056             ACTIVATE_ELEM;
25057             if (ret < 0) {
25058                 VERROR_INT("xmlSchemaValidateElemDecl",
25059                     "calling xmlSchemaVCheckCVCSimpleType() to "
25060                     "validate the attribute 'xsi:nil'");
25061                 return (-1);
25062             }
25063             if (ret == 0) {
25064                 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
25065                     /*
25066                     * cvc-elt (3.3.4) : 3.1
25067                     */
25068                     VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
25069                         "The element is not 'nillable'");
25070                     /* Does not return an error on purpose. */
25071                 } else {
25072                     if (xmlSchemaValueGetAsBoolean(iattr->val)) {
25073                         /*
25074                         * cvc-elt (3.3.4) : 3.2.2
25075                         */
25076                         if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
25077                             (elemDecl->value != NULL)) {
25078                             VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
25079                                 "The element cannot be 'nilled' because "
25080                                 "there is a fixed value constraint defined "
25081                                 "for it");
25082                              /* Does not return an error on purpose. */
25083                         } else
25084                             vctxt->inode->flags |=
25085                                 XML_SCHEMA_ELEM_INFO_NILLED;
25086                     }
25087                 }
25088             }
25089         }
25090         /*
25091         * cvc-elt (3.3.4) : 4
25092         * Handle 'xsi:type'.
25093         */
25094         iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25095             XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25096         if (iattr) {
25097             xmlSchemaTypePtr localType = NULL;
25098
25099             ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
25100                 elemDecl);
25101             if (ret != 0) {
25102                 if (ret == -1) {
25103                     VERROR_INT("xmlSchemaValidateElemDecl",
25104                         "calling xmlSchemaProcessXSIType() to "
25105                         "process the attribute 'xsi:type'");
25106                     return (-1);
25107                 }
25108                 /* Does not return an error on purpose. */
25109             }
25110             if (localType != NULL) {
25111                 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
25112                 actualType = localType;
25113             }
25114         }
25115     }
25116     /*
25117     * IDC: Register identity-constraint XPath matchers.
25118     */
25119     if ((elemDecl->idcs != NULL) &&
25120         (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
25121             return (-1);
25122     /*
25123     * No actual type definition.
25124     */
25125     if (actualType == NULL) {
25126         VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25127             "The type definition is absent");
25128         return (XML_SCHEMAV_CVC_TYPE_1);
25129     }
25130     /*
25131     * Remember the actual type definition.
25132     */
25133     vctxt->inode->typeDef = actualType;
25134
25135     return (0);
25136 }
25137
25138 static int
25139 xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
25140 {
25141     xmlSchemaAttrInfoPtr iattr;
25142     int ret = 0, i;
25143
25144     /*
25145     * SPEC cvc-type (3.1.1)
25146     * "The attributes of must be empty, excepting those whose namespace
25147     * name is identical to http://www.w3.org/2001/XMLSchema-instance and
25148     * whose local name is one of type, nil, schemaLocation or
25149     * noNamespaceSchemaLocation."
25150     */
25151     if (vctxt->nbAttrInfos == 0)
25152         return (0);
25153     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25154         iattr = vctxt->attrInfos[i];
25155         if (! iattr->metaType) {
25156             ACTIVATE_ATTRIBUTE(iattr)
25157             xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25158                 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
25159             ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
25160         }
25161     }
25162     ACTIVATE_ELEM
25163     return (ret);
25164 }
25165
25166 /*
25167 * Cleanup currently used attribute infos.
25168 */
25169 static void
25170 xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
25171 {
25172     int i;
25173     xmlSchemaAttrInfoPtr attr;
25174
25175     if (vctxt->nbAttrInfos == 0)
25176         return;
25177     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25178         attr = vctxt->attrInfos[i];
25179         if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
25180             if (attr->localName != NULL)
25181                 xmlFree((xmlChar *) attr->localName);
25182             if (attr->nsName != NULL)
25183                 xmlFree((xmlChar *) attr->nsName);
25184         }
25185         if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
25186             if (attr->value != NULL)
25187                 xmlFree((xmlChar *) attr->value);
25188         }
25189         if (attr->val != NULL) {
25190             xmlSchemaFreeValue(attr->val);
25191             attr->val = NULL;
25192         }
25193         memset(attr, 0, sizeof(xmlSchemaAttrInfo));
25194     }
25195     vctxt->nbAttrInfos = 0;
25196 }
25197
25198 /*
25199 * 3.4.4 Complex Type Definition Validation Rules
25200 *   Element Locally Valid (Complex Type) (cvc-complex-type)
25201 * 3.2.4 Attribute Declaration Validation Rules
25202 *   Validation Rule: Attribute Locally Valid (cvc-attribute)
25203 *   Attribute Locally Valid (Use) (cvc-au)
25204 *
25205 * Only "assessed" attribute information items will be visible to
25206 * IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
25207 */
25208 static int
25209 xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
25210 {
25211     xmlSchemaTypePtr type = vctxt->inode->typeDef;
25212     xmlSchemaItemListPtr attrUseList;
25213     xmlSchemaAttributeUsePtr attrUse = NULL;
25214     xmlSchemaAttributePtr attrDecl = NULL;
25215     xmlSchemaAttrInfoPtr iattr, tmpiattr;
25216     int i, j, found, nbAttrs, nbUses;
25217     int xpathRes = 0, res, wildIDs = 0, fixed;
25218     xmlNodePtr defAttrOwnerElem = NULL;
25219
25220     /*
25221     * SPEC (cvc-attribute)
25222     * (1) "The declaration must not be `absent` (see Missing
25223     * Sub-components ($5.3) for how this can fail to be
25224     * the case)."
25225     * (2) "Its {type definition} must not be absent."
25226     *
25227     * NOTE (1) + (2): This is not handled here, since we currently do not
25228     * allow validation against schemas which have missing sub-components.
25229     *
25230     * SPEC (cvc-complex-type)
25231     * (3) "For each attribute information item in the element information
25232     * item's [attributes] excepting those whose [namespace name] is
25233     * identical to http://www.w3.org/2001/XMLSchema-instance and whose
25234     * [local name] is one of type, nil, schemaLocation or
25235     * noNamespaceSchemaLocation, the appropriate case among the following
25236     * must be true:
25237     *
25238     */
25239     attrUseList = (xmlSchemaItemListPtr) type->attrUses;
25240     /*
25241     * @nbAttrs is the number of attributes present in the instance.
25242     */
25243     nbAttrs = vctxt->nbAttrInfos;
25244     if (attrUseList != NULL)
25245         nbUses = attrUseList->nbItems;
25246     else
25247         nbUses = 0;
25248     for (i = 0; i < nbUses; i++) {
25249         found = 0;
25250         attrUse = attrUseList->items[i];
25251         attrDecl = WXS_ATTRUSE_DECL(attrUse);
25252         for (j = 0; j < nbAttrs; j++) {
25253             iattr = vctxt->attrInfos[j];
25254             /*
25255             * SPEC (cvc-complex-type) (3)
25256             * Skip meta attributes.
25257             */
25258             if (iattr->metaType)
25259                 continue;
25260             if (iattr->localName[0] != attrDecl->name[0])
25261                 continue;
25262             if (!xmlStrEqual(iattr->localName, attrDecl->name))
25263                 continue;
25264             if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
25265                 continue;
25266             found = 1;
25267             /*
25268             * SPEC (cvc-complex-type)
25269             * (3.1) "If there is among the {attribute uses} an attribute
25270             * use with an {attribute declaration} whose {name} matches
25271             * the attribute information item's [local name] and whose
25272             * {target namespace} is identical to the attribute information
25273             * item's [namespace name] (where an `absent` {target namespace}
25274             * is taken to be identical to a [namespace name] with no value),
25275             * then the attribute information must be `valid` with respect
25276             * to that attribute use as per Attribute Locally Valid (Use)
25277             * ($3.5.4). In this case the {attribute declaration} of that
25278             * attribute use is the `context-determined declaration` for the
25279             * attribute information item with respect to Schema-Validity
25280             * Assessment (Attribute) ($3.2.4) and
25281             * Assessment Outcome (Attribute) ($3.2.5).
25282             */
25283             iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25284             iattr->use = attrUse;
25285             /*
25286             * Context-determined declaration.
25287             */
25288             iattr->decl = attrDecl;
25289             iattr->typeDef = attrDecl->subtypes;
25290             break;
25291         }
25292
25293         if (found)
25294             continue;
25295
25296         if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
25297             /*
25298             * Handle non-existent, required attributes.
25299             *
25300             * SPEC (cvc-complex-type)
25301             * (4) "The {attribute declaration} of each attribute use in
25302             * the {attribute uses} whose {required} is true matches one
25303             * of the attribute information items in the element information
25304             * item's [attributes] as per clause 3.1 above."
25305             */
25306             tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25307             if (tmpiattr == NULL) {
25308                 VERROR_INT(
25309                     "xmlSchemaVAttributesComplex",
25310                     "calling xmlSchemaGetFreshAttrInfo()");
25311                 return (-1);
25312             }
25313             tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
25314             tmpiattr->use = attrUse;
25315             tmpiattr->decl = attrDecl;
25316         } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
25317             ((attrUse->defValue != NULL) ||
25318              (attrDecl->defValue != NULL))) {
25319             /*
25320             * Handle non-existent, optional, default/fixed attributes.
25321             */
25322             tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25323             if (tmpiattr == NULL) {
25324                 VERROR_INT(
25325                     "xmlSchemaVAttributesComplex",
25326                     "calling xmlSchemaGetFreshAttrInfo()");
25327                 return (-1);
25328             }
25329             tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
25330             tmpiattr->use = attrUse;
25331             tmpiattr->decl = attrDecl;
25332             tmpiattr->typeDef = attrDecl->subtypes;
25333             tmpiattr->localName = attrDecl->name;
25334             tmpiattr->nsName = attrDecl->targetNamespace;
25335         }
25336     }
25337
25338     if (vctxt->nbAttrInfos == 0)
25339         return (0);
25340     /*
25341     * Validate against the wildcard.
25342     */
25343     if (type->attributeWildcard != NULL) {
25344         /*
25345         * SPEC (cvc-complex-type)
25346         * (3.2.1) "There must be an {attribute wildcard}."
25347         */
25348         for (i = 0; i < nbAttrs; i++) {
25349             iattr = vctxt->attrInfos[i];
25350             /*
25351             * SPEC (cvc-complex-type) (3)
25352             * Skip meta attributes.
25353             */
25354             if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
25355                 continue;
25356             /*
25357             * SPEC (cvc-complex-type)
25358             * (3.2.2) "The attribute information item must be `valid` with
25359             * respect to it as defined in Item Valid (Wildcard) ($3.10.4)."
25360             *
25361             * SPEC Item Valid (Wildcard) (cvc-wildcard)
25362             * "... its [namespace name] must be `valid` with respect to
25363             * the wildcard constraint, as defined in Wildcard allows
25364             * Namespace Name ($3.10.4)."
25365             */
25366             if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
25367                     iattr->nsName) == 0) {
25368                 /*
25369                 * Handle processContents.
25370                 *
25371                 * SPEC (cvc-wildcard):
25372                 * processContents | context-determined declaration:
25373                 * "strict"          "mustFind"
25374                 * "lax"             "none"
25375                 * "skip"            "skip"
25376                 */
25377                 if (type->attributeWildcard->processContents ==
25378                     XML_SCHEMAS_ANY_SKIP) {
25379                      /*
25380                     * context-determined declaration = "skip"
25381                     *
25382                     * SPEC PSVI Assessment Outcome (Attribute)
25383                     * [validity] = "notKnown"
25384                     * [validation attempted] = "none"
25385                     */
25386                     iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
25387                     continue;
25388                 }
25389                 /*
25390                 * Find an attribute declaration.
25391                 */
25392                 iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25393                     iattr->localName, iattr->nsName);
25394                 if (iattr->decl != NULL) {
25395                     iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25396                     /*
25397                     * SPEC (cvc-complex-type)
25398                     * (5) "Let [Definition:]  the wild IDs be the set of
25399                     * all attribute information item to which clause 3.2
25400                     * applied and whose `validation` resulted in a
25401                     * `context-determined declaration` of mustFind or no
25402                     * `context-determined declaration` at all, and whose
25403                     * [local name] and [namespace name] resolve (as
25404                     * defined by QName resolution (Instance) ($3.15.4)) to
25405                     * an attribute declaration whose {type definition} is
25406                     * or is derived from ID. Then all of the following
25407                     * must be true:"
25408                     */
25409                     iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
25410                     if (xmlSchemaIsDerivedFromBuiltInType(
25411                         iattr->typeDef, XML_SCHEMAS_ID)) {
25412                         /*
25413                         * SPEC (5.1) "There must be no more than one
25414                         * item in `wild IDs`."
25415                         */
25416                         if (wildIDs != 0) {
25417                             /* VAL TODO */
25418                             iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
25419                             TODO
25420                             continue;
25421                         }
25422                         wildIDs++;
25423                         /*
25424                         * SPEC (cvc-complex-type)
25425                         * (5.2) "If `wild IDs` is non-empty, there must not
25426                         * be any attribute uses among the {attribute uses}
25427                         * whose {attribute declaration}'s {type definition}
25428                         * is or is derived from ID."
25429                         */
25430                         if (attrUseList != NULL) {
25431                             for (j = 0; j < attrUseList->nbItems; j++) {
25432                                 if (xmlSchemaIsDerivedFromBuiltInType(
25433                                     WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25434                                     XML_SCHEMAS_ID)) {
25435                                     /* URGENT VAL TODO: implement */
25436                             iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25437                                     TODO
25438                                     break;
25439                                 }
25440                             }
25441                         }
25442                     }
25443                 } else if (type->attributeWildcard->processContents ==
25444                     XML_SCHEMAS_ANY_LAX) {
25445                     iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
25446                     /*
25447                     * SPEC PSVI Assessment Outcome (Attribute)
25448                     * [validity] = "notKnown"
25449                     * [validation attempted] = "none"
25450                     */
25451                 } else {
25452                     iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
25453                 }
25454             }
25455         }
25456     }
25457
25458     if (vctxt->nbAttrInfos == 0)
25459         return (0);
25460
25461     /*
25462     * Get the owner element; needed for creation of default attributes.
25463     * This fixes bug #341337, reported by David Grohmann.
25464     */
25465     if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25466         xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25467         if (ielem && ielem->node && ielem->node->doc)
25468             defAttrOwnerElem = ielem->node;
25469     }
25470     /*
25471     * Validate values, create default attributes, evaluate IDCs.
25472     */
25473     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25474         iattr = vctxt->attrInfos[i];
25475         /*
25476         * VAL TODO: Note that we won't try to resolve IDCs to
25477         * "lax" and "skip" validated attributes. Check what to
25478         * do in this case.
25479         */
25480         if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25481             (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
25482             continue;
25483         /*
25484         * VAL TODO: What to do if the type definition is missing?
25485         */
25486         if (iattr->typeDef == NULL) {
25487             iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
25488             continue;
25489         }
25490
25491         ACTIVATE_ATTRIBUTE(iattr);
25492         fixed = 0;
25493         xpathRes = 0;
25494
25495         if (vctxt->xpathStates != NULL) {
25496             /*
25497             * Evaluate IDCs.
25498             */
25499             xpathRes = xmlSchemaXPathEvaluate(vctxt,
25500                 XML_ATTRIBUTE_NODE);
25501             if (xpathRes == -1) {
25502                 VERROR_INT("xmlSchemaVAttributesComplex",
25503                     "calling xmlSchemaXPathEvaluate()");
25504                 goto internal_error;
25505             }
25506         }
25507
25508         if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
25509             /*
25510             * Default/fixed attributes.
25511             * We need the value only if we need to resolve IDCs or
25512             * will create default attributes.
25513             */
25514             if ((xpathRes) || (defAttrOwnerElem)) {
25515                 if (iattr->use->defValue != NULL) {
25516                     iattr->value = (xmlChar *) iattr->use->defValue;
25517                     iattr->val = iattr->use->defVal;
25518                 } else {
25519                     iattr->value = (xmlChar *) iattr->decl->defValue;
25520                     iattr->val = iattr->decl->defVal;
25521                 }
25522                 /*
25523                 * IDCs will consume the precomputed default value,
25524                 * so we need to clone it.
25525                 */
25526                 if (iattr->val == NULL) {
25527                     VERROR_INT("xmlSchemaVAttributesComplex",
25528                         "default/fixed value on an attribute use was "
25529                         "not precomputed");
25530                     goto internal_error;
25531                 }
25532                 iattr->val = xmlSchemaCopyValue(iattr->val);
25533                 if (iattr->val == NULL) {
25534                     VERROR_INT("xmlSchemaVAttributesComplex",
25535                         "calling xmlSchemaCopyValue()");
25536                     goto internal_error;
25537                 }
25538             }
25539             /*
25540             * PSVI: Add the default attribute to the current element.
25541             * VAL TODO: Should we use the *normalized* value? This currently
25542             *   uses the *initial* value.
25543             */
25544
25545             if (defAttrOwnerElem) {
25546                 xmlChar *normValue;
25547                 const xmlChar *value;
25548
25549                 value = iattr->value;
25550                 /*
25551                 * Normalize the value.
25552                 */
25553                 normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25554                     iattr->value);
25555                 if (normValue != NULL)
25556                     value = BAD_CAST normValue;
25557
25558                 if (iattr->nsName == NULL) {
25559                     if (xmlNewProp(defAttrOwnerElem,
25560                         iattr->localName, value) == NULL) {
25561                         VERROR_INT("xmlSchemaVAttributesComplex",
25562                             "calling xmlNewProp()");
25563                         if (normValue != NULL)
25564                             xmlFree(normValue);
25565                         goto internal_error;
25566                     }
25567                 } else {
25568                     xmlNsPtr ns;
25569
25570                     ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25571                         defAttrOwnerElem, iattr->nsName);
25572                     if (ns == NULL) {
25573                         xmlChar prefix[12];
25574                         int counter = 0;
25575
25576                         /*
25577                         * Create a namespace declaration on the validation
25578                         * root node if no namespace declaration is in scope.
25579                         */
25580                         do {
25581                             snprintf((char *) prefix, 12, "p%d", counter++);
25582                             ns = xmlSearchNs(defAttrOwnerElem->doc,
25583                                 defAttrOwnerElem, BAD_CAST prefix);
25584                             if (counter > 1000) {
25585                                 VERROR_INT(
25586                                     "xmlSchemaVAttributesComplex",
25587                                     "could not compute a ns prefix for a "
25588                                     "default/fixed attribute");
25589                                 if (normValue != NULL)
25590                                     xmlFree(normValue);
25591                                 goto internal_error;
25592                             }
25593                         } while (ns != NULL);
25594                         ns = xmlNewNs(vctxt->validationRoot,
25595                             iattr->nsName, BAD_CAST prefix);
25596                     }
25597                     /*
25598                     * TODO:
25599                     * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25600                     * If we have QNames: do we need to ensure there's a
25601                     * prefix defined for the QName?
25602                     */
25603                     xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
25604                 }
25605                 if (normValue != NULL)
25606                     xmlFree(normValue);
25607             }
25608             /*
25609             * Go directly to IDC evaluation.
25610             */
25611             goto eval_idcs;
25612         }
25613         /*
25614         * Validate the value.
25615         */
25616         if (vctxt->value != NULL) {
25617             /*
25618             * Free last computed value; just for safety reasons.
25619             */
25620             xmlSchemaFreeValue(vctxt->value);
25621             vctxt->value = NULL;
25622         }
25623         /*
25624         * Note that the attribute *use* can be unavailable, if
25625         * the attribute was a wild attribute.
25626         */
25627         if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25628             ((iattr->use != NULL) &&
25629              (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
25630             fixed = 1;
25631         else
25632             fixed = 0;
25633         /*
25634         * SPEC (cvc-attribute)
25635         * (3) "The item's `normalized value` must be locally `valid`
25636         * with respect to that {type definition} as per
25637         * String Valid ($3.14.4)."
25638         *
25639         * VAL TODO: Do we already have the
25640         * "normalized attribute value" here?
25641         */
25642         if (xpathRes || fixed) {
25643             iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
25644             /*
25645             * Request a computed value.
25646             */
25647             res = xmlSchemaVCheckCVCSimpleType(
25648                 ACTXT_CAST vctxt,
25649                 iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
25650                 1, 1, 0);
25651         } else {
25652             res = xmlSchemaVCheckCVCSimpleType(
25653                 ACTXT_CAST vctxt,
25654                 iattr->node, iattr->typeDef, iattr->value, NULL,
25655                 1, 0, 0);
25656         }
25657
25658         if (res != 0) {
25659             if (res == -1) {
25660                 VERROR_INT("xmlSchemaVAttributesComplex",
25661                     "calling xmlSchemaStreamValidateSimpleTypeValue()");
25662                 goto internal_error;
25663             }
25664             iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
25665             /*
25666             * SPEC PSVI Assessment Outcome (Attribute)
25667             * [validity] = "invalid"
25668             */
25669             goto eval_idcs;
25670         }
25671
25672         if (fixed) {
25673             /*
25674             * SPEC Attribute Locally Valid (Use) (cvc-au)
25675             * "For an attribute information item to be `valid`
25676             * with respect to an attribute use its *normalized*
25677             * value must match the *canonical* lexical
25678             * representation of the attribute use's {value
25679             * constraint}value, if it is present and fixed."
25680             *
25681             * VAL TODO: The requirement for the *canonical* value
25682             * will be removed in XML Schema 1.1.
25683             */
25684             /*
25685             * SPEC Attribute Locally Valid (cvc-attribute)
25686             * (4) "The item's *actual* value must match the *value* of
25687             * the {value constraint}, if it is present and fixed."
25688             */
25689             if (iattr->val == NULL) {
25690                 /* VAL TODO: A value was not precomputed. */
25691                 TODO
25692                 goto eval_idcs;
25693             }
25694             if ((iattr->use != NULL) &&
25695                 (iattr->use->defValue != NULL)) {
25696                 if (iattr->use->defVal == NULL) {
25697                     /* VAL TODO: A default value was not precomputed. */
25698                     TODO
25699                     goto eval_idcs;
25700                 }
25701                 iattr->vcValue = iattr->use->defValue;
25702                 /*
25703                 if (xmlSchemaCompareValuesWhtsp(attr->val,
25704                     (xmlSchemaWhitespaceValueType) ws,
25705                     attr->use->defVal,
25706                     (xmlSchemaWhitespaceValueType) ws) != 0) {
25707                 */
25708                 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25709                     iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25710             } else {
25711                 if (iattr->decl->defVal == NULL) {
25712                     /* VAL TODO: A default value was not precomputed. */
25713                     TODO
25714                     goto eval_idcs;
25715                 }
25716                 iattr->vcValue = iattr->decl->defValue;
25717                 /*
25718                 if (xmlSchemaCompareValuesWhtsp(attr->val,
25719                     (xmlSchemaWhitespaceValueType) ws,
25720                     attrDecl->defVal,
25721                     (xmlSchemaWhitespaceValueType) ws) != 0) {
25722                 */
25723                 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25724                     iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25725             }
25726             /*
25727             * [validity] = "valid"
25728             */
25729         }
25730 eval_idcs:
25731         /*
25732         * Evaluate IDCs.
25733         */
25734         if (xpathRes) {
25735             if (xmlSchemaXPathProcessHistory(vctxt,
25736                 vctxt->depth +1) == -1) {
25737                 VERROR_INT("xmlSchemaVAttributesComplex",
25738                     "calling xmlSchemaXPathEvaluate()");
25739                 goto internal_error;
25740             }
25741         } else if (vctxt->xpathStates != NULL)
25742             xmlSchemaXPathPop(vctxt);
25743     }
25744
25745     /*
25746     * Report errors.
25747     */
25748     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25749         iattr = vctxt->attrInfos[i];
25750         if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25751             (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25752             (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25753             (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
25754             continue;
25755         ACTIVATE_ATTRIBUTE(iattr);
25756         switch (iattr->state) {
25757             case XML_SCHEMAS_ATTR_ERR_MISSING: {
25758                     xmlChar *str = NULL;
25759                     ACTIVATE_ELEM;
25760                     xmlSchemaCustomErr(ACTXT_CAST vctxt,
25761                         XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25762                         "The attribute '%s' is required but missing",
25763                         xmlSchemaFormatQName(&str,
25764                             iattr->decl->targetNamespace,
25765                             iattr->decl->name),
25766                         NULL);
25767                     FREE_AND_NULL(str)
25768                     break;
25769                 }
25770             case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25771                 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25772                     "The type definition is absent");
25773                 break;
25774             case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
25775                 xmlSchemaCustomErr(ACTXT_CAST vctxt,
25776                     XML_SCHEMAV_CVC_AU, NULL, NULL,
25777                     "The value '%s' does not match the fixed "
25778                     "value constraint '%s'",
25779                     iattr->value, iattr->vcValue);
25780                 break;
25781             case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25782                 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25783                     "No matching global attribute declaration available, but "
25784                     "demanded by the strict wildcard");
25785                 break;
25786             case XML_SCHEMAS_ATTR_UNKNOWN:
25787                 if (iattr->metaType)
25788                     break;
25789                 /*
25790                 * MAYBE VAL TODO: One might report different error messages
25791                 * for the following errors.
25792                 */
25793                 if (type->attributeWildcard == NULL) {
25794                     xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25795                         XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
25796                 } else {
25797                     xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25798                         XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
25799                 }
25800                 break;
25801             default:
25802                 break;
25803         }
25804     }
25805
25806     ACTIVATE_ELEM;
25807     return (0);
25808 internal_error:
25809     ACTIVATE_ELEM;
25810     return (-1);
25811 }
25812
25813 static int
25814 xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25815                               int *skip)
25816 {
25817     xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25818     /*
25819     * The namespace of the element was already identified to be
25820     * matching the wildcard.
25821     */
25822     if ((skip == NULL) || (wild == NULL) ||
25823         (wild->type != XML_SCHEMA_TYPE_ANY)) {
25824         VERROR_INT("xmlSchemaValidateElemWildcard",
25825             "bad arguments");
25826         return (-1);
25827     }
25828     *skip = 0;
25829     if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25830         /*
25831         * URGENT VAL TODO: Either we need to position the stream to the
25832         * next sibling, or walk the whole subtree.
25833         */
25834         *skip = 1;
25835         return (0);
25836     }
25837     {
25838         xmlSchemaElementPtr decl = NULL;
25839
25840         decl = xmlSchemaGetElem(vctxt->schema,
25841             vctxt->inode->localName, vctxt->inode->nsName);
25842         if (decl != NULL) {
25843             vctxt->inode->decl = decl;
25844             return (0);
25845         }
25846     }
25847     if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25848         /* VAL TODO: Change to proper error code. */
25849         VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
25850             "No matching global element declaration available, but "
25851             "demanded by the strict wildcard");
25852         return (vctxt->err);
25853     }
25854     if (vctxt->nbAttrInfos != 0) {
25855         xmlSchemaAttrInfoPtr iattr;
25856         /*
25857         * SPEC Validation Rule: Schema-Validity Assessment (Element)
25858         * (1.2.1.2.1) - (1.2.1.2.3 )
25859         *
25860         * Use the xsi:type attribute for the type definition.
25861         */
25862         iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25863             XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25864         if (iattr != NULL) {
25865             if (xmlSchemaProcessXSIType(vctxt, iattr,
25866                 &(vctxt->inode->typeDef), NULL) == -1) {
25867                 VERROR_INT("xmlSchemaValidateElemWildcard",
25868                     "calling xmlSchemaProcessXSIType() to "
25869                     "process the attribute 'xsi:nil'");
25870                 return (-1);
25871             }
25872             /*
25873             * Don't return an error on purpose.
25874             */
25875             return (0);
25876         }
25877     }
25878     /*
25879     * SPEC Validation Rule: Schema-Validity Assessment (Element)
25880     *
25881     * Fallback to "anyType".
25882     */
25883     vctxt->inode->typeDef =
25884         xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25885     return (0);
25886 }
25887
25888 /*
25889 * xmlSchemaCheckCOSValidDefault:
25890 *
25891 * This will be called if: not nilled, no content and a default/fixed
25892 * value is provided.
25893 */
25894
25895 static int
25896 xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25897                               const xmlChar *value,
25898                               xmlSchemaValPtr *val)
25899 {
25900     int ret = 0;
25901     xmlSchemaNodeInfoPtr inode = vctxt->inode;
25902
25903     /*
25904     * cos-valid-default:
25905     * Schema Component Constraint: Element Default Valid (Immediate)
25906     * For a string to be a valid default with respect to a type
25907     * definition the appropriate case among the following must be true:
25908     */
25909     if WXS_IS_COMPLEX(inode->typeDef) {
25910         /*
25911         * Complex type.
25912         *
25913         * SPEC (2.1) "its {content type} must be a simple type definition
25914         * or mixed."
25915         * SPEC (2.2.2) "If the {content type} is mixed, then the {content
25916         * type}'s particle must be `emptiable` as defined by
25917         * Particle Emptiable ($3.9.6)."
25918         */
25919         if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25920             ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25921              (! WXS_EMPTIABLE(inode->typeDef)))) {
25922             ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25923             /* NOTE that this covers (2.2.2) as well. */
25924             VERROR(ret, NULL,
25925                 "For a string to be a valid default, the type definition "
25926                 "must be a simple type or a complex type with simple content "
25927                 "or mixed content and a particle emptiable");
25928             return(ret);
25929         }
25930     }
25931     /*
25932     * 1 If the type definition is a simple type definition, then the string
25933     * must be `valid` with respect to that definition as defined by String
25934     * Valid ($3.14.4).
25935     *
25936     * AND
25937     *
25938     * 2.2.1 If the {content type} is a simple type definition, then the
25939     * string must be `valid` with respect to that simple type definition
25940     * as defined by String Valid ($3.14.4).
25941     */
25942     if (WXS_IS_SIMPLE(inode->typeDef)) {
25943
25944         ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25945             NULL, inode->typeDef, value, val, 1, 1, 0);
25946
25947     } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
25948
25949         ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25950             NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25951     }
25952     if (ret < 0) {
25953         VERROR_INT("xmlSchemaCheckCOSValidDefault",
25954             "calling xmlSchemaVCheckCVCSimpleType()");
25955     }
25956     return (ret);
25957 }
25958
25959 static void
25960 xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
25961                                const xmlChar * name ATTRIBUTE_UNUSED,
25962                                xmlSchemaElementPtr item,
25963                                xmlSchemaNodeInfoPtr inode)
25964 {
25965     inode->decl = item;
25966 #ifdef DEBUG_CONTENT
25967     {
25968         xmlChar *str = NULL;
25969
25970         if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
25971             xmlGenericError(xmlGenericErrorContext,
25972                 "AUTOMATON callback for '%s' [declaration]\n",
25973                 xmlSchemaFormatQName(&str,
25974                 inode->localName, inode->nsName));
25975         } else {
25976             xmlGenericError(xmlGenericErrorContext,
25977                     "AUTOMATON callback for '%s' [wildcard]\n",
25978                     xmlSchemaFormatQName(&str,
25979                     inode->localName, inode->nsName));
25980
25981         }
25982         FREE_AND_NULL(str)
25983     }
25984 #endif
25985 }
25986
25987 static int
25988 xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
25989 {
25990     vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25991     if (vctxt->inode == NULL) {
25992         VERROR_INT("xmlSchemaValidatorPushElem",
25993             "calling xmlSchemaGetFreshElemInfo()");
25994         return (-1);
25995     }
25996     vctxt->nbAttrInfos = 0;
25997     return (0);
25998 }
25999
26000 static int
26001 xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
26002                              xmlSchemaNodeInfoPtr inode,
26003                              xmlSchemaTypePtr type,
26004                              const xmlChar *value)
26005 {
26006     if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
26007         return (xmlSchemaVCheckCVCSimpleType(
26008             ACTXT_CAST vctxt, NULL,
26009             type, value, &(inode->val), 1, 1, 0));
26010     else
26011         return (xmlSchemaVCheckCVCSimpleType(
26012             ACTXT_CAST vctxt, NULL,
26013             type, value, NULL, 1, 0, 0));
26014 }
26015
26016
26017
26018 /*
26019 * Process END of element.
26020 */
26021 static int
26022 xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
26023 {
26024     int ret = 0;
26025     xmlSchemaNodeInfoPtr inode = vctxt->inode;
26026
26027     if (vctxt->nbAttrInfos != 0)
26028         xmlSchemaClearAttrInfos(vctxt);
26029     if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
26030         /*
26031         * This element was not expected;
26032         * we will not validate child elements of broken parents.
26033         * Skip validation of all content of the parent.
26034         */
26035         vctxt->skipDepth = vctxt->depth -1;
26036         goto end_elem;
26037     }
26038     if ((inode->typeDef == NULL) ||
26039         (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
26040         /*
26041         * 1. the type definition might be missing if the element was
26042         *    error prone
26043         * 2. it might be abstract.
26044         */
26045         goto end_elem;
26046     }
26047     /*
26048     * Check the content model.
26049     */
26050     if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
26051         (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
26052
26053         /*
26054         * Workaround for "anyType".
26055         */
26056         if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
26057             goto character_content;
26058
26059         if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
26060             xmlChar *values[10];
26061             int terminal, nbval = 10, nbneg;
26062
26063             if (inode->regexCtxt == NULL) {
26064                 /*
26065                 * Create the regex context.
26066                 */
26067                 inode->regexCtxt =
26068                     xmlRegNewExecCtxt(inode->typeDef->contModel,
26069                     (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26070                     vctxt);
26071                 if (inode->regexCtxt == NULL) {
26072                     VERROR_INT("xmlSchemaValidatorPopElem",
26073                         "failed to create a regex context");
26074                     goto internal_error;
26075                 }
26076 #ifdef DEBUG_AUTOMATA
26077                 xmlGenericError(xmlGenericErrorContext,
26078                     "AUTOMATON create on '%s'\n", inode->localName);
26079 #endif
26080             }
26081
26082             /*
26083              * Do not check further content if the node has been nilled
26084              */
26085             if (INODE_NILLED(inode)) {
26086                 ret = 0;
26087 #ifdef DEBUG_AUTOMATA
26088                 xmlGenericError(xmlGenericErrorContext,
26089                     "AUTOMATON succeeded on nilled '%s'\n",
26090                     inode->localName);
26091 #endif
26092                 goto skip_nilled;
26093             }
26094
26095             /*
26096             * Get hold of the still expected content, since a further
26097             * call to xmlRegExecPushString() will loose this information.
26098             */
26099             xmlRegExecNextValues(inode->regexCtxt,
26100                 &nbval, &nbneg, &values[0], &terminal);
26101             ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
26102             if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) {
26103                 /*
26104                 * Still missing something.
26105                 */
26106                 ret = 1;
26107                 inode->flags |=
26108                     XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26109                 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26110                     XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
26111                     "Missing child element(s)",
26112                     nbval, nbneg, values);
26113 #ifdef DEBUG_AUTOMATA
26114                 xmlGenericError(xmlGenericErrorContext,
26115                     "AUTOMATON missing ERROR on '%s'\n",
26116                     inode->localName);
26117 #endif
26118             } else {
26119                 /*
26120                 * Content model is satisfied.
26121                 */
26122                 ret = 0;
26123 #ifdef DEBUG_AUTOMATA
26124                 xmlGenericError(xmlGenericErrorContext,
26125                     "AUTOMATON succeeded on '%s'\n",
26126                     inode->localName);
26127 #endif
26128             }
26129
26130         }
26131     }
26132
26133 skip_nilled:
26134
26135     if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
26136         goto end_elem;
26137
26138 character_content:
26139
26140     if (vctxt->value != NULL) {
26141         xmlSchemaFreeValue(vctxt->value);
26142         vctxt->value = NULL;
26143     }
26144     /*
26145     * Check character content.
26146     */
26147     if (inode->decl == NULL) {
26148         /*
26149         * Speedup if no declaration exists.
26150         */
26151         if (WXS_IS_SIMPLE(inode->typeDef)) {
26152             ret = xmlSchemaVCheckINodeDataType(vctxt,
26153                 inode, inode->typeDef, inode->value);
26154         } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26155             ret = xmlSchemaVCheckINodeDataType(vctxt,
26156                 inode, inode->typeDef->contentTypeDef,
26157                 inode->value);
26158         }
26159         if (ret < 0) {
26160             VERROR_INT("xmlSchemaValidatorPopElem",
26161                 "calling xmlSchemaVCheckCVCSimpleType()");
26162             goto internal_error;
26163         }
26164         goto end_elem;
26165     }
26166     /*
26167     * cvc-elt (3.3.4) : 5
26168     * The appropriate case among the following must be true:
26169     */
26170     /*
26171     * cvc-elt (3.3.4) : 5.1
26172     * If the declaration has a {value constraint},
26173     * the item has neither element nor character [children] and
26174     * clause 3.2 has not applied, then all of the following must be true:
26175     */
26176     if ((inode->decl->value != NULL) &&
26177         (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
26178         (! INODE_NILLED(inode))) {
26179         /*
26180         * cvc-elt (3.3.4) : 5.1.1
26181         * If the `actual type definition` is a `local type definition`
26182         * then the canonical lexical representation of the {value constraint}
26183         * value must be a valid default for the `actual type definition` as
26184         * defined in Element Default Valid (Immediate) ($3.3.6).
26185         */
26186         /*
26187         * NOTE: 'local' above means types acquired by xsi:type.
26188         * NOTE: Although the *canonical* value is stated, it is not
26189         * relevant if canonical or not. Additionally XML Schema 1.1
26190         * will removed this requirement as well.
26191         */
26192         if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
26193
26194             ret = xmlSchemaCheckCOSValidDefault(vctxt,
26195                 inode->decl->value, &(inode->val));
26196             if (ret != 0) {
26197                 if (ret < 0) {
26198                     VERROR_INT("xmlSchemaValidatorPopElem",
26199                         "calling xmlSchemaCheckCOSValidDefault()");
26200                     goto internal_error;
26201                 }
26202                 goto end_elem;
26203             }
26204             /*
26205             * Stop here, to avoid redundant validation of the value
26206             * (see following).
26207             */
26208             goto default_psvi;
26209         }
26210         /*
26211         * cvc-elt (3.3.4) : 5.1.2
26212         * The element information item with the canonical lexical
26213         * representation of the {value constraint} value used as its
26214         * `normalized value` must be `valid` with respect to the
26215         * `actual type definition` as defined by Element Locally Valid (Type)
26216         * ($3.3.4).
26217         */
26218         if (WXS_IS_SIMPLE(inode->typeDef)) {
26219             ret = xmlSchemaVCheckINodeDataType(vctxt,
26220                 inode, inode->typeDef, inode->decl->value);
26221         } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26222             ret = xmlSchemaVCheckINodeDataType(vctxt,
26223                 inode, inode->typeDef->contentTypeDef,
26224                 inode->decl->value);
26225         }
26226         if (ret != 0) {
26227             if (ret < 0) {
26228                 VERROR_INT("xmlSchemaValidatorPopElem",
26229                     "calling xmlSchemaVCheckCVCSimpleType()");
26230                 goto internal_error;
26231             }
26232             goto end_elem;
26233         }
26234
26235 default_psvi:
26236         /*
26237         * PSVI: Create a text node on the instance element.
26238         */
26239         if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
26240             (inode->node != NULL)) {
26241             xmlNodePtr textChild;
26242             xmlChar *normValue;
26243             /*
26244             * VAL TODO: Normalize the value.
26245             */
26246             normValue = xmlSchemaNormalizeValue(inode->typeDef,
26247                 inode->decl->value);
26248             if (normValue != NULL) {
26249                 textChild = xmlNewText(BAD_CAST normValue);
26250                 xmlFree(normValue);
26251             } else
26252                 textChild = xmlNewText(inode->decl->value);
26253             if (textChild == NULL) {
26254                 VERROR_INT("xmlSchemaValidatorPopElem",
26255                     "calling xmlNewText()");
26256                 goto internal_error;
26257             } else
26258                 xmlAddChild(inode->node, textChild);
26259         }
26260
26261     } else if (! INODE_NILLED(inode)) {
26262         /*
26263         * 5.2.1 The element information item must be `valid` with respect
26264         * to the `actual type definition` as defined by Element Locally
26265         * Valid (Type) ($3.3.4).
26266         */
26267         if (WXS_IS_SIMPLE(inode->typeDef)) {
26268              /*
26269             * SPEC (cvc-type) (3.1)
26270             * "If the type definition is a simple type definition, ..."
26271             * (3.1.3) "If clause 3.2 of Element Locally Valid
26272             * (Element) ($3.3.4) did not apply, then the `normalized value`
26273             * must be `valid` with respect to the type definition as defined
26274             * by String Valid ($3.14.4).
26275             */
26276             ret = xmlSchemaVCheckINodeDataType(vctxt,
26277                     inode, inode->typeDef, inode->value);
26278         } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26279             /*
26280             * SPEC (cvc-type) (3.2) "If the type definition is a complex type
26281             * definition, then the element information item must be
26282             * `valid` with respect to the type definition as per
26283             * Element Locally Valid (Complex Type) ($3.4.4);"
26284             *
26285             * SPEC (cvc-complex-type) (2.2)
26286             * "If the {content type} is a simple type definition, ...
26287             * the `normalized value` of the element information item is
26288             * `valid` with respect to that simple type definition as
26289             * defined by String Valid ($3.14.4)."
26290             */
26291             ret = xmlSchemaVCheckINodeDataType(vctxt,
26292                 inode, inode->typeDef->contentTypeDef, inode->value);
26293         }
26294         if (ret != 0) {
26295             if (ret < 0) {
26296                 VERROR_INT("xmlSchemaValidatorPopElem",
26297                     "calling xmlSchemaVCheckCVCSimpleType()");
26298                 goto internal_error;
26299             }
26300             goto end_elem;
26301         }
26302         /*
26303         * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
26304         * not applied, all of the following must be true:
26305         */
26306         if ((inode->decl->value != NULL) &&
26307             (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
26308
26309             /*
26310             * TODO: We will need a computed value, when comparison is
26311             * done on computed values.
26312             */
26313             /*
26314             * 5.2.2.1 The element information item must have no element
26315             * information item [children].
26316             */
26317             if (inode->flags &
26318                     XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
26319                 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
26320                 VERROR(ret, NULL,
26321                     "The content must not containt element nodes since "
26322                     "there is a fixed value constraint");
26323                 goto end_elem;
26324             } else {
26325                 /*
26326                 * 5.2.2.2 The appropriate case among the following must
26327                 * be true:
26328                 */
26329                 if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
26330                     /*
26331                     * 5.2.2.2.1 If the {content type} of the `actual type
26332                     * definition` is mixed, then the *initial value* of the
26333                     * item must match the canonical lexical representation
26334                     * of the {value constraint} value.
26335                     *
26336                     * ... the *initial value* of an element information
26337                     * item is the string composed of, in order, the
26338                     * [character code] of each character information item in
26339                     * the [children] of that element information item.
26340                     */
26341                     if (! xmlStrEqual(inode->value, inode->decl->value)){
26342                         /*
26343                         * VAL TODO: Report invalid & expected values as well.
26344                         * VAL TODO: Implement the canonical stuff.
26345                         */
26346                         ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
26347                         xmlSchemaCustomErr(ACTXT_CAST vctxt,
26348                             ret, NULL, NULL,
26349                             "The initial value '%s' does not match the fixed "
26350                             "value constraint '%s'",
26351                             inode->value, inode->decl->value);
26352                         goto end_elem;
26353                     }
26354                 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26355                     /*
26356                     * 5.2.2.2.2 If the {content type} of the `actual type
26357                     * definition` is a simple type definition, then the
26358                     * *actual value* of the item must match the canonical
26359                     * lexical representation of the {value constraint} value.
26360                     */
26361                     /*
26362                     * VAL TODO: *actual value* is the normalized value, impl.
26363                     *           this.
26364                     * VAL TODO: Report invalid & expected values as well.
26365                     * VAL TODO: Implement a comparison with the computed values.
26366                     */
26367                     if (! xmlStrEqual(inode->value,
26368                             inode->decl->value)) {
26369                         ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
26370                         xmlSchemaCustomErr(ACTXT_CAST vctxt,
26371                             ret, NULL, NULL,
26372                             "The actual value '%s' does not match the fixed "
26373                             "value constraint '%s'",
26374                             inode->value,
26375                             inode->decl->value);
26376                         goto end_elem;
26377                     }
26378                 }
26379             }
26380         }
26381     }
26382
26383 end_elem:
26384     if (vctxt->depth < 0) {
26385         /* TODO: raise error? */
26386         return (0);
26387     }
26388     if (vctxt->depth == vctxt->skipDepth)
26389         vctxt->skipDepth = -1;
26390     /*
26391     * Evaluate the history of XPath state objects.
26392     */
26393     if (inode->appliedXPath &&
26394         (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
26395         goto internal_error;
26396     /*
26397     * MAYBE TODO:
26398     * SPEC (6) "The element information item must be `valid` with
26399     * respect to each of the {identity-constraint definitions} as per
26400     * Identity-constraint Satisfied ($3.11.4)."
26401     */
26402     /*
26403     * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26404     *   need to be built in any case.
26405     *   We will currently build IDC node-tables and bubble them only if
26406     *   keyrefs do exist.
26407     */
26408
26409     /*
26410     * Add the current IDC target-nodes to the IDC node-tables.
26411     */
26412     if ((inode->idcMatchers != NULL) &&
26413         (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26414     {
26415         if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26416             goto internal_error;
26417     }
26418     /*
26419     * Validate IDC keyrefs.
26420     */
26421     if (vctxt->inode->hasKeyrefs)
26422         if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26423             goto internal_error;
26424     /*
26425     * Merge/free the IDC table.
26426     */
26427     if (inode->idcTable != NULL) {
26428 #ifdef DEBUG_IDC_NODE_TABLE
26429         xmlSchemaDebugDumpIDCTable(stdout,
26430             inode->nsName,
26431             inode->localName,
26432             inode->idcTable);
26433 #endif
26434         if ((vctxt->depth > 0) &&
26435             (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26436         {
26437             /*
26438             * Merge the IDC node table with the table of the parent node.
26439             */
26440             if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26441                 goto internal_error;
26442         }
26443     }
26444     /*
26445     * Clear the current ielem.
26446     * VAL TODO: Don't free the PSVI IDC tables if they are
26447     * requested for the PSVI.
26448     */
26449     xmlSchemaClearElemInfo(vctxt, inode);
26450     /*
26451     * Skip further processing if we are on the validation root.
26452     */
26453     if (vctxt->depth == 0) {
26454         vctxt->depth--;
26455         vctxt->inode = NULL;
26456         return (0);
26457     }
26458     /*
26459     * Reset the keyrefDepth if needed.
26460     */
26461     if (vctxt->aidcs != NULL) {
26462         xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26463         do {
26464             if (aidc->keyrefDepth == vctxt->depth) {
26465                 /*
26466                 * A 'keyrefDepth' of a key/unique IDC matches the current
26467                 * depth, this means that we are leaving the scope of the
26468                 * top-most keyref IDC which refers to this IDC.
26469                 */
26470                 aidc->keyrefDepth = -1;
26471             }
26472             aidc = aidc->next;
26473         } while (aidc != NULL);
26474     }
26475     vctxt->depth--;
26476     vctxt->inode = vctxt->elemInfos[vctxt->depth];
26477     /*
26478     * VAL TODO: 7 If the element information item is the `validation root`, it must be
26479     * `valid` per Validation Root Valid (ID/IDREF) ($3.3.4).
26480     */
26481     return (ret);
26482
26483 internal_error:
26484     vctxt->err = -1;
26485     return (-1);
26486 }
26487
26488 /*
26489 * 3.4.4 Complex Type Definition Validation Rules
26490 * Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26491 */
26492 static int
26493 xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
26494 {
26495     xmlSchemaNodeInfoPtr pielem;
26496     xmlSchemaTypePtr ptype;
26497     int ret = 0;
26498
26499     if (vctxt->depth <= 0) {
26500         VERROR_INT("xmlSchemaValidateChildElem",
26501             "not intended for the validation root");
26502         return (-1);
26503     }
26504     pielem = vctxt->elemInfos[vctxt->depth -1];
26505     if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26506         pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26507     /*
26508     * Handle 'nilled' elements.
26509     */
26510     if (INODE_NILLED(pielem)) {
26511         /*
26512         * SPEC (cvc-elt) (3.3.4) : (3.2.1)
26513         */
26514         ACTIVATE_PARENT_ELEM;
26515         ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26516         VERROR(ret, NULL,
26517             "Neither character nor element content is allowed, "
26518             "because the element was 'nilled'");
26519         ACTIVATE_ELEM;
26520         goto unexpected_elem;
26521     }
26522
26523     ptype = pielem->typeDef;
26524
26525     if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26526         /*
26527         * Workaround for "anyType": we have currently no content model
26528         * assigned for "anyType", so handle it explicitely.
26529         * "anyType" has an unbounded, lax "any" wildcard.
26530         */
26531         vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26532             vctxt->inode->localName,
26533             vctxt->inode->nsName);
26534
26535         if (vctxt->inode->decl == NULL) {
26536             xmlSchemaAttrInfoPtr iattr;
26537             /*
26538             * Process "xsi:type".
26539             * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
26540             */
26541             iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26542                 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26543             if (iattr != NULL) {
26544                 ret = xmlSchemaProcessXSIType(vctxt, iattr,
26545                     &(vctxt->inode->typeDef), NULL);
26546                 if (ret != 0) {
26547                     if (ret == -1) {
26548                         VERROR_INT("xmlSchemaValidateChildElem",
26549                             "calling xmlSchemaProcessXSIType() to "
26550                             "process the attribute 'xsi:nil'");
26551                         return (-1);
26552                     }
26553                     return (ret);
26554                 }
26555             } else {
26556                  /*
26557                  * Fallback to "anyType".
26558                  *
26559                  * SPEC (cvc-assess-elt)
26560                  * "If the item cannot be `strictly assessed`, [...]
26561                  * an element information item's schema validity may be laxly
26562                  * assessed if its `context-determined declaration` is not
26563                  * skip by `validating` with respect to the `ur-type
26564                  * definition` as per Element Locally Valid (Type) ($3.3.4)."
26565                 */
26566                 vctxt->inode->typeDef =
26567                     xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26568             }
26569         }
26570         return (0);
26571     }
26572
26573     switch (ptype->contentType) {
26574         case XML_SCHEMA_CONTENT_EMPTY:
26575             /*
26576             * SPEC (2.1) "If the {content type} is empty, then the
26577             * element information item has no character or element
26578             * information item [children]."
26579             */
26580             ACTIVATE_PARENT_ELEM
26581             ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26582             VERROR(ret, NULL,
26583                 "Element content is not allowed, "
26584                 "because the content type is empty");
26585             ACTIVATE_ELEM
26586             goto unexpected_elem;
26587             break;
26588
26589         case XML_SCHEMA_CONTENT_MIXED:
26590         case XML_SCHEMA_CONTENT_ELEMENTS: {
26591             xmlRegExecCtxtPtr regexCtxt;
26592             xmlChar *values[10];
26593             int terminal, nbval = 10, nbneg;
26594
26595             /* VAL TODO: Optimized "anyType" validation.*/
26596
26597             if (ptype->contModel == NULL) {
26598                 VERROR_INT("xmlSchemaValidateChildElem",
26599                     "type has elem content but no content model");
26600                 return (-1);
26601             }
26602             /*
26603             * Safety belf for evaluation if the cont. model was already
26604             * examined to be invalid.
26605             */
26606             if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26607                 VERROR_INT("xmlSchemaValidateChildElem",
26608                     "validating elem, but elem content is already invalid");
26609                 return (-1);
26610             }
26611
26612             regexCtxt = pielem->regexCtxt;
26613             if (regexCtxt == NULL) {
26614                 /*
26615                 * Create the regex context.
26616                 */
26617                 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26618                     (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26619                     vctxt);
26620                 if (regexCtxt == NULL) {
26621                     VERROR_INT("xmlSchemaValidateChildElem",
26622                         "failed to create a regex context");
26623                     return (-1);
26624                 }
26625                 pielem->regexCtxt = regexCtxt;
26626 #ifdef DEBUG_AUTOMATA
26627                 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26628                     pielem->localName);
26629 #endif
26630             }
26631
26632             /*
26633             * SPEC (2.4) "If the {content type} is element-only or mixed,
26634             * then the sequence of the element information item's
26635             * element information item [children], if any, taken in
26636             * order, is `valid` with respect to the {content type}'s
26637             * particle, as defined in Element Sequence Locally Valid
26638             * (Particle) ($3.9.4)."
26639             */
26640             ret = xmlRegExecPushString2(regexCtxt,
26641                 vctxt->inode->localName,
26642                 vctxt->inode->nsName,
26643                 vctxt->inode);
26644 #ifdef DEBUG_AUTOMATA
26645             if (ret < 0)
26646                 xmlGenericError(xmlGenericErrorContext,
26647                 "AUTOMATON push ERROR for '%s' on '%s'\n",
26648                 vctxt->inode->localName, pielem->localName);
26649             else
26650                 xmlGenericError(xmlGenericErrorContext,
26651                 "AUTOMATON push OK for '%s' on '%s'\n",
26652                 vctxt->inode->localName, pielem->localName);
26653 #endif
26654             if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26655                 VERROR_INT("xmlSchemaValidateChildElem",
26656                     "calling xmlRegExecPushString2()");
26657                 return (-1);
26658             }
26659             if (ret < 0) {
26660                 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26661                     &values[0], &terminal);
26662                 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26663                     XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26664                     "This element is not expected",
26665                     nbval, nbneg, values);
26666                 ret = vctxt->err;
26667                 goto unexpected_elem;
26668             } else
26669                 ret = 0;
26670         }
26671             break;
26672         case XML_SCHEMA_CONTENT_SIMPLE:
26673         case XML_SCHEMA_CONTENT_BASIC:
26674             ACTIVATE_PARENT_ELEM
26675             if (WXS_IS_COMPLEX(ptype)) {
26676                 /*
26677                 * SPEC (cvc-complex-type) (2.2)
26678                 * "If the {content type} is a simple type definition, then
26679                 * the element information item has no element information
26680                 * item [children], ..."
26681                 */
26682                 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26683                 VERROR(ret, NULL, "Element content is not allowed, "
26684                     "because the content type is a simple type definition");
26685             } else {
26686                 /*
26687                 * SPEC (cvc-type) (3.1.2) "The element information item must
26688                 * have no element information item [children]."
26689                 */
26690                 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26691                 VERROR(ret, NULL, "Element content is not allowed, "
26692                     "because the type definition is simple");
26693             }
26694             ACTIVATE_ELEM
26695             ret = vctxt->err;
26696             goto unexpected_elem;
26697             break;
26698
26699         default:
26700             break;
26701     }
26702     return (ret);
26703 unexpected_elem:
26704     /*
26705     * Pop this element and set the skipDepth to skip
26706     * all further content of the parent element.
26707     */
26708     vctxt->skipDepth = vctxt->depth;
26709     vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26710     pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26711     return (ret);
26712 }
26713
26714 #define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26715 #define XML_SCHEMA_PUSH_TEXT_CREATED 2
26716 #define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26717
26718 static int
26719 xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26720                   int nodeType, const xmlChar *value, int len,
26721                   int mode, int *consumed)
26722 {
26723     /*
26724     * Unfortunately we have to duplicate the text sometimes.
26725     * OPTIMIZE: Maybe we could skip it, if:
26726     *   1. content type is simple
26727     *   2. whitespace is "collapse"
26728     *   3. it consists of whitespace only
26729     *
26730     * Process character content.
26731     */
26732     if (consumed != NULL)
26733         *consumed = 0;
26734     if (INODE_NILLED(vctxt->inode)) {
26735         /*
26736         * SPEC cvc-elt (3.3.4 - 3.2.1)
26737         * "The element information item must have no character or
26738         * element information item [children]."
26739         */
26740         VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26741             "Neither character nor element content is allowed "
26742             "because the element is 'nilled'");
26743         return (vctxt->err);
26744     }
26745     /*
26746     * SPEC (2.1) "If the {content type} is empty, then the
26747     * element information item has no character or element
26748     * information item [children]."
26749     */
26750     if (vctxt->inode->typeDef->contentType ==
26751             XML_SCHEMA_CONTENT_EMPTY) {
26752         VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26753             "Character content is not allowed, "
26754             "because the content type is empty");
26755         return (vctxt->err);
26756     }
26757
26758     if (vctxt->inode->typeDef->contentType ==
26759             XML_SCHEMA_CONTENT_ELEMENTS) {
26760         if ((nodeType != XML_TEXT_NODE) ||
26761             (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26762             /*
26763             * SPEC cvc-complex-type (2.3)
26764             * "If the {content type} is element-only, then the
26765             * element information item has no character information
26766             * item [children] other than those whose [character
26767             * code] is defined as a white space in [XML 1.0 (Second
26768             * Edition)]."
26769             */
26770             VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26771                 "Character content other than whitespace is not allowed "
26772                 "because the content type is 'element-only'");
26773             return (vctxt->err);
26774         }
26775         return (0);
26776     }
26777
26778     if ((value == NULL) || (value[0] == 0))
26779         return (0);
26780     /*
26781     * Save the value.
26782     * NOTE that even if the content type is *mixed*, we need the
26783     * *initial value* for default/fixed value constraints.
26784     */
26785     if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26786         ((vctxt->inode->decl == NULL) ||
26787         (vctxt->inode->decl->value == NULL)))
26788         return (0);
26789
26790     if (vctxt->inode->value == NULL) {
26791         /*
26792         * Set the value.
26793         */
26794         switch (mode) {
26795             case XML_SCHEMA_PUSH_TEXT_PERSIST:
26796                 /*
26797                 * When working on a tree.
26798                 */
26799                 vctxt->inode->value = value;
26800                 break;
26801             case XML_SCHEMA_PUSH_TEXT_CREATED:
26802                 /*
26803                 * When working with the reader.
26804                 * The value will be freed by the element info.
26805                 */
26806                 vctxt->inode->value = value;
26807                 if (consumed != NULL)
26808                     *consumed = 1;
26809                 vctxt->inode->flags |=
26810                     XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26811                 break;
26812             case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26813                 /*
26814                 * When working with SAX.
26815                 * The value will be freed by the element info.
26816                 */
26817                 if (len != -1)
26818                     vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26819                 else
26820                     vctxt->inode->value = BAD_CAST xmlStrdup(value);
26821                 vctxt->inode->flags |=
26822                     XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26823                 break;
26824             default:
26825                 break;
26826         }
26827     } else {
26828         if (len < 0)
26829             len = xmlStrlen(value);
26830         /*
26831         * Concat the value.
26832         */
26833         if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
26834             vctxt->inode->value = BAD_CAST xmlStrncat(
26835                 (xmlChar *) vctxt->inode->value, value, len);
26836         } else {
26837             vctxt->inode->value =
26838                 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
26839             vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26840         }
26841     }
26842
26843     return (0);
26844 }
26845
26846 static int
26847 xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
26848 {
26849     int ret = 0;
26850
26851     if ((vctxt->skipDepth != -1) &&
26852         (vctxt->depth >= vctxt->skipDepth)) {
26853         VERROR_INT("xmlSchemaValidateElem",
26854             "in skip-state");
26855         goto internal_error;
26856     }
26857     if (vctxt->xsiAssemble) {
26858         /*
26859         * We will stop validation if there was an error during
26860         * dynamic schema construction.
26861         * Note that we simply set @skipDepth to 0, this could
26862         * mean that a streaming document via SAX would be
26863         * still read to the end but it won't be validated any more.
26864         * TODO: If we are sure how to stop the validation at once
26865         *   for all input scenarios, then this should be changed to
26866         *   instantly stop the validation.
26867         */
26868         ret = xmlSchemaAssembleByXSI(vctxt);
26869         if (ret != 0) {
26870             if (ret == -1)
26871                 goto internal_error;
26872             vctxt->skipDepth = 0;
26873             return(ret);
26874         }
26875         /*
26876          * Augment the IDC definitions for the main schema and all imported ones
26877          * NOTE: main schema is the first in the imported list
26878          */
26879         xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt);
26880     }
26881     if (vctxt->depth > 0) {
26882         /*
26883         * Validate this element against the content model
26884         * of the parent.
26885         */
26886         ret = xmlSchemaValidateChildElem(vctxt);
26887         if (ret != 0) {
26888             if (ret < 0) {
26889                 VERROR_INT("xmlSchemaValidateElem",
26890                     "calling xmlSchemaStreamValidateChildElement()");
26891                 goto internal_error;
26892             }
26893             goto exit;
26894         }
26895         if (vctxt->depth == vctxt->skipDepth)
26896             goto exit;
26897         if ((vctxt->inode->decl == NULL) &&
26898             (vctxt->inode->typeDef == NULL)) {
26899             VERROR_INT("xmlSchemaValidateElem",
26900                 "the child element was valid but neither the "
26901                 "declaration nor the type was set");
26902             goto internal_error;
26903         }
26904     } else {
26905         /*
26906         * Get the declaration of the validation root.
26907         */
26908         vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26909             vctxt->inode->localName,
26910             vctxt->inode->nsName);
26911         if (vctxt->inode->decl == NULL) {
26912             ret = XML_SCHEMAV_CVC_ELT_1;
26913             VERROR(ret, NULL,
26914                 "No matching global declaration available "
26915                 "for the validation root");
26916             goto exit;
26917         }
26918     }
26919
26920     if (vctxt->inode->decl == NULL)
26921         goto type_validation;
26922
26923     if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26924         int skip;
26925         /*
26926         * Wildcards.
26927         */
26928         ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26929         if (ret != 0) {
26930             if (ret < 0) {
26931                 VERROR_INT("xmlSchemaValidateElem",
26932                     "calling xmlSchemaValidateElemWildcard()");
26933                 goto internal_error;
26934             }
26935             goto exit;
26936         }
26937         if (skip) {
26938             vctxt->skipDepth = vctxt->depth;
26939             goto exit;
26940         }
26941         /*
26942         * The declaration might be set by the wildcard validation,
26943         * when the processContents is "lax" or "strict".
26944         */
26945         if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26946             /*
26947             * Clear the "decl" field to not confuse further processing.
26948             */
26949             vctxt->inode->decl = NULL;
26950             goto type_validation;
26951         }
26952     }
26953     /*
26954     * Validate against the declaration.
26955     */
26956     ret = xmlSchemaValidateElemDecl(vctxt);
26957     if (ret != 0) {
26958         if (ret < 0) {
26959             VERROR_INT("xmlSchemaValidateElem",
26960                 "calling xmlSchemaValidateElemDecl()");
26961             goto internal_error;
26962         }
26963         goto exit;
26964     }
26965     /*
26966     * Validate against the type definition.
26967     */
26968 type_validation:
26969
26970     if (vctxt->inode->typeDef == NULL) {
26971         vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26972         ret = XML_SCHEMAV_CVC_TYPE_1;
26973         VERROR(ret, NULL,
26974             "The type definition is absent");
26975         goto exit;
26976     }
26977     if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26978         vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26979         ret = XML_SCHEMAV_CVC_TYPE_2;
26980             VERROR(ret, NULL,
26981             "The type definition is abstract");
26982         goto exit;
26983     }
26984     /*
26985     * Evaluate IDCs. Do it here, since new IDC matchers are registered
26986     * during validation against the declaration. This must be done
26987     * _before_ attribute validation.
26988     */
26989     if (vctxt->xpathStates != NULL) {
26990         ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
26991         vctxt->inode->appliedXPath = 1;
26992         if (ret == -1) {
26993             VERROR_INT("xmlSchemaValidateElem",
26994                 "calling xmlSchemaXPathEvaluate()");
26995             goto internal_error;
26996         }
26997     }
26998     /*
26999     * Validate attributes.
27000     */
27001     if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
27002         if ((vctxt->nbAttrInfos != 0) ||
27003             (vctxt->inode->typeDef->attrUses != NULL)) {
27004
27005             ret = xmlSchemaVAttributesComplex(vctxt);
27006         }
27007     } else if (vctxt->nbAttrInfos != 0) {
27008
27009         ret = xmlSchemaVAttributesSimple(vctxt);
27010     }
27011     /*
27012     * Clear registered attributes.
27013     */
27014     if (vctxt->nbAttrInfos != 0)
27015         xmlSchemaClearAttrInfos(vctxt);
27016     if (ret == -1) {
27017         VERROR_INT("xmlSchemaValidateElem",
27018             "calling attributes validation");
27019         goto internal_error;
27020     }
27021     /*
27022     * Don't return an error if attributes are invalid on purpose.
27023     */
27024     ret = 0;
27025
27026 exit:
27027     if (ret != 0)
27028         vctxt->skipDepth = vctxt->depth;
27029     return (ret);
27030 internal_error:
27031     return (-1);
27032 }
27033
27034 #ifdef XML_SCHEMA_READER_ENABLED
27035 static int
27036 xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
27037 {
27038     const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
27039     int depth, nodeType, ret = 0, consumed;
27040     xmlSchemaNodeInfoPtr ielem;
27041
27042     vctxt->depth = -1;
27043     ret = xmlTextReaderRead(vctxt->reader);
27044     /*
27045     * Move to the document element.
27046     */
27047     while (ret == 1) {
27048         nodeType = xmlTextReaderNodeType(vctxt->reader);
27049         if (nodeType == XML_ELEMENT_NODE)
27050             goto root_found;
27051         ret = xmlTextReaderRead(vctxt->reader);
27052     }
27053     goto exit;
27054
27055 root_found:
27056
27057     do {
27058         depth = xmlTextReaderDepth(vctxt->reader);
27059         nodeType = xmlTextReaderNodeType(vctxt->reader);
27060
27061         if (nodeType == XML_ELEMENT_NODE) {
27062
27063             vctxt->depth++;
27064             if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27065                 VERROR_INT("xmlSchemaVReaderWalk",
27066                     "calling xmlSchemaValidatorPushElem()");
27067                 goto internal_error;
27068             }
27069             ielem = vctxt->inode;
27070             ielem->localName = xmlTextReaderLocalName(vctxt->reader);
27071             ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
27072             ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
27073             /*
27074             * Is the element empty?
27075             */
27076             ret = xmlTextReaderIsEmptyElement(vctxt->reader);
27077             if (ret == -1) {
27078                 VERROR_INT("xmlSchemaVReaderWalk",
27079                     "calling xmlTextReaderIsEmptyElement()");
27080                 goto internal_error;
27081             }
27082             if (ret) {
27083                 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27084             }
27085             /*
27086             * Register attributes.
27087             */
27088             vctxt->nbAttrInfos = 0;
27089             ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
27090             if (ret == -1) {
27091                 VERROR_INT("xmlSchemaVReaderWalk",
27092                     "calling xmlTextReaderMoveToFirstAttribute()");
27093                 goto internal_error;
27094             }
27095             if (ret == 1) {
27096                 do {
27097                     /*
27098                     * VAL TODO: How do we know that the reader works on a
27099                     * node tree, to be able to pass a node here?
27100                     */
27101                     if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
27102                         (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
27103                         xmlTextReaderNamespaceUri(vctxt->reader), 1,
27104                         xmlTextReaderValue(vctxt->reader), 1) == -1) {
27105
27106                         VERROR_INT("xmlSchemaVReaderWalk",
27107                             "calling xmlSchemaValidatorPushAttribute()");
27108                         goto internal_error;
27109                     }
27110                     ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
27111                     if (ret == -1) {
27112                         VERROR_INT("xmlSchemaVReaderWalk",
27113                             "calling xmlTextReaderMoveToFirstAttribute()");
27114                         goto internal_error;
27115                     }
27116                 } while (ret == 1);
27117                 /*
27118                 * Back to element position.
27119                 */
27120                 ret = xmlTextReaderMoveToElement(vctxt->reader);
27121                 if (ret == -1) {
27122                     VERROR_INT("xmlSchemaVReaderWalk",
27123                         "calling xmlTextReaderMoveToElement()");
27124                     goto internal_error;
27125                 }
27126             }
27127             /*
27128             * Validate the element.
27129             */
27130             ret= xmlSchemaValidateElem(vctxt);
27131             if (ret != 0) {
27132                 if (ret == -1) {
27133                     VERROR_INT("xmlSchemaVReaderWalk",
27134                         "calling xmlSchemaValidateElem()");
27135                     goto internal_error;
27136                 }
27137                 goto exit;
27138             }
27139             if (vctxt->depth == vctxt->skipDepth) {
27140                 int curDepth;
27141                 /*
27142                 * Skip all content.
27143                 */
27144                 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
27145                     ret = xmlTextReaderRead(vctxt->reader);
27146                     curDepth = xmlTextReaderDepth(vctxt->reader);
27147                     while ((ret == 1) && (curDepth != depth)) {
27148                         ret = xmlTextReaderRead(vctxt->reader);
27149                         curDepth = xmlTextReaderDepth(vctxt->reader);
27150                     }
27151                     if (ret < 0) {
27152                         /*
27153                         * VAL TODO: A reader error occured; what to do here?
27154                         */
27155                         ret = 1;
27156                         goto exit;
27157                     }
27158                 }
27159                 goto leave_elem;
27160             }
27161             /*
27162             * READER VAL TODO: Is an END_ELEM really never called
27163             * if the elem is empty?
27164             */
27165             if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27166                 goto leave_elem;
27167         } else if (nodeType == END_ELEM) {
27168             /*
27169             * Process END of element.
27170             */
27171 leave_elem:
27172             ret = xmlSchemaValidatorPopElem(vctxt);
27173             if (ret != 0) {
27174                 if (ret < 0) {
27175                     VERROR_INT("xmlSchemaVReaderWalk",
27176                         "calling xmlSchemaValidatorPopElem()");
27177                     goto internal_error;
27178                 }
27179                 goto exit;
27180             }
27181             if (vctxt->depth >= 0)
27182                 ielem = vctxt->inode;
27183             else
27184                 ielem = NULL;
27185         } else if ((nodeType == XML_TEXT_NODE) ||
27186             (nodeType == XML_CDATA_SECTION_NODE) ||
27187             (nodeType == WHTSP) ||
27188             (nodeType == SIGN_WHTSP)) {
27189             /*
27190             * Process character content.
27191             */
27192             xmlChar *value;
27193
27194             if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
27195                 nodeType = XML_TEXT_NODE;
27196
27197             value = xmlTextReaderValue(vctxt->reader);
27198             ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
27199                 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
27200             if (! consumed)
27201                 xmlFree(value);
27202             if (ret == -1) {
27203                 VERROR_INT("xmlSchemaVReaderWalk",
27204                     "calling xmlSchemaVPushText()");
27205                 goto internal_error;
27206             }
27207         } else if ((nodeType == XML_ENTITY_NODE) ||
27208             (nodeType == XML_ENTITY_REF_NODE)) {
27209             /*
27210             * VAL TODO: What to do with entities?
27211             */
27212             TODO
27213         }
27214         /*
27215         * Read next node.
27216         */
27217         ret = xmlTextReaderRead(vctxt->reader);
27218     } while (ret == 1);
27219
27220 exit:
27221     return (ret);
27222 internal_error:
27223     return (-1);
27224 }
27225 #endif
27226
27227 /************************************************************************
27228  *                                                                      *
27229  *                      SAX validation handlers                         *
27230  *                                                                      *
27231  ************************************************************************/
27232
27233 /*
27234 * Process text content.
27235 */
27236 static void
27237 xmlSchemaSAXHandleText(void *ctx,
27238                        const xmlChar * ch,
27239                        int len)
27240 {
27241     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27242
27243     if (vctxt->depth < 0)
27244         return;
27245     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27246         return;
27247     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27248         vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27249     if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
27250         XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27251         VERROR_INT("xmlSchemaSAXHandleCDataSection",
27252             "calling xmlSchemaVPushText()");
27253         vctxt->err = -1;
27254         xmlStopParser(vctxt->parserCtxt);
27255     }
27256 }
27257
27258 /*
27259 * Process CDATA content.
27260 */
27261 static void
27262 xmlSchemaSAXHandleCDataSection(void *ctx,
27263                              const xmlChar * ch,
27264                              int len)
27265 {
27266     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27267
27268     if (vctxt->depth < 0)
27269         return;
27270     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27271         return;
27272     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27273         vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27274     if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
27275         XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27276         VERROR_INT("xmlSchemaSAXHandleCDataSection",
27277             "calling xmlSchemaVPushText()");
27278         vctxt->err = -1;
27279         xmlStopParser(vctxt->parserCtxt);
27280     }
27281 }
27282
27283 static void
27284 xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
27285                             const xmlChar * name ATTRIBUTE_UNUSED)
27286 {
27287     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27288
27289     if (vctxt->depth < 0)
27290         return;
27291     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27292         return;
27293     /* SAX VAL TODO: What to do here? */
27294     TODO
27295 }
27296
27297 static void
27298 xmlSchemaSAXHandleStartElementNs(void *ctx,
27299                                  const xmlChar * localname,
27300                                  const xmlChar * prefix ATTRIBUTE_UNUSED,
27301                                  const xmlChar * URI,
27302                                  int nb_namespaces,
27303                                  const xmlChar ** namespaces,
27304                                  int nb_attributes,
27305                                  int nb_defaulted ATTRIBUTE_UNUSED,
27306                                  const xmlChar ** attributes)
27307 {
27308     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27309     int ret;
27310     xmlSchemaNodeInfoPtr ielem;
27311     int i, j;
27312
27313     /*
27314     * SAX VAL TODO: What to do with nb_defaulted?
27315     */
27316     /*
27317     * Skip elements if inside a "skip" wildcard or invalid.
27318     */
27319     vctxt->depth++;
27320     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27321         return;
27322     /*
27323     * Push the element.
27324     */
27325     if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27326         VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27327             "calling xmlSchemaValidatorPushElem()");
27328         goto internal_error;
27329     }
27330     ielem = vctxt->inode;
27331     /*
27332     * TODO: Is this OK?
27333     */
27334     ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
27335     ielem->localName = localname;
27336     ielem->nsName = URI;
27337     ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27338     /*
27339     * Register namespaces on the elem info.
27340     */
27341     if (nb_namespaces != 0) {
27342         /*
27343         * Although the parser builds its own namespace list,
27344         * we have no access to it, so we'll use an own one.
27345         */
27346         for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
27347             /*
27348             * Store prefix and namespace name.
27349             */
27350             if (ielem->nsBindings == NULL) {
27351                 ielem->nsBindings =
27352                     (const xmlChar **) xmlMalloc(10 *
27353                         sizeof(const xmlChar *));
27354                 if (ielem->nsBindings == NULL) {
27355                     xmlSchemaVErrMemory(vctxt,
27356                         "allocating namespace bindings for SAX validation",
27357                         NULL);
27358                     goto internal_error;
27359                 }
27360                 ielem->nbNsBindings = 0;
27361                 ielem->sizeNsBindings = 5;
27362             } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
27363                 ielem->sizeNsBindings *= 2;
27364                 ielem->nsBindings =
27365                     (const xmlChar **) xmlRealloc(
27366                         (void *) ielem->nsBindings,
27367                         ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
27368                 if (ielem->nsBindings == NULL) {
27369                     xmlSchemaVErrMemory(vctxt,
27370                         "re-allocating namespace bindings for SAX validation",
27371                         NULL);
27372                     goto internal_error;
27373                 }
27374             }
27375
27376             ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
27377             if (namespaces[j+1][0] == 0) {
27378                 /*
27379                 * Handle xmlns="".
27380                 */
27381                 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
27382             } else
27383                 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
27384                     namespaces[j+1];
27385             ielem->nbNsBindings++;
27386         }
27387     }
27388     /*
27389     * Register attributes.
27390     * SAX VAL TODO: We are not adding namespace declaration
27391     * attributes yet.
27392     */
27393     if (nb_attributes != 0) {
27394         xmlChar *value;
27395
27396         for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27397             /*
27398             * Duplicate the value, changing any &#38; to a literal ampersand.
27399             *
27400             * libxml2 differs from normal SAX here in that it escapes all ampersands
27401             * as &#38; instead of delivering the raw converted string. Changing the
27402             * behavior at this point would break applications that use this API, so
27403             * we are forced to work around it. There is no danger of accidentally
27404             * decoding some entity other than &#38; in this step because without
27405             * unescaped ampersands there can be no other entities in the string.
27406             */
27407             value = xmlStringLenDecodeEntities(vctxt->parserCtxt, attributes[j+3],
27408                 attributes[j+4] - attributes[j+3], XML_SUBSTITUTE_REF, 0, 0, 0);
27409             /*
27410             * TODO: Set the node line.
27411             */
27412             ret = xmlSchemaValidatorPushAttribute(vctxt,
27413                 NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
27414                 value, 1);
27415             if (ret == -1) {
27416                 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27417                     "calling xmlSchemaValidatorPushAttribute()");
27418                 goto internal_error;
27419             }
27420         }
27421     }
27422     /*
27423     * Validate the element.
27424     */
27425     ret = xmlSchemaValidateElem(vctxt);
27426     if (ret != 0) {
27427         if (ret == -1) {
27428             VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27429                 "calling xmlSchemaValidateElem()");
27430             goto internal_error;
27431         }
27432         goto exit;
27433     }
27434
27435 exit:
27436     return;
27437 internal_error:
27438     vctxt->err = -1;
27439     xmlStopParser(vctxt->parserCtxt);
27440     return;
27441 }
27442
27443 static void
27444 xmlSchemaSAXHandleEndElementNs(void *ctx,
27445                                const xmlChar * localname ATTRIBUTE_UNUSED,
27446                                const xmlChar * prefix ATTRIBUTE_UNUSED,
27447                                const xmlChar * URI ATTRIBUTE_UNUSED)
27448 {
27449     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27450     int res;
27451
27452     /*
27453     * Skip elements if inside a "skip" wildcard or if invalid.
27454     */
27455     if (vctxt->skipDepth != -1) {
27456         if (vctxt->depth > vctxt->skipDepth) {
27457             vctxt->depth--;
27458             return;
27459         } else
27460             vctxt->skipDepth = -1;
27461     }
27462     /*
27463     * SAX VAL TODO: Just a temporary check.
27464     */
27465     if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27466         (!xmlStrEqual(vctxt->inode->nsName, URI))) {
27467         VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27468             "elem pop mismatch");
27469     }
27470     res = xmlSchemaValidatorPopElem(vctxt);
27471     if (res != 0) {
27472         if (res < 0) {
27473             VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27474                 "calling xmlSchemaValidatorPopElem()");
27475             goto internal_error;
27476         }
27477         goto exit;
27478     }
27479 exit:
27480     return;
27481 internal_error:
27482     vctxt->err = -1;
27483     xmlStopParser(vctxt->parserCtxt);
27484     return;
27485 }
27486
27487 /************************************************************************
27488  *                                                                      *
27489  *                      Validation interfaces                           *
27490  *                                                                      *
27491  ************************************************************************/
27492
27493 /**
27494  * xmlSchemaNewValidCtxt:
27495  * @schema:  a precompiled XML Schemas
27496  *
27497  * Create an XML Schemas validation context based on the given schema.
27498  *
27499  * Returns the validation context or NULL in case of error
27500  */
27501 xmlSchemaValidCtxtPtr
27502 xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27503 {
27504     xmlSchemaValidCtxtPtr ret;
27505
27506     ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27507     if (ret == NULL) {
27508         xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
27509         return (NULL);
27510     }
27511     memset(ret, 0, sizeof(xmlSchemaValidCtxt));
27512     ret->type = XML_SCHEMA_CTXT_VALIDATOR;
27513     ret->dict = xmlDictCreate();
27514     ret->nodeQNames = xmlSchemaItemListCreate();
27515     ret->schema = schema;
27516     return (ret);
27517 }
27518
27519 /**
27520  * xmlSchemaValidateSetFilename:
27521  * @vctxt: the schema validation context
27522  * @filename: the file name
27523  *
27524  * Workaround to provide file error reporting information when this is
27525  * not provided by current APIs
27526  */
27527 void
27528 xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt, const char *filename) {
27529     if (vctxt == NULL)
27530         return;
27531     if (vctxt->filename != NULL)
27532         xmlFree(vctxt->filename);
27533     if (filename != NULL)
27534         vctxt->filename = (char *) xmlStrdup((const xmlChar *) filename);
27535     else
27536         vctxt->filename = NULL;
27537 }
27538
27539 /**
27540  * xmlSchemaClearValidCtxt:
27541  * @vctxt: the schema validation context
27542  *
27543  * Free the resources associated to the schema validation context;
27544  * leaves some fields alive intended for reuse of the context.
27545  */
27546 static void
27547 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27548 {
27549     if (vctxt == NULL)
27550         return;
27551
27552     /*
27553     * TODO: Should we clear the flags?
27554     *   Might be problematic if one reuses the context
27555     *   and assumes that the options remain the same.
27556     */
27557     vctxt->flags = 0;
27558     vctxt->validationRoot = NULL;
27559     vctxt->doc = NULL;
27560 #ifdef LIBXML_READER_ENABLED
27561     vctxt->reader = NULL;
27562 #endif
27563     vctxt->hasKeyrefs = 0;
27564
27565     if (vctxt->value != NULL) {
27566         xmlSchemaFreeValue(vctxt->value);
27567         vctxt->value = NULL;
27568     }
27569     /*
27570     * Augmented IDC information.
27571     */
27572     if (vctxt->aidcs != NULL) {
27573         xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27574         do {
27575             next = cur->next;
27576             xmlFree(cur);
27577             cur = next;
27578         } while (cur != NULL);
27579         vctxt->aidcs = NULL;
27580     }
27581     if (vctxt->idcMatcherCache != NULL) {
27582         xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp;
27583
27584         while (matcher) {
27585             tmp = matcher;
27586             matcher = matcher->nextCached;
27587             xmlSchemaIDCFreeMatcherList(tmp);
27588         }
27589         vctxt->idcMatcherCache = NULL;
27590     }
27591
27592
27593     if (vctxt->idcNodes != NULL) {
27594         int i;
27595         xmlSchemaPSVIIDCNodePtr item;
27596
27597         for (i = 0; i < vctxt->nbIdcNodes; i++) {
27598             item = vctxt->idcNodes[i];
27599             xmlFree(item->keys);
27600             xmlFree(item);
27601         }
27602         xmlFree(vctxt->idcNodes);
27603         vctxt->idcNodes = NULL;
27604         vctxt->nbIdcNodes = 0;
27605         vctxt->sizeIdcNodes = 0;
27606     }
27607     /*
27608     * Note that we won't delete the XPath state pool here.
27609     */
27610     if (vctxt->xpathStates != NULL) {
27611         xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27612         vctxt->xpathStates = NULL;
27613     }
27614     /*
27615     * Attribute info.
27616     */
27617     if (vctxt->nbAttrInfos != 0) {
27618         xmlSchemaClearAttrInfos(vctxt);
27619     }
27620     /*
27621     * Element info.
27622     */
27623     if (vctxt->elemInfos != NULL) {
27624         int i;
27625         xmlSchemaNodeInfoPtr ei;
27626
27627         for (i = 0; i < vctxt->sizeElemInfos; i++) {
27628             ei = vctxt->elemInfos[i];
27629             if (ei == NULL)
27630                 break;
27631             xmlSchemaClearElemInfo(vctxt, ei);
27632         }
27633     }
27634     xmlSchemaItemListClear(vctxt->nodeQNames);
27635     /* Recreate the dict. */
27636     xmlDictFree(vctxt->dict);
27637     /*
27638     * TODO: Is is save to recreate it? Do we have a scenario
27639     * where the user provides the dict?
27640     */
27641     vctxt->dict = xmlDictCreate();
27642
27643     if (vctxt->filename != NULL) {
27644         xmlFree(vctxt->filename);
27645         vctxt->filename = NULL;
27646     }
27647 }
27648
27649 /**
27650  * xmlSchemaFreeValidCtxt:
27651  * @ctxt:  the schema validation context
27652  *
27653  * Free the resources associated to the schema validation context
27654  */
27655 void
27656 xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27657 {
27658     if (ctxt == NULL)
27659         return;
27660     if (ctxt->value != NULL)
27661         xmlSchemaFreeValue(ctxt->value);
27662     if (ctxt->pctxt != NULL)
27663         xmlSchemaFreeParserCtxt(ctxt->pctxt);
27664     if (ctxt->idcNodes != NULL) {
27665         int i;
27666         xmlSchemaPSVIIDCNodePtr item;
27667
27668         for (i = 0; i < ctxt->nbIdcNodes; i++) {
27669             item = ctxt->idcNodes[i];
27670             xmlFree(item->keys);
27671             xmlFree(item);
27672         }
27673         xmlFree(ctxt->idcNodes);
27674     }
27675     if (ctxt->idcKeys != NULL) {
27676         int i;
27677         for (i = 0; i < ctxt->nbIdcKeys; i++)
27678             xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27679         xmlFree(ctxt->idcKeys);
27680     }
27681
27682     if (ctxt->xpathStates != NULL) {
27683         xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27684         ctxt->xpathStates = NULL;
27685     }
27686     if (ctxt->xpathStatePool != NULL) {
27687         xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27688         ctxt->xpathStatePool = NULL;
27689     }
27690
27691     /*
27692     * Augmented IDC information.
27693     */
27694     if (ctxt->aidcs != NULL) {
27695         xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27696         do {
27697             next = cur->next;
27698             xmlFree(cur);
27699             cur = next;
27700         } while (cur != NULL);
27701     }
27702     if (ctxt->attrInfos != NULL) {
27703         int i;
27704         xmlSchemaAttrInfoPtr attr;
27705
27706         /* Just a paranoid call to the cleanup. */
27707         if (ctxt->nbAttrInfos != 0)
27708             xmlSchemaClearAttrInfos(ctxt);
27709         for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27710             attr = ctxt->attrInfos[i];
27711             xmlFree(attr);
27712         }
27713         xmlFree(ctxt->attrInfos);
27714     }
27715     if (ctxt->elemInfos != NULL) {
27716         int i;
27717         xmlSchemaNodeInfoPtr ei;
27718
27719         for (i = 0; i < ctxt->sizeElemInfos; i++) {
27720             ei = ctxt->elemInfos[i];
27721             if (ei == NULL)
27722                 break;
27723             xmlSchemaClearElemInfo(ctxt, ei);
27724             xmlFree(ei);
27725         }
27726         xmlFree(ctxt->elemInfos);
27727     }
27728     if (ctxt->nodeQNames != NULL)
27729         xmlSchemaItemListFree(ctxt->nodeQNames);
27730     if (ctxt->dict != NULL)
27731         xmlDictFree(ctxt->dict);
27732     if (ctxt->filename != NULL)
27733         xmlFree(ctxt->filename);
27734     xmlFree(ctxt);
27735 }
27736
27737 /**
27738  * xmlSchemaIsValid:
27739  * @ctxt: the schema validation context
27740  *
27741  * Check if any error was detected during validation.
27742  *
27743  * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27744  *         of internal error.
27745  */
27746 int
27747 xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27748 {
27749     if (ctxt == NULL)
27750         return(-1);
27751     return(ctxt->err == 0);
27752 }
27753
27754 /**
27755  * xmlSchemaSetValidErrors:
27756  * @ctxt:  a schema validation context
27757  * @err:  the error function
27758  * @warn: the warning function
27759  * @ctx: the functions context
27760  *
27761  * Set the error and warning callback informations
27762  */
27763 void
27764 xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27765                         xmlSchemaValidityErrorFunc err,
27766                         xmlSchemaValidityWarningFunc warn, void *ctx)
27767 {
27768     if (ctxt == NULL)
27769         return;
27770     ctxt->error = err;
27771     ctxt->warning = warn;
27772     ctxt->errCtxt = ctx;
27773     if (ctxt->pctxt != NULL)
27774         xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
27775 }
27776
27777 /**
27778  * xmlSchemaSetValidStructuredErrors:
27779  * @ctxt:  a schema validation context
27780  * @serror:  the structured error function
27781  * @ctx: the functions context
27782  *
27783  * Set the structured error callback
27784  */
27785 void
27786 xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
27787                                   xmlStructuredErrorFunc serror, void *ctx)
27788 {
27789     if (ctxt == NULL)
27790         return;
27791         ctxt->serror = serror;
27792     ctxt->error = NULL;
27793     ctxt->warning = NULL;
27794     ctxt->errCtxt = ctx;
27795     if (ctxt->pctxt != NULL)
27796         xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
27797 }
27798
27799 /**
27800  * xmlSchemaGetValidErrors:
27801  * @ctxt: a XML-Schema validation context
27802  * @err: the error function result
27803  * @warn: the warning function result
27804  * @ctx: the functions context result
27805  *
27806  * Get the error and warning callback informations
27807  *
27808  * Returns -1 in case of error and 0 otherwise
27809  */
27810 int
27811 xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27812                         xmlSchemaValidityErrorFunc * err,
27813                         xmlSchemaValidityWarningFunc * warn, void **ctx)
27814 {
27815         if (ctxt == NULL)
27816                 return (-1);
27817         if (err != NULL)
27818                 *err = ctxt->error;
27819         if (warn != NULL)
27820                 *warn = ctxt->warning;
27821         if (ctx != NULL)
27822                 *ctx = ctxt->errCtxt;
27823         return (0);
27824 }
27825
27826
27827 /**
27828  * xmlSchemaSetValidOptions:
27829  * @ctxt:       a schema validation context
27830  * @options: a combination of xmlSchemaValidOption
27831  *
27832  * Sets the options to be used during the validation.
27833  *
27834  * Returns 0 in case of success, -1 in case of an
27835  * API error.
27836  */
27837 int
27838 xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27839                          int options)
27840
27841 {
27842     int i;
27843
27844     if (ctxt == NULL)
27845         return (-1);
27846     /*
27847     * WARNING: Change the start value if adding to the
27848     * xmlSchemaValidOption.
27849     * TODO: Is there an other, more easy to maintain,
27850     * way?
27851     */
27852     for (i = 1; i < (int) sizeof(int) * 8; i++) {
27853         if (options & 1<<i)
27854             return (-1);
27855     }
27856     ctxt->options = options;
27857     return (0);
27858 }
27859
27860 /**
27861  * xmlSchemaValidCtxtGetOptions:
27862  * @ctxt: a schema validation context
27863  *
27864  * Get the validation context options.
27865  *
27866  * Returns the option combination or -1 on error.
27867  */
27868 int
27869 xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
27870
27871 {
27872     if (ctxt == NULL)
27873         return (-1);
27874     else
27875         return (ctxt->options);
27876 }
27877
27878 static int
27879 xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27880 {
27881     xmlAttrPtr attr;
27882     int ret = 0;
27883     xmlSchemaNodeInfoPtr ielem = NULL;
27884     xmlNodePtr node, valRoot;
27885     const xmlChar *nsName;
27886
27887     /* DOC VAL TODO: Move this to the start function. */
27888     if (vctxt->validationRoot != NULL)
27889         valRoot = vctxt->validationRoot;
27890     else
27891         valRoot = xmlDocGetRootElement(vctxt->doc);
27892     if (valRoot == NULL) {
27893         /* VAL TODO: Error code? */
27894         VERROR(1, NULL, "The document has no document element");
27895         return (1);
27896     }
27897     vctxt->depth = -1;
27898     vctxt->validationRoot = valRoot;
27899     node = valRoot;
27900     while (node != NULL) {
27901         if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27902             goto next_sibling;
27903         if (node->type == XML_ELEMENT_NODE) {
27904
27905             /*
27906             * Init the node-info.
27907             */
27908             vctxt->depth++;
27909             if (xmlSchemaValidatorPushElem(vctxt) == -1)
27910                 goto internal_error;
27911             ielem = vctxt->inode;
27912             ielem->node = node;
27913             ielem->nodeLine = node->line;
27914             ielem->localName = node->name;
27915             if (node->ns != NULL)
27916                 ielem->nsName = node->ns->href;
27917             ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27918             /*
27919             * Register attributes.
27920             * DOC VAL TODO: We do not register namespace declaration
27921             * attributes yet.
27922             */
27923             vctxt->nbAttrInfos = 0;
27924             if (node->properties != NULL) {
27925                 attr = node->properties;
27926                 do {
27927                     if (attr->ns != NULL)
27928                         nsName = attr->ns->href;
27929                     else
27930                         nsName = NULL;
27931                     ret = xmlSchemaValidatorPushAttribute(vctxt,
27932                         (xmlNodePtr) attr,
27933                         /*
27934                         * Note that we give it the line number of the
27935                         * parent element.
27936                         */
27937                         ielem->nodeLine,
27938                         attr->name, nsName, 0,
27939                         xmlNodeListGetString(attr->doc, attr->children, 1), 1);
27940                     if (ret == -1) {
27941                         VERROR_INT("xmlSchemaDocWalk",
27942                             "calling xmlSchemaValidatorPushAttribute()");
27943                         goto internal_error;
27944                     }
27945                     attr = attr->next;
27946                 } while (attr);
27947             }
27948             /*
27949             * Validate the element.
27950             */
27951             ret = xmlSchemaValidateElem(vctxt);
27952             if (ret != 0) {
27953                 if (ret == -1) {
27954                     VERROR_INT("xmlSchemaDocWalk",
27955                         "calling xmlSchemaValidateElem()");
27956                     goto internal_error;
27957                 }
27958                 /*
27959                 * Don't stop validation; just skip the content
27960                 * of this element.
27961                 */
27962                 goto leave_node;
27963             }
27964             if ((vctxt->skipDepth != -1) &&
27965                 (vctxt->depth >= vctxt->skipDepth))
27966                 goto leave_node;
27967         } else if ((node->type == XML_TEXT_NODE) ||
27968             (node->type == XML_CDATA_SECTION_NODE)) {
27969             /*
27970             * Process character content.
27971             */
27972             if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
27973                 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27974             ret = xmlSchemaVPushText(vctxt, node->type, node->content,
27975                 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
27976             if (ret < 0) {
27977                 VERROR_INT("xmlSchemaVDocWalk",
27978                     "calling xmlSchemaVPushText()");
27979                 goto internal_error;
27980             }
27981             /*
27982             * DOC VAL TODO: Should we skip further validation of the
27983             * element content here?
27984             */
27985         } else if ((node->type == XML_ENTITY_NODE) ||
27986             (node->type == XML_ENTITY_REF_NODE)) {
27987             /*
27988             * DOC VAL TODO: What to do with entities?
27989             */
27990             VERROR_INT("xmlSchemaVDocWalk",
27991                 "there is at least one entity reference in the node-tree "
27992                 "currently being validated. Processing of entities with "
27993                 "this XML Schema processor is not supported (yet). Please "
27994                 "substitute entities before validation.");
27995             goto internal_error;
27996         } else {
27997             goto leave_node;
27998             /*
27999             * DOC VAL TODO: XInclude nodes, etc.
28000             */
28001         }
28002         /*
28003         * Walk the doc.
28004         */
28005         if (node->children != NULL) {
28006             node = node->children;
28007             continue;
28008         }
28009 leave_node:
28010         if (node->type == XML_ELEMENT_NODE) {
28011             /*
28012             * Leaving the scope of an element.
28013             */
28014             if (node != vctxt->inode->node) {
28015                 VERROR_INT("xmlSchemaVDocWalk",
28016                     "element position mismatch");
28017                 goto internal_error;
28018             }
28019             ret = xmlSchemaValidatorPopElem(vctxt);
28020             if (ret != 0) {
28021                 if (ret < 0) {
28022                     VERROR_INT("xmlSchemaVDocWalk",
28023                         "calling xmlSchemaValidatorPopElem()");
28024                     goto internal_error;
28025                 }
28026             }
28027             if (node == valRoot)
28028                 goto exit;
28029         }
28030 next_sibling:
28031         if (node->next != NULL)
28032             node = node->next;
28033         else {
28034             node = node->parent;
28035             goto leave_node;
28036         }
28037     }
28038
28039 exit:
28040     return (ret);
28041 internal_error:
28042     return (-1);
28043 }
28044
28045 static int
28046 xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
28047     /*
28048     * Some initialization.
28049     */
28050     vctxt->err = 0;
28051     vctxt->nberrors = 0;
28052     vctxt->depth = -1;
28053     vctxt->skipDepth = -1;
28054     vctxt->xsiAssemble = 0;
28055     vctxt->hasKeyrefs = 0;
28056 #ifdef ENABLE_IDC_NODE_TABLES_TEST
28057     vctxt->createIDCNodeTables = 1;
28058 #else
28059     vctxt->createIDCNodeTables = 0;
28060 #endif
28061     /*
28062     * Create a schema + parser if necessary.
28063     */
28064     if (vctxt->schema == NULL) {
28065         xmlSchemaParserCtxtPtr pctxt;
28066
28067         vctxt->xsiAssemble = 1;
28068         /*
28069         * If not schema was given then we will create a schema
28070         * dynamically using XSI schema locations.
28071         *
28072         * Create the schema parser context.
28073         */
28074         if ((vctxt->pctxt == NULL) &&
28075            (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
28076            return (-1);
28077         pctxt = vctxt->pctxt;
28078         pctxt->xsiAssemble = 1;
28079         /*
28080         * Create the schema.
28081         */
28082         vctxt->schema = xmlSchemaNewSchema(pctxt);
28083         if (vctxt->schema == NULL)
28084             return (-1);
28085         /*
28086         * Create the schema construction context.
28087         */
28088         pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
28089         if (pctxt->constructor == NULL)
28090             return(-1);
28091         pctxt->constructor->mainSchema = vctxt->schema;
28092         /*
28093         * Take ownership of the constructor to be able to free it.
28094         */
28095         pctxt->ownsConstructor = 1;
28096     }
28097     /*
28098     * Augment the IDC definitions for the main schema and all imported ones
28099     * NOTE: main schema if the first in the imported list
28100     */
28101     xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt);
28102
28103     return(0);
28104 }
28105
28106 static void
28107 xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
28108     if (vctxt->xsiAssemble) {
28109         if (vctxt->schema != NULL) {
28110             xmlSchemaFree(vctxt->schema);
28111             vctxt->schema = NULL;
28112         }
28113     }
28114     xmlSchemaClearValidCtxt(vctxt);
28115 }
28116
28117 static int
28118 xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
28119 {
28120     int ret = 0;
28121
28122     if (xmlSchemaPreRun(vctxt) < 0)
28123         return(-1);
28124
28125     if (vctxt->doc != NULL) {
28126         /*
28127          * Tree validation.
28128          */
28129         ret = xmlSchemaVDocWalk(vctxt);
28130 #ifdef LIBXML_READER_ENABLED
28131     } else if (vctxt->reader != NULL) {
28132         /*
28133          * XML Reader validation.
28134          */
28135 #ifdef XML_SCHEMA_READER_ENABLED
28136         ret = xmlSchemaVReaderWalk(vctxt);
28137 #endif
28138 #endif
28139     } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
28140         /*
28141          * SAX validation.
28142          */
28143         ret = xmlParseDocument(vctxt->parserCtxt);
28144     } else {
28145         VERROR_INT("xmlSchemaVStart",
28146             "no instance to validate");
28147         ret = -1;
28148     }
28149
28150     xmlSchemaPostRun(vctxt);
28151     if (ret == 0)
28152         ret = vctxt->err;
28153     return (ret);
28154 }
28155
28156 /**
28157  * xmlSchemaValidateOneElement:
28158  * @ctxt:  a schema validation context
28159  * @elem:  an element node
28160  *
28161  * Validate a branch of a tree, starting with the given @elem.
28162  *
28163  * Returns 0 if the element and its subtree is valid, a positive error
28164  * code number otherwise and -1 in case of an internal or API error.
28165  */
28166 int
28167 xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
28168 {
28169     if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
28170         return (-1);
28171
28172     if (ctxt->schema == NULL)
28173         return (-1);
28174
28175     ctxt->doc = elem->doc;
28176     ctxt->node = elem;
28177     ctxt->validationRoot = elem;
28178     return(xmlSchemaVStart(ctxt));
28179 }
28180
28181 /**
28182  * xmlSchemaValidateDoc:
28183  * @ctxt:  a schema validation context
28184  * @doc:  a parsed document tree
28185  *
28186  * Validate a document tree in memory.
28187  *
28188  * Returns 0 if the document is schemas valid, a positive error code
28189  *     number otherwise and -1 in case of internal or API error.
28190  */
28191 int
28192 xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
28193 {
28194     if ((ctxt == NULL) || (doc == NULL))
28195         return (-1);
28196
28197     ctxt->doc = doc;
28198     ctxt->node = xmlDocGetRootElement(doc);
28199     if (ctxt->node == NULL) {
28200         xmlSchemaCustomErr(ACTXT_CAST ctxt,
28201             XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
28202             (xmlNodePtr) doc, NULL,
28203             "The document has no document element", NULL, NULL);
28204         return (ctxt->err);
28205     }
28206     ctxt->validationRoot = ctxt->node;
28207     return (xmlSchemaVStart(ctxt));
28208 }
28209
28210
28211 /************************************************************************
28212  *                                                                      *
28213  *              Function and data for SAX streaming API                 *
28214  *                                                                      *
28215  ************************************************************************/
28216 typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
28217 typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
28218
28219 struct _xmlSchemaSplitSAXData {
28220     xmlSAXHandlerPtr      user_sax;
28221     void                 *user_data;
28222     xmlSchemaValidCtxtPtr ctxt;
28223     xmlSAXHandlerPtr      schemas_sax;
28224 };
28225
28226 #define XML_SAX_PLUG_MAGIC 0xdc43ba21
28227
28228 struct _xmlSchemaSAXPlug {
28229     unsigned int magic;
28230
28231     /* the original callbacks informations */
28232     xmlSAXHandlerPtr     *user_sax_ptr;
28233     xmlSAXHandlerPtr      user_sax;
28234     void                **user_data_ptr;
28235     void                 *user_data;
28236
28237     /* the block plugged back and validation informations */
28238     xmlSAXHandler         schemas_sax;
28239     xmlSchemaValidCtxtPtr ctxt;
28240 };
28241
28242 /* All those functions just bounces to the user provided SAX handlers */
28243 static void
28244 internalSubsetSplit(void *ctx, const xmlChar *name,
28245                const xmlChar *ExternalID, const xmlChar *SystemID)
28246 {
28247     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28248     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28249         (ctxt->user_sax->internalSubset != NULL))
28250         ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
28251                                        SystemID);
28252 }
28253
28254 static int
28255 isStandaloneSplit(void *ctx)
28256 {
28257     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28258     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28259         (ctxt->user_sax->isStandalone != NULL))
28260         return(ctxt->user_sax->isStandalone(ctxt->user_data));
28261     return(0);
28262 }
28263
28264 static int
28265 hasInternalSubsetSplit(void *ctx)
28266 {
28267     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28268     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28269         (ctxt->user_sax->hasInternalSubset != NULL))
28270         return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
28271     return(0);
28272 }
28273
28274 static int
28275 hasExternalSubsetSplit(void *ctx)
28276 {
28277     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28278     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28279         (ctxt->user_sax->hasExternalSubset != NULL))
28280         return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
28281     return(0);
28282 }
28283
28284 static void
28285 externalSubsetSplit(void *ctx, const xmlChar *name,
28286                const xmlChar *ExternalID, const xmlChar *SystemID)
28287 {
28288     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28289     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28290         (ctxt->user_sax->externalSubset != NULL))
28291         ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID,
28292                                        SystemID);
28293 }
28294
28295 static xmlParserInputPtr
28296 resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
28297 {
28298     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28299     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28300         (ctxt->user_sax->resolveEntity != NULL))
28301         return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
28302                                              systemId));
28303     return(NULL);
28304 }
28305
28306 static xmlEntityPtr
28307 getEntitySplit(void *ctx, const xmlChar *name)
28308 {
28309     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28310     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28311         (ctxt->user_sax->getEntity != NULL))
28312         return(ctxt->user_sax->getEntity(ctxt->user_data, name));
28313     return(NULL);
28314 }
28315
28316 static xmlEntityPtr
28317 getParameterEntitySplit(void *ctx, const xmlChar *name)
28318 {
28319     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28320     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28321         (ctxt->user_sax->getParameterEntity != NULL))
28322         return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
28323     return(NULL);
28324 }
28325
28326
28327 static void
28328 entityDeclSplit(void *ctx, const xmlChar *name, int type,
28329           const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
28330 {
28331     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28332     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28333         (ctxt->user_sax->entityDecl != NULL))
28334         ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
28335                                    systemId, content);
28336 }
28337
28338 static void
28339 attributeDeclSplit(void *ctx, const xmlChar * elem,
28340                    const xmlChar * name, int type, int def,
28341                    const xmlChar * defaultValue, xmlEnumerationPtr tree)
28342 {
28343     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28344     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28345         (ctxt->user_sax->attributeDecl != NULL)) {
28346         ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
28347                                       def, defaultValue, tree);
28348     } else {
28349         xmlFreeEnumeration(tree);
28350     }
28351 }
28352
28353 static void
28354 elementDeclSplit(void *ctx, const xmlChar *name, int type,
28355             xmlElementContentPtr content)
28356 {
28357     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28358     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28359         (ctxt->user_sax->elementDecl != NULL))
28360         ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
28361 }
28362
28363 static void
28364 notationDeclSplit(void *ctx, const xmlChar *name,
28365              const xmlChar *publicId, const xmlChar *systemId)
28366 {
28367     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28368     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28369         (ctxt->user_sax->notationDecl != NULL))
28370         ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
28371                                      systemId);
28372 }
28373
28374 static void
28375 unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
28376                    const xmlChar *publicId, const xmlChar *systemId,
28377                    const xmlChar *notationName)
28378 {
28379     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28380     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28381         (ctxt->user_sax->unparsedEntityDecl != NULL))
28382         ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
28383                                            systemId, notationName);
28384 }
28385
28386 static void
28387 setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
28388 {
28389     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28390     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28391         (ctxt->user_sax->setDocumentLocator != NULL))
28392         ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
28393 }
28394
28395 static void
28396 startDocumentSplit(void *ctx)
28397 {
28398     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28399     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28400         (ctxt->user_sax->startDocument != NULL))
28401         ctxt->user_sax->startDocument(ctxt->user_data);
28402 }
28403
28404 static void
28405 endDocumentSplit(void *ctx)
28406 {
28407     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28408     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28409         (ctxt->user_sax->endDocument != NULL))
28410         ctxt->user_sax->endDocument(ctxt->user_data);
28411 }
28412
28413 static void
28414 processingInstructionSplit(void *ctx, const xmlChar *target,
28415                       const xmlChar *data)
28416 {
28417     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28418     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28419         (ctxt->user_sax->processingInstruction != NULL))
28420         ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
28421 }
28422
28423 static void
28424 commentSplit(void *ctx, const xmlChar *value)
28425 {
28426     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28427     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28428         (ctxt->user_sax->comment != NULL))
28429         ctxt->user_sax->comment(ctxt->user_data, value);
28430 }
28431
28432 /*
28433  * Varargs error callbacks to the user application, harder ...
28434  */
28435
28436 static void XMLCDECL
28437 warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28438     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28439     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28440         (ctxt->user_sax->warning != NULL)) {
28441         TODO
28442     }
28443 }
28444 static void XMLCDECL
28445 errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28446     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28447     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28448         (ctxt->user_sax->error != NULL)) {
28449         TODO
28450     }
28451 }
28452 static void XMLCDECL
28453 fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28454     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28455     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28456         (ctxt->user_sax->fatalError != NULL)) {
28457         TODO
28458     }
28459 }
28460
28461 /*
28462  * Those are function where both the user handler and the schemas handler
28463  * need to be called.
28464  */
28465 static void
28466 charactersSplit(void *ctx, const xmlChar *ch, int len)
28467 {
28468     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28469     if (ctxt == NULL)
28470         return;
28471     if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
28472         ctxt->user_sax->characters(ctxt->user_data, ch, len);
28473     if (ctxt->ctxt != NULL)
28474         xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28475 }
28476
28477 static void
28478 ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
28479 {
28480     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28481     if (ctxt == NULL)
28482         return;
28483     if ((ctxt->user_sax != NULL) &&
28484         (ctxt->user_sax->ignorableWhitespace != NULL))
28485         ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
28486     if (ctxt->ctxt != NULL)
28487         xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28488 }
28489
28490 static void
28491 cdataBlockSplit(void *ctx, const xmlChar *value, int len)
28492 {
28493     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28494     if (ctxt == NULL)
28495         return;
28496     if ((ctxt->user_sax != NULL) &&
28497         (ctxt->user_sax->cdataBlock != NULL))
28498         ctxt->user_sax->cdataBlock(ctxt->user_data, value, len);
28499     if (ctxt->ctxt != NULL)
28500         xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28501 }
28502
28503 static void
28504 referenceSplit(void *ctx, const xmlChar *name)
28505 {
28506     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28507     if (ctxt == NULL)
28508         return;
28509     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28510         (ctxt->user_sax->reference != NULL))
28511         ctxt->user_sax->reference(ctxt->user_data, name);
28512     if (ctxt->ctxt != NULL)
28513         xmlSchemaSAXHandleReference(ctxt->user_data, name);
28514 }
28515
28516 static void
28517 startElementNsSplit(void *ctx, const xmlChar * localname,
28518                     const xmlChar * prefix, const xmlChar * URI,
28519                     int nb_namespaces, const xmlChar ** namespaces,
28520                     int nb_attributes, int nb_defaulted,
28521                     const xmlChar ** attributes) {
28522     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28523     if (ctxt == NULL)
28524         return;
28525     if ((ctxt->user_sax != NULL) &&
28526         (ctxt->user_sax->startElementNs != NULL))
28527         ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28528                                        URI, nb_namespaces, namespaces,
28529                                        nb_attributes, nb_defaulted,
28530                                        attributes);
28531     if (ctxt->ctxt != NULL)
28532         xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28533                                          URI, nb_namespaces, namespaces,
28534                                          nb_attributes, nb_defaulted,
28535                                          attributes);
28536 }
28537
28538 static void
28539 endElementNsSplit(void *ctx, const xmlChar * localname,
28540                     const xmlChar * prefix, const xmlChar * URI) {
28541     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28542     if (ctxt == NULL)
28543         return;
28544     if ((ctxt->user_sax != NULL) &&
28545         (ctxt->user_sax->endElementNs != NULL))
28546         ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28547     if (ctxt->ctxt != NULL)
28548         xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28549 }
28550
28551 /**
28552  * xmlSchemaSAXPlug:
28553  * @ctxt:  a schema validation context
28554  * @sax:  a pointer to the original xmlSAXHandlerPtr
28555  * @user_data:  a pointer to the original SAX user data pointer
28556  *
28557  * Plug a SAX based validation layer in a SAX parsing event flow.
28558  * The original @saxptr and @dataptr data are replaced by new pointers
28559  * but the calls to the original will be maintained.
28560  *
28561  * Returns a pointer to a data structure needed to unplug the validation layer
28562  *         or NULL in case of errors.
28563  */
28564 xmlSchemaSAXPlugPtr
28565 xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28566                  xmlSAXHandlerPtr *sax, void **user_data)
28567 {
28568     xmlSchemaSAXPlugPtr ret;
28569     xmlSAXHandlerPtr old_sax;
28570
28571     if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28572         return(NULL);
28573
28574     /*
28575      * We only allow to plug into SAX2 event streams
28576      */
28577     old_sax = *sax;
28578     if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28579         return(NULL);
28580     if ((old_sax != NULL) &&
28581         (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28582         ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28583         return(NULL);
28584
28585     /*
28586      * everything seems right allocate the local data needed for that layer
28587      */
28588     ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28589     if (ret == NULL) {
28590         return(NULL);
28591     }
28592     memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28593     ret->magic = XML_SAX_PLUG_MAGIC;
28594     ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28595     ret->ctxt = ctxt;
28596     ret->user_sax_ptr = sax;
28597     ret->user_sax = old_sax;
28598     if (old_sax == NULL) {
28599         /*
28600          * go direct, no need for the split block and functions.
28601          */
28602         ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28603         ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28604         /*
28605          * Note that we use the same text-function for both, to prevent
28606          * the parser from testing for ignorable whitespace.
28607          */
28608         ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28609         ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28610
28611         ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28612         ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28613
28614         ret->user_data = ctxt;
28615         *user_data = ctxt;
28616     } else {
28617        /*
28618         * for each callback unused by Schemas initialize it to the Split
28619         * routine only if non NULL in the user block, this can speed up
28620         * things at the SAX level.
28621         */
28622         if (old_sax->internalSubset != NULL)
28623             ret->schemas_sax.internalSubset = internalSubsetSplit;
28624         if (old_sax->isStandalone != NULL)
28625             ret->schemas_sax.isStandalone = isStandaloneSplit;
28626         if (old_sax->hasInternalSubset != NULL)
28627             ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28628         if (old_sax->hasExternalSubset != NULL)
28629             ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28630         if (old_sax->resolveEntity != NULL)
28631             ret->schemas_sax.resolveEntity = resolveEntitySplit;
28632         if (old_sax->getEntity != NULL)
28633             ret->schemas_sax.getEntity = getEntitySplit;
28634         if (old_sax->entityDecl != NULL)
28635             ret->schemas_sax.entityDecl = entityDeclSplit;
28636         if (old_sax->notationDecl != NULL)
28637             ret->schemas_sax.notationDecl = notationDeclSplit;
28638         if (old_sax->attributeDecl != NULL)
28639             ret->schemas_sax.attributeDecl = attributeDeclSplit;
28640         if (old_sax->elementDecl != NULL)
28641             ret->schemas_sax.elementDecl = elementDeclSplit;
28642         if (old_sax->unparsedEntityDecl != NULL)
28643             ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28644         if (old_sax->setDocumentLocator != NULL)
28645             ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28646         if (old_sax->startDocument != NULL)
28647             ret->schemas_sax.startDocument = startDocumentSplit;
28648         if (old_sax->endDocument != NULL)
28649             ret->schemas_sax.endDocument = endDocumentSplit;
28650         if (old_sax->processingInstruction != NULL)
28651             ret->schemas_sax.processingInstruction = processingInstructionSplit;
28652         if (old_sax->comment != NULL)
28653             ret->schemas_sax.comment = commentSplit;
28654         if (old_sax->warning != NULL)
28655             ret->schemas_sax.warning = warningSplit;
28656         if (old_sax->error != NULL)
28657             ret->schemas_sax.error = errorSplit;
28658         if (old_sax->fatalError != NULL)
28659             ret->schemas_sax.fatalError = fatalErrorSplit;
28660         if (old_sax->getParameterEntity != NULL)
28661             ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28662         if (old_sax->externalSubset != NULL)
28663             ret->schemas_sax.externalSubset = externalSubsetSplit;
28664
28665         /*
28666          * the 6 schemas callback have to go to the splitter functions
28667          * Note that we use the same text-function for ignorableWhitespace
28668          * if possible, to prevent the parser from testing for ignorable
28669          * whitespace.
28670          */
28671         ret->schemas_sax.characters = charactersSplit;
28672         if ((old_sax->ignorableWhitespace != NULL) &&
28673             (old_sax->ignorableWhitespace != old_sax->characters))
28674             ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28675         else
28676             ret->schemas_sax.ignorableWhitespace = charactersSplit;
28677         ret->schemas_sax.cdataBlock = cdataBlockSplit;
28678         ret->schemas_sax.reference = referenceSplit;
28679         ret->schemas_sax.startElementNs = startElementNsSplit;
28680         ret->schemas_sax.endElementNs = endElementNsSplit;
28681
28682         ret->user_data_ptr = user_data;
28683         ret->user_data = *user_data;
28684         *user_data = ret;
28685     }
28686
28687     /*
28688      * plug the pointers back.
28689      */
28690     *sax = &(ret->schemas_sax);
28691     ctxt->sax = *sax;
28692     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28693     xmlSchemaPreRun(ctxt);
28694     return(ret);
28695 }
28696
28697 /**
28698  * xmlSchemaSAXUnplug:
28699  * @plug:  a data structure returned by xmlSchemaSAXPlug
28700  *
28701  * Unplug a SAX based validation layer in a SAX parsing event flow.
28702  * The original pointers used in the call are restored.
28703  *
28704  * Returns 0 in case of success and -1 in case of failure.
28705  */
28706 int
28707 xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28708 {
28709     xmlSAXHandlerPtr *sax;
28710     void **user_data;
28711
28712     if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28713         return(-1);
28714     plug->magic = 0;
28715
28716     xmlSchemaPostRun(plug->ctxt);
28717     /* restore the data */
28718     sax = plug->user_sax_ptr;
28719     *sax = plug->user_sax;
28720     if (plug->user_sax != NULL) {
28721         user_data = plug->user_data_ptr;
28722         *user_data = plug->user_data;
28723     }
28724
28725     /* free and return */
28726     xmlFree(plug);
28727     return(0);
28728 }
28729
28730 /**
28731  * xmlSchemaValidateSetLocator:
28732  * @vctxt: a schema validation context
28733  * @f: the locator function pointer
28734  * @ctxt: the locator context
28735  *
28736  * Allows to set a locator function to the validation context,
28737  * which will be used to provide file and line information since
28738  * those are not provided as part of the SAX validation flow
28739  * Setting @f to NULL disable the locator.
28740  */
28741
28742 void
28743 xmlSchemaValidateSetLocator(xmlSchemaValidCtxtPtr vctxt,
28744                             xmlSchemaValidityLocatorFunc f,
28745                             void *ctxt)
28746 {
28747     if (vctxt == NULL) return;
28748     vctxt->locFunc = f;
28749     vctxt->locCtxt = ctxt;
28750 }
28751
28752 /**
28753  * xmlSchemaValidateStreamLocator:
28754  * @ctx: the xmlTextReaderPtr used
28755  * @file: returned file information
28756  * @line: returned line information
28757  *
28758  * Internal locator function for the readers
28759  *
28760  * Returns 0 in case the Schema validation could be (des)activated and
28761  *         -1 in case of error.
28762  */
28763 static int
28764 xmlSchemaValidateStreamLocator(void *ctx, const char **file,
28765                                unsigned long *line) {
28766     xmlParserCtxtPtr ctxt;
28767
28768     if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
28769         return(-1);
28770
28771     if (file != NULL)
28772         *file = NULL;
28773     if (line != NULL)
28774         *line = 0;
28775
28776     ctxt = (xmlParserCtxtPtr) ctx;
28777     if (ctxt->input != NULL) {
28778        if (file != NULL)
28779            *file = ctxt->input->filename;
28780        if (line != NULL)
28781            *line = ctxt->input->line;
28782        return(0);
28783     }
28784     return(-1);
28785 }
28786
28787 /**
28788  * xmlSchemaValidateStream:
28789  * @ctxt:  a schema validation context
28790  * @input:  the input to use for reading the data
28791  * @enc:  an optional encoding information
28792  * @sax:  a SAX handler for the resulting events
28793  * @user_data:  the context to provide to the SAX handler.
28794  *
28795  * Validate an input based on a flow of SAX event from the parser
28796  * and forward the events to the @sax handler with the provided @user_data
28797  * the user provided @sax handler must be a SAX2 one.
28798  *
28799  * Returns 0 if the document is schemas valid, a positive error code
28800  *     number otherwise and -1 in case of internal or API error.
28801  */
28802 int
28803 xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
28804                         xmlParserInputBufferPtr input, xmlCharEncoding enc,
28805                         xmlSAXHandlerPtr sax, void *user_data)
28806 {
28807     xmlSchemaSAXPlugPtr plug = NULL;
28808     xmlSAXHandlerPtr old_sax = NULL;
28809     xmlParserCtxtPtr pctxt = NULL;
28810     xmlParserInputPtr inputStream = NULL;
28811     int ret;
28812
28813     if ((ctxt == NULL) || (input == NULL))
28814         return (-1);
28815
28816     /*
28817      * prepare the parser
28818      */
28819     pctxt = xmlNewParserCtxt();
28820     if (pctxt == NULL)
28821         return (-1);
28822     old_sax = pctxt->sax;
28823     pctxt->sax = sax;
28824     pctxt->userData = user_data;
28825 #if 0
28826     if (options)
28827         xmlCtxtUseOptions(pctxt, options);
28828 #endif
28829     pctxt->linenumbers = 1;
28830     xmlSchemaValidateSetLocator(ctxt, xmlSchemaValidateStreamLocator, pctxt);
28831
28832     inputStream = xmlNewIOInputStream(pctxt, input, enc);;
28833     if (inputStream == NULL) {
28834         ret = -1;
28835         goto done;
28836     }
28837     inputPush(pctxt, inputStream);
28838     ctxt->parserCtxt = pctxt;
28839     ctxt->input = input;
28840
28841     /*
28842      * Plug the validation and launch the parsing
28843      */
28844     plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28845     if (plug == NULL) {
28846         ret = -1;
28847         goto done;
28848     }
28849     ctxt->input = input;
28850     ctxt->enc = enc;
28851     ctxt->sax = pctxt->sax;
28852     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28853     ret = xmlSchemaVStart(ctxt);
28854
28855     if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28856         ret = ctxt->parserCtxt->errNo;
28857         if (ret == 0)
28858             ret = 1;
28859     }
28860
28861 done:
28862     ctxt->parserCtxt = NULL;
28863     ctxt->sax = NULL;
28864     ctxt->input = NULL;
28865     if (plug != NULL) {
28866         xmlSchemaSAXUnplug(plug);
28867     }
28868     /* cleanup */
28869     if (pctxt != NULL) {
28870         pctxt->sax = old_sax;
28871         xmlFreeParserCtxt(pctxt);
28872     }
28873     return (ret);
28874 }
28875
28876 /**
28877  * xmlSchemaValidateFile:
28878  * @ctxt: a schema validation context
28879  * @filename: the URI of the instance
28880  * @options: a future set of options, currently unused
28881  *
28882  * Do a schemas validation of the given resource, it will use the
28883  * SAX streamable validation internally.
28884  *
28885  * Returns 0 if the document is valid, a positive error code
28886  *     number otherwise and -1 in case of an internal or API error.
28887  */
28888 int
28889 xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
28890                       const char * filename,
28891                       int options ATTRIBUTE_UNUSED)
28892 {
28893     int ret;
28894     xmlParserInputBufferPtr input;
28895
28896     if ((ctxt == NULL) || (filename == NULL))
28897         return (-1);
28898
28899     input = xmlParserInputBufferCreateFilename(filename,
28900         XML_CHAR_ENCODING_NONE);
28901     if (input == NULL)
28902         return (-1);
28903     ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
28904         NULL, NULL);
28905     return (ret);
28906 }
28907
28908 /**
28909  * xmlSchemaValidCtxtGetParserCtxt:
28910  * @ctxt: a schema validation context
28911  *
28912  * allow access to the parser context of the schema validation context
28913  *
28914  * Returns the parser context of the schema validation context or NULL
28915  *         in case of error.
28916  */
28917 xmlParserCtxtPtr
28918 xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)
28919 {
28920     if (ctxt == NULL)
28921         return(NULL);
28922     return (ctxt->parserCtxt);
28923 }
28924
28925 #define bottom_xmlschemas
28926 #include "elfgcchack.h"
28927 #endif /* LIBXML_SCHEMAS_ENABLED */