- add sources.
[platform/framework/web/crosswalk.git] / src / third_party / libxml / src / xmlschemas.c
1 /*
2  * schemas.c : implementation of the XML Schema handling and
3  *             schema validity checking
4  *
5  * See Copyright for the status of this software.
6  *
7  * Daniel Veillard <veillard@redhat.com>
8  */
9
10 /*
11  * TODO:
12  *   - when types are redefined in includes, check that all
13  *     types in the redef list are equal
14  *     -> need a type equality operation.
15  *   - if we don't intend to use the schema for schemas, we
16  *     need to validate all schema attributes (ref, type, name)
17  *     against their types.
18  *   - Eliminate item creation for: ??
19  *
20  * URGENT TODO:
21  *   - For xsi-driven schema acquisition, augment the IDCs after every
22  *     acquisition episode (xmlSchemaAugmentIDC).
23  *
24  * NOTES:
25  *   - Elimated item creation for: <restriction>, <extension>,
26  *     <simpleContent>, <complexContent>, <list>, <union>
27  *
28  * PROBLEMS:
29  *   - http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0337.html
30  *     IDC XPath expression and chameleon includes: the targetNamespace is changed, so
31  *     XPath will have trouble to resolve to this namespace, since not known.
32  *
33  *
34  * CONSTRAINTS:
35  *
36  * Schema Component Constraint:
37  *   All Group Limited (cos-all-limited)
38  *   Status: complete
39  *   (1.2)
40  *     In xmlSchemaGroupDefReferenceTermFixup() and
41  *   (2)
42  *     In xmlSchemaParseModelGroup()
43  *     TODO: Actually this should go to component-level checks,
44  *     but is done here due to performance. Move it to an other layer
45  *     is schema construction via an API is implemented.
46  */
47 #define IN_LIBXML
48 #include "libxml.h"
49
50 #ifdef LIBXML_SCHEMAS_ENABLED
51
52 #include <string.h>
53 #include <libxml/xmlmemory.h>
54 #include <libxml/parser.h>
55 #include <libxml/parserInternals.h>
56 #include <libxml/hash.h>
57 #include <libxml/uri.h>
58 #include <libxml/xmlschemas.h>
59 #include <libxml/schemasInternals.h>
60 #include <libxml/xmlschemastypes.h>
61 #include <libxml/xmlautomata.h>
62 #include <libxml/xmlregexp.h>
63 #include <libxml/dict.h>
64 #include <libxml/encoding.h>
65 #include <libxml/xmlIO.h>
66 #ifdef LIBXML_PATTERN_ENABLED
67 #include <libxml/pattern.h>
68 #endif
69 #ifdef LIBXML_READER_ENABLED
70 #include <libxml/xmlreader.h>
71 #endif
72
73 /* #define DEBUG 1 */
74
75 /* #define DEBUG_CONTENT 1 */
76
77 /* #define DEBUG_TYPE 1 */
78
79 /* #define DEBUG_CONTENT_REGEXP 1 */
80
81 /* #define DEBUG_AUTOMATA 1 */
82
83 /* #define DEBUG_IDC */
84
85 /* #define DEBUG_IDC_NODE_TABLE */
86
87 /* #define WXS_ELEM_DECL_CONS_ENABLED */
88
89 #ifdef DEBUG_IDC
90  #ifndef DEBUG_IDC_NODE_TABLE
91   #define DEBUG_IDC_NODE_TABLE
92  #endif
93 #endif
94
95 /* #define ENABLE_PARTICLE_RESTRICTION 1 */
96
97 #define ENABLE_REDEFINE
98
99 /* #define ENABLE_NAMED_LOCALS */
100
101 /* #define ENABLE_IDC_NODE_TABLES_TEST */
102
103 #define DUMP_CONTENT_MODEL
104
105 #ifdef LIBXML_READER_ENABLED
106 /* #define XML_SCHEMA_READER_ENABLED */
107 #endif
108
109 #define UNBOUNDED (1 << 30)
110 #define TODO                                                            \
111     xmlGenericError(xmlGenericErrorContext,                             \
112             "Unimplemented block at %s:%d\n",                           \
113             __FILE__, __LINE__);
114
115 #define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
116
117 /*
118  * The XML Schemas namespaces
119  */
120 static const xmlChar *xmlSchemaNs = (const xmlChar *)
121     "http://www.w3.org/2001/XMLSchema";
122
123 static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
124     "http://www.w3.org/2001/XMLSchema-instance";
125
126 static const xmlChar *xmlNamespaceNs = (const xmlChar *)
127     "http://www.w3.org/2000/xmlns/";
128
129 /*
130 * Come casting macros.
131 */
132 #define ACTXT_CAST (xmlSchemaAbstractCtxtPtr)
133 #define PCTXT_CAST (xmlSchemaParserCtxtPtr)
134 #define VCTXT_CAST (xmlSchemaValidCtxtPtr)
135 #define WXS_BASIC_CAST (xmlSchemaBasicItemPtr)
136 #define WXS_TREE_CAST (xmlSchemaTreeItemPtr)
137 #define WXS_PTC_CAST (xmlSchemaParticlePtr)
138 #define WXS_TYPE_CAST (xmlSchemaTypePtr)
139 #define WXS_ELEM_CAST (xmlSchemaElementPtr)
140 #define WXS_ATTR_GROUP_CAST (xmlSchemaAttributeGroupPtr)
141 #define WXS_ATTR_CAST (xmlSchemaAttributePtr)
142 #define WXS_ATTR_USE_CAST (xmlSchemaAttributeUsePtr)
143 #define WXS_ATTR_PROHIB_CAST (xmlSchemaAttributeUseProhibPtr)
144 #define WXS_MODEL_GROUPDEF_CAST (xmlSchemaModelGroupDefPtr)
145 #define WXS_MODEL_GROUP_CAST (xmlSchemaModelGroupPtr)
146 #define WXS_IDC_CAST (xmlSchemaIDCPtr)
147 #define WXS_QNAME_CAST (xmlSchemaQNameRefPtr)
148 #define WXS_LIST_CAST (xmlSchemaItemListPtr)
149
150 /*
151 * Macros to query common properties of components.
152 */
153 #define WXS_ITEM_NODE(i) xmlSchemaGetComponentNode(WXS_BASIC_CAST (i))
154
155 #define WXS_ITEM_TYPE_NAME(i) xmlSchemaGetComponentTypeStr(WXS_BASIC_CAST (i))
156 /*
157 * Macros for element declarations.
158 */
159 #define WXS_ELEM_TYPEDEF(e) (e)->subtypes
160
161 #define WXS_SUBST_HEAD(item) (item)->refDecl
162 /*
163 * Macros for attribute declarations.
164 */
165 #define WXS_ATTR_TYPEDEF(a) (a)->subtypes
166 /*
167 * Macros for attribute uses.
168 */
169 #define WXS_ATTRUSE_DECL(au) WXS_ATTR_CAST (WXS_ATTR_USE_CAST (au))->attrDecl
170
171 #define WXS_ATTRUSE_TYPEDEF(au) WXS_ATTR_TYPEDEF(WXS_ATTRUSE_DECL( WXS_ATTR_USE_CAST au))
172
173 #define WXS_ATTRUSE_DECL_NAME(au) (WXS_ATTRUSE_DECL(au))->name
174
175 #define WXS_ATTRUSE_DECL_TNS(au) (WXS_ATTRUSE_DECL(au))->targetNamespace
176 /*
177 * Macros for attribute groups.
178 */
179 #define WXS_ATTR_GROUP_HAS_REFS(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS)
180 #define WXS_ATTR_GROUP_EXPANDED(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED)
181 /*
182 * Macros for particles.
183 */
184 #define WXS_PARTICLE(p) WXS_PTC_CAST (p)
185
186 #define WXS_PARTICLE_TERM(p) (WXS_PARTICLE(p))->children
187
188 #define WXS_PARTICLE_TERM_AS_ELEM(p) (WXS_ELEM_CAST WXS_PARTICLE_TERM(p))
189
190 #define WXS_PARTICLE_MODEL(p) WXS_MODEL_GROUP_CAST WXS_PARTICLE(p)->children
191 /*
192 * Macros for model groups definitions.
193 */
194 #define WXS_MODELGROUPDEF_MODEL(mgd) (WXS_MODEL_GROUP_CAST (mgd))->children
195 /*
196 * Macros for model groups.
197 */
198 #define WXS_IS_MODEL_GROUP(i) \
199     (((i)->type == XML_SCHEMA_TYPE_SEQUENCE) || \
200      ((i)->type == XML_SCHEMA_TYPE_CHOICE) || \
201      ((i)->type == XML_SCHEMA_TYPE_ALL))
202
203 #define WXS_MODELGROUP_PARTICLE(mg) WXS_PTC_CAST (mg)->children
204 /*
205 * Macros for schema buckets.
206 */
207 #define WXS_IS_BUCKET_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \
208     ((t) == XML_SCHEMA_SCHEMA_REDEFINE))
209
210 #define WXS_IS_BUCKET_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \
211     ((t) == XML_SCHEMA_SCHEMA_IMPORT))
212
213 #define WXS_IMPBUCKET(b) ((xmlSchemaImportPtr) (b))
214
215 #define WXS_INCBUCKET(b) ((xmlSchemaIncludePtr) (b))
216 /*
217 * Macros for complex/simple types.
218 */
219 #define WXS_IS_ANYTYPE(i) \
220      (( (i)->type == XML_SCHEMA_TYPE_BASIC) && \
221       ( (WXS_TYPE_CAST (i))->builtInType == XML_SCHEMAS_ANYTYPE))
222
223 #define WXS_IS_COMPLEX(i) \
224     (((i)->type == XML_SCHEMA_TYPE_COMPLEX) || \
225      ((i)->builtInType == XML_SCHEMAS_ANYTYPE))
226
227 #define WXS_IS_SIMPLE(item) \
228     ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
229      ((item->type == XML_SCHEMA_TYPE_BASIC) && \
230       (item->builtInType != XML_SCHEMAS_ANYTYPE)))
231
232 #define WXS_IS_ANY_SIMPLE_TYPE(i) \
233     (((i)->type == XML_SCHEMA_TYPE_BASIC) && \
234       ((i)->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
235
236 #define WXS_IS_RESTRICTION(t) \
237     ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)
238
239 #define WXS_IS_EXTENSION(t) \
240     ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
241
242 #define WXS_IS_TYPE_NOT_FIXED(i) \
243     (((i)->type != XML_SCHEMA_TYPE_BASIC) && \
244      (((i)->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
245
246 #define WXS_IS_TYPE_NOT_FIXED_1(item) \
247     (((item)->type != XML_SCHEMA_TYPE_BASIC) && \
248      (((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0))
249
250 #define WXS_TYPE_IS_GLOBAL(t) ((t)->flags & XML_SCHEMAS_TYPE_GLOBAL)
251
252 #define WXS_TYPE_IS_LOCAL(t) (((t)->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0)
253 /*
254 * Macros for exclusively for complex types.
255 */
256 #define WXS_HAS_COMPLEX_CONTENT(item) \
257     ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
258      (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
259      (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
260
261 #define WXS_HAS_SIMPLE_CONTENT(item) \
262     ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
263      (item->contentType == XML_SCHEMA_CONTENT_BASIC))
264
265 #define WXS_HAS_MIXED_CONTENT(item) \
266     (item->contentType == XML_SCHEMA_CONTENT_MIXED)
267
268 #define WXS_EMPTIABLE(t) \
269     (xmlSchemaIsParticleEmptiable(WXS_PTC_CAST (t)->subtypes))
270
271 #define WXS_TYPE_CONTENTTYPE(t) (t)->subtypes
272
273 #define WXS_TYPE_PARTICLE(t) WXS_PTC_CAST (t)->subtypes
274
275 #define WXS_TYPE_PARTICLE_TERM(t) WXS_PARTICLE_TERM(WXS_TYPE_PARTICLE(t))
276 /*
277 * Macros for exclusively for simple types.
278 */
279 #define WXS_LIST_ITEMTYPE(t) (t)->subtypes
280
281 #define WXS_IS_ATOMIC(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
282
283 #define WXS_IS_LIST(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
284
285 #define WXS_IS_UNION(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
286 /*
287 * Misc parser context macros.
288 */
289 #define WXS_CONSTRUCTOR(ctx) (ctx)->constructor
290
291 #define WXS_HAS_BUCKETS(ctx) \
292 ( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \
293 (WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) )
294
295 #define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups
296
297 #define WXS_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket
298
299 #define WXS_SCHEMA(ctx) (ctx)->schema
300
301 #define WXS_ADD_LOCAL(ctx, item) \
302     xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, item)
303
304 #define WXS_ADD_GLOBAL(ctx, item) \
305     xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, item)
306
307 #define WXS_ADD_PENDING(ctx, item) \
308     xmlSchemaAddItemSize(&((ctx)->constructor->pending), 10, item)
309 /*
310 * xmlSchemaItemList macros.
311 */
312 #define WXS_ILIST_IS_EMPTY(l) ((l == NULL) || ((l)->nbItems == 0))
313 /*
314 * Misc macros.
315 */
316 #define IS_SCHEMA(node, type) \
317    ((node != NULL) && (node->ns != NULL) && \
318     (xmlStrEqual(node->name, (const xmlChar *) type)) && \
319     (xmlStrEqual(node->ns->href, xmlSchemaNs)))
320
321 #define FREE_AND_NULL(str) if ((str) != NULL) { xmlFree((xmlChar *) (str)); str = NULL; }
322
323 /*
324 * Since we put the default/fixed values into the dict, we can
325 * use pointer comparison for those values.
326 * REMOVED: (xmlStrEqual((v1), (v2)))
327 */
328 #define WXS_ARE_DEFAULT_STR_EQUAL(v1, v2) ((v1) == (v2))
329
330 #define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
331
332 #define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0))
333
334 #define HFAILURE if (res == -1) goto exit_failure;
335
336 #define HERROR if (res != 0) goto exit_error;
337
338 #define HSTOP(ctx) if ((ctx)->stop) goto exit;
339 /*
340 * Some flags used for various schema constraints.
341 */
342 #define SUBSET_RESTRICTION  1<<0
343 #define SUBSET_EXTENSION    1<<1
344 #define SUBSET_SUBSTITUTION 1<<2
345 #define SUBSET_LIST         1<<3
346 #define SUBSET_UNION        1<<4
347
348 typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
349 typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
350
351 typedef struct _xmlSchemaItemList xmlSchemaItemList;
352 typedef xmlSchemaItemList *xmlSchemaItemListPtr;
353 struct _xmlSchemaItemList {
354     void **items;  /* used for dynamic addition of schemata */
355     int nbItems; /* used for dynamic addition of schemata */
356     int sizeItems; /* used for dynamic addition of schemata */
357 };
358
359 #define XML_SCHEMA_CTXT_PARSER 1
360 #define XML_SCHEMA_CTXT_VALIDATOR 2
361
362 typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
363 typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
364 struct _xmlSchemaAbstractCtxt {
365     int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */
366 };
367
368 typedef struct _xmlSchemaBucket xmlSchemaBucket;
369 typedef xmlSchemaBucket *xmlSchemaBucketPtr;
370
371 #define XML_SCHEMA_SCHEMA_MAIN 0
372 #define XML_SCHEMA_SCHEMA_IMPORT 1
373 #define XML_SCHEMA_SCHEMA_INCLUDE 2
374 #define XML_SCHEMA_SCHEMA_REDEFINE 3
375
376 /**
377  * xmlSchemaSchemaRelation:
378  *
379  * Used to create a graph of schema relationships.
380  */
381 typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation;
382 typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr;
383 struct _xmlSchemaSchemaRelation {
384     xmlSchemaSchemaRelationPtr next;
385     int type; /* E.g. XML_SCHEMA_SCHEMA_IMPORT */
386     const xmlChar *importNamespace;
387     xmlSchemaBucketPtr bucket;
388 };
389
390 #define XML_SCHEMA_BUCKET_MARKED 1<<0
391 #define XML_SCHEMA_BUCKET_COMPS_ADDED 1<<1
392
393 struct _xmlSchemaBucket {
394     int type;
395     int flags;
396     const xmlChar *schemaLocation;
397     const xmlChar *origTargetNamespace;
398     const xmlChar *targetNamespace;
399     xmlDocPtr doc;
400     xmlSchemaSchemaRelationPtr relations;
401     int located;
402     int parsed;
403     int imported;
404     int preserveDoc;
405     xmlSchemaItemListPtr globals; /* Global components. */
406     xmlSchemaItemListPtr locals; /* Local components. */
407 };
408
409 /**
410  * xmlSchemaImport:
411  * (extends xmlSchemaBucket)
412  *
413  * Reflects a schema. Holds some information
414  * about the schema and its toplevel components. Duplicate
415  * toplevel components are not checked at this level.
416  */
417 typedef struct _xmlSchemaImport xmlSchemaImport;
418 typedef xmlSchemaImport *xmlSchemaImportPtr;
419 struct _xmlSchemaImport {
420     int type; /* Main OR import OR include. */
421     int flags;
422     const xmlChar *schemaLocation; /* The URI of the schema document. */
423     /* For chameleon includes, @origTargetNamespace will be NULL */
424     const xmlChar *origTargetNamespace;
425     /*
426     * For chameleon includes, @targetNamespace will be the
427     * targetNamespace of the including schema.
428     */
429     const xmlChar *targetNamespace;
430     xmlDocPtr doc; /* The schema node-tree. */
431     /* @relations will hold any included/imported/redefined schemas. */
432     xmlSchemaSchemaRelationPtr relations;
433     int located;
434     int parsed;
435     int imported;
436     int preserveDoc;
437     xmlSchemaItemListPtr globals;
438     xmlSchemaItemListPtr locals;
439     /* The imported schema. */
440     xmlSchemaPtr schema;
441 };
442
443 /*
444 * (extends xmlSchemaBucket)
445 */
446 typedef struct _xmlSchemaInclude xmlSchemaInclude;
447 typedef xmlSchemaInclude *xmlSchemaIncludePtr;
448 struct _xmlSchemaInclude {
449     int type;
450     int flags;
451     const xmlChar *schemaLocation;
452     const xmlChar *origTargetNamespace;
453     const xmlChar *targetNamespace;
454     xmlDocPtr doc;
455     xmlSchemaSchemaRelationPtr relations;
456     int located;
457     int parsed;
458     int imported;
459     int preserveDoc;
460     xmlSchemaItemListPtr globals; /* Global components. */
461     xmlSchemaItemListPtr locals; /* Local components. */
462
463     /* The owning main or import schema bucket. */
464     xmlSchemaImportPtr ownerImport;
465 };
466
467 /**
468  * xmlSchemaBasicItem:
469  *
470  * The abstract base type for schema components.
471  */
472 typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
473 typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
474 struct _xmlSchemaBasicItem {
475     xmlSchemaTypeType type;
476 };
477
478 /**
479  * xmlSchemaAnnotItem:
480  *
481  * The abstract base type for annotated schema components.
482  * (Extends xmlSchemaBasicItem)
483  */
484 typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
485 typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
486 struct _xmlSchemaAnnotItem {
487     xmlSchemaTypeType type;
488     xmlSchemaAnnotPtr annot;
489 };
490
491 /**
492  * xmlSchemaTreeItem:
493  *
494  * The abstract base type for tree-like structured schema components.
495  * (Extends xmlSchemaAnnotItem)
496  */
497 typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
498 typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
499 struct _xmlSchemaTreeItem {
500     xmlSchemaTypeType type;
501     xmlSchemaAnnotPtr annot;
502     xmlSchemaTreeItemPtr next;
503     xmlSchemaTreeItemPtr children;
504 };
505
506
507 #define XML_SCHEMA_ATTR_USE_FIXED 1<<0
508 /**
509  * xmlSchemaAttributeUsePtr:
510  *
511  * The abstract base type for tree-like structured schema components.
512  * (Extends xmlSchemaTreeItem)
513  */
514 typedef struct _xmlSchemaAttributeUse xmlSchemaAttributeUse;
515 typedef xmlSchemaAttributeUse *xmlSchemaAttributeUsePtr;
516 struct _xmlSchemaAttributeUse {
517     xmlSchemaTypeType type;
518     xmlSchemaAnnotPtr annot;
519     xmlSchemaAttributeUsePtr next; /* The next attr. use. */
520     /*
521     * The attr. decl. OR a QName-ref. to an attr. decl. OR
522     * a QName-ref. to an attribute group definition.
523     */
524     xmlSchemaAttributePtr attrDecl;
525
526     int flags;
527     xmlNodePtr node;
528     int occurs; /* required, optional */
529     const xmlChar * defValue;
530     xmlSchemaValPtr defVal;
531 };
532
533 /**
534  * xmlSchemaAttributeUseProhibPtr:
535  *
536  * A helper component to reflect attribute prohibitions.
537  * (Extends xmlSchemaBasicItem)
538  */
539 typedef struct _xmlSchemaAttributeUseProhib xmlSchemaAttributeUseProhib;
540 typedef xmlSchemaAttributeUseProhib *xmlSchemaAttributeUseProhibPtr;
541 struct _xmlSchemaAttributeUseProhib {
542     xmlSchemaTypeType type; /* == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB */
543     xmlNodePtr node;
544     const xmlChar *name;
545     const xmlChar *targetNamespace;
546     int isRef;
547 };
548
549 /**
550  * xmlSchemaRedef:
551  */
552 typedef struct _xmlSchemaRedef xmlSchemaRedef;
553 typedef xmlSchemaRedef *xmlSchemaRedefPtr;
554 struct _xmlSchemaRedef {
555     xmlSchemaRedefPtr next;
556     xmlSchemaBasicItemPtr item; /* The redefining component. */
557     xmlSchemaBasicItemPtr reference; /* The referencing component. */
558     xmlSchemaBasicItemPtr target; /* The to-be-redefined component. */
559     const xmlChar *refName; /* The name of the to-be-redefined component. */
560     const xmlChar *refTargetNs; /* The target namespace of the
561                                    to-be-redefined comp. */
562     xmlSchemaBucketPtr targetBucket; /* The redefined schema. */
563 };
564
565 /**
566  * xmlSchemaConstructionCtxt:
567  */
568 typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt;
569 typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr;
570 struct _xmlSchemaConstructionCtxt {
571     xmlSchemaPtr mainSchema; /* The main schema. */
572     xmlSchemaBucketPtr mainBucket; /* The main schema bucket */
573     xmlDictPtr dict;
574     xmlSchemaItemListPtr buckets; /* List of schema buckets. */
575     /* xmlSchemaItemListPtr relations; */ /* List of schema relations. */
576     xmlSchemaBucketPtr bucket; /* The current schema bucket */
577     xmlSchemaItemListPtr pending; /* All Components of all schemas that
578                                      need to be fixed. */
579     xmlHashTablePtr substGroups;
580     xmlSchemaRedefPtr redefs;
581     xmlSchemaRedefPtr lastRedef;
582 };
583
584 #define XML_SCHEMAS_PARSE_ERROR         1
585 #define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
586
587 struct _xmlSchemaParserCtxt {
588     int type;
589     void *errCtxt;             /* user specific error context */
590     xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */
591     xmlSchemaValidityWarningFunc warning;       /* the callback in case of warning */
592     int err;
593     int nberrors;
594     xmlStructuredErrorFunc serror;
595
596     xmlSchemaConstructionCtxtPtr constructor;
597     int ownsConstructor; /* TODO: Move this to parser *flags*. */
598
599     /* xmlSchemaPtr topschema;  */
600     /* xmlHashTablePtr namespaces;  */
601
602     xmlSchemaPtr schema;        /* The main schema in use */
603     int counter;
604
605     const xmlChar *URL;
606     xmlDocPtr doc;
607     int preserve;               /* Whether the doc should be freed  */
608
609     const char *buffer;
610     int size;
611
612     /*
613      * Used to build complex element content models
614      */
615     xmlAutomataPtr am;
616     xmlAutomataStatePtr start;
617     xmlAutomataStatePtr end;
618     xmlAutomataStatePtr state;
619
620     xmlDictPtr dict;            /* dictionnary for interned string names */
621     xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
622     int options;
623     xmlSchemaValidCtxtPtr vctxt;
624     int isS4S;
625     int isRedefine;
626     int xsiAssemble;
627     int stop; /* If the parser should stop; i.e. a critical error. */
628     const xmlChar *targetNamespace;
629     xmlSchemaBucketPtr redefined; /* The schema to be redefined. */
630
631     xmlSchemaRedefPtr redef; /* Used for redefinitions. */
632     int redefCounter; /* Used for redefinitions. */
633     xmlSchemaItemListPtr attrProhibs;
634 };
635
636 /**
637  * xmlSchemaQNameRef:
638  *
639  * A component reference item (not a schema component)
640  * (Extends xmlSchemaBasicItem)
641  */
642 typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
643 typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
644 struct _xmlSchemaQNameRef {
645     xmlSchemaTypeType type;
646     xmlSchemaBasicItemPtr item; /* The resolved referenced item. */
647     xmlSchemaTypeType itemType;
648     const xmlChar *name;
649     const xmlChar *targetNamespace;
650     xmlNodePtr node;
651 };
652
653 /**
654  * xmlSchemaParticle:
655  *
656  * A particle component.
657  * (Extends xmlSchemaTreeItem)
658  */
659 typedef struct _xmlSchemaParticle xmlSchemaParticle;
660 typedef xmlSchemaParticle *xmlSchemaParticlePtr;
661 struct _xmlSchemaParticle {
662     xmlSchemaTypeType type;
663     xmlSchemaAnnotPtr annot;
664     xmlSchemaTreeItemPtr next; /* next particle */
665     xmlSchemaTreeItemPtr children; /* the "term" (e.g. a model group,
666         a group definition, a XML_SCHEMA_EXTRA_QNAMEREF (if a reference),
667         etc.) */
668     int minOccurs;
669     int maxOccurs;
670     xmlNodePtr node;
671 };
672
673 /**
674  * xmlSchemaModelGroup:
675  *
676  * A model group component.
677  * (Extends xmlSchemaTreeItem)
678  */
679 typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
680 typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
681 struct _xmlSchemaModelGroup {
682     xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
683     xmlSchemaAnnotPtr annot;
684     xmlSchemaTreeItemPtr next; /* not used */
685     xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
686     xmlNodePtr node;
687 };
688
689 #define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
690 #define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1
691 /**
692  * xmlSchemaModelGroupDef:
693  *
694  * A model group definition component.
695  * (Extends xmlSchemaTreeItem)
696  */
697 typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
698 typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
699 struct _xmlSchemaModelGroupDef {
700     xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
701     xmlSchemaAnnotPtr annot;
702     xmlSchemaTreeItemPtr next; /* not used */
703     xmlSchemaTreeItemPtr children; /* the "model group" */
704     const xmlChar *name;
705     const xmlChar *targetNamespace;
706     xmlNodePtr node;
707     int flags;
708 };
709
710 typedef struct _xmlSchemaIDC xmlSchemaIDC;
711 typedef xmlSchemaIDC *xmlSchemaIDCPtr;
712
713 /**
714  * xmlSchemaIDCSelect:
715  *
716  * The identity-constraint "field" and "selector" item, holding the
717  * XPath expression.
718  */
719 typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
720 typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
721 struct _xmlSchemaIDCSelect {
722     xmlSchemaIDCSelectPtr next;
723     xmlSchemaIDCPtr idc;
724     int index; /* an index position if significant for IDC key-sequences */
725     const xmlChar *xpath; /* the XPath expression */
726     void *xpathComp; /* the compiled XPath expression */
727 };
728
729 /**
730  * xmlSchemaIDC:
731  *
732  * The identity-constraint definition component.
733  * (Extends xmlSchemaAnnotItem)
734  */
735
736 struct _xmlSchemaIDC {
737     xmlSchemaTypeType type;
738     xmlSchemaAnnotPtr annot;
739     xmlSchemaIDCPtr next;
740     xmlNodePtr node;
741     const xmlChar *name;
742     const xmlChar *targetNamespace;
743     xmlSchemaIDCSelectPtr selector;
744     xmlSchemaIDCSelectPtr fields;
745     int nbFields;
746     xmlSchemaQNameRefPtr ref;
747 };
748
749 /**
750  * xmlSchemaIDCAug:
751  *
752  * The augmented IDC information used for validation.
753  */
754 typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
755 typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
756 struct _xmlSchemaIDCAug {
757     xmlSchemaIDCAugPtr next; /* next in a list */
758     xmlSchemaIDCPtr def; /* the IDC definition */
759     int keyrefDepth; /* the lowest tree level to which IDC
760                         tables need to be bubbled upwards */
761 };
762
763 /**
764  * xmlSchemaPSVIIDCKeySequence:
765  *
766  * The key sequence of a node table item.
767  */
768 typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
769 typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
770 struct _xmlSchemaPSVIIDCKey {
771     xmlSchemaTypePtr type;
772     xmlSchemaValPtr val;
773 };
774
775 /**
776  * xmlSchemaPSVIIDCNode:
777  *
778  * The node table item of a node table.
779  */
780 typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
781 typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
782 struct _xmlSchemaPSVIIDCNode {
783     xmlNodePtr node;
784     xmlSchemaPSVIIDCKeyPtr *keys;
785     int nodeLine;
786     int nodeQNameID;
787
788 };
789
790 /**
791  * xmlSchemaPSVIIDCBinding:
792  *
793  * The identity-constraint binding item of the [identity-constraint table].
794  */
795 typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
796 typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
797 struct _xmlSchemaPSVIIDCBinding {
798     xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
799     xmlSchemaIDCPtr definition; /* the IDC definition */
800     xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
801     int nbNodes; /* number of entries in the node table */
802     int sizeNodes; /* size of the node table */
803     xmlSchemaItemListPtr dupls;
804 };
805
806
807 #define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
808 #define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
809
810 #define XPATH_STATE_OBJ_MATCHES -2
811 #define XPATH_STATE_OBJ_BLOCKED -3
812
813 typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
814 typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
815
816 /**
817  * xmlSchemaIDCStateObj:
818  *
819  * The state object used to evaluate XPath expressions.
820  */
821 typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
822 typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
823 struct _xmlSchemaIDCStateObj {
824     int type;
825     xmlSchemaIDCStateObjPtr next; /* next if in a list */
826     int depth; /* depth of creation */
827     int *history; /* list of (depth, state-id) tuples */
828     int nbHistory;
829     int sizeHistory;
830     xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
831                                        matcher */
832     xmlSchemaIDCSelectPtr sel;
833     void *xpathCtxt;
834 };
835
836 #define IDC_MATCHER 0
837
838 /**
839  * xmlSchemaIDCMatcher:
840  *
841  * Used to evaluate IDC selectors (and fields).
842  */
843 struct _xmlSchemaIDCMatcher {
844     int type;
845     int depth; /* the tree depth at creation time */
846     xmlSchemaIDCMatcherPtr next; /* next in the list */
847     xmlSchemaIDCMatcherPtr nextCached; /* next in the cache list */
848     xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
849     int idcType;
850     xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
851                                          elements */
852     int sizeKeySeqs;
853     xmlSchemaItemListPtr targets; /* list of target-node
854                                      (xmlSchemaPSVIIDCNodePtr) entries */
855 };
856
857 /*
858 * Element info flags.
859 */
860 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES  1<<0
861 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
862 #define XML_SCHEMA_ELEM_INFO_NILLED            1<<2
863 #define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE        1<<3
864
865 #define XML_SCHEMA_NODE_INFO_VALUE_NEEDED      1<<4
866 #define XML_SCHEMA_ELEM_INFO_EMPTY             1<<5
867 #define XML_SCHEMA_ELEM_INFO_HAS_CONTENT       1<<6
868
869 #define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT  1<<7
870 #define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT  1<<8
871 #define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED  1<<9
872 #define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE  1<<10
873
874 /**
875  * xmlSchemaNodeInfo:
876  *
877  * Holds information of an element node.
878  */
879 struct _xmlSchemaNodeInfo {
880     int nodeType;
881     xmlNodePtr node;
882     int nodeLine;
883     const xmlChar *localName;
884     const xmlChar *nsName;
885     const xmlChar *value;
886     xmlSchemaValPtr val; /* the pre-computed value if any */
887     xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
888
889     int flags; /* combination of node info flags */
890
891     int valNeeded;
892     int normVal;
893
894     xmlSchemaElementPtr decl; /* the element/attribute declaration */
895     int depth;
896     xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
897                                             for the scope element*/
898     xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
899                                            element */
900     xmlRegExecCtxtPtr regexCtxt;
901
902     const xmlChar **nsBindings; /* Namespace bindings on this element */
903     int nbNsBindings;
904     int sizeNsBindings;
905
906     int hasKeyrefs;
907     int appliedXPath; /* Indicates that an XPath has been applied. */
908 };
909
910 #define XML_SCHEMAS_ATTR_UNKNOWN 1
911 #define XML_SCHEMAS_ATTR_ASSESSED 2
912 #define XML_SCHEMAS_ATTR_PROHIBITED 3
913 #define XML_SCHEMAS_ATTR_ERR_MISSING 4
914 #define XML_SCHEMAS_ATTR_INVALID_VALUE 5
915 #define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
916 #define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
917 #define XML_SCHEMAS_ATTR_DEFAULT 8
918 #define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
919 #define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
920 #define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
921 #define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
922 #define XML_SCHEMAS_ATTR_WILD_SKIP 13
923 #define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
924 #define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
925 #define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
926 #define XML_SCHEMAS_ATTR_META 17
927 /*
928 * @metaType values of xmlSchemaAttrInfo.
929 */
930 #define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
931 #define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
932 #define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
933 #define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
934 #define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
935
936 typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
937 typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
938 struct _xmlSchemaAttrInfo {
939     int nodeType;
940     xmlNodePtr node;
941     int nodeLine;
942     const xmlChar *localName;
943     const xmlChar *nsName;
944     const xmlChar *value;
945     xmlSchemaValPtr val; /* the pre-computed value if any */
946     xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
947     int flags; /* combination of node info flags */
948
949     xmlSchemaAttributePtr decl; /* the attribute declaration */
950     xmlSchemaAttributeUsePtr use;  /* the attribute use */
951     int state;
952     int metaType;
953     const xmlChar *vcValue; /* the value constraint value */
954     xmlSchemaNodeInfoPtr parent;
955 };
956
957
958 #define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
959 /**
960  * xmlSchemaValidCtxt:
961  *
962  * A Schemas validation context
963  */
964 struct _xmlSchemaValidCtxt {
965     int type;
966     void *errCtxt;             /* user specific data block */
967     xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */
968     xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
969     xmlStructuredErrorFunc serror;
970
971     xmlSchemaPtr schema;        /* The schema in use */
972     xmlDocPtr doc;
973     xmlParserInputBufferPtr input;
974     xmlCharEncoding enc;
975     xmlSAXHandlerPtr sax;
976     xmlParserCtxtPtr parserCtxt;
977     void *user_data; /* TODO: What is this for? */
978
979     int err;
980     int nberrors;
981
982     xmlNodePtr node;
983     xmlNodePtr cur;
984     /* xmlSchemaTypePtr type; */
985
986     xmlRegExecCtxtPtr regexp;
987     xmlSchemaValPtr value;
988
989     int valueWS;
990     int options;
991     xmlNodePtr validationRoot;
992     xmlSchemaParserCtxtPtr pctxt;
993     int xsiAssemble;
994
995     int depth;
996     xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
997     int sizeElemInfos;
998     xmlSchemaNodeInfoPtr inode; /* the current element information */
999
1000     xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
1001
1002     xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
1003     xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
1004     xmlSchemaIDCMatcherPtr idcMatcherCache; /* Cache for IDC matcher objects. */
1005
1006     xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
1007     int nbIdcNodes;
1008     int sizeIdcNodes;
1009
1010     xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
1011     int nbIdcKeys;
1012     int sizeIdcKeys;
1013
1014     int flags;
1015
1016     xmlDictPtr dict;
1017
1018 #ifdef LIBXML_READER_ENABLED
1019     xmlTextReaderPtr reader;
1020 #endif
1021
1022     xmlSchemaAttrInfoPtr *attrInfos;
1023     int nbAttrInfos;
1024     int sizeAttrInfos;
1025
1026     int skipDepth;
1027     xmlSchemaItemListPtr nodeQNames;
1028     int hasKeyrefs;
1029     int createIDCNodeTables;
1030     int psviExposeIDCNodeTables;
1031 };
1032
1033 /**
1034  * xmlSchemaSubstGroup:
1035  *
1036  *
1037  */
1038 typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
1039 typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
1040 struct _xmlSchemaSubstGroup {
1041     xmlSchemaElementPtr head;
1042     xmlSchemaItemListPtr members;
1043 };
1044
1045 /************************************************************************
1046  *                                                                      *
1047  *                      Some predeclarations                            *
1048  *                                                                      *
1049  ************************************************************************/
1050
1051 static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
1052                                  xmlSchemaPtr schema,
1053                                  xmlNodePtr node);
1054 static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
1055                                  xmlSchemaPtr schema,
1056                                  xmlNodePtr node);
1057 static int
1058 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
1059                    xmlSchemaAbstractCtxtPtr ctxt);
1060 static const xmlChar *
1061 xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
1062 static int
1063 xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1064                      xmlNodePtr node);
1065 static int
1066 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
1067                        xmlSchemaParserCtxtPtr ctxt);
1068 static void
1069 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
1070 static xmlSchemaWhitespaceValueType
1071 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
1072 static xmlSchemaTreeItemPtr
1073 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1074                          xmlNodePtr node, xmlSchemaTypeType type,
1075                          int withParticle);
1076 static const xmlChar *
1077 xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item);
1078 static xmlSchemaTypeLinkPtr
1079 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
1080 static void
1081 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1082                      const char *funcName,
1083                      const char *message);
1084 static int
1085 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt,
1086                              xmlSchemaTypePtr type,
1087                              xmlSchemaTypePtr baseType,
1088                              int subset);
1089 static void
1090 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
1091                                    xmlSchemaParserCtxtPtr ctxt);
1092 static void
1093 xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
1094 static xmlSchemaQNameRefPtr
1095 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
1096                                 xmlSchemaPtr schema,
1097                                 xmlNodePtr node);
1098
1099 /************************************************************************
1100  *                                                                      *
1101  *                      Helper functions                                *
1102  *                                                                      *
1103  ************************************************************************/
1104
1105 /**
1106  * xmlSchemaItemTypeToStr:
1107  * @type: the type of the schema item
1108  *
1109  * Returns the component name of a schema item.
1110  */
1111 static const xmlChar *
1112 xmlSchemaItemTypeToStr(xmlSchemaTypeType type)
1113 {
1114     switch (type) {
1115         case XML_SCHEMA_TYPE_BASIC:
1116             return(BAD_CAST "simple type definition");
1117         case XML_SCHEMA_TYPE_SIMPLE:
1118             return(BAD_CAST "simple type definition");
1119         case XML_SCHEMA_TYPE_COMPLEX:
1120             return(BAD_CAST "complex type definition");
1121         case XML_SCHEMA_TYPE_ELEMENT:
1122             return(BAD_CAST "element declaration");
1123         case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1124             return(BAD_CAST "attribute use");
1125         case XML_SCHEMA_TYPE_ATTRIBUTE:
1126             return(BAD_CAST "attribute declaration");
1127         case XML_SCHEMA_TYPE_GROUP:
1128             return(BAD_CAST "model group definition");
1129         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1130             return(BAD_CAST "attribute group definition");
1131         case XML_SCHEMA_TYPE_NOTATION:
1132             return(BAD_CAST "notation declaration");
1133         case XML_SCHEMA_TYPE_SEQUENCE:
1134             return(BAD_CAST "model group (sequence)");
1135         case XML_SCHEMA_TYPE_CHOICE:
1136             return(BAD_CAST "model group (choice)");
1137         case XML_SCHEMA_TYPE_ALL:
1138             return(BAD_CAST "model group (all)");
1139         case XML_SCHEMA_TYPE_PARTICLE:
1140             return(BAD_CAST "particle");
1141         case XML_SCHEMA_TYPE_IDC_UNIQUE:
1142             return(BAD_CAST "unique identity-constraint");
1143             /* return(BAD_CAST "IDC (unique)"); */
1144         case XML_SCHEMA_TYPE_IDC_KEY:
1145             return(BAD_CAST "key identity-constraint");
1146             /* return(BAD_CAST "IDC (key)"); */
1147         case XML_SCHEMA_TYPE_IDC_KEYREF:
1148             return(BAD_CAST "keyref identity-constraint");
1149             /* return(BAD_CAST "IDC (keyref)"); */
1150         case XML_SCHEMA_TYPE_ANY:
1151             return(BAD_CAST "wildcard (any)");
1152         case XML_SCHEMA_EXTRA_QNAMEREF:
1153             return(BAD_CAST "[helper component] QName reference");
1154         case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
1155             return(BAD_CAST "[helper component] attribute use prohibition");
1156         default:
1157             return(BAD_CAST "Not a schema component");
1158     }
1159 }
1160
1161 /**
1162  * xmlSchemaGetComponentTypeStr:
1163  * @type: the type of the schema item
1164  *
1165  * Returns the component name of a schema item.
1166  */
1167 static const xmlChar *
1168 xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)
1169 {
1170     switch (item->type) {
1171         case XML_SCHEMA_TYPE_BASIC:
1172             if (WXS_IS_COMPLEX(WXS_TYPE_CAST item))
1173                 return(BAD_CAST "complex type definition");
1174             else
1175                 return(BAD_CAST "simple type definition");
1176         default:
1177             return(xmlSchemaItemTypeToStr(item->type));
1178     }
1179 }
1180
1181 /**
1182  * xmlSchemaGetComponentNode:
1183  * @item: a schema component
1184  *
1185  * Returns node associated with the schema component.
1186  * NOTE that such a node need not be available; plus, a component's
1187  * node need not to reflect the component directly, since there is no
1188  * one-to-one relationship between the XML Schema representation and
1189  * the component representation.
1190  */
1191 static xmlNodePtr
1192 xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
1193 {
1194     switch (item->type) {
1195         case XML_SCHEMA_TYPE_ELEMENT:
1196             return (((xmlSchemaElementPtr) item)->node);
1197         case XML_SCHEMA_TYPE_ATTRIBUTE:
1198             return (((xmlSchemaAttributePtr) item)->node);
1199         case XML_SCHEMA_TYPE_COMPLEX:
1200         case XML_SCHEMA_TYPE_SIMPLE:
1201             return (((xmlSchemaTypePtr) item)->node);
1202         case XML_SCHEMA_TYPE_ANY:
1203         case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1204             return (((xmlSchemaWildcardPtr) item)->node);
1205         case XML_SCHEMA_TYPE_PARTICLE:
1206             return (((xmlSchemaParticlePtr) item)->node);
1207         case XML_SCHEMA_TYPE_SEQUENCE:
1208         case XML_SCHEMA_TYPE_CHOICE:
1209         case XML_SCHEMA_TYPE_ALL:
1210             return (((xmlSchemaModelGroupPtr) item)->node);
1211         case XML_SCHEMA_TYPE_GROUP:
1212             return (((xmlSchemaModelGroupDefPtr) item)->node);
1213         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1214             return (((xmlSchemaAttributeGroupPtr) item)->node);
1215         case XML_SCHEMA_TYPE_IDC_UNIQUE:
1216         case XML_SCHEMA_TYPE_IDC_KEY:
1217         case XML_SCHEMA_TYPE_IDC_KEYREF:
1218             return (((xmlSchemaIDCPtr) item)->node);
1219         case XML_SCHEMA_EXTRA_QNAMEREF:
1220             return(((xmlSchemaQNameRefPtr) item)->node);
1221         /* TODO: What to do with NOTATIONs?
1222         case XML_SCHEMA_TYPE_NOTATION:
1223             return (((xmlSchemaNotationPtr) item)->node);
1224         */
1225         case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1226             return (((xmlSchemaAttributeUsePtr) item)->node);
1227         default:
1228             return (NULL);
1229     }
1230 }
1231
1232 #if 0
1233 /**
1234  * xmlSchemaGetNextComponent:
1235  * @item: a schema component
1236  *
1237  * Returns the next sibling of the schema component.
1238  */
1239 static xmlSchemaBasicItemPtr
1240 xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1241 {
1242     switch (item->type) {
1243         case XML_SCHEMA_TYPE_ELEMENT:
1244             return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1245         case XML_SCHEMA_TYPE_ATTRIBUTE:
1246             return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1247         case XML_SCHEMA_TYPE_COMPLEX:
1248         case XML_SCHEMA_TYPE_SIMPLE:
1249             return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1250         case XML_SCHEMA_TYPE_ANY:
1251         case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1252             return (NULL);
1253         case XML_SCHEMA_TYPE_PARTICLE:
1254             return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1255         case XML_SCHEMA_TYPE_SEQUENCE:
1256         case XML_SCHEMA_TYPE_CHOICE:
1257         case XML_SCHEMA_TYPE_ALL:
1258             return (NULL);
1259         case XML_SCHEMA_TYPE_GROUP:
1260             return (NULL);
1261         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1262             return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1263         case XML_SCHEMA_TYPE_IDC_UNIQUE:
1264         case XML_SCHEMA_TYPE_IDC_KEY:
1265         case XML_SCHEMA_TYPE_IDC_KEYREF:
1266             return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1267         default:
1268             return (NULL);
1269     }
1270 }
1271 #endif
1272
1273
1274 /**
1275  * xmlSchemaFormatQName:
1276  * @buf: the string buffer
1277  * @namespaceName:  the namespace name
1278  * @localName: the local name
1279  *
1280  * Returns the given QName in the format "{namespaceName}localName" or
1281  * just "localName" if @namespaceName is NULL.
1282  *
1283  * Returns the localName if @namespaceName is NULL, a formatted
1284  * string otherwise.
1285  */
1286 static const xmlChar*
1287 xmlSchemaFormatQName(xmlChar **buf,
1288                      const xmlChar *namespaceName,
1289                      const xmlChar *localName)
1290 {
1291     FREE_AND_NULL(*buf)
1292     if (namespaceName != NULL) {
1293         *buf = xmlStrdup(BAD_CAST "{");
1294         *buf = xmlStrcat(*buf, namespaceName);
1295         *buf = xmlStrcat(*buf, BAD_CAST "}");
1296     }
1297     if (localName != NULL) {
1298         if (namespaceName == NULL)
1299             return(localName);
1300         *buf = xmlStrcat(*buf, localName);
1301     } else {
1302         *buf = xmlStrcat(*buf, BAD_CAST "(NULL)");
1303     }
1304     return ((const xmlChar *) *buf);
1305 }
1306
1307 static const xmlChar*
1308 xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
1309 {
1310     if (ns != NULL)
1311         return (xmlSchemaFormatQName(buf, ns->href, localName));
1312     else
1313         return (xmlSchemaFormatQName(buf, NULL, localName));
1314 }
1315
1316 static const xmlChar *
1317 xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1318 {
1319     switch (item->type) {
1320         case XML_SCHEMA_TYPE_ELEMENT:
1321             return (((xmlSchemaElementPtr) item)->name);
1322         case XML_SCHEMA_TYPE_ATTRIBUTE:
1323             return (((xmlSchemaAttributePtr) item)->name);
1324         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1325             return (((xmlSchemaAttributeGroupPtr) item)->name);
1326         case XML_SCHEMA_TYPE_BASIC:
1327         case XML_SCHEMA_TYPE_SIMPLE:
1328         case XML_SCHEMA_TYPE_COMPLEX:
1329             return (((xmlSchemaTypePtr) item)->name);
1330         case XML_SCHEMA_TYPE_GROUP:
1331             return (((xmlSchemaModelGroupDefPtr) item)->name);
1332         case XML_SCHEMA_TYPE_IDC_KEY:
1333         case XML_SCHEMA_TYPE_IDC_UNIQUE:
1334         case XML_SCHEMA_TYPE_IDC_KEYREF:
1335             return (((xmlSchemaIDCPtr) item)->name);
1336         case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1337             if (WXS_ATTRUSE_DECL(item) != NULL) {
1338                 return(xmlSchemaGetComponentName(
1339                     WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1340             } else
1341                 return(NULL);
1342         case XML_SCHEMA_EXTRA_QNAMEREF:
1343             return (((xmlSchemaQNameRefPtr) item)->name);
1344         case XML_SCHEMA_TYPE_NOTATION:
1345             return (((xmlSchemaNotationPtr) item)->name);
1346         default:
1347             /*
1348             * Other components cannot have names.
1349             */
1350             break;
1351     }
1352     return (NULL);
1353 }
1354
1355 #define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
1356 #define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
1357 /*
1358 static const xmlChar *
1359 xmlSchemaGetQNameRefName(void *ref)
1360 {
1361     return(((xmlSchemaQNameRefPtr) ref)->name);
1362 }
1363
1364 static const xmlChar *
1365 xmlSchemaGetQNameRefTargetNs(void *ref)
1366 {
1367     return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
1368 }
1369 */
1370
1371 static const xmlChar *
1372 xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1373 {
1374     switch (item->type) {
1375         case XML_SCHEMA_TYPE_ELEMENT:
1376             return (((xmlSchemaElementPtr) item)->targetNamespace);
1377         case XML_SCHEMA_TYPE_ATTRIBUTE:
1378             return (((xmlSchemaAttributePtr) item)->targetNamespace);
1379         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1380             return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1381         case XML_SCHEMA_TYPE_BASIC:
1382             return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1383         case XML_SCHEMA_TYPE_SIMPLE:
1384         case XML_SCHEMA_TYPE_COMPLEX:
1385             return (((xmlSchemaTypePtr) item)->targetNamespace);
1386         case XML_SCHEMA_TYPE_GROUP:
1387             return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1388         case XML_SCHEMA_TYPE_IDC_KEY:
1389         case XML_SCHEMA_TYPE_IDC_UNIQUE:
1390         case XML_SCHEMA_TYPE_IDC_KEYREF:
1391             return (((xmlSchemaIDCPtr) item)->targetNamespace);
1392         case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1393             if (WXS_ATTRUSE_DECL(item) != NULL) {
1394                 return(xmlSchemaGetComponentTargetNs(
1395                     WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1396             }
1397             /* TODO: Will returning NULL break something? */
1398             break;
1399         case XML_SCHEMA_EXTRA_QNAMEREF:
1400             return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
1401         case XML_SCHEMA_TYPE_NOTATION:
1402             return (((xmlSchemaNotationPtr) item)->targetNamespace);
1403         default:
1404             /*
1405             * Other components cannot have names.
1406             */
1407             break;
1408     }
1409     return (NULL);
1410 }
1411
1412 static const xmlChar*
1413 xmlSchemaGetComponentQName(xmlChar **buf,
1414                            void *item)
1415 {
1416     return (xmlSchemaFormatQName(buf,
1417         xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1418         xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1419 }
1420
1421 static const xmlChar*
1422 xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
1423 {
1424     xmlChar *str = NULL;
1425
1426     *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
1427     *buf = xmlStrcat(*buf, BAD_CAST " '");
1428     *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
1429         (xmlSchemaBasicItemPtr) item));
1430     *buf = xmlStrcat(*buf, BAD_CAST "'");
1431     FREE_AND_NULL(str);
1432     return(*buf);
1433 }
1434
1435 static const xmlChar*
1436 xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
1437 {
1438     return(xmlSchemaGetComponentDesignation(buf, idc));
1439 }
1440
1441 /**
1442  * xmlSchemaWildcardPCToString:
1443  * @pc: the type of processContents
1444  *
1445  * Returns a string representation of the type of
1446  * processContents.
1447  */
1448 static const xmlChar *
1449 xmlSchemaWildcardPCToString(int pc)
1450 {
1451     switch (pc) {
1452         case XML_SCHEMAS_ANY_SKIP:
1453             return (BAD_CAST "skip");
1454         case XML_SCHEMAS_ANY_LAX:
1455             return (BAD_CAST "lax");
1456         case XML_SCHEMAS_ANY_STRICT:
1457             return (BAD_CAST "strict");
1458         default:
1459             return (BAD_CAST "invalid process contents");
1460     }
1461 }
1462
1463 /**
1464  * xmlSchemaGetCanonValueWhtspExt:
1465  * @val: the precomputed value
1466  * @retValue: the returned value
1467  * @ws: the whitespace type of the value
1468  *
1469  * Get a the cononical representation of the value.
1470  * The caller has to free the returned retValue.
1471  *
1472  * Returns 0 if the value could be built and -1 in case of
1473  *         API errors or if the value type is not supported yet.
1474  */
1475 static int
1476 xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1477                                xmlSchemaWhitespaceValueType ws,
1478                                xmlChar **retValue)
1479 {
1480     int list;
1481     xmlSchemaValType valType;
1482     const xmlChar *value, *value2 = NULL;
1483
1484
1485     if ((retValue == NULL) || (val == NULL))
1486         return (-1);
1487     list = xmlSchemaValueGetNext(val) ? 1 : 0;
1488     *retValue = NULL;
1489     do {
1490         value = NULL;
1491         valType = xmlSchemaGetValType(val);
1492         switch (valType) {
1493             case XML_SCHEMAS_STRING:
1494             case XML_SCHEMAS_NORMSTRING:
1495             case XML_SCHEMAS_ANYSIMPLETYPE:
1496                 value = xmlSchemaValueGetAsString(val);
1497                 if (value != NULL) {
1498                     if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1499                         value2 = xmlSchemaCollapseString(value);
1500                     else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1501                         value2 = xmlSchemaWhiteSpaceReplace(value);
1502                     if (value2 != NULL)
1503                         value = value2;
1504                 }
1505                 break;
1506             default:
1507                 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1508                     if (value2 != NULL)
1509                         xmlFree((xmlChar *) value2);
1510                     goto internal_error;
1511                 }
1512                 value = value2;
1513         }
1514         if (*retValue == NULL)
1515             if (value == NULL) {
1516                 if (! list)
1517                     *retValue = xmlStrdup(BAD_CAST "");
1518             } else
1519                 *retValue = xmlStrdup(value);
1520         else if (value != NULL) {
1521             /* List. */
1522             *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1523             *retValue = xmlStrcat((xmlChar *) *retValue, value);
1524         }
1525         FREE_AND_NULL(value2)
1526         val = xmlSchemaValueGetNext(val);
1527     } while (val != NULL);
1528
1529     return (0);
1530 internal_error:
1531     if (*retValue != NULL)
1532         xmlFree((xmlChar *) (*retValue));
1533     if (value2 != NULL)
1534         xmlFree((xmlChar *) value2);
1535     return (-1);
1536 }
1537
1538 /**
1539  * xmlSchemaFormatItemForReport:
1540  * @buf: the string buffer
1541  * @itemDes: the designation of the item
1542  * @itemName: the name of the item
1543  * @item: the item as an object
1544  * @itemNode: the node of the item
1545  * @local: the local name
1546  * @parsing: if the function is used during the parse
1547  *
1548  * Returns a representation of the given item used
1549  * for error reports.
1550  *
1551  * The following order is used to build the resulting
1552  * designation if the arguments are not NULL:
1553  * 1a. If itemDes not NULL -> itemDes
1554  * 1b. If (itemDes not NULL) and (itemName not NULL)
1555  *     -> itemDes + itemName
1556  * 2. If the preceding was NULL and (item not NULL) -> item
1557  * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1558  *
1559  * If the itemNode is an attribute node, the name of the attribute
1560  * will be appended to the result.
1561  *
1562  * Returns the formatted string and sets @buf to the resulting value.
1563  */
1564 static xmlChar*
1565 xmlSchemaFormatItemForReport(xmlChar **buf,
1566                      const xmlChar *itemDes,
1567                      xmlSchemaBasicItemPtr item,
1568                      xmlNodePtr itemNode)
1569 {
1570     xmlChar *str = NULL;
1571     int named = 1;
1572
1573     if (*buf != NULL) {
1574         xmlFree(*buf);
1575         *buf = NULL;
1576     }
1577
1578     if (itemDes != NULL) {
1579         *buf = xmlStrdup(itemDes);
1580     } else if (item != NULL) {
1581         switch (item->type) {
1582         case XML_SCHEMA_TYPE_BASIC: {
1583             xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1584
1585             if (WXS_IS_ATOMIC(type))
1586                 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1587             else if (WXS_IS_LIST(type))
1588                 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
1589             else if (WXS_IS_UNION(type))
1590                 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1591             else
1592                 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1593             *buf = xmlStrcat(*buf, type->name);
1594             *buf = xmlStrcat(*buf, BAD_CAST "'");
1595             }
1596             break;
1597         case XML_SCHEMA_TYPE_SIMPLE: {
1598             xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1599
1600             if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1601                 *buf = xmlStrdup(BAD_CAST"");
1602             } else {
1603                 *buf = xmlStrdup(BAD_CAST "local ");
1604             }
1605             if (WXS_IS_ATOMIC(type))
1606                 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1607             else if (WXS_IS_LIST(type))
1608                 *buf = xmlStrcat(*buf, BAD_CAST "list type");
1609             else if (WXS_IS_UNION(type))
1610                 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1611             else
1612                 *buf = xmlStrcat(*buf, BAD_CAST "simple type");
1613             if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1614                 *buf = xmlStrcat(*buf, BAD_CAST " '");
1615                 *buf = xmlStrcat(*buf, type->name);
1616                 *buf = xmlStrcat(*buf, BAD_CAST "'");
1617             }
1618             }
1619             break;
1620         case XML_SCHEMA_TYPE_COMPLEX: {
1621             xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1622
1623             if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
1624                 *buf = xmlStrdup(BAD_CAST "");
1625             else
1626                 *buf = xmlStrdup(BAD_CAST "local ");
1627             *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1628             if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1629                 *buf = xmlStrcat(*buf, BAD_CAST " '");
1630                 *buf = xmlStrcat(*buf, type->name);
1631                 *buf = xmlStrcat(*buf, BAD_CAST "'");
1632             }
1633             }
1634             break;
1635         case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
1636                 xmlSchemaAttributeUsePtr ause;
1637
1638                 ause = WXS_ATTR_USE_CAST item;
1639                 *buf = xmlStrdup(BAD_CAST "attribute use ");
1640                 if (WXS_ATTRUSE_DECL(ause) != NULL) {
1641                     *buf = xmlStrcat(*buf, BAD_CAST "'");
1642                     *buf = xmlStrcat(*buf,
1643                         xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
1644                     FREE_AND_NULL(str)
1645                         *buf = xmlStrcat(*buf, BAD_CAST "'");
1646                 } else {
1647                     *buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
1648                 }
1649             }
1650             break;
1651         case XML_SCHEMA_TYPE_ATTRIBUTE: {
1652                 xmlSchemaAttributePtr attr;
1653
1654                 attr = (xmlSchemaAttributePtr) item;
1655                 *buf = xmlStrdup(BAD_CAST "attribute decl.");
1656                 *buf = xmlStrcat(*buf, BAD_CAST " '");
1657                 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1658                     attr->targetNamespace, attr->name));
1659                 FREE_AND_NULL(str)
1660                     *buf = xmlStrcat(*buf, BAD_CAST "'");
1661             }
1662             break;
1663         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1664             xmlSchemaGetComponentDesignation(buf, item);
1665             break;
1666         case XML_SCHEMA_TYPE_ELEMENT: {
1667                 xmlSchemaElementPtr elem;
1668
1669                 elem = (xmlSchemaElementPtr) item;
1670                 *buf = xmlStrdup(BAD_CAST "element decl.");
1671                 *buf = xmlStrcat(*buf, BAD_CAST " '");
1672                 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1673                     elem->targetNamespace, elem->name));
1674                 *buf = xmlStrcat(*buf, BAD_CAST "'");
1675             }
1676             break;
1677         case XML_SCHEMA_TYPE_IDC_UNIQUE:
1678         case XML_SCHEMA_TYPE_IDC_KEY:
1679         case XML_SCHEMA_TYPE_IDC_KEYREF:
1680             if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1681                 *buf = xmlStrdup(BAD_CAST "unique '");
1682             else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1683                 *buf = xmlStrdup(BAD_CAST "key '");
1684             else
1685                 *buf = xmlStrdup(BAD_CAST "keyRef '");
1686             *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1687             *buf = xmlStrcat(*buf, BAD_CAST "'");
1688             break;
1689         case XML_SCHEMA_TYPE_ANY:
1690         case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1691             *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1692                     ((xmlSchemaWildcardPtr) item)->processContents));
1693             *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1694             break;
1695         case XML_SCHEMA_FACET_MININCLUSIVE:
1696         case XML_SCHEMA_FACET_MINEXCLUSIVE:
1697         case XML_SCHEMA_FACET_MAXINCLUSIVE:
1698         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1699         case XML_SCHEMA_FACET_TOTALDIGITS:
1700         case XML_SCHEMA_FACET_FRACTIONDIGITS:
1701         case XML_SCHEMA_FACET_PATTERN:
1702         case XML_SCHEMA_FACET_ENUMERATION:
1703         case XML_SCHEMA_FACET_WHITESPACE:
1704         case XML_SCHEMA_FACET_LENGTH:
1705         case XML_SCHEMA_FACET_MAXLENGTH:
1706         case XML_SCHEMA_FACET_MINLENGTH:
1707             *buf = xmlStrdup(BAD_CAST "facet '");
1708             *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1709             *buf = xmlStrcat(*buf, BAD_CAST "'");
1710             break;
1711         case XML_SCHEMA_TYPE_GROUP: {
1712                 *buf = xmlStrdup(BAD_CAST "model group def.");
1713                 *buf = xmlStrcat(*buf, BAD_CAST " '");
1714                 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1715                 *buf = xmlStrcat(*buf, BAD_CAST "'");
1716                 FREE_AND_NULL(str)
1717             }
1718             break;
1719         case XML_SCHEMA_TYPE_SEQUENCE:
1720         case XML_SCHEMA_TYPE_CHOICE:
1721         case XML_SCHEMA_TYPE_ALL:
1722         case XML_SCHEMA_TYPE_PARTICLE:
1723             *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1724             break;
1725         case XML_SCHEMA_TYPE_NOTATION: {
1726                 *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1727                 *buf = xmlStrcat(*buf, BAD_CAST " '");
1728                 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1729                 *buf = xmlStrcat(*buf, BAD_CAST "'");
1730                 FREE_AND_NULL(str);
1731             }
1732         default:
1733             named = 0;
1734         }
1735     } else
1736         named = 0;
1737
1738     if ((named == 0) && (itemNode != NULL)) {
1739         xmlNodePtr elem;
1740
1741         if (itemNode->type == XML_ATTRIBUTE_NODE)
1742             elem = itemNode->parent;
1743         else
1744             elem = itemNode;
1745         *buf = xmlStrdup(BAD_CAST "Element '");
1746         if (elem->ns != NULL) {
1747             *buf = xmlStrcat(*buf,
1748                 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1749             FREE_AND_NULL(str)
1750         } else
1751             *buf = xmlStrcat(*buf, elem->name);
1752         *buf = xmlStrcat(*buf, BAD_CAST "'");
1753
1754     }
1755     if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1756         *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1757         if (itemNode->ns != NULL) {
1758             *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1759                 itemNode->ns->href, itemNode->name));
1760             FREE_AND_NULL(str)
1761         } else
1762             *buf = xmlStrcat(*buf, itemNode->name);
1763         *buf = xmlStrcat(*buf, BAD_CAST "'");
1764     }
1765     FREE_AND_NULL(str)
1766
1767     return (*buf);
1768 }
1769
1770 /**
1771  * xmlSchemaFormatFacetEnumSet:
1772  * @buf: the string buffer
1773  * @type: the type holding the enumeration facets
1774  *
1775  * Builds a string consisting of all enumeration elements.
1776  *
1777  * Returns a string of all enumeration elements.
1778  */
1779 static const xmlChar *
1780 xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1781                             xmlChar **buf, xmlSchemaTypePtr type)
1782 {
1783     xmlSchemaFacetPtr facet;
1784     xmlSchemaWhitespaceValueType ws;
1785     xmlChar *value = NULL;
1786     int res, found = 0;
1787
1788     if (*buf != NULL)
1789         xmlFree(*buf);
1790     *buf = NULL;
1791
1792     do {
1793         /*
1794         * Use the whitespace type of the base type.
1795         */
1796         ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1797         for (facet = type->facets; facet != NULL; facet = facet->next) {
1798             if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1799                 continue;
1800             found = 1;
1801             res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1802                 ws, &value);
1803             if (res == -1) {
1804                 xmlSchemaInternalErr(actxt,
1805                     "xmlSchemaFormatFacetEnumSet",
1806                     "compute the canonical lexical representation");
1807                 if (*buf != NULL)
1808                     xmlFree(*buf);
1809                 *buf = NULL;
1810                 return (NULL);
1811             }
1812             if (*buf == NULL)
1813                 *buf = xmlStrdup(BAD_CAST "'");
1814             else
1815                 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1816             *buf = xmlStrcat(*buf, BAD_CAST value);
1817             *buf = xmlStrcat(*buf, BAD_CAST "'");
1818             if (value != NULL) {
1819                 xmlFree((xmlChar *)value);
1820                 value = NULL;
1821             }
1822         }
1823         /*
1824         * The enumeration facet of a type restricts the enumeration
1825         * facet of the ancestor type; i.e., such restricted enumerations
1826         * do not belong to the set of the given type. Thus we break
1827         * on the first found enumeration.
1828         */
1829         if (found)
1830             break;
1831         type = type->baseType;
1832     } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1833
1834     return ((const xmlChar *) *buf);
1835 }
1836
1837 /************************************************************************
1838  *                                                                      *
1839  *                      Error functions                                 *
1840  *                                                                      *
1841  ************************************************************************/
1842
1843 #if 0
1844 static void
1845 xmlSchemaErrMemory(const char *msg)
1846 {
1847     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1848                      msg);
1849 }
1850 #endif
1851
1852 static void
1853 xmlSchemaPSimpleErr(const char *msg)
1854 {
1855     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1856                      msg);
1857 }
1858
1859 /**
1860  * xmlSchemaPErrMemory:
1861  * @node: a context node
1862  * @extra:  extra informations
1863  *
1864  * Handle an out of memory condition
1865  */
1866 static void
1867 xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1868                     const char *extra, xmlNodePtr node)
1869 {
1870     if (ctxt != NULL)
1871         ctxt->nberrors++;
1872     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1873                      extra);
1874 }
1875
1876 /**
1877  * xmlSchemaPErr:
1878  * @ctxt: the parsing context
1879  * @node: the context node
1880  * @error: the error code
1881  * @msg: the error message
1882  * @str1: extra data
1883  * @str2: extra data
1884  *
1885  * Handle a parser error
1886  */
1887 static void
1888 xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1889               const char *msg, const xmlChar * str1, const xmlChar * str2)
1890 {
1891     xmlGenericErrorFunc channel = NULL;
1892     xmlStructuredErrorFunc schannel = NULL;
1893     void *data = NULL;
1894
1895     if (ctxt != NULL) {
1896         ctxt->nberrors++;
1897         ctxt->err = error;
1898         channel = ctxt->error;
1899         data = ctxt->errCtxt;
1900         schannel = ctxt->serror;
1901     }
1902     __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1903                     error, XML_ERR_ERROR, NULL, 0,
1904                     (const char *) str1, (const char *) str2, NULL, 0, 0,
1905                     msg, str1, str2);
1906 }
1907
1908 /**
1909  * xmlSchemaPErr2:
1910  * @ctxt: the parsing context
1911  * @node: the context node
1912  * @node: the current child
1913  * @error: the error code
1914  * @msg: the error message
1915  * @str1: extra data
1916  * @str2: extra data
1917  *
1918  * Handle a parser error
1919  */
1920 static void
1921 xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1922                xmlNodePtr child, int error,
1923                const char *msg, const xmlChar * str1, const xmlChar * str2)
1924 {
1925     if (child != NULL)
1926         xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1927     else
1928         xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1929 }
1930
1931
1932 /**
1933  * xmlSchemaPErrExt:
1934  * @ctxt: the parsing context
1935  * @node: the context node
1936  * @error: the error code
1937  * @strData1: extra data
1938  * @strData2: extra data
1939  * @strData3: extra data
1940  * @msg: the message
1941  * @str1:  extra parameter for the message display
1942  * @str2:  extra parameter for the message display
1943  * @str3:  extra parameter for the message display
1944  * @str4:  extra parameter for the message display
1945  * @str5:  extra parameter for the message display
1946  *
1947  * Handle a parser error
1948  */
1949 static void
1950 xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1951                 const xmlChar * strData1, const xmlChar * strData2,
1952                 const xmlChar * strData3, const char *msg, const xmlChar * str1,
1953                 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1954                 const xmlChar * str5)
1955 {
1956
1957     xmlGenericErrorFunc channel = NULL;
1958     xmlStructuredErrorFunc schannel = NULL;
1959     void *data = NULL;
1960
1961     if (ctxt != NULL) {
1962         ctxt->nberrors++;
1963         ctxt->err = error;
1964         channel = ctxt->error;
1965         data = ctxt->errCtxt;
1966         schannel = ctxt->serror;
1967     }
1968     __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1969                     error, XML_ERR_ERROR, NULL, 0,
1970                     (const char *) strData1, (const char *) strData2,
1971                     (const char *) strData3, 0, 0, msg, str1, str2,
1972                     str3, str4, str5);
1973 }
1974
1975 /************************************************************************
1976  *                                                                      *
1977  *                      Allround error functions                        *
1978  *                                                                      *
1979  ************************************************************************/
1980
1981 /**
1982  * xmlSchemaVTypeErrMemory:
1983  * @node: a context node
1984  * @extra:  extra informations
1985  *
1986  * Handle an out of memory condition
1987  */
1988 static void
1989 xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
1990                     const char *extra, xmlNodePtr node)
1991 {
1992     if (ctxt != NULL) {
1993         ctxt->nberrors++;
1994         ctxt->err = XML_SCHEMAV_INTERNAL;
1995     }
1996     __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
1997                      extra);
1998 }
1999
2000 static void
2001 xmlSchemaPSimpleInternalErr(xmlNodePtr node,
2002                             const char *msg, const xmlChar *str)
2003 {
2004      __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node,
2005          msg, (const char *) str);
2006 }
2007
2008 #define WXS_ERROR_TYPE_ERROR 1
2009 #define WXS_ERROR_TYPE_WARNING 2
2010 /**
2011  * xmlSchemaErr3:
2012  * @ctxt: the validation context
2013  * @node: the context node
2014  * @error: the error code
2015  * @msg: the error message
2016  * @str1: extra data
2017  * @str2: extra data
2018  * @str3: extra data
2019  *
2020  * Handle a validation error
2021  */
2022 static void
2023 xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
2024                   xmlErrorLevel errorLevel,
2025                   int error, xmlNodePtr node, int line, const char *msg,
2026                   const xmlChar *str1, const xmlChar *str2,
2027                   const xmlChar *str3, const xmlChar *str4)
2028 {
2029     xmlStructuredErrorFunc schannel = NULL;
2030     xmlGenericErrorFunc channel = NULL;
2031     void *data = NULL;
2032
2033     if (ctxt != NULL) {
2034         if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2035             xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
2036             const char *file = NULL;
2037             if (errorLevel != XML_ERR_WARNING) {
2038                 vctxt->nberrors++;
2039                 vctxt->err = error;
2040                 channel = vctxt->error;
2041             } else {
2042                 channel = vctxt->warning;
2043             }
2044             schannel = vctxt->serror;
2045             data = vctxt->errCtxt;
2046
2047             /*
2048             * Error node. If we specify a line number, then
2049             * do not channel any node to the error function.
2050             */
2051             if (line == 0) {
2052                 if ((node == NULL) &&
2053                     (vctxt->depth >= 0) &&
2054                     (vctxt->inode != NULL)) {
2055                     node = vctxt->inode->node;
2056                 }
2057                 /*
2058                 * Get filename and line if no node-tree.
2059                 */
2060                 if ((node == NULL) &&
2061                     (vctxt->parserCtxt != NULL) &&
2062                     (vctxt->parserCtxt->input != NULL)) {
2063                     file = vctxt->parserCtxt->input->filename;
2064                     line = vctxt->parserCtxt->input->line;
2065                 }
2066             } else {
2067                 /*
2068                 * Override the given node's (if any) position
2069                 * and channel only the given line number.
2070                 */
2071                 node = NULL;
2072                 /*
2073                 * Get filename.
2074                 */
2075                 if (vctxt->doc != NULL)
2076                     file = (const char *) vctxt->doc->URL;
2077                 else if ((vctxt->parserCtxt != NULL) &&
2078                     (vctxt->parserCtxt->input != NULL))
2079                     file = vctxt->parserCtxt->input->filename;
2080             }
2081             __xmlRaiseError(schannel, channel, data, ctxt,
2082                 node, XML_FROM_SCHEMASV,
2083                 error, errorLevel, file, line,
2084                 (const char *) str1, (const char *) str2,
2085                 (const char *) str3, 0, 0, msg, str1, str2, str3, str4);
2086
2087         } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2088             xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
2089             if (errorLevel != XML_ERR_WARNING) {
2090                 pctxt->nberrors++;
2091                 pctxt->err = error;
2092                 channel = pctxt->error;
2093             } else {
2094                 channel = pctxt->warning;
2095             }
2096             schannel = pctxt->serror;
2097             data = pctxt->errCtxt;
2098             __xmlRaiseError(schannel, channel, data, ctxt,
2099                 node, XML_FROM_SCHEMASP, error,
2100                 errorLevel, NULL, 0,
2101                 (const char *) str1, (const char *) str2,
2102                 (const char *) str3, 0, 0, msg, str1, str2, str3, str4);
2103         } else {
2104             TODO
2105         }
2106     }
2107 }
2108
2109 /**
2110  * xmlSchemaErr3:
2111  * @ctxt: the validation context
2112  * @node: the context node
2113  * @error: the error code
2114  * @msg: the error message
2115  * @str1: extra data
2116  * @str2: extra data
2117  * @str3: extra data
2118  *
2119  * Handle a validation error
2120  */
2121 static void
2122 xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
2123               int error, xmlNodePtr node, const char *msg,
2124               const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
2125 {
2126     xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2127         msg, str1, str2, str3, NULL);
2128 }
2129
2130 static void
2131 xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
2132               int error, xmlNodePtr node, const char *msg,
2133               const xmlChar *str1, const xmlChar *str2,
2134               const xmlChar *str3, const xmlChar *str4)
2135 {
2136     xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2137         msg, str1, str2, str3, str4);
2138 }
2139
2140 static void
2141 xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2142              int error, xmlNodePtr node, const char *msg,
2143              const xmlChar *str1, const xmlChar *str2)
2144 {
2145     xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
2146 }
2147
2148 static xmlChar *
2149 xmlSchemaFormatNodeForError(xmlChar ** msg,
2150                             xmlSchemaAbstractCtxtPtr actxt,
2151                             xmlNodePtr node)
2152 {
2153     xmlChar *str = NULL;
2154
2155     *msg = NULL;
2156     if ((node != NULL) &&
2157         (node->type != XML_ELEMENT_NODE) &&
2158         (node->type != XML_ATTRIBUTE_NODE))
2159     {
2160         /*
2161         * Don't try to format other nodes than element and
2162         * attribute nodes.
2163         * Play save and return an empty string.
2164         */
2165         *msg = xmlStrdup(BAD_CAST "");
2166         return(*msg);
2167     }
2168     if (node != NULL) {
2169         /*
2170         * Work on tree nodes.
2171         */
2172         if (node->type == XML_ATTRIBUTE_NODE) {
2173             xmlNodePtr elem = node->parent;
2174
2175             *msg = xmlStrdup(BAD_CAST "Element '");
2176             if (elem->ns != NULL)
2177                 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2178                     elem->ns->href, elem->name));
2179             else
2180                 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2181                     NULL, elem->name));
2182             FREE_AND_NULL(str);
2183             *msg = xmlStrcat(*msg, BAD_CAST "', ");
2184             *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2185         } else {
2186             *msg = xmlStrdup(BAD_CAST "Element '");
2187         }
2188         if (node->ns != NULL)
2189             *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2190             node->ns->href, node->name));
2191         else
2192             *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2193             NULL, node->name));
2194         FREE_AND_NULL(str);
2195         *msg = xmlStrcat(*msg, BAD_CAST "': ");
2196     } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2197         xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2198         /*
2199         * Work on node infos.
2200         */
2201         if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2202             xmlSchemaNodeInfoPtr ielem =
2203                 vctxt->elemInfos[vctxt->depth];
2204
2205             *msg = xmlStrdup(BAD_CAST "Element '");
2206             *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2207                 ielem->nsName, ielem->localName));
2208             FREE_AND_NULL(str);
2209             *msg = xmlStrcat(*msg, BAD_CAST "', ");
2210             *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2211         } else {
2212             *msg = xmlStrdup(BAD_CAST "Element '");
2213         }
2214         *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2215             vctxt->inode->nsName, vctxt->inode->localName));
2216         FREE_AND_NULL(str);
2217         *msg = xmlStrcat(*msg, BAD_CAST "': ");
2218     } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
2219         /*
2220         * Hmm, no node while parsing?
2221         * Return an empty string, in case NULL will break something.
2222         */
2223         *msg = xmlStrdup(BAD_CAST "");
2224     } else {
2225         TODO
2226         return (NULL);
2227     }
2228     /*
2229     * VAL TODO: The output of the given schema component is currently
2230     * disabled.
2231     */
2232 #if 0
2233     if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2234         *msg = xmlStrcat(*msg, BAD_CAST " [");
2235         *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2236             NULL, type, NULL, 0));
2237         FREE_AND_NULL(str)
2238         *msg = xmlStrcat(*msg, BAD_CAST "]");
2239     }
2240 #endif
2241     return (*msg);
2242 }
2243
2244 static void
2245 xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
2246                      const char *funcName,
2247                      const char *message,
2248                      const xmlChar *str1,
2249                      const xmlChar *str2)
2250 {
2251     xmlChar *msg = NULL;
2252
2253     if (actxt == NULL)
2254         return;
2255     msg = xmlStrdup(BAD_CAST "Internal error: ");
2256     msg = xmlStrcat(msg, BAD_CAST funcName);
2257     msg = xmlStrcat(msg, BAD_CAST ", ");
2258     msg = xmlStrcat(msg, BAD_CAST message);
2259     msg = xmlStrcat(msg, BAD_CAST ".\n");
2260
2261     if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2262         xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
2263             (const char *) msg, str1, str2);
2264
2265     else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
2266         xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
2267             (const char *) msg, str1, str2);
2268
2269     FREE_AND_NULL(msg)
2270 }
2271
2272 static void
2273 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2274                      const char *funcName,
2275                      const char *message)
2276 {
2277     xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2278 }
2279
2280 #if 0
2281 static void
2282 xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2283                      const char *funcName,
2284                      const char *message,
2285                      const xmlChar *str1,
2286                      const xmlChar *str2)
2287 {
2288     xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
2289         str1, str2);
2290 }
2291 #endif
2292
2293 static void
2294 xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2295                    xmlParserErrors error,
2296                    xmlNodePtr node,
2297                    xmlSchemaBasicItemPtr item,
2298                    const char *message,
2299                    const xmlChar *str1, const xmlChar *str2,
2300                    const xmlChar *str3, const xmlChar *str4)
2301 {
2302     xmlChar *msg = NULL;
2303
2304     if ((node == NULL) && (item != NULL) &&
2305         (actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2306         node = WXS_ITEM_NODE(item);
2307         xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2308         msg = xmlStrcat(msg, BAD_CAST ": ");
2309     } else
2310         xmlSchemaFormatNodeForError(&msg, actxt, node);
2311     msg = xmlStrcat(msg, (const xmlChar *) message);
2312     msg = xmlStrcat(msg, BAD_CAST ".\n");
2313     xmlSchemaErr4(actxt, error, node,
2314         (const char *) msg, str1, str2, str3, str4);
2315     FREE_AND_NULL(msg)
2316 }
2317
2318 static void
2319 xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2320                    xmlParserErrors error,
2321                    xmlNodePtr node,
2322                    xmlSchemaBasicItemPtr item,
2323                    const char *message,
2324                    const xmlChar *str1,
2325                    const xmlChar *str2)
2326 {
2327     xmlSchemaCustomErr4(actxt, error, node, item,
2328         message, str1, str2, NULL, NULL);
2329 }
2330
2331
2332
2333 static void
2334 xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2335                    xmlParserErrors error,
2336                    xmlNodePtr node,
2337                    xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2338                    const char *message,
2339                    const xmlChar *str1,
2340                    const xmlChar *str2,
2341                    const xmlChar *str3)
2342 {
2343     xmlChar *msg = NULL;
2344
2345     xmlSchemaFormatNodeForError(&msg, actxt, node);
2346     msg = xmlStrcat(msg, (const xmlChar *) message);
2347     msg = xmlStrcat(msg, BAD_CAST ".\n");
2348
2349     /* URGENT TODO: Set the error code to something sane. */
2350     xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2351         (const char *) msg, str1, str2, str3, NULL);
2352
2353     FREE_AND_NULL(msg)
2354 }
2355
2356
2357
2358 static void
2359 xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2360                    xmlParserErrors error,
2361                    xmlSchemaPSVIIDCNodePtr idcNode,
2362                    xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2363                    const char *message,
2364                    const xmlChar *str1,
2365                    const xmlChar *str2)
2366 {
2367     xmlChar *msg = NULL, *qname = NULL;
2368
2369     msg = xmlStrdup(BAD_CAST "Element '%s': ");
2370     msg = xmlStrcat(msg, (const xmlChar *) message);
2371     msg = xmlStrcat(msg, BAD_CAST ".\n");
2372     xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
2373         error, NULL, idcNode->nodeLine, (const char *) msg,
2374         xmlSchemaFormatQName(&qname,
2375             vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2376             vctxt->nodeQNames->items[idcNode->nodeQNameID]),
2377         str1, str2, NULL);
2378     FREE_AND_NULL(qname);
2379     FREE_AND_NULL(msg);
2380 }
2381
2382 static int
2383 xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2384                            xmlNodePtr node)
2385 {
2386     if (node != NULL)
2387         return (node->type);
2388     if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2389         (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2390         return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2391     return (-1);
2392 }
2393
2394 static int
2395 xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2396 {
2397     switch (item->type) {
2398         case XML_SCHEMA_TYPE_COMPLEX:
2399         case XML_SCHEMA_TYPE_SIMPLE:
2400             if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2401                 return(1);
2402             break;
2403         case XML_SCHEMA_TYPE_GROUP:
2404             return (1);
2405         case XML_SCHEMA_TYPE_ELEMENT:
2406             if ( ((xmlSchemaElementPtr) item)->flags &
2407                 XML_SCHEMAS_ELEM_GLOBAL)
2408                 return(1);
2409             break;
2410         case XML_SCHEMA_TYPE_ATTRIBUTE:
2411             if ( ((xmlSchemaAttributePtr) item)->flags &
2412                 XML_SCHEMAS_ATTR_GLOBAL)
2413                 return(1);
2414             break;
2415         /* Note that attribute groups are always global. */
2416         default:
2417             return(1);
2418     }
2419     return (0);
2420 }
2421
2422 static void
2423 xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2424                        xmlParserErrors error,
2425                        xmlNodePtr node,
2426                        const xmlChar *value,
2427                        xmlSchemaTypePtr type,
2428                        int displayValue)
2429 {
2430     xmlChar *msg = NULL;
2431
2432     xmlSchemaFormatNodeForError(&msg, actxt, node);
2433
2434     if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2435             XML_ATTRIBUTE_NODE))
2436         msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2437     else
2438         msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2439             "value of ");
2440
2441     if (! xmlSchemaIsGlobalItem(type))
2442         msg = xmlStrcat(msg, BAD_CAST "the local ");
2443     else
2444         msg = xmlStrcat(msg, BAD_CAST "the ");
2445
2446     if (WXS_IS_ATOMIC(type))
2447         msg = xmlStrcat(msg, BAD_CAST "atomic type");
2448     else if (WXS_IS_LIST(type))
2449         msg = xmlStrcat(msg, BAD_CAST "list type");
2450     else if (WXS_IS_UNION(type))
2451         msg = xmlStrcat(msg, BAD_CAST "union type");
2452
2453     if (xmlSchemaIsGlobalItem(type)) {
2454         xmlChar *str = NULL;
2455         msg = xmlStrcat(msg, BAD_CAST " '");
2456         if (type->builtInType != 0) {
2457             msg = xmlStrcat(msg, BAD_CAST "xs:");
2458             msg = xmlStrcat(msg, type->name);
2459         } else
2460             msg = xmlStrcat(msg,
2461                 xmlSchemaFormatQName(&str,
2462                     type->targetNamespace, type->name));
2463         msg = xmlStrcat(msg, BAD_CAST "'");
2464         FREE_AND_NULL(str);
2465     }
2466     msg = xmlStrcat(msg, BAD_CAST ".\n");
2467     if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2468             XML_ATTRIBUTE_NODE))
2469         xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2470     else
2471         xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2472     FREE_AND_NULL(msg)
2473 }
2474
2475 static const xmlChar *
2476 xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2477                               xmlSchemaNodeInfoPtr ni,
2478                               xmlNodePtr node)
2479 {
2480     if (node != NULL) {
2481         if (node->ns != NULL)
2482             return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2483         else
2484             return (xmlSchemaFormatQName(str, NULL, node->name));
2485     } else if (ni != NULL)
2486         return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2487     return (NULL);
2488 }
2489
2490 static void
2491 xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2492                         xmlParserErrors error,
2493                         xmlSchemaAttrInfoPtr ni,
2494                         xmlNodePtr node)
2495 {
2496     xmlChar *msg = NULL, *str = NULL;
2497
2498     xmlSchemaFormatNodeForError(&msg, actxt, node);
2499     msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2500     xmlSchemaErr(actxt, error, node, (const char *) msg,
2501         xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2502         NULL);
2503     FREE_AND_NULL(str)
2504     FREE_AND_NULL(msg)
2505 }
2506
2507 static void
2508 xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2509                         xmlParserErrors error,
2510                         xmlNodePtr node,
2511                         xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2512                         const char *message,
2513                         int nbval,
2514                         int nbneg,
2515                         xmlChar **values)
2516 {
2517     xmlChar *str = NULL, *msg = NULL;
2518     xmlChar *localName, *nsName;
2519     const xmlChar *cur, *end;
2520     int i;
2521
2522     xmlSchemaFormatNodeForError(&msg, actxt, node);
2523     msg = xmlStrcat(msg, (const xmlChar *) message);
2524     msg = xmlStrcat(msg, BAD_CAST ".");
2525     /*
2526     * Note that is does not make sense to report that we have a
2527     * wildcard here, since the wildcard might be unfolded into
2528     * multiple transitions.
2529     */
2530     if (nbval + nbneg > 0) {
2531         if (nbval + nbneg > 1) {
2532             str = xmlStrdup(BAD_CAST " Expected is one of ( ");
2533         } else
2534             str = xmlStrdup(BAD_CAST " Expected is ( ");
2535         nsName = NULL;
2536
2537         for (i = 0; i < nbval + nbneg; i++) {
2538             cur = values[i];
2539             if (cur == NULL)
2540                 continue;
2541             if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2542                 (cur[3] == ' ')) {
2543                 cur += 4;
2544                 str = xmlStrcat(str, BAD_CAST "##other");
2545             }
2546             /*
2547             * Get the local name.
2548             */
2549             localName = NULL;
2550
2551             end = cur;
2552             if (*end == '*') {
2553                 localName = xmlStrdup(BAD_CAST "*");
2554                 end++;
2555             } else {
2556                 while ((*end != 0) && (*end != '|'))
2557                     end++;
2558                 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
2559             }
2560             if (*end != 0) {
2561                 end++;
2562                 /*
2563                 * Skip "*|*" if they come with negated expressions, since
2564                 * they represent the same negated wildcard.
2565                 */
2566                 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2567                     /*
2568                     * Get the namespace name.
2569                     */
2570                     cur = end;
2571                     if (*end == '*') {
2572                         nsName = xmlStrdup(BAD_CAST "{*}");
2573                     } else {
2574                         while (*end != 0)
2575                             end++;
2576
2577                         if (i >= nbval)
2578                             nsName = xmlStrdup(BAD_CAST "{##other:");
2579                         else
2580                             nsName = xmlStrdup(BAD_CAST "{");
2581
2582                         nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2583                         nsName = xmlStrcat(nsName, BAD_CAST "}");
2584                     }
2585                     str = xmlStrcat(str, BAD_CAST nsName);
2586                     FREE_AND_NULL(nsName)
2587                 } else {
2588                     FREE_AND_NULL(localName);
2589                     continue;
2590                 }
2591             }
2592             str = xmlStrcat(str, BAD_CAST localName);
2593             FREE_AND_NULL(localName);
2594
2595             if (i < nbval + nbneg -1)
2596                 str = xmlStrcat(str, BAD_CAST ", ");
2597         }
2598         str = xmlStrcat(str, BAD_CAST " ).\n");
2599         msg = xmlStrcat(msg, BAD_CAST str);
2600         FREE_AND_NULL(str)
2601     } else
2602       msg = xmlStrcat(msg, BAD_CAST "\n");
2603     xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2604     xmlFree(msg);
2605 }
2606
2607 static void
2608 xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2609                   xmlParserErrors error,
2610                   xmlNodePtr node,
2611                   const xmlChar *value,
2612                   unsigned long length,
2613                   xmlSchemaTypePtr type,
2614                   xmlSchemaFacetPtr facet,
2615                   const char *message,
2616                   const xmlChar *str1,
2617                   const xmlChar *str2)
2618 {
2619     xmlChar *str = NULL, *msg = NULL;
2620     xmlSchemaTypeType facetType;
2621     int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2622
2623     xmlSchemaFormatNodeForError(&msg, actxt, node);
2624     if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2625         facetType = XML_SCHEMA_FACET_ENUMERATION;
2626         /*
2627         * If enumerations are validated, one must not expect the
2628         * facet to be given.
2629         */
2630     } else
2631         facetType = facet->type;
2632     msg = xmlStrcat(msg, BAD_CAST "[");
2633     msg = xmlStrcat(msg, BAD_CAST "facet '");
2634     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2635     msg = xmlStrcat(msg, BAD_CAST "'] ");
2636     if (message == NULL) {
2637         /*
2638         * Use a default message.
2639         */
2640         if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2641             (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2642             (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2643
2644             char len[25], actLen[25];
2645
2646             /* FIXME, TODO: What is the max expected string length of the
2647             * this value?
2648             */
2649             if (nodeType == XML_ATTRIBUTE_NODE)
2650                 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2651             else
2652                 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2653
2654             snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2655             snprintf(actLen, 24, "%lu", length);
2656
2657             if (facetType == XML_SCHEMA_FACET_LENGTH)
2658                 msg = xmlStrcat(msg,
2659                 BAD_CAST "this differs from the allowed length of '%s'.\n");
2660             else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2661                 msg = xmlStrcat(msg,
2662                 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2663             else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2664                 msg = xmlStrcat(msg,
2665                 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2666
2667             if (nodeType == XML_ATTRIBUTE_NODE)
2668                 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2669                     value, (const xmlChar *) actLen, (const xmlChar *) len);
2670             else
2671                 xmlSchemaErr(actxt, error, node, (const char *) msg,
2672                     (const xmlChar *) actLen, (const xmlChar *) len);
2673
2674         } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2675             msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2676                 "of the set {%s}.\n");
2677             xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2678                 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2679         } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2680             msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2681                 "by the pattern '%s'.\n");
2682             xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2683                 facet->value);
2684         } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2685             msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2686                 "minimum value allowed ('%s').\n");
2687             xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2688                 facet->value);
2689         } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2690             msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2691                 "maximum value allowed ('%s').\n");
2692             xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2693                 facet->value);
2694         } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2695             msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
2696                 "'%s'.\n");
2697             xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2698                 facet->value);
2699         } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2700             msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2701                 "'%s'.\n");
2702             xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2703                 facet->value);
2704         } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2705             msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2706                 "digits than are allowed ('%s').\n");
2707             xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2708                 facet->value);
2709         } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2710             msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2711                 "digits than are allowed ('%s').\n");
2712             xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2713                 facet->value);
2714         } else if (nodeType == XML_ATTRIBUTE_NODE) {
2715             msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2716             xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2717         } else {
2718             msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2719             xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2720         }
2721     } else {
2722         msg = xmlStrcat(msg, (const xmlChar *) message);
2723         msg = xmlStrcat(msg, BAD_CAST ".\n");
2724         xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2725     }
2726     FREE_AND_NULL(str)
2727     xmlFree(msg);
2728 }
2729
2730 #define VERROR(err, type, msg) \
2731     xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
2732
2733 #define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
2734
2735 #define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2736 #define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
2737
2738 #define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2739
2740
2741 /**
2742  * xmlSchemaPMissingAttrErr:
2743  * @ctxt: the schema validation context
2744  * @ownerDes: the designation of  the owner
2745  * @ownerName: the name of the owner
2746  * @ownerItem: the owner as a schema object
2747  * @ownerElem: the owner as an element node
2748  * @node: the parent element node of the missing attribute node
2749  * @type: the corresponding type of the attribute node
2750  *
2751  * Reports an illegal attribute.
2752  */
2753 static void
2754 xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
2755                          xmlParserErrors error,
2756                          xmlSchemaBasicItemPtr ownerItem,
2757                          xmlNodePtr ownerElem,
2758                          const char *name,
2759                          const char *message)
2760 {
2761     xmlChar *des = NULL;
2762
2763     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2764
2765     if (message != NULL)
2766         xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
2767     else
2768         xmlSchemaPErr(ctxt, ownerElem, error,
2769             "%s: The attribute '%s' is required but missing.\n",
2770             BAD_CAST des, BAD_CAST name);
2771     FREE_AND_NULL(des);
2772 }
2773
2774
2775 /**
2776  * xmlSchemaPResCompAttrErr:
2777  * @ctxt: the schema validation context
2778  * @error: the error code
2779  * @ownerDes: the designation of  the owner
2780  * @ownerItem: the owner as a schema object
2781  * @ownerElem: the owner as an element node
2782  * @name: the name of the attribute holding the QName
2783  * @refName: the referenced local name
2784  * @refURI: the referenced namespace URI
2785  * @message: optional message
2786  *
2787  * Used to report QName attribute values that failed to resolve
2788  * to schema components.
2789  */
2790 static void
2791 xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
2792                          xmlParserErrors error,
2793                          xmlSchemaBasicItemPtr ownerItem,
2794                          xmlNodePtr ownerElem,
2795                          const char *name,
2796                          const xmlChar *refName,
2797                          const xmlChar *refURI,
2798                          xmlSchemaTypeType refType,
2799                          const char *refTypeStr)
2800 {
2801     xmlChar *des = NULL, *strA = NULL;
2802
2803     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2804     if (refTypeStr == NULL)
2805         refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
2806         xmlSchemaPErrExt(ctxt, ownerElem, error,
2807             NULL, NULL, NULL,
2808             "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2809             "%s.\n", BAD_CAST des, BAD_CAST name,
2810             xmlSchemaFormatQName(&strA, refURI, refName),
2811             BAD_CAST refTypeStr, NULL);
2812     FREE_AND_NULL(des)
2813     FREE_AND_NULL(strA)
2814 }
2815
2816 /**
2817  * xmlSchemaPCustomAttrErr:
2818  * @ctxt: the schema parser context
2819  * @error: the error code
2820  * @ownerDes: the designation of the owner
2821  * @ownerItem: the owner as a schema object
2822  * @attr: the illegal attribute node
2823  *
2824  * Reports an illegal attribute during the parse.
2825  */
2826 static void
2827 xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
2828                         xmlParserErrors error,
2829                         xmlChar **ownerDes,
2830                         xmlSchemaBasicItemPtr ownerItem,
2831                         xmlAttrPtr attr,
2832                         const char *msg)
2833 {
2834     xmlChar *des = NULL;
2835
2836     if (ownerDes == NULL)
2837         xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
2838     else if (*ownerDes == NULL) {
2839         xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
2840         des = *ownerDes;
2841     } else
2842         des = *ownerDes;
2843     if (attr == NULL) {
2844         xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL,
2845             "%s, attribute '%s': %s.\n",
2846             BAD_CAST des, (const xmlChar *) "Unknown",
2847             (const xmlChar *) msg, NULL, NULL);
2848     } else {
2849         xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2850             "%s, attribute '%s': %s.\n",
2851             BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2852     }
2853     if (ownerDes == NULL)
2854         FREE_AND_NULL(des);
2855 }
2856
2857 /**
2858  * xmlSchemaPIllegalAttrErr:
2859  * @ctxt: the schema parser context
2860  * @error: the error code
2861  * @ownerDes: the designation of the attribute's owner
2862  * @ownerItem: the attribute's owner item
2863  * @attr: the illegal attribute node
2864  *
2865  * Reports an illegal attribute during the parse.
2866  */
2867 static void
2868 xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
2869                          xmlParserErrors error,
2870                          xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
2871                          xmlAttrPtr attr)
2872 {
2873     xmlChar *strA = NULL, *strB = NULL;
2874
2875     xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2876     xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2877         "%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2878         xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2879         NULL, NULL);
2880     FREE_AND_NULL(strA);
2881     FREE_AND_NULL(strB);
2882 }
2883
2884 /**
2885  * xmlSchemaPCustomErr:
2886  * @ctxt: the schema parser context
2887  * @error: the error code
2888  * @itemDes: the designation of the schema item
2889  * @item: the schema item
2890  * @itemElem: the node of the schema item
2891  * @message: the error message
2892  * @str1: an optional param for the error message
2893  * @str2: an optional param for the error message
2894  * @str3: an optional param for the error message
2895  *
2896  * Reports an error during parsing.
2897  */
2898 static void
2899 xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
2900                     xmlParserErrors error,
2901                     xmlSchemaBasicItemPtr item,
2902                     xmlNodePtr itemElem,
2903                     const char *message,
2904                     const xmlChar *str1,
2905                     const xmlChar *str2,
2906                     const xmlChar *str3)
2907 {
2908     xmlChar *des = NULL, *msg = NULL;
2909
2910     xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
2911     msg = xmlStrdup(BAD_CAST "%s: ");
2912     msg = xmlStrcat(msg, (const xmlChar *) message);
2913     msg = xmlStrcat(msg, BAD_CAST ".\n");
2914     if ((itemElem == NULL) && (item != NULL))
2915         itemElem = WXS_ITEM_NODE(item);
2916     xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
2917         (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2918     FREE_AND_NULL(des);
2919     FREE_AND_NULL(msg);
2920 }
2921
2922 /**
2923  * xmlSchemaPCustomErr:
2924  * @ctxt: the schema parser context
2925  * @error: the error code
2926  * @itemDes: the designation of the schema item
2927  * @item: the schema item
2928  * @itemElem: the node of the schema item
2929  * @message: the error message
2930  * @str1: the optional param for the error message
2931  *
2932  * Reports an error during parsing.
2933  */
2934 static void
2935 xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
2936                     xmlParserErrors error,
2937                     xmlSchemaBasicItemPtr item,
2938                     xmlNodePtr itemElem,
2939                     const char *message,
2940                     const xmlChar *str1)
2941 {
2942     xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
2943         str1, NULL, NULL);
2944 }
2945
2946 /**
2947  * xmlSchemaPAttrUseErr:
2948  * @ctxt: the schema parser context
2949  * @error: the error code
2950  * @itemDes: the designation of the schema type
2951  * @item: the schema type
2952  * @itemElem: the node of the schema type
2953  * @attr: the invalid schema attribute
2954  * @message: the error message
2955  * @str1: the optional param for the error message
2956  *
2957  * Reports an attribute use error during parsing.
2958  */
2959 static void
2960 xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
2961                     xmlParserErrors error,
2962                     xmlNodePtr node,
2963                     xmlSchemaBasicItemPtr ownerItem,
2964                     const xmlSchemaAttributeUsePtr attruse,
2965                     const char *message,
2966                     const xmlChar *str1, const xmlChar *str2,
2967                     const xmlChar *str3,const xmlChar *str4)
2968 {
2969     xmlChar *str = NULL, *msg = NULL;
2970
2971     xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
2972     msg = xmlStrcat(msg, BAD_CAST ", ");
2973     msg = xmlStrcat(msg,
2974         BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
2975         WXS_BASIC_CAST attruse, NULL));
2976     FREE_AND_NULL(str);
2977     msg = xmlStrcat(msg, BAD_CAST ": ");
2978     msg = xmlStrcat(msg, (const xmlChar *) message);
2979     msg = xmlStrcat(msg, BAD_CAST ".\n");
2980     xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
2981         (const char *) msg, str1, str2, str3, str4);
2982     xmlFree(msg);
2983 }
2984
2985 /**
2986  * xmlSchemaPIllegalFacetAtomicErr:
2987  * @ctxt: the schema parser context
2988  * @error: the error code
2989  * @type: the schema type
2990  * @baseType: the base type of type
2991  * @facet: the illegal facet
2992  *
2993  * Reports an illegal facet for atomic simple types.
2994  */
2995 static void
2996 xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
2997                           xmlParserErrors error,
2998                           xmlSchemaTypePtr type,
2999                           xmlSchemaTypePtr baseType,
3000                           xmlSchemaFacetPtr facet)
3001 {
3002     xmlChar *des = NULL, *strT = NULL;
3003
3004     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
3005     xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
3006         "%s: The facet '%s' is not allowed on types derived from the "
3007         "type %s.\n",
3008         BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
3009         xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
3010         NULL, NULL);
3011     FREE_AND_NULL(des);
3012     FREE_AND_NULL(strT);
3013 }
3014
3015 /**
3016  * xmlSchemaPIllegalFacetListUnionErr:
3017  * @ctxt: the schema parser context
3018  * @error: the error code
3019  * @itemDes: the designation of the schema item involved
3020  * @item: the schema item involved
3021  * @facet: the illegal facet
3022  *
3023  * Reports an illegal facet for <list> and <union>.
3024  */
3025 static void
3026 xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
3027                           xmlParserErrors error,
3028                           xmlSchemaTypePtr type,
3029                           xmlSchemaFacetPtr facet)
3030 {
3031     xmlChar *des = NULL;
3032
3033     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3034         type->node);
3035     xmlSchemaPErr(ctxt, type->node, error,
3036         "%s: The facet '%s' is not allowed.\n",
3037         BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
3038     FREE_AND_NULL(des);
3039 }
3040
3041 /**
3042  * xmlSchemaPMutualExclAttrErr:
3043  * @ctxt: the schema validation context
3044  * @error: the error code
3045  * @elemDes: the designation of the parent element node
3046  * @attr: the bad attribute node
3047  * @type: the corresponding type of the attribute node
3048  *
3049  * Reports an illegal attribute.
3050  */
3051 static void
3052 xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3053                          xmlParserErrors error,
3054                          xmlSchemaBasicItemPtr ownerItem,
3055                          xmlAttrPtr attr,
3056                          const char *name1,
3057                          const char *name2)
3058 {
3059     xmlChar *des = NULL;
3060
3061     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
3062     xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
3063         "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
3064         BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
3065     FREE_AND_NULL(des);
3066 }
3067
3068 /**
3069  * xmlSchemaPSimpleTypeErr:
3070  * @ctxt:  the schema validation context
3071  * @error: the error code
3072  * @type: the type specifier
3073  * @ownerDes: the designation of the owner
3074  * @ownerItem: the schema object if existent
3075  * @node: the validated node
3076  * @value: the validated value
3077  *
3078  * Reports a simple type validation error.
3079  * TODO: Should this report the value of an element as well?
3080  */
3081 static void
3082 xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3083                         xmlParserErrors error,
3084                         xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
3085                         xmlNodePtr node,
3086                         xmlSchemaTypePtr type,
3087                         const char *expected,
3088                         const xmlChar *value,
3089                         const char *message,
3090                         const xmlChar *str1,
3091                         const xmlChar *str2)
3092 {
3093     xmlChar *msg = NULL;
3094
3095     xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
3096     if (message == NULL) {
3097         /*
3098         * Use default messages.
3099         */
3100         if (type != NULL) {
3101             if (node->type == XML_ATTRIBUTE_NODE)
3102                 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3103             else
3104                 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3105                 "valid value of ");
3106             if (! xmlSchemaIsGlobalItem(type))
3107                 msg = xmlStrcat(msg, BAD_CAST "the local ");
3108             else
3109                 msg = xmlStrcat(msg, BAD_CAST "the ");
3110
3111             if (WXS_IS_ATOMIC(type))
3112                 msg = xmlStrcat(msg, BAD_CAST "atomic type");
3113             else if (WXS_IS_LIST(type))
3114                 msg = xmlStrcat(msg, BAD_CAST "list type");
3115             else if (WXS_IS_UNION(type))
3116                 msg = xmlStrcat(msg, BAD_CAST "union type");
3117
3118             if (xmlSchemaIsGlobalItem(type)) {
3119                 xmlChar *str = NULL;
3120                 msg = xmlStrcat(msg, BAD_CAST " '");
3121                 if (type->builtInType != 0) {
3122                     msg = xmlStrcat(msg, BAD_CAST "xs:");
3123                     msg = xmlStrcat(msg, type->name);
3124                 } else
3125                     msg = xmlStrcat(msg,
3126                         xmlSchemaFormatQName(&str,
3127                             type->targetNamespace, type->name));
3128                 msg = xmlStrcat(msg, BAD_CAST "'.");
3129                 FREE_AND_NULL(str);
3130             }
3131         } else {
3132             if (node->type == XML_ATTRIBUTE_NODE)
3133                 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3134             else
3135                 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3136                 "valid.");
3137         }
3138         if (expected) {
3139             msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3140             msg = xmlStrcat(msg, BAD_CAST expected);
3141             msg = xmlStrcat(msg, BAD_CAST "'.\n");
3142         } else
3143             msg = xmlStrcat(msg, BAD_CAST "\n");
3144         if (node->type == XML_ATTRIBUTE_NODE)
3145             xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3146         else
3147             xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3148     } else {
3149         msg = xmlStrcat(msg, BAD_CAST message);
3150         msg = xmlStrcat(msg, BAD_CAST ".\n");
3151         xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
3152              (const char*) msg, str1, str2, NULL, NULL, NULL);
3153     }
3154     /* Cleanup. */
3155     FREE_AND_NULL(msg)
3156 }
3157
3158 /**
3159  * xmlSchemaPContentErr:
3160  * @ctxt: the schema parser context
3161  * @error: the error code
3162  * @onwerDes: the designation of the holder of the content
3163  * @ownerItem: the owner item of the holder of the content
3164  * @ownerElem: the node of the holder of the content
3165  * @child: the invalid child node
3166  * @message: the optional error message
3167  * @content: the optional string describing the correct content
3168  *
3169  * Reports an error concerning the content of a schema element.
3170  */
3171 static void
3172 xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
3173                      xmlParserErrors error,
3174                      xmlSchemaBasicItemPtr ownerItem,
3175                      xmlNodePtr ownerElem,
3176                      xmlNodePtr child,
3177                      const char *message,
3178                      const char *content)
3179 {
3180     xmlChar *des = NULL;
3181
3182     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
3183     if (message != NULL)
3184         xmlSchemaPErr2(ctxt, ownerElem, child, error,
3185             "%s: %s.\n",
3186             BAD_CAST des, BAD_CAST message);
3187     else {
3188         if (content != NULL) {
3189             xmlSchemaPErr2(ctxt, ownerElem, child, error,
3190                 "%s: The content is not valid. Expected is %s.\n",
3191                 BAD_CAST des, BAD_CAST content);
3192         } else {
3193             xmlSchemaPErr2(ctxt, ownerElem, child, error,
3194                 "%s: The content is not valid.\n",
3195                 BAD_CAST des, NULL);
3196         }
3197     }
3198     FREE_AND_NULL(des)
3199 }
3200
3201 /************************************************************************
3202  *                                                                      *
3203  *                      Streamable error functions                      *
3204  *                                                                      *
3205  ************************************************************************/
3206
3207
3208
3209
3210 /************************************************************************
3211  *                                                                      *
3212  *                      Validation helper functions                     *
3213  *                                                                      *
3214  ************************************************************************/
3215
3216
3217 /************************************************************************
3218  *                                                                      *
3219  *                      Allocation functions                            *
3220  *                                                                      *
3221  ************************************************************************/
3222
3223 /**
3224  * xmlSchemaNewSchemaForParserCtxt:
3225  * @ctxt:  a schema validation context
3226  *
3227  * Allocate a new Schema structure.
3228  *
3229  * Returns the newly allocated structure or NULL in case or error
3230  */
3231 static xmlSchemaPtr
3232 xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3233 {
3234     xmlSchemaPtr ret;
3235
3236     ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3237     if (ret == NULL) {
3238         xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
3239         return (NULL);
3240     }
3241     memset(ret, 0, sizeof(xmlSchema));
3242     ret->dict = ctxt->dict;
3243     xmlDictReference(ret->dict);
3244
3245     return (ret);
3246 }
3247
3248 /**
3249  * xmlSchemaNewFacet:
3250  *
3251  * Allocate a new Facet structure.
3252  *
3253  * Returns the newly allocated structure or NULL in case or error
3254  */
3255 xmlSchemaFacetPtr
3256 xmlSchemaNewFacet(void)
3257 {
3258     xmlSchemaFacetPtr ret;
3259
3260     ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3261     if (ret == NULL) {
3262         return (NULL);
3263     }
3264     memset(ret, 0, sizeof(xmlSchemaFacet));
3265
3266     return (ret);
3267 }
3268
3269 /**
3270  * xmlSchemaNewAnnot:
3271  * @ctxt:  a schema validation context
3272  * @node:  a node
3273  *
3274  * Allocate a new annotation structure.
3275  *
3276  * Returns the newly allocated structure or NULL in case or error
3277  */
3278 static xmlSchemaAnnotPtr
3279 xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3280 {
3281     xmlSchemaAnnotPtr ret;
3282
3283     ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3284     if (ret == NULL) {
3285         xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
3286         return (NULL);
3287     }
3288     memset(ret, 0, sizeof(xmlSchemaAnnot));
3289     ret->content = node;
3290     return (ret);
3291 }
3292
3293 static xmlSchemaItemListPtr
3294 xmlSchemaItemListCreate(void)
3295 {
3296     xmlSchemaItemListPtr ret;
3297
3298     ret = xmlMalloc(sizeof(xmlSchemaItemList));
3299     if (ret == NULL) {
3300         xmlSchemaPErrMemory(NULL,
3301             "allocating an item list structure", NULL);
3302         return (NULL);
3303     }
3304     memset(ret, 0, sizeof(xmlSchemaItemList));
3305     return (ret);
3306 }
3307
3308 static void
3309 xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3310 {
3311     if (list->items != NULL) {
3312         xmlFree(list->items);
3313         list->items = NULL;
3314     }
3315     list->nbItems = 0;
3316     list->sizeItems = 0;
3317 }
3318
3319 static int
3320 xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3321 {
3322     if (list->items == NULL) {
3323         list->items = (void **) xmlMalloc(
3324             20 * sizeof(void *));
3325         if (list->items == NULL) {
3326             xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3327             return(-1);
3328         }
3329         list->sizeItems = 20;
3330     } else if (list->sizeItems <= list->nbItems) {
3331         list->sizeItems *= 2;
3332         list->items = (void **) xmlRealloc(list->items,
3333             list->sizeItems * sizeof(void *));
3334         if (list->items == NULL) {
3335             xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3336             list->sizeItems = 0;
3337             return(-1);
3338         }
3339     }
3340     list->items[list->nbItems++] = item;
3341     return(0);
3342 }
3343
3344 static int
3345 xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3346                          int initialSize,
3347                          void *item)
3348 {
3349     if (list->items == NULL) {
3350         if (initialSize <= 0)
3351             initialSize = 1;
3352         list->items = (void **) xmlMalloc(
3353             initialSize * sizeof(void *));
3354         if (list->items == NULL) {
3355             xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3356             return(-1);
3357         }
3358         list->sizeItems = initialSize;
3359     } else if (list->sizeItems <= list->nbItems) {
3360         list->sizeItems *= 2;
3361         list->items = (void **) xmlRealloc(list->items,
3362             list->sizeItems * sizeof(void *));
3363         if (list->items == NULL) {
3364             xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3365             list->sizeItems = 0;
3366             return(-1);
3367         }
3368     }
3369     list->items[list->nbItems++] = item;
3370     return(0);
3371 }
3372
3373 static int
3374 xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3375 {
3376     if (list->items == NULL) {
3377         list->items = (void **) xmlMalloc(
3378             20 * sizeof(void *));
3379         if (list->items == NULL) {
3380             xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3381             return(-1);
3382         }
3383         list->sizeItems = 20;
3384     } else if (list->sizeItems <= list->nbItems) {
3385         list->sizeItems *= 2;
3386         list->items = (void **) xmlRealloc(list->items,
3387             list->sizeItems * sizeof(void *));
3388         if (list->items == NULL) {
3389             xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3390             list->sizeItems = 0;
3391             return(-1);
3392         }
3393     }
3394     /*
3395     * Just append if the index is greater/equal than the item count.
3396     */
3397     if (idx >= list->nbItems) {
3398         list->items[list->nbItems++] = item;
3399     } else {
3400         int i;
3401         for (i = list->nbItems; i > idx; i--)
3402             list->items[i] = list->items[i-1];
3403         list->items[idx] = item;
3404         list->nbItems++;
3405     }
3406     return(0);
3407 }
3408
3409 #if 0 /* enable if ever needed */
3410 static int
3411 xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3412                             int initialSize,
3413                             void *item,
3414                             int idx)
3415 {
3416     if (list->items == NULL) {
3417         if (initialSize <= 0)
3418             initialSize = 1;
3419         list->items = (void **) xmlMalloc(
3420             initialSize * sizeof(void *));
3421         if (list->items == NULL) {
3422             xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3423             return(-1);
3424         }
3425         list->sizeItems = initialSize;
3426     } else if (list->sizeItems <= list->nbItems) {
3427         list->sizeItems *= 2;
3428         list->items = (void **) xmlRealloc(list->items,
3429             list->sizeItems * sizeof(void *));
3430         if (list->items == NULL) {
3431             xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3432             list->sizeItems = 0;
3433             return(-1);
3434         }
3435     }
3436     /*
3437     * Just append if the index is greater/equal than the item count.
3438     */
3439     if (idx >= list->nbItems) {
3440         list->items[list->nbItems++] = item;
3441     } else {
3442         int i;
3443         for (i = list->nbItems; i > idx; i--)
3444             list->items[i] = list->items[i-1];
3445         list->items[idx] = item;
3446         list->nbItems++;
3447     }
3448     return(0);
3449 }
3450 #endif
3451
3452 static int
3453 xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3454 {
3455     int i;
3456     if ((list->items == NULL) || (idx >= list->nbItems)) {
3457         xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3458             "index error.\n");
3459         return(-1);
3460     }
3461
3462     if (list->nbItems == 1) {
3463         /* TODO: Really free the list? */
3464         xmlFree(list->items);
3465         list->items = NULL;
3466         list->nbItems = 0;
3467         list->sizeItems = 0;
3468     } else if (list->nbItems -1 == idx) {
3469         list->nbItems--;
3470     } else {
3471         for (i = idx; i < list->nbItems -1; i++)
3472             list->items[i] = list->items[i+1];
3473         list->nbItems--;
3474     }
3475     return(0);
3476 }
3477
3478 /**
3479  * xmlSchemaItemListFree:
3480  * @annot:  a schema type structure
3481  *
3482  * Deallocate a annotation structure
3483  */
3484 static void
3485 xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3486 {
3487     if (list == NULL)
3488         return;
3489     if (list->items != NULL)
3490         xmlFree(list->items);
3491     xmlFree(list);
3492 }
3493
3494 static void
3495 xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
3496 {
3497     if (bucket == NULL)
3498         return;
3499     if (bucket->globals != NULL) {
3500         xmlSchemaComponentListFree(bucket->globals);
3501         xmlSchemaItemListFree(bucket->globals);
3502     }
3503     if (bucket->locals != NULL) {
3504         xmlSchemaComponentListFree(bucket->locals);
3505         xmlSchemaItemListFree(bucket->locals);
3506     }
3507     if (bucket->relations != NULL) {
3508         xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3509         do {
3510             prev = cur;
3511             cur = cur->next;
3512             xmlFree(prev);
3513         } while (cur != NULL);
3514     }
3515     if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3516         xmlFreeDoc(bucket->doc);
3517     }
3518     if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
3519         if (WXS_IMPBUCKET(bucket)->schema != NULL)
3520             xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
3521     }
3522     xmlFree(bucket);
3523 }
3524
3525 static xmlSchemaBucketPtr
3526 xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
3527                          int type, const xmlChar *targetNamespace)
3528 {
3529     xmlSchemaBucketPtr ret;
3530     int size;
3531     xmlSchemaPtr mainSchema;
3532
3533     if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
3534         PERROR_INT("xmlSchemaBucketCreate",
3535             "no main schema on constructor");
3536         return(NULL);
3537     }
3538     mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
3539     /* Create the schema bucket. */
3540     if (WXS_IS_BUCKET_INCREDEF(type))
3541         size = sizeof(xmlSchemaInclude);
3542     else
3543         size = sizeof(xmlSchemaImport);
3544     ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3545     if (ret == NULL) {
3546         xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3547         return(NULL);
3548     }
3549     memset(ret, 0, size);
3550     ret->targetNamespace = targetNamespace;
3551     ret->type = type;
3552     ret->globals = xmlSchemaItemListCreate();
3553     if (ret->globals == NULL) {
3554         xmlFree(ret);
3555         return(NULL);
3556     }
3557     ret->locals = xmlSchemaItemListCreate();
3558     if (ret->locals == NULL) {
3559         xmlFree(ret);
3560         return(NULL);
3561     }
3562     /*
3563     * The following will assure that only the first bucket is marked as
3564     * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3565     * For each following import buckets an xmlSchema will be created.
3566     * An xmlSchema will be created for every distinct targetNamespace.
3567     * We assign the targetNamespace to the schemata here.
3568     */
3569     if (! WXS_HAS_BUCKETS(pctxt)) {
3570         if (WXS_IS_BUCKET_INCREDEF(type)) {
3571             PERROR_INT("xmlSchemaBucketCreate",
3572                 "first bucket but it's an include or redefine");
3573             xmlSchemaBucketFree(ret);
3574             return(NULL);
3575         }
3576         /* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3577         ret->type = XML_SCHEMA_SCHEMA_MAIN;
3578         /* Point to the *main* schema. */
3579         WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3580         WXS_IMPBUCKET(ret)->schema = mainSchema;
3581         /*
3582         * Ensure that the main schema gets a targetNamespace.
3583         */
3584         mainSchema->targetNamespace = targetNamespace;
3585     } else {
3586         if (type == XML_SCHEMA_SCHEMA_MAIN) {
3587             PERROR_INT("xmlSchemaBucketCreate",
3588                 "main bucket but it's not the first one");
3589             xmlSchemaBucketFree(ret);
3590             return(NULL);
3591         } else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3592             /*
3593             * Create a schema for imports and assign the
3594             * targetNamespace.
3595             */
3596             WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3597             if (WXS_IMPBUCKET(ret)->schema == NULL) {
3598                 xmlSchemaBucketFree(ret);
3599                 return(NULL);
3600             }
3601             WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
3602         }
3603     }
3604     if (WXS_IS_BUCKET_IMPMAIN(type)) {
3605         int res;
3606         /*
3607         * Imports go into the "schemasImports" slot of the main *schema*.
3608         * Note that we create an import entry for the main schema as well; i.e.,
3609         * even if there's only one schema, we'll get an import.
3610         */
3611         if (mainSchema->schemasImports == NULL) {
3612             mainSchema->schemasImports = xmlHashCreateDict(5,
3613                 WXS_CONSTRUCTOR(pctxt)->dict);
3614             if (mainSchema->schemasImports == NULL) {
3615                 xmlSchemaBucketFree(ret);
3616                 return(NULL);
3617             }
3618         }
3619         if (targetNamespace == NULL)
3620             res = xmlHashAddEntry(mainSchema->schemasImports,
3621                 XML_SCHEMAS_NO_NAMESPACE, ret);
3622         else
3623             res = xmlHashAddEntry(mainSchema->schemasImports,
3624                 targetNamespace, ret);
3625         if (res != 0) {
3626             PERROR_INT("xmlSchemaBucketCreate",
3627                 "failed to add the schema bucket to the hash");
3628             xmlSchemaBucketFree(ret);
3629             return(NULL);
3630         }
3631     } else {
3632         /* Set the @ownerImport of an include bucket. */
3633         if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3634             WXS_INCBUCKET(ret)->ownerImport =
3635                 WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
3636         else
3637             WXS_INCBUCKET(ret)->ownerImport =
3638                 WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
3639
3640         /* Includes got into the "includes" slot of the *main* schema. */
3641         if (mainSchema->includes == NULL) {
3642             mainSchema->includes = xmlSchemaItemListCreate();
3643             if (mainSchema->includes == NULL) {
3644                 xmlSchemaBucketFree(ret);
3645                 return(NULL);
3646             }
3647         }
3648         xmlSchemaItemListAdd(mainSchema->includes, ret);
3649     }
3650     /*
3651     * Add to list of all buckets; this is used for lookup
3652     * during schema construction time only.
3653     */
3654     if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
3655         return(NULL);
3656     return(ret);
3657 }
3658
3659 static int
3660 xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
3661 {
3662     if (*list == NULL) {
3663         *list = xmlSchemaItemListCreate();
3664         if (*list == NULL)
3665             return(-1);
3666     }
3667     xmlSchemaItemListAddSize(*list, initialSize, item);
3668     return(0);
3669 }
3670
3671 /**
3672  * xmlSchemaFreeAnnot:
3673  * @annot:  a schema type structure
3674  *
3675  * Deallocate a annotation structure
3676  */
3677 static void
3678 xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3679 {
3680     if (annot == NULL)
3681         return;
3682     if (annot->next == NULL) {
3683         xmlFree(annot);
3684     } else {
3685         xmlSchemaAnnotPtr prev;
3686
3687         do {
3688             prev = annot;
3689             annot = annot->next;
3690             xmlFree(prev);
3691         } while (annot != NULL);
3692     }
3693 }
3694
3695 /**
3696  * xmlSchemaFreeNotation:
3697  * @schema:  a schema notation structure
3698  *
3699  * Deallocate a Schema Notation structure.
3700  */
3701 static void
3702 xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3703 {
3704     if (nota == NULL)
3705         return;
3706     xmlFree(nota);
3707 }
3708
3709 /**
3710  * xmlSchemaFreeAttribute:
3711  * @attr:  an attribute declaration
3712  *
3713  * Deallocates an attribute declaration structure.
3714  */
3715 static void
3716 xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3717 {
3718     if (attr == NULL)
3719         return;
3720     if (attr->annot != NULL)
3721         xmlSchemaFreeAnnot(attr->annot);
3722     if (attr->defVal != NULL)
3723         xmlSchemaFreeValue(attr->defVal);
3724     xmlFree(attr);
3725 }
3726
3727 /**
3728  * xmlSchemaFreeAttributeUse:
3729  * @use:  an attribute use
3730  *
3731  * Deallocates an attribute use structure.
3732  */
3733 static void
3734 xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3735 {
3736     if (use == NULL)
3737         return;
3738     if (use->annot != NULL)
3739         xmlSchemaFreeAnnot(use->annot);
3740     if (use->defVal != NULL)
3741         xmlSchemaFreeValue(use->defVal);
3742     xmlFree(use);
3743 }
3744
3745 /**
3746  * xmlSchemaFreeAttributeUseProhib:
3747  * @prohib:  an attribute use prohibition
3748  *
3749  * Deallocates an attribute use structure.
3750  */
3751 static void
3752 xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3753 {
3754     if (prohib == NULL)
3755         return;
3756     xmlFree(prohib);
3757 }
3758
3759 /**
3760  * xmlSchemaFreeWildcardNsSet:
3761  * set:  a schema wildcard namespace
3762  *
3763  * Deallocates a list of wildcard constraint structures.
3764  */
3765 static void
3766 xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3767 {
3768     xmlSchemaWildcardNsPtr next;
3769
3770     while (set != NULL) {
3771         next = set->next;
3772         xmlFree(set);
3773         set = next;
3774     }
3775 }
3776
3777 /**
3778  * xmlSchemaFreeWildcard:
3779  * @wildcard:  a wildcard structure
3780  *
3781  * Deallocates a wildcard structure.
3782  */
3783 void
3784 xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3785 {
3786     if (wildcard == NULL)
3787         return;
3788     if (wildcard->annot != NULL)
3789         xmlSchemaFreeAnnot(wildcard->annot);
3790     if (wildcard->nsSet != NULL)
3791         xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3792     if (wildcard->negNsSet != NULL)
3793         xmlFree(wildcard->negNsSet);
3794     xmlFree(wildcard);
3795 }
3796
3797 /**
3798  * xmlSchemaFreeAttributeGroup:
3799  * @schema:  a schema attribute group structure
3800  *
3801  * Deallocate a Schema Attribute Group structure.
3802  */
3803 static void
3804 xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
3805 {
3806     if (attrGr == NULL)
3807         return;
3808     if (attrGr->annot != NULL)
3809         xmlSchemaFreeAnnot(attrGr->annot);
3810     if (attrGr->attrUses != NULL)
3811         xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3812     xmlFree(attrGr);
3813 }
3814
3815 /**
3816  * xmlSchemaFreeQNameRef:
3817  * @item: a QName reference structure
3818  *
3819  * Deallocatea a QName reference structure.
3820  */
3821 static void
3822 xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3823 {
3824     xmlFree(item);
3825 }
3826
3827 /**
3828  * xmlSchemaFreeTypeLinkList:
3829  * @alink: a type link
3830  *
3831  * Deallocate a list of types.
3832  */
3833 static void
3834 xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3835 {
3836     xmlSchemaTypeLinkPtr next;
3837
3838     while (link != NULL) {
3839         next = link->next;
3840         xmlFree(link);
3841         link = next;
3842     }
3843 }
3844
3845 static void
3846 xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3847 {
3848     xmlSchemaIDCStateObjPtr next;
3849     while (sto != NULL) {
3850         next = sto->next;
3851         if (sto->history != NULL)
3852             xmlFree(sto->history);
3853         if (sto->xpathCtxt != NULL)
3854             xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3855         xmlFree(sto);
3856         sto = next;
3857     }
3858 }
3859
3860 /**
3861  * xmlSchemaFreeIDC:
3862  * @idc: a identity-constraint definition
3863  *
3864  * Deallocates an identity-constraint definition.
3865  */
3866 static void
3867 xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3868 {
3869     xmlSchemaIDCSelectPtr cur, prev;
3870
3871     if (idcDef == NULL)
3872         return;
3873     if (idcDef->annot != NULL)
3874         xmlSchemaFreeAnnot(idcDef->annot);
3875     /* Selector */
3876     if (idcDef->selector != NULL) {
3877         if (idcDef->selector->xpathComp != NULL)
3878             xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3879         xmlFree(idcDef->selector);
3880     }
3881     /* Fields */
3882     if (idcDef->fields != NULL) {
3883         cur = idcDef->fields;
3884         do {
3885             prev = cur;
3886             cur = cur->next;
3887             if (prev->xpathComp != NULL)
3888                 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
3889             xmlFree(prev);
3890         } while (cur != NULL);
3891     }
3892     xmlFree(idcDef);
3893 }
3894
3895 /**
3896  * xmlSchemaFreeElement:
3897  * @schema:  a schema element structure
3898  *
3899  * Deallocate a Schema Element structure.
3900  */
3901 static void
3902 xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3903 {
3904     if (elem == NULL)
3905         return;
3906     if (elem->annot != NULL)
3907         xmlSchemaFreeAnnot(elem->annot);
3908     if (elem->contModel != NULL)
3909         xmlRegFreeRegexp(elem->contModel);
3910     if (elem->defVal != NULL)
3911         xmlSchemaFreeValue(elem->defVal);
3912     xmlFree(elem);
3913 }
3914
3915 /**
3916  * xmlSchemaFreeFacet:
3917  * @facet:  a schema facet structure
3918  *
3919  * Deallocate a Schema Facet structure.
3920  */
3921 void
3922 xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3923 {
3924     if (facet == NULL)
3925         return;
3926     if (facet->val != NULL)
3927         xmlSchemaFreeValue(facet->val);
3928     if (facet->regexp != NULL)
3929         xmlRegFreeRegexp(facet->regexp);
3930     if (facet->annot != NULL)
3931         xmlSchemaFreeAnnot(facet->annot);
3932     xmlFree(facet);
3933 }
3934
3935 /**
3936  * xmlSchemaFreeType:
3937  * @type:  a schema type structure
3938  *
3939  * Deallocate a Schema Type structure.
3940  */
3941 void
3942 xmlSchemaFreeType(xmlSchemaTypePtr type)
3943 {
3944     if (type == NULL)
3945         return;
3946     if (type->annot != NULL)
3947         xmlSchemaFreeAnnot(type->annot);
3948     if (type->facets != NULL) {
3949         xmlSchemaFacetPtr facet, next;
3950
3951         facet = type->facets;
3952         while (facet != NULL) {
3953             next = facet->next;
3954             xmlSchemaFreeFacet(facet);
3955             facet = next;
3956         }
3957     }
3958     if (type->attrUses != NULL)
3959         xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
3960     if (type->memberTypes != NULL)
3961         xmlSchemaFreeTypeLinkList(type->memberTypes);
3962     if (type->facetSet != NULL) {
3963         xmlSchemaFacetLinkPtr next, link;
3964
3965         link = type->facetSet;
3966         do {
3967             next = link->next;
3968             xmlFree(link);
3969             link = next;
3970         } while (link != NULL);
3971     }
3972     if (type->contModel != NULL)
3973         xmlRegFreeRegexp(type->contModel);
3974     xmlFree(type);
3975 }
3976
3977 /**
3978  * xmlSchemaFreeModelGroupDef:
3979  * @item:  a schema model group definition
3980  *
3981  * Deallocates a schema model group definition.
3982  */
3983 static void
3984 xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3985 {
3986     if (item->annot != NULL)
3987         xmlSchemaFreeAnnot(item->annot);
3988     xmlFree(item);
3989 }
3990
3991 /**
3992  * xmlSchemaFreeModelGroup:
3993  * @item:  a schema model group
3994  *
3995  * Deallocates a schema model group structure.
3996  */
3997 static void
3998 xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3999 {
4000     if (item->annot != NULL)
4001         xmlSchemaFreeAnnot(item->annot);
4002     xmlFree(item);
4003 }
4004
4005 static void
4006 xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
4007 {
4008     if ((list == NULL) || (list->nbItems == 0))
4009         return;
4010     {
4011         xmlSchemaTreeItemPtr item;
4012         xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
4013         int i;
4014
4015         for (i = 0; i < list->nbItems; i++) {
4016             item = items[i];
4017             if (item == NULL)
4018                 continue;
4019             switch (item->type) {
4020                 case XML_SCHEMA_TYPE_SIMPLE:
4021                 case XML_SCHEMA_TYPE_COMPLEX:
4022                     xmlSchemaFreeType((xmlSchemaTypePtr) item);
4023                     break;
4024                 case XML_SCHEMA_TYPE_ATTRIBUTE:
4025                     xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
4026                     break;
4027                 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
4028                     xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
4029                     break;
4030                 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
4031                     xmlSchemaFreeAttributeUseProhib(
4032                         (xmlSchemaAttributeUseProhibPtr) item);
4033                     break;
4034                 case XML_SCHEMA_TYPE_ELEMENT:
4035                     xmlSchemaFreeElement((xmlSchemaElementPtr) item);
4036                     break;
4037                 case XML_SCHEMA_TYPE_PARTICLE:
4038                     if (item->annot != NULL)
4039                         xmlSchemaFreeAnnot(item->annot);
4040                     xmlFree(item);
4041                     break;
4042                 case XML_SCHEMA_TYPE_SEQUENCE:
4043                 case XML_SCHEMA_TYPE_CHOICE:
4044                 case XML_SCHEMA_TYPE_ALL:
4045                     xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4046                     break;
4047                 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4048                     xmlSchemaFreeAttributeGroup(
4049                         (xmlSchemaAttributeGroupPtr) item);
4050                     break;
4051                 case XML_SCHEMA_TYPE_GROUP:
4052                     xmlSchemaFreeModelGroupDef(
4053                         (xmlSchemaModelGroupDefPtr) item);
4054                     break;
4055                 case XML_SCHEMA_TYPE_ANY:
4056                 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4057                     xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4058                     break;
4059                 case XML_SCHEMA_TYPE_IDC_KEY:
4060                 case XML_SCHEMA_TYPE_IDC_UNIQUE:
4061                 case XML_SCHEMA_TYPE_IDC_KEYREF:
4062                     xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4063                     break;
4064                 case XML_SCHEMA_TYPE_NOTATION:
4065                     xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4066                     break;
4067                 case XML_SCHEMA_EXTRA_QNAMEREF:
4068                     xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4069                     break;
4070                 default: {
4071                     /* TODO: This should never be hit. */
4072                     xmlSchemaPSimpleInternalErr(NULL,
4073                         "Internal error: xmlSchemaComponentListFree, "
4074                         "unexpected component type '%s'\n",
4075                         (const xmlChar *) WXS_ITEM_TYPE_NAME(item));
4076                          }
4077                     break;
4078             }
4079         }
4080         list->nbItems = 0;
4081     }
4082 }
4083
4084 /**
4085  * xmlSchemaFree:
4086  * @schema:  a schema structure
4087  *
4088  * Deallocate a Schema structure.
4089  */
4090 void
4091 xmlSchemaFree(xmlSchemaPtr schema)
4092 {
4093     if (schema == NULL)
4094         return;
4095     /* @volatiles is not used anymore :-/ */
4096     if (schema->volatiles != NULL)
4097         TODO
4098     /*
4099     * Note that those slots are not responsible for freeing
4100     * schema components anymore; this will now be done by
4101     * the schema buckets.
4102     */
4103     if (schema->notaDecl != NULL)
4104         xmlHashFree(schema->notaDecl, NULL);
4105     if (schema->attrDecl != NULL)
4106         xmlHashFree(schema->attrDecl, NULL);
4107     if (schema->attrgrpDecl != NULL)
4108         xmlHashFree(schema->attrgrpDecl, NULL);
4109     if (schema->elemDecl != NULL)
4110         xmlHashFree(schema->elemDecl, NULL);
4111     if (schema->typeDecl != NULL)
4112         xmlHashFree(schema->typeDecl, NULL);
4113     if (schema->groupDecl != NULL)
4114         xmlHashFree(schema->groupDecl, NULL);
4115     if (schema->idcDef != NULL)
4116         xmlHashFree(schema->idcDef, NULL);
4117
4118     if (schema->schemasImports != NULL)
4119         xmlHashFree(schema->schemasImports,
4120                     (xmlHashDeallocator) xmlSchemaBucketFree);
4121     if (schema->includes != NULL) {
4122         xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4123         int i;
4124         for (i = 0; i < list->nbItems; i++) {
4125             xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4126         }
4127         xmlSchemaItemListFree(list);
4128     }
4129     if (schema->annot != NULL)
4130         xmlSchemaFreeAnnot(schema->annot);
4131     /* Never free the doc here, since this will be done by the buckets. */
4132
4133     xmlDictFree(schema->dict);
4134     xmlFree(schema);
4135 }
4136
4137 /************************************************************************
4138  *                                                                      *
4139  *                      Debug functions                                 *
4140  *                                                                      *
4141  ************************************************************************/
4142
4143 #ifdef LIBXML_OUTPUT_ENABLED
4144
4145 static void
4146 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4147
4148 /**
4149  * xmlSchemaElementDump:
4150  * @elem:  an element
4151  * @output:  the file output
4152  *
4153  * Dump the element
4154  */
4155 static void
4156 xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
4157                      const xmlChar * name ATTRIBUTE_UNUSED,
4158                      const xmlChar * namespace ATTRIBUTE_UNUSED,
4159                      const xmlChar * context ATTRIBUTE_UNUSED)
4160 {
4161     if (elem == NULL)
4162         return;
4163
4164
4165     fprintf(output, "Element");
4166     if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4167         fprintf(output, " (global)");
4168     fprintf(output, ": '%s' ", elem->name);
4169     if (namespace != NULL)
4170         fprintf(output, "ns '%s'", namespace);
4171     fprintf(output, "\n");
4172 #if 0
4173     if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
4174         fprintf(output, "  min %d ", elem->minOccurs);
4175         if (elem->maxOccurs >= UNBOUNDED)
4176             fprintf(output, "max: unbounded\n");
4177         else if (elem->maxOccurs != 1)
4178             fprintf(output, "max: %d\n", elem->maxOccurs);
4179         else
4180             fprintf(output, "\n");
4181     }
4182 #endif
4183     /*
4184     * Misc other properties.
4185     */
4186     if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4187         (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4188         (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
4189         (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
4190         fprintf(output, "  props: ");
4191         if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4192             fprintf(output, "[fixed] ");
4193         if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4194             fprintf(output, "[default] ");
4195         if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4196             fprintf(output, "[abstract] ");
4197         if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4198             fprintf(output, "[nillable] ");
4199         fprintf(output, "\n");
4200     }
4201     /*
4202     * Default/fixed value.
4203     */
4204     if (elem->value != NULL)
4205         fprintf(output, "  value: '%s'\n", elem->value);
4206     /*
4207     * Type.
4208     */
4209     if (elem->namedType != NULL) {
4210         fprintf(output, "  type: '%s' ", elem->namedType);
4211         if (elem->namedTypeNs != NULL)
4212             fprintf(output, "ns '%s'\n", elem->namedTypeNs);
4213         else
4214             fprintf(output, "\n");
4215     } else if (elem->subtypes != NULL) {
4216         /*
4217         * Dump local types.
4218         */
4219         xmlSchemaTypeDump(elem->subtypes, output);
4220     }
4221     /*
4222     * Substitution group.
4223     */
4224     if (elem->substGroup != NULL) {
4225         fprintf(output, "  substitutionGroup: '%s' ", elem->substGroup);
4226         if (elem->substGroupNs != NULL)
4227             fprintf(output, "ns '%s'\n", elem->substGroupNs);
4228         else
4229             fprintf(output, "\n");
4230     }
4231 }
4232
4233 /**
4234  * xmlSchemaAnnotDump:
4235  * @output:  the file output
4236  * @annot:  a annotation
4237  *
4238  * Dump the annotation
4239  */
4240 static void
4241 xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4242 {
4243     xmlChar *content;
4244
4245     if (annot == NULL)
4246         return;
4247
4248     content = xmlNodeGetContent(annot->content);
4249     if (content != NULL) {
4250         fprintf(output, "  Annot: %s\n", content);
4251         xmlFree(content);
4252     } else
4253         fprintf(output, "  Annot: empty\n");
4254 }
4255
4256 /**
4257  * xmlSchemaContentModelDump:
4258  * @particle: the schema particle
4259  * @output: the file output
4260  * @depth: the depth used for intentation
4261  *
4262  * Dump a SchemaType structure
4263  */
4264 static void
4265 xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4266 {
4267     xmlChar *str = NULL;
4268     xmlSchemaTreeItemPtr term;
4269     char shift[100];
4270     int i;
4271
4272     if (particle == NULL)
4273         return;
4274     for (i = 0;((i < depth) && (i < 25));i++)
4275         shift[2 * i] = shift[2 * i + 1] = ' ';
4276     shift[2 * i] = shift[2 * i + 1] = 0;
4277     fprintf(output, "%s", shift);
4278     if (particle->children == NULL) {
4279         fprintf(output, "MISSING particle term\n");
4280         return;
4281     }
4282     term = particle->children;
4283     if (term == NULL) {
4284         fprintf(output, "(NULL)");
4285     } else {
4286         switch (term->type) {
4287             case XML_SCHEMA_TYPE_ELEMENT:
4288                 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4289                     ((xmlSchemaElementPtr)term)->targetNamespace,
4290                     ((xmlSchemaElementPtr)term)->name));
4291                 FREE_AND_NULL(str);
4292                 break;
4293             case XML_SCHEMA_TYPE_SEQUENCE:
4294                 fprintf(output, "SEQUENCE");
4295                 break;
4296             case XML_SCHEMA_TYPE_CHOICE:
4297                 fprintf(output, "CHOICE");
4298                 break;
4299             case XML_SCHEMA_TYPE_ALL:
4300                 fprintf(output, "ALL");
4301                 break;
4302             case XML_SCHEMA_TYPE_ANY:
4303                 fprintf(output, "ANY");
4304                 break;
4305             default:
4306                 fprintf(output, "UNKNOWN\n");
4307                 return;
4308         }
4309     }
4310     if (particle->minOccurs != 1)
4311         fprintf(output, " min: %d", particle->minOccurs);
4312     if (particle->maxOccurs >= UNBOUNDED)
4313         fprintf(output, " max: unbounded");
4314     else if (particle->maxOccurs != 1)
4315         fprintf(output, " max: %d", particle->maxOccurs);
4316     fprintf(output, "\n");
4317     if (term &&
4318         ((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4319          (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4320          (term->type == XML_SCHEMA_TYPE_ALL)) &&
4321          (term->children != NULL)) {
4322         xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4323             output, depth +1);
4324     }
4325     if (particle->next != NULL)
4326         xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4327                 output, depth);
4328 }
4329
4330 /**
4331  * xmlSchemaAttrUsesDump:
4332  * @uses:  attribute uses list
4333  * @output:  the file output
4334  *
4335  * Dumps a list of attribute use components.
4336  */
4337 static void
4338 xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4339 {
4340     xmlSchemaAttributeUsePtr use;
4341     xmlSchemaAttributeUseProhibPtr prohib;
4342     xmlSchemaQNameRefPtr ref;
4343     const xmlChar *name, *tns;
4344     xmlChar *str = NULL;
4345     int i;
4346
4347     if ((uses == NULL) || (uses->nbItems == 0))
4348         return;
4349
4350     fprintf(output, "  attributes:\n");
4351     for (i = 0; i < uses->nbItems; i++) {
4352         use = uses->items[i];
4353         if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4354             fprintf(output, "  [prohibition] ");
4355             prohib = (xmlSchemaAttributeUseProhibPtr) use;
4356             name = prohib->name;
4357             tns = prohib->targetNamespace;
4358         } else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4359             fprintf(output, "  [reference] ");
4360             ref = (xmlSchemaQNameRefPtr) use;
4361             name = ref->name;
4362             tns = ref->targetNamespace;
4363         } else {
4364             fprintf(output, "  [use] ");
4365             name = WXS_ATTRUSE_DECL_NAME(use);
4366             tns = WXS_ATTRUSE_DECL_TNS(use);
4367         }
4368         fprintf(output, "'%s'\n",
4369             (const char *) xmlSchemaFormatQName(&str, tns, name));
4370         FREE_AND_NULL(str);
4371     }
4372 }
4373
4374 /**
4375  * xmlSchemaTypeDump:
4376  * @output:  the file output
4377  * @type:  a type structure
4378  *
4379  * Dump a SchemaType structure
4380  */
4381 static void
4382 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4383 {
4384     if (type == NULL) {
4385         fprintf(output, "Type: NULL\n");
4386         return;
4387     }
4388     fprintf(output, "Type: ");
4389     if (type->name != NULL)
4390         fprintf(output, "'%s' ", type->name);
4391     else
4392         fprintf(output, "(no name) ");
4393     if (type->targetNamespace != NULL)
4394         fprintf(output, "ns '%s' ", type->targetNamespace);
4395     switch (type->type) {
4396         case XML_SCHEMA_TYPE_BASIC:
4397             fprintf(output, "[basic] ");
4398             break;
4399         case XML_SCHEMA_TYPE_SIMPLE:
4400             fprintf(output, "[simple] ");
4401             break;
4402         case XML_SCHEMA_TYPE_COMPLEX:
4403             fprintf(output, "[complex] ");
4404             break;
4405         case XML_SCHEMA_TYPE_SEQUENCE:
4406             fprintf(output, "[sequence] ");
4407             break;
4408         case XML_SCHEMA_TYPE_CHOICE:
4409             fprintf(output, "[choice] ");
4410             break;
4411         case XML_SCHEMA_TYPE_ALL:
4412             fprintf(output, "[all] ");
4413             break;
4414         case XML_SCHEMA_TYPE_UR:
4415             fprintf(output, "[ur] ");
4416             break;
4417         case XML_SCHEMA_TYPE_RESTRICTION:
4418             fprintf(output, "[restriction] ");
4419             break;
4420         case XML_SCHEMA_TYPE_EXTENSION:
4421             fprintf(output, "[extension] ");
4422             break;
4423         default:
4424             fprintf(output, "[unknown type %d] ", type->type);
4425             break;
4426     }
4427     fprintf(output, "content: ");
4428     switch (type->contentType) {
4429         case XML_SCHEMA_CONTENT_UNKNOWN:
4430             fprintf(output, "[unknown] ");
4431             break;
4432         case XML_SCHEMA_CONTENT_EMPTY:
4433             fprintf(output, "[empty] ");
4434             break;
4435         case XML_SCHEMA_CONTENT_ELEMENTS:
4436             fprintf(output, "[element] ");
4437             break;
4438         case XML_SCHEMA_CONTENT_MIXED:
4439             fprintf(output, "[mixed] ");
4440             break;
4441         case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
4442         /* not used. */
4443             break;
4444         case XML_SCHEMA_CONTENT_BASIC:
4445             fprintf(output, "[basic] ");
4446             break;
4447         case XML_SCHEMA_CONTENT_SIMPLE:
4448             fprintf(output, "[simple] ");
4449             break;
4450         case XML_SCHEMA_CONTENT_ANY:
4451             fprintf(output, "[any] ");
4452             break;
4453     }
4454     fprintf(output, "\n");
4455     if (type->base != NULL) {
4456         fprintf(output, "  base type: '%s'", type->base);
4457         if (type->baseNs != NULL)
4458             fprintf(output, " ns '%s'\n", type->baseNs);
4459         else
4460             fprintf(output, "\n");
4461     }
4462     if (type->attrUses != NULL)
4463         xmlSchemaAttrUsesDump(type->attrUses, output);
4464     if (type->annot != NULL)
4465         xmlSchemaAnnotDump(output, type->annot);
4466 #ifdef DUMP_CONTENT_MODEL
4467     if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4468         (type->subtypes != NULL)) {
4469         xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4470             output, 1);
4471     }
4472 #endif
4473 }
4474
4475 /**
4476  * xmlSchemaDump:
4477  * @output:  the file output
4478  * @schema:  a schema structure
4479  *
4480  * Dump a Schema structure.
4481  */
4482 void
4483 xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4484 {
4485     if (output == NULL)
4486         return;
4487     if (schema == NULL) {
4488         fprintf(output, "Schemas: NULL\n");
4489         return;
4490     }
4491     fprintf(output, "Schemas: ");
4492     if (schema->name != NULL)
4493         fprintf(output, "%s, ", schema->name);
4494     else
4495         fprintf(output, "no name, ");
4496     if (schema->targetNamespace != NULL)
4497         fprintf(output, "%s", (const char *) schema->targetNamespace);
4498     else
4499         fprintf(output, "no target namespace");
4500     fprintf(output, "\n");
4501     if (schema->annot != NULL)
4502         xmlSchemaAnnotDump(output, schema->annot);
4503     xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
4504                 output);
4505     xmlHashScanFull(schema->elemDecl,
4506                     (xmlHashScannerFull) xmlSchemaElementDump, output);
4507 }
4508
4509 #ifdef DEBUG_IDC_NODE_TABLE
4510 /**
4511  * xmlSchemaDebugDumpIDCTable:
4512  * @vctxt: the WXS validation context
4513  *
4514  * Displays the current IDC table for debug purposes.
4515  */
4516 static void
4517 xmlSchemaDebugDumpIDCTable(FILE * output,
4518                            const xmlChar *namespaceName,
4519                            const xmlChar *localName,
4520                            xmlSchemaPSVIIDCBindingPtr bind)
4521 {
4522     xmlChar *str = NULL;
4523     const xmlChar *value;
4524     xmlSchemaPSVIIDCNodePtr tab;
4525     xmlSchemaPSVIIDCKeyPtr key;
4526     int i, j, res;
4527
4528     fprintf(output, "IDC: TABLES on '%s'\n",
4529         xmlSchemaFormatQName(&str, namespaceName, localName));
4530     FREE_AND_NULL(str)
4531
4532     if (bind == NULL)
4533         return;
4534     do {
4535         fprintf(output, "IDC:   BINDING '%s' (%d)\n",
4536             xmlSchemaGetComponentQName(&str,
4537                 bind->definition), bind->nbNodes);
4538         FREE_AND_NULL(str)
4539         for (i = 0; i < bind->nbNodes; i++) {
4540             tab = bind->nodeTable[i];
4541             fprintf(output, "         ( ");
4542             for (j = 0; j < bind->definition->nbFields; j++) {
4543                 key = tab->keys[j];
4544                 if ((key != NULL) && (key->val != NULL)) {
4545                     res = xmlSchemaGetCanonValue(key->val, &value);
4546                     if (res >= 0)
4547                         fprintf(output, "'%s' ", value);
4548                     else
4549                         fprintf(output, "CANON-VALUE-FAILED ");
4550                     if (res == 0)
4551                         FREE_AND_NULL(value)
4552                 } else if (key != NULL)
4553                     fprintf(output, "(no val), ");
4554                 else
4555                     fprintf(output, "(key missing), ");
4556             }
4557             fprintf(output, ")\n");
4558         }
4559         if (bind->dupls && bind->dupls->nbItems) {
4560             fprintf(output, "IDC:     dupls (%d):\n", bind->dupls->nbItems);
4561             for (i = 0; i < bind->dupls->nbItems; i++) {
4562                 tab = bind->dupls->items[i];
4563                 fprintf(output, "         ( ");
4564                 for (j = 0; j < bind->definition->nbFields; j++) {
4565                     key = tab->keys[j];
4566                     if ((key != NULL) && (key->val != NULL)) {
4567                         res = xmlSchemaGetCanonValue(key->val, &value);
4568                         if (res >= 0)
4569                             fprintf(output, "'%s' ", value);
4570                         else
4571                             fprintf(output, "CANON-VALUE-FAILED ");
4572                         if (res == 0)
4573                             FREE_AND_NULL(value)
4574                     } else if (key != NULL)
4575                     fprintf(output, "(no val), ");
4576                         else
4577                             fprintf(output, "(key missing), ");
4578                 }
4579                 fprintf(output, ")\n");
4580             }
4581         }
4582         bind = bind->next;
4583     } while (bind != NULL);
4584 }
4585 #endif /* DEBUG_IDC */
4586 #endif /* LIBXML_OUTPUT_ENABLED */
4587
4588 /************************************************************************
4589  *                                                                      *
4590  *                      Utilities                                       *
4591  *                                                                      *
4592  ************************************************************************/
4593
4594 /**
4595  * xmlSchemaGetPropNode:
4596  * @node: the element node
4597  * @name: the name of the attribute
4598  *
4599  * Seeks an attribute with a name of @name in
4600  * no namespace.
4601  *
4602  * Returns the attribute or NULL if not present.
4603  */
4604 static xmlAttrPtr
4605 xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
4606 {
4607     xmlAttrPtr prop;
4608
4609     if ((node == NULL) || (name == NULL))
4610         return(NULL);
4611     prop = node->properties;
4612     while (prop != NULL) {
4613         if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
4614             return(prop);
4615         prop = prop->next;
4616     }
4617     return (NULL);
4618 }
4619
4620 /**
4621  * xmlSchemaGetPropNodeNs:
4622  * @node: the element node
4623  * @uri: the uri
4624  * @name: the name of the attribute
4625  *
4626  * Seeks an attribute with a local name of @name and
4627  * a namespace URI of @uri.
4628  *
4629  * Returns the attribute or NULL if not present.
4630  */
4631 static xmlAttrPtr
4632 xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
4633 {
4634     xmlAttrPtr prop;
4635
4636     if ((node == NULL) || (name == NULL))
4637         return(NULL);
4638     prop = node->properties;
4639     while (prop != NULL) {
4640         if ((prop->ns != NULL) &&
4641             xmlStrEqual(prop->name, BAD_CAST name) &&
4642             xmlStrEqual(prop->ns->href, BAD_CAST uri))
4643             return(prop);
4644         prop = prop->next;
4645     }
4646     return (NULL);
4647 }
4648
4649 static const xmlChar *
4650 xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4651 {
4652     xmlChar *val;
4653     const xmlChar *ret;
4654
4655     val = xmlNodeGetContent(node);
4656     if (val == NULL)
4657         val = xmlStrdup((xmlChar *)"");
4658     ret = xmlDictLookup(ctxt->dict, val, -1);
4659     xmlFree(val);
4660     return(ret);
4661 }
4662
4663 static const xmlChar *
4664 xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4665 {
4666     return((const xmlChar*) xmlNodeGetContent(node));
4667 }
4668
4669 /**
4670  * xmlSchemaGetProp:
4671  * @ctxt: the parser context
4672  * @node: the node
4673  * @name: the property name
4674  *
4675  * Read a attribute value and internalize the string
4676  *
4677  * Returns the string or NULL if not present.
4678  */
4679 static const xmlChar *
4680 xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4681                  const char *name)
4682 {
4683     xmlChar *val;
4684     const xmlChar *ret;
4685
4686     val = xmlGetNoNsProp(node, BAD_CAST name);
4687     if (val == NULL)
4688         return(NULL);
4689     ret = xmlDictLookup(ctxt->dict, val, -1);
4690     xmlFree(val);
4691     return(ret);
4692 }
4693
4694 /************************************************************************
4695  *                                                                      *
4696  *                      Parsing functions                               *
4697  *                                                                      *
4698  ************************************************************************/
4699
4700 #define WXS_FIND_GLOBAL_ITEM(slot)                      \
4701     if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4702         ret = xmlHashLookup(schema->slot, name); \
4703         if (ret != NULL) goto exit; \
4704     } \
4705     if (xmlHashSize(schema->schemasImports) > 1) { \
4706         xmlSchemaImportPtr import; \
4707         if (nsName == NULL) \
4708             import = xmlHashLookup(schema->schemasImports, \
4709                 XML_SCHEMAS_NO_NAMESPACE); \
4710         else \
4711             import = xmlHashLookup(schema->schemasImports, nsName); \
4712         if (import == NULL) \
4713             goto exit; \
4714         ret = xmlHashLookup(import->schema->slot, name); \
4715     }
4716
4717 /**
4718  * xmlSchemaGetElem:
4719  * @schema:  the schema context
4720  * @name:  the element name
4721  * @ns:  the element namespace
4722  *
4723  * Lookup a global element declaration in the schema.
4724  *
4725  * Returns the element declaration or NULL if not found.
4726  */
4727 static xmlSchemaElementPtr
4728 xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
4729                  const xmlChar * nsName)
4730 {
4731     xmlSchemaElementPtr ret = NULL;
4732
4733     if ((name == NULL) || (schema == NULL))
4734         return(NULL);
4735     if (schema != NULL) {
4736         WXS_FIND_GLOBAL_ITEM(elemDecl)
4737     }
4738 exit:
4739 #ifdef DEBUG
4740     if (ret == NULL) {
4741         if (nsName == NULL)
4742             fprintf(stderr, "Unable to lookup element decl. %s", name);
4743         else
4744             fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
4745                     nsName);
4746     }
4747 #endif
4748     return (ret);
4749 }
4750
4751 /**
4752  * xmlSchemaGetType:
4753  * @schema:  the main schema
4754  * @name:  the type's name
4755  * nsName:  the type's namespace
4756  *
4757  * Lookup a type in the schemas or the predefined types
4758  *
4759  * Returns the group definition or NULL if not found.
4760  */
4761 static xmlSchemaTypePtr
4762 xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
4763                  const xmlChar * nsName)
4764 {
4765     xmlSchemaTypePtr ret = NULL;
4766
4767     if (name == NULL)
4768         return (NULL);
4769     /* First try the built-in types. */
4770     if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4771         ret = xmlSchemaGetPredefinedType(name, nsName);
4772         if (ret != NULL)
4773             goto exit;
4774         /*
4775         * Note that we try the parsed schemas as well here
4776         * since one might have parsed the S4S, which contain more
4777         * than the built-in types.
4778         * TODO: Can we optimize this?
4779         */
4780     }
4781     if (schema != NULL) {
4782         WXS_FIND_GLOBAL_ITEM(typeDecl)
4783     }
4784 exit:
4785
4786 #ifdef DEBUG
4787     if (ret == NULL) {
4788         if (nsName == NULL)
4789             fprintf(stderr, "Unable to lookup type %s", name);
4790         else
4791             fprintf(stderr, "Unable to lookup type %s:%s", name,
4792                     nsName);
4793     }
4794 #endif
4795     return (ret);
4796 }
4797
4798 /**
4799  * xmlSchemaGetAttributeDecl:
4800  * @schema:  the context of the schema
4801  * @name:  the name of the attribute
4802  * @ns:  the target namespace of the attribute
4803  *
4804  * Lookup a an attribute in the schema or imported schemas
4805  *
4806  * Returns the attribute declaration or NULL if not found.
4807  */
4808 static xmlSchemaAttributePtr
4809 xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
4810                  const xmlChar * nsName)
4811 {
4812     xmlSchemaAttributePtr ret = NULL;
4813
4814     if ((name == NULL) || (schema == NULL))
4815         return (NULL);
4816     if (schema != NULL) {
4817         WXS_FIND_GLOBAL_ITEM(attrDecl)
4818     }
4819 exit:
4820 #ifdef DEBUG
4821     if (ret == NULL) {
4822         if (nsName == NULL)
4823             fprintf(stderr, "Unable to lookup attribute %s", name);
4824         else
4825             fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4826                     nsName);
4827     }
4828 #endif
4829     return (ret);
4830 }
4831
4832 /**
4833  * xmlSchemaGetAttributeGroup:
4834  * @schema:  the context of the schema
4835  * @name:  the name of the attribute group
4836  * @ns:  the target namespace of the attribute group
4837  *
4838  * Lookup a an attribute group in the schema or imported schemas
4839  *
4840  * Returns the attribute group definition or NULL if not found.
4841  */
4842 static xmlSchemaAttributeGroupPtr
4843 xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4844                  const xmlChar * nsName)
4845 {
4846     xmlSchemaAttributeGroupPtr ret = NULL;
4847
4848     if ((name == NULL) || (schema == NULL))
4849         return (NULL);
4850     if (schema != NULL) {
4851         WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4852     }
4853 exit:
4854     /* TODO:
4855     if ((ret != NULL) && (ret->redef != NULL)) {
4856         * Return the last redefinition. *
4857         ret = ret->redef;
4858     }
4859     */
4860 #ifdef DEBUG
4861     if (ret == NULL) {
4862         if (nsName == NULL)
4863             fprintf(stderr, "Unable to lookup attribute group %s", name);
4864         else
4865             fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4866                     nsName);
4867     }
4868 #endif
4869     return (ret);
4870 }
4871
4872 /**
4873  * xmlSchemaGetGroup:
4874  * @schema:  the context of the schema
4875  * @name:  the name of the group
4876  * @ns:  the target namespace of the group
4877  *
4878  * Lookup a group in the schema or imported schemas
4879  *
4880  * Returns the group definition or NULL if not found.
4881  */
4882 static xmlSchemaModelGroupDefPtr
4883 xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4884                  const xmlChar * nsName)
4885 {
4886     xmlSchemaModelGroupDefPtr ret = NULL;
4887
4888     if ((name == NULL) || (schema == NULL))
4889         return (NULL);
4890     if (schema != NULL) {
4891         WXS_FIND_GLOBAL_ITEM(groupDecl)
4892     }
4893 exit:
4894
4895 #ifdef DEBUG
4896     if (ret == NULL) {
4897         if (nsName == NULL)
4898             fprintf(stderr, "Unable to lookup group %s", name);
4899         else
4900             fprintf(stderr, "Unable to lookup group %s:%s", name,
4901                     nsName);
4902     }
4903 #endif
4904     return (ret);
4905 }
4906
4907 static xmlSchemaNotationPtr
4908 xmlSchemaGetNotation(xmlSchemaPtr schema,
4909                      const xmlChar *name,
4910                      const xmlChar *nsName)
4911 {
4912     xmlSchemaNotationPtr ret = NULL;
4913
4914     if ((name == NULL) || (schema == NULL))
4915         return (NULL);
4916     if (schema != NULL) {
4917         WXS_FIND_GLOBAL_ITEM(notaDecl)
4918     }
4919 exit:
4920     return (ret);
4921 }
4922
4923 static xmlSchemaIDCPtr
4924 xmlSchemaGetIDC(xmlSchemaPtr schema,
4925                 const xmlChar *name,
4926                 const xmlChar *nsName)
4927 {
4928     xmlSchemaIDCPtr ret = NULL;
4929
4930     if ((name == NULL) || (schema == NULL))
4931         return (NULL);
4932     if (schema != NULL) {
4933         WXS_FIND_GLOBAL_ITEM(idcDef)
4934     }
4935 exit:
4936     return (ret);
4937 }
4938
4939 /**
4940  * xmlSchemaGetNamedComponent:
4941  * @schema:  the schema
4942  * @name:  the name of the group
4943  * @ns:  the target namespace of the group
4944  *
4945  * Lookup a group in the schema or imported schemas
4946  *
4947  * Returns the group definition or NULL if not found.
4948  */
4949 static xmlSchemaBasicItemPtr
4950 xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4951                            xmlSchemaTypeType itemType,
4952                            const xmlChar *name,
4953                            const xmlChar *targetNs)
4954 {
4955     switch (itemType) {
4956         case XML_SCHEMA_TYPE_GROUP:
4957             return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
4958                 name, targetNs));
4959         case XML_SCHEMA_TYPE_ELEMENT:
4960             return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
4961                 name, targetNs));
4962         default:
4963             TODO
4964             return (NULL);
4965     }
4966 }
4967
4968 /************************************************************************
4969  *                                                                      *
4970  *                      Parsing functions                               *
4971  *                                                                      *
4972  ************************************************************************/
4973
4974 #define IS_BLANK_NODE(n)                                                \
4975     (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
4976
4977 /**
4978  * xmlSchemaIsBlank:
4979  * @str:  a string
4980  * @len: the length of the string or -1
4981  *
4982  * Check if a string is ignorable
4983  *
4984  * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4985  */
4986 static int
4987 xmlSchemaIsBlank(xmlChar * str, int len)
4988 {
4989     if (str == NULL)
4990         return (1);
4991     if (len < 0) {
4992         while (*str != 0) {
4993             if (!(IS_BLANK_CH(*str)))
4994                 return (0);
4995             str++;
4996         }
4997     } else while ((*str != 0) && (len != 0)) {
4998         if (!(IS_BLANK_CH(*str)))
4999             return (0);
5000         str++;
5001         len--;
5002     }
5003
5004     return (1);
5005 }
5006
5007 #define WXS_COMP_NAME(c, t) ((t) (c))->name
5008 #define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
5009 /*
5010 * xmlSchemaFindRedefCompInGraph:
5011 * ATTENTION TODO: This uses pointer comp. for strings.
5012 */
5013 static xmlSchemaBasicItemPtr
5014 xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
5015                               xmlSchemaTypeType type,
5016                               const xmlChar *name,
5017                               const xmlChar *nsName)
5018 {
5019     xmlSchemaBasicItemPtr ret;
5020     int i;
5021
5022     if ((bucket == NULL) || (name == NULL))
5023         return(NULL);
5024     if ((bucket->globals == NULL) ||
5025         (bucket->globals->nbItems == 0))
5026         goto subschemas;
5027     /*
5028     * Search in global components.
5029     */
5030     for (i = 0; i < bucket->globals->nbItems; i++) {
5031         ret = bucket->globals->items[i];
5032         if (ret->type == type) {
5033             switch (type) {
5034                 case XML_SCHEMA_TYPE_COMPLEX:
5035                 case XML_SCHEMA_TYPE_SIMPLE:
5036                     if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
5037                         (WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5038                         nsName))
5039                     {
5040                         return(ret);
5041                     }
5042                     break;
5043                 case XML_SCHEMA_TYPE_GROUP:
5044                     if ((WXS_COMP_NAME(ret,
5045                             xmlSchemaModelGroupDefPtr) == name) &&
5046                         (WXS_COMP_TNS(ret,
5047                             xmlSchemaModelGroupDefPtr) == nsName))
5048                     {
5049                         return(ret);
5050                     }
5051                     break;
5052                 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5053                     if ((WXS_COMP_NAME(ret,
5054                             xmlSchemaAttributeGroupPtr) == name) &&
5055                         (WXS_COMP_TNS(ret,
5056                             xmlSchemaAttributeGroupPtr) == nsName))
5057                     {
5058                         return(ret);
5059                     }
5060                     break;
5061                 default:
5062                     /* Should not be hit. */
5063                     return(NULL);
5064             }
5065         }
5066     }
5067 subschemas:
5068     /*
5069     * Process imported/included schemas.
5070     */
5071     if (bucket->relations != NULL) {
5072         xmlSchemaSchemaRelationPtr rel = bucket->relations;
5073
5074         /*
5075         * TODO: Marking the bucket will not avoid multiple searches
5076         * in the same schema, but avoids at least circularity.
5077         */
5078         bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5079         do {
5080             if ((rel->bucket != NULL) &&
5081                 ((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5082                 ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5083                     type, name, nsName);
5084                 if (ret != NULL)
5085                     return(ret);
5086             }
5087             rel = rel->next;
5088         } while (rel != NULL);
5089          bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5090     }
5091     return(NULL);
5092 }
5093
5094 /**
5095  * xmlSchemaAddNotation:
5096  * @ctxt:  a schema parser context
5097  * @schema:  the schema being built
5098  * @name:  the item name
5099  *
5100  * Add an XML schema annotation declaration
5101  * *WARNING* this interface is highly subject to change
5102  *
5103  * Returns the new struture or NULL in case of error
5104  */
5105 static xmlSchemaNotationPtr
5106 xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5107                      const xmlChar *name, const xmlChar *nsName,
5108                      xmlNodePtr node ATTRIBUTE_UNUSED)
5109 {
5110     xmlSchemaNotationPtr ret = NULL;
5111
5112     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5113         return (NULL);
5114
5115     ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5116     if (ret == NULL) {
5117         xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
5118         return (NULL);
5119     }
5120     memset(ret, 0, sizeof(xmlSchemaNotation));
5121     ret->type = XML_SCHEMA_TYPE_NOTATION;
5122     ret->name = name;
5123     ret->targetNamespace = nsName;
5124     /* TODO: do we need the node to be set?
5125     * ret->node = node;*/
5126     WXS_ADD_GLOBAL(ctxt, ret);
5127     return (ret);
5128 }
5129
5130 /**
5131  * xmlSchemaAddAttribute:
5132  * @ctxt:  a schema parser context
5133  * @schema:  the schema being built
5134  * @name:  the item name
5135  * @namespace:  the namespace
5136  *
5137  * Add an XML schema Attrribute declaration
5138  * *WARNING* this interface is highly subject to change
5139  *
5140  * Returns the new struture or NULL in case of error
5141  */
5142 static xmlSchemaAttributePtr
5143 xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5144                       const xmlChar * name, const xmlChar * nsName,
5145                       xmlNodePtr node, int topLevel)
5146 {
5147     xmlSchemaAttributePtr ret = NULL;
5148
5149     if ((ctxt == NULL) || (schema == NULL))
5150         return (NULL);
5151
5152     ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5153     if (ret == NULL) {
5154         xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
5155         return (NULL);
5156     }
5157     memset(ret, 0, sizeof(xmlSchemaAttribute));
5158     ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5159     ret->node = node;
5160     ret->name = name;
5161     ret->targetNamespace = nsName;
5162
5163     if (topLevel)
5164         WXS_ADD_GLOBAL(ctxt, ret);
5165     else
5166         WXS_ADD_LOCAL(ctxt, ret);
5167     WXS_ADD_PENDING(ctxt, ret);
5168     return (ret);
5169 }
5170
5171 /**
5172  * xmlSchemaAddAttributeUse:
5173  * @ctxt:  a schema parser context
5174  * @schema:  the schema being built
5175  * @name:  the item name
5176  * @namespace:  the namespace
5177  *
5178  * Add an XML schema Attrribute declaration
5179  * *WARNING* this interface is highly subject to change
5180  *
5181  * Returns the new struture or NULL in case of error
5182  */
5183 static xmlSchemaAttributeUsePtr
5184 xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5185                          xmlNodePtr node)
5186 {
5187     xmlSchemaAttributeUsePtr ret = NULL;
5188
5189     if (pctxt == NULL)
5190         return (NULL);
5191
5192     ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5193     if (ret == NULL) {
5194         xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5195         return (NULL);
5196     }
5197     memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5198     ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5199     ret->node = node;
5200
5201     WXS_ADD_LOCAL(pctxt, ret);
5202     return (ret);
5203 }
5204
5205 /*
5206 * xmlSchemaAddRedef:
5207 *
5208 * Adds a redefinition information. This is used at a later stage to:
5209 * resolve references to the redefined components and to check constraints.
5210 */
5211 static xmlSchemaRedefPtr
5212 xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5213                   xmlSchemaBucketPtr targetBucket,
5214                   void *item,
5215                   const xmlChar *refName,
5216                   const xmlChar *refTargetNs)
5217 {
5218     xmlSchemaRedefPtr ret;
5219
5220     ret = (xmlSchemaRedefPtr)
5221         xmlMalloc(sizeof(xmlSchemaRedef));
5222     if (ret == NULL) {
5223         xmlSchemaPErrMemory(pctxt,
5224             "allocating redefinition info", NULL);
5225         return (NULL);
5226     }
5227     memset(ret, 0, sizeof(xmlSchemaRedef));
5228     ret->item = item;
5229     ret->targetBucket = targetBucket;
5230     ret->refName = refName;
5231     ret->refTargetNs = refTargetNs;
5232     if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5233         WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5234     else
5235         WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5236     WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5237
5238     return (ret);
5239 }
5240
5241 /**
5242  * xmlSchemaAddAttributeGroupDefinition:
5243  * @ctxt:  a schema parser context
5244  * @schema:  the schema being built
5245  * @name:  the item name
5246  * @nsName:  the target namespace
5247  * @node: the corresponding node
5248  *
5249  * Add an XML schema Attrribute Group definition.
5250  *
5251  * Returns the new struture or NULL in case of error
5252  */
5253 static xmlSchemaAttributeGroupPtr
5254 xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5255                            xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5256                            const xmlChar *name,
5257                            const xmlChar *nsName,
5258                            xmlNodePtr node)
5259 {
5260     xmlSchemaAttributeGroupPtr ret = NULL;
5261
5262     if ((pctxt == NULL) || (name == NULL))
5263         return (NULL);
5264
5265     ret = (xmlSchemaAttributeGroupPtr)
5266         xmlMalloc(sizeof(xmlSchemaAttributeGroup));
5267     if (ret == NULL) {
5268         xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
5269         return (NULL);
5270     }
5271     memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
5272     ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5273     ret->name = name;
5274     ret->targetNamespace = nsName;
5275     ret->node = node;
5276
5277     /* TODO: Remove the flag. */
5278     ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5279     if (pctxt->isRedefine) {
5280         pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5281             ret, name, nsName);
5282         if (pctxt->redef == NULL) {
5283             xmlFree(ret);
5284             return(NULL);
5285         }
5286         pctxt->redefCounter = 0;
5287     }
5288     WXS_ADD_GLOBAL(pctxt, ret);
5289     WXS_ADD_PENDING(pctxt, ret);
5290     return (ret);
5291 }
5292
5293 /**
5294  * xmlSchemaAddElement:
5295  * @ctxt:  a schema parser context
5296  * @schema:  the schema being built
5297  * @name:  the type name
5298  * @namespace:  the type namespace
5299  *
5300  * Add an XML schema Element declaration
5301  * *WARNING* this interface is highly subject to change
5302  *
5303  * Returns the new struture or NULL in case of error
5304  */
5305 static xmlSchemaElementPtr
5306 xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
5307                     const xmlChar * name, const xmlChar * nsName,
5308                     xmlNodePtr node, int topLevel)
5309 {
5310     xmlSchemaElementPtr ret = NULL;
5311
5312     if ((ctxt == NULL) || (name == NULL))
5313         return (NULL);
5314
5315     ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5316     if (ret == NULL) {
5317         xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
5318         return (NULL);
5319     }
5320     memset(ret, 0, sizeof(xmlSchemaElement));
5321     ret->type = XML_SCHEMA_TYPE_ELEMENT;
5322     ret->name = name;
5323     ret->targetNamespace = nsName;
5324     ret->node = node;
5325
5326     if (topLevel)
5327         WXS_ADD_GLOBAL(ctxt, ret);
5328     else
5329         WXS_ADD_LOCAL(ctxt, ret);
5330     WXS_ADD_PENDING(ctxt, ret);
5331     return (ret);
5332 }
5333
5334 /**
5335  * xmlSchemaAddType:
5336  * @ctxt:  a schema parser context
5337  * @schema:  the schema being built
5338  * @name:  the item name
5339  * @namespace:  the namespace
5340  *
5341  * Add an XML schema item
5342  * *WARNING* this interface is highly subject to change
5343  *
5344  * Returns the new struture or NULL in case of error
5345  */
5346 static xmlSchemaTypePtr
5347 xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5348                  xmlSchemaTypeType type,
5349                  const xmlChar * name, const xmlChar * nsName,
5350                  xmlNodePtr node, int topLevel)
5351 {
5352     xmlSchemaTypePtr ret = NULL;
5353
5354     if ((ctxt == NULL) || (schema == NULL))
5355         return (NULL);
5356
5357     ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5358     if (ret == NULL) {
5359         xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
5360         return (NULL);
5361     }
5362     memset(ret, 0, sizeof(xmlSchemaType));
5363     ret->type = type;
5364     ret->name = name;
5365     ret->targetNamespace = nsName;
5366     ret->node = node;
5367     if (topLevel) {
5368         if (ctxt->isRedefine) {
5369             ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5370                 ret, name, nsName);
5371             if (ctxt->redef == NULL) {
5372                 xmlFree(ret);
5373                 return(NULL);
5374             }
5375             ctxt->redefCounter = 0;
5376         }
5377         WXS_ADD_GLOBAL(ctxt, ret);
5378     } else
5379         WXS_ADD_LOCAL(ctxt, ret);
5380     WXS_ADD_PENDING(ctxt, ret);
5381     return (ret);
5382 }
5383
5384 static xmlSchemaQNameRefPtr
5385 xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
5386                      xmlSchemaTypeType refType,
5387                      const xmlChar *refName,
5388                      const xmlChar *refNs)
5389 {
5390     xmlSchemaQNameRefPtr ret;
5391
5392     ret = (xmlSchemaQNameRefPtr)
5393         xmlMalloc(sizeof(xmlSchemaQNameRef));
5394     if (ret == NULL) {
5395         xmlSchemaPErrMemory(pctxt,
5396             "allocating QName reference item", NULL);
5397         return (NULL);
5398     }
5399     ret->node = NULL;
5400     ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5401     ret->name = refName;
5402     ret->targetNamespace = refNs;
5403     ret->item = NULL;
5404     ret->itemType = refType;
5405     /*
5406     * Store the reference item in the schema.
5407     */
5408     WXS_ADD_LOCAL(pctxt, ret);
5409     return (ret);
5410 }
5411
5412 static xmlSchemaAttributeUseProhibPtr
5413 xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5414 {
5415     xmlSchemaAttributeUseProhibPtr ret;
5416
5417     ret = (xmlSchemaAttributeUseProhibPtr)
5418         xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5419     if (ret == NULL) {
5420         xmlSchemaPErrMemory(pctxt,
5421             "allocating attribute use prohibition", NULL);
5422         return (NULL);
5423     }
5424     memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5425     ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5426     WXS_ADD_LOCAL(pctxt, ret);
5427     return (ret);
5428 }
5429
5430
5431 /**
5432  * xmlSchemaAddModelGroup:
5433  * @ctxt:  a schema parser context
5434  * @schema:  the schema being built
5435  * @type: the "compositor" type of the model group
5436  * @node: the node in the schema doc
5437  *
5438  * Adds a schema model group
5439  * *WARNING* this interface is highly subject to change
5440  *
5441  * Returns the new struture or NULL in case of error
5442  */
5443 static xmlSchemaModelGroupPtr
5444 xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5445                        xmlSchemaPtr schema,
5446                        xmlSchemaTypeType type,
5447                        xmlNodePtr node)
5448 {
5449     xmlSchemaModelGroupPtr ret = NULL;
5450
5451     if ((ctxt == NULL) || (schema == NULL))
5452         return (NULL);
5453
5454     ret = (xmlSchemaModelGroupPtr)
5455         xmlMalloc(sizeof(xmlSchemaModelGroup));
5456     if (ret == NULL) {
5457         xmlSchemaPErrMemory(ctxt, "allocating model group component",
5458             NULL);
5459         return (NULL);
5460     }
5461     memset(ret, 0, sizeof(xmlSchemaModelGroup));
5462     ret->type = type;
5463     ret->node = node;
5464     WXS_ADD_LOCAL(ctxt, ret);
5465     if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5466         (type == XML_SCHEMA_TYPE_CHOICE))
5467         WXS_ADD_PENDING(ctxt, ret);
5468     return (ret);
5469 }
5470
5471
5472 /**
5473  * xmlSchemaAddParticle:
5474  * @ctxt:  a schema parser context
5475  * @schema:  the schema being built
5476  * @node: the corresponding node in the schema doc
5477  * @min: the minOccurs
5478  * @max: the maxOccurs
5479  *
5480  * Adds an XML schema particle component.
5481  * *WARNING* this interface is highly subject to change
5482  *
5483  * Returns the new struture or NULL in case of error
5484  */
5485 static xmlSchemaParticlePtr
5486 xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
5487                      xmlNodePtr node, int min, int max)
5488 {
5489     xmlSchemaParticlePtr ret = NULL;
5490     if (ctxt == NULL)
5491         return (NULL);
5492
5493 #ifdef DEBUG
5494     fprintf(stderr, "Adding particle component\n");
5495 #endif
5496     ret = (xmlSchemaParticlePtr)
5497         xmlMalloc(sizeof(xmlSchemaParticle));
5498     if (ret == NULL) {
5499         xmlSchemaPErrMemory(ctxt, "allocating particle component",
5500             NULL);
5501         return (NULL);
5502     }
5503     ret->type = XML_SCHEMA_TYPE_PARTICLE;
5504     ret->annot = NULL;
5505     ret->node = node;
5506     ret->minOccurs = min;
5507     ret->maxOccurs = max;
5508     ret->next = NULL;
5509     ret->children = NULL;
5510
5511     WXS_ADD_LOCAL(ctxt, ret);
5512     /*
5513     * Note that addition to pending components will be done locally
5514     * to the specific parsing function, since the most particles
5515     * need not to be fixed up (i.e. the reference to be resolved).
5516     * REMOVED: WXS_ADD_PENDING(ctxt, ret);
5517     */
5518     return (ret);
5519 }
5520
5521 /**
5522  * xmlSchemaAddModelGroupDefinition:
5523  * @ctxt:  a schema validation context
5524  * @schema:  the schema being built
5525  * @name:  the group name
5526  *
5527  * Add an XML schema Group definition
5528  *
5529  * Returns the new struture or NULL in case of error
5530  */
5531 static xmlSchemaModelGroupDefPtr
5532 xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5533                                  xmlSchemaPtr schema,
5534                                  const xmlChar *name,
5535                                  const xmlChar *nsName,
5536                                  xmlNodePtr node)
5537 {
5538     xmlSchemaModelGroupDefPtr ret = NULL;
5539
5540     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5541         return (NULL);
5542
5543     ret = (xmlSchemaModelGroupDefPtr)
5544         xmlMalloc(sizeof(xmlSchemaModelGroupDef));
5545     if (ret == NULL) {
5546         xmlSchemaPErrMemory(ctxt, "adding group", NULL);
5547         return (NULL);
5548     }
5549     memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
5550     ret->name = name;
5551     ret->type = XML_SCHEMA_TYPE_GROUP;
5552     ret->node = node;
5553     ret->targetNamespace = nsName;
5554
5555     if (ctxt->isRedefine) {
5556         ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5557             ret, name, nsName);
5558         if (ctxt->redef == NULL) {
5559             xmlFree(ret);
5560             return(NULL);
5561         }
5562         ctxt->redefCounter = 0;
5563     }
5564     WXS_ADD_GLOBAL(ctxt, ret);
5565     WXS_ADD_PENDING(ctxt, ret);
5566     return (ret);
5567 }
5568
5569 /**
5570  * xmlSchemaNewWildcardNs:
5571  * @ctxt:  a schema validation context
5572  *
5573  * Creates a new wildcard namespace constraint.
5574  *
5575  * Returns the new struture or NULL in case of error
5576  */
5577 static xmlSchemaWildcardNsPtr
5578 xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5579 {
5580     xmlSchemaWildcardNsPtr ret;
5581
5582     ret = (xmlSchemaWildcardNsPtr)
5583         xmlMalloc(sizeof(xmlSchemaWildcardNs));
5584     if (ret == NULL) {
5585         xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
5586         return (NULL);
5587     }
5588     ret->value = NULL;
5589     ret->next = NULL;
5590     return (ret);
5591 }
5592
5593 static xmlSchemaIDCPtr
5594 xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5595                   const xmlChar *name, const xmlChar *nsName,
5596                   int category, xmlNodePtr node)
5597 {
5598     xmlSchemaIDCPtr ret = NULL;
5599
5600     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5601         return (NULL);
5602
5603     ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5604     if (ret == NULL) {
5605         xmlSchemaPErrMemory(ctxt,
5606             "allocating an identity-constraint definition", NULL);
5607         return (NULL);
5608     }
5609     memset(ret, 0, sizeof(xmlSchemaIDC));
5610     /* The target namespace of the parent element declaration. */
5611     ret->targetNamespace = nsName;
5612     ret->name = name;
5613     ret->type = category;
5614     ret->node = node;
5615
5616     WXS_ADD_GLOBAL(ctxt, ret);
5617     /*
5618     * Only keyrefs need to be fixup up.
5619     */
5620     if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
5621         WXS_ADD_PENDING(ctxt, ret);
5622     return (ret);
5623 }
5624
5625 /**
5626  * xmlSchemaAddWildcard:
5627  * @ctxt:  a schema validation context
5628  * @schema: a schema
5629  *
5630  * Adds a wildcard.
5631  * It corresponds to a xsd:anyAttribute and xsd:any.
5632  *
5633  * Returns the new struture or NULL in case of error
5634  */
5635 static xmlSchemaWildcardPtr
5636 xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5637                      xmlSchemaTypeType type, xmlNodePtr node)
5638 {
5639     xmlSchemaWildcardPtr ret = NULL;
5640
5641     if ((ctxt == NULL) || (schema == NULL))
5642         return (NULL);
5643
5644     ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5645     if (ret == NULL) {
5646         xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5647         return (NULL);
5648     }
5649     memset(ret, 0, sizeof(xmlSchemaWildcard));
5650     ret->type = type;
5651     ret->node = node;
5652     WXS_ADD_LOCAL(ctxt, ret);
5653     return (ret);
5654 }
5655
5656 static void
5657 xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5658 {
5659     if (group == NULL)
5660         return;
5661     if (group->members != NULL)
5662         xmlSchemaItemListFree(group->members);
5663     xmlFree(group);
5664 }
5665
5666 static xmlSchemaSubstGroupPtr
5667 xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5668                        xmlSchemaElementPtr head)
5669 {
5670     xmlSchemaSubstGroupPtr ret;
5671
5672     /* Init subst group hash. */
5673     if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5674         WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5675         if (WXS_SUBST_GROUPS(pctxt) == NULL)
5676             return(NULL);
5677     }
5678     /* Create a new substitution group. */
5679     ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5680     if (ret == NULL) {
5681         xmlSchemaPErrMemory(NULL,
5682             "allocating a substitution group container", NULL);
5683         return(NULL);
5684     }
5685     memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5686     ret->head = head;
5687     /* Create list of members. */
5688     ret->members = xmlSchemaItemListCreate();
5689     if (ret->members == NULL) {
5690         xmlSchemaSubstGroupFree(ret);
5691         return(NULL);
5692     }
5693     /* Add subst group to hash. */
5694     if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5695         head->name, head->targetNamespace, ret) != 0) {
5696         PERROR_INT("xmlSchemaSubstGroupAdd",
5697             "failed to add a new substitution container");
5698         xmlSchemaSubstGroupFree(ret);
5699         return(NULL);
5700     }
5701     return(ret);
5702 }
5703
5704 static xmlSchemaSubstGroupPtr
5705 xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5706                        xmlSchemaElementPtr head)
5707 {
5708     if (WXS_SUBST_GROUPS(pctxt) == NULL)
5709         return(NULL);
5710     return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5711         head->name, head->targetNamespace));
5712
5713 }
5714
5715 /**
5716  * xmlSchemaAddElementSubstitutionMember:
5717  * @pctxt:  a schema parser context
5718  * @head:  the head of the substitution group
5719  * @member: the new member of the substitution group
5720  *
5721  * Allocate a new annotation structure.
5722  *
5723  * Returns the newly allocated structure or NULL in case or error
5724  */
5725 static int
5726 xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5727                                       xmlSchemaElementPtr head,
5728                                       xmlSchemaElementPtr member)
5729 {
5730     xmlSchemaSubstGroupPtr substGroup = NULL;
5731
5732     if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5733         return (-1);
5734
5735     substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5736     if (substGroup == NULL)
5737         substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5738     if (substGroup == NULL)
5739         return(-1);
5740     if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5741         return(-1);
5742     return(0);
5743 }
5744
5745 /************************************************************************
5746  *                                                                      *
5747  *              Utilities for parsing                                   *
5748  *                                                                      *
5749  ************************************************************************/
5750
5751 /**
5752  * xmlSchemaPValAttrNodeQNameValue:
5753  * @ctxt:  a schema parser context
5754  * @schema: the schema context
5755  * @ownerDes: the designation of the parent element
5756  * @ownerItem: the parent as a schema object
5757  * @value:  the QName value
5758  * @local: the resulting local part if found, the attribute value otherwise
5759  * @uri:  the resulting namespace URI if found
5760  *
5761  * Extracts the local name and the URI of a QName value and validates it.
5762  * This one is intended to be used on attribute values that
5763  * should resolve to schema components.
5764  *
5765  * Returns 0, in case the QName is valid, a positive error code
5766  * if not valid and -1 if an internal error occurs.
5767  */
5768 static int
5769 xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
5770                                        xmlSchemaPtr schema,
5771                                        xmlSchemaBasicItemPtr ownerItem,
5772                                        xmlAttrPtr attr,
5773                                        const xmlChar *value,
5774                                        const xmlChar **uri,
5775                                        const xmlChar **local)
5776 {
5777     const xmlChar *pref;
5778     xmlNsPtr ns;
5779     int len, ret;
5780
5781     *uri = NULL;
5782     *local = NULL;
5783     ret = xmlValidateQName(value, 1);
5784     if (ret > 0) {
5785         xmlSchemaPSimpleTypeErr(ctxt,
5786             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5787             ownerItem, (xmlNodePtr) attr,
5788             xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5789             NULL, value, NULL, NULL, NULL);
5790         *local = value;
5791         return (ctxt->err);
5792     } else if (ret < 0)
5793         return (-1);
5794
5795     if (!strchr((char *) value, ':')) {
5796         ns = xmlSearchNs(attr->doc, attr->parent, NULL);
5797         if (ns)
5798             *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5799         else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5800             /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5801             * parser context. */
5802             /*
5803             * This one takes care of included schemas with no
5804             * target namespace.
5805             */
5806             *uri = ctxt->targetNamespace;
5807         }
5808         *local = xmlDictLookup(ctxt->dict, value, -1);
5809         return (0);
5810     }
5811     /*
5812     * At this point xmlSplitQName3 has to return a local name.
5813     */
5814     *local = xmlSplitQName3(value, &len);
5815     *local = xmlDictLookup(ctxt->dict, *local, -1);
5816     pref = xmlDictLookup(ctxt->dict, value, len);
5817     ns = xmlSearchNs(attr->doc, attr->parent, pref);
5818     if (ns == NULL) {
5819         xmlSchemaPSimpleTypeErr(ctxt,
5820             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5821             ownerItem, (xmlNodePtr) attr,
5822             xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5823             "The value '%s' of simple type 'xs:QName' has no "
5824             "corresponding namespace declaration in scope", value, NULL);
5825         return (ctxt->err);
5826     } else {
5827         *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5828     }
5829     return (0);
5830 }
5831
5832 /**
5833  * xmlSchemaPValAttrNodeQName:
5834  * @ctxt:  a schema parser context
5835  * @schema: the schema context
5836  * @ownerDes: the designation of the owner element
5837  * @ownerItem: the owner as a schema object
5838  * @attr:  the attribute node
5839  * @local: the resulting local part if found, the attribute value otherwise
5840  * @uri:  the resulting namespace URI if found
5841  *
5842  * Extracts and validates the QName of an attribute value.
5843  * This one is intended to be used on attribute values that
5844  * should resolve to schema components.
5845  *
5846  * Returns 0, in case the QName is valid, a positive error code
5847  * if not valid and -1 if an internal error occurs.
5848  */
5849 static int
5850 xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
5851                                        xmlSchemaPtr schema,
5852                                        xmlSchemaBasicItemPtr ownerItem,
5853                                        xmlAttrPtr attr,
5854                                        const xmlChar **uri,
5855                                        const xmlChar **local)
5856 {
5857     const xmlChar *value;
5858
5859     value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5860     return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5861         ownerItem, attr, value, uri, local));
5862 }
5863
5864 /**
5865  * xmlSchemaPValAttrQName:
5866  * @ctxt:  a schema parser context
5867  * @schema: the schema context
5868  * @ownerDes: the designation of the parent element
5869  * @ownerItem: the owner as a schema object
5870  * @ownerElem:  the parent node of the attribute
5871  * @name:  the name of the attribute
5872  * @local: the resulting local part if found, the attribute value otherwise
5873  * @uri:  the resulting namespace URI if found
5874  *
5875  * Extracts and validates the QName of an attribute value.
5876  *
5877  * Returns 0, in case the QName is valid, a positive error code
5878  * if not valid and -1 if an internal error occurs.
5879  */
5880 static int
5881 xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5882                                    xmlSchemaPtr schema,
5883                                    xmlSchemaBasicItemPtr ownerItem,
5884                                    xmlNodePtr ownerElem,
5885                                    const char *name,
5886                                    const xmlChar **uri,
5887                                    const xmlChar **local)
5888 {
5889     xmlAttrPtr attr;
5890
5891     attr = xmlSchemaGetPropNode(ownerElem, name);
5892     if (attr == NULL) {
5893         *local = NULL;
5894         *uri = NULL;
5895         return (0);
5896     }
5897     return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5898         ownerItem, attr, uri, local));
5899 }
5900
5901 /**
5902  * xmlSchemaPValAttrID:
5903  * @ctxt:  a schema parser context
5904  * @schema: the schema context
5905  * @ownerDes: the designation of the parent element
5906  * @ownerItem: the owner as a schema object
5907  * @ownerElem:  the parent node of the attribute
5908  * @name:  the name of the attribute
5909  *
5910  * Extracts and validates the ID of an attribute value.
5911  *
5912  * Returns 0, in case the ID is valid, a positive error code
5913  * if not valid and -1 if an internal error occurs.
5914  */
5915 static int
5916 xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
5917 {
5918     int ret;
5919     const xmlChar *value;
5920
5921     if (attr == NULL)
5922         return(0);
5923     value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
5924     ret = xmlValidateNCName(value, 1);
5925     if (ret == 0) {
5926         /*
5927         * NOTE: the IDness might have already be declared in the DTD
5928         */
5929         if (attr->atype != XML_ATTRIBUTE_ID) {
5930             xmlIDPtr res;
5931             xmlChar *strip;
5932
5933             /*
5934             * TODO: Use xmlSchemaStrip here; it's not exported at this
5935             * moment.
5936             */
5937             strip = xmlSchemaCollapseString(value);
5938             if (strip != NULL) {
5939                 xmlFree((xmlChar *) value);
5940                 value = strip;
5941             }
5942             res = xmlAddID(NULL, attr->doc, value, attr);
5943             if (res == NULL) {
5944                 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5945                 xmlSchemaPSimpleTypeErr(ctxt,
5946                     XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5947                     NULL, (xmlNodePtr) attr,
5948                     xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5949                     NULL, NULL, "Duplicate value '%s' of simple "
5950                     "type 'xs:ID'", value, NULL);
5951             } else
5952                 attr->atype = XML_ATTRIBUTE_ID;
5953         }
5954     } else if (ret > 0) {
5955         ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5956         xmlSchemaPSimpleTypeErr(ctxt,
5957             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5958             NULL, (xmlNodePtr) attr,
5959             xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5960             NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5961             "not a valid 'xs:NCName'",
5962             value, NULL);
5963     }
5964     if (value != NULL)
5965         xmlFree((xmlChar *)value);
5966
5967     return (ret);
5968 }
5969
5970 static int
5971 xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
5972                     xmlNodePtr ownerElem,
5973                     const xmlChar *name)
5974 {
5975     xmlAttrPtr attr;
5976
5977     attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5978     if (attr == NULL)
5979         return(0);
5980     return(xmlSchemaPValAttrNodeID(ctxt, attr));
5981
5982 }
5983
5984 /**
5985  * xmlGetMaxOccurs:
5986  * @ctxt:  a schema validation context
5987  * @node:  a subtree containing XML Schema informations
5988  *
5989  * Get the maxOccurs property
5990  *
5991  * Returns the default if not found, or the value
5992  */
5993 static int
5994 xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5995                 int min, int max, int def, const char *expected)
5996 {
5997     const xmlChar *val, *cur;
5998     int ret = 0;
5999     xmlAttrPtr attr;
6000
6001     attr = xmlSchemaGetPropNode(node, "maxOccurs");
6002     if (attr == NULL)
6003         return (def);
6004     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6005
6006     if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
6007         if (max != UNBOUNDED) {
6008             xmlSchemaPSimpleTypeErr(ctxt,
6009                 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6010                 /* XML_SCHEMAP_INVALID_MINOCCURS, */
6011                 NULL, (xmlNodePtr) attr, NULL, expected,
6012                 val, NULL, NULL, NULL);
6013             return (def);
6014         } else
6015             return (UNBOUNDED);  /* encoding it with -1 might be another option */
6016     }
6017
6018     cur = val;
6019     while (IS_BLANK_CH(*cur))
6020         cur++;
6021     if (*cur == 0) {
6022         xmlSchemaPSimpleTypeErr(ctxt,
6023             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6024             /* XML_SCHEMAP_INVALID_MINOCCURS, */
6025             NULL, (xmlNodePtr) attr, NULL, expected,
6026             val, NULL, NULL, NULL);
6027         return (def);
6028     }
6029     while ((*cur >= '0') && (*cur <= '9')) {
6030         ret = ret * 10 + (*cur - '0');
6031         cur++;
6032     }
6033     while (IS_BLANK_CH(*cur))
6034         cur++;
6035     /*
6036     * TODO: Restrict the maximal value to Integer.
6037     */
6038     if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6039         xmlSchemaPSimpleTypeErr(ctxt,
6040             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6041             /* XML_SCHEMAP_INVALID_MINOCCURS, */
6042             NULL, (xmlNodePtr) attr, NULL, expected,
6043             val, NULL, NULL, NULL);
6044         return (def);
6045     }
6046     return (ret);
6047 }
6048
6049 /**
6050  * xmlGetMinOccurs:
6051  * @ctxt:  a schema validation context
6052  * @node:  a subtree containing XML Schema informations
6053  *
6054  * Get the minOccurs property
6055  *
6056  * Returns the default if not found, or the value
6057  */
6058 static int
6059 xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6060                 int min, int max, int def, const char *expected)
6061 {
6062     const xmlChar *val, *cur;
6063     int ret = 0;
6064     xmlAttrPtr attr;
6065
6066     attr = xmlSchemaGetPropNode(node, "minOccurs");
6067     if (attr == NULL)
6068         return (def);
6069     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6070     cur = val;
6071     while (IS_BLANK_CH(*cur))
6072         cur++;
6073     if (*cur == 0) {
6074         xmlSchemaPSimpleTypeErr(ctxt,
6075             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6076             /* XML_SCHEMAP_INVALID_MINOCCURS, */
6077             NULL, (xmlNodePtr) attr, NULL, expected,
6078             val, NULL, NULL, NULL);
6079         return (def);
6080     }
6081     while ((*cur >= '0') && (*cur <= '9')) {
6082         ret = ret * 10 + (*cur - '0');
6083         cur++;
6084     }
6085     while (IS_BLANK_CH(*cur))
6086         cur++;
6087     /*
6088     * TODO: Restrict the maximal value to Integer.
6089     */
6090     if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6091         xmlSchemaPSimpleTypeErr(ctxt,
6092             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6093             /* XML_SCHEMAP_INVALID_MINOCCURS, */
6094             NULL, (xmlNodePtr) attr, NULL, expected,
6095             val, NULL, NULL, NULL);
6096         return (def);
6097     }
6098     return (ret);
6099 }
6100
6101 /**
6102  * xmlSchemaPGetBoolNodeValue:
6103  * @ctxt:  a schema validation context
6104  * @ownerDes:  owner designation
6105  * @ownerItem:  the owner as a schema item
6106  * @node: the node holding the value
6107  *
6108  * Converts a boolean string value into 1 or 0.
6109  *
6110  * Returns 0 or 1.
6111  */
6112 static int
6113 xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
6114                            xmlSchemaBasicItemPtr ownerItem,
6115                            xmlNodePtr node)
6116 {
6117     xmlChar *value = NULL;
6118     int res = 0;
6119
6120     value = xmlNodeGetContent(node);
6121     /*
6122     * 3.2.2.1 Lexical representation
6123     * An instance of a datatype that is defined as ï¿½boolean�
6124     * can have the following legal literals {true, false, 1, 0}.
6125     */
6126     if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6127         res = 1;
6128     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6129         res = 0;
6130     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6131         res = 1;
6132     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
6133         res = 0;
6134     else {
6135         xmlSchemaPSimpleTypeErr(ctxt,
6136             XML_SCHEMAP_INVALID_BOOLEAN,
6137             ownerItem, node,
6138             xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6139             NULL, BAD_CAST value,
6140             NULL, NULL, NULL);
6141     }
6142     if (value != NULL)
6143         xmlFree(value);
6144     return (res);
6145 }
6146
6147 /**
6148  * xmlGetBooleanProp:
6149  * @ctxt:  a schema validation context
6150  * @node:  a subtree containing XML Schema informations
6151  * @name:  the attribute name
6152  * @def:  the default value
6153  *
6154  * Evaluate if a boolean property is set
6155  *
6156  * Returns the default if not found, 0 if found to be false,
6157  * 1 if found to be true
6158  */
6159 static int
6160 xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
6161                   xmlNodePtr node,
6162                   const char *name, int def)
6163 {
6164     const xmlChar *val;
6165
6166     val = xmlSchemaGetProp(ctxt, node, name);
6167     if (val == NULL)
6168         return (def);
6169     /*
6170     * 3.2.2.1 Lexical representation
6171     * An instance of a datatype that is defined as ï¿½boolean�
6172     * can have the following legal literals {true, false, 1, 0}.
6173     */
6174     if (xmlStrEqual(val, BAD_CAST "true"))
6175         def = 1;
6176     else if (xmlStrEqual(val, BAD_CAST "false"))
6177         def = 0;
6178     else if (xmlStrEqual(val, BAD_CAST "1"))
6179         def = 1;
6180     else if (xmlStrEqual(val, BAD_CAST "0"))
6181         def = 0;
6182     else {
6183         xmlSchemaPSimpleTypeErr(ctxt,
6184             XML_SCHEMAP_INVALID_BOOLEAN,
6185             NULL,
6186             (xmlNodePtr) xmlSchemaGetPropNode(node, name),
6187             xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6188             NULL, val, NULL, NULL, NULL);
6189     }
6190     return (def);
6191 }
6192
6193 /************************************************************************
6194  *                                                                      *
6195  *              Shema extraction from an Infoset                        *
6196  *                                                                      *
6197  ************************************************************************/
6198 static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6199                                                  ctxt, xmlSchemaPtr schema,
6200                                                  xmlNodePtr node,
6201                                                  int topLevel);
6202 static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6203                                                   ctxt,
6204                                                   xmlSchemaPtr schema,
6205                                                   xmlNodePtr node,
6206                                                   int topLevel);
6207 static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6208                                                   ctxt,
6209                                                   xmlSchemaPtr schema,
6210                                                   xmlNodePtr node,
6211                                                   xmlSchemaTypeType parentType);
6212 static xmlSchemaBasicItemPtr
6213 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6214                              xmlSchemaPtr schema,
6215                              xmlNodePtr node,
6216                              xmlSchemaItemListPtr uses,
6217                              int parentType);
6218 static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6219                                            xmlSchemaPtr schema,
6220                                            xmlNodePtr node);
6221 static xmlSchemaWildcardPtr
6222 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6223                            xmlSchemaPtr schema, xmlNodePtr node);
6224
6225 /**
6226  * xmlSchemaPValAttrNodeValue:
6227  *
6228  * @ctxt:  a schema parser context
6229  * @ownerDes: the designation of the parent element
6230  * @ownerItem: the schema object owner if existent
6231  * @attr:  the schema attribute node being validated
6232  * @value: the value
6233  * @type: the built-in type to be validated against
6234  *
6235  * Validates a value against the given built-in type.
6236  * This one is intended to be used internally for validation
6237  * of schema attribute values during parsing of the schema.
6238  *
6239  * Returns 0 if the value is valid, a positive error code
6240  * number otherwise and -1 in case of an internal or API error.
6241  */
6242 static int
6243 xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
6244                            xmlSchemaBasicItemPtr ownerItem,
6245                            xmlAttrPtr attr,
6246                            const xmlChar *value,
6247                            xmlSchemaTypePtr type)
6248 {
6249
6250     int ret = 0;
6251
6252     /*
6253     * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6254     * one is really meant to be used internally, so better not.
6255     */
6256     if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
6257         return (-1);
6258     if (type->type != XML_SCHEMA_TYPE_BASIC) {
6259         PERROR_INT("xmlSchemaPValAttrNodeValue",
6260             "the given type is not a built-in type");
6261         return (-1);
6262     }
6263     switch (type->builtInType) {
6264         case XML_SCHEMAS_NCNAME:
6265         case XML_SCHEMAS_QNAME:
6266         case XML_SCHEMAS_ANYURI:
6267         case XML_SCHEMAS_TOKEN:
6268         case XML_SCHEMAS_LANGUAGE:
6269             ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6270                 (xmlNodePtr) attr);
6271             break;
6272         default: {
6273             PERROR_INT("xmlSchemaPValAttrNodeValue",
6274                 "validation using the given type is not supported while "
6275                 "parsing a schema");
6276             return (-1);
6277         }
6278     }
6279     /*
6280     * TODO: Should we use the S4S error codes instead?
6281     */
6282     if (ret < 0) {
6283         PERROR_INT("xmlSchemaPValAttrNodeValue",
6284             "failed to validate a schema attribute value");
6285         return (-1);
6286     } else if (ret > 0) {
6287         if (WXS_IS_LIST(type))
6288             ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6289         else
6290             ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6291         xmlSchemaPSimpleTypeErr(pctxt,
6292             ret, ownerItem, (xmlNodePtr) attr,
6293             type, NULL, value, NULL, NULL, NULL);
6294     }
6295     return (ret);
6296 }
6297
6298 /**
6299  * xmlSchemaPValAttrNode:
6300  *
6301  * @ctxt:  a schema parser context
6302  * @ownerDes: the designation of the parent element
6303  * @ownerItem: the schema object owner if existent
6304  * @attr:  the schema attribute node being validated
6305  * @type: the built-in type to be validated against
6306  * @value: the resulting value if any
6307  *
6308  * Extracts and validates a value against the given built-in type.
6309  * This one is intended to be used internally for validation
6310  * of schema attribute values during parsing of the schema.
6311  *
6312  * Returns 0 if the value is valid, a positive error code
6313  * number otherwise and -1 in case of an internal or API error.
6314  */
6315 static int
6316 xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
6317                            xmlSchemaBasicItemPtr ownerItem,
6318                            xmlAttrPtr attr,
6319                            xmlSchemaTypePtr type,
6320                            const xmlChar **value)
6321 {
6322     const xmlChar *val;
6323
6324     if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
6325         return (-1);
6326
6327     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6328     if (value != NULL)
6329         *value = val;
6330
6331     return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
6332         val, type));
6333 }
6334
6335 /**
6336  * xmlSchemaPValAttr:
6337  *
6338  * @ctxt:  a schema parser context
6339  * @node: the element node of the attribute
6340  * @ownerDes: the designation of the parent element
6341  * @ownerItem: the schema object owner if existent
6342  * @ownerElem: the owner element node
6343  * @name:  the name of the schema attribute node
6344  * @type: the built-in type to be validated against
6345  * @value: the resulting value if any
6346  *
6347  * Extracts and validates a value against the given built-in type.
6348  * This one is intended to be used internally for validation
6349  * of schema attribute values during parsing of the schema.
6350  *
6351  * Returns 0 if the value is valid, a positive error code
6352  * number otherwise and -1 in case of an internal or API error.
6353  */
6354 static int
6355 xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6356                        xmlSchemaBasicItemPtr ownerItem,
6357                        xmlNodePtr ownerElem,
6358                        const char *name,
6359                        xmlSchemaTypePtr type,
6360                        const xmlChar **value)
6361 {
6362     xmlAttrPtr attr;
6363
6364     if ((ctxt == NULL) || (type == NULL)) {
6365         if (value != NULL)
6366             *value = NULL;
6367         return (-1);
6368     }
6369     if (type->type != XML_SCHEMA_TYPE_BASIC) {
6370         if (value != NULL)
6371             *value = NULL;
6372         xmlSchemaPErr(ctxt, ownerElem,
6373             XML_SCHEMAP_INTERNAL,
6374             "Internal error: xmlSchemaPValAttr, the given "
6375             "type '%s' is not a built-in type.\n",
6376             type->name, NULL);
6377         return (-1);
6378     }
6379     attr = xmlSchemaGetPropNode(ownerElem, name);
6380     if (attr == NULL) {
6381         if (value != NULL)
6382             *value = NULL;
6383         return (0);
6384     }
6385     return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
6386         type, value));
6387 }
6388
6389 static int
6390 xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
6391                   xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6392                   xmlNodePtr node,
6393                   xmlAttrPtr attr,
6394                   const xmlChar *namespaceName)
6395 {
6396     /* TODO: Pointer comparison instead? */
6397     if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
6398         return (0);
6399     if (xmlStrEqual(xmlSchemaNs, namespaceName))
6400         return (0);
6401     /*
6402     * Check if the referenced namespace was <import>ed.
6403     */
6404     if (WXS_BUCKET(pctxt)->relations != NULL) {
6405         xmlSchemaSchemaRelationPtr rel;
6406
6407         rel = WXS_BUCKET(pctxt)->relations;
6408         do {
6409             if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
6410                 xmlStrEqual(namespaceName, rel->importNamespace))
6411                 return (0);
6412             rel = rel->next;
6413         } while (rel != NULL);
6414     }
6415     /*
6416     * No matching <import>ed namespace found.
6417     */
6418     {
6419         xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6420
6421         if (namespaceName == NULL)
6422             xmlSchemaCustomErr(ACTXT_CAST pctxt,
6423                 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6424                 "References from this schema to components in no "
6425                 "namespace are not allowed, since not indicated by an "
6426                 "import statement", NULL, NULL);
6427         else
6428             xmlSchemaCustomErr(ACTXT_CAST pctxt,
6429                 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6430                 "References from this schema to components in the "
6431                 "namespace '%s' are not allowed, since not indicated by an "
6432                 "import statement", namespaceName, NULL);
6433     }
6434     return (XML_SCHEMAP_SRC_RESOLVE);
6435 }
6436
6437 /**
6438  * xmlSchemaParseLocalAttributes:
6439  * @ctxt:  a schema validation context
6440  * @schema:  the schema being built
6441  * @node:  a subtree containing XML Schema informations
6442  * @type:  the hosting type where the attributes will be anchored
6443  *
6444  * Parses attribute uses and attribute declarations and
6445  * attribute group references.
6446  */
6447 static int
6448 xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6449                         xmlNodePtr *child, xmlSchemaItemListPtr *list,
6450                         int parentType, int *hasRefs)
6451 {
6452     void *item;
6453
6454     while ((IS_SCHEMA((*child), "attribute")) ||
6455            (IS_SCHEMA((*child), "attributeGroup"))) {
6456         if (IS_SCHEMA((*child), "attribute")) {
6457             item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6458                 *list, parentType);
6459         } else {
6460             item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6461             if ((item != NULL) && (hasRefs != NULL))
6462                 *hasRefs = 1;
6463         }
6464         if (item != NULL) {
6465             if (*list == NULL) {
6466                 /* TODO: Customize grow factor. */
6467                 *list = xmlSchemaItemListCreate();
6468                 if (*list == NULL)
6469                     return(-1);
6470             }
6471             if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6472                 return(-1);
6473         }
6474         *child = (*child)->next;
6475     }
6476     return (0);
6477 }
6478
6479 /**
6480  * xmlSchemaParseAnnotation:
6481  * @ctxt:  a schema validation context
6482  * @schema:  the schema being built
6483  * @node:  a subtree containing XML Schema informations
6484  *
6485  * parse a XML schema Attrribute declaration
6486  * *WARNING* this interface is highly subject to change
6487  *
6488  * Returns -1 in case of error, 0 if the declaration is improper and
6489  *         1 in case of success.
6490  */
6491 static xmlSchemaAnnotPtr
6492 xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed)
6493 {
6494     xmlSchemaAnnotPtr ret;
6495     xmlNodePtr child = NULL;
6496     xmlAttrPtr attr;
6497     int barked = 0;
6498
6499     /*
6500     * INFO: S4S completed.
6501     */
6502     /*
6503     * id = ID
6504     * {any attributes with non-schema namespace . . .}>
6505     * Content: (appinfo | documentation)*
6506     */
6507     if ((ctxt == NULL) || (node == NULL))
6508         return (NULL);
6509     if (needed)
6510         ret = xmlSchemaNewAnnot(ctxt, node);
6511     else
6512         ret = NULL;
6513     attr = node->properties;
6514     while (attr != NULL) {
6515         if (((attr->ns == NULL) &&
6516             (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
6517             ((attr->ns != NULL) &&
6518             xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6519
6520             xmlSchemaPIllegalAttrErr(ctxt,
6521                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6522         }
6523         attr = attr->next;
6524     }
6525     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6526     /*
6527     * And now for the children...
6528     */
6529     child = node->children;
6530     while (child != NULL) {
6531         if (IS_SCHEMA(child, "appinfo")) {
6532             /* TODO: make available the content of "appinfo". */
6533             /*
6534             * source = anyURI
6535             * {any attributes with non-schema namespace . . .}>
6536             * Content: ({any})*
6537             */
6538             attr = child->properties;
6539             while (attr != NULL) {
6540                 if (((attr->ns == NULL) &&
6541                      (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
6542                      ((attr->ns != NULL) &&
6543                       xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6544
6545                     xmlSchemaPIllegalAttrErr(ctxt,
6546                         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6547                 }
6548                 attr = attr->next;
6549             }
6550             xmlSchemaPValAttr(ctxt, NULL, child, "source",
6551                 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
6552             child = child->next;
6553         } else if (IS_SCHEMA(child, "documentation")) {
6554             /* TODO: make available the content of "documentation". */
6555             /*
6556             * source = anyURI
6557             * {any attributes with non-schema namespace . . .}>
6558             * Content: ({any})*
6559             */
6560             attr = child->properties;
6561             while (attr != NULL) {
6562                 if (attr->ns == NULL) {
6563                     if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
6564                         xmlSchemaPIllegalAttrErr(ctxt,
6565                             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6566                     }
6567                 } else {
6568                     if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6569                         (xmlStrEqual(attr->name, BAD_CAST "lang") &&
6570                         (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
6571
6572                         xmlSchemaPIllegalAttrErr(ctxt,
6573                             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6574                     }
6575                 }
6576                 attr = attr->next;
6577             }
6578             /*
6579             * Attribute "xml:lang".
6580             */
6581             attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6582             if (attr != NULL)
6583                 xmlSchemaPValAttrNode(ctxt, NULL, attr,
6584                 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
6585             child = child->next;
6586         } else {
6587             if (!barked)
6588                 xmlSchemaPContentErr(ctxt,
6589                     XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6590                     NULL, node, child, NULL, "(appinfo | documentation)*");
6591             barked = 1;
6592             child = child->next;
6593         }
6594     }
6595
6596     return (ret);
6597 }
6598
6599 /**
6600  * xmlSchemaParseFacet:
6601  * @ctxt:  a schema validation context
6602  * @schema:  the schema being built
6603  * @node:  a subtree containing XML Schema informations
6604  *
6605  * parse a XML schema Facet declaration
6606  * *WARNING* this interface is highly subject to change
6607  *
6608  * Returns the new type structure or NULL in case of error
6609  */
6610 static xmlSchemaFacetPtr
6611 xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6612                     xmlNodePtr node)
6613 {
6614     xmlSchemaFacetPtr facet;
6615     xmlNodePtr child = NULL;
6616     const xmlChar *value;
6617
6618     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6619         return (NULL);
6620
6621     facet = xmlSchemaNewFacet();
6622     if (facet == NULL) {
6623         xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6624         return (NULL);
6625     }
6626     facet->node = node;
6627     value = xmlSchemaGetProp(ctxt, node, "value");
6628     if (value == NULL) {
6629         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6630                        "Facet %s has no value\n", node->name, NULL);
6631         xmlSchemaFreeFacet(facet);
6632         return (NULL);
6633     }
6634     if (IS_SCHEMA(node, "minInclusive")) {
6635         facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
6636     } else if (IS_SCHEMA(node, "minExclusive")) {
6637         facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
6638     } else if (IS_SCHEMA(node, "maxInclusive")) {
6639         facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
6640     } else if (IS_SCHEMA(node, "maxExclusive")) {
6641         facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
6642     } else if (IS_SCHEMA(node, "totalDigits")) {
6643         facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
6644     } else if (IS_SCHEMA(node, "fractionDigits")) {
6645         facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
6646     } else if (IS_SCHEMA(node, "pattern")) {
6647         facet->type = XML_SCHEMA_FACET_PATTERN;
6648     } else if (IS_SCHEMA(node, "enumeration")) {
6649         facet->type = XML_SCHEMA_FACET_ENUMERATION;
6650     } else if (IS_SCHEMA(node, "whiteSpace")) {
6651         facet->type = XML_SCHEMA_FACET_WHITESPACE;
6652     } else if (IS_SCHEMA(node, "length")) {
6653         facet->type = XML_SCHEMA_FACET_LENGTH;
6654     } else if (IS_SCHEMA(node, "maxLength")) {
6655         facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6656     } else if (IS_SCHEMA(node, "minLength")) {
6657         facet->type = XML_SCHEMA_FACET_MINLENGTH;
6658     } else {
6659         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6660                        "Unknown facet type %s\n", node->name, NULL);
6661         xmlSchemaFreeFacet(facet);
6662         return (NULL);
6663     }
6664     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6665     facet->value = value;
6666     if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6667         (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6668         const xmlChar *fixed;
6669
6670         fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6671         if (fixed != NULL) {
6672             if (xmlStrEqual(fixed, BAD_CAST "true"))
6673                 facet->fixed = 1;
6674         }
6675     }
6676     child = node->children;
6677
6678     if (IS_SCHEMA(child, "annotation")) {
6679         facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6680         child = child->next;
6681     }
6682     if (child != NULL) {
6683         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6684                        "Facet %s has unexpected child content\n",
6685                        node->name, NULL);
6686     }
6687     return (facet);
6688 }
6689
6690 /**
6691  * xmlSchemaParseWildcardNs:
6692  * @ctxt:  a schema parser context
6693  * @wildc:  the wildcard, already created
6694  * @node:  a subtree containing XML Schema informations
6695  *
6696  * Parses the attribute "processContents" and "namespace"
6697  * of a xsd:anyAttribute and xsd:any.
6698  * *WARNING* this interface is highly subject to change
6699  *
6700  * Returns 0 if everything goes fine, a positive error code
6701  * if something is not valid and -1 if an internal error occurs.
6702  */
6703 static int
6704 xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
6705                          xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6706                          xmlSchemaWildcardPtr wildc,
6707                          xmlNodePtr node)
6708 {
6709     const xmlChar *pc, *ns, *dictnsItem;
6710     int ret = 0;
6711     xmlChar *nsItem;
6712     xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6713     xmlAttrPtr attr;
6714
6715     pc = xmlSchemaGetProp(ctxt, node, "processContents");
6716     if ((pc == NULL)
6717         || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6718         wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6719     } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6720         wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6721     } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6722         wildc->processContents = XML_SCHEMAS_ANY_LAX;
6723     } else {
6724         xmlSchemaPSimpleTypeErr(ctxt,
6725             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6726             NULL, node,
6727             NULL, "(strict | skip | lax)", pc,
6728             NULL, NULL, NULL);
6729         wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6730         ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6731     }
6732     /*
6733      * Build the namespace constraints.
6734      */
6735     attr = xmlSchemaGetPropNode(node, "namespace");
6736     ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6737     if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
6738         wildc->any = 1;
6739     else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6740         wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6741         if (wildc->negNsSet == NULL) {
6742             return (-1);
6743         }
6744         wildc->negNsSet->value = ctxt->targetNamespace;
6745     } else {
6746         const xmlChar *end, *cur;
6747
6748         cur = ns;
6749         do {
6750             while (IS_BLANK_CH(*cur))
6751                 cur++;
6752             end = cur;
6753             while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6754                 end++;
6755             if (end == cur)
6756                 break;
6757             nsItem = xmlStrndup(cur, end - cur);
6758             if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6759                     (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
6760                 xmlSchemaPSimpleTypeErr(ctxt,
6761                     XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
6762                     NULL, (xmlNodePtr) attr,
6763                     NULL,
6764                     "((##any | ##other) | List of (xs:anyURI | "
6765                     "(##targetNamespace | ##local)))",
6766                     nsItem, NULL, NULL, NULL);
6767                 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6768             } else {
6769                 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
6770                     dictnsItem = ctxt->targetNamespace;
6771                 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6772                     dictnsItem = NULL;
6773                 } else {
6774                     /*
6775                     * Validate the item (anyURI).
6776                     */
6777                     xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
6778                         nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6779                     dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6780                 }
6781                 /*
6782                 * Avoid dublicate namespaces.
6783                 */
6784                 tmp = wildc->nsSet;
6785                 while (tmp != NULL) {
6786                     if (dictnsItem == tmp->value)
6787                         break;
6788                     tmp = tmp->next;
6789                 }
6790                 if (tmp == NULL) {
6791                     tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6792                     if (tmp == NULL) {
6793                         xmlFree(nsItem);
6794                         return (-1);
6795                     }
6796                     tmp->value = dictnsItem;
6797                     tmp->next = NULL;
6798                     if (wildc->nsSet == NULL)
6799                         wildc->nsSet = tmp;
6800                     else if (lastNs != NULL)
6801                         lastNs->next = tmp;
6802                     lastNs = tmp;
6803                 }
6804
6805             }
6806             xmlFree(nsItem);
6807             cur = end;
6808         } while (*cur != 0);
6809     }
6810     return (ret);
6811 }
6812
6813 static int
6814 xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6815                                  xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
6816                                  xmlNodePtr node,
6817                                  int minOccurs,
6818                                  int maxOccurs) {
6819
6820     if ((maxOccurs == 0) && ( minOccurs == 0))
6821         return (0);
6822     if (maxOccurs != UNBOUNDED) {
6823         /*
6824         * TODO: Maybe we should better not create the particle,
6825         * if min/max is invalid, since it could confuse the build of the
6826         * content model.
6827         */
6828         /*
6829         * 3.9.6 Schema Component Constraint: Particle Correct
6830         *
6831         */
6832         if (maxOccurs < 1) {
6833             /*
6834             * 2.2 {max occurs} must be greater than or equal to 1.
6835             */
6836             xmlSchemaPCustomAttrErr(ctxt,
6837                 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
6838                 NULL, NULL,
6839                 xmlSchemaGetPropNode(node, "maxOccurs"),
6840                 "The value must be greater than or equal to 1");
6841             return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6842         } else if (minOccurs > maxOccurs) {
6843             /*
6844             * 2.1 {min occurs} must not be greater than {max occurs}.
6845             */
6846             xmlSchemaPCustomAttrErr(ctxt,
6847                 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
6848                 NULL, NULL,
6849                 xmlSchemaGetPropNode(node, "minOccurs"),
6850                 "The value must not be greater than the value of 'maxOccurs'");
6851             return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6852         }
6853     }
6854     return (0);
6855 }
6856
6857 /**
6858  * xmlSchemaParseAny:
6859  * @ctxt:  a schema validation context
6860  * @schema:  the schema being built
6861  * @node:  a subtree containing XML Schema informations
6862  *
6863  * Parsea a XML schema <any> element. A particle and wildcard
6864  * will be created (except if minOccurs==maxOccurs==0, in this case
6865  * nothing will be created).
6866  * *WARNING* this interface is highly subject to change
6867  *
6868  * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
6869  */
6870 static xmlSchemaParticlePtr
6871 xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6872                   xmlNodePtr node)
6873 {
6874     xmlSchemaParticlePtr particle;
6875     xmlNodePtr child = NULL;
6876     xmlSchemaWildcardPtr wild;
6877     int min, max;
6878     xmlAttrPtr attr;
6879     xmlSchemaAnnotPtr annot = NULL;
6880
6881     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6882         return (NULL);
6883     /*
6884     * Check for illegal attributes.
6885     */
6886     attr = node->properties;
6887     while (attr != NULL) {
6888         if (attr->ns == NULL) {
6889             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6890                 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6891                 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6892                 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6893                 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
6894                 xmlSchemaPIllegalAttrErr(ctxt,
6895                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6896             }
6897         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6898             xmlSchemaPIllegalAttrErr(ctxt,
6899                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6900         }
6901         attr = attr->next;
6902     }
6903     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6904     /*
6905     * minOccurs/maxOccurs.
6906     */
6907     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6908         "(xs:nonNegativeInteger | unbounded)");
6909     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6910         "xs:nonNegativeInteger");
6911     xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6912     /*
6913     * Create & parse the wildcard.
6914     */
6915     wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6916     if (wild == NULL)
6917         return (NULL);
6918     xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
6919     /*
6920     * And now for the children...
6921     */
6922     child = node->children;
6923     if (IS_SCHEMA(child, "annotation")) {
6924         annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6925         child = child->next;
6926     }
6927     if (child != NULL) {
6928         xmlSchemaPContentErr(ctxt,
6929             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6930             NULL, node, child,
6931             NULL, "(annotation?)");
6932     }
6933     /*
6934     * No component if minOccurs==maxOccurs==0.
6935     */
6936     if ((min == 0) && (max == 0)) {
6937         /* Don't free the wildcard, since it's already on the list. */
6938         return (NULL);
6939     }
6940     /*
6941     * Create the particle.
6942     */
6943     particle = xmlSchemaAddParticle(ctxt, node, min, max);
6944     if (particle == NULL)
6945         return (NULL);
6946     particle->annot = annot;
6947     particle->children = (xmlSchemaTreeItemPtr) wild;
6948
6949     return (particle);
6950 }
6951
6952 /**
6953  * xmlSchemaParseNotation:
6954  * @ctxt:  a schema validation context
6955  * @schema:  the schema being built
6956  * @node:  a subtree containing XML Schema informations
6957  *
6958  * parse a XML schema Notation declaration
6959  *
6960  * Returns the new structure or NULL in case of error
6961  */
6962 static xmlSchemaNotationPtr
6963 xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6964                        xmlNodePtr node)
6965 {
6966     const xmlChar *name;
6967     xmlSchemaNotationPtr ret;
6968     xmlNodePtr child = NULL;
6969
6970     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6971         return (NULL);
6972     name = xmlSchemaGetProp(ctxt, node, "name");
6973     if (name == NULL) {
6974         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6975                        "Notation has no name\n", NULL, NULL);
6976         return (NULL);
6977     }
6978     ret = xmlSchemaAddNotation(ctxt, schema, name,
6979         ctxt->targetNamespace, node);
6980     if (ret == NULL)
6981         return (NULL);
6982     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6983
6984     child = node->children;
6985     if (IS_SCHEMA(child, "annotation")) {
6986         ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6987         child = child->next;
6988     }
6989     if (child != NULL) {
6990         xmlSchemaPContentErr(ctxt,
6991             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6992             NULL, node, child,
6993             NULL, "(annotation?)");
6994     }
6995
6996     return (ret);
6997 }
6998
6999 /**
7000  * xmlSchemaParseAnyAttribute:
7001  * @ctxt:  a schema validation context
7002  * @schema:  the schema being built
7003  * @node:  a subtree containing XML Schema informations
7004  *
7005  * parse a XML schema AnyAttrribute declaration
7006  * *WARNING* this interface is highly subject to change
7007  *
7008  * Returns a wildcard or NULL.
7009  */
7010 static xmlSchemaWildcardPtr
7011 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
7012                            xmlSchemaPtr schema, xmlNodePtr node)
7013 {
7014     xmlSchemaWildcardPtr ret;
7015     xmlNodePtr child = NULL;
7016     xmlAttrPtr attr;
7017
7018     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7019         return (NULL);
7020
7021     ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
7022         node);
7023     if (ret == NULL) {
7024         return (NULL);
7025     }
7026     /*
7027     * Check for illegal attributes.
7028     */
7029     attr = node->properties;
7030     while (attr != NULL) {
7031         if (attr->ns == NULL) {
7032             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7033                 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7034                 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
7035                 xmlSchemaPIllegalAttrErr(ctxt,
7036                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7037             }
7038         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7039             xmlSchemaPIllegalAttrErr(ctxt,
7040                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7041         }
7042         attr = attr->next;
7043     }
7044     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7045     /*
7046     * Parse the namespace list.
7047     */
7048     if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
7049         return (NULL);
7050     /*
7051     * And now for the children...
7052     */
7053     child = node->children;
7054     if (IS_SCHEMA(child, "annotation")) {
7055         ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7056         child = child->next;
7057     }
7058     if (child != NULL) {
7059         xmlSchemaPContentErr(ctxt,
7060             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7061             NULL, node, child,
7062             NULL, "(annotation?)");
7063     }
7064
7065     return (ret);
7066 }
7067
7068
7069 /**
7070  * xmlSchemaParseAttribute:
7071  * @ctxt:  a schema validation context
7072  * @schema:  the schema being built
7073  * @node:  a subtree containing XML Schema informations
7074  *
7075  * parse a XML schema Attrribute declaration
7076  * *WARNING* this interface is highly subject to change
7077  *
7078  * Returns the attribute declaration.
7079  */
7080 static xmlSchemaBasicItemPtr
7081 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7082                              xmlSchemaPtr schema,
7083                              xmlNodePtr node,
7084                              xmlSchemaItemListPtr uses,
7085                              int parentType)
7086 {
7087     const xmlChar *attrValue, *name = NULL, *ns = NULL;
7088     xmlSchemaAttributeUsePtr use = NULL;
7089     xmlNodePtr child = NULL;
7090     xmlAttrPtr attr;
7091     const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7092     int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7093     int nberrors, hasForm = 0, defValueType = 0;
7094
7095 #define WXS_ATTR_DEF_VAL_DEFAULT 1
7096 #define WXS_ATTR_DEF_VAL_FIXED 2
7097
7098     /*
7099      * 3.2.3 Constraints on XML Representations of Attribute Declarations
7100      */
7101
7102     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7103         return (NULL);
7104     attr = xmlSchemaGetPropNode(node, "ref");
7105     if (attr != NULL) {
7106         if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7107             NULL, attr, &tmpNs, &tmpName) != 0) {
7108             return (NULL);
7109         }
7110         if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7111             return(NULL);
7112         isRef = 1;
7113     }
7114     nberrors = pctxt->nberrors;
7115     /*
7116     * Check for illegal attributes.
7117     */
7118     attr = node->properties;
7119     while (attr != NULL) {
7120         if (attr->ns == NULL) {
7121             if (isRef) {
7122                 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7123                     xmlSchemaPValAttrNodeID(pctxt, attr);
7124                     goto attr_next;
7125                 } else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7126                     goto attr_next;
7127                 }
7128             } else {
7129                 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7130                     goto attr_next;
7131                 } else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7132                     xmlSchemaPValAttrNodeID(pctxt, attr);
7133                     goto attr_next;
7134                 } else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7135                     xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7136                         attr, &tmpNs, &tmpName);
7137                     goto attr_next;
7138                 } else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7139                     /*
7140                     * Evaluate the target namespace
7141                     */
7142                     hasForm = 1;
7143                     attrValue = xmlSchemaGetNodeContent(pctxt,
7144                         (xmlNodePtr) attr);
7145                     if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7146                         ns = pctxt->targetNamespace;
7147                     } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7148                     {
7149                         xmlSchemaPSimpleTypeErr(pctxt,
7150                             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7151                             NULL, (xmlNodePtr) attr,
7152                             NULL, "(qualified | unqualified)",
7153                             attrValue, NULL, NULL, NULL);
7154                     }
7155                     goto attr_next;
7156                 }
7157             }
7158             if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7159
7160                 attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7161                 /* TODO: Maybe we need to normalize the value beforehand. */
7162                 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7163                     occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7164                 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7165                     occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7166                 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7167                     occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7168                 else {
7169                     xmlSchemaPSimpleTypeErr(pctxt,
7170                         XML_SCHEMAP_INVALID_ATTR_USE,
7171                         NULL, (xmlNodePtr) attr,
7172                         NULL, "(optional | prohibited | required)",
7173                         attrValue, NULL, NULL, NULL);
7174                 }
7175                 goto attr_next;
7176             } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7177                 /*
7178                 * 3.2.3 : 1
7179                 * default and fixed must not both be present.
7180                 */
7181                 if (defValue) {
7182                     xmlSchemaPMutualExclAttrErr(pctxt,
7183                         XML_SCHEMAP_SRC_ATTRIBUTE_1,
7184                         NULL, attr, "default", "fixed");
7185                 } else {
7186                     defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7187                     defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7188                 }
7189                 goto attr_next;
7190             } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7191                 /*
7192                 * 3.2.3 : 1
7193                 * default and fixed must not both be present.
7194                 */
7195                 if (defValue) {
7196                     xmlSchemaPMutualExclAttrErr(pctxt,
7197                         XML_SCHEMAP_SRC_ATTRIBUTE_1,
7198                         NULL, attr, "default", "fixed");
7199                 } else {
7200                     defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7201                     defValueType = WXS_ATTR_DEF_VAL_FIXED;
7202                 }
7203                 goto attr_next;
7204             }
7205         } else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7206             goto attr_next;
7207
7208         xmlSchemaPIllegalAttrErr(pctxt,
7209             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7210
7211 attr_next:
7212         attr = attr->next;
7213     }
7214     /*
7215     * 3.2.3 : 2
7216     * If default and use are both present, use must have
7217     * the actual value optional.
7218     */
7219     if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7220         (occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7221         xmlSchemaPSimpleTypeErr(pctxt,
7222             XML_SCHEMAP_SRC_ATTRIBUTE_2,
7223             NULL, node, NULL,
7224             "(optional | prohibited | required)", NULL,
7225             "The value of the attribute 'use' must be 'optional' "
7226             "if the attribute 'default' is present",
7227             NULL, NULL);
7228     }
7229     /*
7230     * We want correct attributes.
7231     */
7232     if (nberrors != pctxt->nberrors)
7233         return(NULL);
7234     if (! isRef) {
7235         xmlSchemaAttributePtr attrDecl;
7236
7237         /* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7238         if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7239             ns = pctxt->targetNamespace;
7240         /*
7241         * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7242         * TODO: Move this to the component layer.
7243         */
7244         if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7245             xmlSchemaCustomErr(ACTXT_CAST pctxt,
7246                 XML_SCHEMAP_NO_XSI,
7247                 node, NULL,
7248                 "The target namespace must not match '%s'",
7249                 xmlSchemaInstanceNs, NULL);
7250         }
7251         attr = xmlSchemaGetPropNode(node, "name");
7252         if (attr == NULL) {
7253             xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7254                 NULL, node, "name", NULL);
7255             return (NULL);
7256         }
7257         if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7258             xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7259             return (NULL);
7260         }
7261         /*
7262         * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7263         * TODO: Move this to the component layer.
7264         */
7265         if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7266             xmlSchemaPSimpleTypeErr(pctxt,
7267                 XML_SCHEMAP_NO_XMLNS,
7268                 NULL, (xmlNodePtr) attr,
7269                 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7270                 "The value of the attribute must not match 'xmlns'",
7271                 NULL, NULL);
7272             return (NULL);
7273         }
7274         if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7275             goto check_children;
7276         /*
7277         * Create the attribute use component.
7278         */
7279         use = xmlSchemaAddAttributeUse(pctxt, node);
7280         if (use == NULL)
7281             return(NULL);
7282         use->occurs = occurs;
7283         /*
7284         * Create the attribute declaration.
7285         */
7286         attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7287         if (attrDecl == NULL)
7288             return (NULL);
7289         if (tmpName != NULL) {
7290             attrDecl->typeName = tmpName;
7291             attrDecl->typeNs = tmpNs;
7292         }
7293         use->attrDecl = attrDecl;
7294         /*
7295         * Value constraint.
7296         */
7297         if (defValue != NULL) {
7298             attrDecl->defValue = defValue;
7299             if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7300                 attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7301         }
7302     } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7303         xmlSchemaQNameRefPtr ref;
7304
7305         /*
7306         * Create the attribute use component.
7307         */
7308         use = xmlSchemaAddAttributeUse(pctxt, node);
7309         if (use == NULL)
7310             return(NULL);
7311         /*
7312         * We need to resolve the reference at later stage.
7313         */
7314         WXS_ADD_PENDING(pctxt, use);
7315         use->occurs = occurs;
7316         /*
7317         * Create a QName reference to the attribute declaration.
7318         */
7319         ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7320             tmpName, tmpNs);
7321         if (ref == NULL)
7322             return(NULL);
7323         /*
7324         * Assign the reference. This will be substituted for the
7325         * referenced attribute declaration when the QName is resolved.
7326         */
7327         use->attrDecl = WXS_ATTR_CAST ref;
7328         /*
7329         * Value constraint.
7330         */
7331         if (defValue != NULL)
7332             use->defValue = defValue;
7333             if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7334                 use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7335     }
7336
7337 check_children:
7338     /*
7339     * And now for the children...
7340     */
7341     child = node->children;
7342     if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7343         xmlSchemaAttributeUseProhibPtr prohib;
7344
7345         if (IS_SCHEMA(child, "annotation")) {
7346             xmlSchemaParseAnnotation(pctxt, child, 0);
7347             child = child->next;
7348         }
7349         if (child != NULL) {
7350             xmlSchemaPContentErr(pctxt,
7351                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7352                 NULL, node, child, NULL,
7353                 "(annotation?)");
7354         }
7355         /*
7356         * Check for pointlessness of attribute prohibitions.
7357         */
7358         if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7359             xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7360                 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7361                 node, NULL,
7362                 "Skipping attribute use prohibition, since it is "
7363                 "pointless inside an <attributeGroup>",
7364                 NULL, NULL, NULL);
7365             return(NULL);
7366         } else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7367             xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7368                 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7369                 node, NULL,
7370                 "Skipping attribute use prohibition, since it is "
7371                 "pointless when extending a type",
7372                 NULL, NULL, NULL);
7373             return(NULL);
7374         }
7375         if (! isRef) {
7376             tmpName = name;
7377             tmpNs = ns;
7378         }
7379         /*
7380         * Check for duplicate attribute prohibitions.
7381         */
7382         if (uses) {
7383             int i;
7384
7385             for (i = 0; i < uses->nbItems; i++) {
7386                 use = uses->items[i];
7387                 if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7388                     (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7389                     (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7390                 {
7391                     xmlChar *str = NULL;
7392
7393                     xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7394                         XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7395                         node, NULL,
7396                         "Skipping duplicate attribute use prohibition '%s'",
7397                         xmlSchemaFormatQName(&str, tmpNs, tmpName),
7398                         NULL, NULL);
7399                     FREE_AND_NULL(str)
7400                     return(NULL);
7401                 }
7402             }
7403         }
7404         /*
7405         * Create the attribute prohibition helper component.
7406         */
7407         prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7408         if (prohib == NULL)
7409             return(NULL);
7410         prohib->node = node;
7411         prohib->name = tmpName;
7412         prohib->targetNamespace = tmpNs;
7413         if (isRef) {
7414             /*
7415             * We need at least to resolve to the attribute declaration.
7416             */
7417             WXS_ADD_PENDING(pctxt, prohib);
7418         }
7419         return(WXS_BASIC_CAST prohib);
7420     } else {
7421         if (IS_SCHEMA(child, "annotation")) {
7422             /*
7423             * TODO: Should this go into the attr decl?
7424             */
7425             use->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7426             child = child->next;
7427         }
7428         if (isRef) {
7429             if (child != NULL) {
7430                 if (IS_SCHEMA(child, "simpleType"))
7431                     /*
7432                     * 3.2.3 : 3.2
7433                     * If ref is present, then all of <simpleType>,
7434                     * form and type must be absent.
7435                     */
7436                     xmlSchemaPContentErr(pctxt,
7437                         XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7438                         NULL, node, child, NULL,
7439                         "(annotation?)");
7440                 else
7441                     xmlSchemaPContentErr(pctxt,
7442                         XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7443                         NULL, node, child, NULL,
7444                         "(annotation?)");
7445             }
7446         } else {
7447             if (IS_SCHEMA(child, "simpleType")) {
7448                 if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7449                     /*
7450                     * 3.2.3 : 4
7451                     * type and <simpleType> must not both be present.
7452                     */
7453                     xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7454                         NULL, node, child,
7455                         "The attribute 'type' and the <simpleType> child "
7456                         "are mutually exclusive", NULL);
7457                 } else
7458                     WXS_ATTRUSE_TYPEDEF(use) =
7459                         xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7460                 child = child->next;
7461             }
7462             if (child != NULL)
7463                 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7464                 NULL, node, child, NULL,
7465                 "(annotation?, simpleType?)");
7466         }
7467     }
7468     return (WXS_BASIC_CAST use);
7469 }
7470
7471
7472 static xmlSchemaAttributePtr
7473 xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7474                               xmlSchemaPtr schema,
7475                               xmlNodePtr node)
7476 {
7477     const xmlChar *attrValue;
7478     xmlSchemaAttributePtr ret;
7479     xmlNodePtr child = NULL;
7480     xmlAttrPtr attr;
7481
7482     /*
7483      * Note that the w3c spec assumes the schema to be validated with schema
7484      * for schemas beforehand.
7485      *
7486      * 3.2.3 Constraints on XML Representations of Attribute Declarations
7487      */
7488     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7489         return (NULL);
7490     /*
7491     * 3.2.3 : 3.1
7492     * One of ref or name must be present, but not both
7493     */
7494     attr = xmlSchemaGetPropNode(node, "name");
7495     if (attr == NULL) {
7496         xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7497             NULL, node, "name", NULL);
7498         return (NULL);
7499     }
7500     if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7501         xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7502         return (NULL);
7503     }
7504     /*
7505     * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7506     * TODO: Move this to the component layer.
7507     */
7508     if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7509         xmlSchemaPSimpleTypeErr(pctxt,
7510             XML_SCHEMAP_NO_XMLNS,
7511             NULL, (xmlNodePtr) attr,
7512             xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7513             "The value of the attribute must not match 'xmlns'",
7514             NULL, NULL);
7515         return (NULL);
7516     }
7517     /*
7518     * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7519     * TODO: Move this to the component layer.
7520     *       Or better leave it here and add it to the component layer
7521     *       if we have a schema construction API.
7522     */
7523     if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7524         xmlSchemaCustomErr(ACTXT_CAST pctxt,
7525             XML_SCHEMAP_NO_XSI, node, NULL,
7526             "The target namespace must not match '%s'",
7527             xmlSchemaInstanceNs, NULL);
7528     }
7529
7530     ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7531         pctxt->targetNamespace, node, 1);
7532     if (ret == NULL)
7533         return (NULL);
7534     ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7535
7536     /*
7537     * Check for illegal attributes.
7538     */
7539     attr = node->properties;
7540     while (attr != NULL) {
7541         if (attr->ns == NULL) {
7542             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7543                 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7544                 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7545                 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7546                 (!xmlStrEqual(attr->name, BAD_CAST "type")))
7547             {
7548                 xmlSchemaPIllegalAttrErr(pctxt,
7549                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7550             }
7551         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7552             xmlSchemaPIllegalAttrErr(pctxt,
7553                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7554         }
7555         attr = attr->next;
7556     }
7557     xmlSchemaPValAttrQName(pctxt, schema, NULL,
7558         node, "type", &ret->typeNs, &ret->typeName);
7559
7560     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7561     /*
7562     * Attribute "fixed".
7563     */
7564     ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
7565     if (ret->defValue != NULL)
7566         ret->flags |= XML_SCHEMAS_ATTR_FIXED;
7567     /*
7568     * Attribute "default".
7569     */
7570     attr = xmlSchemaGetPropNode(node, "default");
7571     if (attr != NULL) {
7572         /*
7573         * 3.2.3 : 1
7574         * default and fixed must not both be present.
7575         */
7576         if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
7577             xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7578                 WXS_BASIC_CAST ret, attr, "default", "fixed");
7579         } else
7580             ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7581     }
7582     /*
7583     * And now for the children...
7584     */
7585     child = node->children;
7586     if (IS_SCHEMA(child, "annotation")) {
7587         ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7588         child = child->next;
7589     }
7590     if (IS_SCHEMA(child, "simpleType")) {
7591         if (ret->typeName != NULL) {
7592             /*
7593             * 3.2.3 : 4
7594             * type and <simpleType> must not both be present.
7595             */
7596             xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7597                 NULL, node, child,
7598                 "The attribute 'type' and the <simpleType> child "
7599                 "are mutually exclusive", NULL);
7600         } else
7601             ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7602         child = child->next;
7603     }
7604     if (child != NULL)
7605         xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7606             NULL, node, child, NULL,
7607             "(annotation?, simpleType?)");
7608
7609     return (ret);
7610 }
7611
7612 /**
7613  * xmlSchemaParseAttributeGroupRef:
7614  * @ctxt:  a schema validation context
7615  * @schema:  the schema being built
7616  * @node:  a subtree containing XML Schema informations
7617  *
7618  * Parse an attribute group definition reference.
7619  * Note that a reference to an attribute group does not
7620  * correspond to any component at all.
7621  * *WARNING* this interface is highly subject to change
7622  *
7623  * Returns the attribute group or NULL in case of error.
7624  */
7625 static xmlSchemaQNameRefPtr
7626 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7627                                 xmlSchemaPtr schema,
7628                                 xmlNodePtr node)
7629 {
7630     xmlSchemaQNameRefPtr ret;
7631     xmlNodePtr child = NULL;
7632     xmlAttrPtr attr;
7633     const xmlChar *refNs = NULL, *ref = NULL;
7634
7635     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7636         return (NULL);
7637
7638     attr = xmlSchemaGetPropNode(node, "ref");
7639     if (attr == NULL) {
7640         xmlSchemaPMissingAttrErr(pctxt,
7641             XML_SCHEMAP_S4S_ATTR_MISSING,
7642             NULL, node, "ref", NULL);
7643         return (NULL);
7644     }
7645     xmlSchemaPValAttrNodeQName(pctxt, schema,
7646         NULL, attr, &refNs, &ref);
7647     if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7648         return(NULL);
7649
7650     /*
7651     * Check for illegal attributes.
7652     */
7653     attr = node->properties;
7654     while (attr != NULL) {
7655         if (attr->ns == NULL) {
7656             if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
7657                 (!xmlStrEqual(attr->name, BAD_CAST "id")))
7658             {
7659                 xmlSchemaPIllegalAttrErr(pctxt,
7660                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7661             }
7662         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7663             xmlSchemaPIllegalAttrErr(pctxt,
7664                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7665         }
7666         attr = attr->next;
7667     }
7668     /* Attribute ID */
7669     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7670
7671     /*
7672     * And now for the children...
7673     */
7674     child = node->children;
7675     if (IS_SCHEMA(child, "annotation")) {
7676         /*
7677         * TODO: We do not have a place to store the annotation, do we?
7678         */
7679         xmlSchemaParseAnnotation(pctxt, child, 0);
7680         child = child->next;
7681     }
7682     if (child != NULL) {
7683         xmlSchemaPContentErr(pctxt,
7684             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7685             NULL, node, child, NULL,
7686             "(annotation?)");
7687     }
7688
7689     /*
7690     * Handle attribute group redefinitions.
7691     */
7692     if (pctxt->isRedefine && pctxt->redef &&
7693         (pctxt->redef->item->type ==
7694             XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7695         (ref == pctxt->redef->refName) &&
7696         (refNs == pctxt->redef->refTargetNs))
7697     {
7698         /*
7699         * SPEC src-redefine:
7700         * (7.1) "If it has an <attributeGroup> among its contents
7701         * the ï¿½actual value� of whose ref [attribute] is the same
7702         * as the ï¿½actual value� of its own name attribute plus
7703         * target namespace, then it must have exactly one such group."
7704         */
7705         if (pctxt->redefCounter != 0) {
7706             xmlChar *str = NULL;
7707
7708             xmlSchemaCustomErr(ACTXT_CAST pctxt,
7709                 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7710                 "The redefining attribute group definition "
7711                 "'%s' must not contain more than one "
7712                 "reference to the redefined definition",
7713                 xmlSchemaFormatQName(&str, refNs, ref), NULL);
7714             FREE_AND_NULL(str);
7715             return(NULL);
7716         }
7717         pctxt->redefCounter++;
7718         /*
7719         * URGENT TODO: How to ensure that the reference will not be
7720         * handled by the normal component resolution mechanism?
7721         */
7722         ret = xmlSchemaNewQNameRef(pctxt,
7723             XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7724         if (ret == NULL)
7725             return(NULL);
7726         ret->node = node;
7727         pctxt->redef->reference = WXS_BASIC_CAST ret;
7728     } else {
7729         /*
7730         * Create a QName-reference helper component. We will substitute this
7731         * component for the attribute uses of the referenced attribute group
7732         * definition.
7733         */
7734         ret = xmlSchemaNewQNameRef(pctxt,
7735             XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7736         if (ret == NULL)
7737             return(NULL);
7738         ret->node = node;
7739         /* Add to pending items, to be able to resolve the reference. */
7740         WXS_ADD_PENDING(pctxt, ret);
7741     }
7742     return (ret);
7743 }
7744
7745 /**
7746  * xmlSchemaParseAttributeGroupDefinition:
7747  * @pctxt:  a schema validation context
7748  * @schema:  the schema being built
7749  * @node:  a subtree containing XML Schema informations
7750  *
7751  * parse a XML schema Attribute Group declaration
7752  * *WARNING* this interface is highly subject to change
7753  *
7754  * Returns the attribute group definition or NULL in case of error.
7755  */
7756 static xmlSchemaAttributeGroupPtr
7757 xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7758                                        xmlSchemaPtr schema,
7759                                        xmlNodePtr node)
7760 {
7761     const xmlChar *name;
7762     xmlSchemaAttributeGroupPtr ret;
7763     xmlNodePtr child = NULL;
7764     xmlAttrPtr attr;
7765     int hasRefs = 0;
7766
7767     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7768         return (NULL);
7769
7770     attr = xmlSchemaGetPropNode(node, "name");
7771     if (attr == NULL) {
7772         xmlSchemaPMissingAttrErr(pctxt,
7773             XML_SCHEMAP_S4S_ATTR_MISSING,
7774             NULL, node, "name", NULL);
7775         return (NULL);
7776     }
7777     /*
7778     * The name is crucial, exit if invalid.
7779     */
7780     if (xmlSchemaPValAttrNode(pctxt,
7781         NULL, attr,
7782         xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7783         return (NULL);
7784     }
7785     ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7786         name, pctxt->targetNamespace, node);
7787     if (ret == NULL)
7788         return (NULL);
7789     /*
7790     * Check for illegal attributes.
7791     */
7792     attr = node->properties;
7793     while (attr != NULL) {
7794         if (attr->ns == NULL) {
7795             if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7796                 (!xmlStrEqual(attr->name, BAD_CAST "id")))
7797             {
7798                 xmlSchemaPIllegalAttrErr(pctxt,
7799                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7800             }
7801         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7802             xmlSchemaPIllegalAttrErr(pctxt,
7803                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7804         }
7805         attr = attr->next;
7806     }
7807     /* Attribute ID */
7808     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7809     /*
7810     * And now for the children...
7811     */
7812     child = node->children;
7813     if (IS_SCHEMA(child, "annotation")) {
7814         ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7815         child = child->next;
7816     }
7817     /*
7818     * Parse contained attribute decls/refs.
7819     */
7820     if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7821         (xmlSchemaItemListPtr *) &(ret->attrUses),
7822         XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7823         return(NULL);
7824     if (hasRefs)
7825         ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7826     /*
7827     * Parse the attribute wildcard.
7828     */
7829     if (IS_SCHEMA(child, "anyAttribute")) {
7830         ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7831             schema, child);
7832         child = child->next;
7833     }
7834     if (child != NULL) {
7835         xmlSchemaPContentErr(pctxt,
7836             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7837             NULL, node, child, NULL,
7838             "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
7839     }
7840     return (ret);
7841 }
7842
7843 /**
7844  * xmlSchemaPValAttrFormDefault:
7845  * @value:  the value
7846  * @flags: the flags to be modified
7847  * @flagQualified: the specific flag for "qualified"
7848  *
7849  * Returns 0 if the value is valid, 1 otherwise.
7850  */
7851 static int
7852 xmlSchemaPValAttrFormDefault(const xmlChar *value,
7853                              int *flags,
7854                              int flagQualified)
7855 {
7856     if (xmlStrEqual(value, BAD_CAST "qualified")) {
7857         if  ((*flags & flagQualified) == 0)
7858             *flags |= flagQualified;
7859     } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
7860         return (1);
7861
7862     return (0);
7863 }
7864
7865 /**
7866  * xmlSchemaPValAttrBlockFinal:
7867  * @value:  the value
7868  * @flags: the flags to be modified
7869  * @flagAll: the specific flag for "#all"
7870  * @flagExtension: the specific flag for "extension"
7871  * @flagRestriction: the specific flag for "restriction"
7872  * @flagSubstitution: the specific flag for "substitution"
7873  * @flagList: the specific flag for "list"
7874  * @flagUnion: the specific flag for "union"
7875  *
7876  * Validates the value of the attribute "final" and "block". The value
7877  * is converted into the specified flag values and returned in @flags.
7878  *
7879  * Returns 0 if the value is valid, 1 otherwise.
7880  */
7881
7882 static int
7883 xmlSchemaPValAttrBlockFinal(const xmlChar *value,
7884                             int *flags,
7885                             int flagAll,
7886                             int flagExtension,
7887                             int flagRestriction,
7888                             int flagSubstitution,
7889                             int flagList,
7890                             int flagUnion)
7891 {
7892     int ret = 0;
7893
7894     /*
7895     * TODO: This does not check for dublicate entries.
7896     */
7897     if ((flags == NULL) || (value == NULL))
7898         return (-1);
7899     if (value[0] == 0)
7900         return (0);
7901     if (xmlStrEqual(value, BAD_CAST "#all")) {
7902         if (flagAll != -1)
7903             *flags |= flagAll;
7904         else {
7905             if (flagExtension != -1)
7906                 *flags |= flagExtension;
7907             if (flagRestriction != -1)
7908                 *flags |= flagRestriction;
7909             if (flagSubstitution != -1)
7910                 *flags |= flagSubstitution;
7911             if (flagList != -1)
7912                 *flags |= flagList;
7913             if (flagUnion != -1)
7914                 *flags |= flagUnion;
7915         }
7916     } else {
7917         const xmlChar *end, *cur = value;
7918         xmlChar *item;
7919
7920         do {
7921             while (IS_BLANK_CH(*cur))
7922                 cur++;
7923             end = cur;
7924             while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7925                 end++;
7926             if (end == cur)
7927                 break;
7928             item = xmlStrndup(cur, end - cur);
7929             if (xmlStrEqual(item, BAD_CAST "extension")) {
7930                 if (flagExtension != -1) {
7931                     if ((*flags & flagExtension) == 0)
7932                         *flags |= flagExtension;
7933                 } else
7934                     ret = 1;
7935             } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
7936                 if (flagRestriction != -1) {
7937                     if ((*flags & flagRestriction) == 0)
7938                         *flags |= flagRestriction;
7939                 } else
7940                     ret = 1;
7941             } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
7942                 if (flagSubstitution != -1) {
7943                     if ((*flags & flagSubstitution) == 0)
7944                         *flags |= flagSubstitution;
7945                 } else
7946                     ret = 1;
7947             } else if (xmlStrEqual(item, BAD_CAST "list")) {
7948                 if (flagList != -1) {
7949                     if ((*flags & flagList) == 0)
7950                         *flags |= flagList;
7951                 } else
7952                     ret = 1;
7953             } else if (xmlStrEqual(item, BAD_CAST "union")) {
7954                 if (flagUnion != -1) {
7955                     if ((*flags & flagUnion) == 0)
7956                         *flags |= flagUnion;
7957                 } else
7958                     ret = 1;
7959             } else
7960                 ret = 1;
7961             if (item != NULL)
7962                 xmlFree(item);
7963             cur = end;
7964         } while ((ret == 0) && (*cur != 0));
7965     }
7966
7967     return (ret);
7968 }
7969
7970 static int
7971 xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
7972                              xmlSchemaIDCPtr idc,
7973                              xmlSchemaIDCSelectPtr selector,
7974                              xmlAttrPtr attr,
7975                              int isField)
7976 {
7977     xmlNodePtr node;
7978
7979     /*
7980     * c-selector-xpath:
7981     * Schema Component Constraint: Selector Value OK
7982     *
7983     * TODO: 1 The {selector} must be a valid XPath expression, as defined
7984     * in [XPath].
7985     */
7986     if (selector == NULL) {
7987         xmlSchemaPErr(ctxt, idc->node,
7988             XML_SCHEMAP_INTERNAL,
7989             "Internal error: xmlSchemaCheckCSelectorXPath, "
7990             "the selector is not specified.\n", NULL, NULL);
7991         return (-1);
7992     }
7993     if (attr == NULL)
7994         node = idc->node;
7995     else
7996         node = (xmlNodePtr) attr;
7997     if (selector->xpath == NULL) {
7998         xmlSchemaPCustomErr(ctxt,
7999             /* TODO: Adjust error code. */
8000             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8001             NULL, node,
8002             "The XPath expression of the selector is not valid", NULL);
8003         return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8004     } else {
8005         const xmlChar **nsArray = NULL;
8006         xmlNsPtr *nsList = NULL;
8007         /*
8008         * Compile the XPath expression.
8009         */
8010         /*
8011         * TODO: We need the array of in-scope namespaces for compilation.
8012         * TODO: Call xmlPatterncompile with different options for selector/
8013         * field.
8014         */
8015         if (attr == NULL)
8016             nsList = NULL;
8017         else
8018             nsList = xmlGetNsList(attr->doc, attr->parent);
8019         /*
8020         * Build an array of prefixes and namespaces.
8021         */
8022         if (nsList != NULL) {
8023             int i, count = 0;
8024
8025             for (i = 0; nsList[i] != NULL; i++)
8026                 count++;
8027
8028             nsArray = (const xmlChar **) xmlMalloc(
8029                 (count * 2 + 1) * sizeof(const xmlChar *));
8030             if (nsArray == NULL) {
8031                 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
8032                     NULL);
8033                 xmlFree(nsList);
8034                 return (-1);
8035             }
8036             for (i = 0; i < count; i++) {
8037                 nsArray[2 * i] = nsList[i]->href;
8038                 nsArray[2 * i + 1] = nsList[i]->prefix;
8039             }
8040             nsArray[count * 2] = NULL;
8041             xmlFree(nsList);
8042         }
8043         /*
8044         * TODO: Differentiate between "selector" and "field".
8045         */
8046         if (isField)
8047             selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8048                 NULL, XML_PATTERN_XSFIELD, nsArray);
8049         else
8050             selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8051                 NULL, XML_PATTERN_XSSEL, nsArray);
8052         if (nsArray != NULL)
8053             xmlFree((xmlChar **) nsArray);
8054
8055         if (selector->xpathComp == NULL) {
8056             xmlSchemaPCustomErr(ctxt,
8057                 /* TODO: Adjust error code? */
8058                 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8059                 NULL, node,
8060                 "The XPath expression '%s' could not be "
8061                 "compiled", selector->xpath);
8062             return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8063         }
8064     }
8065     return (0);
8066 }
8067
8068 #define ADD_ANNOTATION(annot)   \
8069     xmlSchemaAnnotPtr cur = item->annot; \
8070     if (item->annot == NULL) {  \
8071         item->annot = annot;    \
8072         return (annot);         \
8073     }                           \
8074     cur = item->annot;          \
8075     if (cur->next != NULL) {    \
8076         cur = cur->next;        \
8077     }                           \
8078     cur->next = annot;
8079
8080 /**
8081  * xmlSchemaAssignAnnotation:
8082  * @item: the schema component
8083  * @annot: the annotation
8084  *
8085  * Adds the annotation to the given schema component.
8086  *
8087  * Returns the given annotaion.
8088  */
8089 static xmlSchemaAnnotPtr
8090 xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8091                        xmlSchemaAnnotPtr annot)
8092 {
8093     if ((annItem == NULL) || (annot == NULL))
8094         return (NULL);
8095     switch (annItem->type) {
8096         case XML_SCHEMA_TYPE_ELEMENT: {
8097                 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8098                 ADD_ANNOTATION(annot)
8099             }
8100             break;
8101         case XML_SCHEMA_TYPE_ATTRIBUTE: {
8102                 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8103                 ADD_ANNOTATION(annot)
8104             }
8105             break;
8106         case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8107         case XML_SCHEMA_TYPE_ANY: {
8108                 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8109                 ADD_ANNOTATION(annot)
8110             }
8111             break;
8112         case XML_SCHEMA_TYPE_PARTICLE:
8113         case XML_SCHEMA_TYPE_IDC_KEY:
8114         case XML_SCHEMA_TYPE_IDC_KEYREF:
8115         case XML_SCHEMA_TYPE_IDC_UNIQUE: {
8116                 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8117                 ADD_ANNOTATION(annot)
8118             }
8119             break;
8120         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8121                 xmlSchemaAttributeGroupPtr item =
8122                     (xmlSchemaAttributeGroupPtr) annItem;
8123                 ADD_ANNOTATION(annot)
8124             }
8125             break;
8126         case XML_SCHEMA_TYPE_NOTATION: {
8127                 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8128                 ADD_ANNOTATION(annot)
8129             }
8130             break;
8131         case XML_SCHEMA_FACET_MININCLUSIVE:
8132         case XML_SCHEMA_FACET_MINEXCLUSIVE:
8133         case XML_SCHEMA_FACET_MAXINCLUSIVE:
8134         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8135         case XML_SCHEMA_FACET_TOTALDIGITS:
8136         case XML_SCHEMA_FACET_FRACTIONDIGITS:
8137         case XML_SCHEMA_FACET_PATTERN:
8138         case XML_SCHEMA_FACET_ENUMERATION:
8139         case XML_SCHEMA_FACET_WHITESPACE:
8140         case XML_SCHEMA_FACET_LENGTH:
8141         case XML_SCHEMA_FACET_MAXLENGTH:
8142         case XML_SCHEMA_FACET_MINLENGTH: {
8143                 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8144                 ADD_ANNOTATION(annot)
8145             }
8146             break;
8147         case XML_SCHEMA_TYPE_SIMPLE:
8148         case XML_SCHEMA_TYPE_COMPLEX: {
8149                 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8150                 ADD_ANNOTATION(annot)
8151             }
8152             break;
8153         case XML_SCHEMA_TYPE_GROUP: {
8154                 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8155                 ADD_ANNOTATION(annot)
8156             }
8157             break;
8158         case XML_SCHEMA_TYPE_SEQUENCE:
8159         case XML_SCHEMA_TYPE_CHOICE:
8160         case XML_SCHEMA_TYPE_ALL: {
8161                 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8162                 ADD_ANNOTATION(annot)
8163             }
8164             break;
8165         default:
8166              xmlSchemaPCustomErr(NULL,
8167                 XML_SCHEMAP_INTERNAL,
8168                 NULL, NULL,
8169                 "Internal error: xmlSchemaAddAnnotation, "
8170                 "The item is not a annotated schema component", NULL);
8171              break;
8172     }
8173     return (annot);
8174 }
8175
8176 /**
8177  * xmlSchemaParseIDCSelectorAndField:
8178  * @ctxt:  a schema validation context
8179  * @schema:  the schema being built
8180  * @node:  a subtree containing XML Schema informations
8181  *
8182  * Parses a XML Schema identity-contraint definition's
8183  * <selector> and <field> elements.
8184  *
8185  * Returns the parsed identity-constraint definition.
8186  */
8187 static xmlSchemaIDCSelectPtr
8188 xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
8189                           xmlSchemaIDCPtr idc,
8190                           xmlNodePtr node,
8191                           int isField)
8192 {
8193     xmlSchemaIDCSelectPtr item;
8194     xmlNodePtr child = NULL;
8195     xmlAttrPtr attr;
8196
8197     /*
8198     * Check for illegal attributes.
8199     */
8200     attr = node->properties;
8201     while (attr != NULL) {
8202         if (attr->ns == NULL) {
8203             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8204                 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
8205                 xmlSchemaPIllegalAttrErr(ctxt,
8206                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8207             }
8208         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8209             xmlSchemaPIllegalAttrErr(ctxt,
8210                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8211         }
8212         attr = attr->next;
8213     }
8214     /*
8215     * Create the item.
8216     */
8217     item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8218     if (item == NULL) {
8219         xmlSchemaPErrMemory(ctxt,
8220             "allocating a 'selector' of an identity-constraint definition",
8221             NULL);
8222         return (NULL);
8223     }
8224     memset(item, 0, sizeof(xmlSchemaIDCSelect));
8225     /*
8226     * Attribute "xpath" (mandatory).
8227     */
8228     attr = xmlSchemaGetPropNode(node, "xpath");
8229     if (attr == NULL) {
8230         xmlSchemaPMissingAttrErr(ctxt,
8231             XML_SCHEMAP_S4S_ATTR_MISSING,
8232             NULL, node,
8233             "name", NULL);
8234     } else {
8235         item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8236         /*
8237         * URGENT TODO: "field"s have an other syntax than "selector"s.
8238         */
8239
8240         if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8241             isField) == -1) {
8242             xmlSchemaPErr(ctxt,
8243                 (xmlNodePtr) attr,
8244                 XML_SCHEMAP_INTERNAL,
8245                 "Internal error: xmlSchemaParseIDCSelectorAndField, "
8246                 "validating the XPath expression of a IDC selector.\n",
8247                 NULL, NULL);
8248         }
8249
8250     }
8251     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8252     /*
8253     * And now for the children...
8254     */
8255     child = node->children;
8256     if (IS_SCHEMA(child, "annotation")) {
8257         /*
8258         * Add the annotation to the parent IDC.
8259         */
8260         xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
8261             xmlSchemaParseAnnotation(ctxt, child, 1));
8262         child = child->next;
8263     }
8264     if (child != NULL) {
8265         xmlSchemaPContentErr(ctxt,
8266             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8267             NULL, node, child,
8268             NULL, "(annotation?)");
8269     }
8270
8271     return (item);
8272 }
8273
8274 /**
8275  * xmlSchemaParseIDC:
8276  * @ctxt:  a schema validation context
8277  * @schema:  the schema being built
8278  * @node:  a subtree containing XML Schema informations
8279  *
8280  * Parses a XML Schema identity-contraint definition.
8281  *
8282  * Returns the parsed identity-constraint definition.
8283  */
8284 static xmlSchemaIDCPtr
8285 xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
8286                   xmlSchemaPtr schema,
8287                   xmlNodePtr node,
8288                   xmlSchemaTypeType idcCategory,
8289                   const xmlChar *targetNamespace)
8290 {
8291     xmlSchemaIDCPtr item = NULL;
8292     xmlNodePtr child = NULL;
8293     xmlAttrPtr attr;
8294     const xmlChar *name = NULL;
8295     xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
8296
8297     /*
8298     * Check for illegal attributes.
8299     */
8300     attr = node->properties;
8301     while (attr != NULL) {
8302         if (attr->ns == NULL) {
8303             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8304                 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8305                 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8306                  (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
8307                 xmlSchemaPIllegalAttrErr(ctxt,
8308                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8309             }
8310         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8311             xmlSchemaPIllegalAttrErr(ctxt,
8312                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8313         }
8314         attr = attr->next;
8315     }
8316     /*
8317     * Attribute "name" (mandatory).
8318     */
8319     attr = xmlSchemaGetPropNode(node, "name");
8320     if (attr == NULL) {
8321         xmlSchemaPMissingAttrErr(ctxt,
8322             XML_SCHEMAP_S4S_ATTR_MISSING,
8323             NULL, node,
8324             "name", NULL);
8325         return (NULL);
8326     } else if (xmlSchemaPValAttrNode(ctxt,
8327         NULL, attr,
8328         xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8329         return (NULL);
8330     }
8331     /* Create the component. */
8332     item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8333         idcCategory, node);
8334     if (item == NULL)
8335         return(NULL);
8336
8337     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8338     if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8339         /*
8340         * Attribute "refer" (mandatory).
8341         */
8342         attr = xmlSchemaGetPropNode(node, "refer");
8343         if (attr == NULL) {
8344             xmlSchemaPMissingAttrErr(ctxt,
8345                 XML_SCHEMAP_S4S_ATTR_MISSING,
8346                 NULL, node,
8347                 "refer", NULL);
8348         } else {
8349             /*
8350             * Create a reference item.
8351             */
8352             item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
8353                 NULL, NULL);
8354             if (item->ref == NULL)
8355                 return (NULL);
8356             xmlSchemaPValAttrNodeQName(ctxt, schema,
8357                 NULL, attr,
8358                 &(item->ref->targetNamespace),
8359                 &(item->ref->name));
8360             xmlSchemaCheckReference(ctxt, schema, node, attr,
8361                 item->ref->targetNamespace);
8362         }
8363     }
8364     /*
8365     * And now for the children...
8366     */
8367     child = node->children;
8368     if (IS_SCHEMA(child, "annotation")) {
8369         item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8370         child = child->next;
8371     }
8372     if (child == NULL) {
8373         xmlSchemaPContentErr(ctxt,
8374                 XML_SCHEMAP_S4S_ELEM_MISSING,
8375                 NULL, node, child,
8376                 "A child element is missing",
8377                 "(annotation?, (selector, field+))");
8378     }
8379     /*
8380     * Child element <selector>.
8381     */
8382     if (IS_SCHEMA(child, "selector")) {
8383         item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
8384             item, child, 0);
8385         child = child->next;
8386         /*
8387         * Child elements <field>.
8388         */
8389         if (IS_SCHEMA(child, "field")) {
8390             do {
8391                 field = xmlSchemaParseIDCSelectorAndField(ctxt,
8392                     item, child, 1);
8393                 if (field != NULL) {
8394                     field->index = item->nbFields;
8395                     item->nbFields++;
8396                     if (lastField != NULL)
8397                         lastField->next = field;
8398                     else
8399                         item->fields = field;
8400                     lastField = field;
8401                 }
8402                 child = child->next;
8403             } while (IS_SCHEMA(child, "field"));
8404         } else {
8405             xmlSchemaPContentErr(ctxt,
8406                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8407                 NULL, node, child,
8408                 NULL, "(annotation?, (selector, field+))");
8409         }
8410     }
8411     if (child != NULL) {
8412         xmlSchemaPContentErr(ctxt,
8413             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8414             NULL, node, child,
8415             NULL, "(annotation?, (selector, field+))");
8416     }
8417
8418     return (item);
8419 }
8420
8421 /**
8422  * xmlSchemaParseElement:
8423  * @ctxt:  a schema validation context
8424  * @schema:  the schema being built
8425  * @node:  a subtree containing XML Schema informations
8426  * @topLevel: indicates if this is global declaration
8427  *
8428  * Parses a XML schema element declaration.
8429  * *WARNING* this interface is highly subject to change
8430  *
8431  * Returns the element declaration or a particle; NULL in case
8432  * of an error or if the particle has minOccurs==maxOccurs==0.
8433  */
8434 static xmlSchemaBasicItemPtr
8435 xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8436                       xmlNodePtr node, int *isElemRef, int topLevel)
8437 {
8438     xmlSchemaElementPtr decl = NULL;
8439     xmlSchemaParticlePtr particle = NULL;
8440     xmlSchemaAnnotPtr annot = NULL;
8441     xmlNodePtr child = NULL;
8442     xmlAttrPtr attr, nameAttr;
8443     int min, max, isRef = 0;
8444     xmlChar *des = NULL;
8445
8446     /* 3.3.3 Constraints on XML Representations of Element Declarations */
8447     /* TODO: Complete implementation of 3.3.6 */
8448
8449     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8450         return (NULL);
8451
8452     if (isElemRef != NULL)
8453         *isElemRef = 0;
8454     /*
8455     * If we get a "ref" attribute on a local <element> we will assume it's
8456     * a reference - even if there's a "name" attribute; this seems to be more
8457     * robust.
8458     */
8459     nameAttr = xmlSchemaGetPropNode(node, "name");
8460     attr = xmlSchemaGetPropNode(node, "ref");
8461     if ((topLevel) || (attr == NULL)) {
8462         if (nameAttr == NULL) {
8463             xmlSchemaPMissingAttrErr(ctxt,
8464                 XML_SCHEMAP_S4S_ATTR_MISSING,
8465                 NULL, node, "name", NULL);
8466             return (NULL);
8467         }
8468     } else
8469         isRef = 1;
8470
8471     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8472     child = node->children;
8473     if (IS_SCHEMA(child, "annotation")) {
8474         annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8475         child = child->next;
8476     }
8477     /*
8478     * Skip particle part if a global declaration.
8479     */
8480     if (topLevel)
8481         goto declaration_part;
8482     /*
8483     * The particle part ==================================================
8484     */
8485     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8486     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8487     xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
8488     particle = xmlSchemaAddParticle(ctxt, node, min, max);
8489     if (particle == NULL)
8490         goto return_null;
8491
8492     /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8493
8494     if (isRef) {
8495         const xmlChar *refNs = NULL, *ref = NULL;
8496         xmlSchemaQNameRefPtr refer = NULL;
8497         /*
8498         * The reference part =============================================
8499         */
8500         if (isElemRef != NULL)
8501             *isElemRef = 1;
8502
8503         xmlSchemaPValAttrNodeQName(ctxt, schema,
8504             NULL, attr, &refNs, &ref);
8505         xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
8506         /*
8507         * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
8508         */
8509         if (nameAttr != NULL) {
8510             xmlSchemaPMutualExclAttrErr(ctxt,
8511                 XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
8512         }
8513         /*
8514         * Check for illegal attributes.
8515         */
8516         attr = node->properties;
8517         while (attr != NULL) {
8518             if (attr->ns == NULL) {
8519                 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8520                     xmlStrEqual(attr->name, BAD_CAST "name") ||
8521                     xmlStrEqual(attr->name, BAD_CAST "id") ||
8522                     xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8523                     xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8524                 {
8525                     attr = attr->next;
8526                     continue;
8527                 } else {
8528                     /* SPEC (3.3.3 : 2.2) */
8529                     xmlSchemaPCustomAttrErr(ctxt,
8530                         XML_SCHEMAP_SRC_ELEMENT_2_2,
8531                         NULL, NULL, attr,
8532                         "Only the attributes 'minOccurs', 'maxOccurs' and "
8533                         "'id' are allowed in addition to 'ref'");
8534                     break;
8535                 }
8536             } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8537                 xmlSchemaPIllegalAttrErr(ctxt,
8538                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8539             }
8540             attr = attr->next;
8541         }
8542         /*
8543         * No children except <annotation> expected.
8544         */
8545         if (child != NULL) {
8546             xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8547                 NULL, node, child, NULL, "(annotation?)");
8548         }
8549         if ((min == 0) && (max == 0))
8550             goto return_null;
8551         /*
8552         * Create the reference item and attach it to the particle.
8553         */
8554         refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
8555             ref, refNs);
8556         if (refer == NULL)
8557             goto return_null;
8558         particle->children = (xmlSchemaTreeItemPtr) refer;
8559         particle->annot = annot;
8560         /*
8561         * Add the particle to pending components, since the reference
8562         * need to be resolved.
8563         */
8564         WXS_ADD_PENDING(ctxt, particle);
8565         return ((xmlSchemaBasicItemPtr) particle);
8566     }
8567     /*
8568     * The declaration part ===============================================
8569     */
8570 declaration_part:
8571     {
8572         const xmlChar *ns = NULL, *fixed, *name, *attrValue;
8573         xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8574
8575         if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
8576             xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
8577             goto return_null;
8578         /*
8579         * Evaluate the target namespace.
8580         */
8581         if (topLevel) {
8582             ns = ctxt->targetNamespace;
8583         } else {
8584             attr = xmlSchemaGetPropNode(node, "form");
8585             if (attr != NULL) {
8586                 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8587                 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
8588                     ns = ctxt->targetNamespace;
8589                 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
8590                     xmlSchemaPSimpleTypeErr(ctxt,
8591                         XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8592                         NULL, (xmlNodePtr) attr,
8593                         NULL, "(qualified | unqualified)",
8594                         attrValue, NULL, NULL, NULL);
8595                 }
8596             } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8597                 ns = ctxt->targetNamespace;
8598         }
8599         decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
8600         if (decl == NULL) {
8601             goto return_null;
8602         }
8603         /*
8604         * Check for illegal attributes.
8605         */
8606         attr = node->properties;
8607         while (attr != NULL) {
8608             if (attr->ns == NULL) {
8609                 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8610                     (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
8611                     (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8612                     (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
8613                     (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
8614                     (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
8615                     (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8616                 {
8617                     if (topLevel == 0) {
8618                         if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8619                             (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8620                             (!xmlStrEqual(attr->name, BAD_CAST "form")))
8621                         {
8622                             xmlSchemaPIllegalAttrErr(ctxt,
8623                                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8624                         }
8625                     } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8626                         (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
8627                         (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8628
8629                         xmlSchemaPIllegalAttrErr(ctxt,
8630                             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8631                     }
8632                 }
8633             } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8634
8635                 xmlSchemaPIllegalAttrErr(ctxt,
8636                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8637             }
8638             attr = attr->next;
8639         }
8640         /*
8641         * Extract/validate attributes.
8642         */
8643         if (topLevel) {
8644             /*
8645             * Process top attributes of global element declarations here.
8646             */
8647             decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8648             decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
8649             xmlSchemaPValAttrQName(ctxt, schema,
8650                 NULL, node, "substitutionGroup",
8651                 &(decl->substGroupNs), &(decl->substGroup));
8652             if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
8653                 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
8654             /*
8655             * Attribute "final".
8656             */
8657             attr = xmlSchemaGetPropNode(node, "final");
8658             if (attr == NULL) {
8659                 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8660                     decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8661                 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8662                     decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
8663             } else {
8664                 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8665                 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8666                     -1,
8667                     XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8668                     XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
8669                     xmlSchemaPSimpleTypeErr(ctxt,
8670                         XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8671                         NULL, (xmlNodePtr) attr,
8672                         NULL, "(#all | List of (extension | restriction))",
8673                         attrValue, NULL, NULL, NULL);
8674                 }
8675             }
8676         }
8677         /*
8678         * Attribute "block".
8679         */
8680         attr = xmlSchemaGetPropNode(node, "block");
8681         if (attr == NULL) {
8682             /*
8683             * Apply default "block" values.
8684             */
8685             if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8686                 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8687             if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8688                 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8689             if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8690                 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
8691         } else {
8692             attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8693             if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8694                 -1,
8695                 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
8696                 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
8697                 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8698                 xmlSchemaPSimpleTypeErr(ctxt,
8699                     XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8700                     NULL, (xmlNodePtr) attr,
8701                     NULL, "(#all | List of (extension | "
8702                     "restriction | substitution))", attrValue,
8703                     NULL, NULL, NULL);
8704             }
8705         }
8706         if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
8707             decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
8708
8709         attr = xmlSchemaGetPropNode(node, "type");
8710         if (attr != NULL) {
8711             xmlSchemaPValAttrNodeQName(ctxt, schema,
8712                 NULL, attr,
8713                 &(decl->namedTypeNs), &(decl->namedType));
8714             xmlSchemaCheckReference(ctxt, schema, node,
8715                 attr, decl->namedTypeNs);
8716         }
8717         decl->value = xmlSchemaGetProp(ctxt, node, "default");
8718         attr = xmlSchemaGetPropNode(node, "fixed");
8719         if (attr != NULL) {
8720             fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8721             if (decl->value != NULL) {
8722                 /*
8723                 * 3.3.3 : 1
8724                 * default and fixed must not both be present.
8725                 */
8726                 xmlSchemaPMutualExclAttrErr(ctxt,
8727                     XML_SCHEMAP_SRC_ELEMENT_1,
8728                     NULL, attr, "default", "fixed");
8729             } else {
8730                 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8731                 decl->value = fixed;
8732             }
8733         }
8734         /*
8735         * And now for the children...
8736         */
8737         if (IS_SCHEMA(child, "complexType")) {
8738             /*
8739             * 3.3.3 : 3
8740             * "type" and either <simpleType> or <complexType> are mutually
8741             * exclusive
8742             */
8743             if (decl->namedType != NULL) {
8744                 xmlSchemaPContentErr(ctxt,
8745                     XML_SCHEMAP_SRC_ELEMENT_3,
8746                     NULL, node, child,
8747                     "The attribute 'type' and the <complexType> child are "
8748                     "mutually exclusive", NULL);
8749             } else
8750                 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
8751             child = child->next;
8752         } else if (IS_SCHEMA(child, "simpleType")) {
8753             /*
8754             * 3.3.3 : 3
8755             * "type" and either <simpleType> or <complexType> are
8756             * mutually exclusive
8757             */
8758             if (decl->namedType != NULL) {
8759                 xmlSchemaPContentErr(ctxt,
8760                     XML_SCHEMAP_SRC_ELEMENT_3,
8761                     NULL, node, child,
8762                     "The attribute 'type' and the <simpleType> child are "
8763                     "mutually exclusive", NULL);
8764             } else
8765                 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8766             child = child->next;
8767         }
8768         while ((IS_SCHEMA(child, "unique")) ||
8769             (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
8770             if (IS_SCHEMA(child, "unique")) {
8771                 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8772                     XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
8773             } else if (IS_SCHEMA(child, "key")) {
8774                 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8775                     XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
8776             } else if (IS_SCHEMA(child, "keyref")) {
8777                 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8778                     XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
8779             }
8780             if (lastIDC != NULL)
8781                 lastIDC->next = curIDC;
8782             else
8783                 decl->idcs = (void *) curIDC;
8784             lastIDC = curIDC;
8785             child = child->next;
8786         }
8787         if (child != NULL) {
8788             xmlSchemaPContentErr(ctxt,
8789                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8790                 NULL, node, child,
8791                 NULL, "(annotation?, ((simpleType | complexType)?, "
8792                 "(unique | key | keyref)*))");
8793         }
8794         decl->annot = annot;
8795     }
8796     /*
8797     * NOTE: Element Declaration Representation OK 4. will be checked at a
8798     * different layer.
8799     */
8800     FREE_AND_NULL(des)
8801     if (topLevel)
8802         return ((xmlSchemaBasicItemPtr) decl);
8803     else {
8804         particle->children = (xmlSchemaTreeItemPtr) decl;
8805         return ((xmlSchemaBasicItemPtr) particle);
8806     }
8807
8808 return_null:
8809     FREE_AND_NULL(des);
8810     if (annot != NULL) {
8811         if (particle != NULL)
8812             particle->annot = NULL;
8813         if (decl != NULL)
8814             decl->annot = NULL;
8815         xmlSchemaFreeAnnot(annot);
8816     }
8817     return (NULL);
8818 }
8819
8820 /**
8821  * xmlSchemaParseUnion:
8822  * @ctxt:  a schema validation context
8823  * @schema:  the schema being built
8824  * @node:  a subtree containing XML Schema informations
8825  *
8826  * parse a XML schema Union definition
8827  * *WARNING* this interface is highly subject to change
8828  *
8829  * Returns -1 in case of internal error, 0 in case of success and a positive
8830  * error code otherwise.
8831  */
8832 static int
8833 xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8834                     xmlNodePtr node)
8835 {
8836     xmlSchemaTypePtr type;
8837     xmlNodePtr child = NULL;
8838     xmlAttrPtr attr;
8839     const xmlChar *cur = NULL;
8840
8841     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8842         return (-1);
8843     /* Not a component, don't create it. */
8844     type = ctxt->ctxtType;
8845     /*
8846     * Mark the simple type as being of variety "union".
8847     */
8848     type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
8849     /*
8850     * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8851     * then the ï¿½simple ur-type definition�."
8852     */
8853     type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8854     /*
8855     * Check for illegal attributes.
8856     */
8857     attr = node->properties;
8858     while (attr != NULL) {
8859         if (attr->ns == NULL) {
8860             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8861                 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
8862                 xmlSchemaPIllegalAttrErr(ctxt,
8863                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8864             }
8865         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8866             xmlSchemaPIllegalAttrErr(ctxt,
8867                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8868         }
8869         attr = attr->next;
8870     }
8871     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8872     /*
8873     * Attribute "memberTypes". This is a list of QNames.
8874     * TODO: Check the value to contain anything.
8875     */
8876     attr = xmlSchemaGetPropNode(node, "memberTypes");
8877     if (attr != NULL) {
8878         const xmlChar *end;
8879         xmlChar *tmp;
8880         const xmlChar *localName, *nsName;
8881         xmlSchemaTypeLinkPtr link, lastLink = NULL;
8882         xmlSchemaQNameRefPtr ref;
8883
8884         cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8885         type->base = cur;
8886         do {
8887             while (IS_BLANK_CH(*cur))
8888                 cur++;
8889             end = cur;
8890             while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8891                 end++;
8892             if (end == cur)
8893                 break;
8894             tmp = xmlStrndup(cur, end - cur);
8895             if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
8896                 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
8897                 /*
8898                 * Create the member type link.
8899                 */
8900                 link = (xmlSchemaTypeLinkPtr)
8901                     xmlMalloc(sizeof(xmlSchemaTypeLink));
8902                 if (link == NULL) {
8903                     xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8904                         "allocating a type link", NULL);
8905                     return (-1);
8906                 }
8907                 link->type = NULL;
8908                 link->next = NULL;
8909                 if (lastLink == NULL)
8910                     type->memberTypes = link;
8911                 else
8912                     lastLink->next = link;
8913                 lastLink = link;
8914                 /*
8915                 * Create a reference item.
8916                 */
8917                 ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
8918                     localName, nsName);
8919                 if (ref == NULL) {
8920                     FREE_AND_NULL(tmp)
8921                     return (-1);
8922                 }
8923                 /*
8924                 * Assign the reference to the link, it will be resolved
8925                 * later during fixup of the union simple type.
8926                 */
8927                 link->type = (xmlSchemaTypePtr) ref;
8928             }
8929             FREE_AND_NULL(tmp)
8930             cur = end;
8931         } while (*cur != 0);
8932
8933     }
8934     /*
8935     * And now for the children...
8936     */
8937     child = node->children;
8938     if (IS_SCHEMA(child, "annotation")) {
8939         /*
8940         * Add the annotation to the simple type ancestor.
8941         */
8942         xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8943             xmlSchemaParseAnnotation(ctxt, child, 1));
8944         child = child->next;
8945     }
8946     if (IS_SCHEMA(child, "simpleType")) {
8947         xmlSchemaTypePtr subtype, last = NULL;
8948
8949         /*
8950         * Anchor the member types in the "subtypes" field of the
8951         * simple type.
8952         */
8953         while (IS_SCHEMA(child, "simpleType")) {
8954             subtype = (xmlSchemaTypePtr)
8955                 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8956             if (subtype != NULL) {
8957                 if (last == NULL) {
8958                     type->subtypes = subtype;
8959                     last = subtype;
8960                 } else {
8961                     last->next = subtype;
8962                     last = subtype;
8963                 }
8964                 last->next = NULL;
8965             }
8966             child = child->next;
8967         }
8968     }
8969     if (child != NULL) {
8970         xmlSchemaPContentErr(ctxt,
8971             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8972             NULL, node, child, NULL, "(annotation?, simpleType*)");
8973     }
8974     if ((attr == NULL) && (type->subtypes == NULL)) {
8975          /*
8976         * src-union-memberTypes-or-simpleTypes
8977         * Either the memberTypes [attribute] of the <union> element must
8978         * be non-empty or there must be at least one simpleType [child].
8979         */
8980         xmlSchemaPCustomErr(ctxt,
8981             XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
8982             NULL, node,
8983             "Either the attribute 'memberTypes' or "
8984             "at least one <simpleType> child must be present", NULL);
8985     }
8986     return (0);
8987 }
8988
8989 /**
8990  * xmlSchemaParseList:
8991  * @ctxt:  a schema validation context
8992  * @schema:  the schema being built
8993  * @node:  a subtree containing XML Schema informations
8994  *
8995  * parse a XML schema List definition
8996  * *WARNING* this interface is highly subject to change
8997  *
8998  * Returns -1 in case of error, 0 if the declaration is improper and
8999  *         1 in case of success.
9000  */
9001 static xmlSchemaTypePtr
9002 xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9003                    xmlNodePtr node)
9004 {
9005     xmlSchemaTypePtr type;
9006     xmlNodePtr child = NULL;
9007     xmlAttrPtr attr;
9008
9009     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9010         return (NULL);
9011     /* Not a component, don't create it. */
9012     type = ctxt->ctxtType;
9013     /*
9014     * Mark the type as being of variety "list".
9015     */
9016     type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
9017     /*
9018     * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
9019     * then the ï¿½simple ur-type definition�."
9020     */
9021     type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
9022     /*
9023     * Check for illegal attributes.
9024     */
9025     attr = node->properties;
9026     while (attr != NULL) {
9027         if (attr->ns == NULL) {
9028             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9029                 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
9030                 xmlSchemaPIllegalAttrErr(ctxt,
9031                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9032             }
9033         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9034             xmlSchemaPIllegalAttrErr(ctxt,
9035                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9036         }
9037         attr = attr->next;
9038     }
9039
9040     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9041
9042     /*
9043     * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9044     * fields for holding the reference to the itemType.
9045     *
9046     * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9047     * the "ref" fields.
9048     */
9049     xmlSchemaPValAttrQName(ctxt, schema, NULL,
9050         node, "itemType", &(type->baseNs), &(type->base));
9051     /*
9052     * And now for the children...
9053     */
9054     child = node->children;
9055     if (IS_SCHEMA(child, "annotation")) {
9056         xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9057             xmlSchemaParseAnnotation(ctxt, child, 1));
9058         child = child->next;
9059     }
9060     if (IS_SCHEMA(child, "simpleType")) {
9061         /*
9062         * src-list-itemType-or-simpleType
9063         * Either the itemType [attribute] or the <simpleType> [child] of
9064         * the <list> element must be present, but not both.
9065         */
9066         if (type->base != NULL) {
9067             xmlSchemaPCustomErr(ctxt,
9068                 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9069                 NULL, node,
9070                 "The attribute 'itemType' and the <simpleType> child "
9071                 "are mutually exclusive", NULL);
9072         } else {
9073             type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9074         }
9075         child = child->next;
9076     } else if (type->base == NULL) {
9077         xmlSchemaPCustomErr(ctxt,
9078             XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9079             NULL, node,
9080             "Either the attribute 'itemType' or the <simpleType> child "
9081             "must be present", NULL);
9082     }
9083     if (child != NULL) {
9084         xmlSchemaPContentErr(ctxt,
9085             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9086             NULL, node, child, NULL, "(annotation?, simpleType?)");
9087     }
9088     if ((type->base == NULL) &&
9089         (type->subtypes == NULL) &&
9090         (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
9091         xmlSchemaPCustomErr(ctxt,
9092             XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9093             NULL, node,
9094             "Either the attribute 'itemType' or the <simpleType> child "
9095             "must be present", NULL);
9096     }
9097     return (NULL);
9098 }
9099
9100 /**
9101  * xmlSchemaParseSimpleType:
9102  * @ctxt:  a schema validation context
9103  * @schema:  the schema being built
9104  * @node:  a subtree containing XML Schema informations
9105  *
9106  * parse a XML schema Simple Type definition
9107  * *WARNING* this interface is highly subject to change
9108  *
9109  * Returns -1 in case of error, 0 if the declaration is improper and
9110  * 1 in case of success.
9111  */
9112 static xmlSchemaTypePtr
9113 xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9114                          xmlNodePtr node, int topLevel)
9115 {
9116     xmlSchemaTypePtr type, oldCtxtType;
9117     xmlNodePtr child = NULL;
9118     const xmlChar *attrValue = NULL;
9119     xmlAttrPtr attr;
9120     int hasRestriction = 0;
9121
9122     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9123         return (NULL);
9124
9125     if (topLevel) {
9126         attr = xmlSchemaGetPropNode(node, "name");
9127         if (attr == NULL) {
9128             xmlSchemaPMissingAttrErr(ctxt,
9129                 XML_SCHEMAP_S4S_ATTR_MISSING,
9130                 NULL, node,
9131                 "name", NULL);
9132             return (NULL);
9133         } else {
9134             if (xmlSchemaPValAttrNode(ctxt,
9135                 NULL, attr,
9136                 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9137                 return (NULL);
9138             /*
9139             * Skip built-in types.
9140             */
9141             if (ctxt->isS4S) {
9142                 xmlSchemaTypePtr biType;
9143
9144                 if (ctxt->isRedefine) {
9145                     /*
9146                     * REDEFINE: Disallow redefinition of built-in-types.
9147                     * TODO: It seems that the spec does not say anything
9148                     * about this case.
9149                     */
9150                     xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9151                         NULL, node,
9152                         "Redefinition of built-in simple types is not "
9153                         "supported", NULL);
9154                     return(NULL);
9155                 }
9156                 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9157                 if (biType != NULL)
9158                     return (biType);
9159             }
9160         }
9161     }
9162     /*
9163     * TargetNamespace:
9164     * SPEC "The ï¿½actual value� of the targetNamespace [attribute]
9165     * of the <schema> ancestor element information item if present,
9166     * otherwise ï¿½absent�.
9167     */
9168     if (topLevel == 0) {
9169 #ifdef ENABLE_NAMED_LOCALS
9170         char buf[40];
9171 #endif
9172         /*
9173         * Parse as local simple type definition.
9174         */
9175 #ifdef ENABLE_NAMED_LOCALS
9176         snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
9177         type = xmlSchemaAddType(ctxt, schema,
9178             XML_SCHEMA_TYPE_SIMPLE,
9179             xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
9180             ctxt->targetNamespace, node, 0);
9181 #else
9182         type = xmlSchemaAddType(ctxt, schema,
9183             XML_SCHEMA_TYPE_SIMPLE,
9184             NULL, ctxt->targetNamespace, node, 0);
9185 #endif
9186         if (type == NULL)
9187             return (NULL);
9188         type->type = XML_SCHEMA_TYPE_SIMPLE;
9189         type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9190         /*
9191         * Check for illegal attributes.
9192         */
9193         attr = node->properties;
9194         while (attr != NULL) {
9195             if (attr->ns == NULL) {
9196                 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
9197                     xmlSchemaPIllegalAttrErr(ctxt,
9198                         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9199                 }
9200             } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9201                     xmlSchemaPIllegalAttrErr(ctxt,
9202                         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9203             }
9204             attr = attr->next;
9205         }
9206     } else {
9207         /*
9208         * Parse as global simple type definition.
9209         *
9210         * Note that attrValue is the value of the attribute "name" here.
9211         */
9212         type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9213             attrValue, ctxt->targetNamespace, node, 1);
9214         if (type == NULL)
9215             return (NULL);
9216         type->type = XML_SCHEMA_TYPE_SIMPLE;
9217         type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9218         type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9219         /*
9220         * Check for illegal attributes.
9221         */
9222         attr = node->properties;
9223         while (attr != NULL) {
9224             if (attr->ns == NULL) {
9225                 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9226                     (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9227                     (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
9228                     xmlSchemaPIllegalAttrErr(ctxt,
9229                         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9230                 }
9231             } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9232                 xmlSchemaPIllegalAttrErr(ctxt,
9233                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9234             }
9235             attr = attr->next;
9236         }
9237         /*
9238         * Attribute "final".
9239         */
9240         attr = xmlSchemaGetPropNode(node, "final");
9241         if (attr == NULL) {
9242             if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9243                 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9244             if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9245                 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9246             if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9247                 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
9248         } else {
9249             attrValue = xmlSchemaGetProp(ctxt, node, "final");
9250             if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9251                 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
9252                 XML_SCHEMAS_TYPE_FINAL_LIST,
9253                 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9254
9255                 xmlSchemaPSimpleTypeErr(ctxt,
9256                     XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9257                     WXS_BASIC_CAST type, (xmlNodePtr) attr,
9258                     NULL, "(#all | List of (list | union | restriction)",
9259                     attrValue, NULL, NULL, NULL);
9260             }
9261         }
9262     }
9263     type->targetNamespace = ctxt->targetNamespace;
9264     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9265     /*
9266     * And now for the children...
9267     */
9268     oldCtxtType = ctxt->ctxtType;
9269
9270     ctxt->ctxtType = type;
9271
9272     child = node->children;
9273     if (IS_SCHEMA(child, "annotation")) {
9274         type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9275         child = child->next;
9276     }
9277     if (child == NULL) {
9278         xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
9279             NULL, node, child, NULL,
9280             "(annotation?, (restriction | list | union))");
9281     } else if (IS_SCHEMA(child, "restriction")) {
9282         xmlSchemaParseRestriction(ctxt, schema, child,
9283             XML_SCHEMA_TYPE_SIMPLE);
9284         hasRestriction = 1;
9285         child = child->next;
9286     } else if (IS_SCHEMA(child, "list")) {
9287         xmlSchemaParseList(ctxt, schema, child);
9288         child = child->next;
9289     } else if (IS_SCHEMA(child, "union")) {
9290         xmlSchemaParseUnion(ctxt, schema, child);
9291         child = child->next;
9292     }
9293     if (child != NULL) {
9294         xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9295             NULL, node, child, NULL,
9296             "(annotation?, (restriction | list | union))");
9297     }
9298     /*
9299     * REDEFINE: SPEC src-redefine (5)
9300     * "Within the [children], each <simpleType> must have a
9301     * <restriction> among its [children] ... the ï¿½actual value� of whose
9302     * base [attribute] must be the same as the ï¿½actual value� of its own
9303     * name attribute plus target namespace;"
9304     */
9305     if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9306         xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9307             NULL, node, "This is a redefinition, thus the "
9308             "<simpleType> must have a <restriction> child", NULL);
9309     }
9310
9311     ctxt->ctxtType = oldCtxtType;
9312     return (type);
9313 }
9314
9315 /**
9316  * xmlSchemaParseModelGroupDefRef:
9317  * @ctxt:  the parser context
9318  * @schema: the schema being built
9319  * @node:  the node
9320  *
9321  * Parses a reference to a model group definition.
9322  *
9323  * We will return a particle component with a qname-component or
9324  * NULL in case of an error.
9325  */
9326 static xmlSchemaTreeItemPtr
9327 xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9328                                xmlSchemaPtr schema,
9329                                xmlNodePtr node)
9330 {
9331     xmlSchemaParticlePtr item;
9332     xmlNodePtr child = NULL;
9333     xmlAttrPtr attr;
9334     const xmlChar *ref = NULL, *refNs = NULL;
9335     int min, max;
9336
9337     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9338         return (NULL);
9339
9340     attr = xmlSchemaGetPropNode(node, "ref");
9341     if (attr == NULL) {
9342         xmlSchemaPMissingAttrErr(ctxt,
9343             XML_SCHEMAP_S4S_ATTR_MISSING,
9344             NULL, node, "ref", NULL);
9345         return (NULL);
9346     } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
9347         attr, &refNs, &ref) != 0) {
9348         return (NULL);
9349     }
9350     xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
9351     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9352     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9353         "(xs:nonNegativeInteger | unbounded)");
9354     /*
9355     * Check for illegal attributes.
9356     */
9357     attr = node->properties;
9358     while (attr != NULL) {
9359         if (attr->ns == NULL) {
9360             if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
9361                 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9362                 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9363                 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
9364                 xmlSchemaPIllegalAttrErr(ctxt,
9365                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9366             }
9367         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9368             xmlSchemaPIllegalAttrErr(ctxt,
9369                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9370         }
9371         attr = attr->next;
9372     }
9373     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9374     item = xmlSchemaAddParticle(ctxt, node, min, max);
9375     if (item == NULL)
9376         return (NULL);
9377     /*
9378     * Create a qname-reference and set as the term; it will be substituted
9379     * for the model group after the reference has been resolved.
9380     */
9381     item->children = (xmlSchemaTreeItemPtr)
9382         xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
9383     xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9384     /*
9385     * And now for the children...
9386     */
9387     child = node->children;
9388     /* TODO: Is annotation even allowed for a model group reference? */
9389     if (IS_SCHEMA(child, "annotation")) {
9390         /*
9391         * TODO: What to do exactly with the annotation?
9392         */
9393         item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9394         child = child->next;
9395     }
9396     if (child != NULL) {
9397         xmlSchemaPContentErr(ctxt,
9398             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9399             NULL, node, child, NULL,
9400             "(annotation?)");
9401     }
9402     /*
9403     * Corresponds to no component at all if minOccurs==maxOccurs==0.
9404     */
9405     if ((min == 0) && (max == 0))
9406         return (NULL);
9407
9408     return ((xmlSchemaTreeItemPtr) item);
9409 }
9410
9411 /**
9412  * xmlSchemaParseModelGroupDefinition:
9413  * @ctxt:  a schema validation context
9414  * @schema:  the schema being built
9415  * @node:  a subtree containing XML Schema informations
9416  *
9417  * Parses a XML schema model group definition.
9418  *
9419  * Note that the contraint src-redefine (6.2) can't be applied until
9420  * references have been resolved. So we will do this at the
9421  * component fixup level.
9422  *
9423  * *WARNING* this interface is highly subject to change
9424  *
9425  * Returns -1 in case of error, 0 if the declaration is improper and
9426  *         1 in case of success.
9427  */
9428 static xmlSchemaModelGroupDefPtr
9429 xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9430                                    xmlSchemaPtr schema,
9431                                    xmlNodePtr node)
9432 {
9433     xmlSchemaModelGroupDefPtr item;
9434     xmlNodePtr child = NULL;
9435     xmlAttrPtr attr;
9436     const xmlChar *name;
9437
9438     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9439         return (NULL);
9440
9441     attr = xmlSchemaGetPropNode(node, "name");
9442     if (attr == NULL) {
9443         xmlSchemaPMissingAttrErr(ctxt,
9444             XML_SCHEMAP_S4S_ATTR_MISSING,
9445             NULL, node,
9446             "name", NULL);
9447         return (NULL);
9448     } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
9449         xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9450         return (NULL);
9451     }
9452     item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9453         ctxt->targetNamespace, node);
9454     if (item == NULL)
9455         return (NULL);
9456     /*
9457     * Check for illegal attributes.
9458     */
9459     attr = node->properties;
9460     while (attr != NULL) {
9461         if (attr->ns == NULL) {
9462             if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9463                 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
9464                 xmlSchemaPIllegalAttrErr(ctxt,
9465                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9466             }
9467         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9468             xmlSchemaPIllegalAttrErr(ctxt,
9469                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9470         }
9471         attr = attr->next;
9472     }
9473     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9474     /*
9475     * And now for the children...
9476     */
9477     child = node->children;
9478     if (IS_SCHEMA(child, "annotation")) {
9479         item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9480         child = child->next;
9481     }
9482     if (IS_SCHEMA(child, "all")) {
9483         item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9484             XML_SCHEMA_TYPE_ALL, 0);
9485         child = child->next;
9486     } else if (IS_SCHEMA(child, "choice")) {
9487         item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9488             XML_SCHEMA_TYPE_CHOICE, 0);
9489         child = child->next;
9490     } else if (IS_SCHEMA(child, "sequence")) {
9491         item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9492             XML_SCHEMA_TYPE_SEQUENCE, 0);
9493         child = child->next;
9494     }
9495
9496
9497
9498     if (child != NULL) {
9499         xmlSchemaPContentErr(ctxt,
9500             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9501             NULL, node, child, NULL,
9502             "(annotation?, (all | choice | sequence)?)");
9503     }
9504     return (item);
9505 }
9506
9507 /**
9508  * xmlSchemaCleanupDoc:
9509  * @ctxt:  a schema validation context
9510  * @node:  the root of the document.
9511  *
9512  * removes unwanted nodes in a schemas document tree
9513  */
9514 static void
9515 xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9516 {
9517     xmlNodePtr delete, cur;
9518
9519     if ((ctxt == NULL) || (root == NULL)) return;
9520
9521     /*
9522      * Remove all the blank text nodes
9523      */
9524     delete = NULL;
9525     cur = root;
9526     while (cur != NULL) {
9527         if (delete != NULL) {
9528             xmlUnlinkNode(delete);
9529             xmlFreeNode(delete);
9530             delete = NULL;
9531         }
9532         if (cur->type == XML_TEXT_NODE) {
9533             if (IS_BLANK_NODE(cur)) {
9534                 if (xmlNodeGetSpacePreserve(cur) != 1) {
9535                     delete = cur;
9536                 }
9537             }
9538         } else if ((cur->type != XML_ELEMENT_NODE) &&
9539                    (cur->type != XML_CDATA_SECTION_NODE)) {
9540             delete = cur;
9541             goto skip_children;
9542         }
9543
9544         /*
9545          * Skip to next node
9546          */
9547         if (cur->children != NULL) {
9548             if ((cur->children->type != XML_ENTITY_DECL) &&
9549                 (cur->children->type != XML_ENTITY_REF_NODE) &&
9550                 (cur->children->type != XML_ENTITY_NODE)) {
9551                 cur = cur->children;
9552                 continue;
9553             }
9554         }
9555       skip_children:
9556         if (cur->next != NULL) {
9557             cur = cur->next;
9558             continue;
9559         }
9560
9561         do {
9562             cur = cur->parent;
9563             if (cur == NULL)
9564                 break;
9565             if (cur == root) {
9566                 cur = NULL;
9567                 break;
9568             }
9569             if (cur->next != NULL) {
9570                 cur = cur->next;
9571                 break;
9572             }
9573         } while (cur != NULL);
9574     }
9575     if (delete != NULL) {
9576         xmlUnlinkNode(delete);
9577         xmlFreeNode(delete);
9578         delete = NULL;
9579     }
9580 }
9581
9582
9583 static void
9584 xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9585 {
9586     if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9587         schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9588
9589     if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9590         schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9591
9592     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9593         schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9594     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9595         schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9596     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9597         schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9598     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9599         schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9600
9601     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9602         schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9603     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9604         schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9605     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9606         schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9607 }
9608
9609 static int
9610 xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
9611                              xmlSchemaPtr schema,
9612                              xmlNodePtr node)
9613 {
9614     xmlAttrPtr attr;
9615     const xmlChar *val;
9616     int res = 0, oldErrs = ctxt->nberrors;
9617
9618     /*
9619     * Those flags should be moved to the parser context flags,
9620     * since they are not visible at the component level. I.e.
9621     * they are used if processing schema *documents* only.
9622     */
9623     res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9624     HFAILURE;
9625
9626     /*
9627     * Since the version is of type xs:token, we won't bother to
9628     * check it.
9629     */
9630     /* REMOVED:
9631     attr = xmlSchemaGetPropNode(node, "version");
9632     if (attr != NULL) {
9633         res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9634             xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9635         HFAILURE;
9636     }
9637     */
9638     attr = xmlSchemaGetPropNode(node, "targetNamespace");
9639     if (attr != NULL) {
9640         res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
9641             xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9642         HFAILURE;
9643         if (res != 0) {
9644             ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9645             goto exit;
9646         }
9647     }
9648     attr = xmlSchemaGetPropNode(node, "elementFormDefault");
9649     if (attr != NULL) {
9650         val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9651         res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9652             XML_SCHEMAS_QUALIF_ELEM);
9653         HFAILURE;
9654         if (res != 0) {
9655             xmlSchemaPSimpleTypeErr(ctxt,
9656                 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
9657                 NULL, (xmlNodePtr) attr, NULL,
9658                 "(qualified | unqualified)", val, NULL, NULL, NULL);
9659         }
9660     }
9661     attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
9662     if (attr != NULL) {
9663         val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9664         res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9665             XML_SCHEMAS_QUALIF_ATTR);
9666         HFAILURE;
9667         if (res != 0) {
9668             xmlSchemaPSimpleTypeErr(ctxt,
9669                 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
9670                 NULL, (xmlNodePtr) attr, NULL,
9671                 "(qualified | unqualified)", val, NULL, NULL, NULL);
9672         }
9673     }
9674     attr = xmlSchemaGetPropNode(node, "finalDefault");
9675     if (attr != NULL) {
9676         val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9677         res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9678             XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9679             XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9680             -1,
9681             XML_SCHEMAS_FINAL_DEFAULT_LIST,
9682             XML_SCHEMAS_FINAL_DEFAULT_UNION);
9683         HFAILURE;
9684         if (res != 0) {
9685             xmlSchemaPSimpleTypeErr(ctxt,
9686                 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9687                 NULL, (xmlNodePtr) attr, NULL,
9688                 "(#all | List of (extension | restriction | list | union))",
9689                 val, NULL, NULL, NULL);
9690         }
9691     }
9692     attr = xmlSchemaGetPropNode(node, "blockDefault");
9693     if (attr != NULL) {
9694         val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9695         res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9696             XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9697             XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
9698             XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9699         HFAILURE;
9700         if (res != 0) {
9701             xmlSchemaPSimpleTypeErr(ctxt,
9702                 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9703                 NULL, (xmlNodePtr) attr, NULL,
9704                 "(#all | List of (extension | restriction | substitution))",
9705                 val, NULL, NULL, NULL);
9706         }
9707     }
9708
9709 exit:
9710     if (oldErrs != ctxt->nberrors)
9711         res = ctxt->err;
9712     return(res);
9713 exit_failure:
9714     return(-1);
9715 }
9716
9717 /**
9718  * xmlSchemaParseSchemaTopLevel:
9719  * @ctxt:  a schema validation context
9720  * @schema:  the schemas
9721  * @nodes:  the list of top level nodes
9722  *
9723  * Returns the internal XML Schema structure built from the resource or
9724  *         NULL in case of error
9725  */
9726 static int
9727 xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9728                              xmlSchemaPtr schema, xmlNodePtr nodes)
9729 {
9730     xmlNodePtr child;
9731     xmlSchemaAnnotPtr annot;
9732     int res = 0, oldErrs, tmpOldErrs;
9733
9734     if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
9735         return(-1);
9736
9737     oldErrs = ctxt->nberrors;
9738     child = nodes;
9739     while ((IS_SCHEMA(child, "include")) ||
9740            (IS_SCHEMA(child, "import")) ||
9741            (IS_SCHEMA(child, "redefine")) ||
9742            (IS_SCHEMA(child, "annotation"))) {
9743         if (IS_SCHEMA(child, "annotation")) {
9744             annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9745             if (schema->annot == NULL)
9746                 schema->annot = annot;
9747             else
9748                 xmlSchemaFreeAnnot(annot);
9749         } else if (IS_SCHEMA(child, "import")) {
9750             tmpOldErrs = ctxt->nberrors;
9751             res = xmlSchemaParseImport(ctxt, schema, child);
9752             HFAILURE;
9753             HSTOP(ctxt);
9754             if (tmpOldErrs != ctxt->nberrors)
9755                 goto exit;
9756         } else if (IS_SCHEMA(child, "include")) {
9757             tmpOldErrs = ctxt->nberrors;
9758             res = xmlSchemaParseInclude(ctxt, schema, child);
9759             HFAILURE;
9760             HSTOP(ctxt);
9761             if (tmpOldErrs != ctxt->nberrors)
9762                 goto exit;
9763         } else if (IS_SCHEMA(child, "redefine")) {
9764             tmpOldErrs = ctxt->nberrors;
9765             res = xmlSchemaParseRedefine(ctxt, schema, child);
9766             HFAILURE;
9767             HSTOP(ctxt);
9768             if (tmpOldErrs != ctxt->nberrors)
9769                 goto exit;
9770         }
9771         child = child->next;
9772     }
9773     /*
9774     * URGENT TODO: Change the functions to return int results.
9775     * We need especially to catch internal errors.
9776     */
9777     while (child != NULL) {
9778         if (IS_SCHEMA(child, "complexType")) {
9779             xmlSchemaParseComplexType(ctxt, schema, child, 1);
9780             child = child->next;
9781         } else if (IS_SCHEMA(child, "simpleType")) {
9782             xmlSchemaParseSimpleType(ctxt, schema, child, 1);
9783             child = child->next;
9784         } else if (IS_SCHEMA(child, "element")) {
9785             xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
9786             child = child->next;
9787         } else if (IS_SCHEMA(child, "attribute")) {
9788             xmlSchemaParseGlobalAttribute(ctxt, schema, child);
9789             child = child->next;
9790         } else if (IS_SCHEMA(child, "attributeGroup")) {
9791             xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
9792             child = child->next;
9793         } else if (IS_SCHEMA(child, "group")) {
9794             xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
9795             child = child->next;
9796         } else if (IS_SCHEMA(child, "notation")) {
9797             xmlSchemaParseNotation(ctxt, schema, child);
9798             child = child->next;
9799         } else {
9800             xmlSchemaPContentErr(ctxt,
9801                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9802                 NULL, child->parent, child,
9803                 NULL, "((include | import | redefine | annotation)*, "
9804                 "(((simpleType | complexType | group | attributeGroup) "
9805                 "| element | attribute | notation), annotation*)*)");
9806             child = child->next;
9807         }
9808         while (IS_SCHEMA(child, "annotation")) {
9809             /*
9810             * TODO: We should add all annotations.
9811             */
9812             annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9813             if (schema->annot == NULL)
9814                 schema->annot = annot;
9815             else
9816                 xmlSchemaFreeAnnot(annot);
9817             child = child->next;
9818         }
9819     }
9820 exit:
9821     ctxt->ctxtType = NULL;
9822     if (oldErrs != ctxt->nberrors)
9823         res = ctxt->err;
9824     return(res);
9825 exit_failure:
9826     return(-1);
9827 }
9828
9829 static xmlSchemaSchemaRelationPtr
9830 xmlSchemaSchemaRelationCreate(void)
9831 {
9832     xmlSchemaSchemaRelationPtr ret;
9833
9834     ret = (xmlSchemaSchemaRelationPtr)
9835         xmlMalloc(sizeof(xmlSchemaSchemaRelation));
9836     if (ret == NULL) {
9837         xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
9838         return(NULL);
9839     }
9840     memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
9841     return(ret);
9842 }
9843
9844 #if 0
9845 static void
9846 xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
9847 {
9848     xmlFree(rel);
9849 }
9850 #endif
9851
9852 static void
9853 xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9854 {
9855     xmlSchemaRedefPtr prev;
9856
9857     while (redef != NULL) {
9858         prev = redef;
9859         redef = redef->next;
9860         xmlFree(prev);
9861     }
9862 }
9863
9864 static void
9865 xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9866 {
9867     /*
9868     * After the construction context has been freed, there will be
9869     * no schema graph available any more. Only the schema buckets
9870     * will stay alive, which are put into the "schemasImports" and
9871     * "includes" slots of the xmlSchema.
9872     */
9873     if (con->buckets != NULL)
9874         xmlSchemaItemListFree(con->buckets);
9875     if (con->pending != NULL)
9876         xmlSchemaItemListFree(con->pending);
9877     if (con->substGroups != NULL)
9878         xmlHashFree(con->substGroups,
9879             (xmlHashDeallocator) xmlSchemaSubstGroupFree);
9880     if (con->redefs != NULL)
9881         xmlSchemaRedefListFree(con->redefs);
9882     if (con->dict != NULL)
9883         xmlDictFree(con->dict);
9884     xmlFree(con);
9885 }
9886
9887 static xmlSchemaConstructionCtxtPtr
9888 xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9889 {
9890     xmlSchemaConstructionCtxtPtr ret;
9891
9892     ret = (xmlSchemaConstructionCtxtPtr)
9893         xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9894     if (ret == NULL) {
9895         xmlSchemaPErrMemory(NULL,
9896             "allocating schema construction context", NULL);
9897         return (NULL);
9898     }
9899     memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
9900
9901     ret->buckets = xmlSchemaItemListCreate();
9902     if (ret->buckets == NULL) {
9903         xmlSchemaPErrMemory(NULL,
9904             "allocating list of schema buckets", NULL);
9905         xmlFree(ret);
9906         return (NULL);
9907     }
9908     ret->pending = xmlSchemaItemListCreate();
9909     if (ret->pending == NULL) {
9910         xmlSchemaPErrMemory(NULL,
9911             "allocating list of pending global components", NULL);
9912         xmlSchemaConstructionCtxtFree(ret);
9913         return (NULL);
9914     }
9915     ret->dict = dict;
9916     xmlDictReference(dict);
9917     return(ret);
9918 }
9919
9920 static xmlSchemaParserCtxtPtr
9921 xmlSchemaParserCtxtCreate(void)
9922 {
9923     xmlSchemaParserCtxtPtr ret;
9924
9925     ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9926     if (ret == NULL) {
9927         xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9928                             NULL);
9929         return (NULL);
9930     }
9931     memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9932     ret->type = XML_SCHEMA_CTXT_PARSER;
9933     ret->attrProhibs = xmlSchemaItemListCreate();
9934     if (ret->attrProhibs == NULL) {
9935         xmlFree(ret);
9936         return(NULL);
9937     }
9938     return(ret);
9939 }
9940
9941 /**
9942  * xmlSchemaNewParserCtxtUseDict:
9943  * @URL:  the location of the schema
9944  * @dict: the dictionary to be used
9945  *
9946  * Create an XML Schemas parse context for that file/resource expected
9947  * to contain an XML Schemas file.
9948  *
9949  * Returns the parser context or NULL in case of error
9950  */
9951 static xmlSchemaParserCtxtPtr
9952 xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9953 {
9954     xmlSchemaParserCtxtPtr ret;
9955
9956     ret = xmlSchemaParserCtxtCreate();
9957     if (ret == NULL)
9958         return (NULL);
9959     ret->dict = dict;
9960     xmlDictReference(dict);
9961     if (URL != NULL)
9962         ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
9963     return (ret);
9964 }
9965
9966 static int
9967 xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
9968 {
9969     if (vctxt->pctxt == NULL) {
9970         if (vctxt->schema != NULL)
9971             vctxt->pctxt =
9972                 xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
9973         else
9974             vctxt->pctxt = xmlSchemaNewParserCtxt("*");
9975         if (vctxt->pctxt == NULL) {
9976             VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
9977                 "failed to create a temp. parser context");
9978             return (-1);
9979         }
9980         /* TODO: Pass user data. */
9981         xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
9982             vctxt->warning, vctxt->errCtxt);
9983         xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
9984             vctxt->errCtxt);
9985     }
9986     return (0);
9987 }
9988
9989 /**
9990  * xmlSchemaGetSchemaBucket:
9991  * @pctxt: the schema parser context
9992  * @schemaLocation: the URI of the schema document
9993  *
9994  * Returns a schema bucket if it was already parsed.
9995  *
9996  * Returns a schema bucket if it was already parsed from
9997  *         @schemaLocation, NULL otherwise.
9998  */
9999 static xmlSchemaBucketPtr
10000 xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10001                             const xmlChar *schemaLocation)
10002 {
10003     xmlSchemaBucketPtr cur;
10004     xmlSchemaItemListPtr list;
10005
10006     list = pctxt->constructor->buckets;
10007     if (list->nbItems == 0)
10008         return(NULL);
10009     else {
10010         int i;
10011         for (i = 0; i < list->nbItems; i++) {
10012             cur = (xmlSchemaBucketPtr) list->items[i];
10013             /* Pointer comparison! */
10014             if (cur->schemaLocation == schemaLocation)
10015                 return(cur);
10016         }
10017     }
10018     return(NULL);
10019 }
10020
10021 static xmlSchemaBucketPtr
10022 xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10023                                      const xmlChar *schemaLocation,
10024                                      const xmlChar *targetNamespace)
10025 {
10026     xmlSchemaBucketPtr cur;
10027     xmlSchemaItemListPtr list;
10028
10029     list = pctxt->constructor->buckets;
10030     if (list->nbItems == 0)
10031         return(NULL);
10032     else {
10033         int i;
10034         for (i = 0; i < list->nbItems; i++) {
10035             cur = (xmlSchemaBucketPtr) list->items[i];
10036             /* Pointer comparison! */
10037             if ((cur->origTargetNamespace == NULL) &&
10038                 (cur->schemaLocation == schemaLocation) &&
10039                 (cur->targetNamespace == targetNamespace))
10040                 return(cur);
10041         }
10042     }
10043     return(NULL);
10044 }
10045
10046
10047 #define IS_BAD_SCHEMA_DOC(b) \
10048     (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10049
10050 static xmlSchemaBucketPtr
10051 xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10052                                  const xmlChar *targetNamespace,
10053                                  int imported)
10054 {
10055     xmlSchemaBucketPtr cur;
10056     xmlSchemaItemListPtr list;
10057
10058     list = pctxt->constructor->buckets;
10059     if (list->nbItems == 0)
10060         return(NULL);
10061     else {
10062         int i;
10063         for (i = 0; i < list->nbItems; i++) {
10064             cur = (xmlSchemaBucketPtr) list->items[i];
10065             if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10066                 (cur->origTargetNamespace == targetNamespace) &&
10067                 ((imported && cur->imported) ||
10068                  ((!imported) && (!cur->imported))))
10069                 return(cur);
10070         }
10071     }
10072     return(NULL);
10073 }
10074
10075 static int
10076 xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10077                      xmlSchemaPtr schema,
10078                      xmlSchemaBucketPtr bucket)
10079 {
10080     int oldFlags;
10081     xmlDocPtr oldDoc;
10082     xmlNodePtr node;
10083     int ret, oldErrs;
10084     xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10085
10086     /*
10087     * Save old values; reset the *main* schema.
10088     * URGENT TODO: This is not good; move the per-document information
10089     * to the parser. Get rid of passing the main schema to the
10090     * parsing functions.
10091     */
10092     oldFlags = schema->flags;
10093     oldDoc = schema->doc;
10094     if (schema->flags != 0)
10095         xmlSchemaClearSchemaDefaults(schema);
10096     schema->doc = bucket->doc;
10097     pctxt->schema = schema;
10098     /*
10099     * Keep the current target namespace on the parser *not* on the
10100     * main schema.
10101     */
10102     pctxt->targetNamespace = bucket->targetNamespace;
10103     WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
10104
10105     if ((bucket->targetNamespace != NULL) &&
10106         xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
10107         /*
10108         * We are parsing the schema for schemas!
10109         */
10110         pctxt->isS4S = 1;
10111     }
10112     /* Mark it as parsed, even if parsing fails. */
10113     bucket->parsed++;
10114     /* Compile the schema doc. */
10115     node = xmlDocGetRootElement(bucket->doc);
10116     ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10117     if (ret != 0)
10118         goto exit;
10119     /* An empty schema; just get out. */
10120     if (node->children == NULL)
10121         goto exit;
10122     oldErrs = pctxt->nberrors;
10123     ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10124     if (ret != 0)
10125         goto exit;
10126     /*
10127     * TODO: Not nice, but I'm not 100% sure we will get always an error
10128     * as a result of the obove functions; so better rely on pctxt->err
10129     * as well.
10130     */
10131     if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10132         ret = pctxt->err;
10133         goto exit;
10134     }
10135
10136 exit:
10137     WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10138     /* Restore schema values. */
10139     schema->doc = oldDoc;
10140     schema->flags = oldFlags;
10141     return(ret);
10142 }
10143
10144 static int
10145 xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10146                      xmlSchemaPtr schema,
10147                      xmlSchemaBucketPtr bucket)
10148 {
10149     xmlSchemaParserCtxtPtr newpctxt;
10150     int res = 0;
10151
10152     if (bucket == NULL)
10153         return(0);
10154     if (bucket->parsed) {
10155         PERROR_INT("xmlSchemaParseNewDoc",
10156             "reparsing a schema doc");
10157         return(-1);
10158     }
10159     if (bucket->doc == NULL) {
10160         PERROR_INT("xmlSchemaParseNewDoc",
10161             "parsing a schema doc, but there's no doc");
10162         return(-1);
10163     }
10164     if (pctxt->constructor == NULL) {
10165         PERROR_INT("xmlSchemaParseNewDoc",
10166             "no constructor");
10167         return(-1);
10168     }
10169     /* Create and init the temporary parser context. */
10170     newpctxt = xmlSchemaNewParserCtxtUseDict(
10171         (const char *) bucket->schemaLocation, pctxt->dict);
10172     if (newpctxt == NULL)
10173         return(-1);
10174     newpctxt->constructor = pctxt->constructor;
10175     /*
10176     * TODO: Can we avoid that the parser knows about the main schema?
10177     * It would be better if he knows about the current schema bucket
10178     * only.
10179     */
10180     newpctxt->schema = schema;
10181     xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
10182         pctxt->errCtxt);
10183     xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10184         pctxt->errCtxt);
10185     newpctxt->counter = pctxt->counter;
10186
10187
10188     res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10189
10190     /* Channel back errors and cleanup the temporary parser context. */
10191     if (res != 0)
10192         pctxt->err = res;
10193     pctxt->nberrors += newpctxt->nberrors;
10194     pctxt->counter = newpctxt->counter;
10195     newpctxt->constructor = NULL;
10196     /* Free the parser context. */
10197     xmlSchemaFreeParserCtxt(newpctxt);
10198     return(res);
10199 }
10200
10201 static void
10202 xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10203                                 xmlSchemaSchemaRelationPtr rel)
10204 {
10205     xmlSchemaSchemaRelationPtr cur = bucket->relations;
10206
10207     if (cur == NULL) {
10208         bucket->relations = rel;
10209         return;
10210     }
10211     while (cur->next != NULL)
10212         cur = cur->next;
10213     cur->next = rel;
10214 }
10215
10216
10217 static const xmlChar *
10218 xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10219                           xmlNodePtr ctxtNode)
10220 {
10221     /*
10222     * Build an absolue location URI.
10223     */
10224     if (location != NULL) {
10225         if (ctxtNode == NULL)
10226             return(location);
10227         else {
10228             xmlChar *base, *URI;
10229             const xmlChar *ret = NULL;
10230
10231             base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10232             if (base == NULL) {
10233                 URI = xmlBuildURI(location, ctxtNode->doc->URL);
10234             } else {
10235                 URI = xmlBuildURI(location, base);
10236                 xmlFree(base);
10237             }
10238             if (URI != NULL) {
10239                 ret = xmlDictLookup(dict, URI, -1);
10240                 xmlFree(URI);
10241                 return(ret);
10242             }
10243         }
10244     }
10245     return(NULL);
10246 }
10247
10248
10249
10250 /**
10251  * xmlSchemaAddSchemaDoc:
10252  * @pctxt:  a schema validation context
10253  * @schema:  the schema being built
10254  * @node:  a subtree containing XML Schema informations
10255  *
10256  * Parse an included (and to-be-redefined) XML schema document.
10257  *
10258  * Returns 0 on success, a positive error code on errors and
10259  *         -1 in case of an internal or API error.
10260  */
10261
10262 static int
10263 xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10264                 int type, /* import or include or redefine */
10265                 const xmlChar *schemaLocation,
10266                 xmlDocPtr schemaDoc,
10267                 const char *schemaBuffer,
10268                 int schemaBufferLen,
10269                 xmlNodePtr invokingNode,
10270                 const xmlChar *sourceTargetNamespace,
10271                 const xmlChar *importNamespace,
10272                 xmlSchemaBucketPtr *bucket)
10273 {
10274     const xmlChar *targetNamespace = NULL;
10275     xmlSchemaSchemaRelationPtr relation = NULL;
10276     xmlDocPtr doc = NULL;
10277     int res = 0, err = 0, located = 0, preserveDoc = 0;
10278     xmlSchemaBucketPtr bkt = NULL;
10279
10280     if (bucket != NULL)
10281         *bucket = NULL;
10282
10283     switch (type) {
10284         case XML_SCHEMA_SCHEMA_IMPORT:
10285         case XML_SCHEMA_SCHEMA_MAIN:
10286             err = XML_SCHEMAP_SRC_IMPORT;
10287             break;
10288         case XML_SCHEMA_SCHEMA_INCLUDE:
10289             err = XML_SCHEMAP_SRC_INCLUDE;
10290             break;
10291         case XML_SCHEMA_SCHEMA_REDEFINE:
10292             err = XML_SCHEMAP_SRC_REDEFINE;
10293             break;
10294     }
10295
10296
10297     /* Special handling for the main schema:
10298     * skip the location and relation logic and just parse the doc.
10299     * We need just a bucket to be returned in this case.
10300     */
10301     if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10302         goto doc_load;
10303
10304     /* Note that we expect the location to be an absulute URI. */
10305     if (schemaLocation != NULL) {
10306         bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10307         if ((bkt != NULL) &&
10308             (pctxt->constructor->bucket == bkt)) {
10309             /* Report self-imports/inclusions/redefinitions. */
10310
10311             xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10312                 invokingNode, NULL,
10313                 "The schema must not import/include/redefine itself",
10314                 NULL, NULL);
10315             goto exit;
10316         }
10317     }
10318     /*
10319     * Create a relation for the graph of schemas.
10320     */
10321     relation = xmlSchemaSchemaRelationCreate();
10322     if (relation == NULL)
10323         return(-1);
10324     xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10325         relation);
10326     relation->type = type;
10327
10328     /*
10329     * Save the namespace import information.
10330     */
10331     if (WXS_IS_BUCKET_IMPMAIN(type)) {
10332         relation->importNamespace = importNamespace;
10333         if (schemaLocation == NULL) {
10334             /*
10335             * No location; this is just an import of the namespace.
10336             * Note that we don't assign a bucket to the relation
10337             * in this case.
10338             */
10339             goto exit;
10340         }
10341         targetNamespace = importNamespace;
10342     }
10343
10344     /* Did we already fetch the doc? */
10345     if (bkt != NULL) {
10346         if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
10347             /*
10348             * We included/redefined and then try to import a schema,
10349             * but the new location provided for import was different.
10350             */
10351             if (schemaLocation == NULL)
10352                 schemaLocation = BAD_CAST "in_memory_buffer";
10353             if (!xmlStrEqual(schemaLocation,
10354                 bkt->schemaLocation)) {
10355                 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10356                     invokingNode, NULL,
10357                     "The schema document '%s' cannot be imported, since "
10358                     "it was already included or redefined",
10359                     schemaLocation, NULL);
10360                 goto exit;
10361             }
10362         } else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
10363             /*
10364             * We imported and then try to include/redefine a schema,
10365             * but the new location provided for the include/redefine
10366             * was different.
10367             */
10368             if (schemaLocation == NULL)
10369                 schemaLocation = BAD_CAST "in_memory_buffer";
10370             if (!xmlStrEqual(schemaLocation,
10371                 bkt->schemaLocation)) {
10372                 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10373                     invokingNode, NULL,
10374                     "The schema document '%s' cannot be included or "
10375                     "redefined, since it was already imported",
10376                     schemaLocation, NULL);
10377                 goto exit;
10378             }
10379         }
10380     }
10381
10382     if (WXS_IS_BUCKET_IMPMAIN(type)) {
10383         /*
10384         * Given that the schemaLocation [attribute] is only a hint, it is open
10385         * to applications to ignore all but the first <import> for a given
10386         * namespace, regardless of the ï¿½actual value� of schemaLocation, but
10387         * such a strategy risks missing useful information when new
10388         * schemaLocations are offered.
10389         *
10390         * We will use the first <import> that comes with a location.
10391         * Further <import>s *with* a location, will result in an error.
10392         * TODO: Better would be to just report a warning here, but
10393         * we'll try it this way until someone complains.
10394         *
10395         * Schema Document Location Strategy:
10396         * 3 Based on the namespace name, identify an existing schema document,
10397         * either as a resource which is an XML document or a <schema> element
10398         * information item, in some local schema repository;
10399         * 5 Attempt to resolve the namespace name to locate such a resource.
10400         *
10401         * NOTE: (3) and (5) are not supported.
10402         */
10403         if (bkt != NULL) {
10404             relation->bucket = bkt;
10405             goto exit;
10406         }
10407         bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10408             importNamespace, 1);
10409
10410         if (bkt != NULL) {
10411             relation->bucket = bkt;
10412             if (bkt->schemaLocation == NULL) {
10413                 /* First given location of the schema; load the doc. */
10414                 bkt->schemaLocation = schemaLocation;
10415             } else {
10416                 if (!xmlStrEqual(schemaLocation,
10417                     bkt->schemaLocation)) {
10418                     /*
10419                     * Additional location given; just skip it.
10420                     * URGENT TODO: We should report a warning here.
10421                     * res = XML_SCHEMAP_SRC_IMPORT;
10422                     */
10423                     if (schemaLocation == NULL)
10424                         schemaLocation = BAD_CAST "in_memory_buffer";
10425
10426                     xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10427                         XML_SCHEMAP_WARN_SKIP_SCHEMA,
10428                         invokingNode, NULL,
10429                         "Skipping import of schema located at '%s' for the "
10430                         "namespace '%s', since this namespace was already "
10431                         "imported with the schema located at '%s'",
10432                         schemaLocation, importNamespace, bkt->schemaLocation);
10433                 }
10434                 goto exit;
10435             }
10436         }
10437         /*
10438         * No bucket + first location: load the doc and create a
10439         * bucket.
10440         */
10441     } else {
10442         /* <include> and <redefine> */
10443         if (bkt != NULL) {
10444
10445             if ((bkt->origTargetNamespace == NULL) &&
10446                 (bkt->targetNamespace != sourceTargetNamespace)) {
10447                 xmlSchemaBucketPtr chamel;
10448
10449                 /*
10450                 * Chameleon include/redefine: skip loading only if it was
10451                 * aleady build for the targetNamespace of the including
10452                 * schema.
10453                 */
10454                 /*
10455                 * URGENT TODO: If the schema is a chameleon-include then copy
10456                 * the components into the including schema and modify the
10457                 * targetNamespace of those components, do nothing otherwise.
10458                 * NOTE: This is currently worked-around by compiling the
10459                 * chameleon for every destinct including targetNamespace; thus
10460                 * not performant at the moment.
10461                 * TODO: Check when the namespace in wildcards for chameleons
10462                 * needs to be converted: before we built wildcard intersections
10463                 * or after.
10464                 *   Answer: after!
10465                 */
10466                 chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10467                     schemaLocation, sourceTargetNamespace);
10468                 if (chamel != NULL) {
10469                     /* A fitting chameleon was already parsed; NOP. */
10470                     relation->bucket = chamel;
10471                     goto exit;
10472                 }
10473                 /*
10474                 * We need to parse the chameleon again for a different
10475                 * targetNamespace.
10476                 * CHAMELEON TODO: Optimize this by only parsing the
10477                 * chameleon once, and then copying the components to
10478                 * the new targetNamespace.
10479                 */
10480                 bkt = NULL;
10481             } else {
10482                 relation->bucket = bkt;
10483                 goto exit;
10484             }
10485         }
10486     }
10487     if ((bkt != NULL) && (bkt->doc != NULL)) {
10488         PERROR_INT("xmlSchemaAddSchemaDoc",
10489             "trying to load a schema doc, but a doc is already "
10490             "assigned to the schema bucket");
10491         goto exit_failure;
10492     }
10493
10494 doc_load:
10495     /*
10496     * Load the document.
10497     */
10498     if (schemaDoc != NULL) {
10499         doc = schemaDoc;
10500         /* Don' free this one, since it was provided by the caller. */
10501         preserveDoc = 1;
10502         /* TODO: Does the context or the doc hold the location? */
10503         if (schemaDoc->URL != NULL)
10504             schemaLocation = xmlDictLookup(pctxt->dict,
10505                 schemaDoc->URL, -1);
10506         else
10507             schemaLocation = BAD_CAST "in_memory_buffer";
10508     } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10509         xmlParserCtxtPtr parserCtxt;
10510
10511         parserCtxt = xmlNewParserCtxt();
10512         if (parserCtxt == NULL) {
10513             xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10514                 "allocating a parser context", NULL);
10515             goto exit_failure;
10516         }
10517         if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10518             /*
10519             * TODO: Do we have to burden the schema parser dict with all
10520             * the content of the schema doc?
10521             */
10522             xmlDictFree(parserCtxt->dict);
10523             parserCtxt->dict = pctxt->dict;
10524             xmlDictReference(parserCtxt->dict);
10525         }
10526         if (schemaLocation != NULL) {
10527             /* Parse from file. */
10528             doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10529                 NULL, SCHEMAS_PARSE_OPTIONS);
10530         } else if (schemaBuffer != NULL) {
10531             /* Parse from memory buffer. */
10532             doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10533                 NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10534             schemaLocation = BAD_CAST "in_memory_buffer";
10535             if (doc != NULL)
10536                 doc->URL = xmlStrdup(schemaLocation);
10537         }
10538         /*
10539         * For <import>:
10540         * 2.1 The referent is (a fragment of) a resource which is an
10541         * XML document (see clause 1.1), which in turn corresponds to
10542         * a <schema> element information item in a well-formed information
10543         * set, which in turn corresponds to a valid schema.
10544         * TODO: (2.1) fragments of XML documents are not supported.
10545         *
10546         * 2.2 The referent is a <schema> element information item in
10547         * a well-formed information set, which in turn corresponds
10548         * to a valid schema.
10549         * TODO: (2.2) is not supported.
10550         */
10551         if (doc == NULL) {
10552             xmlErrorPtr lerr;
10553             lerr = xmlGetLastError();
10554             /*
10555             * Check if this a parser error, or if the document could
10556             * just not be located.
10557             * TODO: Try to find specific error codes to react only on
10558             * localisation failures.
10559             */
10560             if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10561                 /*
10562                 * We assume a parser error here.
10563                 */
10564                 located = 1;
10565                 /* TODO: Error code ?? */
10566                 res = XML_SCHEMAP_SRC_IMPORT_2_1;
10567                 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10568                     invokingNode, NULL,
10569                     "Failed to parse the XML resource '%s'",
10570                     schemaLocation, NULL);
10571             }
10572         }
10573         xmlFreeParserCtxt(parserCtxt);
10574         if ((doc == NULL) && located)
10575             goto exit_error;
10576     } else {
10577         xmlSchemaPErr(pctxt, NULL,
10578             XML_SCHEMAP_NOTHING_TO_PARSE,
10579             "No information for parsing was provided with the "
10580             "given schema parser context.\n",
10581             NULL, NULL);
10582         goto exit_failure;
10583     }
10584     /*
10585     * Preprocess the document.
10586     */
10587     if (doc != NULL) {
10588         xmlNodePtr docElem = NULL;
10589
10590         located = 1;
10591         docElem = xmlDocGetRootElement(doc);
10592         if (docElem == NULL) {
10593             xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10594                 invokingNode, NULL,
10595                 "The document '%s' has no document element",
10596                 schemaLocation, NULL);
10597             goto exit_error;
10598         }
10599         /*
10600         * Remove all the blank text nodes.
10601         */
10602         xmlSchemaCleanupDoc(pctxt, docElem);
10603         /*
10604         * Check the schema's top level element.
10605         */
10606         if (!IS_SCHEMA(docElem, "schema")) {
10607             xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10608                 invokingNode, NULL,
10609                 "The XML document '%s' is not a schema document",
10610                 schemaLocation, NULL);
10611             goto exit_error;
10612         }
10613         /*
10614         * Note that we don't apply a type check for the
10615         * targetNamespace value here.
10616         */
10617         targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10618             "targetNamespace");
10619     }
10620
10621 /* after_doc_loading: */
10622     if ((bkt == NULL) && located) {
10623         /* Only create a bucket if the schema was located. */
10624         bkt = xmlSchemaBucketCreate(pctxt, type,
10625             targetNamespace);
10626         if (bkt == NULL)
10627             goto exit_failure;
10628     }
10629     if (bkt != NULL) {
10630         bkt->schemaLocation = schemaLocation;
10631         bkt->located = located;
10632         if (doc != NULL) {
10633             bkt->doc = doc;
10634             bkt->targetNamespace = targetNamespace;
10635             bkt->origTargetNamespace = targetNamespace;
10636             if (preserveDoc)
10637                 bkt->preserveDoc = 1;
10638         }
10639         if (WXS_IS_BUCKET_IMPMAIN(type))
10640             bkt->imported++;
10641             /*
10642             * Add it to the graph of schemas.
10643             */
10644         if (relation != NULL)
10645             relation->bucket = bkt;
10646     }
10647
10648 exit:
10649     /*
10650     * Return the bucket explicitely; this is needed for the
10651     * main schema.
10652     */
10653     if (bucket != NULL)
10654         *bucket = bkt;
10655     return (0);
10656
10657 exit_error:
10658     if ((doc != NULL) && (! preserveDoc)) {
10659         xmlFreeDoc(doc);
10660         if (bkt != NULL)
10661             bkt->doc = NULL;
10662     }
10663     return(pctxt->err);
10664
10665 exit_failure:
10666     if ((doc != NULL) && (! preserveDoc)) {
10667         xmlFreeDoc(doc);
10668         if (bkt != NULL)
10669             bkt->doc = NULL;
10670     }
10671     return (-1);
10672 }
10673
10674 /**
10675  * xmlSchemaParseImport:
10676  * @ctxt:  a schema validation context
10677  * @schema:  the schema being built
10678  * @node:  a subtree containing XML Schema informations
10679  *
10680  * parse a XML schema Import definition
10681  * *WARNING* this interface is highly subject to change
10682  *
10683  * Returns 0 in case of success, a positive error code if
10684  * not valid and -1 in case of an internal error.
10685  */
10686 static int
10687 xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
10688                      xmlNodePtr node)
10689 {
10690     xmlNodePtr child;
10691     const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10692     const xmlChar *thisTargetNamespace;
10693     xmlAttrPtr attr;
10694     int ret = 0;
10695     xmlSchemaBucketPtr bucket = NULL;
10696
10697     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10698         return (-1);
10699
10700     /*
10701     * Check for illegal attributes.
10702     */
10703     attr = node->properties;
10704     while (attr != NULL) {
10705         if (attr->ns == NULL) {
10706             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10707                 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10708                 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10709                 xmlSchemaPIllegalAttrErr(pctxt,
10710                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10711             }
10712         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10713             xmlSchemaPIllegalAttrErr(pctxt,
10714                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10715         }
10716         attr = attr->next;
10717     }
10718     /*
10719     * Extract and validate attributes.
10720     */
10721     if (xmlSchemaPValAttr(pctxt, NULL, node,
10722         "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10723         &namespaceName) != 0) {
10724         xmlSchemaPSimpleTypeErr(pctxt,
10725             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10726             NULL, node,
10727             xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10728             NULL, namespaceName, NULL, NULL, NULL);
10729         return (pctxt->err);
10730     }
10731
10732     if (xmlSchemaPValAttr(pctxt, NULL, node,
10733         "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10734         &schemaLocation) != 0) {
10735         xmlSchemaPSimpleTypeErr(pctxt,
10736             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10737             NULL, node,
10738             xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10739             NULL, namespaceName, NULL, NULL, NULL);
10740         return (pctxt->err);
10741     }
10742     /*
10743     * And now for the children...
10744     */
10745     child = node->children;
10746     if (IS_SCHEMA(child, "annotation")) {
10747         /*
10748          * the annotation here is simply discarded ...
10749          * TODO: really?
10750          */
10751         child = child->next;
10752     }
10753     if (child != NULL) {
10754         xmlSchemaPContentErr(pctxt,
10755             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10756             NULL, node, child, NULL,
10757             "(annotation?)");
10758     }
10759     /*
10760     * Apply additional constraints.
10761     *
10762     * Note that it is important to use the original @targetNamespace
10763     * (or none at all), to rule out imports of schemas _with_ a
10764     * @targetNamespace if the importing schema is a chameleon schema
10765     * (with no @targetNamespace).
10766     */
10767     thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
10768     if (namespaceName != NULL) {
10769         /*
10770         * 1.1 If the namespace [attribute] is present, then its ï¿½actual value�
10771         * must not match the ï¿½actual value� of the enclosing <schema>'s
10772         * targetNamespace [attribute].
10773         */
10774         if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
10775             xmlSchemaPCustomErr(pctxt,
10776                 XML_SCHEMAP_SRC_IMPORT_1_1,
10777                 NULL, node,
10778                 "The value of the attribute 'namespace' must not match "
10779                 "the target namespace '%s' of the importing schema",
10780                 thisTargetNamespace);
10781             return (pctxt->err);
10782         }
10783     } else {
10784         /*
10785         * 1.2 If the namespace [attribute] is not present, then the enclosing
10786         * <schema> must have a targetNamespace [attribute].
10787         */
10788         if (thisTargetNamespace == NULL) {
10789             xmlSchemaPCustomErr(pctxt,
10790                 XML_SCHEMAP_SRC_IMPORT_1_2,
10791                 NULL, node,
10792                 "The attribute 'namespace' must be existent if "
10793                 "the importing schema has no target namespace",
10794                 NULL);
10795             return (pctxt->err);
10796         }
10797     }
10798     /*
10799     * Locate and acquire the schema document.
10800     */
10801     if (schemaLocation != NULL)
10802         schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10803             schemaLocation, node);
10804     ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
10805         schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
10806         namespaceName, &bucket);
10807
10808     if (ret != 0)
10809         return(ret);
10810
10811     /*
10812     * For <import>: "It is *not* an error for the application
10813     * schema reference strategy to fail."
10814     * So just don't parse if no schema document was found.
10815     * Note that we will get no bucket if the schema could not be
10816     * located or if there was no schemaLocation.
10817     */
10818     if ((bucket == NULL) && (schemaLocation != NULL)) {
10819         xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10820             XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10821             node, NULL,
10822             "Failed to locate a schema at location '%s'. "
10823             "Skipping the import", schemaLocation, NULL, NULL);
10824     }
10825
10826     if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10827         ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10828     }
10829
10830     return (ret);
10831 }
10832
10833 static int
10834 xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10835                                      xmlSchemaPtr schema,
10836                                      xmlNodePtr node,
10837                                      xmlChar **schemaLocation,
10838                                      int type)
10839 {
10840     xmlAttrPtr attr;
10841
10842     if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10843         (schemaLocation == NULL))
10844         return (-1);
10845
10846     *schemaLocation = NULL;
10847     /*
10848     * Check for illegal attributes.
10849     * Applies for both <include> and <redefine>.
10850     */
10851     attr = node->properties;
10852     while (attr != NULL) {
10853         if (attr->ns == NULL) {
10854             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10855                 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10856                 xmlSchemaPIllegalAttrErr(pctxt,
10857                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10858             }
10859         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10860             xmlSchemaPIllegalAttrErr(pctxt,
10861                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10862         }
10863         attr = attr->next;
10864     }
10865     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
10866     /*
10867     * Preliminary step, extract the URI-Reference and make an URI
10868     * from the base.
10869     */
10870     /*
10871     * Attribute "schemaLocation" is mandatory.
10872     */
10873     attr = xmlSchemaGetPropNode(node, "schemaLocation");
10874     if (attr != NULL) {
10875         xmlChar *base = NULL;
10876         xmlChar *uri = NULL;
10877
10878         if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
10879             xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10880             (const xmlChar **) schemaLocation) != 0)
10881             goto exit_error;
10882         base = xmlNodeGetBase(node->doc, node);
10883         if (base == NULL) {
10884             uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10885         } else {
10886             uri = xmlBuildURI(*schemaLocation, base);
10887             xmlFree(base);
10888         }
10889         if (uri == NULL) {
10890             PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10891                 "could not build an URI from the schemaLocation")
10892             goto exit_failure;
10893         }
10894         (*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10895         xmlFree(uri);
10896     } else {
10897         xmlSchemaPMissingAttrErr(pctxt,
10898             XML_SCHEMAP_S4S_ATTR_MISSING,
10899             NULL, node, "schemaLocation", NULL);
10900         goto exit_error;
10901     }
10902     /*
10903     * Report self-inclusion and self-redefinition.
10904     */
10905     if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
10906         if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
10907             xmlSchemaPCustomErr(pctxt,
10908                 XML_SCHEMAP_SRC_REDEFINE,
10909                 NULL, node,
10910                 "The schema document '%s' cannot redefine itself.",
10911                 *schemaLocation);
10912         } else {
10913             xmlSchemaPCustomErr(pctxt,
10914                 XML_SCHEMAP_SRC_INCLUDE,
10915                 NULL, node,
10916                 "The schema document '%s' cannot include itself.",
10917                 *schemaLocation);
10918         }
10919         goto exit_error;
10920     }
10921
10922     return(0);
10923 exit_error:
10924     return(pctxt->err);
10925 exit_failure:
10926     return(-1);
10927 }
10928
10929 static int
10930 xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
10931                                 xmlSchemaPtr schema,
10932                                 xmlNodePtr node,
10933                                 int type)
10934 {
10935     xmlNodePtr child = NULL;
10936     const xmlChar *schemaLocation = NULL;
10937     int res = 0; /* hasRedefinitions = 0 */
10938     int isChameleon = 0, wasChameleon = 0;
10939     xmlSchemaBucketPtr bucket = NULL;
10940
10941     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10942         return (-1);
10943
10944     /*
10945     * Parse attributes. Note that the returned schemaLocation will
10946     * be already converted to an absolute URI.
10947     */
10948     res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
10949         node, (xmlChar **) (&schemaLocation), type);
10950     if (res != 0)
10951         return(res);
10952     /*
10953     * Load and add the schema document.
10954     */
10955     res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
10956         NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
10957     if (res != 0)
10958         return(res);
10959     /*
10960     * If we get no schema bucket back, then this means that the schema
10961     * document could not be located or was broken XML or was not
10962     * a schema document.
10963     */
10964     if ((bucket == NULL) || (bucket->doc == NULL)) {
10965         if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
10966             /*
10967             * WARNING for <include>:
10968             * We will raise an error if the schema cannot be located
10969             * for inclusions, since the that was the feedback from the
10970             * schema people. I.e. the following spec piece will *not* be
10971             * satisfied:
10972             * SPEC src-include: "It is not an error for the ï¿½actual value� of the
10973             * schemaLocation [attribute] to fail to resolve it all, in which
10974             * case no corresponding inclusion is performed.
10975             * So do we need a warning report here?"
10976             */
10977             res = XML_SCHEMAP_SRC_INCLUDE;
10978             xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10979                 node, NULL,
10980                 "Failed to load the document '%s' for inclusion",
10981                 schemaLocation, NULL);
10982         } else {
10983             /*
10984             * NOTE: This was changed to raise an error even if no redefinitions
10985             * are specified.
10986             *
10987             * SPEC src-redefine (1)
10988             * "If there are any element information items among the [children]
10989             * other than <annotation> then the ï¿½actual value� of the
10990             * schemaLocation [attribute] must successfully resolve."
10991             * TODO: Ask the WG if a the location has always to resolve
10992             * here as well!
10993             */
10994             res = XML_SCHEMAP_SRC_REDEFINE;
10995             xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10996                 node, NULL,
10997                 "Failed to load the document '%s' for redefinition",
10998                 schemaLocation, NULL);
10999         }
11000     } else {
11001         /*
11002         * Check targetNamespace sanity before parsing the new schema.
11003         * TODO: Note that we won't check further content if the
11004         * targetNamespace was bad.
11005         */
11006         if (bucket->origTargetNamespace != NULL) {
11007             /*
11008             * SPEC src-include (2.1)
11009             * "SII has a targetNamespace [attribute], and its ï¿½actual
11010             * value� is identical to the ï¿½actual value� of the targetNamespace
11011             * [attribute] of SII� (which must have such an [attribute])."
11012             */
11013             if (pctxt->targetNamespace == NULL) {
11014                 xmlSchemaCustomErr(ACTXT_CAST pctxt,
11015                     XML_SCHEMAP_SRC_INCLUDE,
11016                     node, NULL,
11017                     "The target namespace of the included/redefined schema "
11018                     "'%s' has to be absent, since the including/redefining "
11019                     "schema has no target namespace",
11020                     schemaLocation, NULL);
11021                 goto exit_error;
11022             } else if (!xmlStrEqual(bucket->origTargetNamespace,
11023                 pctxt->targetNamespace)) {
11024                 /* TODO: Change error function. */
11025                 xmlSchemaPCustomErrExt(pctxt,
11026                     XML_SCHEMAP_SRC_INCLUDE,
11027                     NULL, node,
11028                     "The target namespace '%s' of the included/redefined "
11029                     "schema '%s' differs from '%s' of the "
11030                     "including/redefining schema",
11031                     bucket->origTargetNamespace, schemaLocation,
11032                     pctxt->targetNamespace);
11033                 goto exit_error;
11034             }
11035         } else if (pctxt->targetNamespace != NULL) {
11036             /*
11037             * Chameleons: the original target namespace will
11038             * differ from the resulting namespace.
11039             */
11040             isChameleon = 1;
11041             if (bucket->parsed &&
11042                 bucket->origTargetNamespace != NULL) {
11043                 xmlSchemaCustomErr(ACTXT_CAST pctxt,
11044                     XML_SCHEMAP_SRC_INCLUDE,
11045                     node, NULL,
11046                     "The target namespace of the included/redefined schema "
11047                     "'%s' has to be absent or the same as the "
11048                     "including/redefining schema's target namespace",
11049                     schemaLocation, NULL);
11050                 goto exit_error;
11051             }
11052             bucket->targetNamespace = pctxt->targetNamespace;
11053         }
11054     }
11055     /*
11056     * Parse the schema.
11057     */
11058     if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11059         if (isChameleon) {
11060             /* TODO: Get rid of this flag on the schema itself. */
11061             if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11062                 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11063             } else
11064                 wasChameleon = 1;
11065         }
11066         xmlSchemaParseNewDoc(pctxt, schema, bucket);
11067         /* Restore chameleon flag. */
11068         if (isChameleon && (!wasChameleon))
11069             schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11070     }
11071     /*
11072     * And now for the children...
11073     */
11074     child = node->children;
11075     if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11076         /*
11077         * Parse (simpleType | complexType | group | attributeGroup))*
11078         */
11079         pctxt->redefined = bucket;
11080         /*
11081         * How to proceed if the redefined schema was not located?
11082         */
11083         pctxt->isRedefine = 1;
11084         while (IS_SCHEMA(child, "annotation") ||
11085             IS_SCHEMA(child, "simpleType") ||
11086             IS_SCHEMA(child, "complexType") ||
11087             IS_SCHEMA(child, "group") ||
11088             IS_SCHEMA(child, "attributeGroup")) {
11089             if (IS_SCHEMA(child, "annotation")) {
11090                 /*
11091                 * TODO: discard or not?
11092                 */
11093             } else if (IS_SCHEMA(child, "simpleType")) {
11094                 xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11095             } else if (IS_SCHEMA(child, "complexType")) {
11096                 xmlSchemaParseComplexType(pctxt, schema, child, 1);
11097                 /* hasRedefinitions = 1; */
11098             } else if (IS_SCHEMA(child, "group")) {
11099                 /* hasRedefinitions = 1; */
11100                 xmlSchemaParseModelGroupDefinition(pctxt,
11101                     schema, child);
11102             } else if (IS_SCHEMA(child, "attributeGroup")) {
11103                 /* hasRedefinitions = 1; */
11104                 xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11105                     child);
11106             }
11107             child = child->next;
11108         }
11109         pctxt->redefined = NULL;
11110         pctxt->isRedefine = 0;
11111     } else {
11112         if (IS_SCHEMA(child, "annotation")) {
11113             /*
11114             * TODO: discard or not?
11115             */
11116             child = child->next;
11117         }
11118     }
11119     if (child != NULL) {
11120         res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
11121         if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11122             xmlSchemaPContentErr(pctxt, res,
11123                 NULL, node, child, NULL,
11124                 "(annotation | (simpleType | complexType | group | attributeGroup))*");
11125         } else {
11126              xmlSchemaPContentErr(pctxt, res,
11127                 NULL, node, child, NULL,
11128                 "(annotation?)");
11129         }
11130     }
11131     return(res);
11132
11133 exit_error:
11134     return(pctxt->err);
11135 }
11136
11137 static int
11138 xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11139                        xmlNodePtr node)
11140 {
11141     int res;
11142 #ifndef ENABLE_REDEFINE
11143     TODO
11144     return(0);
11145 #endif
11146     res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11147         XML_SCHEMA_SCHEMA_REDEFINE);
11148     if (res != 0)
11149         return(res);
11150     return(0);
11151 }
11152
11153 static int
11154 xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11155                        xmlNodePtr node)
11156 {
11157     int res;
11158
11159     res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11160         XML_SCHEMA_SCHEMA_INCLUDE);
11161     if (res != 0)
11162         return(res);
11163     return(0);
11164 }
11165
11166 /**
11167  * xmlSchemaParseModelGroup:
11168  * @ctxt:  a schema validation context
11169  * @schema:  the schema being built
11170  * @node:  a subtree containing XML Schema informations
11171  * @type: the "compositor" type
11172  * @particleNeeded: if a a model group with a particle
11173  *
11174  * parse a XML schema Sequence definition.
11175  * Applies parts of:
11176  *   Schema Representation Constraint:
11177  *     Redefinition Constraints and Semantics (src-redefine)
11178  *     (6.1), (6.1.1), (6.1.2)
11179  *
11180  *   Schema Component Constraint:
11181  *     All Group Limited (cos-all-limited) (2)
11182  *     TODO: Actually this should go to component-level checks,
11183  *     but is done here due to performance. Move it to an other layer
11184  *     is schema construction via an API is implemented.
11185  *
11186  * *WARNING* this interface is highly subject to change
11187  *
11188  * Returns -1 in case of error, 0 if the declaration is improper and
11189  *         1 in case of success.
11190  */
11191 static xmlSchemaTreeItemPtr
11192 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11193                          xmlNodePtr node, xmlSchemaTypeType type,
11194                          int withParticle)
11195 {
11196     xmlSchemaModelGroupPtr item;
11197     xmlSchemaParticlePtr particle = NULL;
11198     xmlNodePtr child = NULL;
11199     xmlAttrPtr attr;
11200     int min = 1, max = 1, isElemRef, hasRefs = 0;
11201
11202     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11203         return (NULL);
11204     /*
11205     * Create a model group with the given compositor.
11206     */
11207     item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
11208     if (item == NULL)
11209         return (NULL);
11210
11211     if (withParticle) {
11212         if (type == XML_SCHEMA_TYPE_ALL) {
11213             min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
11214             max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
11215         } else {
11216             /* choice + sequence */
11217             min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11218             max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11219                 "(xs:nonNegativeInteger | unbounded)");
11220         }
11221         xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11222         /*
11223         * Create a particle
11224         */
11225         particle = xmlSchemaAddParticle(ctxt, node, min, max);
11226         if (particle == NULL)
11227             return (NULL);
11228         particle->children = (xmlSchemaTreeItemPtr) item;
11229         /*
11230         * Check for illegal attributes.
11231         */
11232         attr = node->properties;
11233         while (attr != NULL) {
11234             if (attr->ns == NULL) {
11235                 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11236                     (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11237                     (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
11238                     xmlSchemaPIllegalAttrErr(ctxt,
11239                         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11240                 }
11241             } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11242                 xmlSchemaPIllegalAttrErr(ctxt,
11243                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11244             }
11245             attr = attr->next;
11246         }
11247     } else {
11248         /*
11249         * Check for illegal attributes.
11250         */
11251         attr = node->properties;
11252         while (attr != NULL) {
11253             if (attr->ns == NULL) {
11254                 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
11255                     xmlSchemaPIllegalAttrErr(ctxt,
11256                         XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11257                 }
11258             } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11259                 xmlSchemaPIllegalAttrErr(ctxt,
11260                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11261             }
11262             attr = attr->next;
11263         }
11264     }
11265
11266     /*
11267     * Extract and validate attributes.
11268     */
11269     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11270     /*
11271     * And now for the children...
11272     */
11273     child = node->children;
11274     if (IS_SCHEMA(child, "annotation")) {
11275         item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
11276         child = child->next;
11277     }
11278     if (type == XML_SCHEMA_TYPE_ALL) {
11279         xmlSchemaParticlePtr part, last = NULL;
11280
11281         while (IS_SCHEMA(child, "element")) {
11282             part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
11283                 schema, child, &isElemRef, 0);
11284             /*
11285             * SPEC cos-all-limited (2)
11286             * "The {max occurs} of all the particles in the {particles}
11287             * of the ('all') group must be 0 or 1.
11288             */
11289             if (part != NULL) {
11290                 if (isElemRef)
11291                     hasRefs++;
11292                 if (part->minOccurs > 1) {
11293                     xmlSchemaPCustomErr(ctxt,
11294                         XML_SCHEMAP_COS_ALL_LIMITED,
11295                         NULL, child,
11296                         "Invalid value for minOccurs (must be 0 or 1)",
11297                         NULL);
11298                     /* Reset to 1. */
11299                     part->minOccurs = 1;
11300                 }
11301                 if (part->maxOccurs > 1) {
11302                     xmlSchemaPCustomErr(ctxt,
11303                         XML_SCHEMAP_COS_ALL_LIMITED,
11304                         NULL, child,
11305                         "Invalid value for maxOccurs (must be 0 or 1)",
11306                         NULL);
11307                     /* Reset to 1. */
11308                     part->maxOccurs = 1;
11309                 }
11310                 if (last == NULL)
11311                     item->children = (xmlSchemaTreeItemPtr) part;
11312                 else
11313                     last->next = (xmlSchemaTreeItemPtr) part;
11314                 last = part;
11315             }
11316             child = child->next;
11317         }
11318         if (child != NULL) {
11319             xmlSchemaPContentErr(ctxt,
11320                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11321                 NULL, node, child, NULL,
11322                 "(annotation?, (annotation?, element*)");
11323         }
11324     } else {
11325         /* choice + sequence */
11326         xmlSchemaTreeItemPtr part = NULL, last = NULL;
11327
11328         while ((IS_SCHEMA(child, "element")) ||
11329             (IS_SCHEMA(child, "group")) ||
11330             (IS_SCHEMA(child, "any")) ||
11331             (IS_SCHEMA(child, "choice")) ||
11332             (IS_SCHEMA(child, "sequence"))) {
11333
11334             if (IS_SCHEMA(child, "element")) {
11335                 part = (xmlSchemaTreeItemPtr)
11336                     xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11337                 if (part && isElemRef)
11338                     hasRefs++;
11339             } else if (IS_SCHEMA(child, "group")) {
11340                 part =
11341                     xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11342                 if (part != NULL)
11343                     hasRefs++;
11344                 /*
11345                 * Handle redefinitions.
11346                 */
11347                 if (ctxt->isRedefine && ctxt->redef &&
11348                     (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11349                     part && part->children)
11350                 {
11351                     if ((xmlSchemaGetQNameRefName(part->children) ==
11352                             ctxt->redef->refName) &&
11353                         (xmlSchemaGetQNameRefTargetNs(part->children) ==
11354                             ctxt->redef->refTargetNs))
11355                     {
11356                         /*
11357                         * SPEC src-redefine:
11358                         * (6.1) "If it has a <group> among its contents at
11359                         * some level the ï¿½actual value� of whose ref
11360                         * [attribute] is the same as the ï¿½actual value� of
11361                         * its own name attribute plus target namespace, then
11362                         * all of the following must be true:"
11363                         * (6.1.1) "It must have exactly one such group."
11364                         */
11365                         if (ctxt->redefCounter != 0) {
11366                             xmlChar *str = NULL;
11367
11368                             xmlSchemaCustomErr(ACTXT_CAST ctxt,
11369                                 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11370                                 "The redefining model group definition "
11371                                 "'%s' must not contain more than one "
11372                                 "reference to the redefined definition",
11373                                 xmlSchemaFormatQName(&str,
11374                                     ctxt->redef->refTargetNs,
11375                                     ctxt->redef->refName),
11376                                 NULL);
11377                             FREE_AND_NULL(str)
11378                             part = NULL;
11379                         } else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11380                             ((WXS_PARTICLE(part))->maxOccurs != 1))
11381                         {
11382                             xmlChar *str = NULL;
11383                             /*
11384                             * SPEC src-redefine:
11385                             * (6.1.2) "The ï¿½actual value� of both that
11386                             * group's minOccurs and maxOccurs [attribute]
11387                             * must be 1 (or ï¿½absent�).
11388                             */
11389                             xmlSchemaCustomErr(ACTXT_CAST ctxt,
11390                                 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11391                                 "The redefining model group definition "
11392                                 "'%s' must not contain a reference to the "
11393                                 "redefined definition with a "
11394                                 "maxOccurs/minOccurs other than 1",
11395                                 xmlSchemaFormatQName(&str,
11396                                     ctxt->redef->refTargetNs,
11397                                     ctxt->redef->refName),
11398                                 NULL);
11399                             FREE_AND_NULL(str)
11400                             part = NULL;
11401                         }
11402                         ctxt->redef->reference = WXS_BASIC_CAST part;
11403                         ctxt->redefCounter++;
11404                     }
11405                 }
11406             } else if (IS_SCHEMA(child, "any")) {
11407                 part = (xmlSchemaTreeItemPtr)
11408                     xmlSchemaParseAny(ctxt, schema, child);
11409             } else if (IS_SCHEMA(child, "choice")) {
11410                 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11411                     XML_SCHEMA_TYPE_CHOICE, 1);
11412             } else if (IS_SCHEMA(child, "sequence")) {
11413                 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11414                     XML_SCHEMA_TYPE_SEQUENCE, 1);
11415             }
11416             if (part != NULL) {
11417                 if (last == NULL)
11418                     item->children = part;
11419                 else
11420                     last->next = part;
11421                 last = part;
11422             }
11423             child = child->next;
11424         }
11425         if (child != NULL) {
11426             xmlSchemaPContentErr(ctxt,
11427                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11428                 NULL, node, child, NULL,
11429                 "(annotation?, (element | group | choice | sequence | any)*)");
11430         }
11431     }
11432     if ((max == 0) && (min == 0))
11433         return (NULL);
11434     if (hasRefs) {
11435         /*
11436         * We need to resolve references.
11437         */
11438         WXS_ADD_PENDING(ctxt, item);
11439     }
11440     if (withParticle)
11441         return ((xmlSchemaTreeItemPtr) particle);
11442     else
11443         return ((xmlSchemaTreeItemPtr) item);
11444 }
11445
11446 /**
11447  * xmlSchemaParseRestriction:
11448  * @ctxt:  a schema validation context
11449  * @schema:  the schema being built
11450  * @node:  a subtree containing XML Schema informations
11451  *
11452  * parse a XML schema Restriction definition
11453  * *WARNING* this interface is highly subject to change
11454  *
11455  * Returns the type definition or NULL in case of error
11456  */
11457 static xmlSchemaTypePtr
11458 xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11459                           xmlNodePtr node, xmlSchemaTypeType parentType)
11460 {
11461     xmlSchemaTypePtr type;
11462     xmlNodePtr child = NULL;
11463     xmlAttrPtr attr;
11464
11465     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11466         return (NULL);
11467     /* Not a component, don't create it. */
11468     type = ctxt->ctxtType;
11469     type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
11470
11471     /*
11472     * Check for illegal attributes.
11473     */
11474     attr = node->properties;
11475     while (attr != NULL) {
11476         if (attr->ns == NULL) {
11477             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11478                 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11479                 xmlSchemaPIllegalAttrErr(ctxt,
11480                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11481             }
11482         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11483             xmlSchemaPIllegalAttrErr(ctxt,
11484                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11485         }
11486         attr = attr->next;
11487     }
11488     /*
11489     * Extract and validate attributes.
11490     */
11491     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11492     /*
11493     * Attribute
11494     */
11495     /*
11496     * Extract the base type. The "base" attribute is mandatory if inside
11497     * a complex type or if redefining.
11498     *
11499     * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
11500     * among its [children]), the simple type definition which is
11501     * the {content type} of the type definition ï¿½resolved� to by
11502     * the ï¿½actual value� of the base [attribute]"
11503     */
11504     if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
11505         &(type->baseNs), &(type->base)) == 0)
11506     {
11507         if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11508             xmlSchemaPMissingAttrErr(ctxt,
11509                 XML_SCHEMAP_S4S_ATTR_MISSING,
11510                 NULL, node, "base", NULL);
11511         } else if ((ctxt->isRedefine) &&
11512             (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11513         {
11514             if (type->base == NULL) {
11515                 xmlSchemaPMissingAttrErr(ctxt,
11516                     XML_SCHEMAP_S4S_ATTR_MISSING,
11517                     NULL, node, "base", NULL);
11518             } else if ((! xmlStrEqual(type->base, type->name)) ||
11519                 (! xmlStrEqual(type->baseNs, type->targetNamespace)))
11520             {
11521                 xmlChar *str1 = NULL, *str2 = NULL;
11522                 /*
11523                 * REDEFINE: SPEC src-redefine (5)
11524                 * "Within the [children], each <simpleType> must have a
11525                 * <restriction> among its [children] ... the ï¿½actual value� of
11526                 * whose base [attribute] must be the same as the ï¿½actual value�
11527                 * of its own name attribute plus target namespace;"
11528                 */
11529                 xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
11530                     NULL, node, "This is a redefinition, but the QName "
11531                     "value '%s' of the 'base' attribute does not match the "
11532                     "type's designation '%s'",
11533                     xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11534                     xmlSchemaFormatQName(&str2, type->targetNamespace,
11535                         type->name), NULL);
11536                 FREE_AND_NULL(str1);
11537                 FREE_AND_NULL(str2);
11538                 /* Avoid confusion and erase the values. */
11539                 type->base = NULL;
11540                 type->baseNs = NULL;
11541             }
11542         }
11543     }
11544     /*
11545     * And now for the children...
11546     */
11547     child = node->children;
11548     if (IS_SCHEMA(child, "annotation")) {
11549         /*
11550         * Add the annotation to the simple type ancestor.
11551         */
11552         xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11553             xmlSchemaParseAnnotation(ctxt, child, 1));
11554         child = child->next;
11555     }
11556     if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11557         /*
11558         * Corresponds to <simpleType><restriction><simpleType>.
11559         */
11560         if (IS_SCHEMA(child, "simpleType")) {
11561             if (type->base != NULL) {
11562                 /*
11563                 * src-restriction-base-or-simpleType
11564                 * Either the base [attribute] or the simpleType [child] of the
11565                 * <restriction> element must be present, but not both.
11566                 */
11567                 xmlSchemaPContentErr(ctxt,
11568                     XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11569                     NULL, node, child,
11570                     "The attribute 'base' and the <simpleType> child are "
11571                     "mutually exclusive", NULL);
11572             } else {
11573                 type->baseType = (xmlSchemaTypePtr)
11574                     xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11575             }
11576             child = child->next;
11577         } else if (type->base == NULL) {
11578             xmlSchemaPContentErr(ctxt,
11579                 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11580                 NULL, node, child,
11581                 "Either the attribute 'base' or a <simpleType> child "
11582                 "must be present", NULL);
11583         }
11584     } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11585         /*
11586         * Corresponds to <complexType><complexContent><restriction>...
11587         * followed by:
11588         *
11589         * Model groups <all>, <choice> and <sequence>.
11590         */
11591         if (IS_SCHEMA(child, "all")) {
11592             type->subtypes = (xmlSchemaTypePtr)
11593                 xmlSchemaParseModelGroup(ctxt, schema, child,
11594                     XML_SCHEMA_TYPE_ALL, 1);
11595             child = child->next;
11596         } else if (IS_SCHEMA(child, "choice")) {
11597             type->subtypes = (xmlSchemaTypePtr)
11598                 xmlSchemaParseModelGroup(ctxt,
11599                     schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11600             child = child->next;
11601         } else if (IS_SCHEMA(child, "sequence")) {
11602             type->subtypes = (xmlSchemaTypePtr)
11603                 xmlSchemaParseModelGroup(ctxt, schema, child,
11604                     XML_SCHEMA_TYPE_SEQUENCE, 1);
11605             child = child->next;
11606         /*
11607         * Model group reference <group>.
11608         */
11609         } else if (IS_SCHEMA(child, "group")) {
11610             type->subtypes = (xmlSchemaTypePtr)
11611                 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11612             /*
11613             * Note that the reference will be resolved in
11614             * xmlSchemaResolveTypeReferences();
11615             */
11616             child = child->next;
11617         }
11618     } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11619         /*
11620         * Corresponds to <complexType><simpleContent><restriction>...
11621         *
11622         * "1.1 the simple type definition corresponding to the <simpleType>
11623         * among the [children] of <restriction> if there is one;"
11624         */
11625         if (IS_SCHEMA(child, "simpleType")) {
11626             /*
11627             * We will store the to-be-restricted simple type in
11628             * type->contentTypeDef *temporarily*.
11629             */
11630             type->contentTypeDef = (xmlSchemaTypePtr)
11631                 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11632             if ( type->contentTypeDef == NULL)
11633                 return (NULL);
11634             child = child->next;
11635         }
11636     }
11637
11638     if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
11639         (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
11640         xmlSchemaFacetPtr facet, lastfacet = NULL;
11641         /*
11642         * Corresponds to <complexType><simpleContent><restriction>...
11643         * <simpleType><restriction>...
11644         */
11645
11646         /*
11647         * Add the facets to the simple type ancestor.
11648         */
11649         /*
11650         * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11651         * Simple Type Definition Schema Representation Constraint:
11652         * *Single Facet Value*
11653         */
11654         while ((IS_SCHEMA(child, "minInclusive")) ||
11655             (IS_SCHEMA(child, "minExclusive")) ||
11656             (IS_SCHEMA(child, "maxInclusive")) ||
11657             (IS_SCHEMA(child, "maxExclusive")) ||
11658             (IS_SCHEMA(child, "totalDigits")) ||
11659             (IS_SCHEMA(child, "fractionDigits")) ||
11660             (IS_SCHEMA(child, "pattern")) ||
11661             (IS_SCHEMA(child, "enumeration")) ||
11662             (IS_SCHEMA(child, "whiteSpace")) ||
11663             (IS_SCHEMA(child, "length")) ||
11664             (IS_SCHEMA(child, "maxLength")) ||
11665             (IS_SCHEMA(child, "minLength"))) {
11666             facet = xmlSchemaParseFacet(ctxt, schema, child);
11667             if (facet != NULL) {
11668                 if (lastfacet == NULL)
11669                     type->facets = facet;
11670                 else
11671                     lastfacet->next = facet;
11672                 lastfacet = facet;
11673                 lastfacet->next = NULL;
11674             }
11675             child = child->next;
11676         }
11677         /*
11678         * Create links for derivation and validation.
11679         */
11680         if (type->facets != NULL) {
11681             xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11682
11683             facet = type->facets;
11684             do {
11685                 facetLink = (xmlSchemaFacetLinkPtr)
11686                     xmlMalloc(sizeof(xmlSchemaFacetLink));
11687                 if (facetLink == NULL) {
11688                     xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
11689                     xmlFree(facetLink);
11690                     return (NULL);
11691                 }
11692                 facetLink->facet = facet;
11693                 facetLink->next = NULL;
11694                 if (lastFacetLink == NULL)
11695                     type->facetSet = facetLink;
11696                 else
11697                     lastFacetLink->next = facetLink;
11698                 lastFacetLink = facetLink;
11699                 facet = facet->next;
11700             } while (facet != NULL);
11701         }
11702     }
11703     if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11704         /*
11705         * Attribute uses/declarations.
11706         */
11707         if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11708             (xmlSchemaItemListPtr *) &(type->attrUses),
11709             XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11710             return(NULL);
11711         /*
11712         * Attribute wildcard.
11713         */
11714         if (IS_SCHEMA(child, "anyAttribute")) {
11715             type->attributeWildcard =
11716                 xmlSchemaParseAnyAttribute(ctxt, schema, child);
11717             child = child->next;
11718         }
11719     }
11720     if (child != NULL) {
11721         if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11722             xmlSchemaPContentErr(ctxt,
11723                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11724                 NULL, node, child, NULL,
11725                 "annotation?, (group | all | choice | sequence)?, "
11726                 "((attribute | attributeGroup)*, anyAttribute?))");
11727         } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11728              xmlSchemaPContentErr(ctxt,
11729                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11730                 NULL, node, child, NULL,
11731                 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11732                 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11733                 "length | minLength | maxLength | enumeration | whiteSpace | "
11734                 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11735         } else {
11736             /* Simple type */
11737             xmlSchemaPContentErr(ctxt,
11738                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11739                 NULL, node, child, NULL,
11740                 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11741                 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11742                 "length | minLength | maxLength | enumeration | whiteSpace | "
11743                 "pattern)*))");
11744         }
11745     }
11746     return (NULL);
11747 }
11748
11749 /**
11750  * xmlSchemaParseExtension:
11751  * @ctxt:  a schema validation context
11752  * @schema:  the schema being built
11753  * @node:  a subtree containing XML Schema informations
11754  *
11755  * Parses an <extension>, which is found inside a
11756  * <simpleContent> or <complexContent>.
11757  * *WARNING* this interface is highly subject to change.
11758  *
11759  * TODO: Returns the type definition or NULL in case of error
11760  */
11761 static xmlSchemaTypePtr
11762 xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11763                         xmlNodePtr node, xmlSchemaTypeType parentType)
11764 {
11765     xmlSchemaTypePtr type;
11766     xmlNodePtr child = NULL;
11767     xmlAttrPtr attr;
11768
11769     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11770         return (NULL);
11771     /* Not a component, don't create it. */
11772     type = ctxt->ctxtType;
11773     type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
11774
11775     /*
11776     * Check for illegal attributes.
11777     */
11778     attr = node->properties;
11779     while (attr != NULL) {
11780         if (attr->ns == NULL) {
11781             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11782                 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11783                 xmlSchemaPIllegalAttrErr(ctxt,
11784                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11785             }
11786         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11787             xmlSchemaPIllegalAttrErr(ctxt,
11788                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11789         }
11790         attr = attr->next;
11791     }
11792
11793     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11794
11795     /*
11796     * Attribute "base" - mandatory.
11797     */
11798     if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11799         "base", &(type->baseNs), &(type->base)) == 0) &&
11800         (type->base == NULL)) {
11801         xmlSchemaPMissingAttrErr(ctxt,
11802             XML_SCHEMAP_S4S_ATTR_MISSING,
11803             NULL, node, "base", NULL);
11804     }
11805     /*
11806     * And now for the children...
11807     */
11808     child = node->children;
11809     if (IS_SCHEMA(child, "annotation")) {
11810         /*
11811         * Add the annotation to the type ancestor.
11812         */
11813         xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11814             xmlSchemaParseAnnotation(ctxt, child, 1));
11815         child = child->next;
11816     }
11817     if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11818         /*
11819         * Corresponds to <complexType><complexContent><extension>... and:
11820         *
11821         * Model groups <all>, <choice>, <sequence> and <group>.
11822         */
11823         if (IS_SCHEMA(child, "all")) {
11824             type->subtypes = (xmlSchemaTypePtr)
11825                 xmlSchemaParseModelGroup(ctxt, schema,
11826                     child, XML_SCHEMA_TYPE_ALL, 1);
11827             child = child->next;
11828         } else if (IS_SCHEMA(child, "choice")) {
11829             type->subtypes = (xmlSchemaTypePtr)
11830                 xmlSchemaParseModelGroup(ctxt, schema,
11831                     child, XML_SCHEMA_TYPE_CHOICE, 1);
11832             child = child->next;
11833         } else if (IS_SCHEMA(child, "sequence")) {
11834             type->subtypes = (xmlSchemaTypePtr)
11835                 xmlSchemaParseModelGroup(ctxt, schema,
11836                 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11837             child = child->next;
11838         } else if (IS_SCHEMA(child, "group")) {
11839             type->subtypes = (xmlSchemaTypePtr)
11840                 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11841             /*
11842             * Note that the reference will be resolved in
11843             * xmlSchemaResolveTypeReferences();
11844             */
11845             child = child->next;
11846         }
11847     }
11848     if (child != NULL) {
11849         /*
11850         * Attribute uses/declarations.
11851         */
11852         if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11853             (xmlSchemaItemListPtr *) &(type->attrUses),
11854             XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11855             return(NULL);
11856         /*
11857         * Attribute wildcard.
11858         */
11859         if (IS_SCHEMA(child, "anyAttribute")) {
11860             ctxt->ctxtType->attributeWildcard =
11861                 xmlSchemaParseAnyAttribute(ctxt, schema, child);
11862             child = child->next;
11863         }
11864     }
11865     if (child != NULL) {
11866         if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11867             /* Complex content extension. */
11868             xmlSchemaPContentErr(ctxt,
11869                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11870                 NULL, node, child, NULL,
11871                 "(annotation?, ((group | all | choice | sequence)?, "
11872                 "((attribute | attributeGroup)*, anyAttribute?)))");
11873         } else {
11874             /* Simple content extension. */
11875             xmlSchemaPContentErr(ctxt,
11876                 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11877                 NULL, node, child, NULL,
11878                 "(annotation?, ((attribute | attributeGroup)*, "
11879                 "anyAttribute?))");
11880         }
11881     }
11882     return (NULL);
11883 }
11884
11885 /**
11886  * xmlSchemaParseSimpleContent:
11887  * @ctxt:  a schema validation context
11888  * @schema:  the schema being built
11889  * @node:  a subtree containing XML Schema informations
11890  *
11891  * parse a XML schema SimpleContent definition
11892  * *WARNING* this interface is highly subject to change
11893  *
11894  * Returns the type definition or NULL in case of error
11895  */
11896 static int
11897 xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
11898                             xmlSchemaPtr schema, xmlNodePtr node,
11899                             int *hasRestrictionOrExtension)
11900 {
11901     xmlSchemaTypePtr type;
11902     xmlNodePtr child = NULL;
11903     xmlAttrPtr attr;
11904
11905     if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11906         (hasRestrictionOrExtension == NULL))
11907         return (-1);
11908     *hasRestrictionOrExtension = 0;
11909     /* Not a component, don't create it. */
11910     type = ctxt->ctxtType;
11911     type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11912     /*
11913     * Check for illegal attributes.
11914     */
11915     attr = node->properties;
11916     while (attr != NULL) {
11917         if (attr->ns == NULL) {
11918             if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
11919                 xmlSchemaPIllegalAttrErr(ctxt,
11920                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11921             }
11922         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11923             xmlSchemaPIllegalAttrErr(ctxt,
11924                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11925         }
11926         attr = attr->next;
11927     }
11928
11929     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11930
11931     /*
11932     * And now for the children...
11933     */
11934     child = node->children;
11935     if (IS_SCHEMA(child, "annotation")) {
11936         /*
11937         * Add the annotation to the complex type ancestor.
11938         */
11939         xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11940             xmlSchemaParseAnnotation(ctxt, child, 1));
11941         child = child->next;
11942     }
11943     if (child == NULL) {
11944         xmlSchemaPContentErr(ctxt,
11945             XML_SCHEMAP_S4S_ELEM_MISSING,
11946             NULL, node, NULL, NULL,
11947             "(annotation?, (restriction | extension))");
11948     }
11949     if (child == NULL) {
11950         xmlSchemaPContentErr(ctxt,
11951             XML_SCHEMAP_S4S_ELEM_MISSING,
11952             NULL, node, NULL, NULL,
11953             "(annotation?, (restriction | extension))");
11954     }
11955     if (IS_SCHEMA(child, "restriction")) {
11956         xmlSchemaParseRestriction(ctxt, schema, child,
11957             XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11958         (*hasRestrictionOrExtension) = 1;
11959         child = child->next;
11960     } else if (IS_SCHEMA(child, "extension")) {
11961         xmlSchemaParseExtension(ctxt, schema, child,
11962             XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11963         (*hasRestrictionOrExtension) = 1;
11964         child = child->next;
11965     }
11966     if (child != NULL) {
11967         xmlSchemaPContentErr(ctxt,
11968             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11969             NULL, node, child, NULL,
11970             "(annotation?, (restriction | extension))");
11971     }
11972     return (0);
11973 }
11974
11975 /**
11976  * xmlSchemaParseComplexContent:
11977  * @ctxt:  a schema validation context
11978  * @schema:  the schema being built
11979  * @node:  a subtree containing XML Schema informations
11980  *
11981  * parse a XML schema ComplexContent definition
11982  * *WARNING* this interface is highly subject to change
11983  *
11984  * Returns the type definition or NULL in case of error
11985  */
11986 static int
11987 xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
11988                              xmlSchemaPtr schema, xmlNodePtr node,
11989                              int *hasRestrictionOrExtension)
11990 {
11991     xmlSchemaTypePtr type;
11992     xmlNodePtr child = NULL;
11993     xmlAttrPtr attr;
11994
11995     if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11996         (hasRestrictionOrExtension == NULL))
11997         return (-1);
11998     *hasRestrictionOrExtension = 0;
11999     /* Not a component, don't create it. */
12000     type = ctxt->ctxtType;
12001     /*
12002     * Check for illegal attributes.
12003     */
12004     attr = node->properties;
12005     while (attr != NULL) {
12006         if (attr->ns == NULL) {
12007             if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
12008                 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
12009             {
12010                 xmlSchemaPIllegalAttrErr(ctxt,
12011                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12012             }
12013         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12014             xmlSchemaPIllegalAttrErr(ctxt,
12015                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12016         }
12017         attr = attr->next;
12018     }
12019
12020     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12021
12022     /*
12023     * Set the 'mixed' on the complex type ancestor.
12024     */
12025     if (xmlGetBooleanProp(ctxt, node, "mixed", 0))  {
12026         if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
12027             type->flags |= XML_SCHEMAS_TYPE_MIXED;
12028     }
12029     child = node->children;
12030     if (IS_SCHEMA(child, "annotation")) {
12031         /*
12032         * Add the annotation to the complex type ancestor.
12033         */
12034         xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12035             xmlSchemaParseAnnotation(ctxt, child, 1));
12036         child = child->next;
12037     }
12038     if (child == NULL) {
12039         xmlSchemaPContentErr(ctxt,
12040             XML_SCHEMAP_S4S_ELEM_MISSING,
12041             NULL, node, NULL,
12042             NULL, "(annotation?, (restriction | extension))");
12043     }
12044     if (child == NULL) {
12045         xmlSchemaPContentErr(ctxt,
12046             XML_SCHEMAP_S4S_ELEM_MISSING,
12047             NULL, node, NULL,
12048             NULL, "(annotation?, (restriction | extension))");
12049     }
12050     if (IS_SCHEMA(child, "restriction")) {
12051         xmlSchemaParseRestriction(ctxt, schema, child,
12052             XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12053         (*hasRestrictionOrExtension) = 1;
12054         child = child->next;
12055     } else if (IS_SCHEMA(child, "extension")) {
12056         xmlSchemaParseExtension(ctxt, schema, child,
12057             XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12058         (*hasRestrictionOrExtension) = 1;
12059         child = child->next;
12060     }
12061     if (child != NULL) {
12062         xmlSchemaPContentErr(ctxt,
12063             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12064             NULL, node, child,
12065             NULL, "(annotation?, (restriction | extension))");
12066     }
12067     return (0);
12068 }
12069
12070 /**
12071  * xmlSchemaParseComplexType:
12072  * @ctxt:  a schema validation context
12073  * @schema:  the schema being built
12074  * @node:  a subtree containing XML Schema informations
12075  *
12076  * parse a XML schema Complex Type definition
12077  * *WARNING* this interface is highly subject to change
12078  *
12079  * Returns the type definition or NULL in case of error
12080  */
12081 static xmlSchemaTypePtr
12082 xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
12083                           xmlNodePtr node, int topLevel)
12084 {
12085     xmlSchemaTypePtr type, ctxtType;
12086     xmlNodePtr child = NULL;
12087     const xmlChar *name = NULL;
12088     xmlAttrPtr attr;
12089     const xmlChar *attrValue;
12090 #ifdef ENABLE_NAMED_LOCALS
12091     char buf[40];
12092 #endif
12093     int final = 0, block = 0, hasRestrictionOrExtension = 0;
12094
12095
12096     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12097         return (NULL);
12098
12099     ctxtType = ctxt->ctxtType;
12100
12101     if (topLevel) {
12102         attr = xmlSchemaGetPropNode(node, "name");
12103         if (attr == NULL) {
12104             xmlSchemaPMissingAttrErr(ctxt,
12105                 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
12106             return (NULL);
12107         } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
12108             xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12109             return (NULL);
12110         }
12111     }
12112
12113     if (topLevel == 0) {
12114         /*
12115         * Parse as local complex type definition.
12116         */
12117 #ifdef ENABLE_NAMED_LOCALS
12118         snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
12119         type = xmlSchemaAddType(ctxt, schema,
12120             XML_SCHEMA_TYPE_COMPLEX,
12121             xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
12122             ctxt->targetNamespace, node, 0);
12123 #else
12124         type = xmlSchemaAddType(ctxt, schema,
12125             XML_SCHEMA_TYPE_COMPLEX,
12126             NULL, ctxt->targetNamespace, node, 0);
12127 #endif
12128         if (type == NULL)
12129             return (NULL);
12130         name = type->name;
12131         type->node = node;
12132         type->type = XML_SCHEMA_TYPE_COMPLEX;
12133         /*
12134         * TODO: We need the target namespace.
12135         */
12136     } else {
12137         /*
12138         * Parse as global complex type definition.
12139         */
12140         type = xmlSchemaAddType(ctxt, schema,
12141             XML_SCHEMA_TYPE_COMPLEX,
12142             name, ctxt->targetNamespace, node, 1);
12143         if (type == NULL)
12144             return (NULL);
12145         type->node = node;
12146         type->type = XML_SCHEMA_TYPE_COMPLEX;
12147         type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
12148     }
12149     type->targetNamespace = ctxt->targetNamespace;
12150     /*
12151     * Handle attributes.
12152     */
12153     attr = node->properties;
12154     while (attr != NULL) {
12155         if (attr->ns == NULL) {
12156             if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12157                 /*
12158                 * Attribute "id".
12159                 */
12160                 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12161             } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12162                 /*
12163                 * Attribute "mixed".
12164                 */
12165                 if (xmlSchemaPGetBoolNodeValue(ctxt,
12166                         NULL, (xmlNodePtr) attr))
12167                     type->flags |= XML_SCHEMAS_TYPE_MIXED;
12168             } else if (topLevel) {
12169                 /*
12170                 * Attributes of global complex type definitions.
12171                 */
12172                 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12173                     /* Pass. */
12174                 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12175                     /*
12176                     * Attribute "abstract".
12177                     */
12178                     if (xmlSchemaPGetBoolNodeValue(ctxt,
12179                             NULL, (xmlNodePtr) attr))
12180                         type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12181                 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12182                     /*
12183                     * Attribute "final".
12184                     */
12185                     attrValue = xmlSchemaGetNodeContent(ctxt,
12186                         (xmlNodePtr) attr);
12187                     if (xmlSchemaPValAttrBlockFinal(attrValue,
12188                         &(type->flags),
12189                         -1,
12190                         XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12191                         XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12192                         -1, -1, -1) != 0)
12193                     {
12194                         xmlSchemaPSimpleTypeErr(ctxt,
12195                             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12196                             NULL, (xmlNodePtr) attr, NULL,
12197                             "(#all | List of (extension | restriction))",
12198                             attrValue, NULL, NULL, NULL);
12199                     } else
12200                         final = 1;
12201                 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12202                     /*
12203                     * Attribute "block".
12204                     */
12205                     attrValue = xmlSchemaGetNodeContent(ctxt,
12206                         (xmlNodePtr) attr);
12207                     if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
12208                         -1,
12209                         XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
12210                         XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
12211                         -1, -1, -1) != 0) {
12212                         xmlSchemaPSimpleTypeErr(ctxt,
12213                             XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12214                             NULL, (xmlNodePtr) attr, NULL,
12215                             "(#all | List of (extension | restriction)) ",
12216                             attrValue, NULL, NULL, NULL);
12217                     } else
12218                         block = 1;
12219                 } else {
12220                         xmlSchemaPIllegalAttrErr(ctxt,
12221                             XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12222                 }
12223             } else {
12224                 xmlSchemaPIllegalAttrErr(ctxt,
12225                     XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12226             }
12227         } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12228             xmlSchemaPIllegalAttrErr(ctxt,
12229                 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12230         }
12231         attr = attr->next;
12232     }
12233     if (! block) {
12234         /*
12235         * Apply default "block" values.
12236         */
12237         if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12238             type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12239         if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12240             type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12241     }
12242     if (! final) {
12243         /*
12244         * Apply default "block" values.
12245         */
12246         if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12247             type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12248         if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12249             type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12250     }
12251     /*
12252     * And now for the children...
12253     */
12254     child = node->children;
12255     if (IS_SCHEMA(child, "annotation")) {
12256         type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
12257         child = child->next;
12258     }
12259     ctxt->ctxtType = type;
12260     if (IS_SCHEMA(child, "simpleContent")) {
12261         /*
12262         * <complexType><simpleContent>...
12263         * 3.4.3 : 2.2
12264         * Specifying mixed='true' when the <simpleContent>
12265         * alternative is chosen has no effect
12266         */
12267         if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12268             type->flags ^= XML_SCHEMAS_TYPE_MIXED;
12269         xmlSchemaParseSimpleContent(ctxt, schema, child,
12270             &hasRestrictionOrExtension);
12271         child = child->next;
12272     } else if (IS_SCHEMA(child, "complexContent")) {
12273         /*
12274         * <complexType><complexContent>...
12275         */
12276         type->contentType = XML_SCHEMA_CONTENT_EMPTY;
12277         xmlSchemaParseComplexContent(ctxt, schema, child,
12278             &hasRestrictionOrExtension);
12279         child = child->next;
12280     } else {
12281         /*
12282         * E.g <complexType><sequence>... or <complexType><attribute>... etc.
12283         *
12284         * SPEC
12285         * "...the third alternative (neither <simpleContent> nor
12286         * <complexContent>) is chosen. This case is understood as shorthand
12287         * for complex content restricting the ï¿½ur-type definition�, and the
12288         * details of the mappings should be modified as necessary.
12289         */
12290         type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12291         type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
12292         /*
12293         * Parse model groups.
12294         */
12295         if (IS_SCHEMA(child, "all")) {
12296             type->subtypes = (xmlSchemaTypePtr)
12297                 xmlSchemaParseModelGroup(ctxt, schema, child,
12298                     XML_SCHEMA_TYPE_ALL, 1);
12299             child = child->next;
12300         } else if (IS_SCHEMA(child, "choice")) {
12301             type->subtypes = (xmlSchemaTypePtr)
12302                 xmlSchemaParseModelGroup(ctxt, schema, child,
12303                     XML_SCHEMA_TYPE_CHOICE, 1);
12304             child = child->next;
12305         } else if (IS_SCHEMA(child, "sequence")) {
12306             type->subtypes = (xmlSchemaTypePtr)
12307                 xmlSchemaParseModelGroup(ctxt, schema, child,
12308                     XML_SCHEMA_TYPE_SEQUENCE, 1);
12309             child = child->next;
12310         } else if (IS_SCHEMA(child, "group")) {
12311             type->subtypes = (xmlSchemaTypePtr)
12312                 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
12313             /*
12314             * Note that the reference will be resolved in
12315             * xmlSchemaResolveTypeReferences();
12316             */
12317             child = child->next;
12318         }
12319         /*
12320         * Parse attribute decls/refs.
12321         */
12322         if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12323             (xmlSchemaItemListPtr *) &(type->attrUses),
12324             XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12325             return(NULL);
12326         /*
12327         * Parse attribute wildcard.
12328         */
12329         if (IS_SCHEMA(child, "anyAttribute")) {
12330             type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12331             child = child->next;
12332         }
12333     }
12334     if (child != NULL) {
12335         xmlSchemaPContentErr(ctxt,
12336             XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12337             NULL, node, child,
12338             NULL, "(annotation?, (simpleContent | complexContent | "
12339             "((group | all | choice | sequence)?, ((attribute | "
12340             "attributeGroup)*, anyAttribute?))))");
12341     }
12342     /*
12343     * REDEFINE: SPEC src-redefine (5)
12344     */
12345     if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12346         xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
12347             NULL, node, "This is a redefinition, thus the "
12348             "<complexType> must have a <restriction> or <extension> "
12349             "grand-child", NULL);
12350     }
12351     ctxt->ctxtType = ctxtType;
12352     return (type);
12353 }
12354
12355 /************************************************************************
12356  *                                                                      *
12357  *                      Validating using Schemas                        *
12358  *                                                                      *
12359  ************************************************************************/
12360
12361 /************************************************************************
12362  *                                                                      *
12363  *                      Reading/Writing Schemas                         *
12364  *                                                                      *
12365  ************************************************************************/
12366
12367 #if 0 /* Will be enabled if it is clear what options are needed. */
12368 /**
12369  * xmlSchemaParserCtxtSetOptions:
12370  * @ctxt:       a schema parser context
12371  * @options: a combination of xmlSchemaParserOption
12372  *
12373  * Sets the options to be used during the parse.
12374  *
12375  * Returns 0 in case of success, -1 in case of an
12376  * API error.
12377  */
12378 static int
12379 xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12380                               int options)
12381
12382 {
12383     int i;
12384
12385     if (ctxt == NULL)
12386         return (-1);
12387     /*
12388     * WARNING: Change the start value if adding to the
12389     * xmlSchemaParseOption.
12390     */
12391     for (i = 1; i < (int) sizeof(int) * 8; i++) {
12392         if (options & 1<<i) {
12393             return (-1);
12394         }
12395     }
12396     ctxt->options = options;
12397     return (0);
12398 }
12399
12400 /**
12401  * xmlSchemaValidCtxtGetOptions:
12402  * @ctxt: a schema parser context
12403  *
12404  * Returns the option combination of the parser context.
12405  */
12406 static int
12407 xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
12408
12409 {
12410     if (ctxt == NULL)
12411         return (-1);
12412     else
12413         return (ctxt->options);
12414 }
12415 #endif
12416
12417 /**
12418  * xmlSchemaNewParserCtxt:
12419  * @URL:  the location of the schema
12420  *
12421  * Create an XML Schemas parse context for that file/resource expected
12422  * to contain an XML Schemas file.
12423  *
12424  * Returns the parser context or NULL in case of error
12425  */
12426 xmlSchemaParserCtxtPtr
12427 xmlSchemaNewParserCtxt(const char *URL)
12428 {
12429     xmlSchemaParserCtxtPtr ret;
12430
12431     if (URL == NULL)
12432         return (NULL);
12433
12434     ret = xmlSchemaParserCtxtCreate();
12435     if (ret == NULL)
12436         return(NULL);
12437     ret->dict = xmlDictCreate();
12438     ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
12439     return (ret);
12440 }
12441
12442 /**
12443  * xmlSchemaNewMemParserCtxt:
12444  * @buffer:  a pointer to a char array containing the schemas
12445  * @size:  the size of the array
12446  *
12447  * Create an XML Schemas parse context for that memory buffer expected
12448  * to contain an XML Schemas file.
12449  *
12450  * Returns the parser context or NULL in case of error
12451  */
12452 xmlSchemaParserCtxtPtr
12453 xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12454 {
12455     xmlSchemaParserCtxtPtr ret;
12456
12457     if ((buffer == NULL) || (size <= 0))
12458         return (NULL);
12459     ret = xmlSchemaParserCtxtCreate();
12460     if (ret == NULL)
12461         return(NULL);
12462     ret->buffer = buffer;
12463     ret->size = size;
12464     ret->dict = xmlDictCreate();
12465     return (ret);
12466 }
12467
12468 /**
12469  * xmlSchemaNewDocParserCtxt:
12470  * @doc:  a preparsed document tree
12471  *
12472  * Create an XML Schemas parse context for that document.
12473  * NB. The document may be modified during the parsing process.
12474  *
12475  * Returns the parser context or NULL in case of error
12476  */
12477 xmlSchemaParserCtxtPtr
12478 xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12479 {
12480     xmlSchemaParserCtxtPtr ret;
12481
12482     if (doc == NULL)
12483       return (NULL);
12484     ret = xmlSchemaParserCtxtCreate();
12485     if (ret == NULL)
12486         return(NULL);
12487     ret->doc = doc;
12488     ret->dict = xmlDictCreate();
12489     /* The application has responsibility for the document */
12490     ret->preserve = 1;
12491
12492     return (ret);
12493 }
12494
12495 /**
12496  * xmlSchemaFreeParserCtxt:
12497  * @ctxt:  the schema parser context
12498  *
12499  * Free the resources associated to the schema parser context
12500  */
12501 void
12502 xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12503 {
12504     if (ctxt == NULL)
12505         return;
12506     if (ctxt->doc != NULL && !ctxt->preserve)
12507         xmlFreeDoc(ctxt->doc);
12508     if (ctxt->vctxt != NULL) {
12509         xmlSchemaFreeValidCtxt(ctxt->vctxt);
12510     }
12511     if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12512         xmlSchemaConstructionCtxtFree(ctxt->constructor);
12513         ctxt->constructor = NULL;
12514         ctxt->ownsConstructor = 0;
12515     }
12516     if (ctxt->attrProhibs != NULL)
12517         xmlSchemaItemListFree(ctxt->attrProhibs);
12518     xmlDictFree(ctxt->dict);
12519     xmlFree(ctxt);
12520 }
12521
12522 /************************************************************************
12523  *                                                                      *
12524  *                      Building the content models                     *
12525  *                                                                      *
12526  ************************************************************************/
12527
12528 /**
12529  * xmlSchemaBuildContentModelForSubstGroup:
12530  *
12531  * Returns 1 if nillable, 0 otherwise
12532  */
12533 static int
12534 xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
12535         xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
12536 {
12537     xmlAutomataStatePtr start, tmp;
12538     xmlSchemaElementPtr elemDecl, member;
12539     xmlSchemaSubstGroupPtr substGroup;
12540     int i;
12541     int ret = 0;
12542
12543     elemDecl = (xmlSchemaElementPtr) particle->children;
12544     /*
12545     * Wrap the substitution group with a CHOICE.
12546     */
12547     start = pctxt->state;
12548     if (end == NULL)
12549         end = xmlAutomataNewState(pctxt->am);
12550     substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
12551     if (substGroup == NULL) {
12552         xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
12553             XML_SCHEMAP_INTERNAL,
12554             "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12555             "declaration is marked having a subst. group but none "
12556             "available.\n", elemDecl->name, NULL);
12557         return(0);
12558     }
12559     if (counter >= 0) {
12560         /*
12561         * NOTE that we put the declaration in, even if it's abstract.
12562         * However, an error will be raised during *validation* if an element
12563         * information item shall be validated against an abstract element
12564         * declaration.
12565         */
12566         tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12567         xmlAutomataNewTransition2(pctxt->am, tmp, end,
12568                     elemDecl->name, elemDecl->targetNamespace, elemDecl);
12569         /*
12570         * Add subst. group members.
12571         */
12572         for (i = 0; i < substGroup->members->nbItems; i++) {
12573             member = (xmlSchemaElementPtr) substGroup->members->items[i];
12574             xmlAutomataNewTransition2(pctxt->am, tmp, end,
12575                                member->name, member->targetNamespace, member);
12576         }
12577     } else if (particle->maxOccurs == 1) {
12578         /*
12579         * NOTE that we put the declaration in, even if it's abstract,
12580         */
12581         xmlAutomataNewEpsilon(pctxt->am,
12582             xmlAutomataNewTransition2(pctxt->am,
12583             start, NULL,
12584             elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12585         /*
12586         * Add subst. group members.
12587         */
12588         for (i = 0; i < substGroup->members->nbItems; i++) {
12589             member = (xmlSchemaElementPtr) substGroup->members->items[i];
12590             /*
12591             * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2()
12592             *  was incorrectly used instead of xmlAutomataNewTransition2()
12593             *  (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL
12594             *  section in xmlSchemaBuildAContentModel() ).
12595             * TODO: Check if xmlAutomataNewOnceTrans2() was instead
12596             *  intended for the above "counter" section originally. I.e.,
12597             *  check xs:all with subst-groups.
12598             *
12599             * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12600             *                  member->name, member->targetNamespace,
12601             *                  1, 1, member);
12602             */
12603             tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL,
12604                 member->name, member->targetNamespace, member);
12605             xmlAutomataNewEpsilon(pctxt->am, tmp, end);
12606         }
12607     } else {
12608         xmlAutomataStatePtr hop;
12609         int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12610             UNBOUNDED : particle->maxOccurs - 1;
12611         int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12612
12613         counter =
12614             xmlAutomataNewCounter(pctxt->am, minOccurs,
12615             maxOccurs);
12616         hop = xmlAutomataNewState(pctxt->am);
12617
12618         xmlAutomataNewEpsilon(pctxt->am,
12619             xmlAutomataNewTransition2(pctxt->am,
12620             start, NULL,
12621             elemDecl->name, elemDecl->targetNamespace, elemDecl),
12622             hop);
12623         /*
12624          * Add subst. group members.
12625          */
12626         for (i = 0; i < substGroup->members->nbItems; i++) {
12627             member = (xmlSchemaElementPtr) substGroup->members->items[i];
12628             xmlAutomataNewEpsilon(pctxt->am,
12629                 xmlAutomataNewTransition2(pctxt->am,
12630                 start, NULL,
12631                 member->name, member->targetNamespace, member),
12632                 hop);
12633         }
12634         xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12635         xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12636     }
12637     if (particle->minOccurs == 0) {
12638         xmlAutomataNewEpsilon(pctxt->am, start, end);
12639         ret = 1;
12640     }
12641     pctxt->state = end;
12642     return(ret);
12643 }
12644
12645 /**
12646  * xmlSchemaBuildContentModelForElement:
12647  *
12648  * Returns 1 if nillable, 0 otherwise
12649  */
12650 static int
12651 xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12652                                      xmlSchemaParticlePtr particle)
12653 {
12654     int ret = 0;
12655
12656     if (((xmlSchemaElementPtr) particle->children)->flags &
12657         XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12658         /*
12659         * Substitution groups.
12660         */
12661         ret = xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
12662     } else {
12663         xmlSchemaElementPtr elemDecl;
12664         xmlAutomataStatePtr start;
12665
12666         elemDecl = (xmlSchemaElementPtr) particle->children;
12667
12668         if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
12669             return(0);
12670         if (particle->maxOccurs == 1) {
12671             start = ctxt->state;
12672             ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12673                     elemDecl->name, elemDecl->targetNamespace, elemDecl);
12674         } else if ((particle->maxOccurs >= UNBOUNDED) &&
12675                    (particle->minOccurs < 2)) {
12676             /* Special case. */
12677             start = ctxt->state;
12678             ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12679                 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12680             ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
12681                 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12682         } else {
12683             int counter;
12684             int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12685                             UNBOUNDED : particle->maxOccurs - 1;
12686             int minOccurs = particle->minOccurs < 1 ?
12687                             0 : particle->minOccurs - 1;
12688
12689             start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
12690             counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12691             ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12692                 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12693             xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12694             ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12695                 NULL, counter);
12696         }
12697         if (particle->minOccurs == 0) {
12698             xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12699             ret = 1;
12700         }
12701     }
12702     return(ret);
12703 }
12704
12705 /**
12706  * xmlSchemaBuildAContentModel:
12707  * @ctxt:  the schema parser context
12708  * @particle:  the particle component
12709  * @name:  the complex type's name whose content is being built
12710  *
12711  * Create the automaton for the {content type} of a complex type.
12712  *
12713  * Returns 1 if the content is nillable, 0 otherwise
12714  */
12715 static int
12716 xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
12717                             xmlSchemaParticlePtr particle)
12718 {
12719     int ret = 0, tmp2;
12720
12721     if (particle == NULL) {
12722         PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
12723         return(1);
12724     }
12725     if (particle->children == NULL) {
12726         /*
12727         * Just return in this case. A missing "term" of the particle
12728         * might arise due to an invalid "term" component.
12729         */
12730         return(1);
12731     }
12732
12733     switch (particle->children->type) {
12734         case XML_SCHEMA_TYPE_ANY: {
12735             xmlAutomataStatePtr start, end;
12736             xmlSchemaWildcardPtr wild;
12737             xmlSchemaWildcardNsPtr ns;
12738
12739             wild = (xmlSchemaWildcardPtr) particle->children;
12740
12741             start = pctxt->state;
12742             end = xmlAutomataNewState(pctxt->am);
12743
12744             if (particle->maxOccurs == 1) {
12745                 if (wild->any == 1) {
12746                     /*
12747                     * We need to add both transitions:
12748                     *
12749                     * 1. the {"*", "*"} for elements in a namespace.
12750                     */
12751                     pctxt->state =
12752                         xmlAutomataNewTransition2(pctxt->am,
12753                         start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12754                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12755                     /*
12756                     * 2. the {"*"} for elements in no namespace.
12757                     */
12758                     pctxt->state =
12759                         xmlAutomataNewTransition2(pctxt->am,
12760                         start, NULL, BAD_CAST "*", NULL, wild);
12761                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12762
12763                 } else if (wild->nsSet != NULL) {
12764                     ns = wild->nsSet;
12765                     do {
12766                         pctxt->state = start;
12767                         pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12768                             pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12769                         xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12770                         ns = ns->next;
12771                     } while (ns != NULL);
12772
12773                 } else if (wild->negNsSet != NULL) {
12774                     pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12775                         start, end, BAD_CAST "*", wild->negNsSet->value,
12776                         wild);
12777                 }
12778             } else {
12779                 int counter;
12780                 xmlAutomataStatePtr hop;
12781                 int maxOccurs =
12782                     particle->maxOccurs == UNBOUNDED ? UNBOUNDED :
12783                                            particle->maxOccurs - 1;
12784                 int minOccurs =
12785                     particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12786
12787                 counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12788                 hop = xmlAutomataNewState(pctxt->am);
12789                 if (wild->any == 1) {
12790                     pctxt->state =
12791                         xmlAutomataNewTransition2(pctxt->am,
12792                         start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12793                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12794                     pctxt->state =
12795                         xmlAutomataNewTransition2(pctxt->am,
12796                         start, NULL, BAD_CAST "*", NULL, wild);
12797                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12798                 } else if (wild->nsSet != NULL) {
12799                     ns = wild->nsSet;
12800                     do {
12801                         pctxt->state =
12802                             xmlAutomataNewTransition2(pctxt->am,
12803                                 start, NULL, BAD_CAST "*", ns->value, wild);
12804                         xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12805                         ns = ns->next;
12806                     } while (ns != NULL);
12807
12808                 } else if (wild->negNsSet != NULL) {
12809                     pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12810                         start, hop, BAD_CAST "*", wild->negNsSet->value,
12811                         wild);
12812                 }
12813                 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12814                 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12815             }
12816             if (particle->minOccurs == 0) {
12817                 xmlAutomataNewEpsilon(pctxt->am, start, end);
12818                 ret = 1;
12819             }
12820             pctxt->state = end;
12821             break;
12822         }
12823         case XML_SCHEMA_TYPE_ELEMENT:
12824             ret = xmlSchemaBuildContentModelForElement(pctxt, particle);
12825             break;
12826         case XML_SCHEMA_TYPE_SEQUENCE:{
12827             xmlSchemaTreeItemPtr sub;
12828
12829             ret = 1;
12830             /*
12831              * If max and min occurances are default (1) then
12832              * simply iterate over the particles of the <sequence>.
12833              */
12834             if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12835                 sub = particle->children->children;
12836
12837                 while (sub != NULL) {
12838                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
12839                                         (xmlSchemaParticlePtr) sub);
12840                     if (tmp2 != 1) ret = 0;
12841                     sub = sub->next;
12842                 }
12843             } else {
12844                 xmlAutomataStatePtr oldstate = pctxt->state;
12845
12846                 if (particle->maxOccurs >= UNBOUNDED) {
12847                     if (particle->minOccurs > 1) {
12848                         xmlAutomataStatePtr tmp;
12849                         int counter;
12850
12851                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12852                             oldstate, NULL);
12853                         oldstate = pctxt->state;
12854
12855                         counter = xmlAutomataNewCounter(pctxt->am,
12856                             particle->minOccurs - 1, UNBOUNDED);
12857
12858                         sub = particle->children->children;
12859                         while (sub != NULL) {
12860                             tmp2 = xmlSchemaBuildAContentModel(pctxt,
12861                                             (xmlSchemaParticlePtr) sub);
12862                             if (tmp2 != 1) ret = 0;
12863                             sub = sub->next;
12864                         }
12865                         tmp = pctxt->state;
12866                         xmlAutomataNewCountedTrans(pctxt->am, tmp,
12867                                                    oldstate, counter);
12868                         pctxt->state =
12869                             xmlAutomataNewCounterTrans(pctxt->am, tmp,
12870                                                        NULL, counter);
12871                         if (ret == 1)
12872                             xmlAutomataNewEpsilon(pctxt->am,
12873                                                 oldstate, pctxt->state);
12874
12875                     } else {
12876                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12877                             oldstate, NULL);
12878                         oldstate = pctxt->state;
12879
12880                         sub = particle->children->children;
12881                         while (sub != NULL) {
12882                             tmp2 = xmlSchemaBuildAContentModel(pctxt,
12883                                         (xmlSchemaParticlePtr) sub);
12884                             if (tmp2 != 1) ret = 0;
12885                             sub = sub->next;
12886                         }
12887                         xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
12888                                               oldstate);
12889                         /*
12890                          * epsilon needed to block previous trans from
12891                          * being allowed to enter back from another
12892                          * construct
12893                          */
12894                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12895                                             pctxt->state, NULL);
12896                         if (particle->minOccurs == 0) {
12897                             xmlAutomataNewEpsilon(pctxt->am,
12898                                 oldstate, pctxt->state);
12899                             ret = 1;
12900                         }
12901                     }
12902                 } else if ((particle->maxOccurs > 1)
12903                            || (particle->minOccurs > 1)) {
12904                     xmlAutomataStatePtr tmp;
12905                     int counter;
12906
12907                     pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12908                         oldstate, NULL);
12909                     oldstate = pctxt->state;
12910
12911                     counter = xmlAutomataNewCounter(pctxt->am,
12912                         particle->minOccurs - 1,
12913                         particle->maxOccurs - 1);
12914
12915                     sub = particle->children->children;
12916                     while (sub != NULL) {
12917                         tmp2 = xmlSchemaBuildAContentModel(pctxt,
12918                                         (xmlSchemaParticlePtr) sub);
12919                         if (tmp2 != 1) ret = 0;
12920                         sub = sub->next;
12921                     }
12922                     tmp = pctxt->state;
12923                     xmlAutomataNewCountedTrans(pctxt->am,
12924                         tmp, oldstate, counter);
12925                     pctxt->state =
12926                         xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
12927                                                    counter);
12928                     if ((particle->minOccurs == 0) || (ret == 1)) {
12929                         xmlAutomataNewEpsilon(pctxt->am,
12930                                             oldstate, pctxt->state);
12931                         ret = 1;
12932                     }
12933                 } else {
12934                     sub = particle->children->children;
12935                     while (sub != NULL) {
12936                         tmp2 = xmlSchemaBuildAContentModel(pctxt,
12937                                         (xmlSchemaParticlePtr) sub);
12938                         if (tmp2 != 1) ret = 0;
12939                         sub = sub->next;
12940                     }
12941                     if (particle->minOccurs == 0) {
12942                         xmlAutomataNewEpsilon(pctxt->am, oldstate,
12943                                               pctxt->state);
12944                         ret = 1;
12945                     }
12946                 }
12947             }
12948             break;
12949         }
12950         case XML_SCHEMA_TYPE_CHOICE:{
12951             xmlSchemaTreeItemPtr sub;
12952             xmlAutomataStatePtr start, end;
12953
12954             ret = 0;
12955             start = pctxt->state;
12956             end = xmlAutomataNewState(pctxt->am);
12957
12958             /*
12959              * iterate over the subtypes and remerge the end with an
12960              * epsilon transition
12961              */
12962             if (particle->maxOccurs == 1) {
12963                 sub = particle->children->children;
12964                 while (sub != NULL) {
12965                     pctxt->state = start;
12966                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
12967                                         (xmlSchemaParticlePtr) sub);
12968                     if (tmp2 == 1) ret = 1;
12969                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12970                     sub = sub->next;
12971                 }
12972             } else {
12973                 int counter;
12974                 xmlAutomataStatePtr hop, base;
12975                 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12976                     UNBOUNDED : particle->maxOccurs - 1;
12977                 int minOccurs =
12978                     particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12979
12980                 /*
12981                  * use a counter to keep track of the number of transtions
12982                  * which went through the choice.
12983                  */
12984                 counter =
12985                     xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12986                 hop = xmlAutomataNewState(pctxt->am);
12987                 base = xmlAutomataNewState(pctxt->am);
12988
12989                 sub = particle->children->children;
12990                 while (sub != NULL) {
12991                     pctxt->state = base;
12992                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
12993                                         (xmlSchemaParticlePtr) sub);
12994                     if (tmp2 == 1) ret = 1;
12995                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12996                     sub = sub->next;
12997                 }
12998                 xmlAutomataNewEpsilon(pctxt->am, start, base);
12999                 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
13000                 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
13001                 if (ret == 1)
13002                     xmlAutomataNewEpsilon(pctxt->am, base, end);
13003             }
13004             if (particle->minOccurs == 0) {
13005                 xmlAutomataNewEpsilon(pctxt->am, start, end);
13006                 ret = 1;
13007             }
13008             pctxt->state = end;
13009             break;
13010         }
13011         case XML_SCHEMA_TYPE_ALL:{
13012             xmlAutomataStatePtr start, tmp;
13013             xmlSchemaParticlePtr sub;
13014             xmlSchemaElementPtr elemDecl;
13015
13016             ret = 1;
13017
13018             sub = (xmlSchemaParticlePtr) particle->children->children;
13019             if (sub == NULL)
13020                 break;
13021
13022             ret = 0;
13023
13024             start = pctxt->state;
13025             tmp = xmlAutomataNewState(pctxt->am);
13026             xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp);
13027             pctxt->state = tmp;
13028             while (sub != NULL) {
13029                 pctxt->state = tmp;
13030
13031                 elemDecl = (xmlSchemaElementPtr) sub->children;
13032                 if (elemDecl == NULL) {
13033                     PERROR_INT("xmlSchemaBuildAContentModel",
13034                         "<element> particle has no term");
13035                     return(ret);
13036                 };
13037                 /*
13038                 * NOTE: The {max occurs} of all the particles in the
13039                 * {particles} of the group must be 0 or 1; this is
13040                 * already ensured during the parse of the content of
13041                 * <all>.
13042                 */
13043                 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
13044                     int counter;
13045
13046                     /*
13047                      * This is an abstract group, we need to share
13048                      * the same counter for all the element transitions
13049                      * derived from the group
13050                      */
13051                     counter = xmlAutomataNewCounter(pctxt->am,
13052                                        sub->minOccurs, sub->maxOccurs);
13053                     xmlSchemaBuildContentModelForSubstGroup(pctxt,
13054                                        sub, counter, pctxt->state);
13055                 } else {
13056                     if ((sub->minOccurs == 1) &&
13057                         (sub->maxOccurs == 1)) {
13058                         xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
13059                                                 pctxt->state,
13060                                                 elemDecl->name,
13061                                                 elemDecl->targetNamespace,
13062                                                 1, 1, elemDecl);
13063                     } else if ((sub->minOccurs == 0) &&
13064                         (sub->maxOccurs == 1)) {
13065
13066                         xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
13067                                                  pctxt->state,
13068                                                  elemDecl->name,
13069                                                  elemDecl->targetNamespace,
13070                                                  0,
13071                                                  1,
13072                                                  elemDecl);
13073                     }
13074                 }
13075                 sub = (xmlSchemaParticlePtr) sub->next;
13076             }
13077             pctxt->state =
13078                 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0);
13079             if (particle->minOccurs == 0) {
13080                 xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state);
13081                 ret = 1;
13082             }
13083             break;
13084         }
13085         case XML_SCHEMA_TYPE_GROUP:
13086             /*
13087             * If we hit a model group definition, then this means that
13088             * it was empty, thus was not substituted for the containing
13089             * model group. Just do nothing in this case.
13090             * TODO: But the group should be substituted and not occur at
13091             * all in the content model at this point. Fix this.
13092             */
13093             ret = 1;
13094             break;
13095         default:
13096             xmlSchemaInternalErr2(ACTXT_CAST pctxt,
13097                 "xmlSchemaBuildAContentModel",
13098                 "found unexpected term of type '%s' in content model",
13099                 WXS_ITEM_TYPE_NAME(particle->children), NULL);
13100             return(ret);
13101     }
13102     return(ret);
13103 }
13104
13105 /**
13106  * xmlSchemaBuildContentModel:
13107  * @ctxt:  the schema parser context
13108  * @type:  the complex type definition
13109  * @name:  the element name
13110  *
13111  * Builds the content model of the complex type.
13112  */
13113 static void
13114 xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
13115                            xmlSchemaParserCtxtPtr ctxt)
13116 {
13117     if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13118         (type->contModel != NULL) ||
13119         ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13120         (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
13121         return;
13122
13123 #ifdef DEBUG_CONTENT
13124     xmlGenericError(xmlGenericErrorContext,
13125                     "Building content model for %s\n", name);
13126 #endif
13127     ctxt->am = NULL;
13128     ctxt->am = xmlNewAutomata();
13129     if (ctxt->am == NULL) {
13130         xmlGenericError(xmlGenericErrorContext,
13131             "Cannot create automata for complex type %s\n", type->name);
13132         return;
13133     }
13134     ctxt->state = xmlAutomataGetInitState(ctxt->am);
13135     /*
13136     * Build the automaton.
13137     */
13138     xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
13139     xmlAutomataSetFinalState(ctxt->am, ctxt->state);
13140     type->contModel = xmlAutomataCompile(ctxt->am);
13141     if (type->contModel == NULL) {
13142         xmlSchemaPCustomErr(ctxt,
13143             XML_SCHEMAP_INTERNAL,
13144             WXS_BASIC_CAST type, type->node,
13145             "Failed to compile the content model", NULL);
13146     } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
13147         xmlSchemaPCustomErr(ctxt,
13148             XML_SCHEMAP_NOT_DETERMINISTIC,
13149             /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
13150             WXS_BASIC_CAST type, type->node,
13151             "The content model is not determinist", NULL);
13152     } else {
13153 #ifdef DEBUG_CONTENT_REGEXP
13154         xmlGenericError(xmlGenericErrorContext,
13155                         "Content model of %s:\n", type->name);
13156         xmlRegexpPrint(stderr, type->contModel);
13157 #endif
13158     }
13159     ctxt->state = NULL;
13160     xmlFreeAutomata(ctxt->am);
13161     ctxt->am = NULL;
13162 }
13163
13164 /**
13165  * xmlSchemaResolveElementReferences:
13166  * @elem:  the schema element context
13167  * @ctxt:  the schema parser context
13168  *
13169  * Resolves the references of an element declaration
13170  * or particle, which has an element declaration as it's
13171  * term.
13172  */
13173 static void
13174 xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13175                                   xmlSchemaParserCtxtPtr ctxt)
13176 {
13177     if ((ctxt == NULL) || (elemDecl == NULL) ||
13178         ((elemDecl != NULL) &&
13179         (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
13180         return;
13181     elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
13182
13183     if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
13184         xmlSchemaTypePtr type;
13185
13186         /* (type definition) ... otherwise the type definition ï¿½resolved�
13187         * to by the ï¿½actual value� of the type [attribute] ...
13188         */
13189         type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
13190             elemDecl->namedTypeNs);
13191         if (type == NULL) {
13192             xmlSchemaPResCompAttrErr(ctxt,
13193                 XML_SCHEMAP_SRC_RESOLVE,
13194                 WXS_BASIC_CAST elemDecl, elemDecl->node,
13195                 "type", elemDecl->namedType, elemDecl->namedTypeNs,
13196                 XML_SCHEMA_TYPE_BASIC, "type definition");
13197         } else
13198             elemDecl->subtypes = type;
13199     }
13200     if (elemDecl->substGroup != NULL) {
13201         xmlSchemaElementPtr substHead;
13202
13203         /*
13204         * FIXME TODO: Do we need a new field in _xmlSchemaElement for
13205         * substitutionGroup?
13206         */
13207         substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13208             elemDecl->substGroupNs);
13209         if (substHead == NULL) {
13210             xmlSchemaPResCompAttrErr(ctxt,
13211                 XML_SCHEMAP_SRC_RESOLVE,
13212                 WXS_BASIC_CAST elemDecl, NULL,
13213                 "substitutionGroup", elemDecl->substGroup,
13214                 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
13215         } else {
13216             xmlSchemaResolveElementReferences(substHead, ctxt);
13217             /*
13218             * Set the "substitution group affiliation".
13219             * NOTE that now we use the "refDecl" field for this.
13220             */
13221             WXS_SUBST_HEAD(elemDecl) = substHead;
13222             /*
13223             * The type definitions is set to:
13224             * SPEC "...the {type definition} of the element
13225             * declaration ï¿½resolved� to by the ï¿½actual value�
13226             * of the substitutionGroup [attribute], if present"
13227             */
13228             if (elemDecl->subtypes == NULL)
13229                 elemDecl->subtypes = substHead->subtypes;
13230         }
13231     }
13232     /*
13233     * SPEC "The definition of anyType serves as the default type definition
13234     * for element declarations whose XML representation does not specify one."
13235     */
13236     if ((elemDecl->subtypes == NULL) &&
13237         (elemDecl->namedType == NULL) &&
13238         (elemDecl->substGroup == NULL))
13239         elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13240 }
13241
13242 /**
13243  * xmlSchemaResolveUnionMemberTypes:
13244  * @ctxt:  the schema parser context
13245  * @type:  the schema simple type definition
13246  *
13247  * Checks and builds the "member type definitions" property of the union
13248  * simple type. This handles part (1), part (2) is done in
13249  * xmlSchemaFinishMemberTypeDefinitionsProperty()
13250  *
13251  * Returns -1 in case of an internal error, 0 otherwise.
13252  */
13253 static int
13254 xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13255                                  xmlSchemaTypePtr type)
13256 {
13257
13258     xmlSchemaTypeLinkPtr link, lastLink, newLink;
13259     xmlSchemaTypePtr memberType;
13260
13261     /*
13262     * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13263     * define the explicit members as the type definitions ï¿½resolved�
13264     * to by the items in the ï¿½actual value� of the memberTypes [attribute],
13265     * if any, followed by the type definitions corresponding to the
13266     * <simpleType>s among the [children] of <union>, if any."
13267     */
13268     /*
13269     * Resolve references.
13270     */
13271     link = type->memberTypes;
13272     lastLink = NULL;
13273     while (link != NULL) {
13274         const xmlChar *name, *nsName;
13275
13276         name = ((xmlSchemaQNameRefPtr) link->type)->name;
13277         nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13278
13279         memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
13280         if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
13281             xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
13282                 WXS_BASIC_CAST type, type->node, "memberTypes",
13283                 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13284             /*
13285             * Remove the member type link.
13286             */
13287             if (lastLink == NULL)
13288                 type->memberTypes = link->next;
13289             else
13290                 lastLink->next = link->next;
13291             newLink = link;
13292             link = link->next;
13293             xmlFree(newLink);
13294         } else {
13295             link->type = memberType;
13296             lastLink = link;
13297             link = link->next;
13298         }
13299     }
13300     /*
13301     * Add local simple types,
13302     */
13303     memberType = type->subtypes;
13304     while (memberType != NULL) {
13305         link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13306         if (link == NULL) {
13307             xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13308             return (-1);
13309         }
13310         link->type = memberType;
13311         link->next = NULL;
13312         if (lastLink == NULL)
13313             type->memberTypes = link;
13314         else
13315             lastLink->next = link;
13316         lastLink = link;
13317         memberType = memberType->next;
13318     }
13319     return (0);
13320 }
13321
13322 /**
13323  * xmlSchemaIsDerivedFromBuiltInType:
13324  * @ctxt:  the schema parser context
13325  * @type:  the type definition
13326  * @valType: the value type
13327  *
13328  *
13329  * Returns 1 if the type has the given value type, or
13330  * is derived from such a type.
13331  */
13332 static int
13333 xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13334 {
13335     if (type == NULL)
13336         return (0);
13337     if (WXS_IS_COMPLEX(type))
13338         return (0);
13339     if (type->type == XML_SCHEMA_TYPE_BASIC) {
13340         if (type->builtInType == valType)
13341             return(1);
13342         if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13343             (type->builtInType == XML_SCHEMAS_ANYTYPE))
13344             return (0);
13345         return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13346     }
13347     return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13348 }
13349
13350 #if 0
13351 /**
13352  * xmlSchemaIsDerivedFromBuiltInType:
13353  * @ctxt:  the schema parser context
13354  * @type:  the type definition
13355  * @valType: the value type
13356  *
13357  *
13358  * Returns 1 if the type has the given value type, or
13359  * is derived from such a type.
13360  */
13361 static int
13362 xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13363 {
13364     if (type == NULL)
13365         return (0);
13366     if (WXS_IS_COMPLEX(type))
13367         return (0);
13368     if (type->type == XML_SCHEMA_TYPE_BASIC) {
13369         if (type->builtInType == valType)
13370             return(1);
13371         return (0);
13372     } else
13373         return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13374
13375     return (0);
13376 }
13377
13378 static xmlSchemaTypePtr
13379 xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13380 {
13381     if (type == NULL)
13382         return (NULL);
13383     if (WXS_IS_COMPLEX(type))
13384         return (NULL);
13385     if (type->type == XML_SCHEMA_TYPE_BASIC)
13386         return(type);
13387     return(xmlSchemaQueryBuiltInType(type->subtypes));
13388 }
13389 #endif
13390
13391 /**
13392  * xmlSchemaGetPrimitiveType:
13393  * @type:  the simpleType definition
13394  *
13395  * Returns the primitive type of the given type or
13396  * NULL in case of error.
13397  */
13398 static xmlSchemaTypePtr
13399 xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13400 {
13401
13402     while (type != NULL) {
13403         /*
13404         * Note that anySimpleType is actually not a primitive type
13405         * but we need that here.
13406         */
13407         if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13408            (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
13409             return (type);
13410         type = type->baseType;
13411     }
13412
13413     return (NULL);
13414 }
13415
13416 #if 0
13417 /**
13418  * xmlSchemaGetBuiltInTypeAncestor:
13419  * @type:  the simpleType definition
13420  *
13421  * Returns the primitive type of the given type or
13422  * NULL in case of error.
13423  */
13424 static xmlSchemaTypePtr
13425 xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13426 {
13427     if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
13428         return (0);
13429     while (type != NULL) {
13430         if (type->type == XML_SCHEMA_TYPE_BASIC)
13431             return (type);
13432         type = type->baseType;
13433     }
13434
13435     return (NULL);
13436 }
13437 #endif
13438
13439 /**
13440  * xmlSchemaCloneWildcardNsConstraints:
13441  * @ctxt:  the schema parser context
13442  * @dest:  the destination wildcard
13443  * @source: the source wildcard
13444  *
13445  * Clones the namespace constraints of source
13446  * and assignes them to dest.
13447  * Returns -1 on internal error, 0 otherwise.
13448  */
13449 static int
13450 xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
13451                                     xmlSchemaWildcardPtr dest,
13452                                     xmlSchemaWildcardPtr source)
13453 {
13454     xmlSchemaWildcardNsPtr cur, tmp, last;
13455
13456     if ((source == NULL) || (dest == NULL))
13457         return(-1);
13458     dest->any = source->any;
13459     cur = source->nsSet;
13460     last = NULL;
13461     while (cur != NULL) {
13462         tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13463         if (tmp == NULL)
13464             return(-1);
13465         tmp->value = cur->value;
13466         if (last == NULL)
13467             dest->nsSet = tmp;
13468         else
13469             last->next = tmp;
13470         last = tmp;
13471         cur = cur->next;
13472     }
13473     if (dest->negNsSet != NULL)
13474         xmlSchemaFreeWildcardNsSet(dest->negNsSet);
13475     if (source->negNsSet != NULL) {
13476         dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13477         if (dest->negNsSet == NULL)
13478             return(-1);
13479         dest->negNsSet->value = source->negNsSet->value;
13480     } else
13481         dest->negNsSet = NULL;
13482     return(0);
13483 }
13484
13485 /**
13486  * xmlSchemaUnionWildcards:
13487  * @ctxt:  the schema parser context
13488  * @completeWild:  the first wildcard
13489  * @curWild: the second wildcard
13490  *
13491  * Unions the namespace constraints of the given wildcards.
13492  * @completeWild will hold the resulting union.
13493  * Returns a positive error code on failure, -1 in case of an
13494  * internal error, 0 otherwise.
13495  */
13496 static int
13497 xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
13498                             xmlSchemaWildcardPtr completeWild,
13499                             xmlSchemaWildcardPtr curWild)
13500 {
13501     xmlSchemaWildcardNsPtr cur, curB, tmp;
13502
13503     /*
13504     * 1 If O1 and O2 are the same value, then that value must be the
13505     * value.
13506     */
13507     if ((completeWild->any == curWild->any) &&
13508         ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13509         ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13510
13511         if ((completeWild->negNsSet == NULL) ||
13512             (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13513
13514             if (completeWild->nsSet != NULL) {
13515                 int found = 0;
13516
13517                 /*
13518                 * Check equality of sets.
13519                 */
13520                 cur = completeWild->nsSet;
13521                 while (cur != NULL) {
13522                     found = 0;
13523                     curB = curWild->nsSet;
13524                     while (curB != NULL) {
13525                         if (cur->value == curB->value) {
13526                             found = 1;
13527                             break;
13528                         }
13529                         curB = curB->next;
13530                     }
13531                     if (!found)
13532                         break;
13533                     cur = cur->next;
13534                 }
13535                 if (found)
13536                     return(0);
13537             } else
13538                 return(0);
13539         }
13540     }
13541     /*
13542     * 2 If either O1 or O2 is any, then any must be the value
13543     */
13544     if (completeWild->any != curWild->any) {
13545         if (completeWild->any == 0) {
13546             completeWild->any = 1;
13547             if (completeWild->nsSet != NULL) {
13548                 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13549                 completeWild->nsSet = NULL;
13550             }
13551             if (completeWild->negNsSet != NULL) {
13552                 xmlFree(completeWild->negNsSet);
13553                 completeWild->negNsSet = NULL;
13554             }
13555         }
13556         return (0);
13557     }
13558     /*
13559     * 3 If both O1 and O2 are sets of (namespace names or ï¿½absent�),
13560     * then the union of those sets must be the value.
13561     */
13562     if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13563         int found;
13564         xmlSchemaWildcardNsPtr start;
13565
13566         cur = curWild->nsSet;
13567         start = completeWild->nsSet;
13568         while (cur != NULL) {
13569             found = 0;
13570             curB = start;
13571             while (curB != NULL) {
13572                 if (cur->value == curB->value) {
13573                     found = 1;
13574                     break;
13575                 }
13576                 curB = curB->next;
13577             }
13578             if (!found) {
13579                 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13580                 if (tmp == NULL)
13581                     return (-1);
13582                 tmp->value = cur->value;
13583                 tmp->next = completeWild->nsSet;
13584                 completeWild->nsSet = tmp;
13585             }
13586             cur = cur->next;
13587         }
13588
13589         return(0);
13590     }
13591     /*
13592     * 4 If the two are negations of different values (namespace names
13593     * or ï¿½absent�), then a pair of not and ï¿½absent� must be the value.
13594     */
13595     if ((completeWild->negNsSet != NULL) &&
13596         (curWild->negNsSet != NULL) &&
13597         (completeWild->negNsSet->value != curWild->negNsSet->value)) {
13598         completeWild->negNsSet->value = NULL;
13599
13600         return(0);
13601     }
13602     /*
13603      * 5.
13604      */
13605     if (((completeWild->negNsSet != NULL) &&
13606         (completeWild->negNsSet->value != NULL) &&
13607         (curWild->nsSet != NULL)) ||
13608         ((curWild->negNsSet != NULL) &&
13609         (curWild->negNsSet->value != NULL) &&
13610         (completeWild->nsSet != NULL))) {
13611
13612         int nsFound, absentFound = 0;
13613
13614         if (completeWild->nsSet != NULL) {
13615             cur = completeWild->nsSet;
13616             curB = curWild->negNsSet;
13617         } else {
13618             cur = curWild->nsSet;
13619             curB = completeWild->negNsSet;
13620         }
13621         nsFound = 0;
13622         while (cur != NULL) {
13623             if (cur->value == NULL)
13624                 absentFound = 1;
13625             else if (cur->value == curB->value)
13626                 nsFound = 1;
13627             if (nsFound && absentFound)
13628                 break;
13629             cur = cur->next;
13630         }
13631
13632         if (nsFound && absentFound) {
13633             /*
13634             * 5.1 If the set S includes both the negated namespace
13635             * name and ï¿½absent�, then any must be the value.
13636             */
13637             completeWild->any = 1;
13638             if (completeWild->nsSet != NULL) {
13639                 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13640                 completeWild->nsSet = NULL;
13641             }
13642             if (completeWild->negNsSet != NULL) {
13643                 xmlFree(completeWild->negNsSet);
13644                 completeWild->negNsSet = NULL;
13645             }
13646         } else if (nsFound && (!absentFound)) {
13647             /*
13648             * 5.2 If the set S includes the negated namespace name
13649             * but not ï¿½absent�, then a pair of not and ï¿½absent� must
13650             * be the value.
13651             */
13652             if (completeWild->nsSet != NULL) {
13653                 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13654                 completeWild->nsSet = NULL;
13655             }
13656             if (completeWild->negNsSet == NULL) {
13657                 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13658                 if (completeWild->negNsSet == NULL)
13659                     return (-1);
13660             }
13661             completeWild->negNsSet->value = NULL;
13662         } else if ((!nsFound) && absentFound) {
13663             /*
13664             * 5.3 If the set S includes ï¿½absent� but not the negated
13665             * namespace name, then the union is not expressible.
13666             */
13667             xmlSchemaPErr(ctxt, completeWild->node,
13668                 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
13669                 "The union of the wilcard is not expressible.\n",
13670                 NULL, NULL);
13671             return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
13672         } else if ((!nsFound) && (!absentFound)) {
13673             /*
13674             * 5.4 If the set S does not include either the negated namespace
13675             * name or ï¿½absent�, then whichever of O1 or O2 is a pair of not
13676             * and a namespace name must be the value.
13677             */
13678             if (completeWild->negNsSet == NULL) {
13679                 if (completeWild->nsSet != NULL) {
13680                     xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13681                     completeWild->nsSet = NULL;
13682                 }
13683                 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13684                 if (completeWild->negNsSet == NULL)
13685                     return (-1);
13686                 completeWild->negNsSet->value = curWild->negNsSet->value;
13687             }
13688         }
13689         return (0);
13690     }
13691     /*
13692      * 6.
13693      */
13694     if (((completeWild->negNsSet != NULL) &&
13695         (completeWild->negNsSet->value == NULL) &&
13696         (curWild->nsSet != NULL)) ||
13697         ((curWild->negNsSet != NULL) &&
13698         (curWild->negNsSet->value == NULL) &&
13699         (completeWild->nsSet != NULL))) {
13700
13701         if (completeWild->nsSet != NULL) {
13702             cur = completeWild->nsSet;
13703         } else {
13704             cur = curWild->nsSet;
13705         }
13706         while (cur != NULL) {
13707             if (cur->value == NULL) {
13708                 /*
13709                 * 6.1 If the set S includes ï¿½absent�, then any must be the
13710                 * value.
13711                 */
13712                 completeWild->any = 1;
13713                 if (completeWild->nsSet != NULL) {
13714                     xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13715                     completeWild->nsSet = NULL;
13716                 }
13717                 if (completeWild->negNsSet != NULL) {
13718                     xmlFree(completeWild->negNsSet);
13719                     completeWild->negNsSet = NULL;
13720                 }
13721                 return (0);
13722             }
13723             cur = cur->next;
13724         }
13725         if (completeWild->negNsSet == NULL) {
13726             /*
13727             * 6.2 If the set S does not include ï¿½absent�, then a pair of not
13728             * and ï¿½absent� must be the value.
13729             */
13730             if (completeWild->nsSet != NULL) {
13731                 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13732                 completeWild->nsSet = NULL;
13733             }
13734             completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13735             if (completeWild->negNsSet == NULL)
13736                 return (-1);
13737             completeWild->negNsSet->value = NULL;
13738         }
13739         return (0);
13740     }
13741     return (0);
13742
13743 }
13744
13745 /**
13746  * xmlSchemaIntersectWildcards:
13747  * @ctxt:  the schema parser context
13748  * @completeWild:  the first wildcard
13749  * @curWild: the second wildcard
13750  *
13751  * Intersects the namespace constraints of the given wildcards.
13752  * @completeWild will hold the resulting intersection.
13753  * Returns a positive error code on failure, -1 in case of an
13754  * internal error, 0 otherwise.
13755  */
13756 static int
13757 xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
13758                             xmlSchemaWildcardPtr completeWild,
13759                             xmlSchemaWildcardPtr curWild)
13760 {
13761     xmlSchemaWildcardNsPtr cur, curB, prev,  tmp;
13762
13763     /*
13764     * 1 If O1 and O2 are the same value, then that value must be the
13765     * value.
13766     */
13767     if ((completeWild->any == curWild->any) &&
13768         ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13769         ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13770
13771         if ((completeWild->negNsSet == NULL) ||
13772             (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13773
13774             if (completeWild->nsSet != NULL) {
13775                 int found = 0;
13776
13777                 /*
13778                 * Check equality of sets.
13779                 */
13780                 cur = completeWild->nsSet;
13781                 while (cur != NULL) {
13782                     found = 0;
13783                     curB = curWild->nsSet;
13784                     while (curB != NULL) {
13785                         if (cur->value == curB->value) {
13786                             found = 1;
13787                             break;
13788                         }
13789                         curB = curB->next;
13790                     }
13791                     if (!found)
13792                         break;
13793                     cur = cur->next;
13794                 }
13795                 if (found)
13796                     return(0);
13797             } else
13798                 return(0);
13799         }
13800     }
13801     /*
13802     * 2 If either O1 or O2 is any, then the other must be the value.
13803     */
13804     if ((completeWild->any != curWild->any) && (completeWild->any)) {
13805         if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13806             return(-1);
13807         return(0);
13808     }
13809     /*
13810     * 3 If either O1 or O2 is a pair of not and a value (a namespace
13811     * name or ï¿½absent�) and the other is a set of (namespace names or
13812     * ï¿½absent�), then that set, minus the negated value if it was in
13813     * the set, minus ï¿½absent� if it was in the set, must be the value.
13814     */
13815     if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13816         ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13817         const xmlChar *neg;
13818
13819         if (completeWild->nsSet == NULL) {
13820             neg = completeWild->negNsSet->value;
13821             if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13822                 return(-1);
13823         } else
13824             neg = curWild->negNsSet->value;
13825         /*
13826         * Remove absent and negated.
13827         */
13828         prev = NULL;
13829         cur = completeWild->nsSet;
13830         while (cur != NULL) {
13831             if (cur->value == NULL) {
13832                 if (prev == NULL)
13833                     completeWild->nsSet = cur->next;
13834                 else
13835                     prev->next = cur->next;
13836                 xmlFree(cur);
13837                 break;
13838             }
13839             prev = cur;
13840             cur = cur->next;
13841         }
13842         if (neg != NULL) {
13843             prev = NULL;
13844             cur = completeWild->nsSet;
13845             while (cur != NULL) {
13846                 if (cur->value == neg) {
13847                     if (prev == NULL)
13848                         completeWild->nsSet = cur->next;
13849                     else
13850                         prev->next = cur->next;
13851                     xmlFree(cur);
13852                     break;
13853                 }
13854                 prev = cur;
13855                 cur = cur->next;
13856             }
13857         }
13858
13859         return(0);
13860     }
13861     /*
13862     * 4 If both O1 and O2 are sets of (namespace names or ï¿½absent�),
13863     * then the intersection of those sets must be the value.
13864     */
13865     if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13866         int found;
13867
13868         cur = completeWild->nsSet;
13869         prev = NULL;
13870         while (cur != NULL) {
13871             found = 0;
13872             curB = curWild->nsSet;
13873             while (curB != NULL) {
13874                 if (cur->value == curB->value) {
13875                     found = 1;
13876                     break;
13877                 }
13878                 curB = curB->next;
13879             }
13880             if (!found) {
13881                 if (prev == NULL)
13882                     completeWild->nsSet = cur->next;
13883                 else
13884                     prev->next = cur->next;
13885                 tmp = cur->next;
13886                 xmlFree(cur);
13887                 cur = tmp;
13888                 continue;
13889             }
13890             prev = cur;
13891             cur = cur->next;
13892         }
13893
13894         return(0);
13895     }
13896     /* 5 If the two are negations of different namespace names,
13897     * then the intersection is not expressible
13898     */
13899     if ((completeWild->negNsSet != NULL) &&
13900         (curWild->negNsSet != NULL) &&
13901         (completeWild->negNsSet->value != curWild->negNsSet->value) &&
13902         (completeWild->negNsSet->value != NULL) &&
13903         (curWild->negNsSet->value != NULL)) {
13904
13905         xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
13906             "The intersection of the wilcard is not expressible.\n",
13907             NULL, NULL);
13908         return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
13909     }
13910     /*
13911     * 6 If the one is a negation of a namespace name and the other
13912     * is a negation of ï¿½absent�, then the one which is the negation
13913     * of a namespace name must be the value.
13914     */
13915     if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
13916         (completeWild->negNsSet->value != curWild->negNsSet->value) &&
13917         (completeWild->negNsSet->value == NULL)) {
13918         completeWild->negNsSet->value =  curWild->negNsSet->value;
13919     }
13920     return(0);
13921 }
13922
13923 /**
13924  * xmlSchemaIsWildcardNsConstraintSubset:
13925  * @ctxt:  the schema parser context
13926  * @sub:  the first wildcard
13927  * @super: the second wildcard
13928  *
13929  * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
13930  *
13931  * Returns 0 if the namespace constraint of @sub is an intensional
13932  * subset of @super, 1 otherwise.
13933  */
13934 static int
13935 xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
13936                           xmlSchemaWildcardPtr super)
13937 {
13938     /*
13939     * 1 super must be any.
13940     */
13941     if (super->any)
13942         return (0);
13943     /*
13944     * 2.1 sub must be a pair of not and a namespace name or ï¿½absent�.
13945     * 2.2 super must be a pair of not and the same value.
13946     */
13947     if ((sub->negNsSet != NULL) &&
13948         (super->negNsSet != NULL) &&
13949         (sub->negNsSet->value == super->negNsSet->value))
13950         return (0);
13951     /*
13952     * 3.1 sub must be a set whose members are either namespace names or ï¿½absent�.
13953     */
13954     if (sub->nsSet != NULL) {
13955         /*
13956         * 3.2.1 super must be the same set or a superset thereof.
13957         */
13958         if (super->nsSet != NULL) {
13959             xmlSchemaWildcardNsPtr cur, curB;
13960             int found = 0;
13961
13962             cur = sub->nsSet;
13963             while (cur != NULL) {
13964                 found = 0;
13965                 curB = super->nsSet;
13966                 while (curB != NULL) {
13967                     if (cur->value == curB->value) {
13968                         found = 1;
13969                         break;
13970                     }
13971                     curB = curB->next;
13972                 }
13973                 if (!found)
13974                     return (1);
13975                 cur = cur->next;
13976             }
13977             if (found)
13978                 return (0);
13979         } else if (super->negNsSet != NULL) {
13980             xmlSchemaWildcardNsPtr cur;
13981             /*
13982             * 3.2.2 super must be a pair of not and a namespace name or
13983             * ï¿½absent� and that value must not be in sub's set.
13984             */
13985             cur = sub->nsSet;
13986             while (cur != NULL) {
13987                 if (cur->value == super->negNsSet->value)
13988                     return (1);
13989                 cur = cur->next;
13990             }
13991             return (0);
13992         }
13993     }
13994     return (1);
13995 }
13996
13997 static int
13998 xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
13999                                      int *fixed,
14000                                      const xmlChar **value,
14001                                      xmlSchemaValPtr *val)
14002 {
14003     *fixed = 0;
14004     *value = NULL;
14005     if (val != 0)
14006         *val = NULL;
14007
14008     if (attruse->defValue != NULL) {
14009         *value = attruse->defValue;
14010         if (val != NULL)
14011             *val = attruse->defVal;
14012         if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
14013             *fixed = 1;
14014         return(1);
14015     } else if ((attruse->attrDecl != NULL) &&
14016         (attruse->attrDecl->defValue != NULL)) {
14017         *value = attruse->attrDecl->defValue;
14018         if (val != NULL)
14019             *val = attruse->attrDecl->defVal;
14020         if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
14021             *fixed = 1;
14022         return(1);
14023     }
14024     return(0);
14025 }
14026 /**
14027  * xmlSchemaCheckCVCWildcardNamespace:
14028  * @wild:  the wildcard
14029  * @ns:  the namespace
14030  *
14031  * Validation Rule: Wildcard allows Namespace Name
14032  * (cvc-wildcard-namespace)
14033  *
14034  * Returns 0 if the given namespace matches the wildcard,
14035  * 1 otherwise and -1 on API errors.
14036  */
14037 static int
14038 xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
14039                                    const xmlChar* ns)
14040 {
14041     if (wild == NULL)
14042         return(-1);
14043
14044     if (wild->any)
14045         return(0);
14046     else if (wild->nsSet != NULL) {
14047         xmlSchemaWildcardNsPtr cur;
14048
14049         cur = wild->nsSet;
14050         while (cur != NULL) {
14051             if (xmlStrEqual(cur->value, ns))
14052                 return(0);
14053             cur = cur->next;
14054         }
14055     } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
14056         (!xmlStrEqual(wild->negNsSet->value, ns)))
14057         return(0);
14058
14059     return(1);
14060 }
14061
14062 #define XML_SCHEMA_ACTION_DERIVE 0
14063 #define XML_SCHEMA_ACTION_REDEFINE 1
14064
14065 #define WXS_ACTION_STR(a) \
14066 ((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
14067
14068 /*
14069 * Schema Component Constraint:
14070 *   Derivation Valid (Restriction, Complex)
14071 *   derivation-ok-restriction (2) - (4)
14072 *
14073 * ATTENTION:
14074 * In XML Schema 1.1 this will be:
14075 * Validation Rule:
14076 *     Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
14077 *
14078 */
14079 static int
14080 xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
14081                                        int action,
14082                                        xmlSchemaBasicItemPtr item,
14083                                        xmlSchemaBasicItemPtr baseItem,
14084                                        xmlSchemaItemListPtr uses,
14085                                        xmlSchemaItemListPtr baseUses,
14086                                        xmlSchemaWildcardPtr wild,
14087                                        xmlSchemaWildcardPtr baseWild)
14088 {
14089     xmlSchemaAttributeUsePtr cur = NULL, bcur;
14090     int i, j, found; /* err = 0; */
14091     const xmlChar *bEffValue;
14092     int effFixed;
14093
14094     if (uses != NULL) {
14095         for (i = 0; i < uses->nbItems; i++) {
14096             cur = uses->items[i];
14097             found = 0;
14098             if (baseUses == NULL)
14099                 goto not_found;
14100             for (j = 0; j < baseUses->nbItems; j++) {
14101                 bcur = baseUses->items[j];
14102                 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14103                         WXS_ATTRUSE_DECL_NAME(bcur)) &&
14104                     (WXS_ATTRUSE_DECL_TNS(cur) ==
14105                         WXS_ATTRUSE_DECL_TNS(bcur)))
14106                 {
14107                     /*
14108                     * (2.1) "If there is an attribute use in the {attribute
14109                     * uses} of the {base type definition} (call this B) whose
14110                     * {attribute declaration} has the same {name} and {target
14111                     * namespace}, then  all of the following must be true:"
14112                     */
14113                     found = 1;
14114
14115                     if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14116                         (bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14117                     {
14118                         xmlChar *str = NULL;
14119                         /*
14120                         * (2.1.1) "one of the following must be true:"
14121                         * (2.1.1.1) "B's {required} is false."
14122                         * (2.1.1.2) "R's {required} is true."
14123                         */
14124                         xmlSchemaPAttrUseErr4(pctxt,
14125                             XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14126                             WXS_ITEM_NODE(item), item, cur,
14127                             "The 'optional' attribute use is inconsistent "
14128                             "with the corresponding 'required' attribute use of "
14129                             "the %s %s",
14130                             WXS_ACTION_STR(action),
14131                             xmlSchemaGetComponentDesignation(&str, baseItem),
14132                             NULL, NULL);
14133                         FREE_AND_NULL(str);
14134                         /* err = pctxt->err; */
14135                     } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
14136                         WXS_ATTRUSE_TYPEDEF(cur),
14137                         WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14138                     {
14139                         xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14140
14141                         /*
14142                         * SPEC (2.1.2) "R's {attribute declaration}'s
14143                         * {type definition} must be validly derived from
14144                         * B's {type definition} given the empty set as
14145                         * defined in Type Derivation OK (Simple) (�3.14.6)."
14146                         */
14147                         xmlSchemaPAttrUseErr4(pctxt,
14148                             XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14149                             WXS_ITEM_NODE(item), item, cur,
14150                             "The attribute declaration's %s "
14151                             "is not validly derived from "
14152                             "the corresponding %s of the "
14153                             "attribute declaration in the %s %s",
14154                             xmlSchemaGetComponentDesignation(&strA,
14155                                 WXS_ATTRUSE_TYPEDEF(cur)),
14156                             xmlSchemaGetComponentDesignation(&strB,
14157                                 WXS_ATTRUSE_TYPEDEF(bcur)),
14158                             WXS_ACTION_STR(action),
14159                             xmlSchemaGetComponentDesignation(&strC, baseItem));
14160                             /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14161                         FREE_AND_NULL(strA);
14162                         FREE_AND_NULL(strB);
14163                         FREE_AND_NULL(strC);
14164                         /* err = pctxt->err; */
14165                     } else {
14166                         /*
14167                         * 2.1.3 [Definition:]  Let the effective value
14168                         * constraint of an attribute use be its {value
14169                         * constraint}, if present, otherwise its {attribute
14170                         * declaration}'s {value constraint} .
14171                         */
14172                         xmlSchemaGetEffectiveValueConstraint(bcur,
14173                             &effFixed, &bEffValue, NULL);
14174                         /*
14175                         * 2.1.3 ... one of the following must be true
14176                         *
14177                         * 2.1.3.1 B's ï¿½effective value constraint� is
14178                         * ï¿½absent� or default.
14179                         */
14180                         if ((bEffValue != NULL) &&
14181                             (effFixed == 1)) {
14182                             const xmlChar *rEffValue = NULL;
14183
14184                             xmlSchemaGetEffectiveValueConstraint(bcur,
14185                                 &effFixed, &rEffValue, NULL);
14186                             /*
14187                             * 2.1.3.2 R's ï¿½effective value constraint� is
14188                             * fixed with the same string as B's.
14189                             * MAYBE TODO: Compare the computed values.
14190                             *       Hmm, it says "same string" so
14191                             *       string-equality might really be sufficient.
14192                             */
14193                             if ((effFixed == 0) ||
14194                                 (! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14195                             {
14196                                 xmlChar *str = NULL;
14197
14198                                 xmlSchemaPAttrUseErr4(pctxt,
14199                                     XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14200                                     WXS_ITEM_NODE(item), item, cur,
14201                                     "The effective value constraint of the "
14202                                     "attribute use is inconsistent with "
14203                                     "its correspondent in the %s %s",
14204                                     WXS_ACTION_STR(action),
14205                                     xmlSchemaGetComponentDesignation(&str,
14206                                         baseItem),
14207                                     NULL, NULL);
14208                                 FREE_AND_NULL(str);
14209                                 /* err = pctxt->err; */
14210                             }
14211                         }
14212                     }
14213                     break;
14214                 }
14215             }
14216 not_found:
14217             if (!found) {
14218                 /*
14219                 * (2.2) "otherwise the {base type definition} must have an
14220                 * {attribute wildcard} and the {target namespace} of the
14221                 * R's {attribute declaration} must be ï¿½valid� with respect
14222                 * to that wildcard, as defined in Wildcard allows Namespace
14223                 * Name (�3.10.4)."
14224                 */
14225                 if ((baseWild == NULL) ||
14226                     (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14227                     (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14228                 {
14229                     xmlChar *str = NULL;
14230
14231                     xmlSchemaPAttrUseErr4(pctxt,
14232                         XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14233                         WXS_ITEM_NODE(item), item, cur,
14234                         "Neither a matching attribute use, "
14235                         "nor a matching wildcard exists in the %s %s",
14236                         WXS_ACTION_STR(action),
14237                         xmlSchemaGetComponentDesignation(&str, baseItem),
14238                         NULL, NULL);
14239                     FREE_AND_NULL(str);
14240                     /* err = pctxt->err; */
14241                 }
14242             }
14243         }
14244     }
14245     /*
14246     * SPEC derivation-ok-restriction (3):
14247     * (3) "For each attribute use in the {attribute uses} of the {base type
14248     * definition} whose {required} is true, there must be an attribute
14249     * use with an {attribute declaration} with the same {name} and
14250     * {target namespace} as its {attribute declaration} in the {attribute
14251     * uses} of the complex type definition itself whose {required} is true.
14252     */
14253     if (baseUses != NULL) {
14254         for (j = 0; j < baseUses->nbItems; j++) {
14255             bcur = baseUses->items[j];
14256             if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14257                 continue;
14258             found = 0;
14259             if (uses != NULL) {
14260                 for (i = 0; i < uses->nbItems; i++) {
14261                     cur = uses->items[i];
14262                     if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14263                         WXS_ATTRUSE_DECL_NAME(bcur)) &&
14264                         (WXS_ATTRUSE_DECL_TNS(cur) ==
14265                         WXS_ATTRUSE_DECL_TNS(bcur))) {
14266                         found = 1;
14267                         break;
14268                     }
14269                 }
14270             }
14271             if (!found) {
14272                 xmlChar *strA = NULL, *strB = NULL;
14273
14274                 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14275                     XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14276                     NULL, item,
14277                     "A matching attribute use for the "
14278                     "'required' %s of the %s %s is missing",
14279                     xmlSchemaGetComponentDesignation(&strA, bcur),
14280                     WXS_ACTION_STR(action),
14281                     xmlSchemaGetComponentDesignation(&strB, baseItem),
14282                     NULL);
14283                 FREE_AND_NULL(strA);
14284                 FREE_AND_NULL(strB);
14285             }
14286         }
14287     }
14288     /*
14289     * derivation-ok-restriction (4)
14290     */
14291     if (wild != NULL) {
14292         /*
14293         * (4) "If there is an {attribute wildcard}, all of the
14294         * following must be true:"
14295         */
14296         if (baseWild == NULL) {
14297             xmlChar *str = NULL;
14298
14299             /*
14300             * (4.1) "The {base type definition} must also have one."
14301             */
14302             xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14303                 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14304                 NULL, item,
14305                 "The %s has an attribute wildcard, "
14306                 "but the %s %s '%s' does not have one",
14307                 WXS_ITEM_TYPE_NAME(item),
14308                 WXS_ACTION_STR(action),
14309                 WXS_ITEM_TYPE_NAME(baseItem),
14310                 xmlSchemaGetComponentQName(&str, baseItem));
14311             FREE_AND_NULL(str);
14312             return(pctxt->err);
14313         } else if ((baseWild->any == 0) &&
14314                 xmlSchemaCheckCOSNSSubset(wild, baseWild))
14315         {
14316             xmlChar *str = NULL;
14317             /*
14318             * (4.2) "The complex type definition's {attribute wildcard}'s
14319             * {namespace constraint} must be a subset of the {base type
14320             * definition}'s {attribute wildcard}'s {namespace constraint},
14321             * as defined by Wildcard Subset (�3.10.6)."
14322             */
14323             xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14324                 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14325                 NULL, item,
14326                 "The attribute wildcard is not a valid "
14327                 "subset of the wildcard in the %s %s '%s'",
14328                 WXS_ACTION_STR(action),
14329                 WXS_ITEM_TYPE_NAME(baseItem),
14330                 xmlSchemaGetComponentQName(&str, baseItem),
14331                 NULL);
14332             FREE_AND_NULL(str);
14333             return(pctxt->err);
14334         }
14335         /* 4.3 Unless the {base type definition} is the ï¿½ur-type
14336         * definition�, the complex type definition's {attribute
14337         * wildcard}'s {process contents} must be identical to or
14338         * stronger than the {base type definition}'s {attribute
14339         * wildcard}'s {process contents}, where strict is stronger
14340         * than lax is stronger than skip.
14341         */
14342         if ((! WXS_IS_ANYTYPE(baseItem)) &&
14343             (wild->processContents < baseWild->processContents)) {
14344             xmlChar *str = NULL;
14345             xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14346                 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14347                 NULL, baseItem,
14348                 "The {process contents} of the attribute wildcard is "
14349                 "weaker than the one in the %s %s '%s'",
14350                 WXS_ACTION_STR(action),
14351                 WXS_ITEM_TYPE_NAME(baseItem),
14352                 xmlSchemaGetComponentQName(&str, baseItem),
14353                 NULL);
14354             FREE_AND_NULL(str)
14355                 return(pctxt->err);
14356         }
14357     }
14358     return(0);
14359 }
14360
14361
14362 static int
14363 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14364                                   xmlSchemaBasicItemPtr item,
14365                                   xmlSchemaWildcardPtr *completeWild,
14366                                   xmlSchemaItemListPtr list,
14367                                   xmlSchemaItemListPtr prohibs);
14368 /**
14369  * xmlSchemaFixupTypeAttributeUses:
14370  * @ctxt:  the schema parser context
14371  * @type:  the complex type definition
14372  *
14373  *
14374  * Builds the wildcard and the attribute uses on the given complex type.
14375  * Returns -1 if an internal error occurs, 0 otherwise.
14376  *
14377  * ATTENTION TODO: Experimantally this uses pointer comparisons for
14378  * strings, so recheck this if we start to hardcode some schemata, since
14379  * they might not be in the same dict.
14380  * NOTE: It is allowed to "extend" the xs:anyType type.
14381  */
14382 static int
14383 xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
14384                                   xmlSchemaTypePtr type)
14385 {
14386     xmlSchemaTypePtr baseType = NULL;
14387     xmlSchemaAttributeUsePtr use;
14388     xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
14389
14390     if (type->baseType == NULL) {
14391         PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14392             "no base type");
14393         return (-1);
14394     }
14395     baseType = type->baseType;
14396     if (WXS_IS_TYPE_NOT_FIXED(baseType))
14397         if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
14398             return(-1);
14399
14400     uses = type->attrUses;
14401     baseUses = baseType->attrUses;
14402     /*
14403     * Expand attribute group references. And build the 'complete'
14404     * wildcard, i.e. intersect multiple wildcards.
14405     * Move attribute prohibitions into a separate list.
14406     */
14407     if (uses != NULL) {
14408         if (WXS_IS_RESTRICTION(type)) {
14409             /*
14410             * This one will transfer all attr. prohibitions
14411             * into pctxt->attrProhibs.
14412             */
14413             if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14414                 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14415                 pctxt->attrProhibs) == -1)
14416             {
14417                 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14418                 "failed to expand attributes");
14419             }
14420             if (pctxt->attrProhibs->nbItems != 0)
14421                 prohibs = pctxt->attrProhibs;
14422         } else {
14423             if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14424                 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14425                 NULL) == -1)
14426             {
14427                 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14428                 "failed to expand attributes");
14429             }
14430         }
14431     }
14432     /*
14433     * Inherit the attribute uses of the base type.
14434     */
14435     if (baseUses != NULL) {
14436         int i, j;
14437         xmlSchemaAttributeUseProhibPtr pro;
14438
14439         if (WXS_IS_RESTRICTION(type)) {
14440             int usesCount;
14441             xmlSchemaAttributeUsePtr tmp;
14442
14443             if (uses != NULL)
14444                 usesCount = uses->nbItems;
14445             else
14446                 usesCount = 0;
14447
14448             /* Restriction. */
14449             for (i = 0; i < baseUses->nbItems; i++) {
14450                 use = baseUses->items[i];
14451                 if (prohibs) {
14452                     /*
14453                     * Filter out prohibited uses.
14454                     */
14455                     for (j = 0; j < prohibs->nbItems; j++) {
14456                         pro = prohibs->items[j];
14457                         if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14458                             (WXS_ATTRUSE_DECL_TNS(use) ==
14459                                 pro->targetNamespace))
14460                         {
14461                             goto inherit_next;
14462                         }
14463                     }
14464                 }
14465                 if (usesCount) {
14466                     /*
14467                     * Filter out existing uses.
14468                     */
14469                     for (j = 0; j < usesCount; j++) {
14470                         tmp = uses->items[j];
14471                         if ((WXS_ATTRUSE_DECL_NAME(use) ==
14472                                 WXS_ATTRUSE_DECL_NAME(tmp)) &&
14473                             (WXS_ATTRUSE_DECL_TNS(use) ==
14474                                 WXS_ATTRUSE_DECL_TNS(tmp)))
14475                         {
14476                             goto inherit_next;
14477                         }
14478                     }
14479                 }
14480                 if (uses == NULL) {
14481                     type->attrUses = xmlSchemaItemListCreate();
14482                     if (type->attrUses == NULL)
14483                         goto exit_failure;
14484                     uses = type->attrUses;
14485                 }
14486                 xmlSchemaItemListAddSize(uses, 2, use);
14487 inherit_next: {}
14488             }
14489         } else {
14490             /* Extension. */
14491             for (i = 0; i < baseUses->nbItems; i++) {
14492                 use = baseUses->items[i];
14493                 if (uses == NULL) {
14494                     type->attrUses = xmlSchemaItemListCreate();
14495                     if (type->attrUses == NULL)
14496                         goto exit_failure;
14497                     uses = type->attrUses;
14498                 }
14499                 xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14500             }
14501         }
14502     }
14503     /*
14504     * Shrink attr. uses.
14505     */
14506     if (uses) {
14507         if (uses->nbItems == 0) {
14508             xmlSchemaItemListFree(uses);
14509             type->attrUses = NULL;
14510         }
14511         /*
14512         * TODO: We could shrink the size of the array
14513         * to fit the actual number of items.
14514         */
14515     }
14516     /*
14517     * Compute the complete wildcard.
14518     */
14519     if (WXS_IS_EXTENSION(type)) {
14520         if (baseType->attributeWildcard != NULL) {
14521             /*
14522             * (3.2.2.1) "If the ï¿½base wildcard� is non-�absent�, then
14523             * the appropriate case among the following:"
14524             */
14525             if (type->attributeWildcard != NULL) {
14526                 /*
14527                 * Union the complete wildcard with the base wildcard.
14528                 * SPEC {attribute wildcard}
14529                 * (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14530                 * and {annotation} are those of the ï¿½complete wildcard�,
14531                 * and whose {namespace constraint} is the intensional union
14532                 * of the {namespace constraint} of the ï¿½complete wildcard�
14533                 * and of the ï¿½base wildcard�, as defined in Attribute
14534                 * Wildcard Union (�3.10.6)."
14535                 */
14536                 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14537                     baseType->attributeWildcard) == -1)
14538                     goto exit_failure;
14539             } else {
14540                 /*
14541                 * (3.2.2.1.1) "If the ï¿½complete wildcard� is ï¿½absent�,
14542                 * then the ï¿½base wildcard�."
14543                 */
14544                 type->attributeWildcard = baseType->attributeWildcard;
14545             }
14546         } else {
14547             /*
14548             * (3.2.2.2) "otherwise (the ï¿½base wildcard� is ï¿½absent�) the
14549             * ï¿½complete wildcard"
14550             * NOOP
14551             */
14552         }
14553     } else {
14554         /*
14555         * SPEC {attribute wildcard}
14556         * (3.1) "If the <restriction> alternative is chosen, then the
14557         * ï¿½complete wildcard�;"
14558         * NOOP
14559         */
14560     }
14561
14562     return (0);
14563
14564 exit_failure:
14565     return(-1);
14566 }
14567
14568 /**
14569  * xmlSchemaTypeFinalContains:
14570  * @schema:  the schema
14571  * @type:  the type definition
14572  * @final: the final
14573  *
14574  * Evaluates if a type definition contains the given "final".
14575  * This does take "finalDefault" into account as well.
14576  *
14577  * Returns 1 if the type does containt the given "final",
14578  * 0 otherwise.
14579  */
14580 static int
14581 xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
14582 {
14583     if (type == NULL)
14584         return (0);
14585     if (type->flags & final)
14586         return (1);
14587     else
14588         return (0);
14589 }
14590
14591 /**
14592  * xmlSchemaGetUnionSimpleTypeMemberTypes:
14593  * @type:  the Union Simple Type
14594  *
14595  * Returns a list of member types of @type if existing,
14596  * returns NULL otherwise.
14597  */
14598 static xmlSchemaTypeLinkPtr
14599 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14600 {
14601     while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
14602         if (type->memberTypes != NULL)
14603             return (type->memberTypes);
14604         else
14605             type = type->baseType;
14606     }
14607     return (NULL);
14608 }
14609
14610 /**
14611  * xmlSchemaGetParticleTotalRangeMin:
14612  * @particle: the particle
14613  *
14614  * Schema Component Constraint: Effective Total Range
14615  * (all and sequence) + (choice)
14616  *
14617  * Returns the minimun Effective Total Range.
14618  */
14619 static int
14620 xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
14621 {
14622     if ((particle->children == NULL) ||
14623         (particle->minOccurs == 0))
14624         return (0);
14625     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14626         int min = -1, cur;
14627         xmlSchemaParticlePtr part =
14628             (xmlSchemaParticlePtr) particle->children->children;
14629
14630         if (part == NULL)
14631             return (0);
14632         while (part != NULL) {
14633             if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14634                 (part->children->type == XML_SCHEMA_TYPE_ANY))
14635                 cur = part->minOccurs;
14636             else
14637                 cur = xmlSchemaGetParticleTotalRangeMin(part);
14638             if (cur == 0)
14639                 return (0);
14640             if ((min > cur) || (min == -1))
14641                 min = cur;
14642             part = (xmlSchemaParticlePtr) part->next;
14643         }
14644         return (particle->minOccurs * min);
14645     } else {
14646         /* <all> and <sequence> */
14647         int sum = 0;
14648         xmlSchemaParticlePtr part =
14649             (xmlSchemaParticlePtr) particle->children->children;
14650
14651         if (part == NULL)
14652             return (0);
14653         do {
14654             if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14655                 (part->children->type == XML_SCHEMA_TYPE_ANY))
14656                 sum += part->minOccurs;
14657             else
14658                 sum += xmlSchemaGetParticleTotalRangeMin(part);
14659             part = (xmlSchemaParticlePtr) part->next;
14660         } while (part != NULL);
14661         return (particle->minOccurs * sum);
14662     }
14663 }
14664
14665 #if 0
14666 /**
14667  * xmlSchemaGetParticleTotalRangeMax:
14668  * @particle: the particle
14669  *
14670  * Schema Component Constraint: Effective Total Range
14671  * (all and sequence) + (choice)
14672  *
14673  * Returns the maximum Effective Total Range.
14674  */
14675 static int
14676 xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14677 {
14678     if ((particle->children == NULL) ||
14679         (particle->children->children == NULL))
14680         return (0);
14681     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14682         int max = -1, cur;
14683         xmlSchemaParticlePtr part =
14684             (xmlSchemaParticlePtr) particle->children->children;
14685
14686         for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14687             if (part->children == NULL)
14688                 continue;
14689             if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14690                 (part->children->type == XML_SCHEMA_TYPE_ANY))
14691                 cur = part->maxOccurs;
14692             else
14693                 cur = xmlSchemaGetParticleTotalRangeMax(part);
14694             if (cur == UNBOUNDED)
14695                 return (UNBOUNDED);
14696             if ((max < cur) || (max == -1))
14697                 max = cur;
14698         }
14699         /* TODO: Handle overflows? */
14700         return (particle->maxOccurs * max);
14701     } else {
14702         /* <all> and <sequence> */
14703         int sum = 0, cur;
14704         xmlSchemaParticlePtr part =
14705             (xmlSchemaParticlePtr) particle->children->children;
14706
14707         for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14708             if (part->children == NULL)
14709                 continue;
14710             if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14711                 (part->children->type == XML_SCHEMA_TYPE_ANY))
14712                 cur = part->maxOccurs;
14713             else
14714                 cur = xmlSchemaGetParticleTotalRangeMax(part);
14715             if (cur == UNBOUNDED)
14716                 return (UNBOUNDED);
14717             if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14718                 return (UNBOUNDED);
14719             sum += cur;
14720         }
14721         /* TODO: Handle overflows? */
14722         return (particle->maxOccurs * sum);
14723     }
14724 }
14725 #endif
14726
14727 /**
14728  * xmlSchemaIsParticleEmptiable:
14729  * @particle: the particle
14730  *
14731  * Schema Component Constraint: Particle Emptiable
14732  * Checks whether the given particle is emptiable.
14733  *
14734  * Returns 1 if emptiable, 0 otherwise.
14735  */
14736 static int
14737 xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14738 {
14739     /*
14740     * SPEC (1) "Its {min occurs} is 0."
14741     */
14742     if ((particle == NULL) || (particle->minOccurs == 0) ||
14743         (particle->children == NULL))
14744         return (1);
14745     /*
14746     * SPEC (2) "Its {term} is a group and the minimum part of the
14747     * effective total range of that group, [...] is 0."
14748     */
14749     if (WXS_IS_MODEL_GROUP(particle->children)) {
14750         if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
14751             return (1);
14752     }
14753     return (0);
14754 }
14755
14756 /**
14757  * xmlSchemaCheckCOSSTDerivedOK:
14758  * @actxt: a context
14759  * @type:  the derived simple type definition
14760  * @baseType:  the base type definition
14761  * @subset: the subset of ('restriction', ect.)
14762  *
14763  * Schema Component Constraint:
14764  * Type Derivation OK (Simple) (cos-st-derived-OK)
14765  *
14766  * Checks wheter @type can be validly
14767  * derived from @baseType.
14768  *
14769  * Returns 0 on success, an positive error code otherwise.
14770  */
14771 static int
14772 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
14773                              xmlSchemaTypePtr type,
14774                              xmlSchemaTypePtr baseType,
14775                              int subset)
14776 {
14777     /*
14778     * 1 They are the same type definition.
14779     * TODO: The identy check might have to be more complex than this.
14780     */
14781     if (type == baseType)
14782         return (0);
14783     /*
14784     * 2.1 restriction is not in the subset, or in the {final}
14785     * of its own {base type definition};
14786     *
14787     * NOTE that this will be used also via "xsi:type".
14788     *
14789     * TODO: Revise this, it looks strange. How can the "type"
14790     * not be fixed or *in* fixing?
14791     */
14792     if (WXS_IS_TYPE_NOT_FIXED(type))
14793         if (xmlSchemaTypeFixup(type, actxt) == -1)
14794             return(-1);
14795     if (WXS_IS_TYPE_NOT_FIXED(baseType))
14796         if (xmlSchemaTypeFixup(baseType, actxt) == -1)
14797             return(-1);
14798     if ((subset & SUBSET_RESTRICTION) ||
14799         (xmlSchemaTypeFinalContains(type->baseType,
14800             XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14801         return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
14802     }
14803     /* 2.2 */
14804     if (type->baseType == baseType) {
14805         /*
14806         * 2.2.1 D's ï¿½base type definition� is B.
14807         */
14808         return (0);
14809     }
14810     /*
14811     * 2.2.2 D's ï¿½base type definition� is not the ï¿½ur-type definition�
14812     * and is validly derived from B given the subset, as defined by this
14813     * constraint.
14814     */
14815     if ((! WXS_IS_ANYTYPE(type->baseType)) &&
14816         (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
14817             baseType, subset) == 0)) {
14818         return (0);
14819     }
14820     /*
14821     * 2.2.3 D's {variety} is list or union and B is the ï¿½simple ur-type
14822     * definition�.
14823     */
14824     if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14825         (WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
14826         return (0);
14827     }
14828     /*
14829     * 2.2.4 B's {variety} is union and D is validly derived from a type
14830     * definition in B's {member type definitions} given the subset, as
14831     * defined by this constraint.
14832     *
14833     * NOTE: This seems not to involve built-in types, since there is no
14834     * built-in Union Simple Type.
14835     */
14836     if (WXS_IS_UNION(baseType)) {
14837         xmlSchemaTypeLinkPtr cur;
14838
14839         cur = baseType->memberTypes;
14840         while (cur != NULL) {
14841             if (WXS_IS_TYPE_NOT_FIXED(cur->type))
14842                 if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
14843                     return(-1);
14844             if (xmlSchemaCheckCOSSTDerivedOK(actxt,
14845                     type, cur->type, subset) == 0)
14846             {
14847                 /*
14848                 * It just has to be validly derived from at least one
14849                 * member-type.
14850                 */
14851                 return (0);
14852             }
14853             cur = cur->next;
14854         }
14855     }
14856     return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14857 }
14858
14859 /**
14860  * xmlSchemaCheckTypeDefCircularInternal:
14861  * @pctxt:  the schema parser context
14862  * @ctxtType:  the type definition
14863  * @ancestor: an ancestor of @ctxtType
14864  *
14865  * Checks st-props-correct (2) + ct-props-correct (3).
14866  * Circular type definitions are not allowed.
14867  *
14868  * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
14869  * circular, 0 otherwise.
14870  */
14871 static int
14872 xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14873                            xmlSchemaTypePtr ctxtType,
14874                            xmlSchemaTypePtr ancestor)
14875 {
14876     int ret;
14877
14878     if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14879         return (0);
14880
14881     if (ctxtType == ancestor) {
14882         xmlSchemaPCustomErr(pctxt,
14883             XML_SCHEMAP_ST_PROPS_CORRECT_2,
14884             WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
14885             "The definition is circular", NULL);
14886         return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14887     }
14888     if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14889         /*
14890         * Avoid inifinite recursion on circular types not yet checked.
14891         */
14892         return (0);
14893     }
14894     ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14895     ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14896         ancestor->baseType);
14897     ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14898     return (ret);
14899 }
14900
14901 /**
14902  * xmlSchemaCheckTypeDefCircular:
14903  * @item:  the complex/simple type definition
14904  * @ctxt:  the parser context
14905  * @name:  the name
14906  *
14907  * Checks for circular type definitions.
14908  */
14909 static void
14910 xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
14911                               xmlSchemaParserCtxtPtr ctxt)
14912 {
14913     if ((item == NULL) ||
14914         (item->type == XML_SCHEMA_TYPE_BASIC) ||
14915         (item->baseType == NULL))
14916         return;
14917     xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
14918         item->baseType);
14919 }
14920
14921 /*
14922 * Simple Type Definition Representation OK (src-simple-type) 4
14923 *
14924 * "4 Circular union type definition is disallowed. That is, if the
14925 * <union> alternative is chosen, there must not be any entries in the
14926 * memberTypes [attribute] at any depth which resolve to the component
14927 * corresponding to the <simpleType>."
14928 *
14929 * Note that this should work on the *representation* of a component,
14930 * thus assumes any union types in the member types not being yet
14931 * substituted. At this stage we need the variety of the types
14932 * to be already computed.
14933 */
14934 static int
14935 xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
14936                                         xmlSchemaTypePtr ctxType,
14937                                         xmlSchemaTypeLinkPtr members)
14938 {
14939     xmlSchemaTypeLinkPtr member;
14940     xmlSchemaTypePtr memberType;
14941
14942     member = members;
14943     while (member != NULL) {
14944         memberType = member->type;
14945         while ((memberType != NULL) &&
14946             (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
14947             if (memberType == ctxType) {
14948                 xmlSchemaPCustomErr(pctxt,
14949                     XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
14950                     WXS_BASIC_CAST ctxType, NULL,
14951                     "The union type definition is circular", NULL);
14952                 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
14953             }
14954             if ((WXS_IS_UNION(memberType)) &&
14955                 ((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
14956             {
14957                 int res;
14958                 memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
14959                 res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
14960                     ctxType,
14961                     xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
14962                 memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
14963                 if (res != 0)
14964                     return(res);
14965             }
14966             memberType = memberType->baseType;
14967         }
14968         member = member->next;
14969     }
14970     return(0);
14971 }
14972
14973 static int
14974 xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
14975                                    xmlSchemaTypePtr type)
14976 {
14977     if (! WXS_IS_UNION(type))
14978         return(0);
14979     return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
14980         type->memberTypes));
14981 }
14982
14983 /**
14984  * xmlSchemaResolveTypeReferences:
14985  * @item:  the complex/simple type definition
14986  * @ctxt:  the parser context
14987  * @name:  the name
14988  *
14989  * Resolvese type definition references
14990  */
14991 static void
14992 xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
14993                          xmlSchemaParserCtxtPtr ctxt)
14994 {
14995     if (typeDef == NULL)
14996         return;
14997
14998     /*
14999     * Resolve the base type.
15000     */
15001     if (typeDef->baseType == NULL) {
15002         typeDef->baseType = xmlSchemaGetType(ctxt->schema,
15003             typeDef->base, typeDef->baseNs);
15004         if (typeDef->baseType == NULL) {
15005             xmlSchemaPResCompAttrErr(ctxt,
15006                 XML_SCHEMAP_SRC_RESOLVE,
15007                 WXS_BASIC_CAST typeDef, typeDef->node,
15008                 "base", typeDef->base, typeDef->baseNs,
15009                 XML_SCHEMA_TYPE_SIMPLE, NULL);
15010             return;
15011         }
15012     }
15013     if (WXS_IS_SIMPLE(typeDef)) {
15014         if (WXS_IS_UNION(typeDef)) {
15015             /*
15016             * Resolve the memberTypes.
15017             */
15018             xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
15019             return;
15020         } else if (WXS_IS_LIST(typeDef)) {
15021             /*
15022             * Resolve the itemType.
15023             */
15024             if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
15025
15026                 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
15027                     typeDef->base, typeDef->baseNs);
15028
15029                 if ((typeDef->subtypes == NULL) ||
15030                     (! WXS_IS_SIMPLE(typeDef->subtypes)))
15031                 {
15032                     typeDef->subtypes = NULL;
15033                     xmlSchemaPResCompAttrErr(ctxt,
15034                         XML_SCHEMAP_SRC_RESOLVE,
15035                         WXS_BASIC_CAST typeDef, typeDef->node,
15036                         "itemType", typeDef->base, typeDef->baseNs,
15037                         XML_SCHEMA_TYPE_SIMPLE, NULL);
15038                 }
15039             }
15040             return;
15041         }
15042     }
15043     /*
15044     * The ball of letters below means, that if we have a particle
15045     * which has a QName-helper component as its {term}, we want
15046     * to resolve it...
15047     */
15048     else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
15049         ((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
15050             XML_SCHEMA_TYPE_PARTICLE) &&
15051         (WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
15052         ((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
15053             XML_SCHEMA_EXTRA_QNAMEREF))
15054     {
15055         xmlSchemaQNameRefPtr ref =
15056             WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
15057         xmlSchemaModelGroupDefPtr groupDef;
15058
15059         /*
15060         * URGENT TODO: Test this.
15061         */
15062         WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
15063         /*
15064         * Resolve the MG definition reference.
15065         */
15066         groupDef =
15067             WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
15068                 ref->itemType, ref->name, ref->targetNamespace);
15069         if (groupDef == NULL) {
15070             xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
15071                 NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
15072                 "ref", ref->name, ref->targetNamespace, ref->itemType,
15073                 NULL);
15074             /* Remove the particle. */
15075             WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15076         } else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
15077             /* Remove the particle. */
15078             WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15079         else {
15080             /*
15081             * Assign the MG definition's {model group} to the
15082             * particle's {term}.
15083             */
15084             WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
15085
15086             if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
15087                 /*
15088                 * SPEC cos-all-limited (1.2)
15089                 * "1.2 the {term} property of a particle with
15090                 * {max occurs}=1 which is part of a pair which constitutes
15091                 * the {content type} of a complex type definition."
15092                 */
15093                 if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
15094                     xmlSchemaCustomErr(ACTXT_CAST ctxt,
15095                         /* TODO: error code */
15096                         XML_SCHEMAP_COS_ALL_LIMITED,
15097                         WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
15098                         "The particle's {max occurs} must be 1, since the "
15099                         "reference resolves to an 'all' model group",
15100                         NULL, NULL);
15101                 }
15102             }
15103         }
15104     }
15105 }
15106
15107
15108
15109 /**
15110  * xmlSchemaCheckSTPropsCorrect:
15111  * @ctxt:  the schema parser context
15112  * @type:  the simple type definition
15113  *
15114  * Checks st-props-correct.
15115  *
15116  * Returns 0 if the properties are correct,
15117  * if not, a positive error code and -1 on internal
15118  * errors.
15119  */
15120 static int
15121 xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
15122                              xmlSchemaTypePtr type)
15123 {
15124     xmlSchemaTypePtr baseType = type->baseType;
15125     xmlChar *str = NULL;
15126
15127     /* STATE: error funcs converted. */
15128     /*
15129     * Schema Component Constraint: Simple Type Definition Properties Correct
15130     *
15131     * NOTE: This is somehow redundant, since we actually built a simple type
15132     * to have all the needed information; this acts as an self test.
15133     */
15134     /* Base type: If the datatype has been ï¿½derived� by ï¿½restriction�
15135     * then the Simple Type Definition component from which it is ï¿½derived�,
15136     * otherwise the Simple Type Definition for anySimpleType (�4.1.6).
15137     */
15138     if (baseType == NULL) {
15139         /*
15140         * TODO: Think about: "modulo the impact of Missing
15141         * Sub-components (�5.3)."
15142         */
15143         xmlSchemaPCustomErr(ctxt,
15144             XML_SCHEMAP_ST_PROPS_CORRECT_1,
15145             WXS_BASIC_CAST type, NULL,
15146             "No base type existent", NULL);
15147         return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15148
15149     }
15150     if (! WXS_IS_SIMPLE(baseType)) {
15151         xmlSchemaPCustomErr(ctxt,
15152             XML_SCHEMAP_ST_PROPS_CORRECT_1,
15153             WXS_BASIC_CAST type, NULL,
15154             "The base type '%s' is not a simple type",
15155             xmlSchemaGetComponentQName(&str, baseType));
15156         FREE_AND_NULL(str)
15157         return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15158     }
15159     if ( (WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
15160          (WXS_IS_RESTRICTION(type) == 0) &&
15161          (! WXS_IS_ANY_SIMPLE_TYPE(baseType))) {
15162         xmlSchemaPCustomErr(ctxt,
15163             XML_SCHEMAP_ST_PROPS_CORRECT_1,
15164             WXS_BASIC_CAST type, NULL,
15165             "A type, derived by list or union, must have "
15166             "the simple ur-type definition as base type, not '%s'",
15167             xmlSchemaGetComponentQName(&str, baseType));
15168         FREE_AND_NULL(str)
15169         return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15170     }
15171     /*
15172     * Variety: One of {atomic, list, union}.
15173     */
15174     if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15175         (! WXS_IS_LIST(type))) {
15176         xmlSchemaPCustomErr(ctxt,
15177             XML_SCHEMAP_ST_PROPS_CORRECT_1,
15178             WXS_BASIC_CAST type, NULL,
15179             "The variety is absent", NULL);
15180         return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15181     }
15182     /* TODO: Finish this. Hmm, is this finished? */
15183
15184     /*
15185     * 3 The {final} of the {base type definition} must not contain restriction.
15186     */
15187     if (xmlSchemaTypeFinalContains(baseType,
15188         XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15189         xmlSchemaPCustomErr(ctxt,
15190             XML_SCHEMAP_ST_PROPS_CORRECT_3,
15191             WXS_BASIC_CAST type, NULL,
15192             "The 'final' of its base type '%s' must not contain "
15193             "'restriction'",
15194             xmlSchemaGetComponentQName(&str, baseType));
15195         FREE_AND_NULL(str)
15196         return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
15197     }
15198
15199     /*
15200     * 2 All simple type definitions must be derived ultimately from the ï¿½simple
15201     * ur-type definition (so� circular definitions are disallowed). That is, it
15202     * must be possible to reach a built-in primitive datatype or the ï¿½simple
15203     * ur-type definition� by repeatedly following the {base type definition}.
15204     *
15205     * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
15206     */
15207     return (0);
15208 }
15209
15210 /**
15211  * xmlSchemaCheckCOSSTRestricts:
15212  * @ctxt:  the schema parser context
15213  * @type:  the simple type definition
15214  *
15215  * Schema Component Constraint:
15216  * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15217
15218  * Checks if the given @type (simpleType) is derived validly by restriction.
15219  * STATUS:
15220  *
15221  * Returns -1 on internal errors, 0 if the type is validly derived,
15222  * a positive error code otherwise.
15223  */
15224 static int
15225 xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
15226                              xmlSchemaTypePtr type)
15227 {
15228     xmlChar *str = NULL;
15229
15230     if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
15231         PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15232             "given type is not a user-derived simpleType");
15233         return (-1);
15234     }
15235
15236     if (WXS_IS_ATOMIC(type)) {
15237         xmlSchemaTypePtr primitive;
15238         /*
15239         * 1.1 The {base type definition} must be an atomic simple
15240         * type definition or a built-in primitive datatype.
15241         */
15242         if (! WXS_IS_ATOMIC(type->baseType)) {
15243             xmlSchemaPCustomErr(pctxt,
15244                 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
15245                 WXS_BASIC_CAST type, NULL,
15246                 "The base type '%s' is not an atomic simple type",
15247                 xmlSchemaGetComponentQName(&str, type->baseType));
15248             FREE_AND_NULL(str)
15249             return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15250         }
15251         /* 1.2 The {final} of the {base type definition} must not contain
15252         * restriction.
15253         */
15254         /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
15255         if (xmlSchemaTypeFinalContains(type->baseType,
15256             XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15257             xmlSchemaPCustomErr(pctxt,
15258                 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
15259                 WXS_BASIC_CAST type, NULL,
15260                 "The final of its base type '%s' must not contain 'restriction'",
15261                 xmlSchemaGetComponentQName(&str, type->baseType));
15262             FREE_AND_NULL(str)
15263             return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15264         }
15265
15266         /*
15267         * 1.3.1 DF must be an allowed constraining facet for the {primitive
15268         * type definition}, as specified in the appropriate subsection of 3.2
15269         * Primitive datatypes.
15270         */
15271         if (type->facets != NULL) {
15272             xmlSchemaFacetPtr facet;
15273             int ok = 1;
15274
15275             primitive = xmlSchemaGetPrimitiveType(type);
15276             if (primitive == NULL) {
15277                 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15278                     "failed to get primitive type");
15279                 return (-1);
15280             }
15281             facet = type->facets;
15282             do {
15283                 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
15284                     ok = 0;
15285                     xmlSchemaPIllegalFacetAtomicErr(pctxt,
15286                         XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
15287                         type, primitive, facet);
15288                 }
15289                 facet = facet->next;
15290             } while (facet != NULL);
15291             if (ok == 0)
15292                 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
15293         }
15294         /*
15295         * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15296         * of the {base type definition} (call this BF),then the DF's {value}
15297         * must be a valid restriction of BF's {value} as defined in
15298         * [XML Schemas: Datatypes]."
15299         *
15300         * NOTE (1.3.2) Facet derivation constraints are currently handled in
15301         * xmlSchemaDeriveAndValidateFacets()
15302         */
15303     } else if (WXS_IS_LIST(type)) {
15304         xmlSchemaTypePtr itemType = NULL;
15305
15306         itemType = type->subtypes;
15307         if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
15308             PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15309                 "failed to evaluate the item type");
15310             return (-1);
15311         }
15312         if (WXS_IS_TYPE_NOT_FIXED(itemType))
15313             xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
15314         /*
15315         * 2.1 The {item type definition} must have a {variety} of atomic or
15316         * union (in which case all the {member type definitions}
15317         * must be atomic).
15318         */
15319         if ((! WXS_IS_ATOMIC(itemType)) &&
15320             (! WXS_IS_UNION(itemType))) {
15321             xmlSchemaPCustomErr(pctxt,
15322                 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15323                 WXS_BASIC_CAST type, NULL,
15324                 "The item type '%s' does not have a variety of atomic or union",
15325                 xmlSchemaGetComponentQName(&str, itemType));
15326             FREE_AND_NULL(str)
15327             return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15328         } else if (WXS_IS_UNION(itemType)) {
15329             xmlSchemaTypeLinkPtr member;
15330
15331             member = itemType->memberTypes;
15332             while (member != NULL) {
15333                 if (! WXS_IS_ATOMIC(member->type)) {
15334                     xmlSchemaPCustomErr(pctxt,
15335                         XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15336                         WXS_BASIC_CAST type, NULL,
15337                         "The item type is a union type, but the "
15338                         "member type '%s' of this item type is not atomic",
15339                         xmlSchemaGetComponentQName(&str, member->type));
15340                     FREE_AND_NULL(str)
15341                     return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15342                 }
15343                 member = member->next;
15344             }
15345         }
15346
15347         if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
15348             xmlSchemaFacetPtr facet;
15349             /*
15350             * This is the case if we have: <simpleType><list ..
15351             */
15352             /*
15353             * 2.3.1
15354             * 2.3.1.1 The {final} of the {item type definition} must not
15355             * contain list.
15356             */
15357             if (xmlSchemaTypeFinalContains(itemType,
15358                 XML_SCHEMAS_TYPE_FINAL_LIST)) {
15359                 xmlSchemaPCustomErr(pctxt,
15360                     XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
15361                     WXS_BASIC_CAST type, NULL,
15362                     "The final of its item type '%s' must not contain 'list'",
15363                     xmlSchemaGetComponentQName(&str, itemType));
15364                 FREE_AND_NULL(str)
15365                 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15366             }
15367             /*
15368             * 2.3.1.2 The {facets} must only contain the whiteSpace
15369             * facet component.
15370             * OPTIMIZE TODO: the S4S already disallows any facet
15371             * to be specified.
15372             */
15373             if (type->facets != NULL) {
15374                 facet = type->facets;
15375                 do {
15376                     if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15377                         xmlSchemaPIllegalFacetListUnionErr(pctxt,
15378                             XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
15379                             type, facet);
15380                         return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15381                     }
15382                     facet = facet->next;
15383                 } while (facet != NULL);
15384             }
15385             /*
15386             * MAYBE TODO: (Hmm, not really) Datatypes states:
15387             * A ï¿½list� datatype can be ï¿½derived� from an ï¿½atomic� datatype
15388             * whose ï¿½lexical space� allows space (such as string or anyURI)or
15389             * a ï¿½union� datatype any of whose {member type definitions}'s
15390             * ï¿½lexical space� allows space.
15391             */
15392         } else {
15393             /*
15394             * This is the case if we have: <simpleType><restriction ...
15395             * I.e. the variety of "list" is inherited.
15396             */
15397             /*
15398             * 2.3.2
15399             * 2.3.2.1 The {base type definition} must have a {variety} of list.
15400             */
15401             if (! WXS_IS_LIST(type->baseType)) {
15402                 xmlSchemaPCustomErr(pctxt,
15403                     XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
15404                     WXS_BASIC_CAST type, NULL,
15405                     "The base type '%s' must be a list type",
15406                     xmlSchemaGetComponentQName(&str, type->baseType));
15407                 FREE_AND_NULL(str)
15408                 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15409             }
15410             /*
15411             * 2.3.2.2 The {final} of the {base type definition} must not
15412             * contain restriction.
15413             */
15414             if (xmlSchemaTypeFinalContains(type->baseType,
15415                 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15416                 xmlSchemaPCustomErr(pctxt,
15417                     XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
15418                     WXS_BASIC_CAST type, NULL,
15419                     "The 'final' of the base type '%s' must not contain 'restriction'",
15420                     xmlSchemaGetComponentQName(&str, type->baseType));
15421                 FREE_AND_NULL(str)
15422                 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15423             }
15424             /*
15425             * 2.3.2.3 The {item type definition} must be validly derived
15426             * from the {base type definition}'s {item type definition} given
15427             * the empty set, as defined in Type Derivation OK (Simple) (�3.14.6).
15428             */
15429             {
15430                 xmlSchemaTypePtr baseItemType;
15431
15432                 baseItemType = type->baseType->subtypes;
15433                 if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
15434                     PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15435                         "failed to eval the item type of a base type");
15436                     return (-1);
15437                 }
15438                 if ((itemType != baseItemType) &&
15439                     (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
15440                         baseItemType, 0) != 0)) {
15441                     xmlChar *strBIT = NULL, *strBT = NULL;
15442                     xmlSchemaPCustomErrExt(pctxt,
15443                         XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
15444                         WXS_BASIC_CAST type, NULL,
15445                         "The item type '%s' is not validly derived from "
15446                         "the item type '%s' of the base type '%s'",
15447                         xmlSchemaGetComponentQName(&str, itemType),
15448                         xmlSchemaGetComponentQName(&strBIT, baseItemType),
15449                         xmlSchemaGetComponentQName(&strBT, type->baseType));
15450
15451                     FREE_AND_NULL(str)
15452                     FREE_AND_NULL(strBIT)
15453                     FREE_AND_NULL(strBT)
15454                     return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15455                 }
15456             }
15457
15458             if (type->facets != NULL) {
15459                 xmlSchemaFacetPtr facet;
15460                 int ok = 1;
15461                 /*
15462                 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
15463                 * and enumeration facet components are allowed among the {facets}.
15464                 */
15465                 facet = type->facets;
15466                 do {
15467                     switch (facet->type) {
15468                         case XML_SCHEMA_FACET_LENGTH:
15469                         case XML_SCHEMA_FACET_MINLENGTH:
15470                         case XML_SCHEMA_FACET_MAXLENGTH:
15471                         case XML_SCHEMA_FACET_WHITESPACE:
15472                             /*
15473                             * TODO: 2.5.1.2 List datatypes
15474                             * The value of ï¿½whiteSpace� is fixed to the value collapse.
15475                             */
15476                         case XML_SCHEMA_FACET_PATTERN:
15477                         case XML_SCHEMA_FACET_ENUMERATION:
15478                             break;
15479                         default: {
15480                             xmlSchemaPIllegalFacetListUnionErr(pctxt,
15481                                 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
15482                                 type, facet);
15483                             /*
15484                             * We could return, but it's nicer to report all
15485                             * invalid facets.
15486                             */
15487                             ok = 0;
15488                         }
15489                     }
15490                     facet = facet->next;
15491                 } while (facet != NULL);
15492                 if (ok == 0)
15493                     return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15494                 /*
15495                 * SPEC (2.3.2.5) (same as 1.3.2)
15496                 *
15497                 * NOTE (2.3.2.5) This is currently done in
15498                 * xmlSchemaDeriveAndValidateFacets()
15499                 */
15500             }
15501         }
15502     } else if (WXS_IS_UNION(type)) {
15503         /*
15504         * 3.1 The {member type definitions} must all have {variety} of
15505         * atomic or list.
15506         */
15507         xmlSchemaTypeLinkPtr member;
15508
15509         member = type->memberTypes;
15510         while (member != NULL) {
15511             if (WXS_IS_TYPE_NOT_FIXED(member->type))
15512                 xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
15513
15514             if ((! WXS_IS_ATOMIC(member->type)) &&
15515                 (! WXS_IS_LIST(member->type))) {
15516                 xmlSchemaPCustomErr(pctxt,
15517                     XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
15518                     WXS_BASIC_CAST type, NULL,
15519                     "The member type '%s' is neither an atomic, nor a list type",
15520                     xmlSchemaGetComponentQName(&str, member->type));
15521                 FREE_AND_NULL(str)
15522                 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15523             }
15524             member = member->next;
15525         }
15526         /*
15527         * 3.3.1 If the {base type definition} is the ï¿½simple ur-type
15528         * definition�
15529         */
15530         if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
15531             /*
15532             * 3.3.1.1 All of the {member type definitions} must have a
15533             * {final} which does not contain union.
15534             */
15535             member = type->memberTypes;
15536             while (member != NULL) {
15537                 if (xmlSchemaTypeFinalContains(member->type,
15538                     XML_SCHEMAS_TYPE_FINAL_UNION)) {
15539                     xmlSchemaPCustomErr(pctxt,
15540                         XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
15541                         WXS_BASIC_CAST type, NULL,
15542                         "The 'final' of member type '%s' contains 'union'",
15543                         xmlSchemaGetComponentQName(&str, member->type));
15544                     FREE_AND_NULL(str)
15545                     return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15546                 }
15547                 member = member->next;
15548             }
15549             /*
15550             * 3.3.1.2 The {facets} must be empty.
15551             */
15552             if (type->facetSet != NULL) {
15553                 xmlSchemaPCustomErr(pctxt,
15554                     XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
15555                     WXS_BASIC_CAST type, NULL,
15556                     "No facets allowed", NULL);
15557                 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15558             }
15559         } else {
15560             /*
15561             * 3.3.2.1 The {base type definition} must have a {variety} of union.
15562             * I.e. the variety of "list" is inherited.
15563             */
15564             if (! WXS_IS_UNION(type->baseType)) {
15565                 xmlSchemaPCustomErr(pctxt,
15566                     XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
15567                     WXS_BASIC_CAST type, NULL,
15568                     "The base type '%s' is not a union type",
15569                     xmlSchemaGetComponentQName(&str, type->baseType));
15570                 FREE_AND_NULL(str)
15571                 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15572             }
15573             /*
15574             * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15575             */
15576             if (xmlSchemaTypeFinalContains(type->baseType,
15577                 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15578                 xmlSchemaPCustomErr(pctxt,
15579                     XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
15580                     WXS_BASIC_CAST type, NULL,
15581                     "The 'final' of its base type '%s' must not contain 'restriction'",
15582                     xmlSchemaGetComponentQName(&str, type->baseType));
15583                 FREE_AND_NULL(str)
15584                 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15585             }
15586             /*
15587             * 3.3.2.3 The {member type definitions}, in order, must be validly
15588             * derived from the corresponding type definitions in the {base
15589             * type definition}'s {member type definitions} given the empty set,
15590             * as defined in Type Derivation OK (Simple) (�3.14.6).
15591             */
15592             {
15593                 xmlSchemaTypeLinkPtr baseMember;
15594
15595                 /*
15596                 * OPTIMIZE: if the type is restricting, it has no local defined
15597                 * member types and inherits the member types of the base type;
15598                 * thus a check for equality can be skipped.
15599                 */
15600                 /*
15601                 * Even worse: I cannot see a scenario where a restricting
15602                 * union simple type can have other member types as the member
15603                 * types of it's base type. This check seems not necessary with
15604                 * respect to the derivation process in libxml2.
15605                 * But necessary if constructing types with an API.
15606                 */
15607                 if (type->memberTypes != NULL) {
15608                     member = type->memberTypes;
15609                     baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
15610                     if ((member == NULL) && (baseMember != NULL)) {
15611                         PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15612                             "different number of member types in base");
15613                     }
15614                     while (member != NULL) {
15615                         if (baseMember == NULL) {
15616                             PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15617                             "different number of member types in base");
15618                         } else if ((member->type != baseMember->type) &&
15619                             (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
15620                                 member->type, baseMember->type, 0) != 0)) {
15621                             xmlChar *strBMT = NULL, *strBT = NULL;
15622
15623                             xmlSchemaPCustomErrExt(pctxt,
15624                                 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
15625                                 WXS_BASIC_CAST type, NULL,
15626                                 "The member type %s is not validly "
15627                                 "derived from its corresponding member "
15628                                 "type %s of the base type %s",
15629                                 xmlSchemaGetComponentQName(&str, member->type),
15630                                 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15631                                 xmlSchemaGetComponentQName(&strBT, type->baseType));
15632                             FREE_AND_NULL(str)
15633                             FREE_AND_NULL(strBMT)
15634                             FREE_AND_NULL(strBT)
15635                             return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
15636                         }
15637                         member = member->next;
15638                         if (baseMember != NULL)
15639                             baseMember = baseMember->next;
15640                     }
15641                 }
15642             }
15643             /*
15644             * 3.3.2.4 Only pattern and enumeration facet components are
15645             * allowed among the {facets}.
15646             */
15647             if (type->facets != NULL) {
15648                 xmlSchemaFacetPtr facet;
15649                 int ok = 1;
15650
15651                 facet = type->facets;
15652                 do {
15653                     if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15654                         (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
15655                         xmlSchemaPIllegalFacetListUnionErr(pctxt,
15656                                 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
15657                                 type, facet);
15658                         ok = 0;
15659                     }
15660                     facet = facet->next;
15661                 } while (facet != NULL);
15662                 if (ok == 0)
15663                     return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
15664
15665             }
15666             /*
15667             * SPEC (3.3.2.5) (same as 1.3.2)
15668             *
15669             * NOTE (3.3.2.5) This is currently done in
15670             * xmlSchemaDeriveAndValidateFacets()
15671             */
15672         }
15673     }
15674
15675     return (0);
15676 }
15677
15678 /**
15679  * xmlSchemaCheckSRCSimpleType:
15680  * @ctxt:  the schema parser context
15681  * @type:  the simple type definition
15682  *
15683  * Checks crc-simple-type constraints.
15684  *
15685  * Returns 0 if the constraints are satisfied,
15686  * if not a positive error code and -1 on internal
15687  * errors.
15688  */
15689 #if 0
15690 static int
15691 xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15692                             xmlSchemaTypePtr type)
15693 {
15694     /*
15695     * src-simple-type.1 The corresponding simple type definition, if any,
15696     * must satisfy the conditions set out in Constraints on Simple Type
15697     * Definition Schema Components (�3.14.6).
15698     */
15699     if (WXS_IS_RESTRICTION(type)) {
15700         /*
15701         * src-simple-type.2 "If the <restriction> alternative is chosen,
15702         * either it must have a base [attribute] or a <simpleType> among its
15703         * [children], but not both."
15704         * NOTE: This is checked in the parse function of <restriction>.
15705         */
15706         /*
15707         *
15708         */
15709     } else if (WXS_IS_LIST(type)) {
15710         /* src-simple-type.3 "If the <list> alternative is chosen, either it must have
15711         * an itemType [attribute] or a <simpleType> among its [children],
15712         * but not both."
15713         *
15714         * NOTE: This is checked in the parse function of <list>.
15715         */
15716     } else if (WXS_IS_UNION(type)) {
15717         /*
15718         * src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
15719         */
15720     }
15721     return (0);
15722 }
15723 #endif
15724
15725 static int
15726 xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15727 {
15728    if (ctxt->vctxt == NULL) {
15729         ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15730         if (ctxt->vctxt == NULL) {
15731             xmlSchemaPErr(ctxt, NULL,
15732                 XML_SCHEMAP_INTERNAL,
15733                 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
15734                 "failed to create a temp. validation context.\n",
15735                 NULL, NULL);
15736             return (-1);
15737         }
15738         /* TODO: Pass user data. */
15739         xmlSchemaSetValidErrors(ctxt->vctxt,
15740             ctxt->error, ctxt->warning, ctxt->errCtxt);
15741         xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15742             ctxt->serror, ctxt->errCtxt);
15743     }
15744     return (0);
15745 }
15746
15747 static int
15748 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15749                              xmlNodePtr node,
15750                              xmlSchemaTypePtr type,
15751                              const xmlChar *value,
15752                              xmlSchemaValPtr *retVal,
15753                              int fireErrors,
15754                              int normalize,
15755                              int isNormalized);
15756
15757 /**
15758  * xmlSchemaParseCheckCOSValidDefault:
15759  * @pctxt:  the schema parser context
15760  * @type:  the simple type definition
15761  * @value: the default value
15762  * @node: an optional node (the holder of the value)
15763  *
15764  * Schema Component Constraint: Element Default Valid (Immediate)
15765  * (cos-valid-default)
15766  * This will be used by the parser only. For the validator there's
15767  * an other version.
15768  *
15769  * Returns 0 if the constraints are satisfied,
15770  * if not, a positive error code and -1 on internal
15771  * errors.
15772  */
15773 static int
15774 xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15775                                    xmlNodePtr node,
15776                                    xmlSchemaTypePtr type,
15777                                    const xmlChar *value,
15778                                    xmlSchemaValPtr *val)
15779 {
15780     int ret = 0;
15781
15782     /*
15783     * cos-valid-default:
15784     * Schema Component Constraint: Element Default Valid (Immediate)
15785     * For a string to be a valid default with respect to a type
15786     * definition the appropriate case among the following must be true:
15787     */
15788     if WXS_IS_COMPLEX(type) {
15789         /*
15790         * Complex type.
15791         *
15792         * SPEC (2.1) "its {content type} must be a simple type definition
15793         * or mixed."
15794         * SPEC (2.2.2) "If the {content type} is mixed, then the {content
15795         * type}'s particle must be ï¿½emptiable� as defined by
15796         * Particle Emptiable (�3.9.6)."
15797         */
15798         if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15799             ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
15800             /* NOTE that this covers (2.2.2) as well. */
15801             xmlSchemaPCustomErr(pctxt,
15802                 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
15803                 WXS_BASIC_CAST type, type->node,
15804                 "For a string to be a valid default, the type definition "
15805                 "must be a simple type or a complex type with mixed content "
15806                 "and a particle emptiable", NULL);
15807             return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15808         }
15809     }
15810     /*
15811     * 1 If the type definition is a simple type definition, then the string
15812     * must be ï¿½valid� with respect to that definition as defined by String
15813     * Valid (�3.14.4).
15814     *
15815     * AND
15816     *
15817     * 2.2.1 If the {content type} is a simple type definition, then the
15818     * string must be ï¿½valid� with respect to that simple type definition
15819     * as defined by String Valid (�3.14.4).
15820     */
15821     if (WXS_IS_SIMPLE(type))
15822         ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15823             type, value, val, 1, 1, 0);
15824     else if (WXS_HAS_SIMPLE_CONTENT(type))
15825         ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15826             type->contentTypeDef, value, val, 1, 1, 0);
15827     else
15828         return (ret);
15829
15830     if (ret < 0) {
15831         PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15832             "calling xmlSchemaVCheckCVCSimpleType()");
15833     }
15834
15835     return (ret);
15836 }
15837
15838 /**
15839  * xmlSchemaCheckCTPropsCorrect:
15840  * @ctxt:  the schema parser context
15841  * @type:  the complex type definition
15842  *
15843  *.(4.6) Constraints on Complex Type Definition Schema Components
15844  * Schema Component Constraint:
15845  * Complex Type Definition Properties Correct (ct-props-correct)
15846  * STATUS: (seems) complete
15847  *
15848  * Returns 0 if the constraints are satisfied, a positive
15849  * error code if not and -1 if an internal error occured.
15850  */
15851 static int
15852 xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15853                              xmlSchemaTypePtr type)
15854 {
15855     /*
15856     * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15857     *
15858     * SPEC (1) "The values of the properties of a complex type definition must
15859     * be as described in the property tableau in The Complex Type Definition
15860     * Schema Component (�3.4.1), modulo the impact of Missing
15861     * Sub-components (�5.3)."
15862     */
15863     if ((type->baseType != NULL) &&
15864         (WXS_IS_SIMPLE(type->baseType)) &&
15865         (WXS_IS_EXTENSION(type) == 0)) {
15866         /*
15867         * SPEC (2) "If the {base type definition} is a simple type definition,
15868         * the {derivation method} must be extension."
15869         */
15870         xmlSchemaCustomErr(ACTXT_CAST pctxt,
15871             XML_SCHEMAP_SRC_CT_1,
15872             NULL, WXS_BASIC_CAST type,
15873             "If the base type is a simple type, the derivation method must be "
15874             "'extension'", NULL, NULL);
15875         return (XML_SCHEMAP_SRC_CT_1);
15876     }
15877     /*
15878     * SPEC (3) "Circular definitions are disallowed, except for the ï¿½ur-type
15879     * definition�. That is, it must be possible to reach the ï¿½ur-type
15880     * definition by repeatedly following the {base type definition}."
15881     *
15882     * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
15883     */
15884     /*
15885     * NOTE that (4) and (5) need the following:
15886     *   - attribute uses need to be already inherited (apply attr. prohibitions)
15887     *   - attribute group references need to be expanded already
15888     *   - simple types need to be typefixed already
15889     */
15890     if (type->attrUses &&
15891         (((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15892     {
15893         xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15894         xmlSchemaAttributeUsePtr use, tmp;
15895         int i, j, hasId = 0;
15896
15897         for (i = uses->nbItems -1; i >= 0; i--) {
15898             use = uses->items[i];
15899
15900             /*
15901             * SPEC ct-props-correct
15902             * (4) "Two distinct attribute declarations in the
15903             * {attribute uses} must not have identical {name}s and
15904             * {target namespace}s."
15905             */
15906             if (i > 0) {
15907                 for (j = i -1; j >= 0; j--) {
15908                     tmp = uses->items[j];
15909                     if ((WXS_ATTRUSE_DECL_NAME(use) ==
15910                         WXS_ATTRUSE_DECL_NAME(tmp)) &&
15911                         (WXS_ATTRUSE_DECL_TNS(use) ==
15912                         WXS_ATTRUSE_DECL_TNS(tmp)))
15913                     {
15914                         xmlChar *str = NULL;
15915
15916                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
15917                             XML_SCHEMAP_AG_PROPS_CORRECT,
15918                             NULL, WXS_BASIC_CAST type,
15919                             "Duplicate %s",
15920                             xmlSchemaGetComponentDesignation(&str, use),
15921                             NULL);
15922                         FREE_AND_NULL(str);
15923                         /*
15924                         * Remove the duplicate.
15925                         */
15926                         if (xmlSchemaItemListRemove(uses, i) == -1)
15927                             goto exit_failure;
15928                         goto next_use;
15929                     }
15930                 }
15931             }
15932             /*
15933             * SPEC ct-props-correct
15934             * (5) "Two distinct attribute declarations in the
15935             * {attribute uses} must not have {type definition}s which
15936             * are or are derived from ID."
15937             */
15938             if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15939                 if (xmlSchemaIsDerivedFromBuiltInType(
15940                     WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
15941                 {
15942                     if (hasId) {
15943                         xmlChar *str = NULL;
15944
15945                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
15946                             XML_SCHEMAP_AG_PROPS_CORRECT,
15947                             NULL, WXS_BASIC_CAST type,
15948                             "There must not exist more than one attribute "
15949                             "declaration of type 'xs:ID' "
15950                             "(or derived from 'xs:ID'). The %s violates this "
15951                             "constraint",
15952                             xmlSchemaGetComponentDesignation(&str, use),
15953                             NULL);
15954                         FREE_AND_NULL(str);
15955                         if (xmlSchemaItemListRemove(uses, i) == -1)
15956                             goto exit_failure;
15957                     }
15958
15959                     hasId = 1;
15960                 }
15961             }
15962 next_use: {}
15963         }
15964     }
15965     return (0);
15966 exit_failure:
15967     return(-1);
15968 }
15969
15970 static int
15971 xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
15972                        xmlSchemaTypePtr typeB)
15973 {
15974     /*
15975     * TODO: This should implement component-identity
15976     * in the future.
15977     */
15978     if ((typeA == NULL) || (typeB == NULL))
15979         return (0);
15980     return (typeA == typeB);
15981 }
15982
15983 /**
15984  * xmlSchemaCheckCOSCTDerivedOK:
15985  * @ctxt:  the schema parser context
15986  * @type:  the to-be derived complex type definition
15987  * @baseType:  the base complex type definition
15988  * @set: the given set
15989  *
15990  * Schema Component Constraint:
15991  * Type Derivation OK (Complex) (cos-ct-derived-ok)
15992  *
15993  * STATUS: completed
15994  *
15995  * Returns 0 if the constraints are satisfied, or 1
15996  * if not.
15997  */
15998 static int
15999 xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16000                              xmlSchemaTypePtr type,
16001                              xmlSchemaTypePtr baseType,
16002                              int set)
16003 {
16004     int equal = xmlSchemaAreEqualTypes(type, baseType);
16005     /* TODO: Error codes. */
16006     /*
16007     * SPEC "For a complex type definition (call it D, for derived)
16008     * to be validly derived from a type definition (call this
16009     * B, for base) given a subset of {extension, restriction}
16010     * all of the following must be true:"
16011     */
16012     if (! equal) {
16013         /*
16014         * SPEC (1) "If B and D are not the same type definition, then the
16015         * {derivation method} of D must not be in the subset."
16016         */
16017         if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
16018             ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
16019             return (1);
16020     } else {
16021         /*
16022         * SPEC (2.1) "B and D must be the same type definition."
16023         */
16024         return (0);
16025     }
16026     /*
16027     * SPEC (2.2) "B must be D's {base type definition}."
16028     */
16029     if (type->baseType == baseType)
16030         return (0);
16031     /*
16032     * SPEC (2.3.1) "D's {base type definition} must not be the ï¿½ur-type
16033     * definition�."
16034     */
16035     if (WXS_IS_ANYTYPE(type->baseType))
16036         return (1);
16037
16038     if (WXS_IS_COMPLEX(type->baseType)) {
16039         /*
16040         * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
16041         * must be validly derived from B given the subset as defined by this
16042         * constraint."
16043         */
16044         return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
16045             baseType, set));
16046     } else {
16047         /*
16048         * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
16049         * must be validly derived from B given the subset as defined in Type
16050         * Derivation OK (Simple) (�3.14.6).
16051         */
16052         return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
16053             baseType, set));
16054     }
16055 }
16056
16057 /**
16058  * xmlSchemaCheckCOSDerivedOK:
16059  * @type:  the derived simple type definition
16060  * @baseType:  the base type definition
16061  *
16062  * Calls:
16063  * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
16064  *
16065  * Checks wheter @type can be validly derived from @baseType.
16066  *
16067  * Returns 0 on success, an positive error code otherwise.
16068  */
16069 static int
16070 xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16071                            xmlSchemaTypePtr type,
16072                            xmlSchemaTypePtr baseType,
16073                            int set)
16074 {
16075     if (WXS_IS_SIMPLE(type))
16076         return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
16077     else
16078         return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
16079 }
16080
16081 /**
16082  * xmlSchemaCheckCOSCTExtends:
16083  * @ctxt:  the schema parser context
16084  * @type:  the complex type definition
16085  *
16086  * (3.4.6) Constraints on Complex Type Definition Schema Components
16087  * Schema Component Constraint:
16088  * Derivation Valid (Extension) (cos-ct-extends)
16089  *
16090  * STATUS:
16091  *   missing:
16092  *     (1.5)
16093  *     (1.4.3.2.2.2) "Particle Valid (Extension)"
16094  *
16095  * Returns 0 if the constraints are satisfied, a positive
16096  * error code if not and -1 if an internal error occured.
16097  */
16098 static int
16099 xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16100                            xmlSchemaTypePtr type)
16101 {
16102     xmlSchemaTypePtr base = type->baseType;
16103     /*
16104     * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16105     * temporarily only.
16106     */
16107     /*
16108     * SPEC (1) "If the {base type definition} is a complex type definition,
16109     * then all of the following must be true:"
16110     */
16111     if (WXS_IS_COMPLEX(base)) {
16112         /*
16113         * SPEC (1.1) "The {final} of the {base type definition} must not
16114         * contain extension."
16115         */
16116         if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16117             xmlSchemaPCustomErr(ctxt,
16118                 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16119                 WXS_BASIC_CAST type, NULL,
16120                 "The 'final' of the base type definition "
16121                 "contains 'extension'", NULL);
16122             return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16123         }
16124
16125         /*
16126         * ATTENTION: The constrains (1.2) and (1.3) are not applied,
16127         * since they are automatically satisfied through the
16128         * inheriting mechanism.
16129         * Note that even if redefining components, the inheriting mechanism
16130         * is used.
16131         */
16132 #if 0
16133         /*
16134         * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
16135         * uses}
16136         * of the complex type definition itself, that is, for every attribute
16137         * use in the {attribute uses} of the {base type definition}, there
16138         * must be an attribute use in the {attribute uses} of the complex
16139         * type definition itself whose {attribute declaration} has the same
16140         * {name}, {target namespace} and {type definition} as its attribute
16141         * declaration"
16142         */
16143         if (base->attrUses != NULL) {
16144             int i, j, found;
16145             xmlSchemaAttributeUsePtr use, buse;
16146
16147             for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16148                 buse = (WXS_LIST_CAST base->attrUses)->items[i];
16149                 found = 0;
16150                 if (type->attrUses != NULL) {
16151                     use = (WXS_LIST_CAST type->attrUses)->items[j];
16152                     for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16153                     {
16154                         if ((WXS_ATTRUSE_DECL_NAME(use) ==
16155                                 WXS_ATTRUSE_DECL_NAME(buse)) &&
16156                             (WXS_ATTRUSE_DECL_TNS(use) ==
16157                                 WXS_ATTRUSE_DECL_TNS(buse)) &&
16158                             (WXS_ATTRUSE_TYPEDEF(use) ==
16159                                 WXS_ATTRUSE_TYPEDEF(buse))
16160                         {
16161                             found = 1;
16162                             break;
16163                         }
16164                     }
16165                 }
16166                 if (! found) {
16167                     xmlChar *str = NULL;
16168
16169                     xmlSchemaCustomErr(ACTXT_CAST ctxt,
16170                         XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16171                         NULL, WXS_BASIC_CAST type,
16172                         /*
16173                         * TODO: The report does not indicate that also the
16174                         * type needs to be the same.
16175                         */
16176                         "This type is missing a matching correspondent "
16177                         "for its {base type}'s %s in its {attribute uses}",
16178                         xmlSchemaGetComponentDesignation(&str,
16179                             buse->children),
16180                         NULL);
16181                     FREE_AND_NULL(str)
16182                 }
16183             }
16184         }
16185         /*
16186         * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16187         * definition must also have one, and the base type definition's
16188         * {attribute  wildcard}'s {namespace constraint} must be a subset
16189         * of the complex  type definition's {attribute wildcard}'s {namespace
16190         * constraint}, as defined by Wildcard Subset (�3.10.6)."
16191         */
16192
16193         /*
16194         * MAYBE TODO: Enable if ever needed. But this will be needed only
16195         * if created the type via a schema construction API.
16196         */
16197         if (base->attributeWildcard != NULL) {
16198             if (type->attributeWilcard == NULL) {
16199                 xmlChar *str = NULL;
16200
16201                 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16202                     XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16203                     NULL, type,
16204                     "The base %s has an attribute wildcard, "
16205                     "but this type is missing an attribute wildcard",
16206                     xmlSchemaGetComponentDesignation(&str, base));
16207                 FREE_AND_NULL(str)
16208
16209             } else if (xmlSchemaCheckCOSNSSubset(
16210                 base->attributeWildcard, type->attributeWildcard))
16211             {
16212                 xmlChar *str = NULL;
16213
16214                 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16215                     XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16216                     NULL, type,
16217                     "The attribute wildcard is not a valid "
16218                     "superset of the one in the base %s",
16219                     xmlSchemaGetComponentDesignation(&str, base));
16220                 FREE_AND_NULL(str)
16221             }
16222         }
16223 #endif
16224         /*
16225         * SPEC (1.4) "One of the following must be true:"
16226         */
16227         if ((type->contentTypeDef != NULL) &&
16228             (type->contentTypeDef == base->contentTypeDef)) {
16229             /*
16230             * SPEC (1.4.1) "The {content type} of the {base type definition}
16231             * and the {content type} of the complex type definition itself
16232             * must be the same simple type definition"
16233             * PASS
16234             */
16235         } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16236             (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16237             /*
16238             * SPEC (1.4.2) "The {content type} of both the {base type
16239             * definition} and the complex type definition itself must
16240             * be empty."
16241             * PASS
16242             */
16243         } else {
16244             /*
16245             * SPEC (1.4.3) "All of the following must be true:"
16246             */
16247             if (type->subtypes == NULL) {
16248                 /*
16249                 * SPEC 1.4.3.1 The {content type} of the complex type
16250                 * definition itself must specify a particle.
16251                 */
16252                 xmlSchemaPCustomErr(ctxt,
16253                     XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16254                     WXS_BASIC_CAST type, NULL,
16255                     "The content type must specify a particle", NULL);
16256                 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16257             }
16258             /*
16259             * SPEC (1.4.3.2) "One of the following must be true:"
16260             */
16261             if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16262                 /*
16263                 * SPEC (1.4.3.2.1) "The {content type} of the {base type
16264                 * definition} must be empty.
16265                 * PASS
16266                 */
16267             } else {
16268                 /*
16269                 * SPEC (1.4.3.2.2) "All of the following must be true:"
16270                 */
16271                 if ((type->contentType != base->contentType) ||
16272                     ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16273                     (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16274                     /*
16275                     * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16276                     * or both must be element-only."
16277                     */
16278                     xmlSchemaPCustomErr(ctxt,
16279                         XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16280                         WXS_BASIC_CAST type, NULL,
16281                         "The content type of both, the type and its base "
16282                         "type, must either 'mixed' or 'element-only'", NULL);
16283                     return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16284                 }
16285                 /*
16286                 * URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
16287                 * complex type definition must be a ï¿½valid extension�
16288                 * of the {base type definition}'s particle, as defined
16289                 * in Particle Valid (Extension) (�3.9.6)."
16290                 *
16291                 * NOTE that we won't check "Particle Valid (Extension)",
16292                 * since it is ensured by the derivation process in
16293                 * xmlSchemaTypeFixup(). We need to implement this when heading
16294                 * for a construction API
16295                 * TODO: !! This is needed to be checked if redefining a type !!
16296                 */
16297             }
16298             /*
16299             * URGENT TODO (1.5)
16300             */
16301         }
16302     } else {
16303         /*
16304         * SPEC (2) "If the {base type definition} is a simple type definition,
16305         * then all of the following must be true:"
16306         */
16307         if (type->contentTypeDef != base) {
16308             /*
16309             * SPEC (2.1) "The {content type} must be the same simple type
16310             * definition."
16311             */
16312             xmlSchemaPCustomErr(ctxt,
16313                 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16314                 WXS_BASIC_CAST type, NULL,
16315                 "The content type must be the simple base type", NULL);
16316             return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16317         }
16318         if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16319             /*
16320             * SPEC (2.2) "The {final} of the {base type definition} must not
16321             * contain extension"
16322             * NOTE that this is the same as (1.1).
16323             */
16324             xmlSchemaPCustomErr(ctxt,
16325                 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16326                 WXS_BASIC_CAST type, NULL,
16327                 "The 'final' of the base type definition "
16328                 "contains 'extension'", NULL);
16329             return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16330         }
16331     }
16332     return (0);
16333 }
16334
16335 /**
16336  * xmlSchemaCheckDerivationOKRestriction:
16337  * @ctxt:  the schema parser context
16338  * @type:  the complex type definition
16339  *
16340  * (3.4.6) Constraints on Complex Type Definition Schema Components
16341  * Schema Component Constraint:
16342  * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16343  *
16344  * STATUS:
16345  *   missing:
16346  *     (5.4.2) ???
16347  *
16348  * ATTENTION:
16349  * In XML Schema 1.1 this will be:
16350  * Validation Rule: Checking complex type subsumption
16351  *
16352  * Returns 0 if the constraints are satisfied, a positive
16353  * error code if not and -1 if an internal error occured.
16354  */
16355 static int
16356 xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16357                                       xmlSchemaTypePtr type)
16358 {
16359     xmlSchemaTypePtr base;
16360
16361     /*
16362     * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
16363     * temporarily only.
16364     */
16365     base = type->baseType;
16366     if (! WXS_IS_COMPLEX(base)) {
16367         xmlSchemaCustomErr(ACTXT_CAST ctxt,
16368             XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16369             type->node, WXS_BASIC_CAST type,
16370             "The base type must be a complex type", NULL, NULL);
16371         return(ctxt->err);
16372     }
16373     if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16374         /*
16375         * SPEC (1) "The {base type definition} must be a complex type
16376         * definition whose {final} does not contain restriction."
16377         */
16378         xmlSchemaCustomErr(ACTXT_CAST ctxt,
16379             XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16380             type->node, WXS_BASIC_CAST type,
16381             "The 'final' of the base type definition "
16382             "contains 'restriction'", NULL, NULL);
16383         return (ctxt->err);
16384     }
16385     /*
16386     * SPEC (2), (3) and (4)
16387     * Those are handled in a separate function, since the
16388     * same constraints are needed for redefinition of
16389     * attribute groups as well.
16390     */
16391     if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16392         XML_SCHEMA_ACTION_DERIVE,
16393         WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16394         type->attrUses, base->attrUses,
16395         type->attributeWildcard,
16396         base->attributeWildcard) == -1)
16397     {
16398         return(-1);
16399     }
16400     /*
16401     * SPEC (5) "One of the following must be true:"
16402     */
16403     if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16404         /*
16405         * SPEC (5.1) "The {base type definition} must be the
16406         * ï¿½ur-type definition�."
16407         * PASS
16408         */
16409     } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16410             (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16411         /*
16412         * SPEC (5.2.1) "The {content type} of the complex type definition
16413         * must be a simple type definition"
16414         *
16415         * SPEC (5.2.2) "One of the following must be true:"
16416         */
16417         if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16418             (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16419         {
16420             int err;
16421             /*
16422             * SPEC (5.2.2.1) "The {content type} of the {base type
16423             * definition} must be a simple type definition from which
16424             * the {content type} is validly derived given the empty
16425             * set as defined in Type Derivation OK (Simple) (�3.14.6)."
16426             *
16427             * ATTENTION TODO: This seems not needed if the type implicitely
16428             * derived from the base type.
16429             *
16430             */
16431             err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16432                 type->contentTypeDef, base->contentTypeDef, 0);
16433             if (err != 0) {
16434                 xmlChar *strA = NULL, *strB = NULL;
16435
16436                 if (err == -1)
16437                     return(-1);
16438                 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16439                     XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16440                     NULL, WXS_BASIC_CAST type,
16441                     "The {content type} %s is not validly derived from the "
16442                     "base type's {content type} %s",
16443                     xmlSchemaGetComponentDesignation(&strA,
16444                         type->contentTypeDef),
16445                     xmlSchemaGetComponentDesignation(&strB,
16446                         base->contentTypeDef));
16447                 FREE_AND_NULL(strA);
16448                 FREE_AND_NULL(strB);
16449                 return(ctxt->err);
16450             }
16451         } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16452             (xmlSchemaIsParticleEmptiable(
16453                 (xmlSchemaParticlePtr) base->subtypes))) {
16454             /*
16455             * SPEC (5.2.2.2) "The {base type definition} must be mixed
16456             * and have a particle which is ï¿½emptiable� as defined in
16457             * Particle Emptiable (�3.9.6)."
16458             * PASS
16459             */
16460         } else {
16461             xmlSchemaPCustomErr(ctxt,
16462                 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16463                 WXS_BASIC_CAST type, NULL,
16464                 "The content type of the base type must be either "
16465                 "a simple type or 'mixed' and an emptiable particle", NULL);
16466             return (ctxt->err);
16467         }
16468     } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16469         /*
16470         * SPEC (5.3.1) "The {content type} of the complex type itself must
16471         * be empty"
16472         */
16473         if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16474             /*
16475             * SPEC (5.3.2.1) "The {content type} of the {base type
16476             * definition} must also be empty."
16477             * PASS
16478             */
16479         } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16480             (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16481             xmlSchemaIsParticleEmptiable(
16482                 (xmlSchemaParticlePtr) base->subtypes)) {
16483             /*
16484             * SPEC (5.3.2.2) "The {content type} of the {base type
16485             * definition} must be elementOnly or mixed and have a particle
16486             * which is ï¿½emptiable� as defined in Particle Emptiable (�3.9.6)."
16487             * PASS
16488             */
16489         } else {
16490             xmlSchemaPCustomErr(ctxt,
16491                 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16492                 WXS_BASIC_CAST type, NULL,
16493                 "The content type of the base type must be either "
16494                 "empty or 'mixed' (or 'elements-only') and an emptiable "
16495                 "particle", NULL);
16496             return (ctxt->err);
16497         }
16498     } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16499         WXS_HAS_MIXED_CONTENT(type)) {
16500         /*
16501         * SPEC (5.4.1.1) "The {content type} of the complex type definition
16502         * itself must be element-only"
16503         */
16504         if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
16505             /*
16506             * SPEC (5.4.1.2) "The {content type} of the complex type
16507             * definition itself and of the {base type definition} must be
16508             * mixed"
16509             */
16510             xmlSchemaPCustomErr(ctxt,
16511                 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16512                 WXS_BASIC_CAST type, NULL,
16513                 "If the content type is 'mixed', then the content type of the "
16514                 "base type must also be 'mixed'", NULL);
16515             return (ctxt->err);
16516         }
16517         /*
16518         * SPEC (5.4.2) "The particle of the complex type definition itself
16519         * must be a ï¿½valid restriction� of the particle of the {content
16520         * type} of the {base type definition} as defined in Particle Valid
16521         * (Restriction) (�3.9.6).
16522         *
16523         * URGENT TODO: (5.4.2)
16524         */
16525     } else {
16526         xmlSchemaPCustomErr(ctxt,
16527             XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16528             WXS_BASIC_CAST type, NULL,
16529             "The type is not a valid restriction of its base type", NULL);
16530         return (ctxt->err);
16531     }
16532     return (0);
16533 }
16534
16535 /**
16536  * xmlSchemaCheckCTComponent:
16537  * @ctxt:  the schema parser context
16538  * @type:  the complex type definition
16539  *
16540  * (3.4.6) Constraints on Complex Type Definition Schema Components
16541  *
16542  * Returns 0 if the constraints are satisfied, a positive
16543  * error code if not and -1 if an internal error occured.
16544  */
16545 static int
16546 xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16547                           xmlSchemaTypePtr type)
16548 {
16549     int ret;
16550     /*
16551     * Complex Type Definition Properties Correct
16552     */
16553     ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16554     if (ret != 0)
16555         return (ret);
16556     if (WXS_IS_EXTENSION(type))
16557         ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16558     else
16559         ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16560     return (ret);
16561 }
16562
16563 /**
16564  * xmlSchemaCheckSRCCT:
16565  * @ctxt:  the schema parser context
16566  * @type:  the complex type definition
16567  *
16568  * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
16569  * Schema Representation Constraint:
16570  * Complex Type Definition Representation OK (src-ct)
16571  *
16572  * Returns 0 if the constraints are satisfied, a positive
16573  * error code if not and -1 if an internal error occured.
16574  */
16575 static int
16576 xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
16577                     xmlSchemaTypePtr type)
16578 {
16579     xmlSchemaTypePtr base;
16580     int ret = 0;
16581
16582     /*
16583     * TODO: Adjust the error codes here, as I used
16584     * XML_SCHEMAP_SRC_CT_1 only yet.
16585     */
16586     base = type->baseType;
16587     if (! WXS_HAS_SIMPLE_CONTENT(type)) {
16588         /*
16589         * 1 If the <complexContent> alternative is chosen, the type definition
16590         * ï¿½resolved� to by the ï¿½actual value� of the base [attribute]
16591         * must be a complex type definition;
16592         */
16593         if (! WXS_IS_COMPLEX(base)) {
16594             xmlChar *str = NULL;
16595             xmlSchemaPCustomErr(ctxt,
16596                 XML_SCHEMAP_SRC_CT_1,
16597                 WXS_BASIC_CAST type, type->node,
16598                 "If using <complexContent>, the base type is expected to be "
16599                 "a complex type. The base type '%s' is a simple type",
16600                 xmlSchemaFormatQName(&str, base->targetNamespace,
16601                 base->name));
16602             FREE_AND_NULL(str)
16603             return (XML_SCHEMAP_SRC_CT_1);
16604         }
16605     } else {
16606         /*
16607         * SPEC
16608         * 2 If the <simpleContent> alternative is chosen, all of the
16609         * following must be true:
16610         * 2.1 The type definition ï¿½resolved� to by the ï¿½actual value� of the
16611         * base [attribute] must be one of the following:
16612         */
16613         if (WXS_IS_SIMPLE(base)) {
16614             if (WXS_IS_EXTENSION(type) == 0) {
16615                 xmlChar *str = NULL;
16616                 /*
16617                 * 2.1.3 only if the <extension> alternative is also
16618                 * chosen, a simple type definition.
16619                 */
16620                 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
16621                 xmlSchemaPCustomErr(ctxt,
16622                     XML_SCHEMAP_SRC_CT_1,
16623                     WXS_BASIC_CAST type, NULL,
16624                     "If using <simpleContent> and <restriction>, the base "
16625                     "type must be a complex type. The base type '%s' is "
16626                     "a simple type",
16627                     xmlSchemaFormatQName(&str, base->targetNamespace,
16628                         base->name));
16629                 FREE_AND_NULL(str)
16630                 return (XML_SCHEMAP_SRC_CT_1);
16631             }
16632         } else {
16633             /* Base type is a complex type. */
16634             if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16635                 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16636                 /*
16637                 * 2.1.1 a complex type definition whose {content type} is a
16638                 * simple type definition;
16639                 * PASS
16640                 */
16641                 if (base->contentTypeDef == NULL) {
16642                     xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16643                         WXS_BASIC_CAST type, NULL,
16644                         "Internal error: xmlSchemaCheckSRCCT, "
16645                         "'%s', base type has no content type",
16646                         type->name);
16647                     return (-1);
16648                 }
16649             } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16650                 (WXS_IS_RESTRICTION(type))) {
16651
16652                 /*
16653                 * 2.1.2 only if the <restriction> alternative is also
16654                 * chosen, a complex type definition whose {content type}
16655                 * is mixed and a particle emptiable.
16656                 */
16657                 if (! xmlSchemaIsParticleEmptiable(
16658                     (xmlSchemaParticlePtr) base->subtypes)) {
16659                     ret = XML_SCHEMAP_SRC_CT_1;
16660                 } else
16661                     /*
16662                     * Attention: at this point the <simpleType> child is in
16663                     * ->contentTypeDef (put there during parsing).
16664                     */
16665                     if (type->contentTypeDef == NULL) {
16666                     xmlChar *str = NULL;
16667                     /*
16668                     * 2.2 If clause 2.1.2 above is satisfied, then there
16669                     * must be a <simpleType> among the [children] of
16670                     * <restriction>.
16671                     */
16672                     /* TODO: Change error code to ..._SRC_CT_2_2. */
16673                     xmlSchemaPCustomErr(ctxt,
16674                         XML_SCHEMAP_SRC_CT_1,
16675                         WXS_BASIC_CAST type, NULL,
16676                         "A <simpleType> is expected among the children "
16677                         "of <restriction>, if <simpleContent> is used and "
16678                         "the base type '%s' is a complex type",
16679                         xmlSchemaFormatQName(&str, base->targetNamespace,
16680                         base->name));
16681                     FREE_AND_NULL(str)
16682                     return (XML_SCHEMAP_SRC_CT_1);
16683                 }
16684             } else {
16685                 ret = XML_SCHEMAP_SRC_CT_1;
16686             }
16687         }
16688         if (ret > 0) {
16689             xmlChar *str = NULL;
16690             if (WXS_IS_RESTRICTION(type)) {
16691                 xmlSchemaPCustomErr(ctxt,
16692                     XML_SCHEMAP_SRC_CT_1,
16693                     WXS_BASIC_CAST type, NULL,
16694                     "If <simpleContent> and <restriction> is used, the "
16695                     "base type must be a simple type or a complex type with "
16696                     "mixed content and particle emptiable. The base type "
16697                     "'%s' is none of those",
16698                     xmlSchemaFormatQName(&str, base->targetNamespace,
16699                     base->name));
16700             } else {
16701                 xmlSchemaPCustomErr(ctxt,
16702                     XML_SCHEMAP_SRC_CT_1,
16703                     WXS_BASIC_CAST type, NULL,
16704                     "If <simpleContent> and <extension> is used, the "
16705                     "base type must be a simple type. The base type '%s' "
16706                     "is a complex type",
16707                     xmlSchemaFormatQName(&str, base->targetNamespace,
16708                     base->name));
16709             }
16710             FREE_AND_NULL(str)
16711         }
16712     }
16713     /*
16714     * SPEC (3) "The corresponding complex type definition component must
16715     * satisfy the conditions set out in Constraints on Complex Type
16716     * Definition Schema Components (�3.4.6);"
16717     * NOTE (3) will be done in xmlSchemaTypeFixup().
16718     */
16719     /*
16720     * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
16721     * above for {attribute wildcard} is satisfied, the intensional
16722     * intersection must be expressible, as defined in Attribute Wildcard
16723     * Intersection (�3.10.6).
16724     * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
16725     */
16726     return (ret);
16727 }
16728
16729 #ifdef ENABLE_PARTICLE_RESTRICTION
16730 /**
16731  * xmlSchemaCheckParticleRangeOK:
16732  * @ctxt:  the schema parser context
16733  * @type:  the complex type definition
16734  *
16735  * (3.9.6) Constraints on Particle Schema Components
16736  * Schema Component Constraint:
16737  * Occurrence Range OK (range-ok)
16738  *
16739  * STATUS: complete
16740  *
16741  * Returns 0 if the constraints are satisfied, a positive
16742  * error code if not and -1 if an internal error occured.
16743  */
16744 static int
16745 xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16746                               int bmin, int bmax)
16747 {
16748     if (rmin < bmin)
16749         return (1);
16750     if ((bmax != UNBOUNDED) &&
16751         (rmax > bmax))
16752         return (1);
16753     return (0);
16754 }
16755
16756 /**
16757  * xmlSchemaCheckRCaseNameAndTypeOK:
16758  * @ctxt:  the schema parser context
16759  * @r: the restricting element declaration particle
16760  * @b: the base element declaration particle
16761  *
16762  * (3.9.6) Constraints on Particle Schema Components
16763  * Schema Component Constraint:
16764  * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16765  * (rcase-NameAndTypeOK)
16766  *
16767  * STATUS:
16768  *   MISSING (3.2.3)
16769  *   CLARIFY: (3.2.2)
16770  *
16771  * Returns 0 if the constraints are satisfied, a positive
16772  * error code if not and -1 if an internal error occured.
16773  */
16774 static int
16775 xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16776                                  xmlSchemaParticlePtr r,
16777                                  xmlSchemaParticlePtr b)
16778 {
16779     xmlSchemaElementPtr elemR, elemB;
16780
16781     /* TODO: Error codes (rcase-NameAndTypeOK). */
16782     elemR = (xmlSchemaElementPtr) r->children;
16783     elemB = (xmlSchemaElementPtr) b->children;
16784     /*
16785     * SPEC (1) "The declarations' {name}s and {target namespace}s are
16786     * the same."
16787     */
16788     if ((elemR != elemB) &&
16789         ((! xmlStrEqual(elemR->name, elemB->name)) ||
16790         (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16791         return (1);
16792     /*
16793     * SPEC (2) "R's occurrence range is a valid restriction of B's
16794     * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16795     */
16796     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16797             b->minOccurs, b->maxOccurs) != 0)
16798         return (1);
16799     /*
16800     * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16801     * {scope} are global."
16802     */
16803     if (elemR == elemB)
16804         return (0);
16805     /*
16806     * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16807     */
16808     if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16809         (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16810          return (1);
16811     /*
16812     * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16813     * or is not fixed, or R's declaration's {value constraint} is fixed
16814     * with the same value."
16815     */
16816     if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16817         ((elemR->value == NULL) ||
16818          ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16819          /* TODO: Equality of the initial value or normalized or canonical? */
16820          (! xmlStrEqual(elemR->value, elemB->value))))
16821          return (1);
16822     /*
16823     * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16824     * definitions} is a subset of B's declaration's {identity-constraint
16825     * definitions}, if any."
16826     */
16827     if (elemB->idcs != NULL) {
16828         /* TODO */
16829     }
16830     /*
16831     * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16832     * superset of B's declaration's {disallowed substitutions}."
16833     */
16834     if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16835          ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16836         ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16837          ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16838         ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16839          ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16840          return (1);
16841     /*
16842     * SPEC (3.2.5) "R's {type definition} is validly derived given
16843     * {extension, list, union} from B's {type definition}"
16844     *
16845     * BADSPEC TODO: What's the point of adding "list" and "union" to the
16846     * set, if the corresponding constraints handle "restriction" and
16847     * "extension" only?
16848     *
16849     */
16850     {
16851         int set = 0;
16852
16853         set |= SUBSET_EXTENSION;
16854         set |= SUBSET_LIST;
16855         set |= SUBSET_UNION;
16856         if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
16857             elemB->subtypes, set) != 0)
16858             return (1);
16859     }
16860     return (0);
16861 }
16862
16863 /**
16864  * xmlSchemaCheckRCaseNSCompat:
16865  * @ctxt:  the schema parser context
16866  * @r: the restricting element declaration particle
16867  * @b: the base wildcard particle
16868  *
16869  * (3.9.6) Constraints on Particle Schema Components
16870  * Schema Component Constraint:
16871  * Particle Derivation OK (Elt:Any -- NSCompat)
16872  * (rcase-NSCompat)
16873  *
16874  * STATUS: complete
16875  *
16876  * Returns 0 if the constraints are satisfied, a positive
16877  * error code if not and -1 if an internal error occured.
16878  */
16879 static int
16880 xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16881                             xmlSchemaParticlePtr r,
16882                             xmlSchemaParticlePtr b)
16883 {
16884     /* TODO:Error codes (rcase-NSCompat). */
16885     /*
16886     * SPEC "For an element declaration particle to be a ï¿½valid restriction�
16887     * of a wildcard particle all of the following must be true:"
16888     *
16889     * SPEC (1) "The element declaration's {target namespace} is ï¿½valid�
16890     * with respect to the wildcard's {namespace constraint} as defined by
16891     * Wildcard allows Namespace Name (�3.10.4)."
16892     */
16893     if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
16894         ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16895         return (1);
16896     /*
16897     * SPEC (2) "R's occurrence range is a valid restriction of B's
16898     * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16899     */
16900     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16901             b->minOccurs, b->maxOccurs) != 0)
16902         return (1);
16903
16904     return (0);
16905 }
16906
16907 /**
16908  * xmlSchemaCheckRCaseRecurseAsIfGroup:
16909  * @ctxt:  the schema parser context
16910  * @r: the restricting element declaration particle
16911  * @b: the base model group particle
16912  *
16913  * (3.9.6) Constraints on Particle Schema Components
16914  * Schema Component Constraint:
16915  * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
16916  * (rcase-RecurseAsIfGroup)
16917  *
16918  * STATUS: TODO
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 xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16925                                     xmlSchemaParticlePtr r,
16926                                     xmlSchemaParticlePtr b)
16927 {
16928     /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16929     TODO
16930     return (0);
16931 }
16932
16933 /**
16934  * xmlSchemaCheckRCaseNSSubset:
16935  * @ctxt:  the schema parser context
16936  * @r: the restricting wildcard particle
16937  * @b: the base wildcard particle
16938  *
16939  * (3.9.6) Constraints on Particle Schema Components
16940  * Schema Component Constraint:
16941  * Particle Derivation OK (Any:Any -- NSSubset)
16942  * (rcase-NSSubset)
16943  *
16944  * STATUS: complete
16945  *
16946  * Returns 0 if the constraints are satisfied, a positive
16947  * error code if not and -1 if an internal error occured.
16948  */
16949 static int
16950 xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
16951                                     xmlSchemaParticlePtr r,
16952                                     xmlSchemaParticlePtr b,
16953                                     int isAnyTypeBase)
16954 {
16955     /* TODO: Error codes (rcase-NSSubset). */
16956     /*
16957     * SPEC (1) "R's occurrence range is a valid restriction of B's
16958     * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16959     */
16960     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16961             b->minOccurs, b->maxOccurs))
16962         return (1);
16963     /*
16964     * SPEC (2) "R's {namespace constraint} must be an intensional subset
16965     * of B's {namespace constraint} as defined by Wildcard Subset (�3.10.6)."
16966     */
16967     if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
16968         (xmlSchemaWildcardPtr) b->children))
16969         return (1);
16970     /*
16971     * SPEC (3) "Unless B is the content model wildcard of the ï¿½ur-type
16972     * definition�, R's {process contents} must be identical to or stronger
16973     * than B's {process contents}, where strict is stronger than lax is
16974     * stronger than skip."
16975     */
16976     if (! isAnyTypeBase) {
16977         if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
16978             ((xmlSchemaWildcardPtr) b->children)->processContents)
16979             return (1);
16980     }
16981
16982     return (0);
16983 }
16984
16985 /**
16986  * xmlSchemaCheckCOSParticleRestrict:
16987  * @ctxt:  the schema parser context
16988  * @type:  the complex type definition
16989  *
16990  * (3.9.6) Constraints on Particle Schema Components
16991  * Schema Component Constraint:
16992  * Particle Valid (Restriction) (cos-particle-restrict)
16993  *
16994  * STATUS: TODO
16995  *
16996  * Returns 0 if the constraints are satisfied, a positive
16997  * error code if not and -1 if an internal error occured.
16998  */
16999 static int
17000 xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
17001                                   xmlSchemaParticlePtr r,
17002                                   xmlSchemaParticlePtr b)
17003 {
17004     int ret = 0;
17005
17006     /*part = WXS_TYPE_PARTICLE(type);
17007     basePart = WXS_TYPE_PARTICLE(base);
17008     */
17009
17010     TODO
17011
17012     /*
17013     * SPEC (1) "They are the same particle."
17014     */
17015     if (r == b)
17016         return (0);
17017
17018
17019     return (0);
17020 }
17021
17022 #if 0
17023 /**
17024  * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
17025  * @ctxt:  the schema parser context
17026  * @r: the model group particle
17027  * @b: the base wildcard particle
17028  *
17029  * (3.9.6) Constraints on Particle Schema Components
17030  * Schema Component Constraint:
17031  * Particle Derivation OK (All/Choice/Sequence:Any --
17032  *                         NSRecurseCheckCardinality)
17033  * (rcase-NSRecurseCheckCardinality)
17034  *
17035  * STATUS: TODO: subst-groups
17036  *
17037  * Returns 0 if the constraints are satisfied, a positive
17038  * error code if not and -1 if an internal error occured.
17039  */
17040 static int
17041 xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
17042                                              xmlSchemaParticlePtr r,
17043                                              xmlSchemaParticlePtr b)
17044 {
17045     xmlSchemaParticlePtr part;
17046     /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
17047     if ((r->children == NULL) || (r->children->children == NULL))
17048         return (-1);
17049     /*
17050     * SPEC "For a group particle to be a ï¿½valid restriction� of a
17051     * wildcard particle..."
17052     *
17053     * SPEC (1) "Every member of the {particles} of the group is a ï¿½valid
17054     * restriction� of the wildcard as defined by
17055     * Particle Valid (Restriction) (�3.9.6)."
17056     */
17057     part = (xmlSchemaParticlePtr) r->children->children;
17058     do {
17059         if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
17060             return (1);
17061         part = (xmlSchemaParticlePtr) part->next;
17062     } while (part != NULL);
17063     /*
17064     * SPEC (2) "The effective total range of the group [...] is a
17065     * valid restriction of B's occurrence range as defined by
17066     * Occurrence Range OK (�3.9.6)."
17067     */
17068     if (xmlSchemaCheckParticleRangeOK(
17069             xmlSchemaGetParticleTotalRangeMin(r),
17070             xmlSchemaGetParticleTotalRangeMax(r),
17071             b->minOccurs, b->maxOccurs) != 0)
17072         return (1);
17073     return (0);
17074 }
17075 #endif
17076
17077 /**
17078  * xmlSchemaCheckRCaseRecurse:
17079  * @ctxt:  the schema parser context
17080  * @r: the <all> or <sequence> model group particle
17081  * @b: the base <all> or <sequence> model group particle
17082  *
17083  * (3.9.6) Constraints on Particle Schema Components
17084  * Schema Component Constraint:
17085  * Particle Derivation OK (All:All,Sequence:Sequence --
17086                            Recurse)
17087  * (rcase-Recurse)
17088  *
17089  * STATUS:  ?
17090  * TODO: subst-groups
17091  *
17092  * Returns 0 if the constraints are satisfied, a positive
17093  * error code if not and -1 if an internal error occured.
17094  */
17095 static int
17096 xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17097                            xmlSchemaParticlePtr r,
17098                            xmlSchemaParticlePtr b)
17099 {
17100     /* xmlSchemaParticlePtr part; */
17101     /* TODO: Error codes (rcase-Recurse). */
17102     if ((r->children == NULL) || (b->children == NULL) ||
17103         (r->children->type != b->children->type))
17104         return (-1);
17105     /*
17106     * SPEC "For an all or sequence group particle to be a ï¿½valid
17107     * restriction� of another group particle with the same {compositor}..."
17108     *
17109     * SPEC (1) "R's occurrence range is a valid restriction of B's
17110     * occurrence range as defined by Occurrence Range OK (�3.9.6)."
17111     */
17112     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17113             b->minOccurs, b->maxOccurs))
17114         return (1);
17115
17116
17117     return (0);
17118 }
17119
17120 #endif
17121
17122 #define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17123     xmlSchemaPCustomErrExt(pctxt,      \
17124         XML_SCHEMAP_INVALID_FACET_VALUE, \
17125         WXS_BASIC_CAST fac1, fac1->node, \
17126         "It is an error for both '%s' and '%s' to be specified on the "\
17127         "same type definition", \
17128         BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17129         BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17130
17131 #define FACET_RESTR_ERR(fac1, msg) \
17132     xmlSchemaPCustomErr(pctxt,      \
17133         XML_SCHEMAP_INVALID_FACET_VALUE, \
17134         WXS_BASIC_CAST fac1, fac1->node, \
17135         msg, NULL);
17136
17137 #define FACET_RESTR_FIXED_ERR(fac) \
17138     xmlSchemaPCustomErr(pctxt, \
17139         XML_SCHEMAP_INVALID_FACET_VALUE, \
17140         WXS_BASIC_CAST fac, fac->node, \
17141         "The base type's facet is 'fixed', thus the value must not " \
17142         "differ", NULL);
17143
17144 static void
17145 xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17146                         xmlSchemaFacetPtr facet1,
17147                         xmlSchemaFacetPtr facet2,
17148                         int lessGreater,
17149                         int orEqual,
17150                         int ofBase)
17151 {
17152     xmlChar *msg = NULL;
17153
17154     msg = xmlStrdup(BAD_CAST "'");
17155     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17156     msg = xmlStrcat(msg, BAD_CAST "' has to be");
17157     if (lessGreater == 0)
17158         msg = xmlStrcat(msg, BAD_CAST " equal to");
17159     if (lessGreater == 1)
17160         msg = xmlStrcat(msg, BAD_CAST " greater than");
17161     else
17162         msg = xmlStrcat(msg, BAD_CAST " less than");
17163
17164     if (orEqual)
17165         msg = xmlStrcat(msg, BAD_CAST " or equal to");
17166     msg = xmlStrcat(msg, BAD_CAST " '");
17167     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17168     if (ofBase)
17169         msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17170     else
17171         msg = xmlStrcat(msg, BAD_CAST "'");
17172
17173     xmlSchemaPCustomErr(pctxt,
17174         XML_SCHEMAP_INVALID_FACET_VALUE,
17175         WXS_BASIC_CAST facet1, NULL,
17176         (const char *) msg, NULL);
17177
17178     if (msg != NULL)
17179         xmlFree(msg);
17180 }
17181
17182 /*
17183 * xmlSchemaDeriveAndValidateFacets:
17184 *
17185 * Schema Component Constraint: Simple Type Restriction (Facets)
17186 * (st-restrict-facets)
17187 */
17188 static int
17189 xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17190                                  xmlSchemaTypePtr type)
17191 {
17192     xmlSchemaTypePtr base = type->baseType;
17193     xmlSchemaFacetLinkPtr link, cur, last = NULL;
17194     xmlSchemaFacetPtr facet, bfacet,
17195         flength = NULL, ftotdig = NULL, ffracdig = NULL,
17196         fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17197         fmininc = NULL, fmaxinc = NULL,
17198         fminexc = NULL, fmaxexc = NULL,
17199         bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17200         bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17201         bfmininc = NULL, bfmaxinc = NULL,
17202         bfminexc = NULL, bfmaxexc = NULL;
17203     int res; /* err = 0, fixedErr; */
17204
17205     /*
17206     * SPEC st-restrict-facets 1:
17207     * "The {variety} of R is the same as that of B."
17208     */
17209     /*
17210     * SPEC st-restrict-facets 2:
17211     * "If {variety} is atomic, the {primitive type definition}
17212     * of R is the same as that of B."
17213     *
17214     * NOTE: we leave 1 & 2 out for now, since this will be
17215     * satisfied by the derivation process.
17216     * CONSTRUCTION TODO: Maybe needed if using a construction API.
17217     */
17218     /*
17219     * SPEC st-restrict-facets 3:
17220     * "The {facets} of R are the union of S and the {facets}
17221     * of B, eliminating duplicates. To eliminate duplicates,
17222     * when a facet of the same kind occurs in both S and the
17223     * {facets} of B, the one in the {facets} of B is not
17224     * included, with the exception of enumeration and pattern
17225     * facets, for which multiple occurrences with distinct values
17226     * are allowed."
17227     */
17228
17229     if ((type->facetSet == NULL) && (base->facetSet == NULL))
17230         return (0);
17231
17232     last = type->facetSet;
17233     if (last != NULL)
17234         while (last->next != NULL)
17235             last = last->next;
17236
17237     for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17238         facet = cur->facet;
17239         switch (facet->type) {
17240             case XML_SCHEMA_FACET_LENGTH:
17241                 flength = facet; break;
17242             case XML_SCHEMA_FACET_MINLENGTH:
17243                 fminlen = facet; break;
17244             case XML_SCHEMA_FACET_MININCLUSIVE:
17245                 fmininc = facet; break;
17246             case XML_SCHEMA_FACET_MINEXCLUSIVE:
17247                 fminexc = facet; break;
17248             case XML_SCHEMA_FACET_MAXLENGTH:
17249                 fmaxlen = facet; break;
17250             case XML_SCHEMA_FACET_MAXINCLUSIVE:
17251                 fmaxinc = facet; break;
17252             case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17253                 fmaxexc = facet; break;
17254             case XML_SCHEMA_FACET_TOTALDIGITS:
17255                 ftotdig = facet; break;
17256             case XML_SCHEMA_FACET_FRACTIONDIGITS:
17257                 ffracdig = facet; break;
17258             default:
17259                 break;
17260         }
17261     }
17262     for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17263         facet = cur->facet;
17264         switch (facet->type) {
17265             case XML_SCHEMA_FACET_LENGTH:
17266                 bflength = facet; break;
17267             case XML_SCHEMA_FACET_MINLENGTH:
17268                 bfminlen = facet; break;
17269             case XML_SCHEMA_FACET_MININCLUSIVE:
17270                 bfmininc = facet; break;
17271             case XML_SCHEMA_FACET_MINEXCLUSIVE:
17272                 bfminexc = facet; break;
17273             case XML_SCHEMA_FACET_MAXLENGTH:
17274                 bfmaxlen = facet; break;
17275             case XML_SCHEMA_FACET_MAXINCLUSIVE:
17276                 bfmaxinc = facet; break;
17277             case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17278                 bfmaxexc = facet; break;
17279             case XML_SCHEMA_FACET_TOTALDIGITS:
17280                 bftotdig = facet; break;
17281             case XML_SCHEMA_FACET_FRACTIONDIGITS:
17282                 bffracdig = facet; break;
17283             default:
17284                 break;
17285         }
17286     }
17287     /*
17288     * length and minLength or maxLength (2.2) + (3.2)
17289     */
17290     if (flength && (fminlen || fmaxlen)) {
17291         FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17292             "either of 'minLength' or 'maxLength' to be specified on "
17293             "the same type definition")
17294     }
17295     /*
17296     * Mutual exclusions in the same derivation step.
17297     */
17298     if ((fmaxinc) && (fmaxexc)) {
17299         /*
17300         * SCC "maxInclusive and maxExclusive"
17301         */
17302         FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17303     }
17304     if ((fmininc) && (fminexc)) {
17305         /*
17306         * SCC "minInclusive and minExclusive"
17307         */
17308         FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
17309     }
17310
17311     if (flength && bflength) {
17312         /*
17313         * SCC "length valid restriction"
17314         * The values have to be equal.
17315         */
17316         res = xmlSchemaCompareValues(flength->val, bflength->val);
17317         if (res == -2)
17318             goto internal_error;
17319         if (res != 0)
17320             xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17321         if ((res != 0) && (bflength->fixed)) {
17322             FACET_RESTR_FIXED_ERR(flength)
17323         }
17324
17325     }
17326     if (fminlen && bfminlen) {
17327         /*
17328         * SCC "minLength valid restriction"
17329         * minLength >= BASE minLength
17330         */
17331         res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17332         if (res == -2)
17333             goto internal_error;
17334         if (res == -1)
17335             xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17336         if ((res != 0) && (bfminlen->fixed)) {
17337             FACET_RESTR_FIXED_ERR(fminlen)
17338         }
17339     }
17340     if (fmaxlen && bfmaxlen) {
17341         /*
17342         * SCC "maxLength valid restriction"
17343         * maxLength <= BASE minLength
17344         */
17345         res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17346         if (res == -2)
17347             goto internal_error;
17348         if (res == 1)
17349             xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17350         if ((res != 0) && (bfmaxlen->fixed)) {
17351             FACET_RESTR_FIXED_ERR(fmaxlen)
17352         }
17353     }
17354     /*
17355     * SCC "length and minLength or maxLength"
17356     */
17357     if (! flength)
17358         flength = bflength;
17359     if (flength) {
17360         if (! fminlen)
17361             fminlen = bfminlen;
17362         if (fminlen) {
17363             /* (1.1) length >= minLength */
17364             res = xmlSchemaCompareValues(flength->val, fminlen->val);
17365             if (res == -2)
17366                 goto internal_error;
17367             if (res == -1)
17368                 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17369         }
17370         if (! fmaxlen)
17371             fmaxlen = bfmaxlen;
17372         if (fmaxlen) {
17373             /* (2.1) length <= maxLength */
17374             res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17375             if (res == -2)
17376                 goto internal_error;
17377             if (res == 1)
17378                 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17379         }
17380     }
17381     if (fmaxinc) {
17382         /*
17383         * "maxInclusive"
17384         */
17385         if (fmininc) {
17386             /* SCC "maxInclusive >= minInclusive" */
17387             res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17388             if (res == -2)
17389                 goto internal_error;
17390             if (res == -1) {
17391                 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17392             }
17393         }
17394         /*
17395         * SCC "maxInclusive valid restriction"
17396         */
17397         if (bfmaxinc) {
17398             /* maxInclusive <= BASE maxInclusive */
17399             res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17400             if (res == -2)
17401                 goto internal_error;
17402             if (res == 1)
17403                 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17404             if ((res != 0) && (bfmaxinc->fixed)) {
17405                 FACET_RESTR_FIXED_ERR(fmaxinc)
17406             }
17407         }
17408         if (bfmaxexc) {
17409             /* maxInclusive < BASE maxExclusive */
17410             res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17411             if (res == -2)
17412                 goto internal_error;
17413             if (res != -1) {
17414                 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17415             }
17416         }
17417         if (bfmininc) {
17418             /* maxInclusive >= BASE minInclusive */
17419             res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17420             if (res == -2)
17421                 goto internal_error;
17422             if (res == -1) {
17423                 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17424             }
17425         }
17426         if (bfminexc) {
17427             /* maxInclusive > BASE minExclusive */
17428             res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17429             if (res == -2)
17430                 goto internal_error;
17431             if (res != 1) {
17432                 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17433             }
17434         }
17435     }
17436     if (fmaxexc) {
17437         /*
17438         * "maxExclusive >= minExclusive"
17439         */
17440         if (fminexc) {
17441             res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17442             if (res == -2)
17443                 goto internal_error;
17444             if (res == -1) {
17445                 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17446             }
17447         }
17448         /*
17449         * "maxExclusive valid restriction"
17450         */
17451         if (bfmaxexc) {
17452             /* maxExclusive <= BASE maxExclusive */
17453             res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17454             if (res == -2)
17455                 goto internal_error;
17456             if (res == 1) {
17457                 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17458             }
17459             if ((res != 0) && (bfmaxexc->fixed)) {
17460                 FACET_RESTR_FIXED_ERR(fmaxexc)
17461             }
17462         }
17463         if (bfmaxinc) {
17464             /* maxExclusive <= BASE maxInclusive */
17465             res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17466             if (res == -2)
17467                 goto internal_error;
17468             if (res == 1) {
17469                 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17470             }
17471         }
17472         if (bfmininc) {
17473             /* maxExclusive > BASE minInclusive */
17474             res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17475             if (res == -2)
17476                 goto internal_error;
17477             if (res != 1) {
17478                 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17479             }
17480         }
17481         if (bfminexc) {
17482             /* maxExclusive > BASE minExclusive */
17483             res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17484             if (res == -2)
17485                 goto internal_error;
17486             if (res != 1) {
17487                 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17488             }
17489         }
17490     }
17491     if (fminexc) {
17492         /*
17493         * "minExclusive < maxInclusive"
17494         */
17495         if (fmaxinc) {
17496             res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17497             if (res == -2)
17498                 goto internal_error;
17499             if (res != -1) {
17500                 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17501             }
17502         }
17503         /*
17504         * "minExclusive valid restriction"
17505         */
17506         if (bfminexc) {
17507             /* minExclusive >= BASE minExclusive */
17508             res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17509             if (res == -2)
17510                 goto internal_error;
17511             if (res == -1) {
17512                 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17513             }
17514             if ((res != 0) && (bfminexc->fixed)) {
17515                 FACET_RESTR_FIXED_ERR(fminexc)
17516             }
17517         }
17518         if (bfmaxinc) {
17519             /* minExclusive <= BASE maxInclusive */
17520             res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17521             if (res == -2)
17522                 goto internal_error;
17523             if (res == 1) {
17524                 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17525             }
17526         }
17527         if (bfmininc) {
17528             /* minExclusive >= BASE minInclusive */
17529             res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17530             if (res == -2)
17531                 goto internal_error;
17532             if (res == -1) {
17533                 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17534             }
17535         }
17536         if (bfmaxexc) {
17537             /* minExclusive < BASE maxExclusive */
17538             res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17539             if (res == -2)
17540                 goto internal_error;
17541             if (res != -1) {
17542                 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17543             }
17544         }
17545     }
17546     if (fmininc) {
17547         /*
17548         * "minInclusive < maxExclusive"
17549         */
17550         if (fmaxexc) {
17551             res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17552             if (res == -2)
17553                 goto internal_error;
17554             if (res != -1) {
17555                 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17556             }
17557         }
17558         /*
17559         * "minExclusive valid restriction"
17560         */
17561         if (bfmininc) {
17562             /* minInclusive >= BASE minInclusive */
17563             res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17564             if (res == -2)
17565                 goto internal_error;
17566             if (res == -1) {
17567                 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17568             }
17569             if ((res != 0) && (bfmininc->fixed)) {
17570                 FACET_RESTR_FIXED_ERR(fmininc)
17571             }
17572         }
17573         if (bfmaxinc) {
17574             /* minInclusive <= BASE maxInclusive */
17575             res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17576             if (res == -2)
17577                 goto internal_error;
17578             if (res == 1) {
17579                 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17580             }
17581         }
17582         if (bfminexc) {
17583             /* minInclusive > BASE minExclusive */
17584             res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17585             if (res == -2)
17586                 goto internal_error;
17587             if (res != 1)
17588                 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17589         }
17590         if (bfmaxexc) {
17591             /* minInclusive < BASE maxExclusive */
17592             res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17593             if (res == -2)
17594                 goto internal_error;
17595             if (res != -1)
17596                 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17597         }
17598     }
17599     if (ftotdig && bftotdig) {
17600         /*
17601         * SCC " totalDigits valid restriction"
17602         * totalDigits <= BASE totalDigits
17603         */
17604         res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17605         if (res == -2)
17606             goto internal_error;
17607         if (res == 1)
17608             xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17609             -1, 1, 1);
17610         if ((res != 0) && (bftotdig->fixed)) {
17611             FACET_RESTR_FIXED_ERR(ftotdig)
17612         }
17613     }
17614     if (ffracdig && bffracdig) {
17615         /*
17616         * SCC  "fractionDigits valid restriction"
17617         * fractionDigits <= BASE fractionDigits
17618         */
17619         res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17620         if (res == -2)
17621             goto internal_error;
17622         if (res == 1)
17623             xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17624             -1, 1, 1);
17625         if ((res != 0) && (bffracdig->fixed)) {
17626             FACET_RESTR_FIXED_ERR(ffracdig)
17627         }
17628     }
17629     /*
17630     * SCC "fractionDigits less than or equal to totalDigits"
17631     */
17632     if (! ftotdig)
17633         ftotdig = bftotdig;
17634     if (! ffracdig)
17635         ffracdig = bffracdig;
17636     if (ftotdig && ffracdig) {
17637         res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17638         if (res == -2)
17639             goto internal_error;
17640         if (res == 1)
17641             xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17642                 -1, 1, 0);
17643     }
17644     /*
17645     * *Enumerations* won' be added here, since only the first set
17646     * of enumerations in the ancestor-or-self axis is used
17647     * for validation, plus we need to use the base type of those
17648     * enumerations for whitespace.
17649     *
17650     * *Patterns*: won't be add here, since they are ORed at
17651     * type level and ANDed at ancestor level. This will
17652     * happed during validation by walking the base axis
17653     * of the type.
17654     */
17655     for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17656         bfacet = cur->facet;
17657         /*
17658         * Special handling of enumerations and patterns.
17659         * TODO: hmm, they should not appear in the set, so remove this.
17660         */
17661         if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
17662             (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
17663             continue;
17664         /*
17665         * Search for a duplicate facet in the current type.
17666         */
17667         link = type->facetSet;
17668         /* err = 0; */
17669         /* fixedErr = 0; */
17670         while (link != NULL) {
17671             facet = link->facet;
17672             if (facet->type == bfacet->type) {
17673                 switch (facet->type) {
17674                     case XML_SCHEMA_FACET_WHITESPACE:
17675                         /*
17676                         * The whitespace must be stronger.
17677                         */
17678                         if (facet->whitespace < bfacet->whitespace) {
17679                             FACET_RESTR_ERR(facet,
17680                                 "The 'whitespace' value has to be equal to "
17681                                 "or stronger than the 'whitespace' value of "
17682                                 "the base type")
17683                         }
17684                         if ((bfacet->fixed) &&
17685                             (facet->whitespace != bfacet->whitespace)) {
17686                             FACET_RESTR_FIXED_ERR(facet)
17687                         }
17688                         break;
17689                     default:
17690                         break;
17691                 }
17692                 /* Duplicate found. */
17693                 break;
17694             }
17695             link = link->next;
17696         }
17697         /*
17698         * If no duplicate was found: add the base types's facet
17699         * to the set.
17700         */
17701         if (link == NULL) {
17702             link = (xmlSchemaFacetLinkPtr)
17703                 xmlMalloc(sizeof(xmlSchemaFacetLink));
17704             if (link == NULL) {
17705                 xmlSchemaPErrMemory(pctxt,
17706                     "deriving facets, creating a facet link", NULL);
17707                 return (-1);
17708             }
17709             link->facet = cur->facet;
17710             link->next = NULL;
17711             if (last == NULL)
17712                 type->facetSet = link;
17713             else
17714                 last->next = link;
17715             last = link;
17716         }
17717
17718     }
17719
17720     return (0);
17721 internal_error:
17722     PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17723         "an error occured");
17724     return (-1);
17725 }
17726
17727 static int
17728 xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17729                                              xmlSchemaTypePtr type)
17730 {
17731     xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17732     /*
17733     * The actual value is then formed by replacing any union type
17734     * definition in the ï¿½explicit members� with the members of their
17735     * {member type definitions}, in order.
17736     *
17737     * TODO: There's a bug entry at
17738     * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17739     * which indicates that we'll keep the union types the future.
17740     */
17741     link = type->memberTypes;
17742     while (link != NULL) {
17743
17744         if (WXS_IS_TYPE_NOT_FIXED(link->type))
17745             xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
17746
17747         if (WXS_IS_UNION(link->type)) {
17748             subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
17749             if (subLink != NULL) {
17750                 link->type = subLink->type;
17751                 if (subLink->next != NULL) {
17752                     lastLink = link->next;
17753                     subLink = subLink->next;
17754                     prevLink = link;
17755                     while (subLink != NULL) {
17756                         newLink = (xmlSchemaTypeLinkPtr)
17757                             xmlMalloc(sizeof(xmlSchemaTypeLink));
17758                         if (newLink == NULL) {
17759                             xmlSchemaPErrMemory(pctxt, "allocating a type link",
17760                                 NULL);
17761                             return (-1);
17762                         }
17763                         newLink->type = subLink->type;
17764                         prevLink->next = newLink;
17765                         prevLink = newLink;
17766                         newLink->next = lastLink;
17767
17768                         subLink = subLink->next;
17769                     }
17770                 }
17771             }
17772         }
17773         link = link->next;
17774     }
17775     return (0);
17776 }
17777
17778 static void
17779 xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17780 {
17781     int has = 0, needVal = 0, normVal = 0;
17782
17783     has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17784     if (has) {
17785         needVal = (type->baseType->flags &
17786             XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17787         normVal = (type->baseType->flags &
17788             XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17789     }
17790     if (type->facets != NULL) {
17791         xmlSchemaFacetPtr fac;
17792
17793         for (fac = type->facets; fac != NULL; fac = fac->next) {
17794             switch (fac->type) {
17795                 case XML_SCHEMA_FACET_WHITESPACE:
17796                     break;
17797                 case XML_SCHEMA_FACET_PATTERN:
17798                     normVal = 1;
17799                     has = 1;
17800                     break;
17801                 case XML_SCHEMA_FACET_ENUMERATION:
17802                     needVal = 1;
17803                     normVal = 1;
17804                     has = 1;
17805                     break;
17806                 default:
17807                     has = 1;
17808                     break;
17809             }
17810         }
17811     }
17812     if (normVal)
17813         type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17814     if (needVal)
17815         type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17816     if (has)
17817         type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17818
17819     if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
17820         xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17821         /*
17822         * OPTIMIZE VAL TODO: Some facets need a computed value.
17823         */
17824         if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17825             (prim->builtInType != XML_SCHEMAS_STRING)) {
17826             type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17827         }
17828     }
17829 }
17830
17831 static int
17832 xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17833 {
17834
17835
17836     /*
17837     * Evaluate the whitespace-facet value.
17838     */
17839     if (WXS_IS_LIST(type)) {
17840         type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17841         return (0);
17842     } else if (WXS_IS_UNION(type))
17843         return (0);
17844
17845     if (type->facetSet != NULL) {
17846         xmlSchemaFacetLinkPtr lin;
17847
17848         for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17849             if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17850                 switch (lin->facet->whitespace) {
17851                 case XML_SCHEMAS_FACET_PRESERVE:
17852                     type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17853                     break;
17854                 case XML_SCHEMAS_FACET_REPLACE:
17855                     type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17856                     break;
17857                 case XML_SCHEMAS_FACET_COLLAPSE:
17858                     type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17859                     break;
17860                 default:
17861                     return (-1);
17862                 }
17863                 return (0);
17864             }
17865         }
17866     }
17867     /*
17868     * For all ï¿½atomic� datatypes other than string (and types ï¿½derived�
17869     * by ï¿½restriction� from it) the value of whiteSpace is fixed to
17870     * collapse
17871     */
17872     {
17873         xmlSchemaTypePtr anc;
17874
17875         for (anc = type->baseType; anc != NULL &&
17876                 anc->builtInType != XML_SCHEMAS_ANYTYPE;
17877                 anc = anc->baseType) {
17878
17879             if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17880                 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17881                     type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17882
17883                 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17884                     (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17885                     type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17886
17887                 } else
17888                     type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17889                 break;
17890             }
17891         }
17892     }
17893     return (0);
17894 }
17895
17896 static int
17897 xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17898                           xmlSchemaTypePtr type)
17899 {
17900     if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17901         return(0);
17902     if (! WXS_IS_TYPE_NOT_FIXED_1(type))
17903         return(0);
17904     type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
17905
17906     if (WXS_IS_LIST(type)) {
17907         /*
17908         * Corresponds to <simpleType><list>...
17909         */
17910         if (type->subtypes == NULL) {
17911             /*
17912             * This one is really needed, so get out.
17913             */
17914             PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17915                 "list type has no item-type assigned");
17916             return(-1);
17917         }
17918     } else if (WXS_IS_UNION(type)) {
17919         /*
17920         * Corresponds to <simpleType><union>...
17921         */
17922         if (type->memberTypes == NULL) {
17923             /*
17924             * This one is really needed, so get out.
17925             */
17926             PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17927                 "union type has no member-types assigned");
17928             return(-1);
17929         }
17930     } else {
17931         /*
17932         * Corresponds to <simpleType><restriction>...
17933         */
17934         if (type->baseType == NULL) {
17935             PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17936                 "type has no base-type assigned");
17937             return(-1);
17938         }
17939         if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
17940             if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17941                 return(-1);
17942         /*
17943         * Variety
17944         * If the <restriction> alternative is chosen, then the
17945         * {variety} of the {base type definition}.
17946         */
17947         if (WXS_IS_ATOMIC(type->baseType))
17948             type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
17949         else if (WXS_IS_LIST(type->baseType)) {
17950             type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
17951             /*
17952             * Inherit the itemType.
17953             */
17954             type->subtypes = type->baseType->subtypes;
17955         } else if (WXS_IS_UNION(type->baseType)) {
17956             type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
17957             /*
17958             * NOTE that we won't assign the memberTypes of the base,
17959             * since this will make trouble when freeing them; we will
17960             * use a lookup function to access them instead.
17961             */
17962         }
17963     }
17964     return(0);
17965 }
17966
17967 #ifdef DEBUG_TYPE
17968 static void
17969 xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
17970                        xmlSchemaTypePtr type)
17971 {
17972     if (type->node != NULL) {
17973         xmlGenericError(xmlGenericErrorContext,
17974                         "Type of %s : %s:%d :", name,
17975                         type->node->doc->URL,
17976                         xmlGetLineNo(type->node));
17977     } else {
17978         xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
17979     }
17980     if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
17981         switch (type->contentType) {
17982             case XML_SCHEMA_CONTENT_SIMPLE:
17983                 xmlGenericError(xmlGenericErrorContext, "simple\n");
17984                 break;
17985             case XML_SCHEMA_CONTENT_ELEMENTS:
17986                 xmlGenericError(xmlGenericErrorContext, "elements\n");
17987                 break;
17988             case XML_SCHEMA_CONTENT_UNKNOWN:
17989                 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
17990                 break;
17991             case XML_SCHEMA_CONTENT_EMPTY:
17992                 xmlGenericError(xmlGenericErrorContext, "empty\n");
17993                 break;
17994             case XML_SCHEMA_CONTENT_MIXED:
17995                 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
17996                     type->subtypes))
17997                     xmlGenericError(xmlGenericErrorContext,
17998                         "mixed as emptiable particle\n");
17999                 else
18000                     xmlGenericError(xmlGenericErrorContext, "mixed\n");
18001                 break;
18002                 /* Removed, since not used. */
18003                 /*
18004                 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
18005                 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
18006                 break;
18007                 */
18008             case XML_SCHEMA_CONTENT_BASIC:
18009                 xmlGenericError(xmlGenericErrorContext, "basic\n");
18010                 break;
18011             default:
18012                 xmlGenericError(xmlGenericErrorContext,
18013                     "not registered !!!\n");
18014                 break;
18015         }
18016     }
18017 }
18018 #endif
18019
18020 /*
18021 * 3.14.6 Constraints on Simple Type Definition Schema Components
18022 */
18023 static int
18024 xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
18025                                  xmlSchemaTypePtr type)
18026 {
18027     int res, olderrs = pctxt->nberrors;
18028
18029     if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18030         return(-1);
18031
18032     if (! WXS_IS_TYPE_NOT_FIXED(type))
18033         return(0);
18034
18035     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18036     type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
18037
18038     if (type->baseType == NULL) {
18039         PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
18040             "missing baseType");
18041         goto exit_failure;
18042     }
18043     if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
18044         xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
18045     /*
18046     * If a member type of a union is a union itself, we need to substitute
18047     * that member type for its member types.
18048     * NOTE that this might change in WXS 1.1; i.e. we will keep the union
18049     * types in WXS 1.1.
18050     */
18051     if ((type->memberTypes != NULL) &&
18052         (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
18053         return(-1);
18054     /*
18055     * SPEC src-simple-type 1
18056     * "The corresponding simple type definition, if any, must satisfy
18057     * the conditions set out in Constraints on Simple Type Definition
18058     * Schema Components (�3.14.6)."
18059     */
18060     /*
18061     * Schema Component Constraint: Simple Type Definition Properties Correct
18062     * (st-props-correct)
18063     */
18064     res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
18065     HFAILURE HERROR
18066     /*
18067     * Schema Component Constraint: Derivation Valid (Restriction, Simple)
18068     * (cos-st-restricts)
18069     */
18070     res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
18071     HFAILURE HERROR
18072     /*
18073     * TODO: Removed the error report, since it got annoying to get an
18074     * extra error report, if anything failed until now.
18075     * Enable this if needed.
18076     *
18077     * xmlSchemaPErr(ctxt, type->node,
18078     *    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
18079     *    "Simple type '%s' does not satisfy the constraints "
18080     *    "on simple type definitions.\n",
18081     *    type->name, NULL);
18082     */
18083     /*
18084     * Schema Component Constraint: Simple Type Restriction (Facets)
18085     * (st-restrict-facets)
18086     */
18087     res = xmlSchemaCheckFacetValues(type, pctxt);
18088     HFAILURE HERROR
18089     if ((type->facetSet != NULL) ||
18090         (type->baseType->facetSet != NULL)) {
18091         res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18092         HFAILURE HERROR
18093     }
18094     /*
18095     * Whitespace value.
18096     */
18097     res = xmlSchemaTypeFixupWhitespace(type);
18098     HFAILURE HERROR
18099     xmlSchemaTypeFixupOptimFacets(type);
18100
18101 exit_error:
18102 #ifdef DEBUG_TYPE
18103     xmlSchemaDebugFixedType(pctxt, type);
18104 #endif
18105     if (olderrs != pctxt->nberrors)
18106         return(pctxt->err);
18107     return(0);
18108
18109 exit_failure:
18110 #ifdef DEBUG_TYPE
18111     xmlSchemaDebugFixedType(pctxt, type);
18112 #endif
18113     return(-1);
18114 }
18115
18116 static int
18117 xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18118                           xmlSchemaTypePtr type)
18119 {
18120     int res = 0, olderrs = pctxt->nberrors;
18121     xmlSchemaTypePtr baseType = type->baseType;
18122
18123     if (! WXS_IS_TYPE_NOT_FIXED(type))
18124         return(0);
18125     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18126     if (baseType == NULL) {
18127         PERROR_INT("xmlSchemaFixupComplexType",
18128             "missing baseType");
18129         goto exit_failure;
18130     }
18131     /*
18132     * Fixup the base type.
18133     */
18134     if (WXS_IS_TYPE_NOT_FIXED(baseType))
18135         xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
18136     if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18137         /*
18138         * Skip fixup if the base type is invalid.
18139         * TODO: Generate a warning!
18140         */
18141         return(0);
18142     }
18143     /*
18144     * This basically checks if the base type can be derived.
18145     */
18146     res = xmlSchemaCheckSRCCT(pctxt, type);
18147     HFAILURE HERROR
18148     /*
18149     * Fixup the content type.
18150     */
18151     if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18152         /*
18153         * Corresponds to <complexType><simpleContent>...
18154         */
18155         if ((WXS_IS_COMPLEX(baseType)) &&
18156             (baseType->contentTypeDef != NULL) &&
18157             (WXS_IS_RESTRICTION(type))) {
18158             xmlSchemaTypePtr contentBase, content;
18159 #ifdef ENABLE_NAMED_LOCALS
18160             char buf[30];
18161             const xmlChar *tmpname;
18162 #endif
18163             /*
18164             * SPEC (1) If <restriction> + base type is <complexType>,
18165             * "whose own {content type} is a simple type..."
18166             */
18167             if (type->contentTypeDef != NULL) {
18168                 /*
18169                 * SPEC (1.1) "the simple type definition corresponding to the
18170                 * <simpleType> among the [children] of <restriction> if there
18171                 * is one;"
18172                 * Note that this "<simpleType> among the [children]" was put
18173                 * into ->contentTypeDef during parsing.
18174                 */
18175                 contentBase = type->contentTypeDef;
18176                 type->contentTypeDef = NULL;
18177             } else {
18178                 /*
18179                 * (1.2) "...otherwise (<restriction> has no <simpleType>
18180                 * among its [children]), the simple type definition which
18181                 * is the {content type} of the ... base type."
18182                 */
18183                 contentBase = baseType->contentTypeDef;
18184             }
18185             /*
18186             * SPEC
18187             * "... a simple type definition which restricts the simple
18188             * type definition identified in clause 1.1 or clause 1.2
18189             * with a set of facet components"
18190             *
18191             * Create the anonymous simple type, which will be the content
18192             * type of the complex type.
18193             */
18194 #ifdef ENABLE_NAMED_LOCALS
18195             snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18196             tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
18197             content = xmlSchemaAddType(pctxt, pctxt->schema,
18198                 XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
18199                 type->node, 0);
18200 #else
18201             content = xmlSchemaAddType(pctxt, pctxt->schema,
18202                 XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
18203                 type->node, 0);
18204 #endif
18205             if (content == NULL)
18206                 goto exit_failure;
18207             /*
18208             * We will use the same node as for the <complexType>
18209             * to have it somehow anchored in the schema doc.
18210             */
18211             content->type = XML_SCHEMA_TYPE_SIMPLE;
18212             content->baseType = contentBase;
18213             /*
18214             * Move the facets, previously anchored on the
18215             * complexType during parsing.
18216             */
18217             content->facets = type->facets;
18218             type->facets = NULL;
18219             content->facetSet = type->facetSet;
18220             type->facetSet = NULL;
18221
18222             type->contentTypeDef = content;
18223             if (WXS_IS_TYPE_NOT_FIXED(contentBase))
18224                 xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
18225             /*
18226             * Fixup the newly created type. We don't need to check
18227             * for circularity here.
18228             */
18229             res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18230             HFAILURE HERROR
18231             res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18232             HFAILURE HERROR
18233
18234         } else if ((WXS_IS_COMPLEX(baseType)) &&
18235             (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18236             (WXS_IS_RESTRICTION(type))) {
18237             /*
18238             * SPEC (2) If <restriction> + base is a mixed <complexType> with
18239             * an emptiable particle, then a simple type definition which
18240             * restricts the <restriction>'s <simpleType> child.
18241             */
18242             if ((type->contentTypeDef == NULL) ||
18243                 (type->contentTypeDef->baseType == NULL)) {
18244                 /*
18245                 * TODO: Check if this ever happens.
18246                 */
18247                 xmlSchemaPCustomErr(pctxt,
18248                     XML_SCHEMAP_INTERNAL,
18249                     WXS_BASIC_CAST type, NULL,
18250                     "Internal error: xmlSchemaTypeFixup, "
18251                     "complex type '%s': the <simpleContent><restriction> "
18252                     "is missing a <simpleType> child, but was not catched "
18253                     "by xmlSchemaCheckSRCCT()", type->name);
18254                 goto exit_failure;
18255             }
18256         } else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
18257             /*
18258             * SPEC (3) If <extension> + base is <complexType> with
18259             * <simpleType> content, "...then the {content type} of that
18260             * complex type definition"
18261             */
18262             if (baseType->contentTypeDef == NULL) {
18263                 /*
18264                 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18265                 * should have catched this already.
18266                 */
18267                 xmlSchemaPCustomErr(pctxt,
18268                     XML_SCHEMAP_INTERNAL,
18269                     WXS_BASIC_CAST type, NULL,
18270                     "Internal error: xmlSchemaTypeFixup, "
18271                     "complex type '%s': the <extension>ed base type is "
18272                     "a complex type with no simple content type",
18273                     type->name);
18274                 goto exit_failure;
18275             }
18276             type->contentTypeDef = baseType->contentTypeDef;
18277         } else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
18278             /*
18279             * SPEC (4) <extension> + base is <simpleType>
18280             * "... then that simple type definition"
18281             */
18282             type->contentTypeDef = baseType;
18283         } else {
18284             /*
18285             * TODO: Check if this ever happens.
18286             */
18287             xmlSchemaPCustomErr(pctxt,
18288                 XML_SCHEMAP_INTERNAL,
18289                 WXS_BASIC_CAST type, NULL,
18290                 "Internal error: xmlSchemaTypeFixup, "
18291                 "complex type '%s' with <simpleContent>: unhandled "
18292                 "derivation case", type->name);
18293             goto exit_failure;
18294         }
18295     } else {
18296         int dummySequence = 0;
18297         xmlSchemaParticlePtr particle =
18298             (xmlSchemaParticlePtr) type->subtypes;
18299         /*
18300         * Corresponds to <complexType><complexContent>...
18301         *
18302         * NOTE that the effective mixed was already set during parsing of
18303         * <complexType> and <complexContent>; its flag value is
18304         * XML_SCHEMAS_TYPE_MIXED.
18305         *
18306         * Compute the "effective content":
18307         * (2.1.1) + (2.1.2) + (2.1.3)
18308         */
18309         if ((particle == NULL) ||
18310             ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18311             ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18312             (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18313             ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18314             (particle->minOccurs == 0))) &&
18315             ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18316             if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18317                 /*
18318                 * SPEC (2.1.4) "If the ï¿½effective mixed� is true, then
18319                 * a particle whose properties are as follows:..."
18320                 *
18321                 * Empty sequence model group with
18322                 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18323                 * NOTE that we sill assign it the <complexType> node to
18324                 * somehow anchor it in the doc.
18325                 */
18326                 if ((particle == NULL) ||
18327                     (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18328                     /*
18329                     * Create the particle.
18330                     */
18331                     particle = xmlSchemaAddParticle(pctxt,
18332                         type->node, 1, 1);
18333                     if (particle == NULL)
18334                         goto exit_failure;
18335                     /*
18336                     * Create the model group.
18337                     */ /* URGENT TODO: avoid adding to pending items. */
18338                     particle->children = (xmlSchemaTreeItemPtr)
18339                         xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18340                         XML_SCHEMA_TYPE_SEQUENCE, type->node);
18341                     if (particle->children == NULL)
18342                         goto exit_failure;
18343
18344                     type->subtypes = (xmlSchemaTypePtr) particle;
18345                 }
18346                 dummySequence = 1;
18347                 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18348             } else {
18349                 /*
18350                 * SPEC (2.1.5) "otherwise empty"
18351                 */
18352                 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18353             }
18354         } else {
18355             /*
18356             * SPEC (2.2) "otherwise the particle corresponding to the
18357             * <all>, <choice>, <group> or <sequence> among the
18358             * [children]."
18359             */
18360             type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18361         }
18362         /*
18363         * Compute the "content type".
18364         */
18365         if (WXS_IS_RESTRICTION(type)) {
18366             /*
18367             * SPEC (3.1) "If <restriction>..."
18368             * (3.1.1) + (3.1.2) */
18369             if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18370                 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18371                     type->contentType = XML_SCHEMA_CONTENT_MIXED;
18372             }
18373         } else {
18374             /*
18375             * SPEC (3.2) "If <extension>..."
18376             */
18377             if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18378                 /*
18379                 * SPEC (3.2.1)
18380                 * "If the ï¿½effective content� is empty, then the
18381                 *  {content type} of the [...] base ..."
18382                 */
18383                 type->contentType = baseType->contentType;
18384                 type->subtypes = baseType->subtypes;
18385                 /*
18386                 * Fixes bug #347316:
18387                 * This is the case when the base type has a simple
18388                 * type definition as content.
18389                 */
18390                 type->contentTypeDef = baseType->contentTypeDef;
18391                 /*
18392                 * NOTE that the effective mixed is ignored here.
18393                 */
18394             } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18395                 /*
18396                 * SPEC (3.2.2)
18397                 */
18398                 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18399                     type->contentType = XML_SCHEMA_CONTENT_MIXED;
18400             } else {
18401                 /*
18402                 * SPEC (3.2.3)
18403                 */
18404                 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18405                     type->contentType = XML_SCHEMA_CONTENT_MIXED;
18406                     /*
18407                     * "A model group whose {compositor} is sequence and whose
18408                     * {particles} are..."
18409                     */
18410                 if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18411                     (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18412                     ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18413                         XML_SCHEMA_TYPE_ALL))
18414                 {
18415                     /*
18416                     * SPEC cos-all-limited (1)
18417                     */
18418                     xmlSchemaCustomErr(ACTXT_CAST pctxt,
18419                         /* TODO: error code */
18420                         XML_SCHEMAP_COS_ALL_LIMITED,
18421                         WXS_ITEM_NODE(type), NULL,
18422                         "The type has an 'all' model group in its "
18423                         "{content type} and thus cannot be derived from "
18424                         "a non-empty type, since this would produce a "
18425                         "'sequence' model group containing the 'all' "
18426                         "model group; 'all' model groups are not "
18427                         "allowed to appear inside other model groups",
18428                         NULL, NULL);
18429
18430                 } else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18431                     (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18432                     ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18433                         XML_SCHEMA_TYPE_ALL))
18434                 {
18435                     /*
18436                     * SPEC cos-all-limited (1)
18437                     */
18438                     xmlSchemaCustomErr(ACTXT_CAST pctxt,
18439                         /* TODO: error code */
18440                         XML_SCHEMAP_COS_ALL_LIMITED,
18441                         WXS_ITEM_NODE(type), NULL,
18442                         "A type cannot be derived by extension from a type "
18443                         "which has an 'all' model group in its "
18444                         "{content type}, since this would produce a "
18445                         "'sequence' model group containing the 'all' "
18446                         "model group; 'all' model groups are not "
18447                         "allowed to appear inside other model groups",
18448                         NULL, NULL);
18449
18450                 } else if (! dummySequence) {
18451                     xmlSchemaTreeItemPtr effectiveContent =
18452                         (xmlSchemaTreeItemPtr) type->subtypes;
18453                     /*
18454                     * Create the particle.
18455                     */
18456                     particle = xmlSchemaAddParticle(pctxt,
18457                         type->node, 1, 1);
18458                     if (particle == NULL)
18459                         goto exit_failure;
18460                     /*
18461                     * Create the "sequence" model group.
18462                     */
18463                     particle->children = (xmlSchemaTreeItemPtr)
18464                         xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18465                         XML_SCHEMA_TYPE_SEQUENCE, type->node);
18466                     if (particle->children == NULL)
18467                         goto exit_failure;
18468                     WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
18469                     /*
18470                     * SPEC "the particle of the {content type} of
18471                     * the ... base ..."
18472                     * Create a duplicate of the base type's particle
18473                     * and assign its "term" to it.
18474                     */
18475                     particle->children->children =
18476                         (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18477                         type->node,
18478                         ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
18479                         ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
18480                     if (particle->children->children == NULL)
18481                         goto exit_failure;
18482                     particle = (xmlSchemaParticlePtr)
18483                         particle->children->children;
18484                     particle->children =
18485                         ((xmlSchemaParticlePtr) baseType->subtypes)->children;
18486                     /*
18487                     * SPEC "followed by the ï¿½effective content�."
18488                     */
18489                     particle->next = effectiveContent;
18490                     /*
18491                     * This all will result in:
18492                     * new-particle
18493                     *   --> new-sequence(
18494                     *         new-particle
18495                     *           --> base-model,
18496                     *         this-particle
18497                     *           --> this-model
18498                     *       )
18499                     */
18500                 } else {
18501                     /*
18502                     * This is the case when there is already an empty
18503                     * <sequence> with minOccurs==maxOccurs==1.
18504                     * Just add the base types's content type.
18505                     * NOTE that, although we miss to add an intermediate
18506                     * <sequence>, this should produce no difference to
18507                     * neither the regex compilation of the content model,
18508                     * nor to the complex type contraints.
18509                     */
18510                     particle->children->children =
18511                         (xmlSchemaTreeItemPtr) baseType->subtypes;
18512                 }
18513             }
18514         }
18515     }
18516     /*
18517     * Now fixup attribute uses:
18518     *   - expand attr. group references
18519     *     - intersect attribute wildcards
18520     *   - inherit attribute uses of the base type
18521     *   - inherit or union attr. wildcards if extending
18522     *   - apply attr. use prohibitions if restricting
18523     */
18524     res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
18525     HFAILURE HERROR
18526     /*
18527     * Apply the complex type component constraints; this will not
18528     * check attributes, since this is done in
18529     * xmlSchemaFixupTypeAttributeUses().
18530     */
18531     res = xmlSchemaCheckCTComponent(pctxt, type);
18532     HFAILURE HERROR
18533
18534 #ifdef DEBUG_TYPE
18535     xmlSchemaDebugFixedType(pctxt, type);
18536 #endif
18537     if (olderrs != pctxt->nberrors)
18538         return(pctxt->err);
18539     else
18540         return(0);
18541
18542 exit_error:
18543     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18544 #ifdef DEBUG_TYPE
18545     xmlSchemaDebugFixedType(pctxt, type);
18546 #endif
18547     return(pctxt->err);
18548
18549 exit_failure:
18550     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18551 #ifdef DEBUG_TYPE
18552     xmlSchemaDebugFixedType(pctxt, type);
18553 #endif
18554     return(-1);
18555 }
18556
18557
18558 /**
18559  * xmlSchemaTypeFixup:
18560  * @typeDecl:  the schema type definition
18561  * @ctxt:  the schema parser context
18562  *
18563  * Fixes the content model of the type.
18564  * URGENT TODO: We need an int result!
18565  */
18566 static int
18567 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
18568                    xmlSchemaAbstractCtxtPtr actxt)
18569 {
18570     if (type == NULL)
18571         return(0);
18572     if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18573         AERROR_INT("xmlSchemaTypeFixup",
18574             "this function needs a parser context");
18575         return(-1);
18576     }
18577     if (! WXS_IS_TYPE_NOT_FIXED(type))
18578         return(0);
18579     if (type->type == XML_SCHEMA_TYPE_COMPLEX)
18580         return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
18581     else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
18582         return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
18583     return(0);
18584 }
18585
18586 /**
18587  * xmlSchemaCheckFacet:
18588  * @facet:  the facet
18589  * @typeDecl:  the schema type definition
18590  * @pctxt:  the schema parser context or NULL
18591  * @name: the optional name of the type
18592  *
18593  * Checks and computes the values of facets.
18594  *
18595  * Returns 0 if valid, a positive error code if not valid and
18596  *         -1 in case of an internal or API error.
18597  */
18598 int
18599 xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
18600                     xmlSchemaTypePtr typeDecl,
18601                     xmlSchemaParserCtxtPtr pctxt,
18602                     const xmlChar * name ATTRIBUTE_UNUSED)
18603 {
18604     int ret = 0, ctxtGiven;
18605
18606     if ((facet == NULL) || (typeDecl == NULL))
18607         return(-1);
18608     /*
18609     * TODO: will the parser context be given if used from
18610     * the relaxNG module?
18611     */
18612     if (pctxt == NULL)
18613         ctxtGiven = 0;
18614     else
18615         ctxtGiven = 1;
18616
18617     switch (facet->type) {
18618         case XML_SCHEMA_FACET_MININCLUSIVE:
18619         case XML_SCHEMA_FACET_MINEXCLUSIVE:
18620         case XML_SCHEMA_FACET_MAXINCLUSIVE:
18621         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18622         case XML_SCHEMA_FACET_ENUMERATION: {
18623                 /*
18624                  * Okay we need to validate the value
18625                  * at that point.
18626                  */
18627                 xmlSchemaTypePtr base;
18628
18629                 /* 4.3.5.5 Constraints on enumeration Schema Components
18630                 * Schema Component Constraint: enumeration valid restriction
18631                 * It is an ï¿½error� if any member of {value} is not in the
18632                 * ï¿½value space� of {base type definition}.
18633                 *
18634                 * minInclusive, maxInclusive, minExclusive, maxExclusive:
18635                 * The value ï¿½must� be in the
18636                 * ï¿½value space� of the ï¿½base type�.
18637                 */
18638                 /*
18639                 * This function is intended to deliver a compiled value
18640                 * on the facet. In this implementation of XML Schemata the
18641                 * type holding a facet, won't be a built-in type.
18642                 * Thus to ensure that other API
18643                 * calls (relaxng) do work, if the given type is a built-in
18644                 * type, we will assume that the given built-in type *is
18645                 * already* the base type.
18646                 */
18647                 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18648                     base = typeDecl->baseType;
18649                     if (base == NULL) {
18650                         PERROR_INT("xmlSchemaCheckFacet",
18651                             "a type user derived type has no base type");
18652                         return (-1);
18653                     }
18654                 } else
18655                     base = typeDecl;
18656
18657                 if (! ctxtGiven) {
18658                     /*
18659                     * A context is needed if called from RelaxNG.
18660                     */
18661                     pctxt = xmlSchemaNewParserCtxt("*");
18662                     if (pctxt == NULL)
18663                         return (-1);
18664                 }
18665                 /*
18666                 * NOTE: This call does not check the content nodes,
18667                 * since they are not available:
18668                 * facet->node is just the node holding the facet
18669                 * definition, *not* the attribute holding the *value*
18670                 * of the facet.
18671                 */
18672                 ret = xmlSchemaVCheckCVCSimpleType(
18673                     ACTXT_CAST pctxt, facet->node, base,
18674                     facet->value, &(facet->val), 1, 1, 0);
18675                 if (ret != 0) {
18676                     if (ret < 0) {
18677                         /* No error message for RelaxNG. */
18678                         if (ctxtGiven) {
18679                             xmlSchemaCustomErr(ACTXT_CAST pctxt,
18680                                 XML_SCHEMAP_INTERNAL, facet->node, NULL,
18681                                 "Internal error: xmlSchemaCheckFacet, "
18682                                 "failed to validate the value '%s' of the "
18683                                 "facet '%s' against the base type",
18684                                 facet->value, xmlSchemaFacetTypeToString(facet->type));
18685                         }
18686                         goto internal_error;
18687                     }
18688                     ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18689                     /* No error message for RelaxNG. */
18690                     if (ctxtGiven) {
18691                         xmlChar *str = NULL;
18692
18693                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
18694                             ret, facet->node, WXS_BASIC_CAST facet,
18695                             "The value '%s' of the facet does not validate "
18696                             "against the base type '%s'",
18697                             facet->value,
18698                             xmlSchemaFormatQName(&str,
18699                                 base->targetNamespace, base->name));
18700                         FREE_AND_NULL(str);
18701                     }
18702                     goto exit;
18703                 } else if (facet->val == NULL) {
18704                     if (ctxtGiven) {
18705                         PERROR_INT("xmlSchemaCheckFacet",
18706                             "value was not computed");
18707                     }
18708                     TODO
18709                 }
18710                 break;
18711             }
18712         case XML_SCHEMA_FACET_PATTERN:
18713             facet->regexp = xmlRegexpCompile(facet->value);
18714             if (facet->regexp == NULL) {
18715                 ret = XML_SCHEMAP_REGEXP_INVALID;
18716                 /* No error message for RelaxNG. */
18717                 if (ctxtGiven) {
18718                     xmlSchemaCustomErr(ACTXT_CAST pctxt,
18719                         ret, facet->node, WXS_BASIC_CAST typeDecl,
18720                         "The value '%s' of the facet 'pattern' is not a "
18721                         "valid regular expression",
18722                         facet->value, NULL);
18723                 }
18724             }
18725             break;
18726         case XML_SCHEMA_FACET_TOTALDIGITS:
18727         case XML_SCHEMA_FACET_FRACTIONDIGITS:
18728         case XML_SCHEMA_FACET_LENGTH:
18729         case XML_SCHEMA_FACET_MAXLENGTH:
18730         case XML_SCHEMA_FACET_MINLENGTH:
18731
18732             if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18733                 ret = xmlSchemaValidatePredefinedType(
18734                     xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18735                     facet->value, &(facet->val));
18736             } else {
18737                 ret = xmlSchemaValidatePredefinedType(
18738                     xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18739                     facet->value, &(facet->val));
18740             }
18741             if (ret != 0) {
18742                 if (ret < 0) {
18743                     /* No error message for RelaxNG. */
18744                     if (ctxtGiven) {
18745                         PERROR_INT("xmlSchemaCheckFacet",
18746                             "validating facet value");
18747                     }
18748                     goto internal_error;
18749                 }
18750                 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18751                 /* No error message for RelaxNG. */
18752                 if (ctxtGiven) {
18753                     /* error code */
18754                     xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18755                         ret, facet->node, WXS_BASIC_CAST typeDecl,
18756                         "The value '%s' of the facet '%s' is not a valid '%s'",
18757                         facet->value,
18758                         xmlSchemaFacetTypeToString(facet->type),
18759                         (facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18760                             BAD_CAST "nonNegativeInteger" :
18761                             BAD_CAST "positiveInteger",
18762                         NULL);
18763                 }
18764             }
18765             break;
18766
18767         case XML_SCHEMA_FACET_WHITESPACE:{
18768                 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18769                     facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18770                 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18771                     facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18772                 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18773                     facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18774                 } else {
18775                     ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18776                     /* No error message for RelaxNG. */
18777                     if (ctxtGiven) {
18778                         /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
18779                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
18780                             ret, facet->node, WXS_BASIC_CAST typeDecl,
18781                             "The value '%s' of the facet 'whitespace' is not "
18782                             "valid", facet->value, NULL);
18783                     }
18784                 }
18785             }
18786         default:
18787             break;
18788     }
18789 exit:
18790     if ((! ctxtGiven) && (pctxt != NULL))
18791         xmlSchemaFreeParserCtxt(pctxt);
18792     return (ret);
18793 internal_error:
18794     if ((! ctxtGiven) && (pctxt != NULL))
18795         xmlSchemaFreeParserCtxt(pctxt);
18796     return (-1);
18797 }
18798
18799 /**
18800  * xmlSchemaCheckFacetValues:
18801  * @typeDecl:  the schema type definition
18802  * @ctxt:  the schema parser context
18803  *
18804  * Checks the default values types, especially for facets
18805  */
18806 static int
18807 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
18808                           xmlSchemaParserCtxtPtr pctxt)
18809 {
18810     int res, olderrs = pctxt->nberrors;
18811     const xmlChar *name = typeDecl->name;
18812     /*
18813     * NOTE: It is intended to use the facets list, instead
18814     * of facetSet.
18815     */
18816     if (typeDecl->facets != NULL) {
18817         xmlSchemaFacetPtr facet = typeDecl->facets;
18818
18819         /*
18820         * Temporarily assign the "schema" to the validation context
18821         * of the parser context. This is needed for NOTATION validation.
18822         */
18823         if (pctxt->vctxt == NULL) {
18824             if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18825                 return(-1);
18826         }
18827         pctxt->vctxt->schema = pctxt->schema;
18828         while (facet != NULL) {
18829             res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18830             HFAILURE
18831             facet = facet->next;
18832         }
18833         pctxt->vctxt->schema = NULL;
18834     }
18835     if (olderrs != pctxt->nberrors)
18836         return(pctxt->err);
18837     return(0);
18838 exit_failure:
18839     return(-1);
18840 }
18841
18842 /**
18843  * xmlSchemaGetCircModelGrDefRef:
18844  * @ctxtMGroup: the searched model group
18845  * @selfMGroup: the second searched model group
18846  * @particle: the first particle
18847  *
18848  * This one is intended to be used by
18849  * xmlSchemaCheckGroupDefCircular only.
18850  *
18851  * Returns the particle with the circular model group definition reference,
18852  * otherwise NULL.
18853  */
18854 static xmlSchemaTreeItemPtr
18855 xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
18856                               xmlSchemaTreeItemPtr particle)
18857 {
18858     xmlSchemaTreeItemPtr circ = NULL;
18859     xmlSchemaTreeItemPtr term;
18860     xmlSchemaModelGroupDefPtr gdef;
18861
18862     for (; particle != NULL; particle = particle->next) {
18863         term = particle->children;
18864         if (term == NULL)
18865             continue;
18866         switch (term->type) {
18867             case XML_SCHEMA_TYPE_GROUP:
18868                 gdef = (xmlSchemaModelGroupDefPtr) term;
18869                 if (gdef == groupDef)
18870                     return (particle);
18871                 /*
18872                 * Mark this model group definition to avoid infinite
18873                 * recursion on circular references not yet examined.
18874                 */
18875                 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18876                     continue;
18877                 if (gdef->children != NULL) {
18878                     gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18879                     circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18880                         gdef->children->children);
18881                     gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18882                     if (circ != NULL)
18883                         return (circ);
18884                 }
18885                 break;
18886             case XML_SCHEMA_TYPE_SEQUENCE:
18887             case XML_SCHEMA_TYPE_CHOICE:
18888             case XML_SCHEMA_TYPE_ALL:
18889                 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18890                 if (circ != NULL)
18891                     return (circ);
18892                 break;
18893             default:
18894                 break;
18895         }
18896     }
18897     return (NULL);
18898 }
18899
18900 /**
18901  * xmlSchemaCheckGroupDefCircular:
18902  * @item:  the model group definition
18903  * @ctxt:  the parser context
18904  * @name:  the name
18905  *
18906  * Checks for circular references to model group definitions.
18907  */
18908 static void
18909 xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
18910                                xmlSchemaParserCtxtPtr ctxt)
18911 {
18912     /*
18913     * Schema Component Constraint: Model Group Correct
18914     * 2 Circular groups are disallowed. That is, within the {particles}
18915     * of a group there must not be at any depth a particle whose {term}
18916     * is the group itself.
18917     */
18918     if ((item == NULL) ||
18919         (item->type != XML_SCHEMA_TYPE_GROUP) ||
18920         (item->children == NULL))
18921         return;
18922     {
18923         xmlSchemaTreeItemPtr circ;
18924
18925         circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
18926         if (circ != NULL) {
18927             xmlChar *str = NULL;
18928             /*
18929             * TODO: The error report is not adequate: this constraint
18930             * is defined for model groups but not definitions, but since
18931             * there cannot be any circular model groups without a model group
18932             * definition (if not using a construction API), we check those
18933             * defintions only.
18934             */
18935             xmlSchemaPCustomErr(ctxt,
18936                 XML_SCHEMAP_MG_PROPS_CORRECT_2,
18937                 NULL, WXS_ITEM_NODE(circ),
18938                 "Circular reference to the model group definition '%s' "
18939                 "defined", xmlSchemaFormatQName(&str,
18940                     item->targetNamespace, item->name));
18941             FREE_AND_NULL(str)
18942             /*
18943             * NOTE: We will cut the reference to avoid further
18944             * confusion of the processor. This is a fatal error.
18945             */
18946             circ->children = NULL;
18947         }
18948     }
18949 }
18950
18951 /**
18952  * xmlSchemaModelGroupToModelGroupDefFixup:
18953  * @ctxt:  the parser context
18954  * @mg:  the model group
18955  *
18956  * Assigns the model group of model group definitions to the "term"
18957  * of the referencing particle.
18958  * In xmlSchemaResolveModelGroupParticleReferences the model group
18959  * definitions were assigned to the "term", since needed for the
18960  * circularity check.
18961  *
18962  * Schema Component Constraint:
18963  *     All Group Limited (cos-all-limited) (1.2)
18964  */
18965 static void
18966 xmlSchemaModelGroupToModelGroupDefFixup(
18967     xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
18968     xmlSchemaModelGroupPtr mg)
18969 {
18970     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
18971
18972     while (particle != NULL) {
18973         if ((WXS_PARTICLE_TERM(particle) == NULL) ||
18974             ((WXS_PARTICLE_TERM(particle))->type !=
18975                 XML_SCHEMA_TYPE_GROUP))
18976         {
18977             particle = WXS_PTC_CAST particle->next;
18978             continue;
18979         }
18980         if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
18981             /*
18982             * TODO: Remove the particle.
18983             */
18984             WXS_PARTICLE_TERM(particle) = NULL;
18985             particle = WXS_PTC_CAST particle->next;
18986             continue;
18987         }
18988         /*
18989         * Assign the model group to the {term} of the particle.
18990         */
18991         WXS_PARTICLE_TERM(particle) =
18992             WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
18993
18994         particle = WXS_PTC_CAST particle->next;
18995     }
18996 }
18997
18998 /**
18999  * xmlSchemaCheckAttrGroupCircularRecur:
19000  * @ctxtGr: the searched attribute group
19001  * @attr: the current attribute list to be processed
19002  *
19003  * This one is intended to be used by
19004  * xmlSchemaCheckAttrGroupCircular only.
19005  *
19006  * Returns the circular attribute grou reference, otherwise NULL.
19007  */
19008 static xmlSchemaQNameRefPtr
19009 xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
19010                                      xmlSchemaItemListPtr list)
19011 {
19012     xmlSchemaAttributeGroupPtr gr;
19013     xmlSchemaQNameRefPtr ref, circ;
19014     int i;
19015     /*
19016     * We will search for an attribute group reference which
19017     * references the context attribute group.
19018     */
19019     for (i = 0; i < list->nbItems; i++) {
19020         ref = list->items[i];
19021         if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19022             (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
19023             (ref->item != NULL))
19024         {
19025             gr = WXS_ATTR_GROUP_CAST ref->item;
19026             if (gr == ctxtGr)
19027                 return(ref);
19028             if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
19029                 continue;
19030             /*
19031             * Mark as visited to avoid infinite recursion on
19032             * circular references not yet examined.
19033             */
19034             if ((gr->attrUses) &&
19035                 (gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
19036             {
19037                 gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
19038                 circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
19039                     (xmlSchemaItemListPtr) gr->attrUses);
19040                 gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
19041                 if (circ != NULL)
19042                     return (circ);
19043             }
19044
19045         }
19046     }
19047     return (NULL);
19048 }
19049
19050 /**
19051  * xmlSchemaCheckAttrGroupCircular:
19052  * attrGr:  the attribute group definition
19053  * @ctxt:  the parser context
19054  * @name:  the name
19055  *
19056  * Checks for circular references of attribute groups.
19057  */
19058 static int
19059 xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
19060                                 xmlSchemaParserCtxtPtr ctxt)
19061 {
19062     /*
19063     * Schema Representation Constraint:
19064     * Attribute Group Definition Representation OK
19065     * 3 Circular group reference is disallowed outside <redefine>.
19066     * That is, unless this element information item's parent is
19067     * <redefine>, then among the [children], if any, there must
19068     * not be an <attributeGroup> with ref [attribute] which resolves
19069     * to the component corresponding to this <attributeGroup>. Indirect
19070     * circularity is also ruled out. That is, when QName resolution
19071     * (Schema Document) (�3.15.3) is applied to a ï¿½QName� arising from
19072     * any <attributeGroup>s with a ref [attribute] among the [children],
19073     * it must not be the case that a ï¿½QName� is encountered at any depth
19074     * which resolves to the component corresponding to this <attributeGroup>.
19075     */
19076     if (attrGr->attrUses == NULL)
19077         return(0);
19078     else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
19079         return(0);
19080     else {
19081         xmlSchemaQNameRefPtr circ;
19082
19083         circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
19084             (xmlSchemaItemListPtr) attrGr->attrUses);
19085         if (circ != NULL) {
19086             xmlChar *str = NULL;
19087             /*
19088             * TODO: Report the referenced attr group as QName.
19089             */
19090             xmlSchemaPCustomErr(ctxt,
19091                 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
19092                 NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
19093                 "Circular reference to the attribute group '%s' "
19094                 "defined", xmlSchemaGetComponentQName(&str, attrGr));
19095             FREE_AND_NULL(str);
19096             /*
19097             * NOTE: We will cut the reference to avoid further
19098             * confusion of the processor.
19099             * BADSPEC TODO: The spec should define how to process in this case.
19100             */
19101             circ->item = NULL;
19102             return(ctxt->err);
19103         }
19104     }
19105     return(0);
19106 }
19107
19108 static int
19109 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19110                                   xmlSchemaAttributeGroupPtr attrGr);
19111
19112 /**
19113  * xmlSchemaExpandAttributeGroupRefs:
19114  * @pctxt: the parser context
19115  * @node: the node of the component holding the attribute uses
19116  * @completeWild: the intersected wildcard to be returned
19117  * @list: the attribute uses
19118  *
19119  * Substitutes contained attribute group references
19120  * for their attribute uses. Wilcards are intersected.
19121  * Attribute use prohibitions are removed from the list
19122  * and returned via the @prohibs list.
19123  * Pointlessness of attr. prohibs, if a matching attr. decl
19124  * is existent a well, are checked.
19125  */
19126 static int
19127 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19128                                   xmlSchemaBasicItemPtr item,
19129                                   xmlSchemaWildcardPtr *completeWild,
19130                                   xmlSchemaItemListPtr list,
19131                                   xmlSchemaItemListPtr prohibs)
19132 {
19133     xmlSchemaAttributeGroupPtr gr;
19134     xmlSchemaAttributeUsePtr use;
19135     xmlSchemaItemListPtr sublist;
19136     int i, j;
19137     int created = (*completeWild == NULL) ? 0 : 1;
19138
19139     if (prohibs)
19140         prohibs->nbItems = 0;
19141
19142     for (i = 0; i < list->nbItems; i++) {
19143         use = list->items[i];
19144
19145         if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19146             if (prohibs == NULL) {
19147                 PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19148                     "unexpected attr prohibition found");
19149                 return(-1);
19150             }
19151             /*
19152             * Remove from attribute uses.
19153             */
19154             if (xmlSchemaItemListRemove(list, i) == -1)
19155                 return(-1);
19156             i--;
19157             /*
19158             * Note that duplicate prohibitions were already
19159             * handled at parsing time.
19160             */
19161             /*
19162             * Add to list of prohibitions.
19163             */
19164             xmlSchemaItemListAddSize(prohibs, 2, use);
19165             continue;
19166         }
19167         if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19168             ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19169         {
19170             if ((WXS_QNAME_CAST use)->item == NULL)
19171                 return(-1);
19172             gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19173             /*
19174             * Expand the referenced attr. group.
19175             * TODO: remove this, this is done in a previous step, so
19176             * already done here.
19177             */
19178             if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19179                 if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19180                     return(-1);
19181             }
19182             /*
19183             * Build the 'complete' wildcard; i.e. intersect multiple
19184             * wildcards.
19185             */
19186             if (gr->attributeWildcard != NULL) {
19187                 if (*completeWild == NULL) {
19188                     *completeWild = gr->attributeWildcard;
19189                 } else {
19190                     if (! created) {
19191                         xmlSchemaWildcardPtr tmpWild;
19192
19193                          /*
19194                         * Copy the first encountered wildcard as context,
19195                         * except for the annotation.
19196                         *
19197                         * Although the complete wildcard might not correspond
19198                         * to any node in the schema, we will anchor it on
19199                         * the node of the owner component.
19200                         */
19201                         tmpWild =  xmlSchemaAddWildcard(pctxt, pctxt->schema,
19202                             XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19203                             WXS_ITEM_NODE(item));
19204                         if (tmpWild == NULL)
19205                             return(-1);
19206                         if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19207                             tmpWild, *completeWild) == -1)
19208                             return (-1);
19209                         tmpWild->processContents = (*completeWild)->processContents;
19210                         *completeWild = tmpWild;
19211                         created = 1;
19212                     }
19213
19214                     if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19215                         gr->attributeWildcard) == -1)
19216                         return(-1);
19217                 }
19218             }
19219             /*
19220             * Just remove the reference if the referenced group does not
19221             * contain any attribute uses.
19222             */
19223             sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19224             if ((sublist == NULL) || sublist->nbItems == 0) {
19225                 if (xmlSchemaItemListRemove(list, i) == -1)
19226                     return(-1);
19227                 i--;
19228                 continue;
19229             }
19230             /*
19231             * Add the attribute uses.
19232             */
19233             list->items[i] = sublist->items[0];
19234             if (sublist->nbItems != 1) {
19235                 for (j = 1; j < sublist->nbItems; j++) {
19236                     i++;
19237                     if (xmlSchemaItemListInsert(list,
19238                             sublist->items[j], i) == -1)
19239                         return(-1);
19240                 }
19241             }
19242         }
19243
19244     }
19245     /*
19246     * Handle pointless prohibitions of declared attributes.
19247     */
19248     if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19249         xmlSchemaAttributeUseProhibPtr prohib;
19250
19251         for (i = prohibs->nbItems -1; i >= 0; i--) {
19252             prohib = prohibs->items[i];
19253             for (j = 0; j < list->nbItems; j++) {
19254                 use = list->items[j];
19255
19256                 if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19257                     (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19258                 {
19259                     xmlChar *str = NULL;
19260
19261                     xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19262                         XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19263                         prohib->node, NULL,
19264                         "Skipping pointless attribute use prohibition "
19265                         "'%s', since a corresponding attribute use "
19266                         "exists already in the type definition",
19267                         xmlSchemaFormatQName(&str,
19268                             prohib->targetNamespace, prohib->name),
19269                         NULL, NULL);
19270                     FREE_AND_NULL(str);
19271                     /*
19272                     * Remove the prohibition.
19273                     */
19274                     if (xmlSchemaItemListRemove(prohibs, i) == -1)
19275                         return(-1);
19276                     break;
19277                 }
19278             }
19279         }
19280     }
19281     return(0);
19282 }
19283
19284 /**
19285  * xmlSchemaAttributeGroupExpandRefs:
19286  * @pctxt:  the parser context
19287  * @attrGr:  the attribute group definition
19288  *
19289  * Computation of:
19290  * {attribute uses} property
19291  * {attribute wildcard} property
19292  *
19293  * Substitutes contained attribute group references
19294  * for their attribute uses. Wilcards are intersected.
19295  */
19296 static int
19297 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19298                                   xmlSchemaAttributeGroupPtr attrGr)
19299 {
19300     if ((attrGr->attrUses == NULL) ||
19301         (attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19302         return(0);
19303
19304     attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19305     if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19306         &(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19307         return(-1);
19308     return(0);
19309 }
19310
19311 /**
19312  * xmlSchemaAttributeGroupExpandRefs:
19313  * @pctxt:  the parser context
19314  * @attrGr:  the attribute group definition
19315  *
19316  * Substitutes contained attribute group references
19317  * for their attribute uses. Wilcards are intersected.
19318  *
19319  * Schema Component Constraint:
19320  *    Attribute Group Definition Properties Correct (ag-props-correct)
19321  */
19322 static int
19323 xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19324                                   xmlSchemaAttributeGroupPtr attrGr)
19325 {
19326     /*
19327     * SPEC ag-props-correct
19328     * (1) "The values of the properties of an attribute group definition
19329     * must be as described in the property tableau in The Attribute
19330     * Group Definition Schema Component (�3.6.1), modulo the impact of
19331     * Missing Sub-components (�5.3);"
19332     */
19333
19334     if ((attrGr->attrUses != NULL) &&
19335         (WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19336     {
19337         xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19338         xmlSchemaAttributeUsePtr use, tmp;
19339         int i, j, hasId = 0;
19340
19341         for (i = uses->nbItems -1; i >= 0; i--) {
19342             use = uses->items[i];
19343             /*
19344             * SPEC ag-props-correct
19345             * (2) "Two distinct members of the {attribute uses} must not have
19346             * {attribute declaration}s both of whose {name}s match and whose
19347             * {target namespace}s are identical."
19348             */
19349             if (i > 0) {
19350                 for (j = i -1; j >= 0; j--) {
19351                     tmp = uses->items[j];
19352                     if ((WXS_ATTRUSE_DECL_NAME(use) ==
19353                         WXS_ATTRUSE_DECL_NAME(tmp)) &&
19354                         (WXS_ATTRUSE_DECL_TNS(use) ==
19355                         WXS_ATTRUSE_DECL_TNS(tmp)))
19356                     {
19357                         xmlChar *str = NULL;
19358
19359                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
19360                             XML_SCHEMAP_AG_PROPS_CORRECT,
19361                             attrGr->node, WXS_BASIC_CAST attrGr,
19362                             "Duplicate %s",
19363                             xmlSchemaGetComponentDesignation(&str, use),
19364                             NULL);
19365                         FREE_AND_NULL(str);
19366                         /*
19367                         * Remove the duplicate.
19368                         */
19369                         if (xmlSchemaItemListRemove(uses, i) == -1)
19370                             return(-1);
19371                         goto next_use;
19372                     }
19373                 }
19374             }
19375             /*
19376             * SPEC ag-props-correct
19377             * (3) "Two distinct members of the {attribute uses} must not have
19378             * {attribute declaration}s both of whose {type definition}s are or
19379             * are derived from ID."
19380             * TODO: Does 'derived' include member-types of unions?
19381             */
19382             if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19383                 if (xmlSchemaIsDerivedFromBuiltInType(
19384                     WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19385                 {
19386                     if (hasId) {
19387                         xmlChar *str = NULL;
19388
19389                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
19390                             XML_SCHEMAP_AG_PROPS_CORRECT,
19391                             attrGr->node, WXS_BASIC_CAST attrGr,
19392                             "There must not exist more than one attribute "
19393                             "declaration of type 'xs:ID' "
19394                             "(or derived from 'xs:ID'). The %s violates this "
19395                             "constraint",
19396                             xmlSchemaGetComponentDesignation(&str, use),
19397                             NULL);
19398                         FREE_AND_NULL(str);
19399                         if (xmlSchemaItemListRemove(uses, i) == -1)
19400                             return(-1);
19401                     }
19402                     hasId = 1;
19403                 }
19404             }
19405 next_use: {}
19406         }
19407     }
19408     return(0);
19409 }
19410
19411 /**
19412  * xmlSchemaResolveAttrGroupReferences:
19413  * @attrgrpDecl:  the schema attribute definition
19414  * @ctxt:  the schema parser context
19415  * @name:  the attribute name
19416  *
19417  * Resolves references to attribute group definitions.
19418  */
19419 static int
19420 xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19421                                     xmlSchemaParserCtxtPtr ctxt)
19422 {
19423     xmlSchemaAttributeGroupPtr group;
19424
19425     if (ref->item != NULL)
19426         return(0);
19427     group = xmlSchemaGetAttributeGroup(ctxt->schema,
19428         ref->name,
19429         ref->targetNamespace);
19430     if (group == NULL) {
19431         xmlSchemaPResCompAttrErr(ctxt,
19432             XML_SCHEMAP_SRC_RESOLVE,
19433             NULL, ref->node,
19434             "ref", ref->name, ref->targetNamespace,
19435             ref->itemType, NULL);
19436         return(ctxt->err);
19437     }
19438     ref->item = WXS_BASIC_CAST group;
19439     return(0);
19440 }
19441
19442 /**
19443  * xmlSchemaCheckAttrPropsCorrect:
19444  * @item:  an schema attribute declaration/use
19445  * @ctxt:  a schema parser context
19446  * @name:  the name of the attribute
19447  *
19448  *
19449  * Schema Component Constraint:
19450  *    Attribute Declaration Properties Correct (a-props-correct)
19451  *
19452  * Validates the value constraints of an attribute declaration/use.
19453  * NOTE that this needs the simle type definitions to be already
19454  *   builded and checked.
19455  */
19456 static int
19457 xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19458                                xmlSchemaAttributePtr attr)
19459 {
19460
19461     /*
19462     * SPEC a-props-correct (1)
19463     * "The values of the properties of an attribute declaration must
19464     * be as described in the property tableau in The Attribute
19465     * Declaration Schema Component (�3.2.1), modulo the impact of
19466     * Missing Sub-components (�5.3)."
19467     */
19468
19469     if (WXS_ATTR_TYPEDEF(attr) == NULL)
19470         return(0);
19471
19472     if (attr->defValue != NULL) {
19473         int ret;
19474
19475         /*
19476         * SPEC a-props-correct (3)
19477         * "If the {type definition} is or is derived from ID then there
19478         * must not be a {value constraint}."
19479         */
19480         if (xmlSchemaIsDerivedFromBuiltInType(
19481             WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19482         {
19483             xmlSchemaCustomErr(ACTXT_CAST pctxt,
19484                 XML_SCHEMAP_A_PROPS_CORRECT_3,
19485                 NULL, WXS_BASIC_CAST attr,
19486                 "Value constraints are not allowed if the type definition "
19487                 "is or is derived from xs:ID",
19488                 NULL, NULL);
19489             return(pctxt->err);
19490         }
19491         /*
19492         * SPEC a-props-correct (2)
19493         * "if there is a {value constraint}, the canonical lexical
19494         * representation of its value must be ï¿½valid� with respect
19495         * to the {type definition} as defined in String Valid (�3.14.4)."
19496         * TODO: Don't care about the *cononical* stuff here, this requirement
19497         * will be removed in WXS 1.1 anyway.
19498         */
19499         ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
19500             attr->node, WXS_ATTR_TYPEDEF(attr),
19501             attr->defValue, &(attr->defVal),
19502             1, 1, 0);
19503         if (ret != 0) {
19504             if (ret < 0) {
19505                 PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
19506                     "calling xmlSchemaVCheckCVCSimpleType()");
19507                 return(-1);
19508             }
19509             xmlSchemaCustomErr(ACTXT_CAST pctxt,
19510                 XML_SCHEMAP_A_PROPS_CORRECT_2,
19511                 NULL, WXS_BASIC_CAST attr,
19512                 "The value of the value constraint is not valid",
19513                 NULL, NULL);
19514             return(pctxt->err);
19515         }
19516     }
19517
19518     return(0);
19519 }
19520
19521 static xmlSchemaElementPtr
19522 xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19523                                  xmlSchemaElementPtr ancestor)
19524 {
19525     xmlSchemaElementPtr ret;
19526
19527     if (WXS_SUBST_HEAD(ancestor) == NULL)
19528         return (NULL);
19529     if (WXS_SUBST_HEAD(ancestor) == elemDecl)
19530         return (ancestor);
19531
19532     if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
19533         return (NULL);
19534     WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
19535     ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
19536         WXS_SUBST_HEAD(ancestor));
19537     WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
19538
19539     return (ret);
19540 }
19541
19542 /**
19543  * xmlSchemaCheckElemPropsCorrect:
19544  * @ctxt:  a schema parser context
19545  * @decl: the element declaration
19546  * @name:  the name of the attribute
19547  *
19548  * Schema Component Constraint:
19549  * Element Declaration Properties Correct (e-props-correct)
19550  *
19551  * STATUS:
19552  *   missing: (6)
19553  */
19554 static int
19555 xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19556                                xmlSchemaElementPtr elemDecl)
19557 {
19558     int ret = 0;
19559     xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
19560     /*
19561     * SPEC (1) "The values of the properties of an element declaration
19562     * must be as described in the property tableau in The Element
19563     * Declaration Schema Component (�3.3.1), modulo the impact of Missing
19564     * Sub-components (�5.3)."
19565     */
19566     if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19567         xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
19568
19569         xmlSchemaCheckElementDeclComponent(head, pctxt);
19570         /*
19571         * SPEC (3) "If there is a non-�absent� {substitution group
19572         * affiliation}, then {scope} must be global."
19573         */
19574         if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19575             xmlSchemaPCustomErr(pctxt,
19576                 XML_SCHEMAP_E_PROPS_CORRECT_3,
19577                 WXS_BASIC_CAST elemDecl, NULL,
19578                 "Only global element declarations can have a "
19579                 "substitution group affiliation", NULL);
19580             ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
19581         }
19582         /*
19583         * TODO: SPEC (6) "Circular substitution groups are disallowed.
19584         * That is, it must not be possible to return to an element declaration
19585         * by repeatedly following the {substitution group affiliation}
19586         * property."
19587         */
19588         if (head == elemDecl)
19589             circ = head;
19590         else if (WXS_SUBST_HEAD(head) != NULL)
19591             circ = xmlSchemaCheckSubstGroupCircular(head, head);
19592         else
19593             circ = NULL;
19594         if (circ != NULL) {
19595             xmlChar *strA = NULL, *strB = NULL;
19596
19597             xmlSchemaPCustomErrExt(pctxt,
19598                 XML_SCHEMAP_E_PROPS_CORRECT_6,
19599                 WXS_BASIC_CAST circ, NULL,
19600                 "The element declaration '%s' defines a circular "
19601                 "substitution group to element declaration '%s'",
19602                 xmlSchemaGetComponentQName(&strA, circ),
19603                 xmlSchemaGetComponentQName(&strB, head),
19604                 NULL);
19605             FREE_AND_NULL(strA)
19606             FREE_AND_NULL(strB)
19607             ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19608         }
19609         /*
19610         * SPEC (4) "If there is a {substitution group affiliation},
19611         * the {type definition}
19612         * of the element declaration must be validly derived from the {type
19613         * definition} of the {substitution group affiliation}, given the value
19614         * of the {substitution group exclusions} of the {substitution group
19615         * affiliation}, as defined in Type Derivation OK (Complex) (�3.4.6)
19616         * (if the {type definition} is complex) or as defined in
19617         * Type Derivation OK (Simple) (�3.14.6) (if the {type definition} is
19618         * simple)."
19619         *
19620         * NOTE: {substitution group exclusions} means the values of the
19621         * attribute "final".
19622         */
19623
19624         if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
19625             int set = 0;
19626
19627             if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19628                 set |= SUBSET_EXTENSION;
19629             if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19630                 set |= SUBSET_RESTRICTION;
19631
19632             if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
19633                 WXS_ELEM_TYPEDEF(head), set) != 0) {
19634                 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19635
19636                 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
19637                 xmlSchemaPCustomErrExt(pctxt,
19638                     XML_SCHEMAP_E_PROPS_CORRECT_4,
19639                     WXS_BASIC_CAST elemDecl, NULL,
19640                     "The type definition '%s' was "
19641                     "either rejected by the substitution group "
19642                     "affiliation '%s', or not validly derived from its type "
19643                     "definition '%s'",
19644                     xmlSchemaGetComponentQName(&strA, typeDef),
19645                     xmlSchemaGetComponentQName(&strB, head),
19646                     xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
19647                 FREE_AND_NULL(strA)
19648                 FREE_AND_NULL(strB)
19649                 FREE_AND_NULL(strC)
19650             }
19651         }
19652     }
19653     /*
19654     * SPEC (5) "If the {type definition} or {type definition}'s
19655     * {content type}
19656     * is or is derived from ID then there must not be a {value constraint}.
19657     * Note: The use of ID as a type definition for elements goes beyond
19658     * XML 1.0, and should be avoided if backwards compatibility is desired"
19659     */
19660     if ((elemDecl->value != NULL) &&
19661         ((WXS_IS_SIMPLE(typeDef) &&
19662           xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
19663          (WXS_IS_COMPLEX(typeDef) &&
19664           WXS_HAS_SIMPLE_CONTENT(typeDef) &&
19665           xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19666             XML_SCHEMAS_ID)))) {
19667
19668         ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19669         xmlSchemaPCustomErr(pctxt,
19670             XML_SCHEMAP_E_PROPS_CORRECT_5,
19671             WXS_BASIC_CAST elemDecl, NULL,
19672             "The type definition (or type definition's content type) is or "
19673             "is derived from ID; value constraints are not allowed in "
19674             "conjunction with such a type definition", NULL);
19675     } else if (elemDecl->value != NULL) {
19676         int vcret;
19677         xmlNodePtr node = NULL;
19678
19679         /*
19680         * SPEC (2) "If there is a {value constraint}, the canonical lexical
19681         * representation of its value must be ï¿½valid� with respect to the
19682         * {type definition} as defined in Element Default Valid (Immediate)
19683         * (�3.3.6)."
19684         */
19685         if (typeDef == NULL) {
19686             xmlSchemaPErr(pctxt, elemDecl->node,
19687                 XML_SCHEMAP_INTERNAL,
19688                 "Internal error: xmlSchemaCheckElemPropsCorrect, "
19689                 "type is missing... skipping validation of "
19690                 "the value constraint", NULL, NULL);
19691             return (-1);
19692         }
19693         if (elemDecl->node != NULL) {
19694             if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19695                 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19696                     BAD_CAST "fixed");
19697             else
19698                 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19699                     BAD_CAST "default");
19700         }
19701         vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19702             typeDef, elemDecl->value, &(elemDecl->defVal));
19703         if (vcret != 0) {
19704             if (vcret < 0) {
19705                 PERROR_INT("xmlSchemaElemCheckValConstr",
19706                     "failed to validate the value constraint of an "
19707                     "element declaration");
19708                 return (-1);
19709             }
19710             return (vcret);
19711         }
19712     }
19713
19714     return (ret);
19715 }
19716
19717 /**
19718  * xmlSchemaCheckElemSubstGroup:
19719  * @ctxt:  a schema parser context
19720  * @decl: the element declaration
19721  * @name:  the name of the attribute
19722  *
19723  * Schema Component Constraint:
19724  * Substitution Group (cos-equiv-class)
19725  *
19726  * In Libxml2 the subst. groups will be precomputed, in terms of that
19727  * a list will be built for each subst. group head, holding all direct
19728  * referents to this head.
19729  * NOTE that this function needs:
19730  *   1. circular subst. groups to be checked beforehand
19731  *   2. the declaration's type to be derived from the head's type
19732  *
19733  * STATUS:
19734  *
19735  */
19736 static void
19737 xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19738                              xmlSchemaElementPtr elemDecl)
19739 {
19740     if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
19741         /* SPEC (1) "Its {abstract} is false." */
19742         (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19743         return;
19744     {
19745         xmlSchemaElementPtr head;
19746         xmlSchemaTypePtr headType, type;
19747         int set, methSet;
19748         /*
19749         * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19750         * {disallowed substitutions} as the blocking constraint, as defined in
19751         * Substitution Group OK (Transitive) (�3.3.6)."
19752         */
19753         for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19754             head = WXS_SUBST_HEAD(head)) {
19755             set = 0;
19756             methSet = 0;
19757             /*
19758             * The blocking constraints.
19759             */
19760             if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19761                 continue;
19762             headType = head->subtypes;
19763             type = elemDecl->subtypes;
19764             if (headType == type)
19765                 goto add_member;
19766             if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19767                 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19768             if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19769                 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19770             /*
19771             * SPEC: Substitution Group OK (Transitive) (2.3)
19772             * "The set of all {derivation method}s involved in the
19773             * derivation of D's {type definition} from C's {type definition}
19774             * does not intersect with the union of the blocking constraint,
19775             * C's {prohibited substitutions} (if C is complex, otherwise the
19776             * empty set) and the {prohibited substitutions} (respectively the
19777             * empty set) of any intermediate {type definition}s in the
19778             * derivation of D's {type definition} from C's {type definition}."
19779             */
19780             /*
19781             * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19782             * subst.head axis, the methSet does not need to be computed for
19783             * the full depth over and over.
19784             */
19785             /*
19786             * The set of all {derivation method}s involved in the derivation
19787             */
19788             while ((type != NULL) && (type != headType)) {
19789                 if ((WXS_IS_EXTENSION(type)) &&
19790                     ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19791                     methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19792
19793                 if (WXS_IS_RESTRICTION(type) &&
19794                     ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19795                     methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19796
19797                 type = type->baseType;
19798             }
19799             /*
19800             * The {prohibited substitutions} of all intermediate types +
19801             * the head's type.
19802             */
19803             type = elemDecl->subtypes->baseType;
19804             while (type != NULL) {
19805                 if (WXS_IS_COMPLEX(type)) {
19806                     if ((type->flags &
19807                             XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19808                         ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19809                     set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19810                     if ((type->flags &
19811                             XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19812                         ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19813                     set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19814                 } else
19815                     break;
19816                 if (type == headType)
19817                     break;
19818                 type = type->baseType;
19819             }
19820             if ((set != 0) &&
19821                 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19822                 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19823                 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19824                 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19825                 continue;
19826             }
19827 add_member:
19828             xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19829             if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19830                 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19831         }
19832     }
19833 }
19834
19835 #ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */
19836 /**
19837  * xmlSchemaCheckElementDeclComponent
19838  * @pctxt: the schema parser context
19839  * @ctxtComponent: the context component (an element declaration)
19840  * @ctxtParticle: the first particle of the context component
19841  * @searchParticle: the element declaration particle to be analysed
19842  *
19843  * Schema Component Constraint: Element Declarations Consistent
19844  */
19845 static int
19846 xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,
19847                                     xmlSchemaBasicItemPtr ctxtComponent,
19848                                     xmlSchemaParticlePtr ctxtParticle,
19849                                     xmlSchemaParticlePtr searchParticle,
19850                                     xmlSchemaParticlePtr curParticle,
19851                                     int search)
19852 {
19853     return(0);
19854
19855     int ret = 0;
19856     xmlSchemaParticlePtr cur = curParticle;
19857     if (curParticle == NULL) {
19858         return(0);
19859     }
19860     if (WXS_PARTICLE_TERM(curParticle) == NULL) {
19861         /*
19862         * Just return in this case. A missing "term" of the particle
19863         * might arise due to an invalid "term" component.
19864         */
19865         return(0);
19866     }
19867     while (cur != NULL) {
19868         switch (WXS_PARTICLE_TERM(cur)->type) {
19869             case XML_SCHEMA_TYPE_ANY:
19870                 break;
19871             case XML_SCHEMA_TYPE_ELEMENT:
19872                 if (search == 0) {
19873                     ret = xmlSchemaCheckElementDeclConsistent(pctxt,
19874                         ctxtComponent, ctxtParticle, cur, ctxtParticle, 1);
19875                     if (ret != 0)
19876                         return(ret);
19877                 } else {
19878                     xmlSchemaElementPtr elem =
19879                         WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur));
19880                     /*
19881                     * SPEC Element Declarations Consistent:
19882                     * "If the {particles} contains, either directly,
19883                     * indirectly (that is, within the {particles} of a
19884                     * contained model group, recursively) or ï¿½implicitly�
19885                     * two or more element declaration particles with
19886                     * the same {name} and {target namespace}, then
19887                     * all their type definitions must be the same
19888                     * top-level definition [...]"
19889                     */
19890                     if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name,
19891                             WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) &&
19892                         xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19893                             WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace))
19894                     {
19895                         xmlChar *strA = NULL, *strB = NULL;
19896
19897                         xmlSchemaCustomErr(ACTXT_CAST pctxt,
19898                             /* TODO: error code */
19899                             XML_SCHEMAP_COS_NONAMBIG,
19900                             WXS_ITEM_NODE(cur), NULL,
19901                             "In the content model of %s, there are multiple "
19902                             "element declarations for '%s' with different "
19903                             "type definitions",
19904                             xmlSchemaGetComponentDesignation(&strA,
19905                                 ctxtComponent),
19906                             xmlSchemaFormatQName(&strB,
19907                                 WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19908                                 WXS_PARTICLE_TERM_AS_ELEM(cur)->name));
19909                         FREE_AND_NULL(strA);
19910                         FREE_AND_NULL(strB);
19911                         return(XML_SCHEMAP_COS_NONAMBIG);
19912                     }
19913                 }
19914                 break;
19915             case XML_SCHEMA_TYPE_SEQUENCE: {
19916                 break;
19917                 }
19918             case XML_SCHEMA_TYPE_CHOICE:{
19919                 /*
19920                 xmlSchemaTreeItemPtr sub;
19921
19922                 sub = WXS_PARTICLE_TERM(particle)->children;  (xmlSchemaParticlePtr)
19923                 while (sub != NULL) {
19924                     ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent,
19925                         ctxtParticle, ctxtElem);
19926                     if (ret != 0)
19927                         return(ret);
19928                     sub = sub->next;
19929                 }
19930                 */
19931                 break;
19932                 }
19933             case XML_SCHEMA_TYPE_ALL:
19934                 break;
19935             case XML_SCHEMA_TYPE_GROUP:
19936                 break;
19937             default:
19938                 xmlSchemaInternalErr2(ACTXT_CAST pctxt,
19939                     "xmlSchemaCheckElementDeclConsistent",
19940                     "found unexpected term of type '%s' in content model",
19941                     WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL);
19942                 return(-1);
19943         }
19944         cur = (xmlSchemaParticlePtr) cur->next;
19945     }
19946
19947 exit:
19948     return(ret);
19949 }
19950 #endif
19951
19952 /**
19953  * xmlSchemaCheckElementDeclComponent
19954  * @item:  an schema element declaration/particle
19955  * @ctxt:  a schema parser context
19956  * @name:  the name of the attribute
19957  *
19958  * Validates the value constraints of an element declaration.
19959  * Adds substitution group members.
19960  */
19961 static void
19962 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
19963                                    xmlSchemaParserCtxtPtr ctxt)
19964 {
19965     if (elemDecl == NULL)
19966         return;
19967     if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
19968         return;
19969     elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
19970     if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) {
19971         /*
19972         * Adds substitution group members.
19973         */
19974         xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
19975     }
19976 }
19977
19978 /**
19979  * xmlSchemaResolveModelGroupParticleReferences:
19980  * @particle:  a particle component
19981  * @ctxt:  a parser context
19982  *
19983  * Resolves references of a model group's {particles} to
19984  * model group definitions and to element declarations.
19985  */
19986 static void
19987 xmlSchemaResolveModelGroupParticleReferences(
19988     xmlSchemaParserCtxtPtr ctxt,
19989     xmlSchemaModelGroupPtr mg)
19990 {
19991     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19992     xmlSchemaQNameRefPtr ref;
19993     xmlSchemaBasicItemPtr refItem;
19994
19995     /*
19996     * URGENT TODO: Test this.
19997     */
19998     while (particle != NULL) {
19999         if ((WXS_PARTICLE_TERM(particle) == NULL) ||
20000             ((WXS_PARTICLE_TERM(particle))->type !=
20001                 XML_SCHEMA_EXTRA_QNAMEREF))
20002         {
20003             goto next_particle;
20004         }
20005         ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
20006         /*
20007         * Resolve the reference.
20008         * NULL the {term} by default.
20009         */
20010         particle->children = NULL;
20011
20012         refItem = xmlSchemaGetNamedComponent(ctxt->schema,
20013             ref->itemType, ref->name, ref->targetNamespace);
20014         if (refItem == NULL) {
20015             xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
20016                 NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
20017                 ref->targetNamespace, ref->itemType, NULL);
20018             /* TODO: remove the particle. */
20019             goto next_particle;
20020         }
20021         if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
20022             if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
20023                 /* TODO: remove the particle. */
20024                 goto next_particle;
20025             /*
20026             * NOTE that we will assign the model group definition
20027             * itself to the "term" of the particle. This will ease
20028             * the check for circular model group definitions. After
20029             * that the "term" will be assigned the model group of the
20030             * model group definition.
20031             */
20032             if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
20033                     XML_SCHEMA_TYPE_ALL) {
20034                 /*
20035                 * SPEC cos-all-limited (1)
20036                 * SPEC cos-all-limited (1.2)
20037                 * "It appears only as the value of one or both of the
20038                 * following properties:"
20039                 * (1.1) "the {model group} property of a model group
20040                 *        definition."
20041                 * (1.2) "the {term} property of a particle [... of] the "
20042                 * {content type} of a complex type definition."
20043                 */
20044                 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20045                     /* TODO: error code */
20046                     XML_SCHEMAP_COS_ALL_LIMITED,
20047                     WXS_ITEM_NODE(particle), NULL,
20048                     "A model group definition is referenced, but "
20049                     "it contains an 'all' model group, which "
20050                     "cannot be contained by model groups",
20051                     NULL, NULL);
20052                 /* TODO: remove the particle. */
20053                 goto next_particle;
20054             }
20055             particle->children = (xmlSchemaTreeItemPtr) refItem;
20056         } else {
20057             /*
20058             * TODO: Are referenced element declarations the only
20059             * other components we expect here?
20060             */
20061             particle->children = (xmlSchemaTreeItemPtr) refItem;
20062         }
20063 next_particle:
20064         particle = WXS_PTC_CAST particle->next;
20065     }
20066 }
20067
20068 static int
20069 xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
20070                        xmlSchemaValPtr y)
20071 {
20072     xmlSchemaTypePtr tx, ty, ptx, pty;
20073     int ret;
20074
20075     while (x != NULL) {
20076         /* Same types. */
20077         tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
20078         ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
20079         ptx = xmlSchemaGetPrimitiveType(tx);
20080         pty = xmlSchemaGetPrimitiveType(ty);
20081         /*
20082         * (1) if a datatype T' is ï¿½derived� by ï¿½restriction� from an
20083         * atomic datatype T then the ï¿½value space� of T' is a subset of
20084         * the ï¿½value space� of T. */
20085         /*
20086         * (2) if datatypes T' and T'' are ï¿½derived� by ï¿½restriction�
20087         * from a common atomic ancestor T then the ï¿½value space�s of T'
20088         * and T'' may overlap.
20089         */
20090         if (ptx != pty)
20091             return(0);
20092         /*
20093         * We assume computed values to be normalized, so do a fast
20094         * string comparison for string based types.
20095         */
20096         if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
20097             WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
20098             if (! xmlStrEqual(
20099                 xmlSchemaValueGetAsString(x),
20100                 xmlSchemaValueGetAsString(y)))
20101                 return (0);
20102         } else {
20103             ret = xmlSchemaCompareValuesWhtsp(
20104                 x, XML_SCHEMA_WHITESPACE_PRESERVE,
20105                 y, XML_SCHEMA_WHITESPACE_PRESERVE);
20106             if (ret == -2)
20107                 return(-1);
20108             if (ret != 0)
20109                 return(0);
20110         }
20111         /*
20112         * Lists.
20113         */
20114         x = xmlSchemaValueGetNext(x);
20115         if (x != NULL) {
20116             y = xmlSchemaValueGetNext(y);
20117             if (y == NULL)
20118                 return (0);
20119         } else if (xmlSchemaValueGetNext(y) != NULL)
20120             return (0);
20121         else
20122             return (1);
20123     }
20124     return (0);
20125 }
20126
20127 /**
20128  * xmlSchemaResolveAttrUseReferences:
20129  * @item:  an attribute use
20130  * @ctxt:  a parser context
20131  *
20132  * Resolves the referenced attribute declaration.
20133  */
20134 static int
20135 xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
20136                                   xmlSchemaParserCtxtPtr ctxt)
20137 {
20138     if ((ctxt == NULL) || (ause == NULL))
20139         return(-1);
20140     if ((ause->attrDecl == NULL) ||
20141         (ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
20142         return(0);
20143
20144     {
20145         xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
20146
20147         /*
20148         * TODO: Evaluate, what errors could occur if the declaration is not
20149         * found.
20150         */
20151         ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
20152             ref->name, ref->targetNamespace);
20153         if (ause->attrDecl == NULL) {
20154             xmlSchemaPResCompAttrErr(ctxt,
20155                 XML_SCHEMAP_SRC_RESOLVE,
20156                 WXS_BASIC_CAST ause, ause->node,
20157                 "ref", ref->name, ref->targetNamespace,
20158                 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20159             return(ctxt->err);;
20160         }
20161     }
20162     return(0);
20163 }
20164
20165 /**
20166  * xmlSchemaCheckAttrUsePropsCorrect:
20167  * @ctxt:  a parser context
20168  * @use:  an attribute use
20169  *
20170  * Schema Component Constraint:
20171  * Attribute Use Correct (au-props-correct)
20172  *
20173  */
20174 static int
20175 xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
20176                              xmlSchemaAttributeUsePtr use)
20177 {
20178     if ((ctxt == NULL) || (use == NULL))
20179         return(-1);
20180     if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
20181         ((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
20182         return(0);
20183
20184     /*
20185     * SPEC au-props-correct (1)
20186     * "The values of the properties of an attribute use must be as
20187     * described in the property tableau in The Attribute Use Schema
20188     * Component (�3.5.1), modulo the impact of Missing
20189     * Sub-components (�5.3)."
20190     */
20191
20192     if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
20193         ((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
20194         ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20195     {
20196         xmlSchemaPCustomErr(ctxt,
20197             XML_SCHEMAP_AU_PROPS_CORRECT_2,
20198             WXS_BASIC_CAST use, NULL,
20199             "The attribute declaration has a 'fixed' value constraint "
20200             ", thus the attribute use must also have a 'fixed' value "
20201             "constraint",
20202             NULL);
20203         return(ctxt->err);
20204     }
20205     /*
20206     * Compute and check the value constraint's value.
20207     */
20208     if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
20209         int ret;
20210         /*
20211         * TODO: The spec seems to be missing a check of the
20212         * value constraint of the attribute use. We will do it here.
20213         */
20214         /*
20215         * SPEC a-props-correct (3)
20216         */
20217         if (xmlSchemaIsDerivedFromBuiltInType(
20218             WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20219         {
20220             xmlSchemaCustomErr(ACTXT_CAST ctxt,
20221                 XML_SCHEMAP_AU_PROPS_CORRECT,
20222                 NULL, WXS_BASIC_CAST use,
20223                 "Value constraints are not allowed if the type definition "
20224                 "is or is derived from xs:ID",
20225                 NULL, NULL);
20226             return(ctxt->err);
20227         }
20228
20229         ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20230             use->node, WXS_ATTRUSE_TYPEDEF(use),
20231             use->defValue, &(use->defVal),
20232             1, 1, 0);
20233         if (ret != 0) {
20234             if (ret < 0) {
20235                 PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20236                     "calling xmlSchemaVCheckCVCSimpleType()");
20237                 return(-1);
20238             }
20239             xmlSchemaCustomErr(ACTXT_CAST ctxt,
20240                 XML_SCHEMAP_AU_PROPS_CORRECT,
20241                 NULL, WXS_BASIC_CAST use,
20242                 "The value of the value constraint is not valid",
20243                 NULL, NULL);
20244             return(ctxt->err);
20245         }
20246     }
20247     /*
20248     * SPEC au-props-correct (2)
20249     * "If the {attribute declaration} has a fixed
20250     * {value constraint}, then if the attribute use itself has a
20251     * {value constraint}, it must also be fixed and its value must match
20252     * that of the {attribute declaration}'s {value constraint}."
20253     */
20254     if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20255         (((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20256     {
20257         if (! xmlSchemaAreValuesEqual(use->defVal,
20258                 (WXS_ATTRUSE_DECL(use))->defVal))
20259         {
20260             xmlSchemaPCustomErr(ctxt,
20261                 XML_SCHEMAP_AU_PROPS_CORRECT_2,
20262                 WXS_BASIC_CAST use, NULL,
20263                 "The 'fixed' value constraint of the attribute use "
20264                 "must match the attribute declaration's value "
20265                 "constraint '%s'",
20266                 (WXS_ATTRUSE_DECL(use))->defValue);
20267         }
20268         return(ctxt->err);
20269     }
20270     return(0);
20271 }
20272
20273
20274
20275
20276 /**
20277  * xmlSchemaResolveAttrTypeReferences:
20278  * @item:  an attribute declaration
20279  * @ctxt:  a parser context
20280  *
20281  * Resolves the referenced type definition component.
20282  */
20283 static int
20284 xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20285                                    xmlSchemaParserCtxtPtr ctxt)
20286 {
20287     /*
20288     * The simple type definition corresponding to the <simpleType> element
20289     * information item in the [children], if present, otherwise the simple
20290     * type definition ï¿½resolved� to by the ï¿½actual value� of the type
20291     * [attribute], if present, otherwise the ï¿½simple ur-type definition�.
20292     */
20293     if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
20294         return(0);
20295     item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20296     if (item->subtypes != NULL)
20297         return(0);
20298     if (item->typeName != NULL) {
20299         xmlSchemaTypePtr type;
20300
20301         type = xmlSchemaGetType(ctxt->schema, item->typeName,
20302             item->typeNs);
20303         if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
20304             xmlSchemaPResCompAttrErr(ctxt,
20305                 XML_SCHEMAP_SRC_RESOLVE,
20306                 WXS_BASIC_CAST item, item->node,
20307                 "type", item->typeName, item->typeNs,
20308                 XML_SCHEMA_TYPE_SIMPLE, NULL);
20309             return(ctxt->err);
20310         } else
20311             item->subtypes = type;
20312
20313     } else {
20314         /*
20315         * The type defaults to the xs:anySimpleType.
20316         */
20317         item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20318     }
20319     return(0);
20320 }
20321
20322 /**
20323  * xmlSchemaResolveIDCKeyReferences:
20324  * @idc:  the identity-constraint definition
20325  * @ctxt:  the schema parser context
20326  * @name:  the attribute name
20327  *
20328  * Resolve keyRef references to key/unique IDCs.
20329  * Schema Component Constraint:
20330  *   Identity-constraint Definition Properties Correct (c-props-correct)
20331  */
20332 static int
20333 xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
20334                           xmlSchemaParserCtxtPtr pctxt)
20335 {
20336     if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
20337         return(0);
20338     if (idc->ref->name != NULL) {
20339         idc->ref->item = (xmlSchemaBasicItemPtr)
20340             xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20341                 idc->ref->targetNamespace);
20342         if (idc->ref->item == NULL) {
20343             /*
20344             * TODO: It is actually not an error to fail to resolve
20345             * at this stage. BUT we need to be that strict!
20346             */
20347             xmlSchemaPResCompAttrErr(pctxt,
20348                 XML_SCHEMAP_SRC_RESOLVE,
20349                 WXS_BASIC_CAST idc, idc->node,
20350                 "refer", idc->ref->name,
20351                 idc->ref->targetNamespace,
20352                 XML_SCHEMA_TYPE_IDC_KEY, NULL);
20353             return(pctxt->err);
20354         } else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20355             /*
20356             * SPEC c-props-correct (1)
20357             */
20358             xmlSchemaCustomErr(ACTXT_CAST pctxt,
20359                 XML_SCHEMAP_C_PROPS_CORRECT,
20360                 NULL, WXS_BASIC_CAST idc,
20361                 "The keyref references a keyref",
20362                 NULL, NULL);
20363             idc->ref->item = NULL;
20364             return(pctxt->err);
20365         } else {
20366             if (idc->nbFields !=
20367                 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20368                 xmlChar *str = NULL;
20369                 xmlSchemaIDCPtr refer;
20370
20371                 refer = (xmlSchemaIDCPtr) idc->ref->item;
20372                 /*
20373                 * SPEC c-props-correct(2)
20374                 * "If the {identity-constraint category} is keyref,
20375                 * the cardinality of the {fields} must equal that of
20376                 * the {fields} of the {referenced key}.
20377                 */
20378                 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20379                     XML_SCHEMAP_C_PROPS_CORRECT,
20380                     NULL, WXS_BASIC_CAST idc,
20381                     "The cardinality of the keyref differs from the "
20382                     "cardinality of the referenced key/unique '%s'",
20383                     xmlSchemaFormatQName(&str, refer->targetNamespace,
20384                         refer->name),
20385                     NULL);
20386                 FREE_AND_NULL(str)
20387                 return(pctxt->err);
20388             }
20389         }
20390     }
20391     return(0);
20392 }
20393
20394 static int
20395 xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20396                                        xmlSchemaParserCtxtPtr pctxt)
20397 {
20398     if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20399         prohib->targetNamespace) == NULL) {
20400
20401         xmlSchemaPResCompAttrErr(pctxt,
20402             XML_SCHEMAP_SRC_RESOLVE,
20403             NULL, prohib->node,
20404             "ref", prohib->name, prohib->targetNamespace,
20405             XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20406         return(XML_SCHEMAP_SRC_RESOLVE);
20407     }
20408     return(0);
20409 }
20410
20411 #define WXS_REDEFINED_TYPE(c) \
20412 (((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20413
20414 #define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20415 (((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20416
20417 #define WXS_REDEFINED_ATTR_GROUP(c) \
20418 (((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20419
20420 static int
20421 xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20422 {
20423     int err = 0;
20424     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20425     xmlSchemaBasicItemPtr prev, item;
20426     int wasRedefined;
20427
20428     if (redef == NULL)
20429         return(0);
20430
20431     do {
20432         item = redef->item;
20433         /*
20434         * First try to locate the redefined component in the
20435         * schema graph starting with the redefined schema.
20436         * NOTE: According to this schema bug entry:
20437         *   http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20438         *   it's not clear if the referenced component needs to originate
20439         *   from the <redefine>d schema _document_ or the schema; the latter
20440         *   would include all imported and included sub-schemas of the
20441         *   <redefine>d schema. Currenlty we latter approach is used.
20442         *   SUPPLEMENT: It seems that the WG moves towards the latter
20443         *   approach, so we are doing it right.
20444         *
20445         */
20446         prev = xmlSchemaFindRedefCompInGraph(
20447             redef->targetBucket, item->type,
20448             redef->refName, redef->refTargetNs);
20449         if (prev == NULL) {
20450             xmlChar *str = NULL;
20451             xmlNodePtr node;
20452
20453             /*
20454             * SPEC src-redefine:
20455             * (6.2.1) "The ï¿½actual value� of its own name attribute plus
20456             * target namespace must successfully ï¿½resolve� to a model
20457             * group definition in I."
20458             * (7.2.1) "The ï¿½actual value� of its own name attribute plus
20459             * target namespace must successfully ï¿½resolve� to an attribute
20460             * group definition in I."
20461
20462             *
20463             * Note that, if we are redefining with the use of references
20464             * to components, the spec assumes the src-resolve to be used;
20465             * but this won't assure that we search only *inside* the
20466             * redefined schema.
20467             */
20468             if (redef->reference)
20469                 node = WXS_ITEM_NODE(redef->reference);
20470             else
20471                 node = WXS_ITEM_NODE(item);
20472             xmlSchemaCustomErr(ACTXT_CAST pctxt,
20473                 /*
20474                 * TODO: error code.
20475                 * Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20476                 * reference kind.
20477                 */
20478                 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
20479                 "The %s '%s' to be redefined could not be found in "
20480                 "the redefined schema",
20481                 WXS_ITEM_TYPE_NAME(item),
20482                 xmlSchemaFormatQName(&str, redef->refTargetNs,
20483                     redef->refName));
20484             FREE_AND_NULL(str);
20485             err = pctxt->err;
20486             redef = redef->next;
20487             continue;
20488         }
20489         /*
20490         * TODO: Obtaining and setting the redefinition state is really
20491         * clumsy.
20492         */
20493         wasRedefined = 0;
20494         switch (item->type) {
20495             case XML_SCHEMA_TYPE_COMPLEX:
20496             case XML_SCHEMA_TYPE_SIMPLE:
20497                 if ((WXS_TYPE_CAST prev)->flags &
20498                     XML_SCHEMAS_TYPE_REDEFINED)
20499                 {
20500                     wasRedefined = 1;
20501                     break;
20502                 }
20503                 /* Mark it as redefined. */
20504                 (WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20505                 /*
20506                 * Assign the redefined type to the
20507                 * base type of the redefining type.
20508                 * TODO: How
20509                 */
20510                 ((xmlSchemaTypePtr) item)->baseType =
20511                     (xmlSchemaTypePtr) prev;
20512                 break;
20513             case XML_SCHEMA_TYPE_GROUP:
20514                 if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20515                     XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20516                 {
20517                     wasRedefined = 1;
20518                     break;
20519                 }
20520                 /* Mark it as redefined. */
20521                 (WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20522                     XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20523                 if (redef->reference != NULL) {
20524                     /*
20525                     * Overwrite the QName-reference with the
20526                     * referenced model group def.
20527                     */
20528                     (WXS_PTC_CAST redef->reference)->children =
20529                         WXS_TREE_CAST prev;
20530                 }
20531                 redef->target = prev;
20532                 break;
20533             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20534                 if ((WXS_ATTR_GROUP_CAST prev)->flags &
20535                     XML_SCHEMAS_ATTRGROUP_REDEFINED)
20536                 {
20537                     wasRedefined = 1;
20538                     break;
20539                 }
20540                 (WXS_ATTR_GROUP_CAST prev)->flags |=
20541                     XML_SCHEMAS_ATTRGROUP_REDEFINED;
20542                 if (redef->reference != NULL) {
20543                     /*
20544                     * Assign the redefined attribute group to the
20545                     * QName-reference component.
20546                     * This is the easy case, since we will just
20547                     * expand the redefined group.
20548                     */
20549                     (WXS_QNAME_CAST redef->reference)->item = prev;
20550                     redef->target = NULL;
20551                 } else {
20552                     /*
20553                     * This is the complicated case: we need
20554                     * to apply src-redefine (7.2.2) at a later
20555                     * stage, i.e. when attribute group references
20556                     * have beed expanded and simple types have
20557                     * beed fixed.
20558                     */
20559                     redef->target = prev;
20560                 }
20561                 break;
20562             default:
20563                 PERROR_INT("xmlSchemaResolveRedefReferences",
20564                     "Unexpected redefined component type");
20565                 return(-1);
20566         }
20567         if (wasRedefined) {
20568             xmlChar *str = NULL;
20569             xmlNodePtr node;
20570
20571             if (redef->reference)
20572                 node = WXS_ITEM_NODE(redef->reference);
20573             else
20574                 node = WXS_ITEM_NODE(redef->item);
20575
20576             xmlSchemaCustomErr(ACTXT_CAST pctxt,
20577                 /* TODO: error code. */
20578                 XML_SCHEMAP_SRC_REDEFINE,
20579                 node, NULL,
20580                 "The referenced %s was already redefined. Multiple "
20581                 "redefinition of the same component is not supported",
20582                 xmlSchemaGetComponentDesignation(&str, prev),
20583                 NULL);
20584             FREE_AND_NULL(str)
20585             err = pctxt->err;
20586             redef = redef->next;
20587             continue;
20588         }
20589         redef = redef->next;
20590     } while (redef != NULL);
20591
20592     return(err);
20593 }
20594
20595 static int
20596 xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20597 {
20598     int err = 0;
20599     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20600     xmlSchemaBasicItemPtr item;
20601
20602     if (redef == NULL)
20603         return(0);
20604
20605     do {
20606         if (redef->target == NULL) {
20607             redef = redef->next;
20608             continue;
20609         }
20610         item = redef->item;
20611
20612         switch (item->type) {
20613             case XML_SCHEMA_TYPE_SIMPLE:
20614             case XML_SCHEMA_TYPE_COMPLEX:
20615                 /*
20616                 * Since the spec wants the {name} of the redefined
20617                 * type to be 'absent', we'll NULL it.
20618                 */
20619                 (WXS_TYPE_CAST redef->target)->name = NULL;
20620
20621                 /*
20622                 * TODO: Seems like there's nothing more to do. The normal
20623                 * inheritance mechanism is used. But not 100% sure.
20624                 */
20625                 break;
20626             case XML_SCHEMA_TYPE_GROUP:
20627                 /*
20628                 * URGENT TODO:
20629                 * SPEC src-redefine:
20630                 * (6.2.2) "The {model group} of the model group definition
20631                 * which corresponds to it per XML Representation of Model
20632                 * Group Definition Schema Components (�3.7.2) must be a
20633                 * ï¿½valid restriction� of the {model group} of that model
20634                 * group definition in I, as defined in Particle Valid
20635                 * (Restriction) (�3.9.6)."
20636                 */
20637                 break;
20638             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20639                 /*
20640                 * SPEC src-redefine:
20641                 * (7.2.2) "The {attribute uses} and {attribute wildcard} of
20642                 * the attribute group definition which corresponds to it
20643                 * per XML Representation of Attribute Group Definition Schema
20644                 * Components (�3.6.2) must be ï¿½valid restrictions� of the
20645                 * {attribute uses} and {attribute wildcard} of that attribute
20646                 * group definition in I, as defined in clause 2, clause 3 and
20647                 * clause 4 of Derivation Valid (Restriction, Complex)
20648                 * (�3.4.6) (where references to the base type definition are
20649                 * understood as references to the attribute group definition
20650                 * in I)."
20651                 */
20652                 err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20653                     XML_SCHEMA_ACTION_REDEFINE,
20654                     item, redef->target,
20655                     (WXS_ATTR_GROUP_CAST item)->attrUses,
20656                     (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20657                     (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20658                     (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20659                 if (err == -1)
20660                     return(-1);
20661                 break;
20662             default:
20663                 break;
20664         }
20665         redef = redef->next;
20666     } while (redef != NULL);
20667     return(0);
20668 }
20669
20670
20671 static int
20672 xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20673                        xmlSchemaBucketPtr bucket)
20674 {
20675     xmlSchemaBasicItemPtr item;
20676     int err;
20677     xmlHashTablePtr *table;
20678     const xmlChar *name;
20679     int i;
20680
20681 #define WXS_GET_GLOBAL_HASH(c, slot) { \
20682     if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20683         table = &(WXS_IMPBUCKET((c))->schema->slot); \
20684     else \
20685         table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20686
20687     /*
20688     * Add global components to the schema's hash tables.
20689     * This is the place where duplicate components will be
20690     * detected.
20691     * TODO: I think normally we should support imports of the
20692     *   same namespace from multiple locations. We don't do currently,
20693     *   but if we do then according to:
20694     *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20695     *   we would need, if imported directly, to import redefined
20696     *   components as well to be able to catch clashing components.
20697     *   (I hope I'll still know what this means after some months :-()
20698     */
20699     if (bucket == NULL)
20700         return(-1);
20701     if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20702         return(0);
20703     bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20704
20705     for (i = 0; i < bucket->globals->nbItems; i++) {
20706         item = bucket->globals->items[i];
20707         table = NULL;
20708         switch (item->type) {
20709             case XML_SCHEMA_TYPE_COMPLEX:
20710             case XML_SCHEMA_TYPE_SIMPLE:
20711                 if (WXS_REDEFINED_TYPE(item))
20712                     continue;
20713                 name = (WXS_TYPE_CAST item)->name;
20714                 WXS_GET_GLOBAL_HASH(bucket, typeDecl)
20715                 break;
20716             case XML_SCHEMA_TYPE_ELEMENT:
20717                 name = (WXS_ELEM_CAST item)->name;
20718                 WXS_GET_GLOBAL_HASH(bucket, elemDecl)
20719                 break;
20720             case XML_SCHEMA_TYPE_ATTRIBUTE:
20721                 name = (WXS_ATTR_CAST item)->name;
20722                 WXS_GET_GLOBAL_HASH(bucket, attrDecl)
20723                 break;
20724             case XML_SCHEMA_TYPE_GROUP:
20725                 if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20726                     continue;
20727                 name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20728                 WXS_GET_GLOBAL_HASH(bucket, groupDecl)
20729                 break;
20730             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20731                 if (WXS_REDEFINED_ATTR_GROUP(item))
20732                     continue;
20733                 name = (WXS_ATTR_GROUP_CAST item)->name;
20734                 WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
20735                 break;
20736             case XML_SCHEMA_TYPE_IDC_KEY:
20737             case XML_SCHEMA_TYPE_IDC_UNIQUE:
20738             case XML_SCHEMA_TYPE_IDC_KEYREF:
20739                 name = (WXS_IDC_CAST item)->name;
20740                 WXS_GET_GLOBAL_HASH(bucket, idcDef)
20741                 break;
20742             case XML_SCHEMA_TYPE_NOTATION:
20743                 name = ((xmlSchemaNotationPtr) item)->name;
20744                 WXS_GET_GLOBAL_HASH(bucket, notaDecl)
20745                 break;
20746             default:
20747                 PERROR_INT("xmlSchemaAddComponents",
20748                     "Unexpected global component type");
20749                 continue;
20750         }
20751         if (*table == NULL) {
20752             *table = xmlHashCreateDict(10, pctxt->dict);
20753             if (*table == NULL) {
20754                 PERROR_INT("xmlSchemaAddComponents",
20755                     "failed to create a component hash table");
20756                 return(-1);
20757             }
20758         }
20759         err = xmlHashAddEntry(*table, name, item);
20760         if (err != 0) {
20761             xmlChar *str = NULL;
20762
20763             xmlSchemaCustomErr(ACTXT_CAST pctxt,
20764                 XML_SCHEMAP_REDEFINED_TYPE,
20765                 WXS_ITEM_NODE(item),
20766                 WXS_BASIC_CAST item,
20767                 "A global %s '%s' does already exist",
20768                 WXS_ITEM_TYPE_NAME(item),
20769                 xmlSchemaGetComponentQName(&str, item));
20770             FREE_AND_NULL(str);
20771         }
20772     }
20773     /*
20774     * Process imported/included schemas.
20775     */
20776     if (bucket->relations != NULL) {
20777         xmlSchemaSchemaRelationPtr rel = bucket->relations;
20778         do {
20779             if ((rel->bucket != NULL) &&
20780                 ((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20781                 if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20782                     return(-1);
20783             }
20784             rel = rel->next;
20785         } while (rel != NULL);
20786     }
20787     return(0);
20788 }
20789
20790 static int
20791 xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20792                          xmlSchemaBucketPtr rootBucket)
20793 {
20794     xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20795     xmlSchemaTreeItemPtr item, *items;
20796     int nbItems, i, ret = 0;
20797     xmlSchemaBucketPtr oldbucket = con->bucket;
20798     xmlSchemaElementPtr elemDecl;
20799
20800 #define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20801
20802     if ((con->pending == NULL) ||
20803         (con->pending->nbItems == 0))
20804         return(0);
20805
20806     /*
20807     * Since xmlSchemaFixupComplexType() will create new particles
20808     * (local components), and those particle components need a bucket
20809     * on the constructor, we'll assure here that the constructor has
20810     * a bucket.
20811     * TODO: Think about storing locals _only_ on the main bucket.
20812     */
20813     if (con->bucket == NULL)
20814         con->bucket = rootBucket;
20815
20816     /* TODO:
20817     * SPEC (src-redefine):
20818     * (6.2) "If it has no such self-reference, then all of the
20819     * following must be true:"
20820
20821     * (6.2.2) The {model group} of the model group definition which
20822     * corresponds to it per XML Representation of Model Group
20823     * Definition Schema Components (�3.7.2) must be a ï¿½valid
20824     * restriction� of the {model group} of that model group definition
20825     * in I, as defined in Particle Valid (Restriction) (�3.9.6)."
20826     */
20827     xmlSchemaCheckSRCRedefineFirst(pctxt);
20828
20829     /*
20830     * Add global components to the schemata's hash tables.
20831     */
20832     xmlSchemaAddComponents(pctxt, rootBucket);
20833
20834     pctxt->ctxtType = NULL;
20835     items = (xmlSchemaTreeItemPtr *) con->pending->items;
20836     nbItems = con->pending->nbItems;
20837     /*
20838     * Now that we have parsed *all* the schema document(s) and converted
20839     * them to schema components, we can resolve references, apply component
20840     * constraints, create the FSA from the content model, etc.
20841     */
20842     /*
20843     * Resolve references of..
20844     *
20845     * 1. element declarations:
20846     *   - the type definition
20847     *   - the substitution group affiliation
20848     * 2. simple/complex types:
20849     *   - the base type definition
20850     *   - the memberTypes of union types
20851     *   - the itemType of list types
20852     * 3. attributes declarations and attribute uses:
20853     *   - the type definition
20854     *   - if an attribute use, then the attribute declaration
20855     * 4. attribute group references:
20856     *   - the attribute group definition
20857     * 5. particles:
20858     *   - the term of the particle (e.g. a model group)
20859     * 6. IDC key-references:
20860     *   - the referenced IDC 'key' or 'unique' definition
20861     * 7. Attribute prohibitions which had a "ref" attribute.
20862     */
20863     for (i = 0; i < nbItems; i++) {
20864         item = items[i];
20865         switch (item->type) {
20866             case XML_SCHEMA_TYPE_ELEMENT:
20867                 xmlSchemaResolveElementReferences(
20868                     (xmlSchemaElementPtr) item, pctxt);
20869                 FIXHFAILURE;
20870                 break;
20871             case XML_SCHEMA_TYPE_COMPLEX:
20872             case XML_SCHEMA_TYPE_SIMPLE:
20873                 xmlSchemaResolveTypeReferences(
20874                     (xmlSchemaTypePtr) item, pctxt);
20875                 FIXHFAILURE;
20876                 break;
20877             case XML_SCHEMA_TYPE_ATTRIBUTE:
20878                 xmlSchemaResolveAttrTypeReferences(
20879                     (xmlSchemaAttributePtr) item, pctxt);
20880                 FIXHFAILURE;
20881                 break;
20882             case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20883                 xmlSchemaResolveAttrUseReferences(
20884                     (xmlSchemaAttributeUsePtr) item, pctxt);
20885                 FIXHFAILURE;
20886                 break;
20887             case XML_SCHEMA_EXTRA_QNAMEREF:
20888                 if ((WXS_QNAME_CAST item)->itemType ==
20889                     XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20890                 {
20891                     xmlSchemaResolveAttrGroupReferences(
20892                         WXS_QNAME_CAST item, pctxt);
20893                 }
20894                 FIXHFAILURE;
20895                 break;
20896             case XML_SCHEMA_TYPE_SEQUENCE:
20897             case XML_SCHEMA_TYPE_CHOICE:
20898             case XML_SCHEMA_TYPE_ALL:
20899                 xmlSchemaResolveModelGroupParticleReferences(pctxt,
20900                     WXS_MODEL_GROUP_CAST item);
20901                 FIXHFAILURE;
20902                 break;
20903             case XML_SCHEMA_TYPE_IDC_KEY:
20904             case XML_SCHEMA_TYPE_IDC_UNIQUE:
20905             case XML_SCHEMA_TYPE_IDC_KEYREF:
20906                 xmlSchemaResolveIDCKeyReferences(
20907                     (xmlSchemaIDCPtr) item, pctxt);
20908                 FIXHFAILURE;
20909                 break;
20910             case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20911                 /*
20912                 * Handle attribue prohibition which had a
20913                 * "ref" attribute.
20914                 */
20915                 xmlSchemaResolveAttrUseProhibReferences(
20916                     WXS_ATTR_PROHIB_CAST item, pctxt);
20917                 FIXHFAILURE;
20918                 break;
20919             default:
20920                 break;
20921         }
20922     }
20923     if (pctxt->nberrors != 0)
20924         goto exit_error;
20925
20926     /*
20927     * Now that all references are resolved we
20928     * can check for circularity of...
20929     * 1. the base axis of type definitions
20930     * 2. nested model group definitions
20931     * 3. nested attribute group definitions
20932     * TODO: check for circual substitution groups.
20933     */
20934     for (i = 0; i < nbItems; i++) {
20935         item = items[i];
20936         /*
20937         * Let's better stop on the first error here.
20938         */
20939         switch (item->type) {
20940             case XML_SCHEMA_TYPE_COMPLEX:
20941             case XML_SCHEMA_TYPE_SIMPLE:
20942                 xmlSchemaCheckTypeDefCircular(
20943                     (xmlSchemaTypePtr) item, pctxt);
20944                 FIXHFAILURE;
20945                 if (pctxt->nberrors != 0)
20946                     goto exit_error;
20947                 break;
20948             case XML_SCHEMA_TYPE_GROUP:
20949                 xmlSchemaCheckGroupDefCircular(
20950                     (xmlSchemaModelGroupDefPtr) item, pctxt);
20951                 FIXHFAILURE;
20952                 if (pctxt->nberrors != 0)
20953                     goto exit_error;
20954                 break;
20955             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20956                 xmlSchemaCheckAttrGroupCircular(
20957                     (xmlSchemaAttributeGroupPtr) item, pctxt);
20958                 FIXHFAILURE;
20959                 if (pctxt->nberrors != 0)
20960                     goto exit_error;
20961                 break;
20962             default:
20963                 break;
20964         }
20965     }
20966     if (pctxt->nberrors != 0)
20967         goto exit_error;
20968     /*
20969     * Model group definition references:
20970     * Such a reference is reflected by a particle at the component
20971     * level. Until now the 'term' of such particles pointed
20972     * to the model group definition; this was done, in order to
20973     * ease circularity checks. Now we need to set the 'term' of
20974     * such particles to the model group of the model group definition.
20975     */
20976     for (i = 0; i < nbItems; i++) {
20977         item = items[i];
20978         switch (item->type) {
20979             case XML_SCHEMA_TYPE_SEQUENCE:
20980             case XML_SCHEMA_TYPE_CHOICE:
20981                 xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
20982                     WXS_MODEL_GROUP_CAST item);
20983                 break;
20984             default:
20985                 break;
20986         }
20987     }
20988     if (pctxt->nberrors != 0)
20989         goto exit_error;
20990     /*
20991     * Expand attribute group references of attribute group definitions.
20992     */
20993     for (i = 0; i < nbItems; i++) {
20994         item = items[i];
20995         switch (item->type) {
20996             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20997                 if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
20998                     WXS_ATTR_GROUP_HAS_REFS(item))
20999                 {
21000                     xmlSchemaAttributeGroupExpandRefs(pctxt,
21001                         WXS_ATTR_GROUP_CAST item);
21002                     FIXHFAILURE;
21003                 }
21004                 break;
21005             default:
21006                 break;
21007         }
21008     }
21009     if (pctxt->nberrors != 0)
21010         goto exit_error;
21011     /*
21012     * First compute the variety of simple types. This is needed as
21013     * a seperate step, since otherwise we won't be able to detect
21014     * circular union types in all cases.
21015     */
21016     for (i = 0; i < nbItems; i++) {
21017         item = items[i];
21018         switch (item->type) {
21019             case XML_SCHEMA_TYPE_SIMPLE:
21020                 if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
21021                     xmlSchemaFixupSimpleTypeStageOne(pctxt,
21022                         (xmlSchemaTypePtr) item);
21023                     FIXHFAILURE;
21024                 }
21025                 break;
21026             default:
21027                 break;
21028         }
21029     }
21030     if (pctxt->nberrors != 0)
21031         goto exit_error;
21032     /*
21033     * Detect circular union types. Note that this needs the variety to
21034     * be already computed.
21035     */
21036     for (i = 0; i < nbItems; i++) {
21037         item = items[i];
21038         switch (item->type) {
21039             case XML_SCHEMA_TYPE_SIMPLE:
21040                 if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
21041                     xmlSchemaCheckUnionTypeDefCircular(pctxt,
21042                         (xmlSchemaTypePtr) item);
21043                     FIXHFAILURE;
21044                 }
21045                 break;
21046             default:
21047                 break;
21048         }
21049     }
21050     if (pctxt->nberrors != 0)
21051         goto exit_error;
21052
21053     /*
21054     * Do the complete type fixup for simple types.
21055     */
21056     for (i = 0; i < nbItems; i++) {
21057         item = items[i];
21058         switch (item->type) {
21059             case XML_SCHEMA_TYPE_SIMPLE:
21060                 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21061                     xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
21062                     FIXHFAILURE;
21063                 }
21064                 break;
21065             default:
21066                 break;
21067         }
21068     }
21069     if (pctxt->nberrors != 0)
21070         goto exit_error;
21071     /*
21072     * At this point we need build and check all simple types.
21073     */
21074     /*
21075     * Apply contraints for attribute declarations.
21076     */
21077     for (i = 0; i < nbItems; i++) {
21078         item = items[i];
21079         switch (item->type) {
21080             case XML_SCHEMA_TYPE_ATTRIBUTE:
21081                 xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
21082                 FIXHFAILURE;
21083                 break;
21084             default:
21085                 break;
21086         }
21087     }
21088     if (pctxt->nberrors != 0)
21089         goto exit_error;
21090     /*
21091     * Apply constraints for attribute uses.
21092     */
21093     for (i = 0; i < nbItems; i++) {
21094         item = items[i];
21095         switch (item->type) {
21096             case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21097                 if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
21098                     xmlSchemaCheckAttrUsePropsCorrect(pctxt,
21099                         WXS_ATTR_USE_CAST item);
21100                     FIXHFAILURE;
21101                 }
21102                 break;
21103             default:
21104                 break;
21105         }
21106     }
21107     if (pctxt->nberrors != 0)
21108         goto exit_error;
21109
21110     /*
21111     * Apply constraints for attribute group definitions.
21112     */
21113     for (i = 0; i < nbItems; i++) {
21114         item = items[i];
21115         switch (item->type) {
21116         case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21117             if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
21118                 ( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
21119             {
21120                 xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
21121                 FIXHFAILURE;
21122             }
21123             break;
21124         default:
21125             break;
21126         }
21127     }
21128     if (pctxt->nberrors != 0)
21129         goto exit_error;
21130
21131     /*
21132     * Apply constraints for redefinitions.
21133     */
21134     if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
21135         xmlSchemaCheckSRCRedefineSecond(pctxt);
21136     if (pctxt->nberrors != 0)
21137         goto exit_error;
21138
21139     /*
21140     * Complex types are builded and checked.
21141     */
21142     for (i = 0; i < nbItems; i++) {
21143         item = con->pending->items[i];
21144         switch (item->type) {
21145             case XML_SCHEMA_TYPE_COMPLEX:
21146                 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21147                     xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
21148                     FIXHFAILURE;
21149                 }
21150                 break;
21151             default:
21152                 break;
21153         }
21154     }
21155     if (pctxt->nberrors != 0)
21156         goto exit_error;
21157
21158     /*
21159     * The list could have changed, since xmlSchemaFixupComplexType()
21160     * will create particles and model groups in some cases.
21161     */
21162     items = (xmlSchemaTreeItemPtr *) con->pending->items;
21163     nbItems = con->pending->nbItems;
21164
21165     /*
21166     * Apply some constraints for element declarations.
21167     */
21168     for (i = 0; i < nbItems; i++) {
21169         item = items[i];
21170         switch (item->type) {
21171             case XML_SCHEMA_TYPE_ELEMENT:
21172                 elemDecl = (xmlSchemaElementPtr) item;
21173
21174                 if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
21175                 {
21176                     xmlSchemaCheckElementDeclComponent(
21177                         (xmlSchemaElementPtr) elemDecl, pctxt);
21178                     FIXHFAILURE;
21179                 }
21180
21181 #ifdef WXS_ELEM_DECL_CONS_ENABLED
21182                 /*
21183                 * Schema Component Constraint: Element Declarations Consistent
21184                 * Apply this constraint to local types of element declarations.
21185                 */
21186                 if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
21187                     (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
21188                     (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
21189                 {
21190                     xmlSchemaCheckElementDeclConsistent(pctxt,
21191                         WXS_BASIC_CAST elemDecl,
21192                         WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
21193                         NULL, NULL, 0);
21194                 }
21195 #endif
21196                 break;
21197             default:
21198                 break;
21199         }
21200     }
21201     if (pctxt->nberrors != 0)
21202         goto exit_error;
21203
21204     /*
21205     * Finally we can build the automaton from the content model of
21206     * complex types.
21207     */
21208
21209     for (i = 0; i < nbItems; i++) {
21210         item = items[i];
21211         switch (item->type) {
21212             case XML_SCHEMA_TYPE_COMPLEX:
21213                 xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
21214                 /* FIXHFAILURE; */
21215                 break;
21216             default:
21217                 break;
21218         }
21219     }
21220     if (pctxt->nberrors != 0)
21221         goto exit_error;
21222     /*
21223     * URGENT TODO: cos-element-consistent
21224     */
21225     goto exit;
21226
21227 exit_error:
21228     ret = pctxt->err;
21229     goto exit;
21230
21231 exit_failure:
21232     ret = -1;
21233
21234 exit:
21235     /*
21236     * Reset the constructor. This is needed for XSI acquisition, since
21237     * those items will be processed over and over again for every XSI
21238     * if not cleared here.
21239     */
21240     con->bucket = oldbucket;
21241     con->pending->nbItems = 0;
21242     if (con->substGroups != NULL) {
21243         xmlHashFree(con->substGroups,
21244             (xmlHashDeallocator) xmlSchemaSubstGroupFree);
21245         con->substGroups = NULL;
21246     }
21247     if (con->redefs != NULL) {
21248         xmlSchemaRedefListFree(con->redefs);
21249         con->redefs = NULL;
21250     }
21251     return(ret);
21252 }
21253 /**
21254  * xmlSchemaParse:
21255  * @ctxt:  a schema validation context
21256  *
21257  * parse a schema definition resource and build an internal
21258  * XML Shema struture which can be used to validate instances.
21259  *
21260  * Returns the internal XML Schema structure built from the resource or
21261  *         NULL in case of error
21262  */
21263 xmlSchemaPtr
21264 xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21265 {
21266     xmlSchemaPtr mainSchema = NULL;
21267     xmlSchemaBucketPtr bucket = NULL;
21268     int res;
21269
21270     /*
21271     * This one is used if the schema to be parsed was specified via
21272     * the API; i.e. not automatically by the validated instance document.
21273     */
21274
21275     xmlSchemaInitTypes();
21276
21277     if (ctxt == NULL)
21278         return (NULL);
21279
21280     /* TODO: Init the context. Is this all we need?*/
21281     ctxt->nberrors = 0;
21282     ctxt->err = 0;
21283     ctxt->counter = 0;
21284
21285     /* Create the *main* schema. */
21286     mainSchema = xmlSchemaNewSchema(ctxt);
21287     if (mainSchema == NULL)
21288         goto exit_failure;
21289     /*
21290     * Create the schema constructor.
21291     */
21292     if (ctxt->constructor == NULL) {
21293         ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21294         if (ctxt->constructor == NULL)
21295             return(NULL);
21296         /* Take ownership of the constructor to be able to free it. */
21297         ctxt->ownsConstructor = 1;
21298     }
21299     ctxt->constructor->mainSchema = mainSchema;
21300     /*
21301     * Locate and add the schema document.
21302     */
21303     res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21304         ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21305         NULL, NULL, &bucket);
21306     if (res == -1)
21307         goto exit_failure;
21308     if (res != 0)
21309         goto exit;
21310
21311     if (bucket == NULL) {
21312         /* TODO: Error code, actually we failed to *locate* the schema. */
21313         if (ctxt->URL)
21314             xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21315                 NULL, NULL,
21316                 "Failed to locate the main schema resource at '%s'",
21317                 ctxt->URL, NULL);
21318         else
21319             xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21320                 NULL, NULL,
21321                 "Failed to locate the main schema resource",
21322                     NULL, NULL);
21323         goto exit;
21324     }
21325     /* Then do the parsing for good. */
21326     if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
21327         goto exit_failure;
21328     if (ctxt->nberrors != 0)
21329         goto exit;
21330
21331     mainSchema->doc = bucket->doc;
21332     mainSchema->preserve = ctxt->preserve;
21333
21334     ctxt->schema = mainSchema;
21335
21336     if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
21337         goto exit_failure;
21338
21339     /*
21340     * TODO: This is not nice, since we cannot distinguish from the
21341     * result if there was an internal error or not.
21342     */
21343 exit:
21344     if (ctxt->nberrors != 0) {
21345         if (mainSchema) {
21346             xmlSchemaFree(mainSchema);
21347             mainSchema = NULL;
21348         }
21349         if (ctxt->constructor) {
21350             xmlSchemaConstructionCtxtFree(ctxt->constructor);
21351             ctxt->constructor = NULL;
21352             ctxt->ownsConstructor = 0;
21353         }
21354     }
21355     ctxt->schema = NULL;
21356     return(mainSchema);
21357 exit_failure:
21358     /*
21359     * Quite verbose, but should catch internal errors, which were
21360     * not communitated.
21361     */
21362     if (mainSchema) {
21363         xmlSchemaFree(mainSchema);
21364         mainSchema = NULL;
21365     }
21366     if (ctxt->constructor) {
21367         xmlSchemaConstructionCtxtFree(ctxt->constructor);
21368         ctxt->constructor = NULL;
21369         ctxt->ownsConstructor = 0;
21370     }
21371     PERROR_INT2("xmlSchemaParse",
21372         "An internal error occured");
21373     ctxt->schema = NULL;
21374     return(NULL);
21375 }
21376
21377 /**
21378  * xmlSchemaSetParserErrors:
21379  * @ctxt:  a schema validation context
21380  * @err:  the error callback
21381  * @warn:  the warning callback
21382  * @ctx:  contextual data for the callbacks
21383  *
21384  * Set the callback functions used to handle errors for a validation context
21385  */
21386 void
21387 xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21388                          xmlSchemaValidityErrorFunc err,
21389                          xmlSchemaValidityWarningFunc warn, void *ctx)
21390 {
21391     if (ctxt == NULL)
21392         return;
21393     ctxt->error = err;
21394     ctxt->warning = warn;
21395     ctxt->errCtxt = ctx;
21396     if (ctxt->vctxt != NULL)
21397         xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21398 }
21399
21400 /**
21401  * xmlSchemaSetParserStructuredErrors:
21402  * @ctxt:  a schema parser context
21403  * @serror:  the structured error function
21404  * @ctx: the functions context
21405  *
21406  * Set the structured error callback
21407  */
21408 void
21409 xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21410                                    xmlStructuredErrorFunc serror,
21411                                    void *ctx)
21412 {
21413     if (ctxt == NULL)
21414         return;
21415     ctxt->serror = serror;
21416     ctxt->errCtxt = ctx;
21417     if (ctxt->vctxt != NULL)
21418         xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
21419 }
21420
21421 /**
21422  * xmlSchemaGetParserErrors:
21423  * @ctxt:  a XMl-Schema parser context
21424  * @err: the error callback result
21425  * @warn: the warning callback result
21426  * @ctx: contextual data for the callbacks result
21427  *
21428  * Get the callback information used to handle errors for a parser context
21429  *
21430  * Returns -1 in case of failure, 0 otherwise
21431  */
21432 int
21433 xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21434                          xmlSchemaValidityErrorFunc * err,
21435                          xmlSchemaValidityWarningFunc * warn, void **ctx)
21436 {
21437         if (ctxt == NULL)
21438                 return(-1);
21439         if (err != NULL)
21440                 *err = ctxt->error;
21441         if (warn != NULL)
21442                 *warn = ctxt->warning;
21443         if (ctx != NULL)
21444                 *ctx = ctxt->errCtxt;
21445         return(0);
21446 }
21447
21448 /**
21449  * xmlSchemaFacetTypeToString:
21450  * @type:  the facet type
21451  *
21452  * Convert the xmlSchemaTypeType to a char string.
21453  *
21454  * Returns the char string representation of the facet type if the
21455  *     type is a facet and an "Internal Error" string otherwise.
21456  */
21457 static const xmlChar *
21458 xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21459 {
21460     switch (type) {
21461         case XML_SCHEMA_FACET_PATTERN:
21462             return (BAD_CAST "pattern");
21463         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
21464             return (BAD_CAST "maxExclusive");
21465         case XML_SCHEMA_FACET_MAXINCLUSIVE:
21466             return (BAD_CAST "maxInclusive");
21467         case XML_SCHEMA_FACET_MINEXCLUSIVE:
21468             return (BAD_CAST "minExclusive");
21469         case XML_SCHEMA_FACET_MININCLUSIVE:
21470             return (BAD_CAST "minInclusive");
21471         case XML_SCHEMA_FACET_WHITESPACE:
21472             return (BAD_CAST "whiteSpace");
21473         case XML_SCHEMA_FACET_ENUMERATION:
21474             return (BAD_CAST "enumeration");
21475         case XML_SCHEMA_FACET_LENGTH:
21476             return (BAD_CAST "length");
21477         case XML_SCHEMA_FACET_MAXLENGTH:
21478             return (BAD_CAST "maxLength");
21479         case XML_SCHEMA_FACET_MINLENGTH:
21480             return (BAD_CAST "minLength");
21481         case XML_SCHEMA_FACET_TOTALDIGITS:
21482             return (BAD_CAST "totalDigits");
21483         case XML_SCHEMA_FACET_FRACTIONDIGITS:
21484             return (BAD_CAST "fractionDigits");
21485         default:
21486             break;
21487     }
21488     return (BAD_CAST "Internal Error");
21489 }
21490
21491 static xmlSchemaWhitespaceValueType
21492 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21493 {
21494     /*
21495     * The normalization type can be changed only for types which are derived
21496     * from xsd:string.
21497     */
21498     if (type->type == XML_SCHEMA_TYPE_BASIC) {
21499         /*
21500         * Note that we assume a whitespace of preserve for anySimpleType.
21501         */
21502         if ((type->builtInType == XML_SCHEMAS_STRING) ||
21503             (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21504             return(XML_SCHEMA_WHITESPACE_PRESERVE);
21505         else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
21506             return(XML_SCHEMA_WHITESPACE_REPLACE);
21507         else {
21508             /*
21509             * For all ï¿½atomic� datatypes other than string (and types ï¿½derived�
21510             * by ï¿½restriction� from it) the value of whiteSpace is fixed to
21511             * collapse
21512             * Note that this includes built-in list datatypes.
21513             */
21514             return(XML_SCHEMA_WHITESPACE_COLLAPSE);
21515         }
21516     } else if (WXS_IS_LIST(type)) {
21517         /*
21518         * For list types the facet "whiteSpace" is fixed to "collapse".
21519         */
21520         return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21521     } else if (WXS_IS_UNION(type)) {
21522         return (XML_SCHEMA_WHITESPACE_UNKNOWN);
21523     } else if (WXS_IS_ATOMIC(type)) {
21524         if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21525             return (XML_SCHEMA_WHITESPACE_PRESERVE);
21526         else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21527             return (XML_SCHEMA_WHITESPACE_REPLACE);
21528         else
21529             return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21530     }
21531     return (-1);
21532 }
21533
21534 /************************************************************************
21535  *                                                                      *
21536  *                      Simple type validation                          *
21537  *                                                                      *
21538  ************************************************************************/
21539
21540
21541 /************************************************************************
21542  *                                                                      *
21543  *                      DOM Validation code                             *
21544  *                                                                      *
21545  ************************************************************************/
21546
21547 /**
21548  * xmlSchemaAssembleByLocation:
21549  * @pctxt:  a schema parser context
21550  * @vctxt:  a schema validation context
21551  * @schema: the existing schema
21552  * @node: the node that fired the assembling
21553  * @nsName: the namespace name of the new schema
21554  * @location: the location of the schema
21555  *
21556  * Expands an existing schema by an additional schema.
21557  *
21558  * Returns 0 if the new schema is correct, a positive error code
21559  * number otherwise and -1 in case of an internal or API error.
21560  */
21561 static int
21562 xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
21563                             xmlSchemaPtr schema,
21564                             xmlNodePtr node,
21565                             const xmlChar *nsName,
21566                             const xmlChar *location)
21567 {
21568     int ret = 0;
21569     xmlSchemaParserCtxtPtr pctxt;
21570     xmlSchemaBucketPtr bucket = NULL;
21571
21572     if ((vctxt == NULL) || (schema == NULL))
21573         return (-1);
21574
21575     if (vctxt->pctxt == NULL) {
21576         VERROR_INT("xmlSchemaAssembleByLocation",
21577             "no parser context available");
21578         return(-1);
21579     }
21580     pctxt = vctxt->pctxt;
21581     if (pctxt->constructor == NULL) {
21582         PERROR_INT("xmlSchemaAssembleByLocation",
21583             "no constructor");
21584         return(-1);
21585     }
21586     /*
21587     * Acquire the schema document.
21588     */
21589     location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21590         location, node);
21591     /*
21592     * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21593     * the process will automatically change this to
21594     * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21595     */
21596     ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21597         location, NULL, NULL, 0, node, NULL, nsName,
21598         &bucket);
21599     if (ret != 0)
21600         return(ret);
21601     if (bucket == NULL) {
21602         /*
21603         * Generate a warning that the document could not be located.
21604         */
21605         xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21606             node, NULL,
21607             "The document at location '%s' could not be acquired",
21608             location, NULL, NULL);
21609         return(ret);
21610     }
21611     /*
21612     * The first located schema will be handled as if all other
21613     * schemas imported by XSI were imported by this first schema.
21614     */
21615     if ((bucket != NULL) &&
21616         (WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21617         WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21618     /*
21619     * TODO: Is this handled like an import? I.e. is it not an error
21620     * if the schema cannot be located?
21621     */
21622     if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21623         return(0);
21624     /*
21625     * We will reuse the parser context for every schema imported
21626     * directly via XSI. So reset the context.
21627     */
21628     pctxt->nberrors = 0;
21629     pctxt->err = 0;
21630     pctxt->doc = bucket->doc;
21631
21632     ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21633     if (ret == -1) {
21634         pctxt->doc = NULL;
21635         goto exit_failure;
21636     }
21637     /* Paranoid error channelling. */
21638     if ((ret == 0) && (pctxt->nberrors != 0))
21639         ret = pctxt->err;
21640     if (pctxt->nberrors == 0) {
21641         /*
21642         * Only bother to fixup pending components, if there was
21643         * no error yet.
21644         * For every XSI acquired schema (and its sub-schemata) we will
21645         * fixup the components.
21646         */
21647         xmlSchemaFixupComponents(pctxt, bucket);
21648         ret = pctxt->err;
21649         /*
21650         * Not nice, but we need somehow to channel the schema parser
21651         * error to the validation context.
21652         */
21653         if ((ret != 0) && (vctxt->err == 0))
21654             vctxt->err = ret;
21655         vctxt->nberrors += pctxt->nberrors;
21656     } else {
21657         /* Add to validation error sum. */
21658         vctxt->nberrors += pctxt->nberrors;
21659     }
21660     pctxt->doc = NULL;
21661     return(ret);
21662 exit_failure:
21663     pctxt->doc = NULL;
21664     return (-1);
21665 }
21666
21667 static xmlSchemaAttrInfoPtr
21668 xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21669                          int metaType)
21670 {
21671     if (vctxt->nbAttrInfos == 0)
21672         return (NULL);
21673     {
21674         int i;
21675         xmlSchemaAttrInfoPtr iattr;
21676
21677         for (i = 0; i < vctxt->nbAttrInfos; i++) {
21678             iattr = vctxt->attrInfos[i];
21679             if (iattr->metaType == metaType)
21680                 return (iattr);
21681         }
21682
21683     }
21684     return (NULL);
21685 }
21686
21687 /**
21688  * xmlSchemaAssembleByXSI:
21689  * @vctxt:  a schema validation context
21690  *
21691  * Expands an existing schema by an additional schema using
21692  * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21693  * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21694  * must be set to 1.
21695  *
21696  * Returns 0 if the new schema is correct, a positive error code
21697  * number otherwise and -1 in case of an internal or API error.
21698  */
21699 static int
21700 xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
21701 {
21702     const xmlChar *cur, *end;
21703     const xmlChar *nsname = NULL, *location;
21704     int count = 0;
21705     int ret = 0;
21706     xmlSchemaAttrInfoPtr iattr;
21707
21708     /*
21709     * Parse the value; we will assume an even number of values
21710     * to be given (this is how Xerces and XSV work).
21711     *
21712     * URGENT TODO: !! This needs to work for both
21713     * @noNamespaceSchemaLocation AND @schemaLocation on the same
21714     * element !!
21715     */
21716     iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21717         XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21718     if (iattr == NULL)
21719         iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21720         XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21721     if (iattr == NULL)
21722         return (0);
21723     cur = iattr->value;
21724     do {
21725         /*
21726         * TODO: Move the string parsing mechanism away from here.
21727         */
21728         if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
21729             /*
21730             * Get the namespace name.
21731             */
21732             while (IS_BLANK_CH(*cur))
21733                 cur++;
21734             end = cur;
21735             while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21736                 end++;
21737             if (end == cur)
21738                 break;
21739             count++; /* TODO: Don't use the schema's dict. */
21740             nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21741             cur = end;
21742         }
21743         /*
21744         * Get the URI.
21745         */
21746         while (IS_BLANK_CH(*cur))
21747             cur++;
21748         end = cur;
21749         while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21750             end++;
21751         if (end == cur) {
21752             if (iattr->metaType ==
21753                 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21754             {
21755                 /*
21756                 * If using @schemaLocation then tuples are expected.
21757                 * I.e. the namespace name *and* the document's URI.
21758                 */
21759                 xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21760                     iattr->node, NULL,
21761                     "The value must consist of tuples: the target namespace "
21762                     "name and the document's URI", NULL, NULL, NULL);
21763             }
21764             break;
21765         }
21766         count++; /* TODO: Don't use the schema's dict. */
21767         location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21768         cur = end;
21769         ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21770             iattr->node, nsname, location);
21771         if (ret == -1) {
21772             VERROR_INT("xmlSchemaAssembleByXSI",
21773                 "assembling schemata");
21774             return (-1);
21775         }
21776     } while (*cur != 0);
21777     return (ret);
21778 }
21779
21780 static const xmlChar *
21781 xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21782                          const xmlChar *prefix)
21783 {
21784     if (vctxt->sax != NULL) {
21785         int i, j;
21786         xmlSchemaNodeInfoPtr inode;
21787
21788         for (i = vctxt->depth; i >= 0; i--) {
21789             if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21790                 inode = vctxt->elemInfos[i];
21791                 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21792                     if (((prefix == NULL) &&
21793                             (inode->nsBindings[j] == NULL)) ||
21794                         ((prefix != NULL) && xmlStrEqual(prefix,
21795                             inode->nsBindings[j]))) {
21796
21797                         /*
21798                         * Note that the namespace bindings are already
21799                         * in a string dict.
21800                         */
21801                         return (inode->nsBindings[j+1]);
21802                     }
21803                 }
21804             }
21805         }
21806         return (NULL);
21807 #ifdef LIBXML_READER_ENABLED
21808     } else if (vctxt->reader != NULL) {
21809         xmlChar *nsName;
21810
21811         nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21812         if (nsName != NULL) {
21813             const xmlChar *ret;
21814
21815             ret = xmlDictLookup(vctxt->dict, nsName, -1);
21816             xmlFree(nsName);
21817             return (ret);
21818         } else
21819             return (NULL);
21820 #endif
21821     } else {
21822         xmlNsPtr ns;
21823
21824         if ((vctxt->inode->node == NULL) ||
21825             (vctxt->inode->node->doc == NULL)) {
21826             VERROR_INT("xmlSchemaLookupNamespace",
21827                 "no node or node's doc avaliable");
21828             return (NULL);
21829         }
21830         ns = xmlSearchNs(vctxt->inode->node->doc,
21831             vctxt->inode->node, prefix);
21832         if (ns != NULL)
21833             return (ns->href);
21834         return (NULL);
21835     }
21836 }
21837
21838 /*
21839 * This one works on the schema of the validation context.
21840 */
21841 static int
21842 xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21843                           xmlSchemaPtr schema,
21844                           xmlNodePtr node,
21845                           const xmlChar *value,
21846                           xmlSchemaValPtr *val,
21847                           int valNeeded)
21848 {
21849     int ret;
21850
21851     if (vctxt && (vctxt->schema == NULL)) {
21852         VERROR_INT("xmlSchemaValidateNotation",
21853             "a schema is needed on the validation context");
21854         return (-1);
21855     }
21856     ret = xmlValidateQName(value, 1);
21857     if (ret != 0)
21858         return (ret);
21859     {
21860         xmlChar *localName = NULL;
21861         xmlChar *prefix = NULL;
21862
21863         localName = xmlSplitQName2(value, &prefix);
21864         if (prefix != NULL) {
21865             const xmlChar *nsName = NULL;
21866
21867             if (vctxt != NULL)
21868                 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21869             else if (node != NULL) {
21870                 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21871                 if (ns != NULL)
21872                     nsName = ns->href;
21873             } else {
21874                 xmlFree(prefix);
21875                 xmlFree(localName);
21876                 return (1);
21877             }
21878             if (nsName == NULL) {
21879                 xmlFree(prefix);
21880                 xmlFree(localName);
21881                 return (1);
21882             }
21883             if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
21884                 if ((valNeeded) && (val != NULL)) {
21885                     (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName),
21886                                                        xmlStrdup(nsName));
21887                     if (*val == NULL)
21888                         ret = -1;
21889                 }
21890             } else
21891                 ret = 1;
21892             xmlFree(prefix);
21893             xmlFree(localName);
21894         } else {
21895             if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
21896                 if (valNeeded && (val != NULL)) {
21897                     (*val) = xmlSchemaNewNOTATIONValue(
21898                         BAD_CAST xmlStrdup(value), NULL);
21899                     if (*val == NULL)
21900                         ret = -1;
21901                 }
21902             } else
21903                 return (1);
21904         }
21905     }
21906     return (ret);
21907 }
21908
21909 static int
21910 xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21911                        const xmlChar* lname,
21912                        const xmlChar* nsname)
21913 {
21914     int i;
21915
21916     lname = xmlDictLookup(vctxt->dict, lname, -1);
21917     if (lname == NULL)
21918         return(-1);
21919     if (nsname != NULL) {
21920         nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21921         if (nsname == NULL)
21922             return(-1);
21923     }
21924     for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21925         if ((vctxt->nodeQNames->items [i] == lname) &&
21926             (vctxt->nodeQNames->items[i +1] == nsname))
21927             /* Already there */
21928             return(i);
21929     }
21930     /* Add new entry. */
21931     i = vctxt->nodeQNames->nbItems;
21932     xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21933     xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21934     return(i);
21935 }
21936
21937 /************************************************************************
21938  *                                                                      *
21939  *  Validation of identity-constraints (IDC)                            *
21940  *                                                                      *
21941  ************************************************************************/
21942
21943 /**
21944  * xmlSchemaAugmentIDC:
21945  * @idcDef: the IDC definition
21946  *
21947  * Creates an augmented IDC definition item.
21948  *
21949  * Returns the item, or NULL on internal errors.
21950  */
21951 static void
21952 xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
21953                     xmlSchemaValidCtxtPtr vctxt)
21954 {
21955     xmlSchemaIDCAugPtr aidc;
21956
21957     aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
21958     if (aidc == NULL) {
21959         xmlSchemaVErrMemory(vctxt,
21960             "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
21961             NULL);
21962         return;
21963     }
21964     aidc->keyrefDepth = -1;
21965     aidc->def = idcDef;
21966     aidc->next = NULL;
21967     if (vctxt->aidcs == NULL)
21968         vctxt->aidcs = aidc;
21969     else {
21970         aidc->next = vctxt->aidcs;
21971         vctxt->aidcs = aidc;
21972     }
21973     /*
21974     * Save if we have keyrefs at all.
21975     */
21976     if ((vctxt->hasKeyrefs == 0) &&
21977         (idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
21978         vctxt->hasKeyrefs = 1;
21979 }
21980
21981 /**
21982  * xmlSchemaAugmentImportedIDC:
21983  * @imported: the imported schema
21984  *
21985  * Creates an augmented IDC definition for the imported schema.
21986  */
21987 static void
21988 xmlSchemaAugmentImportedIDC(xmlSchemaImportPtr imported, xmlSchemaValidCtxtPtr vctxt) {
21989     if (imported->schema->idcDef != NULL) {
21990             xmlHashScan(imported->schema->idcDef ,
21991             (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
21992     }
21993 }
21994
21995 /**
21996  * xmlSchemaIDCNewBinding:
21997  * @idcDef: the IDC definition of this binding
21998  *
21999  * Creates a new IDC binding.
22000  *
22001  * Returns the new IDC binding, NULL on internal errors.
22002  */
22003 static xmlSchemaPSVIIDCBindingPtr
22004 xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
22005 {
22006     xmlSchemaPSVIIDCBindingPtr ret;
22007
22008     ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
22009             sizeof(xmlSchemaPSVIIDCBinding));
22010     if (ret == NULL) {
22011         xmlSchemaVErrMemory(NULL,
22012             "allocating a PSVI IDC binding item", NULL);
22013         return (NULL);
22014     }
22015     memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
22016     ret->definition = idcDef;
22017     return (ret);
22018 }
22019
22020 /**
22021  * xmlSchemaIDCStoreNodeTableItem:
22022  * @vctxt: the WXS validation context
22023  * @item: the IDC node table item
22024  *
22025  * The validation context is used to store IDC node table items.
22026  * They are stored to avoid copying them if IDC node-tables are merged
22027  * with corresponding parent IDC node-tables (bubbling).
22028  *
22029  * Returns 0 if succeeded, -1 on internal errors.
22030  */
22031 static int
22032 xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
22033                                xmlSchemaPSVIIDCNodePtr item)
22034 {
22035     /*
22036     * Add to gobal list.
22037     */
22038     if (vctxt->idcNodes == NULL) {
22039         vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22040             xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
22041         if (vctxt->idcNodes == NULL) {
22042             xmlSchemaVErrMemory(vctxt,
22043                 "allocating the IDC node table item list", NULL);
22044             return (-1);
22045         }
22046         vctxt->sizeIdcNodes = 20;
22047     } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
22048         vctxt->sizeIdcNodes *= 2;
22049         vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22050             xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
22051             sizeof(xmlSchemaPSVIIDCNodePtr));
22052         if (vctxt->idcNodes == NULL) {
22053             xmlSchemaVErrMemory(vctxt,
22054                 "re-allocating the IDC node table item list", NULL);
22055             return (-1);
22056         }
22057     }
22058     vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
22059
22060     return (0);
22061 }
22062
22063 /**
22064  * xmlSchemaIDCStoreKey:
22065  * @vctxt: the WXS validation context
22066  * @item: the IDC key
22067  *
22068  * The validation context is used to store an IDC key.
22069  *
22070  * Returns 0 if succeeded, -1 on internal errors.
22071  */
22072 static int
22073 xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
22074                      xmlSchemaPSVIIDCKeyPtr key)
22075 {
22076     /*
22077     * Add to gobal list.
22078     */
22079     if (vctxt->idcKeys == NULL) {
22080         vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22081             xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
22082         if (vctxt->idcKeys == NULL) {
22083             xmlSchemaVErrMemory(vctxt,
22084                 "allocating the IDC key storage list", NULL);
22085             return (-1);
22086         }
22087         vctxt->sizeIdcKeys = 40;
22088     } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
22089         vctxt->sizeIdcKeys *= 2;
22090         vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22091             xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
22092             sizeof(xmlSchemaPSVIIDCKeyPtr));
22093         if (vctxt->idcKeys == NULL) {
22094             xmlSchemaVErrMemory(vctxt,
22095                 "re-allocating the IDC key storage list", NULL);
22096             return (-1);
22097         }
22098     }
22099     vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
22100
22101     return (0);
22102 }
22103
22104 /**
22105  * xmlSchemaIDCAppendNodeTableItem:
22106  * @bind: the IDC binding
22107  * @ntItem: the node-table item
22108  *
22109  * Appends the IDC node-table item to the binding.
22110  *
22111  * Returns 0 on success and -1 on internal errors.
22112  */
22113 static int
22114 xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
22115                                 xmlSchemaPSVIIDCNodePtr ntItem)
22116 {
22117     if (bind->nodeTable == NULL) {
22118         bind->sizeNodes = 10;
22119         bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22120             xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
22121         if (bind->nodeTable == NULL) {
22122             xmlSchemaVErrMemory(NULL,
22123                 "allocating an array of IDC node-table items", NULL);
22124             return(-1);
22125         }
22126     } else if (bind->sizeNodes <= bind->nbNodes) {
22127         bind->sizeNodes *= 2;
22128         bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22129             xmlRealloc(bind->nodeTable, bind->sizeNodes *
22130                 sizeof(xmlSchemaPSVIIDCNodePtr));
22131         if (bind->nodeTable == NULL) {
22132             xmlSchemaVErrMemory(NULL,
22133                 "re-allocating an array of IDC node-table items", NULL);
22134             return(-1);
22135         }
22136     }
22137     bind->nodeTable[bind->nbNodes++] = ntItem;
22138     return(0);
22139 }
22140
22141 /**
22142  * xmlSchemaIDCAcquireBinding:
22143  * @vctxt: the WXS validation context
22144  * @matcher: the IDC matcher
22145  *
22146  * Looks up an PSVI IDC binding, for the IDC definition and
22147  * of the given matcher. If none found, a new one is created
22148  * and added to the IDC table.
22149  *
22150  * Returns an IDC binding or NULL on internal errors.
22151  */
22152 static xmlSchemaPSVIIDCBindingPtr
22153 xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
22154                           xmlSchemaIDCMatcherPtr matcher)
22155 {
22156     xmlSchemaNodeInfoPtr ielem;
22157
22158     ielem = vctxt->elemInfos[matcher->depth];
22159
22160     if (ielem->idcTable == NULL) {
22161         ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
22162         if (ielem->idcTable == NULL)
22163             return (NULL);
22164         return(ielem->idcTable);
22165     } else {
22166         xmlSchemaPSVIIDCBindingPtr bind = NULL;
22167
22168         bind = ielem->idcTable;
22169         do {
22170             if (bind->definition == matcher->aidc->def)
22171                 return(bind);
22172             if (bind->next == NULL) {
22173                 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
22174                 if (bind->next == NULL)
22175                     return (NULL);
22176                 return(bind->next);
22177             }
22178             bind = bind->next;
22179         } while (bind != NULL);
22180     }
22181     return (NULL);
22182 }
22183
22184 static xmlSchemaItemListPtr
22185 xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22186                              xmlSchemaIDCMatcherPtr matcher)
22187 {
22188     if (matcher->targets == NULL)
22189         matcher->targets = xmlSchemaItemListCreate();
22190     return(matcher->targets);
22191 }
22192
22193 /**
22194  * xmlSchemaIDCFreeKey:
22195  * @key: the IDC key
22196  *
22197  * Frees an IDC key together with its compiled value.
22198  */
22199 static void
22200 xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
22201 {
22202     if (key->val != NULL)
22203         xmlSchemaFreeValue(key->val);
22204     xmlFree(key);
22205 }
22206
22207 /**
22208  * xmlSchemaIDCFreeBinding:
22209  *
22210  * Frees an IDC binding. Note that the node table-items
22211  * are not freed.
22212  */
22213 static void
22214 xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
22215 {
22216     if (bind->nodeTable != NULL)
22217         xmlFree(bind->nodeTable);
22218     if (bind->dupls != NULL)
22219         xmlSchemaItemListFree(bind->dupls);
22220     xmlFree(bind);
22221 }
22222
22223 /**
22224  * xmlSchemaIDCFreeIDCTable:
22225  * @bind: the first IDC binding in the list
22226  *
22227  * Frees an IDC table, i.e. all the IDC bindings in the list.
22228  */
22229 static void
22230 xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
22231 {
22232     xmlSchemaPSVIIDCBindingPtr prev;
22233
22234     while (bind != NULL) {
22235         prev = bind;
22236         bind = bind->next;
22237         xmlSchemaIDCFreeBinding(prev);
22238     }
22239 }
22240
22241 /**
22242  * xmlSchemaIDCFreeMatcherList:
22243  * @matcher: the first IDC matcher in the list
22244  *
22245  * Frees a list of IDC matchers.
22246  */
22247 static void
22248 xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22249 {
22250     xmlSchemaIDCMatcherPtr next;
22251
22252     while (matcher != NULL) {
22253         next = matcher->next;
22254         if (matcher->keySeqs != NULL) {
22255             int i;
22256             for (i = 0; i < matcher->sizeKeySeqs; i++)
22257                 if (matcher->keySeqs[i] != NULL)
22258                     xmlFree(matcher->keySeqs[i]);
22259             xmlFree(matcher->keySeqs);
22260         }
22261         if (matcher->targets != NULL) {
22262             if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22263                 int i;
22264                 xmlSchemaPSVIIDCNodePtr idcNode;
22265                 /*
22266                 * Node-table items for keyrefs are not stored globally
22267                 * to the validation context, since they are not bubbled.
22268                 * We need to free them here.
22269                 */
22270                 for (i = 0; i < matcher->targets->nbItems; i++) {
22271                     idcNode =
22272                         (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22273                     xmlFree(idcNode->keys);
22274                     xmlFree(idcNode);
22275                 }
22276             }
22277             xmlSchemaItemListFree(matcher->targets);
22278         }
22279         xmlFree(matcher);
22280         matcher = next;
22281     }
22282 }
22283
22284 /**
22285  * xmlSchemaIDCReleaseMatcherList:
22286  * @vctxt: the WXS validation context
22287  * @matcher: the first IDC matcher in the list
22288  *
22289  * Caches a list of IDC matchers for reuse.
22290  */
22291 static void
22292 xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
22293                                xmlSchemaIDCMatcherPtr matcher)
22294 {
22295     xmlSchemaIDCMatcherPtr next;
22296
22297     while (matcher != NULL) {
22298         next = matcher->next;
22299         if (matcher->keySeqs != NULL) {
22300             int i;
22301             /*
22302             * Don't free the array, but only the content.
22303             */
22304             for (i = 0; i < matcher->sizeKeySeqs; i++)
22305                 if (matcher->keySeqs[i] != NULL) {
22306                     xmlFree(matcher->keySeqs[i]);
22307                     matcher->keySeqs[i] = NULL;
22308                 }
22309         }
22310         if (matcher->targets) {
22311             if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22312                 int i;
22313                 xmlSchemaPSVIIDCNodePtr idcNode;
22314                 /*
22315                 * Node-table items for keyrefs are not stored globally
22316                 * to the validation context, since they are not bubbled.
22317                 * We need to free them here.
22318                 */
22319                 for (i = 0; i < matcher->targets->nbItems; i++) {
22320                     idcNode =
22321                         (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22322                     xmlFree(idcNode->keys);
22323                     xmlFree(idcNode);
22324                 }
22325             }
22326             xmlSchemaItemListFree(matcher->targets);
22327             matcher->targets = NULL;
22328         }
22329         matcher->next = NULL;
22330         /*
22331         * Cache the matcher.
22332         */
22333         if (vctxt->idcMatcherCache != NULL)
22334             matcher->nextCached = vctxt->idcMatcherCache;
22335         vctxt->idcMatcherCache = matcher;
22336
22337         matcher = next;
22338     }
22339 }
22340
22341 /**
22342  * xmlSchemaIDCAddStateObject:
22343  * @vctxt: the WXS validation context
22344  * @matcher: the IDC matcher
22345  * @sel: the XPath information
22346  * @parent: the parent "selector" state object if any
22347  * @type: "selector" or "field"
22348  *
22349  * Creates/reuses and activates state objects for the given
22350  * XPath information; if the XPath expression consists of unions,
22351  * multiple state objects are created for every unioned expression.
22352  *
22353  * Returns 0 on success and -1 on internal errors.
22354  */
22355 static int
22356 xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22357                         xmlSchemaIDCMatcherPtr matcher,
22358                         xmlSchemaIDCSelectPtr sel,
22359                         int type)
22360 {
22361     xmlSchemaIDCStateObjPtr sto;
22362
22363     /*
22364     * Reuse the state objects from the pool.
22365     */
22366     if (vctxt->xpathStatePool != NULL) {
22367         sto = vctxt->xpathStatePool;
22368         vctxt->xpathStatePool = sto->next;
22369         sto->next = NULL;
22370     } else {
22371         /*
22372         * Create a new state object.
22373         */
22374         sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22375         if (sto == NULL) {
22376             xmlSchemaVErrMemory(NULL,
22377                 "allocating an IDC state object", NULL);
22378             return (-1);
22379         }
22380         memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22381     }
22382     /*
22383     * Add to global list.
22384     */
22385     if (vctxt->xpathStates != NULL)
22386         sto->next = vctxt->xpathStates;
22387     vctxt->xpathStates = sto;
22388
22389     /*
22390     * Free the old xpath validation context.
22391     */
22392     if (sto->xpathCtxt != NULL)
22393         xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22394
22395     /*
22396     * Create a new XPath (pattern) validation context.
22397     */
22398     sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22399         (xmlPatternPtr) sel->xpathComp);
22400     if (sto->xpathCtxt == NULL) {
22401         VERROR_INT("xmlSchemaIDCAddStateObject",
22402             "failed to create an XPath validation context");
22403         return (-1);
22404     }
22405     sto->type = type;
22406     sto->depth = vctxt->depth;
22407     sto->matcher = matcher;
22408     sto->sel = sel;
22409     sto->nbHistory = 0;
22410
22411 #ifdef DEBUG_IDC
22412     xmlGenericError(xmlGenericErrorContext, "IDC:   STO push '%s'\n",
22413         sto->sel->xpath);
22414 #endif
22415     return (0);
22416 }
22417
22418 /**
22419  * xmlSchemaXPathEvaluate:
22420  * @vctxt: the WXS validation context
22421  * @nodeType: the nodeType of the current node
22422  *
22423  * Evaluates all active XPath state objects.
22424  *
22425  * Returns the number of IC "field" state objects which resolved to
22426  * this node, 0 if none resolved and -1 on internal errors.
22427  */
22428 static int
22429 xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
22430                        xmlElementType nodeType)
22431 {
22432     xmlSchemaIDCStateObjPtr sto, head = NULL, first;
22433     int res, resolved = 0, depth = vctxt->depth;
22434
22435     if (vctxt->xpathStates == NULL)
22436         return (0);
22437
22438     if (nodeType == XML_ATTRIBUTE_NODE)
22439         depth++;
22440 #ifdef DEBUG_IDC
22441     {
22442         xmlChar *str = NULL;
22443         xmlGenericError(xmlGenericErrorContext,
22444             "IDC: EVAL on %s, depth %d, type %d\n",
22445             xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22446                 vctxt->inode->localName), depth, nodeType);
22447         FREE_AND_NULL(str)
22448     }
22449 #endif
22450     /*
22451     * Process all active XPath state objects.
22452     */
22453     first = vctxt->xpathStates;
22454     sto = first;
22455     while (sto != head) {
22456 #ifdef DEBUG_IDC
22457         if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
22458             xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] selector '%s'\n",
22459                 sto->matcher->aidc->def->name, sto->sel->xpath);
22460         else
22461             xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] field '%s'\n",
22462                 sto->matcher->aidc->def->name, sto->sel->xpath);
22463 #endif
22464         if (nodeType == XML_ELEMENT_NODE)
22465             res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
22466                 vctxt->inode->localName, vctxt->inode->nsName);
22467         else
22468             res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
22469                 vctxt->inode->localName, vctxt->inode->nsName);
22470
22471         if (res == -1) {
22472             VERROR_INT("xmlSchemaXPathEvaluate",
22473                 "calling xmlStreamPush()");
22474             return (-1);
22475         }
22476         if (res == 0)
22477             goto next_sto;
22478         /*
22479         * Full match.
22480         */
22481 #ifdef DEBUG_IDC
22482         xmlGenericError(xmlGenericErrorContext, "IDC:     "
22483             "MATCH\n");
22484 #endif
22485         /*
22486         * Register a match in the state object history.
22487         */
22488         if (sto->history == NULL) {
22489             sto->history = (int *) xmlMalloc(5 * sizeof(int));
22490             if (sto->history == NULL) {
22491                 xmlSchemaVErrMemory(NULL,
22492                     "allocating the state object history", NULL);
22493                 return(-1);
22494             }
22495             sto->sizeHistory = 5;
22496         } else if (sto->sizeHistory <= sto->nbHistory) {
22497             sto->sizeHistory *= 2;
22498             sto->history = (int *) xmlRealloc(sto->history,
22499                 sto->sizeHistory * sizeof(int));
22500             if (sto->history == NULL) {
22501                 xmlSchemaVErrMemory(NULL,
22502                     "re-allocating the state object history", NULL);
22503                 return(-1);
22504             }
22505         }
22506         sto->history[sto->nbHistory++] = depth;
22507
22508 #ifdef DEBUG_IDC
22509         xmlGenericError(xmlGenericErrorContext, "IDC:       push match '%d'\n",
22510             vctxt->depth);
22511 #endif
22512
22513         if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22514             xmlSchemaIDCSelectPtr sel;
22515             /*
22516             * Activate state objects for the IDC fields of
22517             * the IDC selector.
22518             */
22519 #ifdef DEBUG_IDC
22520             xmlGenericError(xmlGenericErrorContext, "IDC:     "
22521                 "activating field states\n");
22522 #endif
22523             sel = sto->matcher->aidc->def->fields;
22524             while (sel != NULL) {
22525                 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22526                     sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22527                     return (-1);
22528                 sel = sel->next;
22529             }
22530         } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22531             /*
22532             * An IDC key node was found by the IDC field.
22533             */
22534 #ifdef DEBUG_IDC
22535             xmlGenericError(xmlGenericErrorContext,
22536                 "IDC:     key found\n");
22537 #endif
22538             /*
22539             * Notify that the character value of this node is
22540             * needed.
22541             */
22542             if (resolved == 0) {
22543                 if ((vctxt->inode->flags &
22544                     XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22545                 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22546             }
22547             resolved++;
22548         }
22549 next_sto:
22550         if (sto->next == NULL) {
22551             /*
22552             * Evaluate field state objects created on this node as well.
22553             */
22554             head = first;
22555             sto = vctxt->xpathStates;
22556         } else
22557             sto = sto->next;
22558     }
22559     return (resolved);
22560 }
22561
22562 static const xmlChar *
22563 xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
22564                               xmlChar **buf,
22565                               xmlSchemaPSVIIDCKeyPtr *seq,
22566                               int count)
22567 {
22568     int i, res;
22569     xmlChar *value = NULL;
22570
22571     *buf = xmlStrdup(BAD_CAST "[");
22572     for (i = 0; i < count; i++) {
22573         *buf = xmlStrcat(*buf, BAD_CAST "'");
22574         res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22575             xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22576             &value);
22577         if (res == 0)
22578             *buf = xmlStrcat(*buf, BAD_CAST value);
22579         else {
22580             VERROR_INT("xmlSchemaFormatIDCKeySequence",
22581                 "failed to compute a canonical value");
22582             *buf = xmlStrcat(*buf, BAD_CAST "???");
22583         }
22584         if (i < count -1)
22585             *buf = xmlStrcat(*buf, BAD_CAST "', ");
22586         else
22587             *buf = xmlStrcat(*buf, BAD_CAST "'");
22588         if (value != NULL) {
22589             xmlFree(value);
22590             value = NULL;
22591         }
22592     }
22593     *buf = xmlStrcat(*buf, BAD_CAST "]");
22594
22595     return (BAD_CAST *buf);
22596 }
22597
22598 /**
22599  * xmlSchemaXPathPop:
22600  * @vctxt: the WXS validation context
22601  *
22602  * Pops all XPath states.
22603  *
22604  * Returns 0 on success and -1 on internal errors.
22605  */
22606 static int
22607 xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22608 {
22609     xmlSchemaIDCStateObjPtr sto;
22610     int res;
22611
22612     if (vctxt->xpathStates == NULL)
22613         return(0);
22614     sto = vctxt->xpathStates;
22615     do {
22616         res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22617         if (res == -1)
22618             return (-1);
22619         sto = sto->next;
22620     } while (sto != NULL);
22621     return(0);
22622 }
22623
22624 /**
22625  * xmlSchemaXPathProcessHistory:
22626  * @vctxt: the WXS validation context
22627  * @type: the simple/complex type of the current node if any at all
22628  * @val: the precompiled value
22629  *
22630  * Processes and pops the history items of the IDC state objects.
22631  * IDC key-sequences are validated/created on IDC bindings.
22632  *
22633  * Returns 0 on success and -1 on internal errors.
22634  */
22635 static int
22636 xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
22637                              int depth)
22638 {
22639     xmlSchemaIDCStateObjPtr sto, nextsto;
22640     int res, matchDepth;
22641     xmlSchemaPSVIIDCKeyPtr key = NULL;
22642     xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
22643
22644     if (vctxt->xpathStates == NULL)
22645         return (0);
22646     sto = vctxt->xpathStates;
22647
22648 #ifdef DEBUG_IDC
22649     {
22650         xmlChar *str = NULL;
22651         xmlGenericError(xmlGenericErrorContext,
22652             "IDC: BACK on %s, depth %d\n",
22653             xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22654                 vctxt->inode->localName), vctxt->depth);
22655         FREE_AND_NULL(str)
22656     }
22657 #endif
22658     /*
22659     * Evaluate the state objects.
22660     */
22661     while (sto != NULL) {
22662         res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22663         if (res == -1) {
22664             VERROR_INT("xmlSchemaXPathProcessHistory",
22665                 "calling xmlStreamPop()");
22666             return (-1);
22667         }
22668 #ifdef DEBUG_IDC
22669         xmlGenericError(xmlGenericErrorContext, "IDC:   stream pop '%s'\n",
22670             sto->sel->xpath);
22671 #endif
22672         if (sto->nbHistory == 0)
22673             goto deregister_check;
22674
22675         matchDepth = sto->history[sto->nbHistory -1];
22676
22677         /*
22678         * Only matches at the current depth are of interest.
22679         */
22680         if (matchDepth != depth) {
22681             sto = sto->next;
22682             continue;
22683         }
22684         if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22685             /*
22686             * NOTE: According to
22687             *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22688             *   ... the simple-content of complex types is also allowed.
22689             */
22690
22691             if (WXS_IS_COMPLEX(type)) {
22692                 if (WXS_HAS_SIMPLE_CONTENT(type)) {
22693                     /*
22694                     * Sanity check for complex types with simple content.
22695                     */
22696                     simpleType = type->contentTypeDef;
22697                     if (simpleType == NULL) {
22698                         VERROR_INT("xmlSchemaXPathProcessHistory",
22699                             "field resolves to a CT with simple content "
22700                             "but the CT is missing the ST definition");
22701                         return (-1);
22702                     }
22703                 } else
22704                     simpleType = NULL;
22705             } else
22706                 simpleType = type;
22707             if (simpleType == NULL) {
22708                 xmlChar *str = NULL;
22709
22710                 /*
22711                 * Not qualified if the field resolves to a node of non
22712                 * simple type.
22713                 */
22714                 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22715                     XML_SCHEMAV_CVC_IDC, NULL,
22716                     WXS_BASIC_CAST sto->matcher->aidc->def,
22717                     "The XPath '%s' of a field of %s does evaluate to a node of "
22718                     "non-simple type",
22719                     sto->sel->xpath,
22720                     xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22721                 FREE_AND_NULL(str);
22722                 sto->nbHistory--;
22723                 goto deregister_check;
22724             }
22725
22726             if ((key == NULL) && (vctxt->inode->val == NULL)) {
22727                 /*
22728                 * Failed to provide the normalized value; maybe
22729                 * the value was invalid.
22730                 */
22731                 VERROR(XML_SCHEMAV_CVC_IDC,
22732                     WXS_BASIC_CAST sto->matcher->aidc->def,
22733                     "Warning: No precomputed value available, the value "
22734                     "was either invalid or something strange happend");
22735                 sto->nbHistory--;
22736                 goto deregister_check;
22737             } else {
22738                 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22739                 xmlSchemaPSVIIDCKeyPtr *keySeq;
22740                 int pos, idx;
22741
22742                 /*
22743                 * The key will be anchored on the matcher's list of
22744                 * key-sequences. The position in this list is determined
22745                 * by the target node's depth relative to the matcher's
22746                 * depth of creation (i.e. the depth of the scope element).
22747                 *
22748                 * Element        Depth    Pos   List-entries
22749                 * <scope>          0              NULL
22750                 *   <bar>          1              NULL
22751                 *     <target/>    2       2      target
22752                 *   <bar>
22753                 * </scope>
22754                 *
22755                 * The size of the list is only dependant on the depth of
22756                 * the tree.
22757                 * An entry will be NULLed in selector_leave, i.e. when
22758                 * we hit the target's
22759                 */
22760                 pos = sto->depth - matcher->depth;
22761                 idx = sto->sel->index;
22762
22763                 /*
22764                 * Create/grow the array of key-sequences.
22765                 */
22766                 if (matcher->keySeqs == NULL) {
22767                     if (pos > 9)
22768                         matcher->sizeKeySeqs = pos * 2;
22769                     else
22770                         matcher->sizeKeySeqs = 10;
22771                     matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22772                         xmlMalloc(matcher->sizeKeySeqs *
22773                         sizeof(xmlSchemaPSVIIDCKeyPtr *));
22774                     if (matcher->keySeqs == NULL) {
22775                         xmlSchemaVErrMemory(NULL,
22776                             "allocating an array of key-sequences",
22777                             NULL);
22778                         return(-1);
22779                     }
22780                     memset(matcher->keySeqs, 0,
22781                         matcher->sizeKeySeqs *
22782                         sizeof(xmlSchemaPSVIIDCKeyPtr *));
22783                 } else if (pos >= matcher->sizeKeySeqs) {
22784                     int i = matcher->sizeKeySeqs;
22785
22786                     matcher->sizeKeySeqs *= 2;
22787                     matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22788                         xmlRealloc(matcher->keySeqs,
22789                         matcher->sizeKeySeqs *
22790                         sizeof(xmlSchemaPSVIIDCKeyPtr *));
22791                     if (matcher->keySeqs == NULL) {
22792                         xmlSchemaVErrMemory(NULL,
22793                             "reallocating an array of key-sequences",
22794                             NULL);
22795                         return (-1);
22796                     }
22797                     /*
22798                     * The array needs to be NULLed.
22799                     * TODO: Use memset?
22800                     */
22801                     for (; i < matcher->sizeKeySeqs; i++)
22802                         matcher->keySeqs[i] = NULL;
22803                 }
22804
22805                 /*
22806                 * Get/create the key-sequence.
22807                 */
22808                 keySeq = matcher->keySeqs[pos];
22809                 if (keySeq == NULL) {
22810                     goto create_sequence;
22811                 } else if (keySeq[idx] != NULL) {
22812                     xmlChar *str = NULL;
22813                     /*
22814                     * cvc-identity-constraint:
22815                     * 3 For each node in the ï¿½target node set� all
22816                     * of the {fields}, with that node as the context
22817                     * node, evaluate to either an empty node-set or
22818                     * a node-set with exactly one member, which must
22819                     * have a simple type.
22820                     *
22821                     * The key was already set; report an error.
22822                     */
22823                     xmlSchemaCustomErr(ACTXT_CAST vctxt,
22824                         XML_SCHEMAV_CVC_IDC, NULL,
22825                         WXS_BASIC_CAST matcher->aidc->def,
22826                         "The XPath '%s' of a field of %s evaluates to a "
22827                         "node-set with more than one member",
22828                         sto->sel->xpath,
22829                         xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22830                     FREE_AND_NULL(str);
22831                     sto->nbHistory--;
22832                     goto deregister_check;
22833                 } else
22834                     goto create_key;
22835
22836 create_sequence:
22837                 /*
22838                 * Create a key-sequence.
22839                 */
22840                 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22841                     matcher->aidc->def->nbFields *
22842                     sizeof(xmlSchemaPSVIIDCKeyPtr));
22843                 if (keySeq == NULL) {
22844                     xmlSchemaVErrMemory(NULL,
22845                         "allocating an IDC key-sequence", NULL);
22846                     return(-1);
22847                 }
22848                 memset(keySeq, 0, matcher->aidc->def->nbFields *
22849                     sizeof(xmlSchemaPSVIIDCKeyPtr));
22850                 matcher->keySeqs[pos] = keySeq;
22851 create_key:
22852                 /*
22853                 * Create a key once per node only.
22854                 */
22855                 if (key == NULL) {
22856                     key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22857                         sizeof(xmlSchemaPSVIIDCKey));
22858                     if (key == NULL) {
22859                         xmlSchemaVErrMemory(NULL,
22860                             "allocating a IDC key", NULL);
22861                         xmlFree(keySeq);
22862                         matcher->keySeqs[pos] = NULL;
22863                         return(-1);
22864                     }
22865                     /*
22866                     * Consume the compiled value.
22867                     */
22868                     key->type = simpleType;
22869                     key->val = vctxt->inode->val;
22870                     vctxt->inode->val = NULL;
22871                     /*
22872                     * Store the key in a global list.
22873                     */
22874                     if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22875                         xmlSchemaIDCFreeKey(key);
22876                         return (-1);
22877                     }
22878                 }
22879                 keySeq[idx] = key;
22880             }
22881         } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22882
22883             xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
22884             /* xmlSchemaPSVIIDCBindingPtr bind; */
22885             xmlSchemaPSVIIDCNodePtr ntItem;
22886             xmlSchemaIDCMatcherPtr matcher;
22887             xmlSchemaIDCPtr idc;
22888             xmlSchemaItemListPtr targets;
22889             int pos, i, j, nbKeys;
22890             /*
22891             * Here we have the following scenario:
22892             * An IDC 'selector' state object resolved to a target node,
22893             * during the time this target node was in the
22894             * ancestor-or-self axis, the 'field' state object(s) looked
22895             * out for matching nodes to create a key-sequence for this
22896             * target node. Now we are back to this target node and need
22897             * to put the key-sequence, together with the target node
22898             * itself, into the node-table of the corresponding IDC
22899             * binding.
22900             */
22901             matcher = sto->matcher;
22902             idc = matcher->aidc->def;
22903             nbKeys = idc->nbFields;
22904             pos = depth - matcher->depth;
22905             /*
22906             * Check if the matcher has any key-sequences at all, plus
22907             * if it has a key-sequence for the current target node.
22908             */
22909             if ((matcher->keySeqs == NULL) ||
22910                 (matcher->sizeKeySeqs <= pos)) {
22911                 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22912                     goto selector_key_error;
22913                 else
22914                     goto selector_leave;
22915             }
22916
22917             keySeq = &(matcher->keySeqs[pos]);
22918             if (*keySeq == NULL) {
22919                 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22920                     goto selector_key_error;
22921                 else
22922                     goto selector_leave;
22923             }
22924
22925             for (i = 0; i < nbKeys; i++) {
22926                 if ((*keySeq)[i] == NULL) {
22927                     /*
22928                     * Not qualified, if not all fields did resolve.
22929                     */
22930                     if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22931                         /*
22932                         * All fields of a "key" IDC must resolve.
22933                         */
22934                         goto selector_key_error;
22935                     }
22936                     goto selector_leave;
22937                 }
22938             }
22939             /*
22940             * All fields did resolve.
22941             */
22942
22943             /*
22944             * 4.1 If the {identity-constraint category} is unique(/key),
22945             * then no two members of the ï¿½qualified node set� have
22946             * ï¿½key-sequences� whose members are pairwise equal, as
22947             * defined by Equal in [XML Schemas: Datatypes].
22948             *
22949             * Get the IDC binding from the matcher and check for
22950             * duplicate key-sequences.
22951             */
22952 #if 0
22953             bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22954 #endif
22955             targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
22956             if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
22957                 (targets->nbItems != 0)) {
22958                 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
22959
22960                 i = 0;
22961                 res = 0;
22962                 /*
22963                 * Compare the key-sequences, key by key.
22964                 */
22965                 do {
22966                     bkeySeq =
22967                         ((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys;
22968                     for (j = 0; j < nbKeys; j++) {
22969                         ckey = (*keySeq)[j];
22970                         bkey = bkeySeq[j];
22971                         res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
22972                         if (res == -1) {
22973                             return (-1);
22974                         } else if (res == 0) {
22975                             /*
22976                             * One of the keys differs, so the key-sequence
22977                             * won't be equal; get out.
22978                             */
22979                             break;
22980                         }
22981                     }
22982                     if (res == 1) {
22983                         /*
22984                         * Duplicate key-sequence found.
22985                         */
22986                         break;
22987                     }
22988                     i++;
22989                 } while (i < targets->nbItems);
22990                 if (i != targets->nbItems) {
22991                     xmlChar *str = NULL, *strB = NULL;
22992                     /*
22993                     * TODO: Try to report the key-sequence.
22994                     */
22995                     xmlSchemaCustomErr(ACTXT_CAST vctxt,
22996                         XML_SCHEMAV_CVC_IDC, NULL,
22997                         WXS_BASIC_CAST idc,
22998                         "Duplicate key-sequence %s in %s",
22999                         xmlSchemaFormatIDCKeySequence(vctxt, &str,
23000                             (*keySeq), nbKeys),
23001                         xmlSchemaGetIDCDesignation(&strB, idc));
23002                     FREE_AND_NULL(str);
23003                     FREE_AND_NULL(strB);
23004                     goto selector_leave;
23005                 }
23006             }
23007             /*
23008             * Add a node-table item to the IDC binding.
23009             */
23010             ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
23011                 sizeof(xmlSchemaPSVIIDCNode));
23012             if (ntItem == NULL) {
23013                 xmlSchemaVErrMemory(NULL,
23014                     "allocating an IDC node-table item", NULL);
23015                 xmlFree(*keySeq);
23016                 *keySeq = NULL;
23017                 return(-1);
23018             }
23019             memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
23020
23021             /*
23022             * Store the node-table item in a global list.
23023             */
23024             if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23025                 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
23026                     xmlFree(ntItem);
23027                     xmlFree(*keySeq);
23028                     *keySeq = NULL;
23029                     return (-1);
23030                 }
23031                 ntItem->nodeQNameID = -1;
23032             } else {
23033                 /*
23034                 * Save a cached QName for this node on the IDC node, to be
23035                 * able to report it, even if the node is not saved.
23036                 */
23037                 ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
23038                     vctxt->inode->localName, vctxt->inode->nsName);
23039                 if (ntItem->nodeQNameID == -1) {
23040                     xmlFree(ntItem);
23041                     xmlFree(*keySeq);
23042                     *keySeq = NULL;
23043                     return (-1);
23044                 }
23045             }
23046             /*
23047             * Init the node-table item: Save the node, position and
23048             * consume the key-sequence.
23049             */
23050             ntItem->node = vctxt->node;
23051             ntItem->nodeLine = vctxt->inode->nodeLine;
23052             ntItem->keys = *keySeq;
23053             *keySeq = NULL;
23054 #if 0
23055             if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1)
23056 #endif
23057             if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
23058                 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23059                     /*
23060                     * Free the item, since keyref items won't be
23061                     * put on a global list.
23062                     */
23063                     xmlFree(ntItem->keys);
23064                     xmlFree(ntItem);
23065                 }
23066                 return (-1);
23067             }
23068
23069             goto selector_leave;
23070 selector_key_error:
23071             {
23072                 xmlChar *str = NULL;
23073                 /*
23074                 * 4.2.1 (KEY) The ï¿½target node set� and the
23075                 * ï¿½qualified node set� are equal, that is, every
23076                 * member of the ï¿½target node set� is also a member
23077                 * of the ï¿½qualified node set� and vice versa.
23078                 */
23079                 xmlSchemaCustomErr(ACTXT_CAST vctxt,
23080                     XML_SCHEMAV_CVC_IDC, NULL,
23081                     WXS_BASIC_CAST idc,
23082                     "Not all fields of %s evaluate to a node",
23083                     xmlSchemaGetIDCDesignation(&str, idc), NULL);
23084                 FREE_AND_NULL(str);
23085             }
23086 selector_leave:
23087             /*
23088             * Free the key-sequence if not added to the IDC table.
23089             */
23090             if ((keySeq != NULL) && (*keySeq != NULL)) {
23091                 xmlFree(*keySeq);
23092                 *keySeq = NULL;
23093             }
23094         } /* if selector */
23095
23096         sto->nbHistory--;
23097
23098 deregister_check:
23099         /*
23100         * Deregister state objects if they reach the depth of creation.
23101         */
23102         if ((sto->nbHistory == 0) && (sto->depth == depth)) {
23103 #ifdef DEBUG_IDC
23104             xmlGenericError(xmlGenericErrorContext, "IDC:   STO pop '%s'\n",
23105                 sto->sel->xpath);
23106 #endif
23107             if (vctxt->xpathStates != sto) {
23108                 VERROR_INT("xmlSchemaXPathProcessHistory",
23109                     "The state object to be removed is not the first "
23110                     "in the list");
23111             }
23112             nextsto = sto->next;
23113             /*
23114             * Unlink from the list of active XPath state objects.
23115             */
23116             vctxt->xpathStates = sto->next;
23117             sto->next = vctxt->xpathStatePool;
23118             /*
23119             * Link it to the pool of reusable state objects.
23120             */
23121             vctxt->xpathStatePool = sto;
23122             sto = nextsto;
23123         } else
23124             sto = sto->next;
23125     } /* while (sto != NULL) */
23126     return (0);
23127 }
23128
23129 /**
23130  * xmlSchemaIDCRegisterMatchers:
23131  * @vctxt: the WXS validation context
23132  * @elemDecl: the element declaration
23133  *
23134  * Creates helper objects to evaluate IDC selectors/fields
23135  * successively.
23136  *
23137  * Returns 0 if OK and -1 on internal errors.
23138  */
23139 static int
23140 xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
23141                              xmlSchemaElementPtr elemDecl)
23142 {
23143     xmlSchemaIDCMatcherPtr matcher, last = NULL;
23144     xmlSchemaIDCPtr idc, refIdc;
23145     xmlSchemaIDCAugPtr aidc;
23146
23147     idc = (xmlSchemaIDCPtr) elemDecl->idcs;
23148     if (idc == NULL)
23149         return (0);
23150
23151 #ifdef DEBUG_IDC
23152     {
23153         xmlChar *str = NULL;
23154         xmlGenericError(xmlGenericErrorContext,
23155             "IDC: REGISTER on %s, depth %d\n",
23156             (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
23157                 vctxt->inode->localName), vctxt->depth);
23158         FREE_AND_NULL(str)
23159     }
23160 #endif
23161     if (vctxt->inode->idcMatchers != NULL) {
23162         VERROR_INT("xmlSchemaIDCRegisterMatchers",
23163             "The chain of IDC matchers is expected to be empty");
23164         return (-1);
23165     }
23166     do {
23167         if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23168             /*
23169             * Since IDCs bubbles are expensive we need to know the
23170             * depth at which the bubbles should stop; this will be
23171             * the depth of the top-most keyref IDC. If no keyref
23172             * references a key/unique IDC, the keyrefDepth will
23173             * be -1, indicating that no bubbles are needed.
23174             */
23175             refIdc = (xmlSchemaIDCPtr) idc->ref->item;
23176             if (refIdc != NULL) {
23177                 /*
23178                 * Remember that we have keyrefs on this node.
23179                 */
23180                 vctxt->inode->hasKeyrefs = 1;
23181                 /*
23182                 * Lookup the referenced augmented IDC info.
23183                 */
23184                 aidc = vctxt->aidcs;
23185                 while (aidc != NULL) {
23186                     if (aidc->def == refIdc)
23187                         break;
23188                     aidc = aidc->next;
23189                 }
23190                 if (aidc == NULL) {
23191                     VERROR_INT("xmlSchemaIDCRegisterMatchers",
23192                         "Could not find an augmented IDC item for an IDC "
23193                         "definition");
23194                     return (-1);
23195                 }
23196                 if ((aidc->keyrefDepth == -1) ||
23197                     (vctxt->depth < aidc->keyrefDepth))
23198                     aidc->keyrefDepth = vctxt->depth;
23199             }
23200         }
23201         /*
23202         * Lookup the augmented IDC item for the IDC definition.
23203         */
23204         aidc = vctxt->aidcs;
23205         while (aidc != NULL) {
23206             if (aidc->def == idc)
23207                 break;
23208             aidc = aidc->next;
23209         }
23210         if (aidc == NULL) {
23211             VERROR_INT("xmlSchemaIDCRegisterMatchers",
23212                 "Could not find an augmented IDC item for an IDC definition");
23213             return (-1);
23214         }
23215         /*
23216         * Create an IDC matcher for every IDC definition.
23217         */
23218         if (vctxt->idcMatcherCache != NULL) {
23219             /*
23220             * Reuse a cached matcher.
23221             */
23222             matcher = vctxt->idcMatcherCache;
23223             vctxt->idcMatcherCache = matcher->nextCached;
23224             matcher->nextCached = NULL;
23225         } else {
23226             matcher = (xmlSchemaIDCMatcherPtr)
23227                 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
23228             if (matcher == NULL) {
23229                 xmlSchemaVErrMemory(vctxt,
23230                     "allocating an IDC matcher", NULL);
23231                 return (-1);
23232             }
23233             memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
23234         }
23235         if (last == NULL)
23236             vctxt->inode->idcMatchers = matcher;
23237         else
23238             last->next = matcher;
23239         last = matcher;
23240
23241         matcher->type = IDC_MATCHER;
23242         matcher->depth = vctxt->depth;
23243         matcher->aidc = aidc;
23244         matcher->idcType = aidc->def->type;
23245 #ifdef DEBUG_IDC
23246         xmlGenericError(xmlGenericErrorContext, "IDC:   register matcher\n");
23247 #endif
23248         /*
23249         * Init the automaton state object.
23250         */
23251         if (xmlSchemaIDCAddStateObject(vctxt, matcher,
23252             idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
23253             return (-1);
23254
23255         idc = idc->next;
23256     } while (idc != NULL);
23257     return (0);
23258 }
23259
23260 static int
23261 xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
23262                            xmlSchemaNodeInfoPtr ielem)
23263 {
23264     xmlSchemaPSVIIDCBindingPtr bind;
23265     int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
23266     xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
23267     xmlSchemaPSVIIDCNodePtr *targets, *dupls;
23268
23269     xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
23270     /* vctxt->createIDCNodeTables */
23271     while (matcher != NULL) {
23272         /*
23273         * Skip keyref IDCs and empty IDC target-lists.
23274         */
23275         if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
23276             WXS_ILIST_IS_EMPTY(matcher->targets))
23277         {
23278             matcher = matcher->next;
23279             continue;
23280         }
23281         /*
23282         * If we _want_ the IDC node-table to be created in any case
23283         * then do so. Otherwise create them only if keyrefs need them.
23284         */
23285         if ((! vctxt->createIDCNodeTables) &&
23286             ((matcher->aidc->keyrefDepth == -1) ||
23287              (matcher->aidc->keyrefDepth > vctxt->depth)))
23288         {
23289             matcher = matcher->next;
23290             continue;
23291         }
23292         /*
23293         * Get/create the IDC binding on this element for the IDC definition.
23294         */
23295         bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23296
23297         if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
23298             dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23299             nbDupls = bind->dupls->nbItems;
23300         } else {
23301             dupls = NULL;
23302             nbDupls = 0;
23303         }
23304         if (bind->nodeTable != NULL) {
23305             nbNodeTable = bind->nbNodes;
23306         } else {
23307             nbNodeTable = 0;
23308         }
23309
23310         if ((nbNodeTable == 0) && (nbDupls == 0)) {
23311             /*
23312             * Transfer all IDC target-nodes to the IDC node-table.
23313             */
23314             bind->nodeTable =
23315                 (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23316             bind->sizeNodes = matcher->targets->sizeItems;
23317             bind->nbNodes = matcher->targets->nbItems;
23318
23319             matcher->targets->items = NULL;
23320             matcher->targets->sizeItems = 0;
23321             matcher->targets->nbItems = 0;
23322         } else {
23323             /*
23324             * Compare the key-sequences and add to the IDC node-table.
23325             */
23326             nbTargets = matcher->targets->nbItems;
23327             targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23328             nbFields = matcher->aidc->def->nbFields;
23329             i = 0;
23330             do {
23331                 keys = targets[i]->keys;
23332                 if (nbDupls) {
23333                     /*
23334                     * Search in already found duplicates first.
23335                     */
23336                     j = 0;
23337                     do {
23338                         if (nbFields == 1) {
23339                             res = xmlSchemaAreValuesEqual(keys[0]->val,
23340                                 dupls[j]->keys[0]->val);
23341                             if (res == -1)
23342                                 goto internal_error;
23343                             if (res == 1) {
23344                                 /*
23345                                 * Equal key-sequence.
23346                                 */
23347                                 goto next_target;
23348                             }
23349                         } else {
23350                             res = 0;
23351                             ntkeys = dupls[j]->keys;
23352                             for (k = 0; k < nbFields; k++) {
23353                                 res = xmlSchemaAreValuesEqual(keys[k]->val,
23354                                     ntkeys[k]->val);
23355                                 if (res == -1)
23356                                     goto internal_error;
23357                                 if (res == 0) {
23358                                     /*
23359                                     * One of the keys differs.
23360                                     */
23361                                     break;
23362                                 }
23363                             }
23364                             if (res == 1) {
23365                                 /*
23366                                 * Equal key-sequence found.
23367                                 */
23368                                 goto next_target;
23369                             }
23370                         }
23371                         j++;
23372                     } while (j < nbDupls);
23373                 }
23374                 if (nbNodeTable) {
23375                     j = 0;
23376                     do {
23377                         if (nbFields == 1) {
23378                             res = xmlSchemaAreValuesEqual(keys[0]->val,
23379                                 bind->nodeTable[j]->keys[0]->val);
23380                             if (res == -1)
23381                                 goto internal_error;
23382                             if (res == 0) {
23383                                 /*
23384                                 * The key-sequence differs.
23385                                 */
23386                                 goto next_node_table_entry;
23387                             }
23388                         } else {
23389                             res = 0;
23390                             ntkeys = bind->nodeTable[j]->keys;
23391                             for (k = 0; k < nbFields; k++) {
23392                                 res = xmlSchemaAreValuesEqual(keys[k]->val,
23393                                     ntkeys[k]->val);
23394                                 if (res == -1)
23395                                     goto internal_error;
23396                                 if (res == 0) {
23397                                     /*
23398                                     * One of the keys differs.
23399                                     */
23400                                     goto next_node_table_entry;
23401                                 }
23402                             }
23403                         }
23404                         /*
23405                         * Add the duplicate to the list of duplicates.
23406                         */
23407                         if (bind->dupls == NULL) {
23408                             bind->dupls = xmlSchemaItemListCreate();
23409                             if (bind->dupls == NULL)
23410                                 goto internal_error;
23411                         }
23412                         if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23413                             goto internal_error;
23414                         /*
23415                         * Remove the duplicate entry from the IDC node-table.
23416                         */
23417                         bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23418                         bind->nbNodes--;
23419
23420                         goto next_target;
23421
23422 next_node_table_entry:
23423                         j++;
23424                     } while (j < nbNodeTable);
23425                 }
23426                 /*
23427                 * If everything is fine, then add the IDC target-node to
23428                 * the IDC node-table.
23429                 */
23430                 if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23431                     goto internal_error;
23432
23433 next_target:
23434                 i++;
23435             } while (i < nbTargets);
23436         }
23437         matcher = matcher->next;
23438     }
23439     return(0);
23440
23441 internal_error:
23442     return(-1);
23443 }
23444
23445 /**
23446  * xmlSchemaBubbleIDCNodeTables:
23447  * @depth: the current tree depth
23448  *
23449  * Merges IDC bindings of an element at @depth into the corresponding IDC
23450  * bindings of its parent element. If a duplicate note-table entry is found,
23451  * both, the parent node-table entry and child entry are discarded from the
23452  * node-table of the parent.
23453  *
23454  * Returns 0 if OK and -1 on internal errors.
23455  */
23456 static int
23457 xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23458 {
23459     xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
23460     xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23461     xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
23462     xmlSchemaIDCAugPtr aidc;
23463     int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
23464
23465     bind = vctxt->inode->idcTable;
23466     if (bind == NULL) {
23467         /* Fine, no table, no bubbles. */
23468         return (0);
23469     }
23470
23471     parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23472     /*
23473     * Walk all bindings; create new or add to existing bindings.
23474     * Remove duplicate key-sequences.
23475     */
23476     while (bind != NULL) {
23477
23478         if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23479             goto next_binding;
23480         /*
23481         * Check if the key/unique IDC table needs to be bubbled.
23482         */
23483         if (! vctxt->createIDCNodeTables) {
23484             aidc = vctxt->aidcs;
23485             do {
23486                 if (aidc->def == bind->definition) {
23487                     if ((aidc->keyrefDepth == -1) ||
23488                         (aidc->keyrefDepth >= vctxt->depth)) {
23489                         goto next_binding;
23490                     }
23491                     break;
23492                 }
23493                 aidc = aidc->next;
23494             } while (aidc != NULL);
23495         }
23496
23497         if (parTable != NULL)
23498             parBind = *parTable;
23499         /*
23500         * Search a matching parent binding for the
23501         * IDC definition.
23502         */
23503         while (parBind != NULL) {
23504             if (parBind->definition == bind->definition)
23505                 break;
23506             parBind = parBind->next;
23507         }
23508
23509         if (parBind != NULL) {
23510             /*
23511             * Compare every node-table entry of the child node,
23512             * i.e. the key-sequence within, ...
23513             */
23514             oldNum = parBind->nbNodes; /* Skip newly added items. */
23515
23516             if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23517                 oldDupls = parBind->dupls->nbItems;
23518                 dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23519             } else {
23520                 dupls = NULL;
23521                 oldDupls = 0;
23522             }
23523
23524             parNodes = parBind->nodeTable;
23525             nbFields = bind->definition->nbFields;
23526
23527             for (i = 0; i < bind->nbNodes; i++) {
23528                 node = bind->nodeTable[i];
23529                 if (node == NULL)
23530                     continue;
23531                 /*
23532                 * ...with every key-sequence of the parent node, already
23533                 * evaluated to be a duplicate key-sequence.
23534                 */
23535                 if (oldDupls) {
23536                     j = 0;
23537                     while (j < oldDupls) {
23538                         if (nbFields == 1) {
23539                             ret = xmlSchemaAreValuesEqual(
23540                                 node->keys[0]->val,
23541                                 dupls[j]->keys[0]->val);
23542                             if (ret == -1)
23543                                 goto internal_error;
23544                             if (ret == 0) {
23545                                 j++;
23546                                 continue;
23547                             }
23548                         } else {
23549                             parNode = dupls[j];
23550                             for (k = 0; k < nbFields; k++) {
23551                                 ret = xmlSchemaAreValuesEqual(
23552                                     node->keys[k]->val,
23553                                     parNode->keys[k]->val);
23554                                 if (ret == -1)
23555                                     goto internal_error;
23556                                 if (ret == 0)
23557                                     break;
23558                             }
23559                         }
23560                         if (ret == 1)
23561                             /* Duplicate found. */
23562                             break;
23563                         j++;
23564                     }
23565                     if (j != oldDupls) {
23566                         /* Duplicate found. Skip this entry. */
23567                         continue;
23568                     }
23569                 }
23570                 /*
23571                 * ... and with every key-sequence of the parent node.
23572                 */
23573                 if (oldNum) {
23574                     j = 0;
23575                     while (j < oldNum) {
23576                         parNode = parNodes[j];
23577                         if (nbFields == 1) {
23578                             ret = xmlSchemaAreValuesEqual(
23579                                 node->keys[0]->val,
23580                                 parNode->keys[0]->val);
23581                             if (ret == -1)
23582                                 goto internal_error;
23583                             if (ret == 0) {
23584                                 j++;
23585                                 continue;
23586                             }
23587                         } else {
23588                             for (k = 0; k < nbFields; k++) {
23589                                 ret = xmlSchemaAreValuesEqual(
23590                                     node->keys[k]->val,
23591                                     parNode->keys[k]->val);
23592                                 if (ret == -1)
23593                                     goto internal_error;
23594                                 if (ret == 0)
23595                                     break;
23596                             }
23597                         }
23598                         if (ret == 1)
23599                             /* Duplicate found. */
23600                             break;
23601                         j++;
23602                     }
23603                     if (j != oldNum) {
23604                         /*
23605                         * Handle duplicates. Move the duplicate in
23606                         * the parent's node-table to the list of
23607                         * duplicates.
23608                         */
23609                         oldNum--;
23610                         parBind->nbNodes--;
23611                         /*
23612                         * Move last old item to pos of duplicate.
23613                         */
23614                         parNodes[j] = parNodes[oldNum];
23615
23616                         if (parBind->nbNodes != oldNum) {
23617                             /*
23618                             * If new items exist, move last new item to
23619                             * last of old items.
23620                             */
23621                             parNodes[oldNum] =
23622                                 parNodes[parBind->nbNodes];
23623                         }
23624                         if (parBind->dupls == NULL) {
23625                             parBind->dupls = xmlSchemaItemListCreate();
23626                             if (parBind->dupls == NULL)
23627                                 goto internal_error;
23628                         }
23629                         xmlSchemaItemListAdd(parBind->dupls, parNode);
23630                     } else {
23631                         /*
23632                         * Add the node-table entry (node and key-sequence) of
23633                         * the child node to the node table of the parent node.
23634                         */
23635                         if (parBind->nodeTable == NULL) {
23636                             parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23637                                 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
23638                             if (parBind->nodeTable == NULL) {
23639                                 xmlSchemaVErrMemory(NULL,
23640                                     "allocating IDC list of node-table items", NULL);
23641                                 goto internal_error;
23642                             }
23643                             parBind->sizeNodes = 1;
23644                         } else if (parBind->nbNodes >= parBind->sizeNodes) {
23645                             parBind->sizeNodes *= 2;
23646                             parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23647                                 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23648                                 sizeof(xmlSchemaPSVIIDCNodePtr));
23649                             if (parBind->nodeTable == NULL) {
23650                                 xmlSchemaVErrMemory(NULL,
23651                                     "re-allocating IDC list of node-table items", NULL);
23652                                 goto internal_error;
23653                             }
23654                         }
23655                         parNodes = parBind->nodeTable;
23656                         /*
23657                         * Append the new node-table entry to the 'new node-table
23658                         * entries' section.
23659                         */
23660                         parNodes[parBind->nbNodes++] = node;
23661                     }
23662
23663                 }
23664
23665             }
23666         } else {
23667             /*
23668             * No binding for the IDC was found: create a new one and
23669             * copy all node-tables.
23670             */
23671             parBind = xmlSchemaIDCNewBinding(bind->definition);
23672             if (parBind == NULL)
23673                 goto internal_error;
23674
23675             /*
23676             * TODO: Hmm, how to optimize the initial number of
23677             * allocated entries?
23678             */
23679             if (bind->nbNodes != 0) {
23680                 /*
23681                 * Add all IDC node-table entries.
23682                 */
23683                 if (! vctxt->psviExposeIDCNodeTables) {
23684                     /*
23685                     * Just move the entries.
23686                     * NOTE: this is quite save here, since
23687                     * all the keyref lookups have already been
23688                     * performed.
23689                     */
23690                     parBind->nodeTable = bind->nodeTable;
23691                     bind->nodeTable = NULL;
23692                     parBind->sizeNodes = bind->sizeNodes;
23693                     bind->sizeNodes = 0;
23694                     parBind->nbNodes = bind->nbNodes;
23695                     bind->nbNodes = 0;
23696                 } else {
23697                     /*
23698                     * Copy the entries.
23699                     */
23700                     parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23701                         xmlMalloc(bind->nbNodes *
23702                         sizeof(xmlSchemaPSVIIDCNodePtr));
23703                     if (parBind->nodeTable == NULL) {
23704                         xmlSchemaVErrMemory(NULL,
23705                             "allocating an array of IDC node-table "
23706                             "items", NULL);
23707                         xmlSchemaIDCFreeBinding(parBind);
23708                         goto internal_error;
23709                     }
23710                     parBind->sizeNodes = bind->nbNodes;
23711                     parBind->nbNodes = bind->nbNodes;
23712                     memcpy(parBind->nodeTable, bind->nodeTable,
23713                         bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23714                 }
23715             }
23716             if (bind->dupls) {
23717                 /*
23718                 * Move the duplicates.
23719                 */
23720                 if (parBind->dupls != NULL)
23721                     xmlSchemaItemListFree(parBind->dupls);
23722                 parBind->dupls = bind->dupls;
23723                 bind->dupls = NULL;
23724             }
23725             if (parTable != NULL) {
23726                 if (*parTable == NULL)
23727                     *parTable = parBind;
23728                 else {
23729                     parBind->next = *parTable;
23730                     *parTable = parBind;
23731                 }
23732             }
23733         }
23734
23735 next_binding:
23736         bind = bind->next;
23737     }
23738     return (0);
23739
23740 internal_error:
23741     return(-1);
23742 }
23743
23744 /**
23745  * xmlSchemaCheckCVCIDCKeyRef:
23746  * @vctxt: the WXS validation context
23747  * @elemDecl: the element declaration
23748  *
23749  * Check the cvc-idc-keyref constraints.
23750  */
23751 static int
23752 xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23753 {
23754     xmlSchemaIDCMatcherPtr matcher;
23755     xmlSchemaPSVIIDCBindingPtr bind;
23756
23757     matcher = vctxt->inode->idcMatchers;
23758     /*
23759     * Find a keyref.
23760     */
23761     while (matcher != NULL) {
23762         if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23763             matcher->targets &&
23764             matcher->targets->nbItems)
23765         {
23766             int i, j, k, res, nbFields, hasDupls;
23767             xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
23768             xmlSchemaPSVIIDCNodePtr refNode = NULL;
23769
23770             nbFields = matcher->aidc->def->nbFields;
23771
23772             /*
23773             * Find the IDC node-table for the referenced IDC key/unique.
23774             */
23775             bind = vctxt->inode->idcTable;
23776             while (bind != NULL) {
23777                 if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
23778                     bind->definition)
23779                     break;
23780                 bind = bind->next;
23781             }
23782             hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
23783             /*
23784             * Search for a matching key-sequences.
23785             */
23786             for (i = 0; i < matcher->targets->nbItems; i++) {
23787                 res = 0;
23788                 refNode = matcher->targets->items[i];
23789                 if (bind != NULL) {
23790                     refKeys = refNode->keys;
23791                     for (j = 0; j < bind->nbNodes; j++) {
23792                         keys = bind->nodeTable[j]->keys;
23793                         for (k = 0; k < nbFields; k++) {
23794                             res = xmlSchemaAreValuesEqual(keys[k]->val,
23795                                 refKeys[k]->val);
23796                             if (res == 0)
23797                                 break;
23798                             else if (res == -1) {
23799                                 return (-1);
23800                             }
23801                         }
23802                         if (res == 1) {
23803                             /*
23804                             * Match found.
23805                             */
23806                             break;
23807                         }
23808                     }
23809                     if ((res == 0) && hasDupls) {
23810                         /*
23811                         * Search in duplicates
23812                         */
23813                         for (j = 0; j < bind->dupls->nbItems; j++) {
23814                             keys = ((xmlSchemaPSVIIDCNodePtr)
23815                                 bind->dupls->items[j])->keys;
23816                             for (k = 0; k < nbFields; k++) {
23817                                 res = xmlSchemaAreValuesEqual(keys[k]->val,
23818                                     refKeys[k]->val);
23819                                 if (res == 0)
23820                                     break;
23821                                 else if (res == -1) {
23822                                     return (-1);
23823                                 }
23824                             }
23825                             if (res == 1) {
23826                                 /*
23827                                 * Match in duplicates found.
23828                                 */
23829                                 xmlChar *str = NULL, *strB = NULL;
23830                                 xmlSchemaKeyrefErr(vctxt,
23831                                     XML_SCHEMAV_CVC_IDC, refNode,
23832                                     (xmlSchemaTypePtr) matcher->aidc->def,
23833                                     "More than one match found for "
23834                                     "key-sequence %s of keyref '%s'",
23835                                     xmlSchemaFormatIDCKeySequence(vctxt, &str,
23836                                         refNode->keys, nbFields),
23837                                     xmlSchemaGetComponentQName(&strB,
23838                                         matcher->aidc->def));
23839                                 FREE_AND_NULL(str);
23840                                 FREE_AND_NULL(strB);
23841                                 break;
23842                             }
23843                         }
23844                     }
23845                 }
23846
23847                 if (res == 0) {
23848                     xmlChar *str = NULL, *strB = NULL;
23849                     xmlSchemaKeyrefErr(vctxt,
23850                         XML_SCHEMAV_CVC_IDC, refNode,
23851                         (xmlSchemaTypePtr) matcher->aidc->def,
23852                         "No match found for key-sequence %s of keyref '%s'",
23853                         xmlSchemaFormatIDCKeySequence(vctxt, &str,
23854                             refNode->keys, nbFields),
23855                         xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
23856                     FREE_AND_NULL(str);
23857                     FREE_AND_NULL(strB);
23858                 }
23859             }
23860         }
23861         matcher = matcher->next;
23862     }
23863     /* TODO: Return an error if any error encountered. */
23864     return (0);
23865 }
23866
23867 /************************************************************************
23868  *                                                                      *
23869  *                      XML Reader validation code                      *
23870  *                                                                      *
23871  ************************************************************************/
23872
23873 static xmlSchemaAttrInfoPtr
23874 xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
23875 {
23876     xmlSchemaAttrInfoPtr iattr;
23877     /*
23878     * Grow/create list of attribute infos.
23879     */
23880     if (vctxt->attrInfos == NULL) {
23881         vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23882             xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23883         vctxt->sizeAttrInfos = 1;
23884         if (vctxt->attrInfos == NULL) {
23885             xmlSchemaVErrMemory(vctxt,
23886                 "allocating attribute info list", NULL);
23887             return (NULL);
23888         }
23889     } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23890         vctxt->sizeAttrInfos++;
23891         vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23892             xmlRealloc(vctxt->attrInfos,
23893                 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23894         if (vctxt->attrInfos == NULL) {
23895             xmlSchemaVErrMemory(vctxt,
23896                 "re-allocating attribute info list", NULL);
23897             return (NULL);
23898         }
23899     } else {
23900         iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23901         if (iattr->localName != NULL) {
23902             VERROR_INT("xmlSchemaGetFreshAttrInfo",
23903                 "attr info not cleared");
23904             return (NULL);
23905         }
23906         iattr->nodeType = XML_ATTRIBUTE_NODE;
23907         return (iattr);
23908     }
23909     /*
23910     * Create an attribute info.
23911     */
23912     iattr = (xmlSchemaAttrInfoPtr)
23913         xmlMalloc(sizeof(xmlSchemaAttrInfo));
23914     if (iattr == NULL) {
23915         xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
23916         return (NULL);
23917     }
23918     memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23919     iattr->nodeType = XML_ATTRIBUTE_NODE;
23920     vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23921
23922     return (iattr);
23923 }
23924
23925 static int
23926 xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23927                         xmlNodePtr attrNode,
23928                         int nodeLine,
23929                         const xmlChar *localName,
23930                         const xmlChar *nsName,
23931                         int ownedNames,
23932                         xmlChar *value,
23933                         int ownedValue)
23934 {
23935     xmlSchemaAttrInfoPtr attr;
23936
23937     attr = xmlSchemaGetFreshAttrInfo(vctxt);
23938     if (attr == NULL) {
23939         VERROR_INT("xmlSchemaPushAttribute",
23940             "calling xmlSchemaGetFreshAttrInfo()");
23941         return (-1);
23942     }
23943     attr->node = attrNode;
23944     attr->nodeLine = nodeLine;
23945     attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23946     attr->localName = localName;
23947     attr->nsName = nsName;
23948     if (ownedNames)
23949         attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23950     /*
23951     * Evaluate if it's an XSI attribute.
23952     */
23953     if (nsName != NULL) {
23954         if (xmlStrEqual(localName, BAD_CAST "nil")) {
23955             if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23956                 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
23957             }
23958         } else if (xmlStrEqual(localName, BAD_CAST "type")) {
23959             if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23960                 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
23961             }
23962         } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
23963             if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23964                 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
23965             }
23966         } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
23967             if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23968                 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
23969             }
23970         } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
23971             attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
23972         }
23973     }
23974     attr->value = value;
23975     if (ownedValue)
23976         attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23977     if (attr->metaType != 0)
23978         attr->state = XML_SCHEMAS_ATTR_META;
23979     return (0);
23980 }
23981
23982 /**
23983  * xmlSchemaClearElemInfo:
23984  * @vctxt: the WXS validation context
23985  * @ielem: the element information item
23986  */
23987 static void
23988 xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,
23989                        xmlSchemaNodeInfoPtr ielem)
23990 {
23991     ielem->hasKeyrefs = 0;
23992     ielem->appliedXPath = 0;
23993     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
23994         FREE_AND_NULL(ielem->localName);
23995         FREE_AND_NULL(ielem->nsName);
23996     } else {
23997         ielem->localName = NULL;
23998         ielem->nsName = NULL;
23999     }
24000     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24001         FREE_AND_NULL(ielem->value);
24002     } else {
24003         ielem->value = NULL;
24004     }
24005     if (ielem->val != NULL) {
24006         /*
24007         * PSVI TODO: Be careful not to free it when the value is
24008         * exposed via PSVI.
24009         */
24010         xmlSchemaFreeValue(ielem->val);
24011         ielem->val = NULL;
24012     }
24013     if (ielem->idcMatchers != NULL) {
24014         /*
24015         * REVISIT OPTIMIZE TODO: Use a pool of IDC matchers.
24016         *   Does it work?
24017         */
24018         xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers);
24019 #if 0
24020         xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
24021 #endif
24022         ielem->idcMatchers = NULL;
24023     }
24024     if (ielem->idcTable != NULL) {
24025         /*
24026         * OPTIMIZE TODO: Use a pool of IDC tables??.
24027         */
24028         xmlSchemaIDCFreeIDCTable(ielem->idcTable);
24029         ielem->idcTable = NULL;
24030     }
24031     if (ielem->regexCtxt != NULL) {
24032         xmlRegFreeExecCtxt(ielem->regexCtxt);
24033         ielem->regexCtxt = NULL;
24034     }
24035     if (ielem->nsBindings != NULL) {
24036         xmlFree((xmlChar **)ielem->nsBindings);
24037         ielem->nsBindings = NULL;
24038         ielem->nbNsBindings = 0;
24039         ielem->sizeNsBindings = 0;
24040     }
24041 }
24042
24043 /**
24044  * xmlSchemaGetFreshElemInfo:
24045  * @vctxt: the schema validation context
24046  *
24047  * Creates/reuses and initializes the element info item for
24048  * the currect tree depth.
24049  *
24050  * Returns the element info item or NULL on API or internal errors.
24051  */
24052 static xmlSchemaNodeInfoPtr
24053 xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
24054 {
24055     xmlSchemaNodeInfoPtr info = NULL;
24056
24057     if (vctxt->depth > vctxt->sizeElemInfos) {
24058         VERROR_INT("xmlSchemaGetFreshElemInfo",
24059             "inconsistent depth encountered");
24060         return (NULL);
24061     }
24062     if (vctxt->elemInfos == NULL) {
24063         vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24064             xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
24065         if (vctxt->elemInfos == NULL) {
24066             xmlSchemaVErrMemory(vctxt,
24067                 "allocating the element info array", NULL);
24068             return (NULL);
24069         }
24070         memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
24071         vctxt->sizeElemInfos = 10;
24072     } else if (vctxt->sizeElemInfos <= vctxt->depth) {
24073         int i = vctxt->sizeElemInfos;
24074
24075         vctxt->sizeElemInfos *= 2;
24076         vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24077             xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
24078             sizeof(xmlSchemaNodeInfoPtr));
24079         if (vctxt->elemInfos == NULL) {
24080             xmlSchemaVErrMemory(vctxt,
24081                 "re-allocating the element info array", NULL);
24082             return (NULL);
24083         }
24084         /*
24085         * We need the new memory to be NULLed.
24086         * TODO: Use memset instead?
24087         */
24088         for (; i < vctxt->sizeElemInfos; i++)
24089             vctxt->elemInfos[i] = NULL;
24090     } else
24091         info = vctxt->elemInfos[vctxt->depth];
24092
24093     if (info == NULL) {
24094         info = (xmlSchemaNodeInfoPtr)
24095             xmlMalloc(sizeof(xmlSchemaNodeInfo));
24096         if (info == NULL) {
24097             xmlSchemaVErrMemory(vctxt,
24098                 "allocating an element info", NULL);
24099             return (NULL);
24100         }
24101         vctxt->elemInfos[vctxt->depth] = info;
24102     } else {
24103         if (info->localName != NULL) {
24104             VERROR_INT("xmlSchemaGetFreshElemInfo",
24105                 "elem info has not been cleared");
24106             return (NULL);
24107         }
24108     }
24109     memset(info, 0, sizeof(xmlSchemaNodeInfo));
24110     info->nodeType = XML_ELEMENT_NODE;
24111     info->depth = vctxt->depth;
24112
24113     return (info);
24114 }
24115
24116 #define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
24117 #define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
24118 #define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
24119
24120 static int
24121 xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
24122                         xmlNodePtr node,
24123                         xmlSchemaTypePtr type,
24124                         xmlSchemaValType valType,
24125                         const xmlChar * value,
24126                         xmlSchemaValPtr val,
24127                         unsigned long length,
24128                         int fireErrors)
24129 {
24130     int ret, error = 0;
24131
24132     xmlSchemaTypePtr tmpType;
24133     xmlSchemaFacetLinkPtr facetLink;
24134     xmlSchemaFacetPtr facet;
24135     unsigned long len = 0;
24136     xmlSchemaWhitespaceValueType ws;
24137
24138     /*
24139     * In Libxml2, derived built-in types have currently no explicit facets.
24140     */
24141     if (type->type == XML_SCHEMA_TYPE_BASIC)
24142         return (0);
24143
24144     /*
24145     * NOTE: Do not jump away, if the facetSet of the given type is
24146     * empty: until now, "pattern" and "enumeration" facets of the
24147     * *base types* need to be checked as well.
24148     */
24149     if (type->facetSet == NULL)
24150         goto pattern_and_enum;
24151
24152     if (! WXS_IS_ATOMIC(type)) {
24153         if (WXS_IS_LIST(type))
24154             goto WXS_IS_LIST;
24155         else
24156             goto pattern_and_enum;
24157     }
24158     /*
24159     * Whitespace handling is only of importance for string-based
24160     * types.
24161     */
24162     tmpType = xmlSchemaGetPrimitiveType(type);
24163     if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
24164         WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
24165         ws = xmlSchemaGetWhiteSpaceFacetValue(type);
24166     } else
24167         ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
24168     /*
24169     * If the value was not computed (for string or
24170     * anySimpleType based types), then use the provided
24171     * type.
24172     */
24173     if (val == NULL)
24174         valType = valType;
24175     else
24176         valType = xmlSchemaGetValType(val);
24177
24178     ret = 0;
24179     for (facetLink = type->facetSet; facetLink != NULL;
24180         facetLink = facetLink->next) {
24181         /*
24182         * Skip the pattern "whiteSpace": it is used to
24183         * format the character content beforehand.
24184         */
24185         switch (facetLink->facet->type) {
24186             case XML_SCHEMA_FACET_WHITESPACE:
24187             case XML_SCHEMA_FACET_PATTERN:
24188             case XML_SCHEMA_FACET_ENUMERATION:
24189                 continue;
24190             case XML_SCHEMA_FACET_LENGTH:
24191             case XML_SCHEMA_FACET_MINLENGTH:
24192             case XML_SCHEMA_FACET_MAXLENGTH:
24193                 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
24194                     valType, value, val, &len, ws);
24195                 break;
24196             default:
24197                 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
24198                     valType, value, val, ws);
24199                 break;
24200         }
24201         if (ret < 0) {
24202             AERROR_INT("xmlSchemaValidateFacets",
24203                 "validating against a atomic type facet");
24204             return (-1);
24205         } else if (ret > 0) {
24206             if (fireErrors)
24207                 xmlSchemaFacetErr(actxt, ret, node,
24208                 value, len, type, facetLink->facet, NULL, NULL, NULL);
24209             else
24210                 return (ret);
24211             if (error == 0)
24212                 error = ret;
24213         }
24214         ret = 0;
24215     }
24216
24217 WXS_IS_LIST:
24218     if (! WXS_IS_LIST(type))
24219         goto pattern_and_enum;
24220     /*
24221     * "length", "minLength" and "maxLength" of list types.
24222     */
24223     ret = 0;
24224     for (facetLink = type->facetSet; facetLink != NULL;
24225         facetLink = facetLink->next) {
24226
24227         switch (facetLink->facet->type) {
24228             case XML_SCHEMA_FACET_LENGTH:
24229             case XML_SCHEMA_FACET_MINLENGTH:
24230             case XML_SCHEMA_FACET_MAXLENGTH:
24231                 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
24232                     value, length, NULL);
24233                 break;
24234             default:
24235                 continue;
24236         }
24237         if (ret < 0) {
24238             AERROR_INT("xmlSchemaValidateFacets",
24239                 "validating against a list type facet");
24240             return (-1);
24241         } else if (ret > 0) {
24242             if (fireErrors)
24243                 xmlSchemaFacetErr(actxt, ret, node,
24244                 value, length, type, facetLink->facet, NULL, NULL, NULL);
24245             else
24246                 return (ret);
24247             if (error == 0)
24248                 error = ret;
24249         }
24250         ret = 0;
24251     }
24252
24253 pattern_and_enum:
24254     if (error >= 0) {
24255         int found = 0;
24256         /*
24257         * Process enumerations. Facet values are in the value space
24258         * of the defining type's base type. This seems to be a bug in the
24259         * XML Schema 1.0 spec. Use the whitespace type of the base type.
24260         * Only the first set of enumerations in the ancestor-or-self axis
24261         * is used for validation.
24262         */
24263         ret = 0;
24264         tmpType = type;
24265         do {
24266             for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
24267                 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
24268                     continue;
24269                 found = 1;
24270                 ret = xmlSchemaAreValuesEqual(facet->val, val);
24271                 if (ret == 1)
24272                     break;
24273                 else if (ret < 0) {
24274                     AERROR_INT("xmlSchemaValidateFacets",
24275                         "validating against an enumeration facet");
24276                     return (-1);
24277                 }
24278             }
24279             if (ret != 0)
24280                 break;
24281             /*
24282             * Break on the first set of enumerations. Any additional
24283             *  enumerations which might be existent on the ancestors
24284             *  of the current type are restricted by this set; thus
24285             *  *must* *not* be taken into account.
24286             */
24287             if (found)
24288                 break;
24289             tmpType = tmpType->baseType;
24290         } while ((tmpType != NULL) &&
24291             (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24292         if (found && (ret == 0)) {
24293             ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
24294             if (fireErrors) {
24295                 xmlSchemaFacetErr(actxt, ret, node,
24296                     value, 0, type, NULL, NULL, NULL, NULL);
24297             } else
24298                 return (ret);
24299             if (error == 0)
24300                 error = ret;
24301         }
24302     }
24303
24304     if (error >= 0) {
24305         int found;
24306         /*
24307         * Process patters. Pattern facets are ORed at type level
24308         * and ANDed if derived. Walk the base type axis.
24309         */
24310         tmpType = type;
24311         facet = NULL;
24312         do {
24313             found = 0;
24314             for (facetLink = tmpType->facetSet; facetLink != NULL;
24315                 facetLink = facetLink->next) {
24316                 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
24317                     continue;
24318                 found = 1;
24319                 /*
24320                 * NOTE that for patterns, @value needs to be the
24321                 * normalized vaule.
24322                 */
24323                 ret = xmlRegexpExec(facetLink->facet->regexp, value);
24324                 if (ret == 1)
24325                     break;
24326                 else if (ret < 0) {
24327                     AERROR_INT("xmlSchemaValidateFacets",
24328                         "validating against a pattern facet");
24329                     return (-1);
24330                 } else {
24331                     /*
24332                     * Save the last non-validating facet.
24333                     */
24334                     facet = facetLink->facet;
24335                 }
24336             }
24337             if (found && (ret != 1)) {
24338                 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
24339                 if (fireErrors) {
24340                     xmlSchemaFacetErr(actxt, ret, node,
24341                         value, 0, type, facet, NULL, NULL, NULL);
24342                 } else
24343                     return (ret);
24344                 if (error == 0)
24345                     error = ret;
24346                 break;
24347             }
24348             tmpType = tmpType->baseType;
24349         } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24350     }
24351
24352     return (error);
24353 }
24354
24355 static xmlChar *
24356 xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24357                         const xmlChar *value)
24358 {
24359     switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
24360         case XML_SCHEMA_WHITESPACE_COLLAPSE:
24361             return (xmlSchemaCollapseString(value));
24362         case XML_SCHEMA_WHITESPACE_REPLACE:
24363             return (xmlSchemaWhiteSpaceReplace(value));
24364         default:
24365             return (NULL);
24366     }
24367 }
24368
24369 static int
24370 xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24371                        const xmlChar *value,
24372                        xmlSchemaValPtr *val,
24373                        int valNeeded)
24374 {
24375     int ret;
24376     const xmlChar *nsName;
24377     xmlChar *local, *prefix = NULL;
24378
24379     ret = xmlValidateQName(value, 1);
24380     if (ret != 0) {
24381         if (ret == -1) {
24382             VERROR_INT("xmlSchemaValidateQName",
24383                 "calling xmlValidateQName()");
24384             return (-1);
24385         }
24386         return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24387     }
24388     /*
24389     * NOTE: xmlSplitQName2 will always return a duplicated
24390     * strings.
24391     */
24392     local = xmlSplitQName2(value, &prefix);
24393     if (local == NULL)
24394         local = xmlStrdup(value);
24395     /*
24396     * OPTIMIZE TODO: Use flags for:
24397     *  - is there any namespace binding?
24398     *  - is there a default namespace?
24399     */
24400     nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24401
24402     if (prefix != NULL) {
24403         xmlFree(prefix);
24404         /*
24405         * A namespace must be found if the prefix is
24406         * NOT NULL.
24407         */
24408         if (nsName == NULL) {
24409             ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24410             xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
24411                 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24412                 "The QName value '%s' has no "
24413                 "corresponding namespace declaration in "
24414                 "scope", value, NULL);
24415             if (local != NULL)
24416                 xmlFree(local);
24417             return (ret);
24418         }
24419     }
24420     if (valNeeded && val) {
24421         if (nsName != NULL)
24422             *val = xmlSchemaNewQNameValue(
24423                 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24424         else
24425             *val = xmlSchemaNewQNameValue(NULL,
24426                 BAD_CAST local);
24427     } else
24428         xmlFree(local);
24429     return (0);
24430 }
24431
24432 /*
24433 * cvc-simple-type
24434 */
24435 static int
24436 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24437                              xmlNodePtr node,
24438                              xmlSchemaTypePtr type,
24439                              const xmlChar *value,
24440                              xmlSchemaValPtr *retVal,
24441                              int fireErrors,
24442                              int normalize,
24443                              int isNormalized)
24444 {
24445     int ret = 0, valNeeded = (retVal) ? 1 : 0;
24446     xmlSchemaValPtr val = NULL;
24447     /* xmlSchemaWhitespaceValueType ws; */
24448     xmlChar *normValue = NULL;
24449
24450 #define NORMALIZE(atype) \
24451     if ((! isNormalized) && \
24452     (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24453         normValue = xmlSchemaNormalizeValue(atype, value); \
24454         if (normValue != NULL) \
24455             value = normValue; \
24456         isNormalized = 1; \
24457     }
24458
24459     if ((retVal != NULL) && (*retVal != NULL)) {
24460         xmlSchemaFreeValue(*retVal);
24461         *retVal = NULL;
24462     }
24463     /*
24464     * 3.14.4 Simple Type Definition Validation Rules
24465     * Validation Rule: String Valid
24466     */
24467     /*
24468     * 1 It is schema-valid with respect to that definition as defined
24469     * by Datatype Valid in [XML Schemas: Datatypes].
24470     */
24471     /*
24472     * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24473     * the empty set, as defined in Type Derivation OK (Simple) (�3.14.6), then
24474     * the string must be a ï¿½declared entity name�.
24475     */
24476     /*
24477     * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24478     * given the empty set, as defined in Type Derivation OK (Simple) (�3.14.6),
24479     * then every whitespace-delimited substring of the string must be a ï¿½declared
24480     * entity name�.
24481     */
24482     /*
24483     * 2.3 otherwise no further condition applies.
24484     */
24485     if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24486         valNeeded = 1;
24487     if (value == NULL)
24488         value = BAD_CAST "";
24489     if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
24490         xmlSchemaTypePtr biType; /* The built-in type. */
24491         /*
24492         * SPEC (1.2.1) "if {variety} is ï¿½atomic� then the string must ï¿½match�
24493         * a literal in the ï¿½lexical space� of {base type definition}"
24494         */
24495         /*
24496         * Whitespace-normalize.
24497         */
24498         NORMALIZE(type);
24499         if (type->type != XML_SCHEMA_TYPE_BASIC) {
24500             /*
24501             * Get the built-in type.
24502             */
24503             biType = type->baseType;
24504             while ((biType != NULL) &&
24505                 (biType->type != XML_SCHEMA_TYPE_BASIC))
24506                 biType = biType->baseType;
24507
24508             if (biType == NULL) {
24509                 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24510                     "could not get the built-in type");
24511                 goto internal_error;
24512             }
24513         } else
24514             biType = type;
24515         /*
24516         * NOTATIONs need to be processed here, since they need
24517         * to lookup in the hashtable of NOTATION declarations of the schema.
24518         */
24519         if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24520             switch (biType->builtInType) {
24521                 case XML_SCHEMAS_NOTATION:
24522                     ret = xmlSchemaValidateNotation(
24523                         (xmlSchemaValidCtxtPtr) actxt,
24524                         ((xmlSchemaValidCtxtPtr) actxt)->schema,
24525                         NULL, value, &val, valNeeded);
24526                     break;
24527                 case XML_SCHEMAS_QNAME:
24528                     ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24529                         value, &val, valNeeded);
24530                     break;
24531                 default:
24532                     /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24533                     if (valNeeded)
24534                         ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24535                             value, &val, node);
24536                     else
24537                         ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24538                             value, NULL, node);
24539                     break;
24540             }
24541         } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24542             switch (biType->builtInType) {
24543                 case XML_SCHEMAS_NOTATION:
24544                     ret = xmlSchemaValidateNotation(NULL,
24545                         ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24546                         value, &val, valNeeded);
24547                     break;
24548                 default:
24549                     /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24550                     if (valNeeded)
24551                         ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24552                             value, &val, node);
24553                     else
24554                         ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24555                             value, NULL, node);
24556                     break;
24557             }
24558         } else {
24559             /*
24560             * Validation via a public API is not implemented yet.
24561             */
24562             TODO
24563             goto internal_error;
24564         }
24565         if (ret != 0) {
24566             if (ret < 0) {
24567                 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24568                     "validating against a built-in type");
24569                 goto internal_error;
24570             }
24571             if (WXS_IS_LIST(type))
24572                 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24573             else
24574                 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24575         }
24576         if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24577             /*
24578             * Check facets.
24579             */
24580             ret = xmlSchemaValidateFacets(actxt, node, type,
24581                 (xmlSchemaValType) biType->builtInType, value, val,
24582                 0, fireErrors);
24583             if (ret != 0) {
24584                 if (ret < 0) {
24585                     AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24586                         "validating facets of atomic simple type");
24587                     goto internal_error;
24588                 }
24589                 if (WXS_IS_LIST(type))
24590                     ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24591                 else
24592                     ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24593             }
24594         }
24595         if (fireErrors && (ret > 0))
24596             xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24597     } else if (WXS_IS_LIST(type)) {
24598
24599         xmlSchemaTypePtr itemType;
24600         const xmlChar *cur, *end;
24601         xmlChar *tmpValue = NULL;
24602         unsigned long len = 0;
24603         xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24604         /* 1.2.2 if {variety} is ï¿½list� then the string must be a sequence
24605         * of white space separated tokens, each of which ï¿½match�es a literal
24606         * in the ï¿½lexical space� of {item type definition}
24607         */
24608         /*
24609         * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24610         * the list type has an enum or pattern facet.
24611         */
24612         NORMALIZE(type);
24613         /*
24614         * VAL TODO: Optimize validation of empty values.
24615         * VAL TODO: We do not have computed values for lists.
24616         */
24617         itemType = WXS_LIST_ITEMTYPE(type);
24618         cur = value;
24619         do {
24620             while (IS_BLANK_CH(*cur))
24621                 cur++;
24622             end = cur;
24623             while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24624                 end++;
24625             if (end == cur)
24626                 break;
24627             tmpValue = xmlStrndup(cur, end - cur);
24628             len++;
24629
24630             if (valNeeded)
24631                 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24632                     tmpValue, &curVal, fireErrors, 0, 1);
24633             else
24634                 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24635                     tmpValue, NULL, fireErrors, 0, 1);
24636             FREE_AND_NULL(tmpValue);
24637             if (curVal != NULL) {
24638                 /*
24639                 * Add to list of computed values.
24640                 */
24641                 if (val == NULL)
24642                     val = curVal;
24643                 else
24644                     xmlSchemaValueAppend(prevVal, curVal);
24645                 prevVal = curVal;
24646                 curVal = NULL;
24647             }
24648             if (ret != 0) {
24649                 if (ret < 0) {
24650                     AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24651                         "validating an item of list simple type");
24652                     goto internal_error;
24653                 }
24654                 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24655                 break;
24656             }
24657             cur = end;
24658         } while (*cur != 0);
24659         FREE_AND_NULL(tmpValue);
24660         if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24661             /*
24662             * Apply facets (pattern, enumeration).
24663             */
24664             ret = xmlSchemaValidateFacets(actxt, node, type,
24665                 XML_SCHEMAS_UNKNOWN, value, val,
24666                 len, fireErrors);
24667             if (ret != 0) {
24668                 if (ret < 0) {
24669                     AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24670                         "validating facets of list simple type");
24671                     goto internal_error;
24672                 }
24673                 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24674             }
24675         }
24676         if (fireErrors && (ret > 0)) {
24677             /*
24678             * Report the normalized value.
24679             */
24680             normalize = 1;
24681             NORMALIZE(type);
24682             xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24683         }
24684     } else if (WXS_IS_UNION(type)) {
24685         xmlSchemaTypeLinkPtr memberLink;
24686         /*
24687         * TODO: For all datatypes ï¿½derived� by ï¿½union�  whiteSpace does
24688         * not apply directly; however, the normalization behavior of ï¿½union�
24689         * types is controlled by the value of whiteSpace on that one of the
24690         * ï¿½memberTypes� against which the ï¿½union� is successfully validated.
24691         *
24692         * This means that the value is normalized by the first validating
24693         * member type, then the facets of the union type are applied. This
24694         * needs changing of the value!
24695         */
24696
24697         /*
24698         * 1.2.3 if {variety} is ï¿½union� then the string must ï¿½match� a
24699         * literal in the ï¿½lexical space� of at least one member of
24700         * {member type definitions}
24701         */
24702         memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24703         if (memberLink == NULL) {
24704             AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24705                 "union simple type has no member types");
24706             goto internal_error;
24707         }
24708         /*
24709         * Always normalize union type values, since we currently
24710         * cannot store the whitespace information with the value
24711         * itself; otherwise a later value-comparison would be
24712         * not possible.
24713         */
24714         while (memberLink != NULL) {
24715             if (valNeeded)
24716                 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24717                     memberLink->type, value, &val, 0, 1, 0);
24718             else
24719                 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24720                     memberLink->type, value, NULL, 0, 1, 0);
24721             if (ret <= 0)
24722                 break;
24723             memberLink = memberLink->next;
24724         }
24725         if (ret != 0) {
24726             if (ret < 0) {
24727                 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24728                     "validating members of union simple type");
24729                 goto internal_error;
24730             }
24731             ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24732         }
24733         /*
24734         * Apply facets (pattern, enumeration).
24735         */
24736         if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24737             /*
24738             * The normalization behavior of ï¿½union� types is controlled by
24739             * the value of whiteSpace on that one of the ï¿½memberTypes�
24740             * against which the ï¿½union� is successfully validated.
24741             */
24742             NORMALIZE(memberLink->type);
24743             ret = xmlSchemaValidateFacets(actxt, node, type,
24744                 XML_SCHEMAS_UNKNOWN, value, val,
24745                 0, fireErrors);
24746             if (ret != 0) {
24747                 if (ret < 0) {
24748                     AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24749                         "validating facets of union simple type");
24750                     goto internal_error;
24751                 }
24752                 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24753             }
24754         }
24755         if (fireErrors && (ret > 0))
24756             xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24757     }
24758
24759     if (normValue != NULL)
24760         xmlFree(normValue);
24761     if (ret == 0) {
24762         if (retVal != NULL)
24763             *retVal = val;
24764         else if (val != NULL)
24765             xmlSchemaFreeValue(val);
24766     } else if (val != NULL)
24767         xmlSchemaFreeValue(val);
24768     return (ret);
24769 internal_error:
24770     if (normValue != NULL)
24771         xmlFree(normValue);
24772     if (val != NULL)
24773         xmlSchemaFreeValue(val);
24774     return (-1);
24775 }
24776
24777 static int
24778 xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24779                            const xmlChar *value,
24780                            const xmlChar **nsName,
24781                            const xmlChar **localName)
24782 {
24783     int ret = 0;
24784
24785     if ((nsName == NULL) || (localName == NULL))
24786         return (-1);
24787     *nsName = NULL;
24788     *localName = NULL;
24789
24790     ret = xmlValidateQName(value, 1);
24791     if (ret == -1)
24792         return (-1);
24793     if (ret > 0) {
24794         xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
24795             XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24796             value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24797         return (1);
24798     }
24799     {
24800         xmlChar *local = NULL;
24801         xmlChar *prefix;
24802
24803         /*
24804         * NOTE: xmlSplitQName2 will return a duplicated
24805         * string.
24806         */
24807         local = xmlSplitQName2(value, &prefix);
24808         if (local == NULL)
24809             *localName = xmlDictLookup(vctxt->dict, value, -1);
24810         else {
24811             *localName = xmlDictLookup(vctxt->dict, local, -1);
24812             xmlFree(local);
24813         }
24814
24815         *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24816
24817         if (prefix != NULL) {
24818             xmlFree(prefix);
24819             /*
24820             * A namespace must be found if the prefix is NOT NULL.
24821             */
24822             if (*nsName == NULL) {
24823                 xmlSchemaCustomErr(ACTXT_CAST vctxt,
24824                     XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24825                     WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24826                     "The QName value '%s' has no "
24827                     "corresponding namespace declaration in scope",
24828                     value, NULL);
24829                 return (2);
24830             }
24831         }
24832     }
24833     return (0);
24834 }
24835
24836 static int
24837 xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24838                         xmlSchemaAttrInfoPtr iattr,
24839                         xmlSchemaTypePtr *localType,
24840                         xmlSchemaElementPtr elemDecl)
24841 {
24842     int ret = 0;
24843     /*
24844     * cvc-elt (3.3.4) : (4)
24845     * AND
24846     * Schema-Validity Assessment (Element) (cvc-assess-elt)
24847     *   (1.2.1.2.1) - (1.2.1.2.4)
24848     * Handle 'xsi:type'.
24849     */
24850     if (localType == NULL)
24851         return (-1);
24852     *localType = NULL;
24853     if (iattr == NULL)
24854         return (0);
24855     else {
24856         const xmlChar *nsName = NULL, *local = NULL;
24857         /*
24858         * TODO: We should report a *warning* that the type was overriden
24859         * by the instance.
24860         */
24861         ACTIVATE_ATTRIBUTE(iattr);
24862         /*
24863         * (cvc-elt) (3.3.4) : (4.1)
24864         * (cvc-assess-elt) (1.2.1.2.2)
24865         */
24866         ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24867             &nsName, &local);
24868         if (ret != 0) {
24869             if (ret < 0) {
24870                 VERROR_INT("xmlSchemaValidateElementByDeclaration",
24871                     "calling xmlSchemaQNameExpand() to validate the "
24872                     "attribute 'xsi:type'");
24873                 goto internal_error;
24874             }
24875             goto exit;
24876         }
24877         /*
24878         * (cvc-elt) (3.3.4) : (4.2)
24879         * (cvc-assess-elt) (1.2.1.2.3)
24880         */
24881         *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24882         if (*localType == NULL) {
24883             xmlChar *str = NULL;
24884
24885             xmlSchemaCustomErr(ACTXT_CAST vctxt,
24886                 XML_SCHEMAV_CVC_ELT_4_2, NULL,
24887                 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24888                 "The QName value '%s' of the xsi:type attribute does not "
24889                 "resolve to a type definition",
24890                 xmlSchemaFormatQName(&str, nsName, local), NULL);
24891             FREE_AND_NULL(str);
24892             ret = vctxt->err;
24893             goto exit;
24894         }
24895         if (elemDecl != NULL) {
24896             int set = 0;
24897
24898             /*
24899             * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
24900             * "The ï¿½local type definition� must be validly
24901             * derived from the {type definition} given the union of
24902             * the {disallowed substitutions} and the {type definition}'s
24903             * {prohibited substitutions}, as defined in
24904             * Type Derivation OK (Complex) (�3.4.6)
24905             * (if it is a complex type definition),
24906             * or given {disallowed substitutions} as defined in Type
24907             * Derivation OK (Simple) (�3.14.6) (if it is a simple type
24908             * definition)."
24909             *
24910             * {disallowed substitutions}: the "block" on the element decl.
24911             * {prohibited substitutions}: the "block" on the type def.
24912             */
24913             /*
24914             * OPTIMIZE TODO: We could map types already evaluated
24915             * to be validly derived from other types to avoid checking
24916             * this over and over for the same types.
24917             */
24918             if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24919                 (elemDecl->subtypes->flags &
24920                     XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24921                 set |= SUBSET_EXTENSION;
24922
24923             if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24924                 (elemDecl->subtypes->flags &
24925                     XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24926                 set |= SUBSET_RESTRICTION;
24927
24928             /*
24929             * REMOVED and CHANGED since this produced a parser context
24930             * which adds to the string dict of the schema. So this would
24931             * change the schema and we don't want this. We don't need
24932             * the parser context anymore.
24933             *
24934             * if ((vctxt->pctxt == NULL) &&
24935             *   (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24936             *       return (-1);
24937             */
24938
24939             if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
24940                 elemDecl->subtypes, set) != 0) {
24941                 xmlChar *str = NULL;
24942
24943                 xmlSchemaCustomErr(ACTXT_CAST vctxt,
24944                     XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24945                     "The type definition '%s', specified by xsi:type, is "
24946                     "blocked or not validly derived from the type definition "
24947                     "of the element declaration",
24948                     xmlSchemaFormatQName(&str,
24949                         (*localType)->targetNamespace,
24950                         (*localType)->name),
24951                     NULL);
24952                 FREE_AND_NULL(str);
24953                 ret = vctxt->err;
24954                 *localType = NULL;
24955             }
24956         }
24957     }
24958 exit:
24959     ACTIVATE_ELEM;
24960     return (ret);
24961 internal_error:
24962     ACTIVATE_ELEM;
24963     return (-1);
24964 }
24965
24966 static int
24967 xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
24968 {
24969     xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
24970     xmlSchemaTypePtr actualType;
24971
24972     /*
24973     * cvc-elt (3.3.4) : 1
24974     */
24975     if (elemDecl == NULL) {
24976         VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
24977             "No matching declaration available");
24978         return (vctxt->err);
24979     }
24980     actualType = WXS_ELEM_TYPEDEF(elemDecl);
24981     /*
24982     * cvc-elt (3.3.4) : 2
24983     */
24984     if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
24985         VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
24986             "The element declaration is abstract");
24987         return (vctxt->err);
24988     }
24989     if (actualType == NULL) {
24990         VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24991             "The type definition is absent");
24992         return (XML_SCHEMAV_CVC_TYPE_1);
24993     }
24994     if (vctxt->nbAttrInfos != 0) {
24995         int ret;
24996         xmlSchemaAttrInfoPtr iattr;
24997         /*
24998         * cvc-elt (3.3.4) : 3
24999         * Handle 'xsi:nil'.
25000         */
25001         iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25002             XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
25003         if (iattr) {
25004             ACTIVATE_ATTRIBUTE(iattr);
25005             /*
25006             * Validate the value.
25007             */
25008             ret = xmlSchemaVCheckCVCSimpleType(
25009                 ACTXT_CAST vctxt, NULL,
25010                 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
25011                 iattr->value, &(iattr->val), 1, 0, 0);
25012             ACTIVATE_ELEM;
25013             if (ret < 0) {
25014                 VERROR_INT("xmlSchemaValidateElemDecl",
25015                     "calling xmlSchemaVCheckCVCSimpleType() to "
25016                     "validate the attribute 'xsi:nil'");
25017                 return (-1);
25018             }
25019             if (ret == 0) {
25020                 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
25021                     /*
25022                     * cvc-elt (3.3.4) : 3.1
25023                     */
25024                     VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
25025                         "The element is not 'nillable'");
25026                     /* Does not return an error on purpose. */
25027                 } else {
25028                     if (xmlSchemaValueGetAsBoolean(iattr->val)) {
25029                         /*
25030                         * cvc-elt (3.3.4) : 3.2.2
25031                         */
25032                         if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
25033                             (elemDecl->value != NULL)) {
25034                             VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
25035                                 "The element cannot be 'nilled' because "
25036                                 "there is a fixed value constraint defined "
25037                                 "for it");
25038                              /* Does not return an error on purpose. */
25039                         } else
25040                             vctxt->inode->flags |=
25041                                 XML_SCHEMA_ELEM_INFO_NILLED;
25042                     }
25043                 }
25044             }
25045         }
25046         /*
25047         * cvc-elt (3.3.4) : 4
25048         * Handle 'xsi:type'.
25049         */
25050         iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25051             XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25052         if (iattr) {
25053             xmlSchemaTypePtr localType = NULL;
25054
25055             ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
25056                 elemDecl);
25057             if (ret != 0) {
25058                 if (ret == -1) {
25059                     VERROR_INT("xmlSchemaValidateElemDecl",
25060                         "calling xmlSchemaProcessXSIType() to "
25061                         "process the attribute 'xsi:type'");
25062                     return (-1);
25063                 }
25064                 /* Does not return an error on purpose. */
25065             }
25066             if (localType != NULL) {
25067                 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
25068                 actualType = localType;
25069             }
25070         }
25071     }
25072     /*
25073     * IDC: Register identity-constraint XPath matchers.
25074     */
25075     if ((elemDecl->idcs != NULL) &&
25076         (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
25077             return (-1);
25078     /*
25079     * No actual type definition.
25080     */
25081     if (actualType == NULL) {
25082         VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25083             "The type definition is absent");
25084         return (XML_SCHEMAV_CVC_TYPE_1);
25085     }
25086     /*
25087     * Remember the actual type definition.
25088     */
25089     vctxt->inode->typeDef = actualType;
25090
25091     return (0);
25092 }
25093
25094 static int
25095 xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
25096 {
25097     xmlSchemaAttrInfoPtr iattr;
25098     int ret = 0, i;
25099
25100     /*
25101     * SPEC cvc-type (3.1.1)
25102     * "The attributes of must be empty, excepting those whose namespace
25103     * name is identical to http://www.w3.org/2001/XMLSchema-instance and
25104     * whose local name is one of type, nil, schemaLocation or
25105     * noNamespaceSchemaLocation."
25106     */
25107     if (vctxt->nbAttrInfos == 0)
25108         return (0);
25109     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25110         iattr = vctxt->attrInfos[i];
25111         if (! iattr->metaType) {
25112             ACTIVATE_ATTRIBUTE(iattr)
25113             xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25114                 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
25115             ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
25116         }
25117     }
25118     ACTIVATE_ELEM
25119     return (ret);
25120 }
25121
25122 /*
25123 * Cleanup currently used attribute infos.
25124 */
25125 static void
25126 xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
25127 {
25128     int i;
25129     xmlSchemaAttrInfoPtr attr;
25130
25131     if (vctxt->nbAttrInfos == 0)
25132         return;
25133     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25134         attr = vctxt->attrInfos[i];
25135         if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
25136             if (attr->localName != NULL)
25137                 xmlFree((xmlChar *) attr->localName);
25138             if (attr->nsName != NULL)
25139                 xmlFree((xmlChar *) attr->nsName);
25140         }
25141         if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
25142             if (attr->value != NULL)
25143                 xmlFree((xmlChar *) attr->value);
25144         }
25145         if (attr->val != NULL) {
25146             xmlSchemaFreeValue(attr->val);
25147             attr->val = NULL;
25148         }
25149         memset(attr, 0, sizeof(xmlSchemaAttrInfo));
25150     }
25151     vctxt->nbAttrInfos = 0;
25152 }
25153
25154 /*
25155 * 3.4.4 Complex Type Definition Validation Rules
25156 *   Element Locally Valid (Complex Type) (cvc-complex-type)
25157 * 3.2.4 Attribute Declaration Validation Rules
25158 *   Validation Rule: Attribute Locally Valid (cvc-attribute)
25159 *   Attribute Locally Valid (Use) (cvc-au)
25160 *
25161 * Only "assessed" attribute information items will be visible to
25162 * IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
25163 */
25164 static int
25165 xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
25166 {
25167     xmlSchemaTypePtr type = vctxt->inode->typeDef;
25168     xmlSchemaItemListPtr attrUseList;
25169     xmlSchemaAttributeUsePtr attrUse = NULL;
25170     xmlSchemaAttributePtr attrDecl = NULL;
25171     xmlSchemaAttrInfoPtr iattr, tmpiattr;
25172     int i, j, found, nbAttrs, nbUses;
25173     int xpathRes = 0, res, wildIDs = 0, fixed;
25174     xmlNodePtr defAttrOwnerElem = NULL;
25175
25176     /*
25177     * SPEC (cvc-attribute)
25178     * (1) "The declaration must not be ï¿½absent� (see Missing
25179     * Sub-components (�5.3) for how this can fail to be
25180     * the case)."
25181     * (2) "Its {type definition} must not be absent."
25182     *
25183     * NOTE (1) + (2): This is not handled here, since we currently do not
25184     * allow validation against schemas which have missing sub-components.
25185     *
25186     * SPEC (cvc-complex-type)
25187     * (3) "For each attribute information item in the element information
25188     * item's [attributes] excepting those whose [namespace name] is
25189     * identical to http://www.w3.org/2001/XMLSchema-instance and whose
25190     * [local name] is one of type, nil, schemaLocation or
25191     * noNamespaceSchemaLocation, the appropriate case among the following
25192     * must be true:
25193     *
25194     */
25195     attrUseList = (xmlSchemaItemListPtr) type->attrUses;
25196     /*
25197     * @nbAttrs is the number of attributes present in the instance.
25198     */
25199     nbAttrs = vctxt->nbAttrInfos;
25200     if (attrUseList != NULL)
25201         nbUses = attrUseList->nbItems;
25202     else
25203         nbUses = 0;
25204     for (i = 0; i < nbUses; i++) {
25205         found = 0;
25206         attrUse = attrUseList->items[i];
25207         attrDecl = WXS_ATTRUSE_DECL(attrUse);
25208         for (j = 0; j < nbAttrs; j++) {
25209             iattr = vctxt->attrInfos[j];
25210             /*
25211             * SPEC (cvc-complex-type) (3)
25212             * Skip meta attributes.
25213             */
25214             if (iattr->metaType)
25215                 continue;
25216             if (iattr->localName[0] != attrDecl->name[0])
25217                 continue;
25218             if (!xmlStrEqual(iattr->localName, attrDecl->name))
25219                 continue;
25220             if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
25221                 continue;
25222             found = 1;
25223             /*
25224             * SPEC (cvc-complex-type)
25225             * (3.1) "If there is among the {attribute uses} an attribute
25226             * use with an {attribute declaration} whose {name} matches
25227             * the attribute information item's [local name] and whose
25228             * {target namespace} is identical to the attribute information
25229             * item's [namespace name] (where an ï¿½absent� {target namespace}
25230             * is taken to be identical to a [namespace name] with no value),
25231             * then the attribute information must be ï¿½valid� with respect
25232             * to that attribute use as per Attribute Locally Valid (Use)
25233             * (�3.5.4). In this case the {attribute declaration} of that
25234             * attribute use is the ï¿½context-determined declaration� for the
25235             * attribute information item with respect to Schema-Validity
25236             * Assessment (Attribute) (�3.2.4) and
25237             * Assessment Outcome (Attribute) (�3.2.5).
25238             */
25239             iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25240             iattr->use = attrUse;
25241             /*
25242             * Context-determined declaration.
25243             */
25244             iattr->decl = attrDecl;
25245             iattr->typeDef = attrDecl->subtypes;
25246             break;
25247         }
25248
25249         if (found)
25250             continue;
25251
25252         if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
25253             /*
25254             * Handle non-existent, required attributes.
25255             *
25256             * SPEC (cvc-complex-type)
25257             * (4) "The {attribute declaration} of each attribute use in
25258             * the {attribute uses} whose {required} is true matches one
25259             * of the attribute information items in the element information
25260             * item's [attributes] as per clause 3.1 above."
25261             */
25262             tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25263             if (tmpiattr == NULL) {
25264                 VERROR_INT(
25265                     "xmlSchemaVAttributesComplex",
25266                     "calling xmlSchemaGetFreshAttrInfo()");
25267                 return (-1);
25268             }
25269             tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
25270             tmpiattr->use = attrUse;
25271             tmpiattr->decl = attrDecl;
25272         } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
25273             ((attrUse->defValue != NULL) ||
25274              (attrDecl->defValue != NULL))) {
25275             /*
25276             * Handle non-existent, optional, default/fixed attributes.
25277             */
25278             tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25279             if (tmpiattr == NULL) {
25280                 VERROR_INT(
25281                     "xmlSchemaVAttributesComplex",
25282                     "calling xmlSchemaGetFreshAttrInfo()");
25283                 return (-1);
25284             }
25285             tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
25286             tmpiattr->use = attrUse;
25287             tmpiattr->decl = attrDecl;
25288             tmpiattr->typeDef = attrDecl->subtypes;
25289             tmpiattr->localName = attrDecl->name;
25290             tmpiattr->nsName = attrDecl->targetNamespace;
25291         }
25292     }
25293
25294     if (vctxt->nbAttrInfos == 0)
25295         return (0);
25296     /*
25297     * Validate against the wildcard.
25298     */
25299     if (type->attributeWildcard != NULL) {
25300         /*
25301         * SPEC (cvc-complex-type)
25302         * (3.2.1) "There must be an {attribute wildcard}."
25303         */
25304         for (i = 0; i < nbAttrs; i++) {
25305             iattr = vctxt->attrInfos[i];
25306             /*
25307             * SPEC (cvc-complex-type) (3)
25308             * Skip meta attributes.
25309             */
25310             if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
25311                 continue;
25312             /*
25313             * SPEC (cvc-complex-type)
25314             * (3.2.2) "The attribute information item must be ï¿½valid� with
25315             * respect to it as defined in Item Valid (Wildcard) (�3.10.4)."
25316             *
25317             * SPEC Item Valid (Wildcard) (cvc-wildcard)
25318             * "... its [namespace name] must be ï¿½valid� with respect to
25319             * the wildcard constraint, as defined in Wildcard allows
25320             * Namespace Name (�3.10.4)."
25321             */
25322             if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
25323                     iattr->nsName) == 0) {
25324                 /*
25325                 * Handle processContents.
25326                 *
25327                 * SPEC (cvc-wildcard):
25328                 * processContents | context-determined declaration:
25329                 * "strict"          "mustFind"
25330                 * "lax"             "none"
25331                 * "skip"            "skip"
25332                 */
25333                 if (type->attributeWildcard->processContents ==
25334                     XML_SCHEMAS_ANY_SKIP) {
25335                      /*
25336                     * context-determined declaration = "skip"
25337                     *
25338                     * SPEC PSVI Assessment Outcome (Attribute)
25339                     * [validity] = "notKnown"
25340                     * [validation attempted] = "none"
25341                     */
25342                     iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
25343                     continue;
25344                 }
25345                 /*
25346                 * Find an attribute declaration.
25347                 */
25348                 iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25349                     iattr->localName, iattr->nsName);
25350                 if (iattr->decl != NULL) {
25351                     iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25352                     /*
25353                     * SPEC (cvc-complex-type)
25354                     * (5) "Let [Definition:]  the wild IDs be the set of
25355                     * all attribute information item to which clause 3.2
25356                     * applied and whose ï¿½validation� resulted in a
25357                     * ï¿½context-determined declaration� of mustFind or no
25358                     * ï¿½context-determined declaration� at all, and whose
25359                     * [local name] and [namespace name] resolve (as
25360                     * defined by QName resolution (Instance) (�3.15.4)) to
25361                     * an attribute declaration whose {type definition} is
25362                     * or is derived from ID. Then all of the following
25363                     * must be true:"
25364                     */
25365                     iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
25366                     if (xmlSchemaIsDerivedFromBuiltInType(
25367                         iattr->typeDef, XML_SCHEMAS_ID)) {
25368                         /*
25369                         * SPEC (5.1) "There must be no more than one
25370                         * item in ï¿½wild IDs�."
25371                         */
25372                         if (wildIDs != 0) {
25373                             /* VAL TODO */
25374                             iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
25375                             TODO
25376                             continue;
25377                         }
25378                         wildIDs++;
25379                         /*
25380                         * SPEC (cvc-complex-type)
25381                         * (5.2) "If ï¿½wild IDs� is non-empty, there must not
25382                         * be any attribute uses among the {attribute uses}
25383                         * whose {attribute declaration}'s {type definition}
25384                         * is or is derived from ID."
25385                         */
25386                         if (attrUseList != NULL) {
25387                             for (j = 0; j < attrUseList->nbItems; j++) {
25388                                 if (xmlSchemaIsDerivedFromBuiltInType(
25389                                     WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25390                                     XML_SCHEMAS_ID)) {
25391                                     /* URGENT VAL TODO: implement */
25392                             iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25393                                     TODO
25394                                     break;
25395                                 }
25396                             }
25397                         }
25398                     }
25399                 } else if (type->attributeWildcard->processContents ==
25400                     XML_SCHEMAS_ANY_LAX) {
25401                     iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
25402                     /*
25403                     * SPEC PSVI Assessment Outcome (Attribute)
25404                     * [validity] = "notKnown"
25405                     * [validation attempted] = "none"
25406                     */
25407                 } else {
25408                     iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
25409                 }
25410             }
25411         }
25412     }
25413
25414     if (vctxt->nbAttrInfos == 0)
25415         return (0);
25416
25417     /*
25418     * Get the owner element; needed for creation of default attributes.
25419     * This fixes bug #341337, reported by David Grohmann.
25420     */
25421     if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25422         xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25423         if (ielem && ielem->node && ielem->node->doc)
25424             defAttrOwnerElem = ielem->node;
25425     }
25426     /*
25427     * Validate values, create default attributes, evaluate IDCs.
25428     */
25429     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25430         iattr = vctxt->attrInfos[i];
25431         /*
25432         * VAL TODO: Note that we won't try to resolve IDCs to
25433         * "lax" and "skip" validated attributes. Check what to
25434         * do in this case.
25435         */
25436         if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25437             (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
25438             continue;
25439         /*
25440         * VAL TODO: What to do if the type definition is missing?
25441         */
25442         if (iattr->typeDef == NULL) {
25443             iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
25444             continue;
25445         }
25446
25447         ACTIVATE_ATTRIBUTE(iattr);
25448         fixed = 0;
25449         xpathRes = 0;
25450
25451         if (vctxt->xpathStates != NULL) {
25452             /*
25453             * Evaluate IDCs.
25454             */
25455             xpathRes = xmlSchemaXPathEvaluate(vctxt,
25456                 XML_ATTRIBUTE_NODE);
25457             if (xpathRes == -1) {
25458                 VERROR_INT("xmlSchemaVAttributesComplex",
25459                     "calling xmlSchemaXPathEvaluate()");
25460                 goto internal_error;
25461             }
25462         }
25463
25464         if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
25465             /*
25466             * Default/fixed attributes.
25467             * We need the value only if we need to resolve IDCs or
25468             * will create default attributes.
25469             */
25470             if ((xpathRes) || (defAttrOwnerElem)) {
25471                 if (iattr->use->defValue != NULL) {
25472                     iattr->value = (xmlChar *) iattr->use->defValue;
25473                     iattr->val = iattr->use->defVal;
25474                 } else {
25475                     iattr->value = (xmlChar *) iattr->decl->defValue;
25476                     iattr->val = iattr->decl->defVal;
25477                 }
25478                 /*
25479                 * IDCs will consume the precomputed default value,
25480                 * so we need to clone it.
25481                 */
25482                 if (iattr->val == NULL) {
25483                     VERROR_INT("xmlSchemaVAttributesComplex",
25484                         "default/fixed value on an attribute use was "
25485                         "not precomputed");
25486                     goto internal_error;
25487                 }
25488                 iattr->val = xmlSchemaCopyValue(iattr->val);
25489                 if (iattr->val == NULL) {
25490                     VERROR_INT("xmlSchemaVAttributesComplex",
25491                         "calling xmlSchemaCopyValue()");
25492                     goto internal_error;
25493                 }
25494             }
25495             /*
25496             * PSVI: Add the default attribute to the current element.
25497             * VAL TODO: Should we use the *normalized* value? This currently
25498             *   uses the *initial* value.
25499             */
25500
25501             if (defAttrOwnerElem) {
25502                 xmlChar *normValue;
25503                 const xmlChar *value;
25504
25505                 value = iattr->value;
25506                 /*
25507                 * Normalize the value.
25508                 */
25509                 normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25510                     iattr->value);
25511                 if (normValue != NULL)
25512                     value = BAD_CAST normValue;
25513
25514                 if (iattr->nsName == NULL) {
25515                     if (xmlNewProp(defAttrOwnerElem,
25516                         iattr->localName, value) == NULL) {
25517                         VERROR_INT("xmlSchemaVAttributesComplex",
25518                             "callling xmlNewProp()");
25519                         if (normValue != NULL)
25520                             xmlFree(normValue);
25521                         goto internal_error;
25522                     }
25523                 } else {
25524                     xmlNsPtr ns;
25525
25526                     ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25527                         defAttrOwnerElem, iattr->nsName);
25528                     if (ns == NULL) {
25529                         xmlChar prefix[12];
25530                         int counter = 0;
25531
25532                         /*
25533                         * Create a namespace declaration on the validation
25534                         * root node if no namespace declaration is in scope.
25535                         */
25536                         do {
25537                             snprintf((char *) prefix, 12, "p%d", counter++);
25538                             ns = xmlSearchNs(defAttrOwnerElem->doc,
25539                                 defAttrOwnerElem, BAD_CAST prefix);
25540                             if (counter > 1000) {
25541                                 VERROR_INT(
25542                                     "xmlSchemaVAttributesComplex",
25543                                     "could not compute a ns prefix for a "
25544                                     "default/fixed attribute");
25545                                 if (normValue != NULL)
25546                                     xmlFree(normValue);
25547                                 goto internal_error;
25548                             }
25549                         } while (ns != NULL);
25550                         ns = xmlNewNs(vctxt->validationRoot,
25551                             iattr->nsName, BAD_CAST prefix);
25552                     }
25553                     /*
25554                     * TODO:
25555                     * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25556                     * If we have QNames: do we need to ensure there's a
25557                     * prefix defined for the QName?
25558                     */
25559                     xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
25560                 }
25561                 if (normValue != NULL)
25562                     xmlFree(normValue);
25563             }
25564             /*
25565             * Go directly to IDC evaluation.
25566             */
25567             goto eval_idcs;
25568         }
25569         /*
25570         * Validate the value.
25571         */
25572         if (vctxt->value != NULL) {
25573             /*
25574             * Free last computed value; just for safety reasons.
25575             */
25576             xmlSchemaFreeValue(vctxt->value);
25577             vctxt->value = NULL;
25578         }
25579         /*
25580         * Note that the attribute *use* can be unavailable, if
25581         * the attribute was a wild attribute.
25582         */
25583         if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25584             ((iattr->use != NULL) &&
25585              (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
25586             fixed = 1;
25587         else
25588             fixed = 0;
25589         /*
25590         * SPEC (cvc-attribute)
25591         * (3) "The item's ï¿½normalized value� must be locally ï¿½valid�
25592         * with respect to that {type definition} as per
25593         * String Valid (�3.14.4)."
25594         *
25595         * VAL TODO: Do we already have the
25596         * "normalized attribute value" here?
25597         */
25598         if (xpathRes || fixed) {
25599             iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
25600             /*
25601             * Request a computed value.
25602             */
25603             res = xmlSchemaVCheckCVCSimpleType(
25604                 ACTXT_CAST vctxt,
25605                 iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
25606                 1, 1, 0);
25607         } else {
25608             res = xmlSchemaVCheckCVCSimpleType(
25609                 ACTXT_CAST vctxt,
25610                 iattr->node, iattr->typeDef, iattr->value, NULL,
25611                 1, 0, 0);
25612         }
25613
25614         if (res != 0) {
25615             if (res == -1) {
25616                 VERROR_INT("xmlSchemaVAttributesComplex",
25617                     "calling xmlSchemaStreamValidateSimpleTypeValue()");
25618                 goto internal_error;
25619             }
25620             iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
25621             /*
25622             * SPEC PSVI Assessment Outcome (Attribute)
25623             * [validity] = "invalid"
25624             */
25625             goto eval_idcs;
25626         }
25627
25628         if (fixed) {
25629             /*
25630             * SPEC Attribute Locally Valid (Use) (cvc-au)
25631             * "For an attribute information item to be�valid�
25632             * with respect to an attribute use its *normalized*
25633             * value� must match the *canonical* lexical
25634             * representation of the attribute use's {value
25635             * constraint}value, if it is present and fixed."
25636             *
25637             * VAL TODO: The requirement for the *canonical* value
25638             * will be removed in XML Schema 1.1.
25639             */
25640             /*
25641             * SPEC Attribute Locally Valid (cvc-attribute)
25642             * (4) "The item's *actual* value� must match the *value* of
25643             * the {value constraint}, if it is present and fixed."
25644             */
25645             if (iattr->val == NULL) {
25646                 /* VAL TODO: A value was not precomputed. */
25647                 TODO
25648                 goto eval_idcs;
25649             }
25650             if ((iattr->use != NULL) &&
25651                 (iattr->use->defValue != NULL)) {
25652                 if (iattr->use->defVal == NULL) {
25653                     /* VAL TODO: A default value was not precomputed. */
25654                     TODO
25655                     goto eval_idcs;
25656                 }
25657                 iattr->vcValue = iattr->use->defValue;
25658                 /*
25659                 if (xmlSchemaCompareValuesWhtsp(attr->val,
25660                     (xmlSchemaWhitespaceValueType) ws,
25661                     attr->use->defVal,
25662                     (xmlSchemaWhitespaceValueType) ws) != 0) {
25663                 */
25664                 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25665                     iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25666             } else {
25667                 if (iattr->decl->defVal == NULL) {
25668                     /* VAL TODO: A default value was not precomputed. */
25669                     TODO
25670                     goto eval_idcs;
25671                 }
25672                 iattr->vcValue = iattr->decl->defValue;
25673                 /*
25674                 if (xmlSchemaCompareValuesWhtsp(attr->val,
25675                     (xmlSchemaWhitespaceValueType) ws,
25676                     attrDecl->defVal,
25677                     (xmlSchemaWhitespaceValueType) ws) != 0) {
25678                 */
25679                 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25680                     iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25681             }
25682             /*
25683             * [validity] = "valid"
25684             */
25685         }
25686 eval_idcs:
25687         /*
25688         * Evaluate IDCs.
25689         */
25690         if (xpathRes) {
25691             if (xmlSchemaXPathProcessHistory(vctxt,
25692                 vctxt->depth +1) == -1) {
25693                 VERROR_INT("xmlSchemaVAttributesComplex",
25694                     "calling xmlSchemaXPathEvaluate()");
25695                 goto internal_error;
25696             }
25697         } else if (vctxt->xpathStates != NULL)
25698             xmlSchemaXPathPop(vctxt);
25699     }
25700
25701     /*
25702     * Report errors.
25703     */
25704     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25705         iattr = vctxt->attrInfos[i];
25706         if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25707             (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25708             (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25709             (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
25710             continue;
25711         ACTIVATE_ATTRIBUTE(iattr);
25712         switch (iattr->state) {
25713             case XML_SCHEMAS_ATTR_ERR_MISSING: {
25714                     xmlChar *str = NULL;
25715                     ACTIVATE_ELEM;
25716                     xmlSchemaCustomErr(ACTXT_CAST vctxt,
25717                         XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25718                         "The attribute '%s' is required but missing",
25719                         xmlSchemaFormatQName(&str,
25720                             iattr->decl->targetNamespace,
25721                             iattr->decl->name),
25722                         NULL);
25723                     FREE_AND_NULL(str)
25724                     break;
25725                 }
25726             case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25727                 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25728                     "The type definition is absent");
25729                 break;
25730             case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
25731                 xmlSchemaCustomErr(ACTXT_CAST vctxt,
25732                     XML_SCHEMAV_CVC_AU, NULL, NULL,
25733                     "The value '%s' does not match the fixed "
25734                     "value constraint '%s'",
25735                     iattr->value, iattr->vcValue);
25736                 break;
25737             case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25738                 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25739                     "No matching global attribute declaration available, but "
25740                     "demanded by the strict wildcard");
25741                 break;
25742             case XML_SCHEMAS_ATTR_UNKNOWN:
25743                 if (iattr->metaType)
25744                     break;
25745                 /*
25746                 * MAYBE VAL TODO: One might report different error messages
25747                 * for the following errors.
25748                 */
25749                 if (type->attributeWildcard == NULL) {
25750                     xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25751                         XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
25752                 } else {
25753                     xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25754                         XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
25755                 }
25756                 break;
25757             default:
25758                 break;
25759         }
25760     }
25761
25762     ACTIVATE_ELEM;
25763     return (0);
25764 internal_error:
25765     ACTIVATE_ELEM;
25766     return (-1);
25767 }
25768
25769 static int
25770 xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25771                               int *skip)
25772 {
25773     xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25774     /*
25775     * The namespace of the element was already identified to be
25776     * matching the wildcard.
25777     */
25778     if ((skip == NULL) || (wild == NULL) ||
25779         (wild->type != XML_SCHEMA_TYPE_ANY)) {
25780         VERROR_INT("xmlSchemaValidateElemWildcard",
25781             "bad arguments");
25782         return (-1);
25783     }
25784     *skip = 0;
25785     if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25786         /*
25787         * URGENT VAL TODO: Either we need to position the stream to the
25788         * next sibling, or walk the whole subtree.
25789         */
25790         *skip = 1;
25791         return (0);
25792     }
25793     {
25794         xmlSchemaElementPtr decl = NULL;
25795
25796         decl = xmlSchemaGetElem(vctxt->schema,
25797             vctxt->inode->localName, vctxt->inode->nsName);
25798         if (decl != NULL) {
25799             vctxt->inode->decl = decl;
25800             return (0);
25801         }
25802     }
25803     if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25804         /* VAL TODO: Change to proper error code. */
25805         VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
25806             "No matching global element declaration available, but "
25807             "demanded by the strict wildcard");
25808         return (vctxt->err);
25809     }
25810     if (vctxt->nbAttrInfos != 0) {
25811         xmlSchemaAttrInfoPtr iattr;
25812         /*
25813         * SPEC Validation Rule: Schema-Validity Assessment (Element)
25814         * (1.2.1.2.1) - (1.2.1.2.3 )
25815         *
25816         * Use the xsi:type attribute for the type definition.
25817         */
25818         iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25819             XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25820         if (iattr != NULL) {
25821             if (xmlSchemaProcessXSIType(vctxt, iattr,
25822                 &(vctxt->inode->typeDef), NULL) == -1) {
25823                 VERROR_INT("xmlSchemaValidateElemWildcard",
25824                     "calling xmlSchemaProcessXSIType() to "
25825                     "process the attribute 'xsi:nil'");
25826                 return (-1);
25827             }
25828             /*
25829             * Don't return an error on purpose.
25830             */
25831             return (0);
25832         }
25833     }
25834     /*
25835     * SPEC Validation Rule: Schema-Validity Assessment (Element)
25836     *
25837     * Fallback to "anyType".
25838     */
25839     vctxt->inode->typeDef =
25840         xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25841     return (0);
25842 }
25843
25844 /*
25845 * xmlSchemaCheckCOSValidDefault:
25846 *
25847 * This will be called if: not nilled, no content and a default/fixed
25848 * value is provided.
25849 */
25850
25851 static int
25852 xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25853                               const xmlChar *value,
25854                               xmlSchemaValPtr *val)
25855 {
25856     int ret = 0;
25857     xmlSchemaNodeInfoPtr inode = vctxt->inode;
25858
25859     /*
25860     * cos-valid-default:
25861     * Schema Component Constraint: Element Default Valid (Immediate)
25862     * For a string to be a valid default with respect to a type
25863     * definition the appropriate case among the following must be true:
25864     */
25865     if WXS_IS_COMPLEX(inode->typeDef) {
25866         /*
25867         * Complex type.
25868         *
25869         * SPEC (2.1) "its {content type} must be a simple type definition
25870         * or mixed."
25871         * SPEC (2.2.2) "If the {content type} is mixed, then the {content
25872         * type}'s particle must be ï¿½emptiable� as defined by
25873         * Particle Emptiable (�3.9.6)."
25874         */
25875         if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25876             ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25877              (! WXS_EMPTIABLE(inode->typeDef)))) {
25878             ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25879             /* NOTE that this covers (2.2.2) as well. */
25880             VERROR(ret, NULL,
25881                 "For a string to be a valid default, the type definition "
25882                 "must be a simple type or a complex type with simple content "
25883                 "or mixed content and a particle emptiable");
25884             return(ret);
25885         }
25886     }
25887     /*
25888     * 1 If the type definition is a simple type definition, then the string
25889     * must be ï¿½valid� with respect to that definition as defined by String
25890     * Valid (�3.14.4).
25891     *
25892     * AND
25893     *
25894     * 2.2.1 If the {content type} is a simple type definition, then the
25895     * string must be ï¿½valid� with respect to that simple type definition
25896     * as defined by String Valid (�3.14.4).
25897     */
25898     if (WXS_IS_SIMPLE(inode->typeDef)) {
25899
25900         ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25901             NULL, inode->typeDef, value, val, 1, 1, 0);
25902
25903     } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
25904
25905         ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25906             NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25907     }
25908     if (ret < 0) {
25909         VERROR_INT("xmlSchemaCheckCOSValidDefault",
25910             "calling xmlSchemaVCheckCVCSimpleType()");
25911     }
25912     return (ret);
25913 }
25914
25915 static void
25916 xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
25917                                const xmlChar * name ATTRIBUTE_UNUSED,
25918                                xmlSchemaElementPtr item,
25919                                xmlSchemaNodeInfoPtr inode)
25920 {
25921     inode->decl = item;
25922 #ifdef DEBUG_CONTENT
25923     {
25924         xmlChar *str = NULL;
25925
25926         if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
25927             xmlGenericError(xmlGenericErrorContext,
25928                 "AUTOMATON callback for '%s' [declaration]\n",
25929                 xmlSchemaFormatQName(&str,
25930                 inode->localName, inode->nsName));
25931         } else {
25932             xmlGenericError(xmlGenericErrorContext,
25933                     "AUTOMATON callback for '%s' [wildcard]\n",
25934                     xmlSchemaFormatQName(&str,
25935                     inode->localName, inode->nsName));
25936
25937         }
25938         FREE_AND_NULL(str)
25939     }
25940 #endif
25941 }
25942
25943 static int
25944 xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
25945 {
25946     vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25947     if (vctxt->inode == NULL) {
25948         VERROR_INT("xmlSchemaValidatorPushElem",
25949             "calling xmlSchemaGetFreshElemInfo()");
25950         return (-1);
25951     }
25952     vctxt->nbAttrInfos = 0;
25953     return (0);
25954 }
25955
25956 static int
25957 xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
25958                              xmlSchemaNodeInfoPtr inode,
25959                              xmlSchemaTypePtr type,
25960                              const xmlChar *value)
25961 {
25962     if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
25963         return (xmlSchemaVCheckCVCSimpleType(
25964             ACTXT_CAST vctxt, NULL,
25965             type, value, &(inode->val), 1, 1, 0));
25966     else
25967         return (xmlSchemaVCheckCVCSimpleType(
25968             ACTXT_CAST vctxt, NULL,
25969             type, value, NULL, 1, 0, 0));
25970 }
25971
25972
25973
25974 /*
25975 * Process END of element.
25976 */
25977 static int
25978 xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
25979 {
25980     int ret = 0;
25981     xmlSchemaNodeInfoPtr inode = vctxt->inode;
25982
25983     if (vctxt->nbAttrInfos != 0)
25984         xmlSchemaClearAttrInfos(vctxt);
25985     if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
25986         /*
25987         * This element was not expected;
25988         * we will not validate child elements of broken parents.
25989         * Skip validation of all content of the parent.
25990         */
25991         vctxt->skipDepth = vctxt->depth -1;
25992         goto end_elem;
25993     }
25994     if ((inode->typeDef == NULL) ||
25995         (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
25996         /*
25997         * 1. the type definition might be missing if the element was
25998         *    error prone
25999         * 2. it might be abstract.
26000         */
26001         goto end_elem;
26002     }
26003     /*
26004     * Check the content model.
26005     */
26006     if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
26007         (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
26008
26009         /*
26010         * Workaround for "anyType".
26011         */
26012         if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
26013             goto character_content;
26014
26015         if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
26016             xmlChar *values[10];
26017             int terminal, nbval = 10, nbneg;
26018
26019             if (inode->regexCtxt == NULL) {
26020                 /*
26021                 * Create the regex context.
26022                 */
26023                 inode->regexCtxt =
26024                     xmlRegNewExecCtxt(inode->typeDef->contModel,
26025                     (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26026                     vctxt);
26027                 if (inode->regexCtxt == NULL) {
26028                     VERROR_INT("xmlSchemaValidatorPopElem",
26029                         "failed to create a regex context");
26030                     goto internal_error;
26031                 }
26032 #ifdef DEBUG_AUTOMATA
26033                 xmlGenericError(xmlGenericErrorContext,
26034                     "AUTOMATON create on '%s'\n", inode->localName);
26035 #endif
26036             }
26037             /*
26038             * Get hold of the still expected content, since a further
26039             * call to xmlRegExecPushString() will loose this information.
26040             */
26041             xmlRegExecNextValues(inode->regexCtxt,
26042                 &nbval, &nbneg, &values[0], &terminal);
26043             ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
26044             if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) {
26045                 /*
26046                 * Still missing something.
26047                 */
26048                 ret = 1;
26049                 inode->flags |=
26050                     XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26051                 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26052                     XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
26053                     "Missing child element(s)",
26054                     nbval, nbneg, values);
26055 #ifdef DEBUG_AUTOMATA
26056                 xmlGenericError(xmlGenericErrorContext,
26057                     "AUTOMATON missing ERROR on '%s'\n",
26058                     inode->localName);
26059 #endif
26060             } else {
26061                 /*
26062                 * Content model is satisfied.
26063                 */
26064                 ret = 0;
26065 #ifdef DEBUG_AUTOMATA
26066                 xmlGenericError(xmlGenericErrorContext,
26067                     "AUTOMATON succeeded on '%s'\n",
26068                     inode->localName);
26069 #endif
26070             }
26071
26072         }
26073     }
26074     if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
26075         goto end_elem;
26076
26077 character_content:
26078
26079     if (vctxt->value != NULL) {
26080         xmlSchemaFreeValue(vctxt->value);
26081         vctxt->value = NULL;
26082     }
26083     /*
26084     * Check character content.
26085     */
26086     if (inode->decl == NULL) {
26087         /*
26088         * Speedup if no declaration exists.
26089         */
26090         if (WXS_IS_SIMPLE(inode->typeDef)) {
26091             ret = xmlSchemaVCheckINodeDataType(vctxt,
26092                 inode, inode->typeDef, inode->value);
26093         } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26094             ret = xmlSchemaVCheckINodeDataType(vctxt,
26095                 inode, inode->typeDef->contentTypeDef,
26096                 inode->value);
26097         }
26098         if (ret < 0) {
26099             VERROR_INT("xmlSchemaValidatorPopElem",
26100                 "calling xmlSchemaVCheckCVCSimpleType()");
26101             goto internal_error;
26102         }
26103         goto end_elem;
26104     }
26105     /*
26106     * cvc-elt (3.3.4) : 5
26107     * The appropriate case among the following must be true:
26108     */
26109     /*
26110     * cvc-elt (3.3.4) : 5.1
26111     * If the declaration has a {value constraint},
26112     * the item has neither element nor character [children] and
26113     * clause 3.2 has not applied, then all of the following must be true:
26114     */
26115     if ((inode->decl->value != NULL) &&
26116         (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
26117         (! INODE_NILLED(inode))) {
26118         /*
26119         * cvc-elt (3.3.4) : 5.1.1
26120         * If the ï¿½actual type definition� is a ï¿½local type definition�
26121         * then the canonical lexical representation of the {value constraint}
26122         * value must be a valid default for the ï¿½actual type definition� as
26123         * defined in Element Default Valid (Immediate) (�3.3.6).
26124         */
26125         /*
26126         * NOTE: 'local' above means types acquired by xsi:type.
26127         * NOTE: Although the *canonical* value is stated, it is not
26128         * relevant if canonical or not. Additionally XML Schema 1.1
26129         * will removed this requirement as well.
26130         */
26131         if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
26132
26133             ret = xmlSchemaCheckCOSValidDefault(vctxt,
26134                 inode->decl->value, &(inode->val));
26135             if (ret != 0) {
26136                 if (ret < 0) {
26137                     VERROR_INT("xmlSchemaValidatorPopElem",
26138                         "calling xmlSchemaCheckCOSValidDefault()");
26139                     goto internal_error;
26140                 }
26141                 goto end_elem;
26142             }
26143             /*
26144             * Stop here, to avoid redundant validation of the value
26145             * (see following).
26146             */
26147             goto default_psvi;
26148         }
26149         /*
26150         * cvc-elt (3.3.4) : 5.1.2
26151         * The element information item with the canonical lexical
26152         * representation of the {value constraint} value used as its
26153         * ï¿½normalized value� must be ï¿½valid� with respect to the
26154         * ï¿½actual type definition� as defined by Element Locally Valid (Type)
26155         * (�3.3.4).
26156         */
26157         if (WXS_IS_SIMPLE(inode->typeDef)) {
26158             ret = xmlSchemaVCheckINodeDataType(vctxt,
26159                 inode, inode->typeDef, inode->decl->value);
26160         } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26161             ret = xmlSchemaVCheckINodeDataType(vctxt,
26162                 inode, inode->typeDef->contentTypeDef,
26163                 inode->decl->value);
26164         }
26165         if (ret != 0) {
26166             if (ret < 0) {
26167                 VERROR_INT("xmlSchemaValidatorPopElem",
26168                     "calling xmlSchemaVCheckCVCSimpleType()");
26169                 goto internal_error;
26170             }
26171             goto end_elem;
26172         }
26173
26174 default_psvi:
26175         /*
26176         * PSVI: Create a text node on the instance element.
26177         */
26178         if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
26179             (inode->node != NULL)) {
26180             xmlNodePtr textChild;
26181             xmlChar *normValue;
26182             /*
26183             * VAL TODO: Normalize the value.
26184             */
26185             normValue = xmlSchemaNormalizeValue(inode->typeDef,
26186                 inode->decl->value);
26187             if (normValue != NULL) {
26188                 textChild = xmlNewText(BAD_CAST normValue);
26189                 xmlFree(normValue);
26190             } else
26191                 textChild = xmlNewText(inode->decl->value);
26192             if (textChild == NULL) {
26193                 VERROR_INT("xmlSchemaValidatorPopElem",
26194                     "calling xmlNewText()");
26195                 goto internal_error;
26196             } else
26197                 xmlAddChild(inode->node, textChild);
26198         }
26199
26200     } else if (! INODE_NILLED(inode)) {
26201         /*
26202         * 5.2.1 The element information item must be ï¿½valid� with respect
26203         * to the ï¿½actual type definition� as defined by Element Locally
26204         * Valid (Type) (�3.3.4).
26205         */
26206         if (WXS_IS_SIMPLE(inode->typeDef)) {
26207              /*
26208             * SPEC (cvc-type) (3.1)
26209             * "If the type definition is a simple type definition, ..."
26210             * (3.1.3) "If clause 3.2 of Element Locally Valid
26211             * (Element) (�3.3.4) did not apply, then the ï¿½normalized value�
26212             * must be ï¿½valid� with respect to the type definition as defined
26213             * by String Valid (�3.14.4).
26214             */
26215             ret = xmlSchemaVCheckINodeDataType(vctxt,
26216                     inode, inode->typeDef, inode->value);
26217         } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26218             /*
26219             * SPEC (cvc-type) (3.2) "If the type definition is a complex type
26220             * definition, then the element information item must be
26221             * ï¿½valid� with respect to the type definition as per
26222             * Element Locally Valid (Complex Type) (�3.4.4);"
26223             *
26224             * SPEC (cvc-complex-type) (2.2)
26225             * "If the {content type} is a simple type definition, ...
26226             * the ï¿½normalized value� of the element information item is
26227             * ï¿½valid� with respect to that simple type definition as
26228             * defined by String Valid (�3.14.4)."
26229             */
26230             ret = xmlSchemaVCheckINodeDataType(vctxt,
26231                 inode, inode->typeDef->contentTypeDef, inode->value);
26232         }
26233         if (ret != 0) {
26234             if (ret < 0) {
26235                 VERROR_INT("xmlSchemaValidatorPopElem",
26236                     "calling xmlSchemaVCheckCVCSimpleType()");
26237                 goto internal_error;
26238             }
26239             goto end_elem;
26240         }
26241         /*
26242         * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
26243         * not applied, all of the following must be true:
26244         */
26245         if ((inode->decl->value != NULL) &&
26246             (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
26247
26248             /*
26249             * TODO: We will need a computed value, when comparison is
26250             * done on computed values.
26251             */
26252             /*
26253             * 5.2.2.1 The element information item must have no element
26254             * information item [children].
26255             */
26256             if (inode->flags &
26257                     XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
26258                 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
26259                 VERROR(ret, NULL,
26260                     "The content must not containt element nodes since "
26261                     "there is a fixed value constraint");
26262                 goto end_elem;
26263             } else {
26264                 /*
26265                 * 5.2.2.2 The appropriate case among the following must
26266                 * be true:
26267                 */
26268                 if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
26269                     /*
26270                     * 5.2.2.2.1 If the {content type} of the ï¿½actual type
26271                     * definition� is mixed, then the *initial value* of the
26272                     * item must match the canonical lexical representation
26273                     * of the {value constraint} value.
26274                     *
26275                     * ... the *initial value* of an element information
26276                     * item is the string composed of, in order, the
26277                     * [character code] of each character information item in
26278                     * the [children] of that element information item.
26279                     */
26280                     if (! xmlStrEqual(inode->value, inode->decl->value)){
26281                         /*
26282                         * VAL TODO: Report invalid & expected values as well.
26283                         * VAL TODO: Implement the canonical stuff.
26284                         */
26285                         ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
26286                         xmlSchemaCustomErr(ACTXT_CAST vctxt,
26287                             ret, NULL, NULL,
26288                             "The initial value '%s' does not match the fixed "
26289                             "value constraint '%s'",
26290                             inode->value, inode->decl->value);
26291                         goto end_elem;
26292                     }
26293                 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26294                     /*
26295                     * 5.2.2.2.2 If the {content type} of the ï¿½actual type
26296                     * definition� is a simple type definition, then the
26297                     * *actual value* of the item must match the canonical
26298                     * lexical representation of the {value constraint} value.
26299                     */
26300                     /*
26301                     * VAL TODO: *actual value* is the normalized value, impl.
26302                     *           this.
26303                     * VAL TODO: Report invalid & expected values as well.
26304                     * VAL TODO: Implement a comparison with the computed values.
26305                     */
26306                     if (! xmlStrEqual(inode->value,
26307                             inode->decl->value)) {
26308                         ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
26309                         xmlSchemaCustomErr(ACTXT_CAST vctxt,
26310                             ret, NULL, NULL,
26311                             "The actual value '%s' does not match the fixed "
26312                             "value constraint '%s'",
26313                             inode->value,
26314                             inode->decl->value);
26315                         goto end_elem;
26316                     }
26317                 }
26318             }
26319         }
26320     }
26321
26322 end_elem:
26323     if (vctxt->depth < 0) {
26324         /* TODO: raise error? */
26325         return (0);
26326     }
26327     if (vctxt->depth == vctxt->skipDepth)
26328         vctxt->skipDepth = -1;
26329     /*
26330     * Evaluate the history of XPath state objects.
26331     */
26332     if (inode->appliedXPath &&
26333         (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
26334         goto internal_error;
26335     /*
26336     * MAYBE TODO:
26337     * SPEC (6) "The element information item must be ï¿½valid� with
26338     * respect to each of the {identity-constraint definitions} as per
26339     * Identity-constraint Satisfied (�3.11.4)."
26340     */
26341     /*
26342     * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26343     *   need to be built in any case.
26344     *   We will currently build IDC node-tables and bubble them only if
26345     *   keyrefs do exist.
26346     */
26347
26348     /*
26349     * Add the current IDC target-nodes to the IDC node-tables.
26350     */
26351     if ((inode->idcMatchers != NULL) &&
26352         (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26353     {
26354         if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26355             goto internal_error;
26356     }
26357     /*
26358     * Validate IDC keyrefs.
26359     */
26360     if (vctxt->inode->hasKeyrefs)
26361         if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26362             goto internal_error;
26363     /*
26364     * Merge/free the IDC table.
26365     */
26366     if (inode->idcTable != NULL) {
26367 #ifdef DEBUG_IDC_NODE_TABLE
26368         xmlSchemaDebugDumpIDCTable(stdout,
26369             inode->nsName,
26370             inode->localName,
26371             inode->idcTable);
26372 #endif
26373         if ((vctxt->depth > 0) &&
26374             (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26375         {
26376             /*
26377             * Merge the IDC node table with the table of the parent node.
26378             */
26379             if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26380                 goto internal_error;
26381         }
26382     }
26383     /*
26384     * Clear the current ielem.
26385     * VAL TODO: Don't free the PSVI IDC tables if they are
26386     * requested for the PSVI.
26387     */
26388     xmlSchemaClearElemInfo(vctxt, inode);
26389     /*
26390     * Skip further processing if we are on the validation root.
26391     */
26392     if (vctxt->depth == 0) {
26393         vctxt->depth--;
26394         vctxt->inode = NULL;
26395         return (0);
26396     }
26397     /*
26398     * Reset the keyrefDepth if needed.
26399     */
26400     if (vctxt->aidcs != NULL) {
26401         xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26402         do {
26403             if (aidc->keyrefDepth == vctxt->depth) {
26404                 /*
26405                 * A 'keyrefDepth' of a key/unique IDC matches the current
26406                 * depth, this means that we are leaving the scope of the
26407                 * top-most keyref IDC which refers to this IDC.
26408                 */
26409                 aidc->keyrefDepth = -1;
26410             }
26411             aidc = aidc->next;
26412         } while (aidc != NULL);
26413     }
26414     vctxt->depth--;
26415     vctxt->inode = vctxt->elemInfos[vctxt->depth];
26416     /*
26417     * VAL TODO: 7 If the element information item is the ï¿½validation root�, it must be
26418     * ï¿½valid� per Validation Root Valid (ID/IDREF) (�3.3.4).
26419     */
26420     return (ret);
26421
26422 internal_error:
26423     vctxt->err = -1;
26424     return (-1);
26425 }
26426
26427 /*
26428 * 3.4.4 Complex Type Definition Validation Rules
26429 * Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26430 */
26431 static int
26432 xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
26433 {
26434     xmlSchemaNodeInfoPtr pielem;
26435     xmlSchemaTypePtr ptype;
26436     int ret = 0;
26437
26438     if (vctxt->depth <= 0) {
26439         VERROR_INT("xmlSchemaValidateChildElem",
26440             "not intended for the validation root");
26441         return (-1);
26442     }
26443     pielem = vctxt->elemInfos[vctxt->depth -1];
26444     if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26445         pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26446     /*
26447     * Handle 'nilled' elements.
26448     */
26449     if (INODE_NILLED(pielem)) {
26450         /*
26451         * SPEC (cvc-elt) (3.3.4) : (3.2.1)
26452         */
26453         ACTIVATE_PARENT_ELEM;
26454         ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26455         VERROR(ret, NULL,
26456             "Neither character nor element content is allowed, "
26457             "because the element was 'nilled'");
26458         ACTIVATE_ELEM;
26459         goto unexpected_elem;
26460     }
26461
26462     ptype = pielem->typeDef;
26463
26464     if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26465         /*
26466         * Workaround for "anyType": we have currently no content model
26467         * assigned for "anyType", so handle it explicitely.
26468         * "anyType" has an unbounded, lax "any" wildcard.
26469         */
26470         vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26471             vctxt->inode->localName,
26472             vctxt->inode->nsName);
26473
26474         if (vctxt->inode->decl == NULL) {
26475             xmlSchemaAttrInfoPtr iattr;
26476             /*
26477             * Process "xsi:type".
26478             * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
26479             */
26480             iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26481                 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26482             if (iattr != NULL) {
26483                 ret = xmlSchemaProcessXSIType(vctxt, iattr,
26484                     &(vctxt->inode->typeDef), NULL);
26485                 if (ret != 0) {
26486                     if (ret == -1) {
26487                         VERROR_INT("xmlSchemaValidateChildElem",
26488                             "calling xmlSchemaProcessXSIType() to "
26489                             "process the attribute 'xsi:nil'");
26490                         return (-1);
26491                     }
26492                     return (ret);
26493                 }
26494             } else {
26495                  /*
26496                  * Fallback to "anyType".
26497                  *
26498                  * SPEC (cvc-assess-elt)
26499                  * "If the item cannot be ï¿½strictly assessed�, [...]
26500                  * an element information item's schema validity may be laxly
26501                  * assessed if its ï¿½context-determined declaration� is not
26502                  * skip by ï¿½validating� with respect to the ï¿½ur-type
26503                  * definition� as per Element Locally Valid (Type) (�3.3.4)."
26504                 */
26505                 vctxt->inode->typeDef =
26506                     xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26507             }
26508         }
26509         return (0);
26510     }
26511
26512     switch (ptype->contentType) {
26513         case XML_SCHEMA_CONTENT_EMPTY:
26514             /*
26515             * SPEC (2.1) "If the {content type} is empty, then the
26516             * element information item has no character or element
26517             * information item [children]."
26518             */
26519             ACTIVATE_PARENT_ELEM
26520             ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26521             VERROR(ret, NULL,
26522                 "Element content is not allowed, "
26523                 "because the content type is empty");
26524             ACTIVATE_ELEM
26525             goto unexpected_elem;
26526             break;
26527
26528         case XML_SCHEMA_CONTENT_MIXED:
26529         case XML_SCHEMA_CONTENT_ELEMENTS: {
26530             xmlRegExecCtxtPtr regexCtxt;
26531             xmlChar *values[10];
26532             int terminal, nbval = 10, nbneg;
26533
26534             /* VAL TODO: Optimized "anyType" validation.*/
26535
26536             if (ptype->contModel == NULL) {
26537                 VERROR_INT("xmlSchemaValidateChildElem",
26538                     "type has elem content but no content model");
26539                 return (-1);
26540             }
26541             /*
26542             * Safety belf for evaluation if the cont. model was already
26543             * examined to be invalid.
26544             */
26545             if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26546                 VERROR_INT("xmlSchemaValidateChildElem",
26547                     "validating elem, but elem content is already invalid");
26548                 return (-1);
26549             }
26550
26551             regexCtxt = pielem->regexCtxt;
26552             if (regexCtxt == NULL) {
26553                 /*
26554                 * Create the regex context.
26555                 */
26556                 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26557                     (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26558                     vctxt);
26559                 if (regexCtxt == NULL) {
26560                     VERROR_INT("xmlSchemaValidateChildElem",
26561                         "failed to create a regex context");
26562                     return (-1);
26563                 }
26564                 pielem->regexCtxt = regexCtxt;
26565 #ifdef DEBUG_AUTOMATA
26566                 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26567                     pielem->localName);
26568 #endif
26569             }
26570
26571             /*
26572             * SPEC (2.4) "If the {content type} is element-only or mixed,
26573             * then the sequence of the element information item's
26574             * element information item [children], if any, taken in
26575             * order, is ï¿½valid� with respect to the {content type}'s
26576             * particle, as defined in Element Sequence Locally Valid
26577             * (Particle) (�3.9.4)."
26578             */
26579             ret = xmlRegExecPushString2(regexCtxt,
26580                 vctxt->inode->localName,
26581                 vctxt->inode->nsName,
26582                 vctxt->inode);
26583 #ifdef DEBUG_AUTOMATA
26584             if (ret < 0)
26585                 xmlGenericError(xmlGenericErrorContext,
26586                 "AUTOMATON push ERROR for '%s' on '%s'\n",
26587                 vctxt->inode->localName, pielem->localName);
26588             else
26589                 xmlGenericError(xmlGenericErrorContext,
26590                 "AUTOMATON push OK for '%s' on '%s'\n",
26591                 vctxt->inode->localName, pielem->localName);
26592 #endif
26593             if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26594                 VERROR_INT("xmlSchemaValidateChildElem",
26595                     "calling xmlRegExecPushString2()");
26596                 return (-1);
26597             }
26598             if (ret < 0) {
26599                 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26600                     &values[0], &terminal);
26601                 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26602                     XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26603                     "This element is not expected",
26604                     nbval, nbneg, values);
26605                 ret = vctxt->err;
26606                 goto unexpected_elem;
26607             } else
26608                 ret = 0;
26609         }
26610             break;
26611         case XML_SCHEMA_CONTENT_SIMPLE:
26612         case XML_SCHEMA_CONTENT_BASIC:
26613             ACTIVATE_PARENT_ELEM
26614             if (WXS_IS_COMPLEX(ptype)) {
26615                 /*
26616                 * SPEC (cvc-complex-type) (2.2)
26617                 * "If the {content type} is a simple type definition, then
26618                 * the element information item has no element information
26619                 * item [children], ..."
26620                 */
26621                 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26622                 VERROR(ret, NULL, "Element content is not allowed, "
26623                     "because the content type is a simple type definition");
26624             } else {
26625                 /*
26626                 * SPEC (cvc-type) (3.1.2) "The element information item must
26627                 * have no element information item [children]."
26628                 */
26629                 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26630                 VERROR(ret, NULL, "Element content is not allowed, "
26631                     "because the type definition is simple");
26632             }
26633             ACTIVATE_ELEM
26634             ret = vctxt->err;
26635             goto unexpected_elem;
26636             break;
26637
26638         default:
26639             break;
26640     }
26641     return (ret);
26642 unexpected_elem:
26643     /*
26644     * Pop this element and set the skipDepth to skip
26645     * all further content of the parent element.
26646     */
26647     vctxt->skipDepth = vctxt->depth;
26648     vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26649     pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26650     return (ret);
26651 }
26652
26653 #define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26654 #define XML_SCHEMA_PUSH_TEXT_CREATED 2
26655 #define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26656
26657 static int
26658 xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26659                   int nodeType, const xmlChar *value, int len,
26660                   int mode, int *consumed)
26661 {
26662     /*
26663     * Unfortunately we have to duplicate the text sometimes.
26664     * OPTIMIZE: Maybe we could skip it, if:
26665     *   1. content type is simple
26666     *   2. whitespace is "collapse"
26667     *   3. it consists of whitespace only
26668     *
26669     * Process character content.
26670     */
26671     if (consumed != NULL)
26672         *consumed = 0;
26673     if (INODE_NILLED(vctxt->inode)) {
26674         /*
26675         * SPEC cvc-elt (3.3.4 - 3.2.1)
26676         * "The element information item must have no character or
26677         * element information item [children]."
26678         */
26679         VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26680             "Neither character nor element content is allowed "
26681             "because the element is 'nilled'");
26682         return (vctxt->err);
26683     }
26684     /*
26685     * SPEC (2.1) "If the {content type} is empty, then the
26686     * element information item has no character or element
26687     * information item [children]."
26688     */
26689     if (vctxt->inode->typeDef->contentType ==
26690             XML_SCHEMA_CONTENT_EMPTY) {
26691         VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26692             "Character content is not allowed, "
26693             "because the content type is empty");
26694         return (vctxt->err);
26695     }
26696
26697     if (vctxt->inode->typeDef->contentType ==
26698             XML_SCHEMA_CONTENT_ELEMENTS) {
26699         if ((nodeType != XML_TEXT_NODE) ||
26700             (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26701             /*
26702             * SPEC cvc-complex-type (2.3)
26703             * "If the {content type} is element-only, then the
26704             * element information item has no character information
26705             * item [children] other than those whose [character
26706             * code] is defined as a white space in [XML 1.0 (Second
26707             * Edition)]."
26708             */
26709             VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26710                 "Character content other than whitespace is not allowed "
26711                 "because the content type is 'element-only'");
26712             return (vctxt->err);
26713         }
26714         return (0);
26715     }
26716
26717     if ((value == NULL) || (value[0] == 0))
26718         return (0);
26719     /*
26720     * Save the value.
26721     * NOTE that even if the content type is *mixed*, we need the
26722     * *initial value* for default/fixed value constraints.
26723     */
26724     if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26725         ((vctxt->inode->decl == NULL) ||
26726         (vctxt->inode->decl->value == NULL)))
26727         return (0);
26728
26729     if (vctxt->inode->value == NULL) {
26730         /*
26731         * Set the value.
26732         */
26733         switch (mode) {
26734             case XML_SCHEMA_PUSH_TEXT_PERSIST:
26735                 /*
26736                 * When working on a tree.
26737                 */
26738                 vctxt->inode->value = value;
26739                 break;
26740             case XML_SCHEMA_PUSH_TEXT_CREATED:
26741                 /*
26742                 * When working with the reader.
26743                 * The value will be freed by the element info.
26744                 */
26745                 vctxt->inode->value = value;
26746                 if (consumed != NULL)
26747                     *consumed = 1;
26748                 vctxt->inode->flags |=
26749                     XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26750                 break;
26751             case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26752                 /*
26753                 * When working with SAX.
26754                 * The value will be freed by the element info.
26755                 */
26756                 if (len != -1)
26757                     vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26758                 else
26759                     vctxt->inode->value = BAD_CAST xmlStrdup(value);
26760                 vctxt->inode->flags |=
26761                     XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26762                 break;
26763             default:
26764                 break;
26765         }
26766     } else {
26767         if (len < 0)
26768             len = xmlStrlen(value);
26769         /*
26770         * Concat the value.
26771         */
26772         if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
26773             vctxt->inode->value = BAD_CAST xmlStrncat(
26774                 (xmlChar *) vctxt->inode->value, value, len);
26775         } else {
26776             vctxt->inode->value =
26777                 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
26778             vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26779         }
26780     }
26781
26782     return (0);
26783 }
26784
26785 static int
26786 xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
26787 {
26788     int ret = 0;
26789
26790     if ((vctxt->skipDepth != -1) &&
26791         (vctxt->depth >= vctxt->skipDepth)) {
26792         VERROR_INT("xmlSchemaValidateElem",
26793             "in skip-state");
26794         goto internal_error;
26795     }
26796     if (vctxt->xsiAssemble) {
26797         /*
26798         * We will stop validation if there was an error during
26799         * dynamic schema construction.
26800         * Note that we simply set @skipDepth to 0, this could
26801         * mean that a streaming document via SAX would be
26802         * still read to the end but it won't be validated any more.
26803         * TODO: If we are sure how to stop the validation at once
26804         *   for all input scenarios, then this should be changed to
26805         *   instantly stop the validation.
26806         */
26807         ret = xmlSchemaAssembleByXSI(vctxt);
26808         if (ret != 0) {
26809             if (ret == -1)
26810                 goto internal_error;
26811             vctxt->skipDepth = 0;
26812             return(ret);
26813         }
26814     }
26815     if (vctxt->depth > 0) {
26816         /*
26817         * Validate this element against the content model
26818         * of the parent.
26819         */
26820         ret = xmlSchemaValidateChildElem(vctxt);
26821         if (ret != 0) {
26822             if (ret < 0) {
26823                 VERROR_INT("xmlSchemaValidateElem",
26824                     "calling xmlSchemaStreamValidateChildElement()");
26825                 goto internal_error;
26826             }
26827             goto exit;
26828         }
26829         if (vctxt->depth == vctxt->skipDepth)
26830             goto exit;
26831         if ((vctxt->inode->decl == NULL) &&
26832             (vctxt->inode->typeDef == NULL)) {
26833             VERROR_INT("xmlSchemaValidateElem",
26834                 "the child element was valid but neither the "
26835                 "declaration nor the type was set");
26836             goto internal_error;
26837         }
26838     } else {
26839         /*
26840         * Get the declaration of the validation root.
26841         */
26842         vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26843             vctxt->inode->localName,
26844             vctxt->inode->nsName);
26845         if (vctxt->inode->decl == NULL) {
26846             ret = XML_SCHEMAV_CVC_ELT_1;
26847             VERROR(ret, NULL,
26848                 "No matching global declaration available "
26849                 "for the validation root");
26850             goto exit;
26851         }
26852     }
26853
26854     if (vctxt->inode->decl == NULL)
26855         goto type_validation;
26856
26857     if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26858         int skip;
26859         /*
26860         * Wildcards.
26861         */
26862         ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26863         if (ret != 0) {
26864             if (ret < 0) {
26865                 VERROR_INT("xmlSchemaValidateElem",
26866                     "calling xmlSchemaValidateElemWildcard()");
26867                 goto internal_error;
26868             }
26869             goto exit;
26870         }
26871         if (skip) {
26872             vctxt->skipDepth = vctxt->depth;
26873             goto exit;
26874         }
26875         /*
26876         * The declaration might be set by the wildcard validation,
26877         * when the processContents is "lax" or "strict".
26878         */
26879         if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26880             /*
26881             * Clear the "decl" field to not confuse further processing.
26882             */
26883             vctxt->inode->decl = NULL;
26884             goto type_validation;
26885         }
26886     }
26887     /*
26888     * Validate against the declaration.
26889     */
26890     ret = xmlSchemaValidateElemDecl(vctxt);
26891     if (ret != 0) {
26892         if (ret < 0) {
26893             VERROR_INT("xmlSchemaValidateElem",
26894                 "calling xmlSchemaValidateElemDecl()");
26895             goto internal_error;
26896         }
26897         goto exit;
26898     }
26899     /*
26900     * Validate against the type definition.
26901     */
26902 type_validation:
26903
26904     if (vctxt->inode->typeDef == NULL) {
26905         vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26906         ret = XML_SCHEMAV_CVC_TYPE_1;
26907         VERROR(ret, NULL,
26908             "The type definition is absent");
26909         goto exit;
26910     }
26911     if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26912         vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26913         ret = XML_SCHEMAV_CVC_TYPE_2;
26914             VERROR(ret, NULL,
26915             "The type definition is abstract");
26916         goto exit;
26917     }
26918     /*
26919     * Evaluate IDCs. Do it here, since new IDC matchers are registered
26920     * during validation against the declaration. This must be done
26921     * _before_ attribute validation.
26922     */
26923     if (vctxt->xpathStates != NULL) {
26924         ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
26925         vctxt->inode->appliedXPath = 1;
26926         if (ret == -1) {
26927             VERROR_INT("xmlSchemaValidateElem",
26928                 "calling xmlSchemaXPathEvaluate()");
26929             goto internal_error;
26930         }
26931     }
26932     /*
26933     * Validate attributes.
26934     */
26935     if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
26936         if ((vctxt->nbAttrInfos != 0) ||
26937             (vctxt->inode->typeDef->attrUses != NULL)) {
26938
26939             ret = xmlSchemaVAttributesComplex(vctxt);
26940         }
26941     } else if (vctxt->nbAttrInfos != 0) {
26942
26943         ret = xmlSchemaVAttributesSimple(vctxt);
26944     }
26945     /*
26946     * Clear registered attributes.
26947     */
26948     if (vctxt->nbAttrInfos != 0)
26949         xmlSchemaClearAttrInfos(vctxt);
26950     if (ret == -1) {
26951         VERROR_INT("xmlSchemaValidateElem",
26952             "calling attributes validation");
26953         goto internal_error;
26954     }
26955     /*
26956     * Don't return an error if attributes are invalid on purpose.
26957     */
26958     ret = 0;
26959
26960 exit:
26961     if (ret != 0)
26962         vctxt->skipDepth = vctxt->depth;
26963     return (ret);
26964 internal_error:
26965     return (-1);
26966 }
26967
26968 #ifdef XML_SCHEMA_READER_ENABLED
26969 static int
26970 xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
26971 {
26972     const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
26973     int depth, nodeType, ret = 0, consumed;
26974     xmlSchemaNodeInfoPtr ielem;
26975
26976     vctxt->depth = -1;
26977     ret = xmlTextReaderRead(vctxt->reader);
26978     /*
26979     * Move to the document element.
26980     */
26981     while (ret == 1) {
26982         nodeType = xmlTextReaderNodeType(vctxt->reader);
26983         if (nodeType == XML_ELEMENT_NODE)
26984             goto root_found;
26985         ret = xmlTextReaderRead(vctxt->reader);
26986     }
26987     goto exit;
26988
26989 root_found:
26990
26991     do {
26992         depth = xmlTextReaderDepth(vctxt->reader);
26993         nodeType = xmlTextReaderNodeType(vctxt->reader);
26994
26995         if (nodeType == XML_ELEMENT_NODE) {
26996
26997             vctxt->depth++;
26998             if (xmlSchemaValidatorPushElem(vctxt) == -1) {
26999                 VERROR_INT("xmlSchemaVReaderWalk",
27000                     "calling xmlSchemaValidatorPushElem()");
27001                 goto internal_error;
27002             }
27003             ielem = vctxt->inode;
27004             ielem->localName = xmlTextReaderLocalName(vctxt->reader);
27005             ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
27006             ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
27007             /*
27008             * Is the element empty?
27009             */
27010             ret = xmlTextReaderIsEmptyElement(vctxt->reader);
27011             if (ret == -1) {
27012                 VERROR_INT("xmlSchemaVReaderWalk",
27013                     "calling xmlTextReaderIsEmptyElement()");
27014                 goto internal_error;
27015             }
27016             if (ret) {
27017                 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27018             }
27019             /*
27020             * Register attributes.
27021             */
27022             vctxt->nbAttrInfos = 0;
27023             ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
27024             if (ret == -1) {
27025                 VERROR_INT("xmlSchemaVReaderWalk",
27026                     "calling xmlTextReaderMoveToFirstAttribute()");
27027                 goto internal_error;
27028             }
27029             if (ret == 1) {
27030                 do {
27031                     /*
27032                     * VAL TODO: How do we know that the reader works on a
27033                     * node tree, to be able to pass a node here?
27034                     */
27035                     if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
27036                         (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
27037                         xmlTextReaderNamespaceUri(vctxt->reader), 1,
27038                         xmlTextReaderValue(vctxt->reader), 1) == -1) {
27039
27040                         VERROR_INT("xmlSchemaVReaderWalk",
27041                             "calling xmlSchemaValidatorPushAttribute()");
27042                         goto internal_error;
27043                     }
27044                     ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
27045                     if (ret == -1) {
27046                         VERROR_INT("xmlSchemaVReaderWalk",
27047                             "calling xmlTextReaderMoveToFirstAttribute()");
27048                         goto internal_error;
27049                     }
27050                 } while (ret == 1);
27051                 /*
27052                 * Back to element position.
27053                 */
27054                 ret = xmlTextReaderMoveToElement(vctxt->reader);
27055                 if (ret == -1) {
27056                     VERROR_INT("xmlSchemaVReaderWalk",
27057                         "calling xmlTextReaderMoveToElement()");
27058                     goto internal_error;
27059                 }
27060             }
27061             /*
27062             * Validate the element.
27063             */
27064             ret= xmlSchemaValidateElem(vctxt);
27065             if (ret != 0) {
27066                 if (ret == -1) {
27067                     VERROR_INT("xmlSchemaVReaderWalk",
27068                         "calling xmlSchemaValidateElem()");
27069                     goto internal_error;
27070                 }
27071                 goto exit;
27072             }
27073             if (vctxt->depth == vctxt->skipDepth) {
27074                 int curDepth;
27075                 /*
27076                 * Skip all content.
27077                 */
27078                 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
27079                     ret = xmlTextReaderRead(vctxt->reader);
27080                     curDepth = xmlTextReaderDepth(vctxt->reader);
27081                     while ((ret == 1) && (curDepth != depth)) {
27082                         ret = xmlTextReaderRead(vctxt->reader);
27083                         curDepth = xmlTextReaderDepth(vctxt->reader);
27084                     }
27085                     if (ret < 0) {
27086                         /*
27087                         * VAL TODO: A reader error occured; what to do here?
27088                         */
27089                         ret = 1;
27090                         goto exit;
27091                     }
27092                 }
27093                 goto leave_elem;
27094             }
27095             /*
27096             * READER VAL TODO: Is an END_ELEM really never called
27097             * if the elem is empty?
27098             */
27099             if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27100                 goto leave_elem;
27101         } else if (nodeType == END_ELEM) {
27102             /*
27103             * Process END of element.
27104             */
27105 leave_elem:
27106             ret = xmlSchemaValidatorPopElem(vctxt);
27107             if (ret != 0) {
27108                 if (ret < 0) {
27109                     VERROR_INT("xmlSchemaVReaderWalk",
27110                         "calling xmlSchemaValidatorPopElem()");
27111                     goto internal_error;
27112                 }
27113                 goto exit;
27114             }
27115             if (vctxt->depth >= 0)
27116                 ielem = vctxt->inode;
27117             else
27118                 ielem = NULL;
27119         } else if ((nodeType == XML_TEXT_NODE) ||
27120             (nodeType == XML_CDATA_SECTION_NODE) ||
27121             (nodeType == WHTSP) ||
27122             (nodeType == SIGN_WHTSP)) {
27123             /*
27124             * Process character content.
27125             */
27126             xmlChar *value;
27127
27128             if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
27129                 nodeType = XML_TEXT_NODE;
27130
27131             value = xmlTextReaderValue(vctxt->reader);
27132             ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
27133                 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
27134             if (! consumed)
27135                 xmlFree(value);
27136             if (ret == -1) {
27137                 VERROR_INT("xmlSchemaVReaderWalk",
27138                     "calling xmlSchemaVPushText()");
27139                 goto internal_error;
27140             }
27141         } else if ((nodeType == XML_ENTITY_NODE) ||
27142             (nodeType == XML_ENTITY_REF_NODE)) {
27143             /*
27144             * VAL TODO: What to do with entities?
27145             */
27146             TODO
27147         }
27148         /*
27149         * Read next node.
27150         */
27151         ret = xmlTextReaderRead(vctxt->reader);
27152     } while (ret == 1);
27153
27154 exit:
27155     return (ret);
27156 internal_error:
27157     return (-1);
27158 }
27159 #endif
27160
27161 /************************************************************************
27162  *                                                                      *
27163  *                      SAX validation handlers                         *
27164  *                                                                      *
27165  ************************************************************************/
27166
27167 /*
27168 * Process text content.
27169 */
27170 static void
27171 xmlSchemaSAXHandleText(void *ctx,
27172                        const xmlChar * ch,
27173                        int len)
27174 {
27175     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27176
27177     if (vctxt->depth < 0)
27178         return;
27179     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27180         return;
27181     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27182         vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27183     if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
27184         XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27185         VERROR_INT("xmlSchemaSAXHandleCDataSection",
27186             "calling xmlSchemaVPushText()");
27187         vctxt->err = -1;
27188         xmlStopParser(vctxt->parserCtxt);
27189     }
27190 }
27191
27192 /*
27193 * Process CDATA content.
27194 */
27195 static void
27196 xmlSchemaSAXHandleCDataSection(void *ctx,
27197                              const xmlChar * ch,
27198                              int len)
27199 {
27200     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27201
27202     if (vctxt->depth < 0)
27203         return;
27204     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27205         return;
27206     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27207         vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27208     if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
27209         XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27210         VERROR_INT("xmlSchemaSAXHandleCDataSection",
27211             "calling xmlSchemaVPushText()");
27212         vctxt->err = -1;
27213         xmlStopParser(vctxt->parserCtxt);
27214     }
27215 }
27216
27217 static void
27218 xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
27219                             const xmlChar * name ATTRIBUTE_UNUSED)
27220 {
27221     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27222
27223     if (vctxt->depth < 0)
27224         return;
27225     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27226         return;
27227     /* SAX VAL TODO: What to do here? */
27228     TODO
27229 }
27230
27231 static void
27232 xmlSchemaSAXHandleStartElementNs(void *ctx,
27233                                  const xmlChar * localname,
27234                                  const xmlChar * prefix ATTRIBUTE_UNUSED,
27235                                  const xmlChar * URI,
27236                                  int nb_namespaces,
27237                                  const xmlChar ** namespaces,
27238                                  int nb_attributes,
27239                                  int nb_defaulted ATTRIBUTE_UNUSED,
27240                                  const xmlChar ** attributes)
27241 {
27242     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27243     int ret;
27244     xmlSchemaNodeInfoPtr ielem;
27245     int i, j;
27246
27247     /*
27248     * SAX VAL TODO: What to do with nb_defaulted?
27249     */
27250     /*
27251     * Skip elements if inside a "skip" wildcard or invalid.
27252     */
27253     vctxt->depth++;
27254     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27255         return;
27256     /*
27257     * Push the element.
27258     */
27259     if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27260         VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27261             "calling xmlSchemaValidatorPushElem()");
27262         goto internal_error;
27263     }
27264     ielem = vctxt->inode;
27265     /*
27266     * TODO: Is this OK?
27267     */
27268     ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
27269     ielem->localName = localname;
27270     ielem->nsName = URI;
27271     ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27272     /*
27273     * Register namespaces on the elem info.
27274     */
27275     if (nb_namespaces != 0) {
27276         /*
27277         * Although the parser builds its own namespace list,
27278         * we have no access to it, so we'll use an own one.
27279         */
27280         for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
27281             /*
27282             * Store prefix and namespace name.
27283             */
27284             if (ielem->nsBindings == NULL) {
27285                 ielem->nsBindings =
27286                     (const xmlChar **) xmlMalloc(10 *
27287                         sizeof(const xmlChar *));
27288                 if (ielem->nsBindings == NULL) {
27289                     xmlSchemaVErrMemory(vctxt,
27290                         "allocating namespace bindings for SAX validation",
27291                         NULL);
27292                     goto internal_error;
27293                 }
27294                 ielem->nbNsBindings = 0;
27295                 ielem->sizeNsBindings = 5;
27296             } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
27297                 ielem->sizeNsBindings *= 2;
27298                 ielem->nsBindings =
27299                     (const xmlChar **) xmlRealloc(
27300                         (void *) ielem->nsBindings,
27301                         ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
27302                 if (ielem->nsBindings == NULL) {
27303                     xmlSchemaVErrMemory(vctxt,
27304                         "re-allocating namespace bindings for SAX validation",
27305                         NULL);
27306                     goto internal_error;
27307                 }
27308             }
27309
27310             ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
27311             if (namespaces[j+1][0] == 0) {
27312                 /*
27313                 * Handle xmlns="".
27314                 */
27315                 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
27316             } else
27317                 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
27318                     namespaces[j+1];
27319             ielem->nbNsBindings++;
27320         }
27321     }
27322     /*
27323     * Register attributes.
27324     * SAX VAL TODO: We are not adding namespace declaration
27325     * attributes yet.
27326     */
27327     if (nb_attributes != 0) {
27328         xmlChar *value;
27329
27330         for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27331             /*
27332             * Duplicate the value.
27333             */
27334             value = xmlStrndup(attributes[j+3],
27335                 attributes[j+4] - attributes[j+3]);
27336             /*
27337             * TODO: Set the node line.
27338             */
27339             ret = xmlSchemaValidatorPushAttribute(vctxt,
27340                 NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
27341                 value, 1);
27342             if (ret == -1) {
27343                 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27344                     "calling xmlSchemaValidatorPushAttribute()");
27345                 goto internal_error;
27346             }
27347         }
27348     }
27349     /*
27350     * Validate the element.
27351     */
27352     ret = xmlSchemaValidateElem(vctxt);
27353     if (ret != 0) {
27354         if (ret == -1) {
27355             VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27356                 "calling xmlSchemaValidateElem()");
27357             goto internal_error;
27358         }
27359         goto exit;
27360     }
27361
27362 exit:
27363     return;
27364 internal_error:
27365     vctxt->err = -1;
27366     xmlStopParser(vctxt->parserCtxt);
27367     return;
27368 }
27369
27370 static void
27371 xmlSchemaSAXHandleEndElementNs(void *ctx,
27372                                const xmlChar * localname ATTRIBUTE_UNUSED,
27373                                const xmlChar * prefix ATTRIBUTE_UNUSED,
27374                                const xmlChar * URI ATTRIBUTE_UNUSED)
27375 {
27376     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27377     int res;
27378
27379     /*
27380     * Skip elements if inside a "skip" wildcard or if invalid.
27381     */
27382     if (vctxt->skipDepth != -1) {
27383         if (vctxt->depth > vctxt->skipDepth) {
27384             vctxt->depth--;
27385             return;
27386         } else
27387             vctxt->skipDepth = -1;
27388     }
27389     /*
27390     * SAX VAL TODO: Just a temporary check.
27391     */
27392     if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27393         (!xmlStrEqual(vctxt->inode->nsName, URI))) {
27394         VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27395             "elem pop mismatch");
27396     }
27397     res = xmlSchemaValidatorPopElem(vctxt);
27398     if (res != 0) {
27399         if (res < 0) {
27400             VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27401                 "calling xmlSchemaValidatorPopElem()");
27402             goto internal_error;
27403         }
27404         goto exit;
27405     }
27406 exit:
27407     return;
27408 internal_error:
27409     vctxt->err = -1;
27410     xmlStopParser(vctxt->parserCtxt);
27411     return;
27412 }
27413
27414 /************************************************************************
27415  *                                                                      *
27416  *                      Validation interfaces                           *
27417  *                                                                      *
27418  ************************************************************************/
27419
27420 /**
27421  * xmlSchemaNewValidCtxt:
27422  * @schema:  a precompiled XML Schemas
27423  *
27424  * Create an XML Schemas validation context based on the given schema.
27425  *
27426  * Returns the validation context or NULL in case of error
27427  */
27428 xmlSchemaValidCtxtPtr
27429 xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27430 {
27431     xmlSchemaValidCtxtPtr ret;
27432
27433     ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27434     if (ret == NULL) {
27435         xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
27436         return (NULL);
27437     }
27438     memset(ret, 0, sizeof(xmlSchemaValidCtxt));
27439     ret->type = XML_SCHEMA_CTXT_VALIDATOR;
27440     ret->dict = xmlDictCreate();
27441     ret->nodeQNames = xmlSchemaItemListCreate();
27442     ret->schema = schema;
27443     return (ret);
27444 }
27445
27446 /**
27447  * xmlSchemaClearValidCtxt:
27448  * @ctxt: the schema validation context
27449  *
27450  * Free the resources associated to the schema validation context;
27451  * leaves some fields alive intended for reuse of the context.
27452  */
27453 static void
27454 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27455 {
27456     if (vctxt == NULL)
27457         return;
27458
27459     /*
27460     * TODO: Should we clear the flags?
27461     *   Might be problematic if one reuses the context
27462     *   and assumes that the options remain the same.
27463     */
27464     vctxt->flags = 0;
27465     vctxt->validationRoot = NULL;
27466     vctxt->doc = NULL;
27467 #ifdef LIBXML_READER_ENABLED
27468     vctxt->reader = NULL;
27469 #endif
27470     vctxt->hasKeyrefs = 0;
27471
27472     if (vctxt->value != NULL) {
27473         xmlSchemaFreeValue(vctxt->value);
27474         vctxt->value = NULL;
27475     }
27476     /*
27477     * Augmented IDC information.
27478     */
27479     if (vctxt->aidcs != NULL) {
27480         xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27481         do {
27482             next = cur->next;
27483             xmlFree(cur);
27484             cur = next;
27485         } while (cur != NULL);
27486         vctxt->aidcs = NULL;
27487     }
27488     if (vctxt->idcMatcherCache != NULL) {
27489         xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp;
27490
27491         while (matcher) {
27492             tmp = matcher;
27493             matcher = matcher->nextCached;
27494             xmlSchemaIDCFreeMatcherList(tmp);
27495         }
27496         vctxt->idcMatcherCache = NULL;
27497     }
27498
27499
27500     if (vctxt->idcNodes != NULL) {
27501         int i;
27502         xmlSchemaPSVIIDCNodePtr item;
27503
27504         for (i = 0; i < vctxt->nbIdcNodes; i++) {
27505             item = vctxt->idcNodes[i];
27506             xmlFree(item->keys);
27507             xmlFree(item);
27508         }
27509         xmlFree(vctxt->idcNodes);
27510         vctxt->idcNodes = NULL;
27511         vctxt->nbIdcNodes = 0;
27512         vctxt->sizeIdcNodes = 0;
27513     }
27514     /*
27515     * Note that we won't delete the XPath state pool here.
27516     */
27517     if (vctxt->xpathStates != NULL) {
27518         xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27519         vctxt->xpathStates = NULL;
27520     }
27521     /*
27522     * Attribute info.
27523     */
27524     if (vctxt->nbAttrInfos != 0) {
27525         xmlSchemaClearAttrInfos(vctxt);
27526     }
27527     /*
27528     * Element info.
27529     */
27530     if (vctxt->elemInfos != NULL) {
27531         int i;
27532         xmlSchemaNodeInfoPtr ei;
27533
27534         for (i = 0; i < vctxt->sizeElemInfos; i++) {
27535             ei = vctxt->elemInfos[i];
27536             if (ei == NULL)
27537                 break;
27538             xmlSchemaClearElemInfo(vctxt, ei);
27539         }
27540     }
27541     xmlSchemaItemListClear(vctxt->nodeQNames);
27542     /* Recreate the dict. */
27543     xmlDictFree(vctxt->dict);
27544     /*
27545     * TODO: Is is save to recreate it? Do we have a scenario
27546     * where the user provides the dict?
27547     */
27548     vctxt->dict = xmlDictCreate();
27549 }
27550
27551 /**
27552  * xmlSchemaFreeValidCtxt:
27553  * @ctxt:  the schema validation context
27554  *
27555  * Free the resources associated to the schema validation context
27556  */
27557 void
27558 xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27559 {
27560     if (ctxt == NULL)
27561         return;
27562     if (ctxt->value != NULL)
27563         xmlSchemaFreeValue(ctxt->value);
27564     if (ctxt->pctxt != NULL)
27565         xmlSchemaFreeParserCtxt(ctxt->pctxt);
27566     if (ctxt->idcNodes != NULL) {
27567         int i;
27568         xmlSchemaPSVIIDCNodePtr item;
27569
27570         for (i = 0; i < ctxt->nbIdcNodes; i++) {
27571             item = ctxt->idcNodes[i];
27572             xmlFree(item->keys);
27573             xmlFree(item);
27574         }
27575         xmlFree(ctxt->idcNodes);
27576     }
27577     if (ctxt->idcKeys != NULL) {
27578         int i;
27579         for (i = 0; i < ctxt->nbIdcKeys; i++)
27580             xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27581         xmlFree(ctxt->idcKeys);
27582     }
27583
27584     if (ctxt->xpathStates != NULL) {
27585         xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27586         ctxt->xpathStates = NULL;
27587     }
27588     if (ctxt->xpathStatePool != NULL) {
27589         xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27590         ctxt->xpathStatePool = NULL;
27591     }
27592
27593     /*
27594     * Augmented IDC information.
27595     */
27596     if (ctxt->aidcs != NULL) {
27597         xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27598         do {
27599             next = cur->next;
27600             xmlFree(cur);
27601             cur = next;
27602         } while (cur != NULL);
27603     }
27604     if (ctxt->attrInfos != NULL) {
27605         int i;
27606         xmlSchemaAttrInfoPtr attr;
27607
27608         /* Just a paranoid call to the cleanup. */
27609         if (ctxt->nbAttrInfos != 0)
27610             xmlSchemaClearAttrInfos(ctxt);
27611         for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27612             attr = ctxt->attrInfos[i];
27613             xmlFree(attr);
27614         }
27615         xmlFree(ctxt->attrInfos);
27616     }
27617     if (ctxt->elemInfos != NULL) {
27618         int i;
27619         xmlSchemaNodeInfoPtr ei;
27620
27621         for (i = 0; i < ctxt->sizeElemInfos; i++) {
27622             ei = ctxt->elemInfos[i];
27623             if (ei == NULL)
27624                 break;
27625             xmlSchemaClearElemInfo(ctxt, ei);
27626             xmlFree(ei);
27627         }
27628         xmlFree(ctxt->elemInfos);
27629     }
27630     if (ctxt->nodeQNames != NULL)
27631         xmlSchemaItemListFree(ctxt->nodeQNames);
27632     if (ctxt->dict != NULL)
27633         xmlDictFree(ctxt->dict);
27634     xmlFree(ctxt);
27635 }
27636
27637 /**
27638  * xmlSchemaIsValid:
27639  * @ctxt: the schema validation context
27640  *
27641  * Check if any error was detected during validation.
27642  *
27643  * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27644  *         of internal error.
27645  */
27646 int
27647 xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27648 {
27649     if (ctxt == NULL)
27650         return(-1);
27651     return(ctxt->err == 0);
27652 }
27653
27654 /**
27655  * xmlSchemaSetValidErrors:
27656  * @ctxt:  a schema validation context
27657  * @err:  the error function
27658  * @warn: the warning function
27659  * @ctx: the functions context
27660  *
27661  * Set the error and warning callback informations
27662  */
27663 void
27664 xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27665                         xmlSchemaValidityErrorFunc err,
27666                         xmlSchemaValidityWarningFunc warn, void *ctx)
27667 {
27668     if (ctxt == NULL)
27669         return;
27670     ctxt->error = err;
27671     ctxt->warning = warn;
27672     ctxt->errCtxt = ctx;
27673     if (ctxt->pctxt != NULL)
27674         xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
27675 }
27676
27677 /**
27678  * xmlSchemaSetValidStructuredErrors:
27679  * @ctxt:  a schema validation context
27680  * @serror:  the structured error function
27681  * @ctx: the functions context
27682  *
27683  * Set the structured error callback
27684  */
27685 void
27686 xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
27687                                   xmlStructuredErrorFunc serror, void *ctx)
27688 {
27689     if (ctxt == NULL)
27690         return;
27691         ctxt->serror = serror;
27692     ctxt->error = NULL;
27693     ctxt->warning = NULL;
27694     ctxt->errCtxt = ctx;
27695     if (ctxt->pctxt != NULL)
27696         xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
27697 }
27698
27699 /**
27700  * xmlSchemaGetValidErrors:
27701  * @ctxt: a XML-Schema validation context
27702  * @err: the error function result
27703  * @warn: the warning function result
27704  * @ctx: the functions context result
27705  *
27706  * Get the error and warning callback informations
27707  *
27708  * Returns -1 in case of error and 0 otherwise
27709  */
27710 int
27711 xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27712                         xmlSchemaValidityErrorFunc * err,
27713                         xmlSchemaValidityWarningFunc * warn, void **ctx)
27714 {
27715         if (ctxt == NULL)
27716                 return (-1);
27717         if (err != NULL)
27718                 *err = ctxt->error;
27719         if (warn != NULL)
27720                 *warn = ctxt->warning;
27721         if (ctx != NULL)
27722                 *ctx = ctxt->errCtxt;
27723         return (0);
27724 }
27725
27726
27727 /**
27728  * xmlSchemaSetValidOptions:
27729  * @ctxt:       a schema validation context
27730  * @options: a combination of xmlSchemaValidOption
27731  *
27732  * Sets the options to be used during the validation.
27733  *
27734  * Returns 0 in case of success, -1 in case of an
27735  * API error.
27736  */
27737 int
27738 xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27739                          int options)
27740
27741 {
27742     int i;
27743
27744     if (ctxt == NULL)
27745         return (-1);
27746     /*
27747     * WARNING: Change the start value if adding to the
27748     * xmlSchemaValidOption.
27749     * TODO: Is there an other, more easy to maintain,
27750     * way?
27751     */
27752     for (i = 1; i < (int) sizeof(int) * 8; i++) {
27753         if (options & 1<<i)
27754             return (-1);
27755     }
27756     ctxt->options = options;
27757     return (0);
27758 }
27759
27760 /**
27761  * xmlSchemaValidCtxtGetOptions:
27762  * @ctxt: a schema validation context
27763  *
27764  * Get the validation context options.
27765  *
27766  * Returns the option combination or -1 on error.
27767  */
27768 int
27769 xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
27770
27771 {
27772     if (ctxt == NULL)
27773         return (-1);
27774     else
27775         return (ctxt->options);
27776 }
27777
27778 static int
27779 xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27780 {
27781     xmlAttrPtr attr;
27782     int ret = 0;
27783     xmlSchemaNodeInfoPtr ielem = NULL;
27784     xmlNodePtr node, valRoot;
27785     const xmlChar *nsName;
27786
27787     /* DOC VAL TODO: Move this to the start function. */
27788     valRoot = xmlDocGetRootElement(vctxt->doc);
27789     if (valRoot == NULL) {
27790         /* VAL TODO: Error code? */
27791         VERROR(1, NULL, "The document has no document element");
27792         return (1);
27793     }
27794     vctxt->depth = -1;
27795     vctxt->validationRoot = valRoot;
27796     node = valRoot;
27797     while (node != NULL) {
27798         if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27799             goto next_sibling;
27800         if (node->type == XML_ELEMENT_NODE) {
27801
27802             /*
27803             * Init the node-info.
27804             */
27805             vctxt->depth++;
27806             if (xmlSchemaValidatorPushElem(vctxt) == -1)
27807                 goto internal_error;
27808             ielem = vctxt->inode;
27809             ielem->node = node;
27810             ielem->nodeLine = node->line;
27811             ielem->localName = node->name;
27812             if (node->ns != NULL)
27813                 ielem->nsName = node->ns->href;
27814             ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27815             /*
27816             * Register attributes.
27817             * DOC VAL TODO: We do not register namespace declaration
27818             * attributes yet.
27819             */
27820             vctxt->nbAttrInfos = 0;
27821             if (node->properties != NULL) {
27822                 attr = node->properties;
27823                 do {
27824                     if (attr->ns != NULL)
27825                         nsName = attr->ns->href;
27826                     else
27827                         nsName = NULL;
27828                     ret = xmlSchemaValidatorPushAttribute(vctxt,
27829                         (xmlNodePtr) attr,
27830                         /*
27831                         * Note that we give it the line number of the
27832                         * parent element.
27833                         */
27834                         ielem->nodeLine,
27835                         attr->name, nsName, 0,
27836                         xmlNodeListGetString(attr->doc, attr->children, 1), 1);
27837                     if (ret == -1) {
27838                         VERROR_INT("xmlSchemaDocWalk",
27839                             "calling xmlSchemaValidatorPushAttribute()");
27840                         goto internal_error;
27841                     }
27842                     attr = attr->next;
27843                 } while (attr);
27844             }
27845             /*
27846             * Validate the element.
27847             */
27848             ret = xmlSchemaValidateElem(vctxt);
27849             if (ret != 0) {
27850                 if (ret == -1) {
27851                     VERROR_INT("xmlSchemaDocWalk",
27852                         "calling xmlSchemaValidateElem()");
27853                     goto internal_error;
27854                 }
27855                 /*
27856                 * Don't stop validation; just skip the content
27857                 * of this element.
27858                 */
27859                 goto leave_node;
27860             }
27861             if ((vctxt->skipDepth != -1) &&
27862                 (vctxt->depth >= vctxt->skipDepth))
27863                 goto leave_node;
27864         } else if ((node->type == XML_TEXT_NODE) ||
27865             (node->type == XML_CDATA_SECTION_NODE)) {
27866             /*
27867             * Process character content.
27868             */
27869             if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
27870                 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27871             ret = xmlSchemaVPushText(vctxt, node->type, node->content,
27872                 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
27873             if (ret < 0) {
27874                 VERROR_INT("xmlSchemaVDocWalk",
27875                     "calling xmlSchemaVPushText()");
27876                 goto internal_error;
27877             }
27878             /*
27879             * DOC VAL TODO: Should we skip further validation of the
27880             * element content here?
27881             */
27882         } else if ((node->type == XML_ENTITY_NODE) ||
27883             (node->type == XML_ENTITY_REF_NODE)) {
27884             /*
27885             * DOC VAL TODO: What to do with entities?
27886             */
27887             VERROR_INT("xmlSchemaVDocWalk",
27888                 "there is at least one entity reference in the node-tree "
27889                 "currently being validated. Processing of entities with "
27890                 "this XML Schema processor is not supported (yet). Please "
27891                 "substitute entities before validation.");
27892             goto internal_error;
27893         } else {
27894             goto leave_node;
27895             /*
27896             * DOC VAL TODO: XInclude nodes, etc.
27897             */
27898         }
27899         /*
27900         * Walk the doc.
27901         */
27902         if (node->children != NULL) {
27903             node = node->children;
27904             continue;
27905         }
27906 leave_node:
27907         if (node->type == XML_ELEMENT_NODE) {
27908             /*
27909             * Leaving the scope of an element.
27910             */
27911             if (node != vctxt->inode->node) {
27912                 VERROR_INT("xmlSchemaVDocWalk",
27913                     "element position mismatch");
27914                 goto internal_error;
27915             }
27916             ret = xmlSchemaValidatorPopElem(vctxt);
27917             if (ret != 0) {
27918                 if (ret < 0) {
27919                     VERROR_INT("xmlSchemaVDocWalk",
27920                         "calling xmlSchemaValidatorPopElem()");
27921                     goto internal_error;
27922                 }
27923             }
27924             if (node == valRoot)
27925                 goto exit;
27926         }
27927 next_sibling:
27928         if (node->next != NULL)
27929             node = node->next;
27930         else {
27931             node = node->parent;
27932             goto leave_node;
27933         }
27934     }
27935
27936 exit:
27937     return (ret);
27938 internal_error:
27939     return (-1);
27940 }
27941
27942 static int
27943 xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
27944     /*
27945     * Some initialization.
27946     */
27947     vctxt->err = 0;
27948     vctxt->nberrors = 0;
27949     vctxt->depth = -1;
27950     vctxt->skipDepth = -1;
27951     vctxt->xsiAssemble = 0;
27952     vctxt->hasKeyrefs = 0;
27953 #ifdef ENABLE_IDC_NODE_TABLES_TEST
27954     vctxt->createIDCNodeTables = 1;
27955 #else
27956     vctxt->createIDCNodeTables = 0;
27957 #endif
27958     /*
27959     * Create a schema + parser if necessary.
27960     */
27961     if (vctxt->schema == NULL) {
27962         xmlSchemaParserCtxtPtr pctxt;
27963
27964         vctxt->xsiAssemble = 1;
27965         /*
27966         * If not schema was given then we will create a schema
27967         * dynamically using XSI schema locations.
27968         *
27969         * Create the schema parser context.
27970         */
27971         if ((vctxt->pctxt == NULL) &&
27972            (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
27973            return (-1);
27974         pctxt = vctxt->pctxt;
27975         pctxt->xsiAssemble = 1;
27976         /*
27977         * Create the schema.
27978         */
27979         vctxt->schema = xmlSchemaNewSchema(pctxt);
27980         if (vctxt->schema == NULL)
27981             return (-1);
27982         /*
27983         * Create the schema construction context.
27984         */
27985         pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
27986         if (pctxt->constructor == NULL)
27987             return(-1);
27988         pctxt->constructor->mainSchema = vctxt->schema;
27989         /*
27990         * Take ownership of the constructor to be able to free it.
27991         */
27992         pctxt->ownsConstructor = 1;
27993     }
27994     /*
27995     * Augment the IDC definitions for the main schema and all imported ones
27996     * NOTE: main schema if the first in the imported list
27997     */
27998     xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt);
27999
28000     return(0);
28001 }
28002
28003 static void
28004 xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
28005     if (vctxt->xsiAssemble) {
28006         if (vctxt->schema != NULL) {
28007             xmlSchemaFree(vctxt->schema);
28008             vctxt->schema = NULL;
28009         }
28010     }
28011     xmlSchemaClearValidCtxt(vctxt);
28012 }
28013
28014 static int
28015 xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
28016 {
28017     int ret = 0;
28018
28019     if (xmlSchemaPreRun(vctxt) < 0)
28020         return(-1);
28021
28022     if (vctxt->doc != NULL) {
28023         /*
28024          * Tree validation.
28025          */
28026         ret = xmlSchemaVDocWalk(vctxt);
28027 #ifdef LIBXML_READER_ENABLED
28028     } else if (vctxt->reader != NULL) {
28029         /*
28030          * XML Reader validation.
28031          */
28032 #ifdef XML_SCHEMA_READER_ENABLED
28033         ret = xmlSchemaVReaderWalk(vctxt);
28034 #endif
28035 #endif
28036     } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
28037         /*
28038          * SAX validation.
28039          */
28040         ret = xmlParseDocument(vctxt->parserCtxt);
28041     } else {
28042         VERROR_INT("xmlSchemaVStart",
28043             "no instance to validate");
28044         ret = -1;
28045     }
28046
28047     xmlSchemaPostRun(vctxt);
28048     if (ret == 0)
28049         ret = vctxt->err;
28050     return (ret);
28051 }
28052
28053 /**
28054  * xmlSchemaValidateOneElement:
28055  * @ctxt:  a schema validation context
28056  * @elem:  an element node
28057  *
28058  * Validate a branch of a tree, starting with the given @elem.
28059  *
28060  * Returns 0 if the element and its subtree is valid, a positive error
28061  * code number otherwise and -1 in case of an internal or API error.
28062  */
28063 int
28064 xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
28065 {
28066     if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
28067         return (-1);
28068
28069     if (ctxt->schema == NULL)
28070         return (-1);
28071
28072     ctxt->doc = elem->doc;
28073     ctxt->node = elem;
28074     ctxt->validationRoot = elem;
28075     return(xmlSchemaVStart(ctxt));
28076 }
28077
28078 /**
28079  * xmlSchemaValidateDoc:
28080  * @ctxt:  a schema validation context
28081  * @doc:  a parsed document tree
28082  *
28083  * Validate a document tree in memory.
28084  *
28085  * Returns 0 if the document is schemas valid, a positive error code
28086  *     number otherwise and -1 in case of internal or API error.
28087  */
28088 int
28089 xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
28090 {
28091     if ((ctxt == NULL) || (doc == NULL))
28092         return (-1);
28093
28094     ctxt->doc = doc;
28095     ctxt->node = xmlDocGetRootElement(doc);
28096     if (ctxt->node == NULL) {
28097         xmlSchemaCustomErr(ACTXT_CAST ctxt,
28098             XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
28099             (xmlNodePtr) doc, NULL,
28100             "The document has no document element", NULL, NULL);
28101         return (ctxt->err);
28102     }
28103     ctxt->validationRoot = ctxt->node;
28104     return (xmlSchemaVStart(ctxt));
28105 }
28106
28107
28108 /************************************************************************
28109  *                                                                      *
28110  *              Function and data for SAX streaming API                 *
28111  *                                                                      *
28112  ************************************************************************/
28113 typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
28114 typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
28115
28116 struct _xmlSchemaSplitSAXData {
28117     xmlSAXHandlerPtr      user_sax;
28118     void                 *user_data;
28119     xmlSchemaValidCtxtPtr ctxt;
28120     xmlSAXHandlerPtr      schemas_sax;
28121 };
28122
28123 #define XML_SAX_PLUG_MAGIC 0xdc43ba21
28124
28125 struct _xmlSchemaSAXPlug {
28126     unsigned int magic;
28127
28128     /* the original callbacks informations */
28129     xmlSAXHandlerPtr     *user_sax_ptr;
28130     xmlSAXHandlerPtr      user_sax;
28131     void                **user_data_ptr;
28132     void                 *user_data;
28133
28134     /* the block plugged back and validation informations */
28135     xmlSAXHandler         schemas_sax;
28136     xmlSchemaValidCtxtPtr ctxt;
28137 };
28138
28139 /* All those functions just bounces to the user provided SAX handlers */
28140 static void
28141 internalSubsetSplit(void *ctx, const xmlChar *name,
28142                const xmlChar *ExternalID, const xmlChar *SystemID)
28143 {
28144     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28145     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28146         (ctxt->user_sax->internalSubset != NULL))
28147         ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
28148                                        SystemID);
28149 }
28150
28151 static int
28152 isStandaloneSplit(void *ctx)
28153 {
28154     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28155     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28156         (ctxt->user_sax->isStandalone != NULL))
28157         return(ctxt->user_sax->isStandalone(ctxt->user_data));
28158     return(0);
28159 }
28160
28161 static int
28162 hasInternalSubsetSplit(void *ctx)
28163 {
28164     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28165     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28166         (ctxt->user_sax->hasInternalSubset != NULL))
28167         return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
28168     return(0);
28169 }
28170
28171 static int
28172 hasExternalSubsetSplit(void *ctx)
28173 {
28174     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28175     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28176         (ctxt->user_sax->hasExternalSubset != NULL))
28177         return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
28178     return(0);
28179 }
28180
28181 static void
28182 externalSubsetSplit(void *ctx, const xmlChar *name,
28183                const xmlChar *ExternalID, const xmlChar *SystemID)
28184 {
28185     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28186     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28187         (ctxt->user_sax->externalSubset != NULL))
28188         ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID,
28189                                        SystemID);
28190 }
28191
28192 static xmlParserInputPtr
28193 resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
28194 {
28195     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28196     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28197         (ctxt->user_sax->resolveEntity != NULL))
28198         return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
28199                                              systemId));
28200     return(NULL);
28201 }
28202
28203 static xmlEntityPtr
28204 getEntitySplit(void *ctx, const xmlChar *name)
28205 {
28206     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28207     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28208         (ctxt->user_sax->getEntity != NULL))
28209         return(ctxt->user_sax->getEntity(ctxt->user_data, name));
28210     return(NULL);
28211 }
28212
28213 static xmlEntityPtr
28214 getParameterEntitySplit(void *ctx, const xmlChar *name)
28215 {
28216     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28217     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28218         (ctxt->user_sax->getParameterEntity != NULL))
28219         return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
28220     return(NULL);
28221 }
28222
28223
28224 static void
28225 entityDeclSplit(void *ctx, const xmlChar *name, int type,
28226           const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
28227 {
28228     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28229     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28230         (ctxt->user_sax->entityDecl != NULL))
28231         ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
28232                                    systemId, content);
28233 }
28234
28235 static void
28236 attributeDeclSplit(void *ctx, const xmlChar * elem,
28237                    const xmlChar * name, int type, int def,
28238                    const xmlChar * defaultValue, xmlEnumerationPtr tree)
28239 {
28240     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28241     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28242         (ctxt->user_sax->attributeDecl != NULL)) {
28243         ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
28244                                       def, defaultValue, tree);
28245     } else {
28246         xmlFreeEnumeration(tree);
28247     }
28248 }
28249
28250 static void
28251 elementDeclSplit(void *ctx, const xmlChar *name, int type,
28252             xmlElementContentPtr content)
28253 {
28254     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28255     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28256         (ctxt->user_sax->elementDecl != NULL))
28257         ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
28258 }
28259
28260 static void
28261 notationDeclSplit(void *ctx, const xmlChar *name,
28262              const xmlChar *publicId, const xmlChar *systemId)
28263 {
28264     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28265     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28266         (ctxt->user_sax->notationDecl != NULL))
28267         ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
28268                                      systemId);
28269 }
28270
28271 static void
28272 unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
28273                    const xmlChar *publicId, const xmlChar *systemId,
28274                    const xmlChar *notationName)
28275 {
28276     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28277     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28278         (ctxt->user_sax->unparsedEntityDecl != NULL))
28279         ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
28280                                            systemId, notationName);
28281 }
28282
28283 static void
28284 setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
28285 {
28286     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28287     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28288         (ctxt->user_sax->setDocumentLocator != NULL))
28289         ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
28290 }
28291
28292 static void
28293 startDocumentSplit(void *ctx)
28294 {
28295     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28296     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28297         (ctxt->user_sax->startDocument != NULL))
28298         ctxt->user_sax->startDocument(ctxt->user_data);
28299 }
28300
28301 static void
28302 endDocumentSplit(void *ctx)
28303 {
28304     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28305     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28306         (ctxt->user_sax->endDocument != NULL))
28307         ctxt->user_sax->endDocument(ctxt->user_data);
28308 }
28309
28310 static void
28311 processingInstructionSplit(void *ctx, const xmlChar *target,
28312                       const xmlChar *data)
28313 {
28314     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28315     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28316         (ctxt->user_sax->processingInstruction != NULL))
28317         ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
28318 }
28319
28320 static void
28321 commentSplit(void *ctx, const xmlChar *value)
28322 {
28323     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28324     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28325         (ctxt->user_sax->comment != NULL))
28326         ctxt->user_sax->comment(ctxt->user_data, value);
28327 }
28328
28329 /*
28330  * Varargs error callbacks to the user application, harder ...
28331  */
28332
28333 static void XMLCDECL
28334 warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28335     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28336     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28337         (ctxt->user_sax->warning != NULL)) {
28338         TODO
28339     }
28340 }
28341 static void XMLCDECL
28342 errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28343     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28344     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28345         (ctxt->user_sax->error != NULL)) {
28346         TODO
28347     }
28348 }
28349 static void XMLCDECL
28350 fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28351     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28352     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28353         (ctxt->user_sax->fatalError != NULL)) {
28354         TODO
28355     }
28356 }
28357
28358 /*
28359  * Those are function where both the user handler and the schemas handler
28360  * need to be called.
28361  */
28362 static void
28363 charactersSplit(void *ctx, const xmlChar *ch, int len)
28364 {
28365     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28366     if (ctxt == NULL)
28367         return;
28368     if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
28369         ctxt->user_sax->characters(ctxt->user_data, ch, len);
28370     if (ctxt->ctxt != NULL)
28371         xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28372 }
28373
28374 static void
28375 ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
28376 {
28377     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28378     if (ctxt == NULL)
28379         return;
28380     if ((ctxt->user_sax != NULL) &&
28381         (ctxt->user_sax->ignorableWhitespace != NULL))
28382         ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
28383     if (ctxt->ctxt != NULL)
28384         xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28385 }
28386
28387 static void
28388 cdataBlockSplit(void *ctx, const xmlChar *value, int len)
28389 {
28390     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28391     if (ctxt == NULL)
28392         return;
28393     if ((ctxt->user_sax != NULL) &&
28394         (ctxt->user_sax->cdataBlock != NULL))
28395         ctxt->user_sax->cdataBlock(ctxt->user_data, value, len);
28396     if (ctxt->ctxt != NULL)
28397         xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28398 }
28399
28400 static void
28401 referenceSplit(void *ctx, const xmlChar *name)
28402 {
28403     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28404     if (ctxt == NULL)
28405         return;
28406     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28407         (ctxt->user_sax->reference != NULL))
28408         ctxt->user_sax->reference(ctxt->user_data, name);
28409     if (ctxt->ctxt != NULL)
28410         xmlSchemaSAXHandleReference(ctxt->user_data, name);
28411 }
28412
28413 static void
28414 startElementNsSplit(void *ctx, const xmlChar * localname,
28415                     const xmlChar * prefix, const xmlChar * URI,
28416                     int nb_namespaces, const xmlChar ** namespaces,
28417                     int nb_attributes, int nb_defaulted,
28418                     const xmlChar ** attributes) {
28419     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28420     if (ctxt == NULL)
28421         return;
28422     if ((ctxt->user_sax != NULL) &&
28423         (ctxt->user_sax->startElementNs != NULL))
28424         ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28425                                        URI, nb_namespaces, namespaces,
28426                                        nb_attributes, nb_defaulted,
28427                                        attributes);
28428     if (ctxt->ctxt != NULL)
28429         xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28430                                          URI, nb_namespaces, namespaces,
28431                                          nb_attributes, nb_defaulted,
28432                                          attributes);
28433 }
28434
28435 static void
28436 endElementNsSplit(void *ctx, const xmlChar * localname,
28437                     const xmlChar * prefix, const xmlChar * URI) {
28438     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28439     if (ctxt == NULL)
28440         return;
28441     if ((ctxt->user_sax != NULL) &&
28442         (ctxt->user_sax->endElementNs != NULL))
28443         ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28444     if (ctxt->ctxt != NULL)
28445         xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28446 }
28447
28448 /**
28449  * xmlSchemaSAXPlug:
28450  * @ctxt:  a schema validation context
28451  * @sax:  a pointer to the original xmlSAXHandlerPtr
28452  * @user_data:  a pointer to the original SAX user data pointer
28453  *
28454  * Plug a SAX based validation layer in a SAX parsing event flow.
28455  * The original @saxptr and @dataptr data are replaced by new pointers
28456  * but the calls to the original will be maintained.
28457  *
28458  * Returns a pointer to a data structure needed to unplug the validation layer
28459  *         or NULL in case of errors.
28460  */
28461 xmlSchemaSAXPlugPtr
28462 xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28463                  xmlSAXHandlerPtr *sax, void **user_data)
28464 {
28465     xmlSchemaSAXPlugPtr ret;
28466     xmlSAXHandlerPtr old_sax;
28467
28468     if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28469         return(NULL);
28470
28471     /*
28472      * We only allow to plug into SAX2 event streams
28473      */
28474     old_sax = *sax;
28475     if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28476         return(NULL);
28477     if ((old_sax != NULL) &&
28478         (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28479         ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28480         return(NULL);
28481
28482     /*
28483      * everything seems right allocate the local data needed for that layer
28484      */
28485     ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28486     if (ret == NULL) {
28487         return(NULL);
28488     }
28489     memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28490     ret->magic = XML_SAX_PLUG_MAGIC;
28491     ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28492     ret->ctxt = ctxt;
28493     ret->user_sax_ptr = sax;
28494     ret->user_sax = old_sax;
28495     if (old_sax == NULL) {
28496         /*
28497          * go direct, no need for the split block and functions.
28498          */
28499         ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28500         ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28501         /*
28502          * Note that we use the same text-function for both, to prevent
28503          * the parser from testing for ignorable whitespace.
28504          */
28505         ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28506         ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28507
28508         ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28509         ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28510
28511         ret->user_data = ctxt;
28512         *user_data = ctxt;
28513     } else {
28514        /*
28515         * for each callback unused by Schemas initialize it to the Split
28516         * routine only if non NULL in the user block, this can speed up
28517         * things at the SAX level.
28518         */
28519         if (old_sax->internalSubset != NULL)
28520             ret->schemas_sax.internalSubset = internalSubsetSplit;
28521         if (old_sax->isStandalone != NULL)
28522             ret->schemas_sax.isStandalone = isStandaloneSplit;
28523         if (old_sax->hasInternalSubset != NULL)
28524             ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28525         if (old_sax->hasExternalSubset != NULL)
28526             ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28527         if (old_sax->resolveEntity != NULL)
28528             ret->schemas_sax.resolveEntity = resolveEntitySplit;
28529         if (old_sax->getEntity != NULL)
28530             ret->schemas_sax.getEntity = getEntitySplit;
28531         if (old_sax->entityDecl != NULL)
28532             ret->schemas_sax.entityDecl = entityDeclSplit;
28533         if (old_sax->notationDecl != NULL)
28534             ret->schemas_sax.notationDecl = notationDeclSplit;
28535         if (old_sax->attributeDecl != NULL)
28536             ret->schemas_sax.attributeDecl = attributeDeclSplit;
28537         if (old_sax->elementDecl != NULL)
28538             ret->schemas_sax.elementDecl = elementDeclSplit;
28539         if (old_sax->unparsedEntityDecl != NULL)
28540             ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28541         if (old_sax->setDocumentLocator != NULL)
28542             ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28543         if (old_sax->startDocument != NULL)
28544             ret->schemas_sax.startDocument = startDocumentSplit;
28545         if (old_sax->endDocument != NULL)
28546             ret->schemas_sax.endDocument = endDocumentSplit;
28547         if (old_sax->processingInstruction != NULL)
28548             ret->schemas_sax.processingInstruction = processingInstructionSplit;
28549         if (old_sax->comment != NULL)
28550             ret->schemas_sax.comment = commentSplit;
28551         if (old_sax->warning != NULL)
28552             ret->schemas_sax.warning = warningSplit;
28553         if (old_sax->error != NULL)
28554             ret->schemas_sax.error = errorSplit;
28555         if (old_sax->fatalError != NULL)
28556             ret->schemas_sax.fatalError = fatalErrorSplit;
28557         if (old_sax->getParameterEntity != NULL)
28558             ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28559         if (old_sax->externalSubset != NULL)
28560             ret->schemas_sax.externalSubset = externalSubsetSplit;
28561
28562         /*
28563          * the 6 schemas callback have to go to the splitter functions
28564          * Note that we use the same text-function for ignorableWhitespace
28565          * if possible, to prevent the parser from testing for ignorable
28566          * whitespace.
28567          */
28568         ret->schemas_sax.characters = charactersSplit;
28569         if ((old_sax->ignorableWhitespace != NULL) &&
28570             (old_sax->ignorableWhitespace != old_sax->characters))
28571             ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28572         else
28573             ret->schemas_sax.ignorableWhitespace = charactersSplit;
28574         ret->schemas_sax.cdataBlock = cdataBlockSplit;
28575         ret->schemas_sax.reference = referenceSplit;
28576         ret->schemas_sax.startElementNs = startElementNsSplit;
28577         ret->schemas_sax.endElementNs = endElementNsSplit;
28578
28579         ret->user_data_ptr = user_data;
28580         ret->user_data = *user_data;
28581         *user_data = ret;
28582     }
28583
28584     /*
28585      * plug the pointers back.
28586      */
28587     *sax = &(ret->schemas_sax);
28588     ctxt->sax = *sax;
28589     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28590     xmlSchemaPreRun(ctxt);
28591     return(ret);
28592 }
28593
28594 /**
28595  * xmlSchemaSAXUnplug:
28596  * @plug:  a data structure returned by xmlSchemaSAXPlug
28597  *
28598  * Unplug a SAX based validation layer in a SAX parsing event flow.
28599  * The original pointers used in the call are restored.
28600  *
28601  * Returns 0 in case of success and -1 in case of failure.
28602  */
28603 int
28604 xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28605 {
28606     xmlSAXHandlerPtr *sax;
28607     void **user_data;
28608
28609     if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28610         return(-1);
28611     plug->magic = 0;
28612
28613     xmlSchemaPostRun(plug->ctxt);
28614     /* restore the data */
28615     sax = plug->user_sax_ptr;
28616     *sax = plug->user_sax;
28617     if (plug->user_sax != NULL) {
28618         user_data = plug->user_data_ptr;
28619         *user_data = plug->user_data;
28620     }
28621
28622     /* free and return */
28623     xmlFree(plug);
28624     return(0);
28625 }
28626
28627 /**
28628  * xmlSchemaValidateStream:
28629  * @ctxt:  a schema validation context
28630  * @input:  the input to use for reading the data
28631  * @enc:  an optional encoding information
28632  * @sax:  a SAX handler for the resulting events
28633  * @user_data:  the context to provide to the SAX handler.
28634  *
28635  * Validate an input based on a flow of SAX event from the parser
28636  * and forward the events to the @sax handler with the provided @user_data
28637  * the user provided @sax handler must be a SAX2 one.
28638  *
28639  * Returns 0 if the document is schemas valid, a positive error code
28640  *     number otherwise and -1 in case of internal or API error.
28641  */
28642 int
28643 xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
28644                         xmlParserInputBufferPtr input, xmlCharEncoding enc,
28645                         xmlSAXHandlerPtr sax, void *user_data)
28646 {
28647     xmlSchemaSAXPlugPtr plug = NULL;
28648     xmlSAXHandlerPtr old_sax = NULL;
28649     xmlParserCtxtPtr pctxt = NULL;
28650     xmlParserInputPtr inputStream = NULL;
28651     int ret;
28652
28653     if ((ctxt == NULL) || (input == NULL))
28654         return (-1);
28655
28656     /*
28657      * prepare the parser
28658      */
28659     pctxt = xmlNewParserCtxt();
28660     if (pctxt == NULL)
28661         return (-1);
28662     old_sax = pctxt->sax;
28663     pctxt->sax = sax;
28664     pctxt->userData = user_data;
28665 #if 0
28666     if (options)
28667         xmlCtxtUseOptions(pctxt, options);
28668 #endif
28669     pctxt->linenumbers = 1;
28670
28671     inputStream = xmlNewIOInputStream(pctxt, input, enc);;
28672     if (inputStream == NULL) {
28673         ret = -1;
28674         goto done;
28675     }
28676     inputPush(pctxt, inputStream);
28677     ctxt->parserCtxt = pctxt;
28678     ctxt->input = input;
28679
28680     /*
28681      * Plug the validation and launch the parsing
28682      */
28683     plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28684     if (plug == NULL) {
28685         ret = -1;
28686         goto done;
28687     }
28688     ctxt->input = input;
28689     ctxt->enc = enc;
28690     ctxt->sax = pctxt->sax;
28691     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28692     ret = xmlSchemaVStart(ctxt);
28693
28694     if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28695         ret = ctxt->parserCtxt->errNo;
28696         if (ret == 0)
28697             ret = 1;
28698     }
28699
28700 done:
28701     ctxt->parserCtxt = NULL;
28702     ctxt->sax = NULL;
28703     ctxt->input = NULL;
28704     if (plug != NULL) {
28705         xmlSchemaSAXUnplug(plug);
28706     }
28707     /* cleanup */
28708     if (pctxt != NULL) {
28709         pctxt->sax = old_sax;
28710         xmlFreeParserCtxt(pctxt);
28711     }
28712     return (ret);
28713 }
28714
28715 /**
28716  * xmlSchemaValidateFile:
28717  * @ctxt: a schema validation context
28718  * @filename: the URI of the instance
28719  * @options: a future set of options, currently unused
28720  *
28721  * Do a schemas validation of the given resource, it will use the
28722  * SAX streamable validation internally.
28723  *
28724  * Returns 0 if the document is valid, a positive error code
28725  *     number otherwise and -1 in case of an internal or API error.
28726  */
28727 int
28728 xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
28729                       const char * filename,
28730                       int options ATTRIBUTE_UNUSED)
28731 {
28732     int ret;
28733     xmlParserInputBufferPtr input;
28734
28735     if ((ctxt == NULL) || (filename == NULL))
28736         return (-1);
28737
28738     input = xmlParserInputBufferCreateFilename(filename,
28739         XML_CHAR_ENCODING_NONE);
28740     if (input == NULL)
28741         return (-1);
28742     ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
28743         NULL, NULL);
28744     return (ret);
28745 }
28746
28747 /**
28748  * xmlSchemaValidCtxtGetParserCtxt:
28749  * @ctxt: a schema validation context
28750  *
28751  * allow access to the parser context of the schema validation context
28752  *
28753  * Returns the parser context of the schema validation context or NULL
28754  *         in case of error.
28755  */
28756 xmlParserCtxtPtr
28757 xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)
28758 {
28759     if (ctxt == NULL)
28760         return(NULL);
28761     return (ctxt->parserCtxt);
28762 }
28763
28764 #define bottom_xmlschemas
28765 #include "elfgcchack.h"
28766 #endif /* LIBXML_SCHEMAS_ENABLED */